LLVM 23.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::ByteTyID:
320 case Type::IntegerTyID: {
321 const DataLayout &DL = GV->getDataLayout();
322 // It is unfortunate that DL's function take non-const Type*.
323 return DL.getTypeAllocSize(const_cast<Type*>(Ty));
324 }
326 case Type::VoidTyID:
327 case Type::BFloatTyID:
329 case Type::FP128TyID:
331 case Type::LabelTyID:
334 case Type::TokenTyID:
337 return 0;
338 }
339
340 return 0;
341}
342
343MCSection *HexagonTargetObjectFile::selectSmallSectionForGlobal(
344 const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const {
345 const Type *GTy = GO->getValueType();
346 unsigned Size = getSmallestAddressableSize(GTy, GO, TM);
347
348 // If we have -ffunction-section or -fdata-section then we should emit the
349 // global value to a unique section specifically for it... even for sdata.
350 bool EmitUniquedSection = TM.getDataSections();
351
352 TRACE("Small data. Size(" << Size << ")");
353 // Handle Small Section classification here.
354 if (Kind.isBSS() || Kind.isBSSLocal()) {
355 // If -mno-sort-sda is not set, find out smallest accessible entity in
356 // declaration and add it to the section name string.
357 // Note. It does not track the actual usage of the value, only its de-
358 // claration. Also, compiler adds explicit pad fields to some struct
359 // declarations - they are currently counted towards smallest addres-
360 // sable entity.
361 if (NoSmallDataSorting) {
362 TRACE(" default sbss\n");
363 return SmallBSSSection;
364 }
365
366 StringRef Prefix(".sbss");
367 SmallString<128> Name(Prefix);
369
370 if (EmitUniquedSection) {
371 Name.append(".");
372 Name.append(GO->getName());
373 }
374 TRACE(" unique sbss(" << Name << ")\n");
377 }
378
379 if (Kind.isCommon()) {
380 // This is purely for LTO+Linker Script because commons don't really have a
381 // section. However, the BitcodeSectionWriter pass will query for the
382 // sections of commons (and the linker expects us to know their section) so
383 // we'll return one here.
385 return BSSSection;
386
387 Twine Name = Twine(".scommon") + getSectionSuffixForSize(Size);
388 TRACE(" small COMMON (" << Name << ")\n");
389
393 }
394
395 // We could have changed sdata object to a constant... in this
396 // case the Kind could be wrong for it.
397 if (Kind.isMergeableConst()) {
398 TRACE(" const_object_as_data ");
399 const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GO);
400 if (GVar->hasSection() && isSmallDataSection(GVar->getSection()))
402 }
403
404 if (Kind.isData()) {
405 if (NoSmallDataSorting) {
406 TRACE(" default sdata\n");
407 return SmallDataSection;
408 }
409
410 StringRef Prefix(".sdata");
411 SmallString<128> Name(Prefix);
413
414 if (EmitUniquedSection) {
415 Name.append(".");
416 Name.append(GO->getName());
417 }
418 TRACE(" unique sdata(" << Name << ")\n");
421 }
422
423 TRACE("default ELF section\n");
424 // Otherwise, we work the same as ELF.
426}
427
428// Return the function that uses the lookup table. If there are more
429// than one live function that uses this look table, bail out and place
430// the lookup table in default section.
431const Function *
433 const Function *ReturnFn = nullptr;
434 for (const auto *U : GO->users()) {
435 // validate each instance of user to be a live function.
436 auto *I = dyn_cast<Instruction>(U);
437 if (!I)
438 continue;
439 auto *Bb = I->getParent();
440 if (!Bb)
441 continue;
442 auto *UserFn = Bb->getParent();
443 if (!ReturnFn)
444 ReturnFn = UserFn;
445 else if (ReturnFn != UserFn)
446 return nullptr;
447 }
448 return ReturnFn;
449}
450
451MCSection *HexagonTargetObjectFile::selectSectionForLookupTable(
452 const GlobalObject *GO, const TargetMachine &TM, const Function *Fn) const {
453
455 // If the function has explicit section, place the lookup table in this
456 // explicit section.
457 if (Fn->hasSection())
458 return getExplicitSectionGlobal(Fn, Kind, TM);
459
460 const auto *FuncObj = dyn_cast<GlobalObject>(Fn);
461 return SelectSectionForGlobal(FuncObj, Kind, TM);
462}
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:54
#define I(x, y, z)
Definition MD5.cpp:57
This file defines the SmallString class.
#define LLVM_DEBUG(...)
Definition Debug.h:114
LLVM_ABI 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:133
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:553
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:516
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:258
bool contains(StringRef Other) const
Return true if the given string is a substring of *this, and false otherwise.
Definition StringRef.h:446
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:46
@ X86_AMXTyID
AMX vectors (8192 bits, X86 specific)
Definition Type.h:67
@ FunctionTyID
Functions.
Definition Type.h:73
@ ArrayTyID
Arrays.
Definition Type.h:76
@ TypedPointerTyID
Typed pointer used by some GPU targets.
Definition Type.h:79
@ HalfTyID
16-bit floating point type
Definition Type.h:57
@ TargetExtTyID
Target extension type.
Definition Type.h:80
@ VoidTyID
type with no size
Definition Type.h:64
@ ScalableVectorTyID
Scalable SIMD vector type.
Definition Type.h:78
@ LabelTyID
Labels.
Definition Type.h:65
@ FloatTyID
32-bit floating point type
Definition Type.h:59
@ StructTyID
Structures.
Definition Type.h:75
@ IntegerTyID
Arbitrary bit width integers.
Definition Type.h:71
@ FixedVectorTyID
Fixed width SIMD vector type.
Definition Type.h:77
@ BFloatTyID
16-bit floating point type (7-bit significand)
Definition Type.h:58
@ DoubleTyID
64-bit floating point type
Definition Type.h:60
@ X86_FP80TyID
80-bit floating point type (X87)
Definition Type.h:61
@ PPC_FP128TyID
128-bit floating point type (two 64-bits, PowerPC)
Definition Type.h:63
@ MetadataTyID
Metadata.
Definition Type.h:66
@ TokenTyID
Tokens.
Definition Type.h:68
@ ByteTyID
Arbitrary bit width bytes.
Definition Type.h:72
@ PointerTyID
Pointers.
Definition Type.h:74
@ FP128TyID
128-bit floating point type (112-bit significand)
Definition Type.h:62
iterator_range< user_iterator > users()
Definition Value.h:427
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
Definition Value.cpp:322
@ SHF_ALLOC
Definition ELF.h:1247
@ SHF_HEX_GPREL
Definition ELF.h:1314
@ SHF_WRITE
Definition ELF.h:1244
@ SHF_EXECINSTR
Definition ELF.h:1250
@ SHT_PROGBITS
Definition ELF.h:1146
@ SHT_NOBITS
Definition ELF.h:1153
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
Definition Types.h:26
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
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:547
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559