/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/llvm/lib/Target/Mips/MipsTargetObjectFile.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===-- MipsTargetObjectFile.cpp - Mips Object Files ----------------------===// |
2 | | // |
3 | | // The LLVM Compiler Infrastructure |
4 | | // |
5 | | // This file is distributed under the University of Illinois Open Source |
6 | | // License. See LICENSE.TXT for details. |
7 | | // |
8 | | //===----------------------------------------------------------------------===// |
9 | | |
10 | | #include "MipsTargetObjectFile.h" |
11 | | #include "MipsSubtarget.h" |
12 | | #include "MipsTargetMachine.h" |
13 | | #include "llvm/BinaryFormat/ELF.h" |
14 | | #include "llvm/IR/DataLayout.h" |
15 | | #include "llvm/IR/DerivedTypes.h" |
16 | | #include "llvm/IR/GlobalVariable.h" |
17 | | #include "llvm/MC/MCContext.h" |
18 | | #include "llvm/MC/MCSectionELF.h" |
19 | | #include "llvm/Support/CommandLine.h" |
20 | | #include "llvm/Target/TargetMachine.h" |
21 | | using namespace llvm; |
22 | | |
23 | | static cl::opt<unsigned> |
24 | | SSThreshold("mips-ssection-threshold", cl::Hidden, |
25 | | cl::desc("Small data and bss section threshold size (default=8)"), |
26 | | cl::init(8)); |
27 | | |
28 | | static cl::opt<bool> |
29 | | LocalSData("mlocal-sdata", cl::Hidden, |
30 | | cl::desc("MIPS: Use gp_rel for object-local data."), |
31 | | cl::init(true)); |
32 | | |
33 | | static cl::opt<bool> |
34 | | ExternSData("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 | | |
39 | | static cl::opt<bool> |
40 | | EmbeddedData("membedded-data", cl::Hidden, |
41 | | cl::desc("MIPS: Try to allocate variables in the following" |
42 | | " sections if possible: .rodata, .sdata, .data ."), |
43 | | cl::init(false)); |
44 | | |
45 | 1.70k | void MipsTargetObjectFile::Initialize(MCContext &Ctx, const TargetMachine &TM){ |
46 | 1.70k | TargetLoweringObjectFileELF::Initialize(Ctx, TM); |
47 | 1.70k | InitializeELF(TM.Options.UseInitArray); |
48 | 1.70k | |
49 | 1.70k | SmallDataSection = getContext().getELFSection( |
50 | 1.70k | ".sdata", ELF::SHT_PROGBITS, |
51 | 1.70k | ELF::SHF_WRITE | ELF::SHF_ALLOC | ELF::SHF_MIPS_GPREL); |
52 | 1.70k | |
53 | 1.70k | SmallBSSSection = getContext().getELFSection(".sbss", ELF::SHT_NOBITS, |
54 | 1.70k | ELF::SHF_WRITE | ELF::SHF_ALLOC | |
55 | 1.70k | ELF::SHF_MIPS_GPREL); |
56 | 1.70k | this->TM = &static_cast<const MipsTargetMachine &>(TM); |
57 | 1.70k | } |
58 | | |
59 | | // A address must be loaded from a small section if its size is less than the |
60 | | // small section size threshold. Data in this section must be addressed using |
61 | | // gp_rel operator. |
62 | 25 | static bool IsInSmallSection(uint64_t Size) { |
63 | 25 | // gcc has traditionally not treated zero-sized objects as small data, so this |
64 | 25 | // is effectively part of the ABI. |
65 | 25 | return Size > 0 && Size <= SSThreshold; |
66 | 25 | } |
67 | | |
68 | | /// Return true if this global address should be placed into small data/bss |
69 | | /// section. |
70 | | bool MipsTargetObjectFile::IsGlobalInSmallSection( |
71 | 3.40k | const GlobalObject *GO, const TargetMachine &TM) const { |
72 | 3.40k | // We first check the case where global is a declaration, because finding |
73 | 3.40k | // section kind using getKindForGlobal() is only allowed for global |
74 | 3.40k | // definitions. |
75 | 3.40k | if (GO->isDeclaration() || 3.40k GO->hasAvailableExternallyLinkage()3.14k ) |
76 | 255 | return IsGlobalInSmallSectionImpl(GO, TM); |
77 | 3.14k | |
78 | 3.14k | return IsGlobalInSmallSection(GO, TM, getKindForGlobal(GO, TM)); |
79 | 3.14k | } |
80 | | |
81 | | /// Return true if this global address should be placed into small data/bss |
82 | | /// section. |
83 | | bool MipsTargetObjectFile:: |
84 | | IsGlobalInSmallSection(const GlobalObject *GO, const TargetMachine &TM, |
85 | 7.74k | SectionKind Kind) const { |
86 | 7.74k | return IsGlobalInSmallSectionImpl(GO, TM) && |
87 | 27 | (Kind.isData() || 27 Kind.isBSS()15 || Kind.isCommon()8 || |
88 | 27 | Kind.isReadOnly()); |
89 | 7.74k | } |
90 | | |
91 | | /// Return true if this global address should be placed into small data/bss |
92 | | /// section. This method does all the work, except for checking the section |
93 | | /// kind. |
94 | | bool MipsTargetObjectFile:: |
95 | | IsGlobalInSmallSectionImpl(const GlobalObject *GO, |
96 | 7.99k | const TargetMachine &TM) const { |
97 | 7.99k | const MipsSubtarget &Subtarget = |
98 | 7.99k | *static_cast<const MipsTargetMachine &>(TM).getSubtargetImpl(); |
99 | 7.99k | |
100 | 7.99k | // Return if small section is not available. |
101 | 7.99k | if (!Subtarget.useSmallSection()) |
102 | 7.96k | return false; |
103 | 30 | |
104 | 30 | // Only global variables, not functions. |
105 | 30 | const GlobalVariable *GVA = dyn_cast<GlobalVariable>(GO); |
106 | 30 | if (!GVA) |
107 | 0 | return false; |
108 | 30 | |
109 | 30 | // If the variable has an explicit section, it is placed in that section but |
110 | 30 | // it's addressing mode may change. |
111 | 30 | if (30 GVA->hasSection()30 ) { |
112 | 3 | StringRef Section = GVA->getSection(); |
113 | 3 | |
114 | 3 | // Explicitly placing any variable in the small data section overrides |
115 | 3 | // the global -G value. |
116 | 3 | if (Section == ".sdata" || 3 Section == ".sbss"2 ) |
117 | 2 | return true; |
118 | 1 | |
119 | 1 | // Otherwise reject accessing it through the gp pointer. There are some |
120 | 1 | // historic cases which GCC doesn't appear to respect any more. These |
121 | 1 | // are .lit4, .lit8 and .srdata. For the moment reject these as well. |
122 | 1 | return false; |
123 | 1 | } |
124 | 27 | |
125 | 27 | // Enforce -mlocal-sdata. |
126 | 27 | if (27 !LocalSData && 27 GVA->hasLocalLinkage()0 ) |
127 | 0 | return false; |
128 | 27 | |
129 | 27 | // Enforce -mextern-sdata. |
130 | 27 | if (27 !ExternSData && 27 ((GVA->hasExternalLinkage() && 0 GVA->isDeclaration()0 ) || |
131 | 0 | GVA->hasCommonLinkage())) |
132 | 0 | return false; |
133 | 27 | |
134 | 27 | // Enforce -membedded-data. |
135 | 27 | if (27 EmbeddedData && 27 GVA->isConstant()5 ) |
136 | 2 | return false; |
137 | 25 | |
138 | 25 | Type *Ty = GVA->getValueType(); |
139 | 25 | return IsInSmallSection( |
140 | 25 | GVA->getParent()->getDataLayout().getTypeAllocSize(Ty)); |
141 | 25 | } |
142 | | |
143 | | MCSection *MipsTargetObjectFile::SelectSectionForGlobal( |
144 | 16.8k | const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const { |
145 | 16.8k | // TODO: Could also support "weak" symbols as well with ".gnu.linkonce.s.*" |
146 | 16.8k | // sections? |
147 | 16.8k | |
148 | 16.8k | // Handle Small Section classification here. |
149 | 16.8k | if (Kind.isBSS() && 16.8k IsGlobalInSmallSection(GO, TM, Kind)1.81k ) |
150 | 6 | return SmallBSSSection; |
151 | 16.8k | if (16.8k Kind.isData() && 16.8k IsGlobalInSmallSection(GO, TM, Kind)2.62k ) |
152 | 5 | return SmallDataSection; |
153 | 16.8k | if (16.8k Kind.isReadOnly() && 16.8k IsGlobalInSmallSection(GO, TM, Kind)150 ) |
154 | 4 | return SmallDataSection; |
155 | 16.8k | |
156 | 16.8k | // Otherwise, we work the same as ELF. |
157 | 16.8k | return TargetLoweringObjectFileELF::SelectSectionForGlobal(GO, Kind, TM); |
158 | 16.8k | } |
159 | | |
160 | | /// Return true if this constant should be placed into small data section. |
161 | | bool MipsTargetObjectFile::IsConstantInSmallSection( |
162 | 879 | const DataLayout &DL, const Constant *CN, const TargetMachine &TM) const { |
163 | 879 | return (static_cast<const MipsTargetMachine &>(TM) |
164 | 879 | .getSubtargetImpl() |
165 | 879 | ->useSmallSection() && |
166 | 879 | LocalSData0 && IsInSmallSection(DL.getTypeAllocSize(CN->getType()))0 ); |
167 | 879 | } |
168 | | |
169 | | /// Return true if this constant should be placed into small data section. |
170 | | MCSection *MipsTargetObjectFile::getSectionForConstant(const DataLayout &DL, |
171 | | SectionKind Kind, |
172 | | const Constant *C, |
173 | 555 | unsigned &Align) const { |
174 | 555 | if (IsConstantInSmallSection(DL, C, *TM)) |
175 | 0 | return SmallDataSection; |
176 | 555 | |
177 | 555 | // Otherwise, we work the same as ELF. |
178 | 555 | return TargetLoweringObjectFileELF::getSectionForConstant(DL, Kind, C, Align); |
179 | 555 | } |
180 | | |
181 | | const MCExpr * |
182 | 4 | MipsTargetObjectFile::getDebugThreadLocalSymbol(const MCSymbol *Sym) const { |
183 | 4 | const MCExpr *Expr = |
184 | 4 | MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext()); |
185 | 4 | return MCBinaryExpr::createAdd( |
186 | 4 | Expr, MCConstantExpr::create(0x8000, getContext()), getContext()); |
187 | 4 | } |