MipsTargetObjectFile.cpp revision 6948897e478cbd66626159776a8017b3c18579b9
1c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant//===-- MipsTargetObjectFile.cpp - Mips Object Files ----------------------===//
2c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant//
3c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant//                     The LLVM Compiler Infrastructure
4c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant//
5b64f8b07c104c6cc986570ac8ee0ed16a9f23976Howard Hinnant// This file is distributed under the University of Illinois Open Source
6b64f8b07c104c6cc986570ac8ee0ed16a9f23976Howard Hinnant// License. See LICENSE.TXT for details.
7c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant//
8c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant//===----------------------------------------------------------------------===//
9cedb7fcc10556aaf4302917913c672b1bc6a1db0Daniel Dunbar
10cedb7fcc10556aaf4302917913c672b1bc6a1db0Daniel Dunbar#include "MipsTargetObjectFile.h"
11cedb7fcc10556aaf4302917913c672b1bc6a1db0Daniel Dunbar#include "MipsSubtarget.h"
124dc5b2198d1aa4ab585a3d4a87ee9626d681f9f7Dan Albert#include "MipsTargetMachine.h"
134dc5b2198d1aa4ab585a3d4a87ee9626d681f9f7Dan Albert#include "llvm/IR/DataLayout.h"
14c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant#include "llvm/IR/DerivedTypes.h"
15c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant#include "llvm/IR/GlobalVariable.h"
16c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant#include "llvm/MC/MCContext.h"
17c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant#include "llvm/MC/MCSectionELF.h"
18c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant#include "llvm/Support/CommandLine.h"
19c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant#include "llvm/Support/ELF.h"
20c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant#include "llvm/Target/TargetMachine.h"
21c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnantusing namespace llvm;
22c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant
230a69fa14d2f0521e45a72068c14fe573b140d48bHoward Hinnantstatic cl::opt<unsigned>
240a69fa14d2f0521e45a72068c14fe573b140d48bHoward HinnantSSThreshold("mips-ssection-threshold", cl::Hidden,
250a69fa14d2f0521e45a72068c14fe573b140d48bHoward Hinnant            cl::desc("Small data and bss section threshold size (default=8)"),
26c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant            cl::init(8));
27c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant
28c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnantstatic cl::opt<bool>
29c52f43e72dfcea03037729649da84c23b3beb04aHoward HinnantLocalSData("mlocal-sdata", cl::Hidden,
30c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant           cl::desc("MIPS: Use gp_rel for object-local data."),
31c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant           cl::init(true));
32f8f852138f86e4588916021e1afedfcab25298c0Howard Hinnant
330a69fa14d2f0521e45a72068c14fe573b140d48bHoward Hinnantstatic cl::opt<bool>
34c52f43e72dfcea03037729649da84c23b3beb04aHoward HinnantExternSData("mextern-sdata", cl::Hidden,
35            cl::desc("MIPS: Use gp_rel for data that is not defined by the "
36                     "current object."),
37            cl::init(true));
38
39void MipsTargetObjectFile::Initialize(MCContext &Ctx, const TargetMachine &TM){
40  TargetLoweringObjectFileELF::Initialize(Ctx, TM);
41  InitializeELF(TM.Options.UseInitArray);
42
43  SmallDataSection = getContext().getELFSection(
44      ".sdata", ELF::SHT_PROGBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC);
45
46  SmallBSSSection = getContext().getELFSection(".sbss", ELF::SHT_NOBITS,
47                                               ELF::SHF_WRITE | ELF::SHF_ALLOC);
48  this->TM = &static_cast<const MipsTargetMachine &>(TM);
49}
50
51// A address must be loaded from a small section if its size is less than the
52// small section size threshold. Data in this section must be addressed using
53// gp_rel operator.
54static bool IsInSmallSection(uint64_t Size) {
55  // gcc has traditionally not treated zero-sized objects as small data, so this
56  // is effectively part of the ABI.
57  return Size > 0 && Size <= SSThreshold;
58}
59
60/// Return true if this global address should be placed into small data/bss
61/// section.
62bool MipsTargetObjectFile::
63IsGlobalInSmallSection(const GlobalValue *GV, const TargetMachine &TM) const {
64  // We first check the case where global is a declaration, because finding
65  // section kind using getKindForGlobal() is only allowed for global
66  // definitions.
67  if (GV->isDeclaration() || GV->hasAvailableExternallyLinkage())
68    return IsGlobalInSmallSectionImpl(GV, TM);
69
70  return IsGlobalInSmallSection(GV, TM, getKindForGlobal(GV, TM));
71}
72
73/// Return true if this global address should be placed into small data/bss
74/// section.
75bool MipsTargetObjectFile::
76IsGlobalInSmallSection(const GlobalValue *GV, const TargetMachine &TM,
77                       SectionKind Kind) const {
78  return (IsGlobalInSmallSectionImpl(GV, TM) &&
79          (Kind.isDataRel() || Kind.isBSS() || Kind.isCommon()));
80}
81
82/// Return true if this global address should be placed into small data/bss
83/// section. This method does all the work, except for checking the section
84/// kind.
85bool MipsTargetObjectFile::
86IsGlobalInSmallSectionImpl(const GlobalValue *GV,
87                           const TargetMachine &TM) const {
88  const MipsSubtarget &Subtarget =
89      *static_cast<const MipsTargetMachine &>(TM).getSubtargetImpl();
90
91  // Return if small section is not available.
92  if (!Subtarget.useSmallSection())
93    return false;
94
95  // Only global variables, not functions.
96  const GlobalVariable *GVA = dyn_cast<GlobalVariable>(GV);
97  if (!GVA)
98    return false;
99
100  // Enforce -mlocal-sdata.
101  if (!LocalSData && GV->hasLocalLinkage())
102    return false;
103
104  // Enforce -mextern-sdata.
105  if (!ExternSData && ((GV->hasExternalLinkage() && GV->isDeclaration()) ||
106                       GV->hasCommonLinkage()))
107    return false;
108
109  Type *Ty = GV->getType()->getElementType();
110  return IsInSmallSection(TM.getDataLayout()->getTypeAllocSize(Ty));
111}
112
113MCSection *
114MipsTargetObjectFile::SelectSectionForGlobal(const GlobalValue *GV,
115                                             SectionKind Kind, Mangler &Mang,
116                                             const TargetMachine &TM) const {
117  // TODO: Could also support "weak" symbols as well with ".gnu.linkonce.s.*"
118  // sections?
119
120  // Handle Small Section classification here.
121  if (Kind.isBSS() && IsGlobalInSmallSection(GV, TM, Kind))
122    return SmallBSSSection;
123  if (Kind.isDataRel() && IsGlobalInSmallSection(GV, TM, Kind))
124    return SmallDataSection;
125
126  // Otherwise, we work the same as ELF.
127  return TargetLoweringObjectFileELF::SelectSectionForGlobal(GV, Kind, Mang,TM);
128}
129
130/// Return true if this constant should be placed into small data section.
131bool MipsTargetObjectFile::
132IsConstantInSmallSection(const Constant *CN, const TargetMachine &TM) const {
133  return (static_cast<const MipsTargetMachine &>(TM)
134              .getSubtargetImpl()
135              ->useSmallSection() &&
136          LocalSData && IsInSmallSection(TM.getDataLayout()->getTypeAllocSize(
137                            CN->getType())));
138}
139
140MCSection *
141MipsTargetObjectFile::getSectionForConstant(SectionKind Kind,
142                                            const Constant *C) const {
143  if (IsConstantInSmallSection(C, *TM))
144    return SmallDataSection;
145
146  // Otherwise, we work the same as ELF.
147  return TargetLoweringObjectFileELF::getSectionForConstant(Kind, C);
148}
149