Mercurial > hg > CbC > CbC_llvm
comparison llvm/lib/Target/Hexagon/HexagonTargetObjectFile.cpp @ 150:1d019706d866
LLVM10
author | anatofuz |
---|---|
date | Thu, 13 Feb 2020 15:10:13 +0900 |
parents | |
children | e8a9b4f4d755 0572611fdcc8 |
comparison
equal
deleted
inserted
replaced
147:c2174574ed3a | 150:1d019706d866 |
---|---|
1 //===-- HexagonTargetObjectFile.cpp ---------------------------------------===// | |
2 // | |
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
4 // See https://llvm.org/LICENSE.txt for license information. | |
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
6 // | |
7 //===----------------------------------------------------------------------===// | |
8 // | |
9 // This file contains the declarations of the HexagonTargetAsmInfo properties. | |
10 // | |
11 //===----------------------------------------------------------------------===// | |
12 | |
13 #define DEBUG_TYPE "hexagon-sdata" | |
14 | |
15 #include "HexagonTargetObjectFile.h" | |
16 #include "llvm/ADT/SmallString.h" | |
17 #include "llvm/ADT/StringRef.h" | |
18 #include "llvm/ADT/Twine.h" | |
19 #include "llvm/BinaryFormat/ELF.h" | |
20 #include "llvm/IR/DataLayout.h" | |
21 #include "llvm/IR/DerivedTypes.h" | |
22 #include "llvm/IR/GlobalObject.h" | |
23 #include "llvm/IR/GlobalValue.h" | |
24 #include "llvm/IR/GlobalVariable.h" | |
25 #include "llvm/IR/Type.h" | |
26 #include "llvm/MC/MCContext.h" | |
27 #include "llvm/MC/SectionKind.h" | |
28 #include "llvm/Support/Casting.h" | |
29 #include "llvm/Support/CommandLine.h" | |
30 #include "llvm/Support/Debug.h" | |
31 #include "llvm/Support/raw_ostream.h" | |
32 #include "llvm/Target/TargetMachine.h" | |
33 | |
34 using namespace llvm; | |
35 | |
36 static cl::opt<unsigned> SmallDataThreshold("hexagon-small-data-threshold", | |
37 cl::init(8), cl::Hidden, | |
38 cl::desc("The maximum size of an object in the sdata section")); | |
39 | |
40 static cl::opt<bool> NoSmallDataSorting("mno-sort-sda", cl::init(false), | |
41 cl::Hidden, cl::desc("Disable small data sections sorting")); | |
42 | |
43 static cl::opt<bool> StaticsInSData("hexagon-statics-in-small-data", | |
44 cl::init(false), cl::Hidden, cl::ZeroOrMore, | |
45 cl::desc("Allow static variables in .sdata")); | |
46 | |
47 static cl::opt<bool> TraceGVPlacement("trace-gv-placement", | |
48 cl::Hidden, cl::init(false), | |
49 cl::desc("Trace global value placement")); | |
50 | |
51 static cl::opt<bool> | |
52 EmitJtInText("hexagon-emit-jt-text", cl::Hidden, cl::init(false), | |
53 cl::desc("Emit hexagon jump tables in function section")); | |
54 | |
55 static cl::opt<bool> | |
56 EmitLutInText("hexagon-emit-lut-text", cl::Hidden, cl::init(false), | |
57 cl::desc("Emit hexagon lookup tables in function section")); | |
58 | |
59 // TraceGVPlacement controls messages for all builds. For builds with assertions | |
60 // (debug or release), messages are also controlled by the usual debug flags | |
61 // (e.g. -debug and -debug-only=globallayout) | |
62 #define TRACE_TO(s, X) s << X | |
63 #ifdef NDEBUG | |
64 #define TRACE(X) \ | |
65 do { \ | |
66 if (TraceGVPlacement) { \ | |
67 TRACE_TO(errs(), X); \ | |
68 } \ | |
69 } while (false) | |
70 #else | |
71 #define TRACE(X) \ | |
72 do { \ | |
73 if (TraceGVPlacement) { \ | |
74 TRACE_TO(errs(), X); \ | |
75 } else { \ | |
76 LLVM_DEBUG(TRACE_TO(dbgs(), X)); \ | |
77 } \ | |
78 } while (false) | |
79 #endif | |
80 | |
81 // Returns true if the section name is such that the symbol will be put | |
82 // in a small data section. | |
83 // For instance, global variables with section attributes such as ".sdata" | |
84 // ".sdata.*", ".sbss", and ".sbss.*" will go into small data. | |
85 static bool isSmallDataSection(StringRef Sec) { | |
86 // sectionName is either ".sdata" or ".sbss". Looking for an exact match | |
87 // obviates the need for checks for section names such as ".sdatafoo". | |
88 if (Sec.equals(".sdata") || Sec.equals(".sbss") || Sec.equals(".scommon")) | |
89 return true; | |
90 // If either ".sdata." or ".sbss." is a substring of the section name | |
91 // then put the symbol in small data. | |
92 return Sec.find(".sdata.") != StringRef::npos || | |
93 Sec.find(".sbss.") != StringRef::npos || | |
94 Sec.find(".scommon.") != StringRef::npos; | |
95 } | |
96 | |
97 static const char *getSectionSuffixForSize(unsigned Size) { | |
98 switch (Size) { | |
99 default: | |
100 return ""; | |
101 case 1: | |
102 return ".1"; | |
103 case 2: | |
104 return ".2"; | |
105 case 4: | |
106 return ".4"; | |
107 case 8: | |
108 return ".8"; | |
109 } | |
110 } | |
111 | |
112 void HexagonTargetObjectFile::Initialize(MCContext &Ctx, | |
113 const TargetMachine &TM) { | |
114 TargetLoweringObjectFileELF::Initialize(Ctx, TM); | |
115 InitializeELF(TM.Options.UseInitArray); | |
116 | |
117 SmallDataSection = | |
118 getContext().getELFSection(".sdata", ELF::SHT_PROGBITS, | |
119 ELF::SHF_WRITE | ELF::SHF_ALLOC | | |
120 ELF::SHF_HEX_GPREL); | |
121 SmallBSSSection = | |
122 getContext().getELFSection(".sbss", ELF::SHT_NOBITS, | |
123 ELF::SHF_WRITE | ELF::SHF_ALLOC | | |
124 ELF::SHF_HEX_GPREL); | |
125 } | |
126 | |
127 MCSection *HexagonTargetObjectFile::SelectSectionForGlobal( | |
128 const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const { | |
129 TRACE("[SelectSectionForGlobal] GO(" << GO->getName() << ") "); | |
130 TRACE("input section(" << GO->getSection() << ") "); | |
131 | |
132 TRACE((GO->hasPrivateLinkage() ? "private_linkage " : "") | |
133 << (GO->hasLocalLinkage() ? "local_linkage " : "") | |
134 << (GO->hasInternalLinkage() ? "internal " : "") | |
135 << (GO->hasExternalLinkage() ? "external " : "") | |
136 << (GO->hasCommonLinkage() ? "common_linkage " : "") | |
137 << (GO->hasCommonLinkage() ? "common " : "" ) | |
138 << (Kind.isCommon() ? "kind_common " : "" ) | |
139 << (Kind.isBSS() ? "kind_bss " : "" ) | |
140 << (Kind.isBSSLocal() ? "kind_bss_local " : "" )); | |
141 | |
142 // If the lookup table is used by more than one function, do not place | |
143 // it in text section. | |
144 if (EmitLutInText && GO->getName().startswith("switch.table")) { | |
145 if (const Function *Fn = getLutUsedFunction(GO)) | |
146 return selectSectionForLookupTable(GO, TM, Fn); | |
147 } | |
148 | |
149 if (isGlobalInSmallSection(GO, TM)) | |
150 return selectSmallSectionForGlobal(GO, Kind, TM); | |
151 | |
152 if (Kind.isCommon()) { | |
153 // This is purely for LTO+Linker Script because commons don't really have a | |
154 // section. However, the BitcodeSectionWriter pass will query for the | |
155 // sections of commons (and the linker expects us to know their section) so | |
156 // we'll return one here. | |
157 return BSSSection; | |
158 } | |
159 | |
160 TRACE("default_ELF_section\n"); | |
161 // Otherwise, we work the same as ELF. | |
162 return TargetLoweringObjectFileELF::SelectSectionForGlobal(GO, Kind, TM); | |
163 } | |
164 | |
165 MCSection *HexagonTargetObjectFile::getExplicitSectionGlobal( | |
166 const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const { | |
167 TRACE("[getExplicitSectionGlobal] GO(" << GO->getName() << ") from(" | |
168 << GO->getSection() << ") "); | |
169 TRACE((GO->hasPrivateLinkage() ? "private_linkage " : "") | |
170 << (GO->hasLocalLinkage() ? "local_linkage " : "") | |
171 << (GO->hasInternalLinkage() ? "internal " : "") | |
172 << (GO->hasExternalLinkage() ? "external " : "") | |
173 << (GO->hasCommonLinkage() ? "common_linkage " : "") | |
174 << (GO->hasCommonLinkage() ? "common " : "" ) | |
175 << (Kind.isCommon() ? "kind_common " : "" ) | |
176 << (Kind.isBSS() ? "kind_bss " : "" ) | |
177 << (Kind.isBSSLocal() ? "kind_bss_local " : "" )); | |
178 | |
179 if (GO->hasSection()) { | |
180 StringRef Section = GO->getSection(); | |
181 if (Section.find(".access.text.group") != StringRef::npos) | |
182 return getContext().getELFSection(GO->getSection(), ELF::SHT_PROGBITS, | |
183 ELF::SHF_ALLOC | ELF::SHF_EXECINSTR); | |
184 if (Section.find(".access.data.group") != StringRef::npos) | |
185 return getContext().getELFSection(GO->getSection(), ELF::SHT_PROGBITS, | |
186 ELF::SHF_WRITE | ELF::SHF_ALLOC); | |
187 } | |
188 | |
189 if (isGlobalInSmallSection(GO, TM)) | |
190 return selectSmallSectionForGlobal(GO, Kind, TM); | |
191 | |
192 // Otherwise, we work the same as ELF. | |
193 TRACE("default_ELF_section\n"); | |
194 return TargetLoweringObjectFileELF::getExplicitSectionGlobal(GO, Kind, TM); | |
195 } | |
196 | |
197 /// Return true if this global value should be placed into small data/bss | |
198 /// section. | |
199 bool HexagonTargetObjectFile::isGlobalInSmallSection(const GlobalObject *GO, | |
200 const TargetMachine &TM) const { | |
201 bool HaveSData = isSmallDataEnabled(TM); | |
202 if (!HaveSData) | |
203 LLVM_DEBUG(dbgs() << "Small-data allocation is disabled, but symbols " | |
204 "may have explicit section assignments...\n"); | |
205 // Only global variables, not functions. | |
206 LLVM_DEBUG(dbgs() << "Checking if value is in small-data, -G" | |
207 << SmallDataThreshold << ": \"" << GO->getName() << "\": "); | |
208 const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GO); | |
209 if (!GVar) { | |
210 LLVM_DEBUG(dbgs() << "no, not a global variable\n"); | |
211 return false; | |
212 } | |
213 | |
214 // Globals with external linkage that have an original section set must be | |
215 // emitted to that section, regardless of whether we would put them into | |
216 // small data or not. This is how we can support mixing -G0/-G8 in LTO. | |
217 if (GVar->hasSection()) { | |
218 bool IsSmall = isSmallDataSection(GVar->getSection()); | |
219 LLVM_DEBUG(dbgs() << (IsSmall ? "yes" : "no") | |
220 << ", has section: " << GVar->getSection() << '\n'); | |
221 return IsSmall; | |
222 } | |
223 | |
224 // If sdata is disabled, stop the checks here. | |
225 if (!HaveSData) { | |
226 LLVM_DEBUG(dbgs() << "no, small-data allocation is disabled\n"); | |
227 return false; | |
228 } | |
229 | |
230 if (GVar->isConstant()) { | |
231 LLVM_DEBUG(dbgs() << "no, is a constant\n"); | |
232 return false; | |
233 } | |
234 | |
235 bool IsLocal = GVar->hasLocalLinkage(); | |
236 if (!StaticsInSData && IsLocal) { | |
237 LLVM_DEBUG(dbgs() << "no, is static\n"); | |
238 return false; | |
239 } | |
240 | |
241 Type *GType = GVar->getValueType(); | |
242 if (isa<ArrayType>(GType)) { | |
243 LLVM_DEBUG(dbgs() << "no, is an array\n"); | |
244 return false; | |
245 } | |
246 | |
247 // If the type is a struct with no body provided, treat is conservatively. | |
248 // There cannot be actual definitions of object of such a type in this CU | |
249 // (only references), so assuming that they are not in sdata is safe. If | |
250 // these objects end up in the sdata, the references will still be valid. | |
251 if (StructType *ST = dyn_cast<StructType>(GType)) { | |
252 if (ST->isOpaque()) { | |
253 LLVM_DEBUG(dbgs() << "no, has opaque type\n"); | |
254 return false; | |
255 } | |
256 } | |
257 | |
258 unsigned Size = GVar->getParent()->getDataLayout().getTypeAllocSize(GType); | |
259 if (Size == 0) { | |
260 LLVM_DEBUG(dbgs() << "no, has size 0\n"); | |
261 return false; | |
262 } | |
263 if (Size > SmallDataThreshold) { | |
264 LLVM_DEBUG(dbgs() << "no, size exceeds sdata threshold: " << Size << '\n'); | |
265 return false; | |
266 } | |
267 | |
268 LLVM_DEBUG(dbgs() << "yes\n"); | |
269 return true; | |
270 } | |
271 | |
272 bool HexagonTargetObjectFile::isSmallDataEnabled(const TargetMachine &TM) | |
273 const { | |
274 return SmallDataThreshold > 0 && !TM.isPositionIndependent(); | |
275 } | |
276 | |
277 unsigned HexagonTargetObjectFile::getSmallDataSize() const { | |
278 return SmallDataThreshold; | |
279 } | |
280 | |
281 bool HexagonTargetObjectFile::shouldPutJumpTableInFunctionSection( | |
282 bool UsesLabelDifference, const Function &F) const { | |
283 return EmitJtInText; | |
284 } | |
285 | |
286 /// Descends any type down to "elementary" components, | |
287 /// discovering the smallest addressable one. | |
288 /// If zero is returned, declaration will not be modified. | |
289 unsigned HexagonTargetObjectFile::getSmallestAddressableSize(const Type *Ty, | |
290 const GlobalValue *GV, const TargetMachine &TM) const { | |
291 // Assign the smallest element access size to the highest | |
292 // value which assembler can handle. | |
293 unsigned SmallestElement = 8; | |
294 | |
295 if (!Ty) | |
296 return 0; | |
297 switch (Ty->getTypeID()) { | |
298 case Type::StructTyID: { | |
299 const StructType *STy = cast<const StructType>(Ty); | |
300 for (auto &E : STy->elements()) { | |
301 unsigned AtomicSize = getSmallestAddressableSize(E, GV, TM); | |
302 if (AtomicSize < SmallestElement) | |
303 SmallestElement = AtomicSize; | |
304 } | |
305 return (STy->getNumElements() == 0) ? 0 : SmallestElement; | |
306 } | |
307 case Type::ArrayTyID: { | |
308 const ArrayType *ATy = cast<const ArrayType>(Ty); | |
309 return getSmallestAddressableSize(ATy->getElementType(), GV, TM); | |
310 } | |
311 case Type::VectorTyID: { | |
312 const VectorType *PTy = cast<const VectorType>(Ty); | |
313 return getSmallestAddressableSize(PTy->getElementType(), GV, TM); | |
314 } | |
315 case Type::PointerTyID: | |
316 case Type::HalfTyID: | |
317 case Type::FloatTyID: | |
318 case Type::DoubleTyID: | |
319 case Type::IntegerTyID: { | |
320 const DataLayout &DL = GV->getParent()->getDataLayout(); | |
321 // It is unfortunate that DL's function take non-const Type*. | |
322 return DL.getTypeAllocSize(const_cast<Type*>(Ty)); | |
323 } | |
324 case Type::FunctionTyID: | |
325 case Type::VoidTyID: | |
326 case Type::X86_FP80TyID: | |
327 case Type::FP128TyID: | |
328 case Type::PPC_FP128TyID: | |
329 case Type::LabelTyID: | |
330 case Type::MetadataTyID: | |
331 case Type::X86_MMXTyID: | |
332 case Type::TokenTyID: | |
333 return 0; | |
334 } | |
335 | |
336 return 0; | |
337 } | |
338 | |
339 MCSection *HexagonTargetObjectFile::selectSmallSectionForGlobal( | |
340 const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const { | |
341 const Type *GTy = GO->getValueType(); | |
342 unsigned Size = getSmallestAddressableSize(GTy, GO, TM); | |
343 | |
344 // If we have -ffunction-section or -fdata-section then we should emit the | |
345 // global value to a unique section specifically for it... even for sdata. | |
346 bool EmitUniquedSection = TM.getDataSections(); | |
347 | |
348 TRACE("Small data. Size(" << Size << ")"); | |
349 // Handle Small Section classification here. | |
350 if (Kind.isBSS() || Kind.isBSSLocal()) { | |
351 // If -mno-sort-sda is not set, find out smallest accessible entity in | |
352 // declaration and add it to the section name string. | |
353 // Note. It does not track the actual usage of the value, only its de- | |
354 // claration. Also, compiler adds explicit pad fields to some struct | |
355 // declarations - they are currently counted towards smallest addres- | |
356 // sable entity. | |
357 if (NoSmallDataSorting) { | |
358 TRACE(" default sbss\n"); | |
359 return SmallBSSSection; | |
360 } | |
361 | |
362 StringRef Prefix(".sbss"); | |
363 SmallString<128> Name(Prefix); | |
364 Name.append(getSectionSuffixForSize(Size)); | |
365 | |
366 if (EmitUniquedSection) { | |
367 Name.append("."); | |
368 Name.append(GO->getName()); | |
369 } | |
370 TRACE(" unique sbss(" << Name << ")\n"); | |
371 return getContext().getELFSection(Name.str(), ELF::SHT_NOBITS, | |
372 ELF::SHF_WRITE | ELF::SHF_ALLOC | ELF::SHF_HEX_GPREL); | |
373 } | |
374 | |
375 if (Kind.isCommon()) { | |
376 // This is purely for LTO+Linker Script because commons don't really have a | |
377 // section. However, the BitcodeSectionWriter pass will query for the | |
378 // sections of commons (and the linker expects us to know their section) so | |
379 // we'll return one here. | |
380 if (NoSmallDataSorting) | |
381 return BSSSection; | |
382 | |
383 Twine Name = Twine(".scommon") + getSectionSuffixForSize(Size); | |
384 TRACE(" small COMMON (" << Name << ")\n"); | |
385 | |
386 return getContext().getELFSection(Name.str(), ELF::SHT_NOBITS, | |
387 ELF::SHF_WRITE | ELF::SHF_ALLOC | | |
388 ELF::SHF_HEX_GPREL); | |
389 } | |
390 | |
391 // We could have changed sdata object to a constant... in this | |
392 // case the Kind could be wrong for it. | |
393 if (Kind.isMergeableConst()) { | |
394 TRACE(" const_object_as_data "); | |
395 const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GO); | |
396 if (GVar->hasSection() && isSmallDataSection(GVar->getSection())) | |
397 Kind = SectionKind::getData(); | |
398 } | |
399 | |
400 if (Kind.isData()) { | |
401 if (NoSmallDataSorting) { | |
402 TRACE(" default sdata\n"); | |
403 return SmallDataSection; | |
404 } | |
405 | |
406 StringRef Prefix(".sdata"); | |
407 SmallString<128> Name(Prefix); | |
408 Name.append(getSectionSuffixForSize(Size)); | |
409 | |
410 if (EmitUniquedSection) { | |
411 Name.append("."); | |
412 Name.append(GO->getName()); | |
413 } | |
414 TRACE(" unique sdata(" << Name << ")\n"); | |
415 return getContext().getELFSection(Name.str(), ELF::SHT_PROGBITS, | |
416 ELF::SHF_WRITE | ELF::SHF_ALLOC | ELF::SHF_HEX_GPREL); | |
417 } | |
418 | |
419 TRACE("default ELF section\n"); | |
420 // Otherwise, we work the same as ELF. | |
421 return TargetLoweringObjectFileELF::SelectSectionForGlobal(GO, Kind, TM); | |
422 } | |
423 | |
424 // Return the function that uses the lookup table. If there are more | |
425 // than one live function that uses this look table, bail out and place | |
426 // the lookup table in default section. | |
427 const Function * | |
428 HexagonTargetObjectFile::getLutUsedFunction(const GlobalObject *GO) const { | |
429 const Function *ReturnFn = nullptr; | |
430 for (auto U : GO->users()) { | |
431 // validate each instance of user to be a live function. | |
432 auto *I = dyn_cast<Instruction>(U); | |
433 if (!I) | |
434 continue; | |
435 auto *Bb = I->getParent(); | |
436 if (!Bb) | |
437 continue; | |
438 auto *UserFn = Bb->getParent(); | |
439 if (!ReturnFn) | |
440 ReturnFn = UserFn; | |
441 else if (ReturnFn != UserFn) | |
442 return nullptr; | |
443 } | |
444 return ReturnFn; | |
445 } | |
446 | |
447 MCSection *HexagonTargetObjectFile::selectSectionForLookupTable( | |
448 const GlobalObject *GO, const TargetMachine &TM, const Function *Fn) const { | |
449 | |
450 SectionKind Kind = SectionKind::getText(); | |
451 // If the function has explicit section, place the lookup table in this | |
452 // explicit section. | |
453 if (Fn->hasSection()) | |
454 return getExplicitSectionGlobal(Fn, Kind, TM); | |
455 | |
456 const auto *FuncObj = dyn_cast<GlobalObject>(Fn); | |
457 return SelectSectionForGlobal(FuncObj, Kind, TM); | |
458 } |