LLVM 22.0.0git
HexagonTargetObjectFile.cpp
Go to the documentation of this file.
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
15#include "llvm/ADT/StringRef.h"
16#include "llvm/ADT/Twine.h"
18#include "llvm/IR/DataLayout.h"
21#include "llvm/IR/GlobalValue.h"
23#include "llvm/IR/Module.h"
24#include "llvm/IR/Type.h"
25#include "llvm/MC/MCContext.h"
26#include "llvm/MC/SectionKind.h"
29#include "llvm/Support/Debug.h"
32
33#define DEBUG_TYPE "hexagon-sdata"
34
35using namespace llvm;
36
37static cl::opt<unsigned> SmallDataThreshold("hexagon-small-data-threshold",
39 cl::desc("The maximum size of an object in the sdata section"));
40
41static cl::opt<bool> NoSmallDataSorting("mno-sort-sda", cl::init(false),
42 cl::Hidden, cl::desc("Disable small data sections sorting"));
43
44static cl::opt<bool>
45 StaticsInSData("hexagon-statics-in-small-data", cl::Hidden,
46 cl::desc("Allow static variables in .sdata"));
47
48static cl::opt<bool> TraceGVPlacement("trace-gv-placement",
49 cl::Hidden, cl::init(false),
50 cl::desc("Trace global value placement"));
51
52static cl::opt<bool>
53 EmitJtInText("hexagon-emit-jt-text", cl::Hidden, cl::init(false),
54 cl::desc("Emit hexagon jump tables in function section"));
55
56static cl::opt<bool>
57 EmitLutInText("hexagon-emit-lut-text", cl::Hidden, cl::init(false),
58 cl::desc("Emit hexagon lookup tables in function section"));
59
60// TraceGVPlacement controls messages for all builds. For builds with assertions
61// (debug or release), messages are also controlled by the usual debug flags
62// (e.g. -debug and -debug-only=globallayout)
63#define TRACE_TO(s, X) s << X
64#ifdef NDEBUG
65#define TRACE(X) \
66 do { \
67 if (TraceGVPlacement) { \
68 TRACE_TO(errs(), X); \
69 } \
70 } while (false)
71#else
72#define TRACE(X) \
73 do { \
74 if (TraceGVPlacement) { \
75 TRACE_TO(errs(), X); \
76 } else { \
77 LLVM_DEBUG(TRACE_TO(dbgs(), X)); \
78 } \
79 } while (false)
80#endif
81
82// Returns true if the section name is such that the symbol will be put
83// in a small data section.
84// For instance, global variables with section attributes such as ".sdata"
85// ".sdata.*", ".sbss", and ".sbss.*" will go into small data.
86static bool isSmallDataSection(StringRef Sec) {
87 // sectionName is either ".sdata" or ".sbss". Looking for an exact match
88 // obviates the need for checks for section names such as ".sdatafoo".
89 if (Sec == ".sdata" || Sec == ".sbss" || Sec == ".scommon")
90 return true;
91 // If either ".sdata." or ".sbss." is a substring of the section name
92 // then put the symbol in small data.
93 return Sec.contains(".sdata.") || Sec.contains(".sbss.") ||
94 Sec.contains(".scommon.");
95}
96
97static 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
125
127 const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const {
128 TRACE("[SelectSectionForGlobal] GO(" << GO->getName() << ") ");
129 TRACE("input section(" << GO->getSection() << ") ");
130
131 TRACE((GO->hasPrivateLinkage() ? "private_linkage " : "")
132 << (GO->hasLocalLinkage() ? "local_linkage " : "")
133 << (GO->hasInternalLinkage() ? "internal " : "")
134 << (GO->hasExternalLinkage() ? "external " : "")
135 << (GO->hasCommonLinkage() ? "common_linkage " : "")
136 << (GO->hasCommonLinkage() ? "common " : "" )
137 << (Kind.isCommon() ? "kind_common " : "" )
138 << (Kind.isBSS() ? "kind_bss " : "" )
139 << (Kind.isBSSLocal() ? "kind_bss_local " : "" ));
140
141 // If the lookup table is used by more than one function, do not place
142 // it in text section.
143 if (EmitLutInText && GO->getName().starts_with("switch.table")) {
144 if (const Function *Fn = getLutUsedFunction(GO))
145 return selectSectionForLookupTable(GO, TM, Fn);
146 }
147
148 if (isGlobalInSmallSection(GO, TM))
149 return selectSmallSectionForGlobal(GO, Kind, TM);
150
151 if (Kind.isCommon()) {
152 // This is purely for LTO+Linker Script because commons don't really have a
153 // section. However, the BitcodeSectionWriter pass will query for the
154 // sections of commons (and the linker expects us to know their section) so
155 // we'll return one here.
156 return BSSSection;
157 }
158
159 TRACE("default_ELF_section\n");
160 // Otherwise, we work the same as ELF.
162}
163
165 const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const {
166 TRACE("[getExplicitSectionGlobal] GO(" << GO->getName() << ") from("
167 << GO->getSection() << ") ");
168 TRACE((GO->hasPrivateLinkage() ? "private_linkage " : "")
169 << (GO->hasLocalLinkage() ? "local_linkage " : "")
170 << (GO->hasInternalLinkage() ? "internal " : "")
171 << (GO->hasExternalLinkage() ? "external " : "")
172 << (GO->hasCommonLinkage() ? "common_linkage " : "")
173 << (GO->hasCommonLinkage() ? "common " : "" )
174 << (Kind.isCommon() ? "kind_common " : "" )
175 << (Kind.isBSS() ? "kind_bss " : "" )
176 << (Kind.isBSSLocal() ? "kind_bss_local " : "" ));
177
178 if (GO->hasSection()) {
179 StringRef Section = GO->getSection();
180 if (Section.contains(".access.text.group"))
183 if (Section.contains(".access.data.group"))
186 }
187
188 if (isGlobalInSmallSection(GO, TM))
189 return selectSmallSectionForGlobal(GO, Kind, TM);
190
191 // Otherwise, we work the same as ELF.
192 TRACE("default_ELF_section\n");
194}
195
196/// Return true if this global value should be placed into small data/bss
197/// section.
199 const TargetMachine &TM) const {
200 bool HaveSData = isSmallDataEnabled(TM);
201 if (!HaveSData)
202 LLVM_DEBUG(dbgs() << "Small-data allocation is disabled, but symbols "
203 "may have explicit section assignments...\n");
204 // Only global variables, not functions.
205 LLVM_DEBUG(dbgs() << "Checking if value is in small-data, -G"
206 << SmallDataThreshold << ": \"" << GO->getName() << "\": ");
208 if (!GVar) {
209 LLVM_DEBUG(dbgs() << "no, not a global variable\n");
210 return false;
211 }
212
213 // Globals with external linkage that have an original section set must be
214 // emitted to that section, regardless of whether we would put them into
215 // small data or not. This is how we can support mixing -G0/-G8 in LTO.
216 if (GVar->hasSection()) {
217 bool IsSmall = isSmallDataSection(GVar->getSection());
218 LLVM_DEBUG(dbgs() << (IsSmall ? "yes" : "no")
219 << ", has section: " << GVar->getSection() << '\n');
220 return IsSmall;
221 }
222
223 // If sdata is disabled, stop the checks here.
224 if (!HaveSData) {
225 LLVM_DEBUG(dbgs() << "no, small-data allocation is disabled\n");
226 return false;
227 }
228
229 if (GVar->isConstant()) {
230 LLVM_DEBUG(dbgs() << "no, is a constant\n");
231 return false;
232 }
233
234 bool IsLocal = GVar->hasLocalLinkage();
235 if (!StaticsInSData && IsLocal) {
236 LLVM_DEBUG(dbgs() << "no, is static\n");
237 return false;
238 }
239
240 Type *GType = GVar->getValueType();
241 if (isa<ArrayType>(GType)) {
242 LLVM_DEBUG(dbgs() << "no, is an array\n");
243 return false;
244 }
245
246 // If the type is a struct with no body provided, treat is conservatively.
247 // There cannot be actual definitions of object of such a type in this CU
248 // (only references), so assuming that they are not in sdata is safe. If
249 // these objects end up in the sdata, the references will still be valid.
250 if (StructType *ST = dyn_cast<StructType>(GType)) {
251 if (ST->isOpaque()) {
252 LLVM_DEBUG(dbgs() << "no, has opaque type\n");
253 return false;
254 }
255 }
256
257 unsigned Size = GVar->getDataLayout().getTypeAllocSize(GType);
258 if (Size == 0) {
259 LLVM_DEBUG(dbgs() << "no, has size 0\n");
260 return false;
261 }
262 if (Size > SmallDataThreshold) {
263 LLVM_DEBUG(dbgs() << "no, size exceeds sdata threshold: " << Size << '\n');
264 return false;
265 }
266
267 LLVM_DEBUG(dbgs() << "yes\n");
268 return true;
269}
270
272 const {
273 return SmallDataThreshold > 0 && !TM.isPositionIndependent();
274}
275
279
281 bool UsesLabelDifference, const Function &F) const {
282 return EmitJtInText;
283}
284
285/// Descends any type down to "elementary" components,
286/// discovering the smallest addressable one.
287/// If zero is returned, declaration will not be modified.
288unsigned HexagonTargetObjectFile::getSmallestAddressableSize(const Type *Ty,
289 const GlobalValue *GV, const TargetMachine &TM) const {
290 // Assign the smallest element access size to the highest
291 // value which assembler can handle.
292 unsigned SmallestElement = 8;
293
294 if (!Ty)
295 return 0;
296 switch (Ty->getTypeID()) {
297 case Type::StructTyID: {
298 const StructType *STy = cast<const StructType>(Ty);
299 for (auto &E : STy->elements()) {
300 unsigned AtomicSize = getSmallestAddressableSize(E, GV, TM);
301 if (AtomicSize < SmallestElement)
302 SmallestElement = AtomicSize;
303 }
304 return (STy->getNumElements() == 0) ? 0 : SmallestElement;
305 }
306 case Type::ArrayTyID: {
307 const ArrayType *ATy = cast<const ArrayType>(Ty);
308 return getSmallestAddressableSize(ATy->getElementType(), GV, TM);
309 }
312 const VectorType *PTy = cast<const VectorType>(Ty);
313 return getSmallestAddressableSize(PTy->getElementType(), GV, TM);
314 }
316 case Type::HalfTyID:
317 case Type::FloatTyID:
318 case Type::DoubleTyID:
319 case Type::IntegerTyID: {
320 const DataLayout &DL = GV->getDataLayout();
321 // It is unfortunate that DL's function take non-const Type*.
322 return DL.getTypeAllocSize(const_cast<Type*>(Ty));
323 }
325 case Type::VoidTyID:
326 case Type::BFloatTyID:
328 case Type::FP128TyID:
330 case Type::LabelTyID:
333 case Type::TokenTyID:
336 return 0;
337 }
338
339 return 0;
340}
341
342MCSection *HexagonTargetObjectFile::selectSmallSectionForGlobal(
343 const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const {
344 const Type *GTy = GO->getValueType();
345 unsigned Size = getSmallestAddressableSize(GTy, GO, TM);
346
347 // If we have -ffunction-section or -fdata-section then we should emit the
348 // global value to a unique section specifically for it... even for sdata.
349 bool EmitUniquedSection = TM.getDataSections();
350
351 TRACE("Small data. Size(" << Size << ")");
352 // Handle Small Section classification here.
353 if (Kind.isBSS() || Kind.isBSSLocal()) {
354 // If -mno-sort-sda is not set, find out smallest accessible entity in
355 // declaration and add it to the section name string.
356 // Note. It does not track the actual usage of the value, only its de-
357 // claration. Also, compiler adds explicit pad fields to some struct
358 // declarations - they are currently counted towards smallest addres-
359 // sable entity.
360 if (NoSmallDataSorting) {
361 TRACE(" default sbss\n");
362 return SmallBSSSection;
363 }
364
365 StringRef Prefix(".sbss");
366 SmallString<128> Name(Prefix);
368
369 if (EmitUniquedSection) {
370 Name.append(".");
371 Name.append(GO->getName());
372 }
373 TRACE(" unique sbss(" << Name << ")\n");
376 }
377
378 if (Kind.isCommon()) {
379 // This is purely for LTO+Linker Script because commons don't really have a
380 // section. However, the BitcodeSectionWriter pass will query for the
381 // sections of commons (and the linker expects us to know their section) so
382 // we'll return one here.
384 return BSSSection;
385
386 Twine Name = Twine(".scommon") + getSectionSuffixForSize(Size);
387 TRACE(" small COMMON (" << Name << ")\n");
388
392 }
393
394 // We could have changed sdata object to a constant... in this
395 // case the Kind could be wrong for it.
396 if (Kind.isMergeableConst()) {
397 TRACE(" const_object_as_data ");
398 const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GO);
399 if (GVar->hasSection() && isSmallDataSection(GVar->getSection()))
401 }
402
403 if (Kind.isData()) {
404 if (NoSmallDataSorting) {
405 TRACE(" default sdata\n");
406 return SmallDataSection;
407 }
408
409 StringRef Prefix(".sdata");
410 SmallString<128> Name(Prefix);
412
413 if (EmitUniquedSection) {
414 Name.append(".");
415 Name.append(GO->getName());
416 }
417 TRACE(" unique sdata(" << Name << ")\n");
420 }
421
422 TRACE("default ELF section\n");
423 // Otherwise, we work the same as ELF.
425}
426
427// Return the function that uses the lookup table. If there are more
428// than one live function that uses this look table, bail out and place
429// the lookup table in default section.
430const Function *
432 const Function *ReturnFn = nullptr;
433 for (const auto *U : GO->users()) {
434 // validate each instance of user to be a live function.
435 auto *I = dyn_cast<Instruction>(U);
436 if (!I)
437 continue;
438 auto *Bb = I->getParent();
439 if (!Bb)
440 continue;
441 auto *UserFn = Bb->getParent();
442 if (!ReturnFn)
443 ReturnFn = UserFn;
444 else if (ReturnFn != UserFn)
445 return nullptr;
446 }
447 return ReturnFn;
448}
449
450MCSection *HexagonTargetObjectFile::selectSectionForLookupTable(
451 const GlobalObject *GO, const TargetMachine &TM, const Function *Fn) const {
452
454 // If the function has explicit section, place the lookup table in this
455 // explicit section.
456 if (Fn->hasSection())
457 return getExplicitSectionGlobal(Fn, Kind, TM);
458
459 const auto *FuncObj = dyn_cast<GlobalObject>(Fn);
460 return SelectSectionForGlobal(FuncObj, Kind, TM);
461}
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static cl::opt< bool > TraceGVPlacement("trace-gv-placement", cl::Hidden, cl::init(false), cl::desc("Trace global value placement"))
static cl::opt< bool > EmitJtInText("hexagon-emit-jt-text", cl::Hidden, cl::init(false), cl::desc("Emit hexagon jump tables in function section"))
static cl::opt< unsigned > SmallDataThreshold("hexagon-small-data-threshold", cl::init(8), cl::Hidden, cl::desc("The maximum size of an object in the sdata section"))
static cl::opt< bool > StaticsInSData("hexagon-statics-in-small-data", cl::Hidden, cl::desc("Allow static variables in .sdata"))
#define TRACE(X)
static const char * getSectionSuffixForSize(unsigned Size)
static cl::opt< bool > EmitLutInText("hexagon-emit-lut-text", cl::Hidden, cl::init(false), cl::desc("Emit hexagon lookup tables in function section"))
static cl::opt< bool > NoSmallDataSorting("mno-sort-sda", cl::init(false), cl::Hidden, cl::desc("Disable small data sections sorting"))
static bool isSmallDataSection(StringRef Sec)
Module.h This file contains the declarations for the Module class.
#define F(x, y, z)
Definition MD5.cpp:55
#define I(x, y, z)
Definition MD5.cpp:58
This file defines the SmallString class.
#define LLVM_DEBUG(...)
Definition Debug.h:119
TypeSize getTypeAllocSize(Type *Ty) const
Returns the offset in bytes between successive objects of the specified type, including alignment pad...
StringRef getSection() const
Get the custom section of this global if it has one.
bool hasSection() const
Check if this global has a custom object file section.
bool hasExternalLinkage() const
bool hasLocalLinkage() const
bool hasPrivateLinkage() const
bool hasInternalLinkage() const
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this global belongs to.
Definition Globals.cpp:132
bool hasCommonLinkage() const
Type * getValueType() const
bool isConstant() const
If the value is a global constant, its value is immutable throughout the runtime execution of the pro...
bool shouldPutJumpTableInFunctionSection(bool UsesLabelDifference, const Function &F) const override
bool isSmallDataEnabled(const TargetMachine &TM) const
void Initialize(MCContext &Ctx, const TargetMachine &TM) override
This method must be called before any actual lowering is done.
bool isGlobalInSmallSection(const GlobalObject *GO, const TargetMachine &TM) const
Return true if this global value should be placed into small data/bss section.
MCSection * SelectSectionForGlobal(const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const override
MCSection * getExplicitSectionGlobal(const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const override
Targets should implement this method to assign a section to globals with an explicit section specfied...
const Function * getLutUsedFunction(const GlobalObject *GO) const
Context object for machine code objects.
Definition MCContext.h:83
MCSectionELF * getELFSection(const Twine &Section, unsigned Type, unsigned Flags)
Definition MCContext.h:549
MCSection * BSSSection
Section that is default initialized to zero.
MCContext & getContext() const
Instances of this class represent a uniqued identifier for a section in the current translation unit.
Definition MCSection.h:496
SectionKind - This is a simple POD value that classifies the properties of a section.
Definition SectionKind.h:22
static SectionKind getText()
static SectionKind getData()
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
Definition StringRef.h:269
bool contains(StringRef Other) const
Return true if the given string is a substring of *this, and false otherwise.
Definition StringRef.h:434
Class to represent struct types.
ArrayRef< Type * > elements() const
unsigned getNumElements() const
Random access to the elements.
void Initialize(MCContext &Ctx, const TargetMachine &TM) override
This method must be called before any actual lowering is done.
MCSection * SelectSectionForGlobal(const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const override
MCSection * getExplicitSectionGlobal(const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const override
Targets should implement this method to assign a section to globals with an explicit section specfied...
Primary interface to the complete machine description for the target machine.
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:45
@ X86_AMXTyID
AMX vectors (8192 bits, X86 specific)
Definition Type.h:66
@ FunctionTyID
Functions.
Definition Type.h:71
@ ArrayTyID
Arrays.
Definition Type.h:74
@ TypedPointerTyID
Typed pointer used by some GPU targets.
Definition Type.h:77
@ HalfTyID
16-bit floating point type
Definition Type.h:56
@ TargetExtTyID
Target extension type.
Definition Type.h:78
@ VoidTyID
type with no size
Definition Type.h:63
@ ScalableVectorTyID
Scalable SIMD vector type.
Definition Type.h:76
@ LabelTyID
Labels.
Definition Type.h:64
@ FloatTyID
32-bit floating point type
Definition Type.h:58
@ StructTyID
Structures.
Definition Type.h:73
@ IntegerTyID
Arbitrary bit width integers.
Definition Type.h:70
@ FixedVectorTyID
Fixed width SIMD vector type.
Definition Type.h:75
@ BFloatTyID
16-bit floating point type (7-bit significand)
Definition Type.h:57
@ DoubleTyID
64-bit floating point type
Definition Type.h:59
@ X86_FP80TyID
80-bit floating point type (X87)
Definition Type.h:60
@ PPC_FP128TyID
128-bit floating point type (two 64-bits, PowerPC)
Definition Type.h:62
@ MetadataTyID
Metadata.
Definition Type.h:65
@ TokenTyID
Tokens.
Definition Type.h:67
@ PointerTyID
Pointers.
Definition Type.h:72
@ FP128TyID
128-bit floating point type (112-bit significand)
Definition Type.h:61
iterator_range< user_iterator > users()
Definition Value.h:426
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
Definition Value.cpp:322
@ SHT_PROGBITS
Definition ELF.h:1140
@ SHT_NOBITS
Definition ELF.h:1147
@ SHF_ALLOC
Definition ELF.h:1240
@ SHF_HEX_GPREL
Definition ELF.h:1307
@ SHF_WRITE
Definition ELF.h:1237
@ SHF_EXECINSTR
Definition ELF.h:1243
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:649
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:207
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:548
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:565