LLVM 24.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
113 const TargetMachine &TM,
114 const Module &M) {
116
117 SmallDataSection =
121 SmallBSSSection =
125}
126
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().starts_with("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.
163}
164
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.contains(".access.text.group"))
184 if (Section.contains(".access.data.group"))
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");
195}
196
197/// Return true if this global value should be placed into small data/bss
198/// section.
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() << "\": ");
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->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
273 const {
274 return SmallDataThreshold > 0 && !TM.isPositionIndependent();
275}
276
280
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.
289unsigned 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 }
313 const VectorType *PTy = cast<const VectorType>(Ty);
314 return getSmallestAddressableSize(PTy->getElementType(), GV, TM);
315 }
317 case Type::HalfTyID:
318 case Type::FloatTyID:
319 case Type::DoubleTyID:
320 case Type::ByteTyID:
321 case Type::IntegerTyID: {
322 const DataLayout &DL = GV->getDataLayout();
323 // It is unfortunate that DL's function take non-const Type*.
324 return DL.getTypeAllocSize(const_cast<Type*>(Ty));
325 }
327 case Type::VoidTyID:
328 case Type::BFloatTyID:
330 case Type::FP128TyID:
332 case Type::LabelTyID:
335 case Type::TokenTyID:
338 return 0;
339 }
340
341 return 0;
342}
343
344MCSection *HexagonTargetObjectFile::selectSmallSectionForGlobal(
345 const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const {
346 const Type *GTy = GO->getValueType();
347 unsigned Size = getSmallestAddressableSize(GTy, GO, TM);
348
349 // If we have -ffunction-section or -fdata-section then we should emit the
350 // global value to a unique section specifically for it... even for sdata.
351 bool EmitUniquedSection = TM.getDataSections();
352
353 TRACE("Small data. Size(" << Size << ")");
354 // Handle Small Section classification here.
355 if (Kind.isBSS() || Kind.isBSSLocal()) {
356 // If -mno-sort-sda is not set, find out smallest accessible entity in
357 // declaration and add it to the section name string.
358 // Note. It does not track the actual usage of the value, only its de-
359 // claration. Also, compiler adds explicit pad fields to some struct
360 // declarations - they are currently counted towards smallest addres-
361 // sable entity.
362 if (NoSmallDataSorting) {
363 TRACE(" default sbss\n");
364 return SmallBSSSection;
365 }
366
367 StringRef Prefix(".sbss");
368 SmallString<128> Name(Prefix);
370
371 if (EmitUniquedSection) {
372 Name.append(".");
373 Name.append(GO->getName());
374 }
375 TRACE(" unique sbss(" << Name << ")\n");
378 }
379
380 if (Kind.isCommon()) {
381 // This is purely for LTO+Linker Script because commons don't really have a
382 // section. However, the BitcodeSectionWriter pass will query for the
383 // sections of commons (and the linker expects us to know their section) so
384 // we'll return one here.
386 return BSSSection;
387
388 Twine Name = Twine(".scommon") + getSectionSuffixForSize(Size);
389 TRACE(" small COMMON (" << Name << ")\n");
390
394 }
395
396 // We could have changed sdata object to a constant... in this
397 // case the Kind could be wrong for it.
398 if (Kind.isMergeableConst()) {
399 TRACE(" const_object_as_data ");
400 const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GO);
401 if (GVar->hasSection() && isSmallDataSection(GVar->getSection()))
403 }
404
405 if (Kind.isData()) {
406 if (NoSmallDataSorting) {
407 TRACE(" default sdata\n");
408 return SmallDataSection;
409 }
410
411 StringRef Prefix(".sdata");
412 SmallString<128> Name(Prefix);
414
415 if (EmitUniquedSection) {
416 Name.append(".");
417 Name.append(GO->getName());
418 }
419 TRACE(" unique sdata(" << Name << ")\n");
422 }
423
424 TRACE("default ELF section\n");
425 // Otherwise, we work the same as ELF.
427}
428
429// Return the function that uses the lookup table. If there are more
430// than one live function that uses this look table, bail out and place
431// the lookup table in default section.
432const Function *
434 const Function *ReturnFn = nullptr;
435 for (const auto *U : GO->users()) {
436 // validate each instance of user to be a live function.
437 auto *I = dyn_cast<Instruction>(U);
438 if (!I)
439 continue;
440 auto *Bb = I->getParent();
441 if (!Bb)
442 continue;
443 auto *UserFn = Bb->getParent();
444 if (!ReturnFn)
445 ReturnFn = UserFn;
446 else if (ReturnFn != UserFn)
447 return nullptr;
448 }
449 return ReturnFn;
450}
451
452MCSection *HexagonTargetObjectFile::selectSectionForLookupTable(
453 const GlobalObject *GO, const TargetMachine &TM, const Function *Fn) const {
454
456 // If the function has explicit section, place the lookup table in this
457 // explicit section.
458 if (Fn->hasSection())
459 return getExplicitSectionGlobal(Fn, Kind, TM);
460
461 const auto *FuncObj = dyn_cast<GlobalObject>(Fn);
462 return SelectSectionForGlobal(FuncObj, Kind, TM);
463}
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:119
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:205
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, const Module &M) 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:550
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:580
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:68
SectionKind - This is a simple POD value that classifies the properties of a section.
Definition SectionKind.h:22
static SectionKind getText()
static SectionKind getData()
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
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.
MCSection * SelectSectionForGlobal(const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const override
void initialize(MCContext &Ctx, const TargetMachine &TM, const Module &M) override
This method must be called before any actual lowering is done.
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:428
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
Definition Value.cpp:319
@ SHF_ALLOC
Definition ELF.h:1259
@ SHF_HEX_GPREL
Definition ELF.h:1326
@ SHF_WRITE
Definition ELF.h:1256
@ SHF_EXECINSTR
Definition ELF.h:1262
@ SHT_PROGBITS
Definition ELF.h:1157
@ SHT_NOBITS
Definition ELF.h:1164
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:643
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
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