File: | llvm/lib/Target/Hexagon/HexagonTargetObjectFile.cpp |
Warning: | line 144, column 24 Called C++ object pointer is null |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 | #include "HexagonTargetObjectFile.h" | |||
14 | #include "llvm/ADT/SmallString.h" | |||
15 | #include "llvm/ADT/StringRef.h" | |||
16 | #include "llvm/ADT/Twine.h" | |||
17 | #include "llvm/BinaryFormat/ELF.h" | |||
18 | #include "llvm/IR/DataLayout.h" | |||
19 | #include "llvm/IR/DerivedTypes.h" | |||
20 | #include "llvm/IR/GlobalObject.h" | |||
21 | #include "llvm/IR/GlobalValue.h" | |||
22 | #include "llvm/IR/GlobalVariable.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" | |||
27 | #include "llvm/Support/Casting.h" | |||
28 | #include "llvm/Support/CommandLine.h" | |||
29 | #include "llvm/Support/Debug.h" | |||
30 | #include "llvm/Support/raw_ostream.h" | |||
31 | #include "llvm/Target/TargetMachine.h" | |||
32 | ||||
33 | #define DEBUG_TYPE"hexagon-sdata" "hexagon-sdata" | |||
34 | ||||
35 | using namespace llvm; | |||
36 | ||||
37 | static cl::opt<unsigned> SmallDataThreshold("hexagon-small-data-threshold", | |||
38 | cl::init(8), cl::Hidden, | |||
39 | cl::desc("The maximum size of an object in the sdata section")); | |||
40 | ||||
41 | static cl::opt<bool> NoSmallDataSorting("mno-sort-sda", cl::init(false), | |||
42 | cl::Hidden, cl::desc("Disable small data sections sorting")); | |||
43 | ||||
44 | static cl::opt<bool> StaticsInSData("hexagon-statics-in-small-data", | |||
45 | cl::init(false), cl::Hidden, cl::ZeroOrMore, | |||
46 | cl::desc("Allow static variables in .sdata")); | |||
47 | ||||
48 | static cl::opt<bool> TraceGVPlacement("trace-gv-placement", | |||
49 | cl::Hidden, cl::init(false), | |||
50 | cl::desc("Trace global value placement")); | |||
51 | ||||
52 | static 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 | ||||
56 | static 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 s << X | |||
64 | #ifdef NDEBUG1 | |||
65 | #define TRACE(X)do { if (TraceGVPlacement) { errs() << X; } } while (false ) \ | |||
66 | do { \ | |||
67 | if (TraceGVPlacement) { \ | |||
68 | TRACE_TO(errs(), X)errs() << X; \ | |||
69 | } \ | |||
70 | } while (false) | |||
71 | #else | |||
72 | #define TRACE(X)do { if (TraceGVPlacement) { errs() << X; } } while (false ) \ | |||
73 | do { \ | |||
74 | if (TraceGVPlacement) { \ | |||
75 | TRACE_TO(errs(), X)errs() << X; \ | |||
76 | } else { \ | |||
77 | LLVM_DEBUG(TRACE_TO(dbgs(), X))do { } while (false); \ | |||
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. | |||
86 | static 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.equals(".sdata") || Sec.equals(".sbss") || Sec.equals(".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.find(".sdata.") != StringRef::npos || | |||
94 | Sec.find(".sbss.") != StringRef::npos || | |||
95 | Sec.find(".scommon.") != StringRef::npos; | |||
96 | } | |||
97 | ||||
98 | static const char *getSectionSuffixForSize(unsigned Size) { | |||
99 | switch (Size) { | |||
100 | default: | |||
101 | return ""; | |||
102 | case 1: | |||
103 | return ".1"; | |||
104 | case 2: | |||
105 | return ".2"; | |||
106 | case 4: | |||
107 | return ".4"; | |||
108 | case 8: | |||
109 | return ".8"; | |||
110 | } | |||
111 | } | |||
112 | ||||
113 | void HexagonTargetObjectFile::Initialize(MCContext &Ctx, | |||
114 | const TargetMachine &TM) { | |||
115 | TargetLoweringObjectFileELF::Initialize(Ctx, TM); | |||
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() << ") ")do { if (TraceGVPlacement) { errs() << "[SelectSectionForGlobal] GO(" << GO->getName() << ") "; } } while (false); | |||
| ||||
130 | TRACE("input section(" << GO->getSection() << ") ")do { if (TraceGVPlacement) { errs() << "input section(" << GO->getSection() << ") "; } } while (false ); | |||
131 | ||||
132 | TRACE((GO->hasPrivateLinkage() ? "private_linkage " : "")do { if (TraceGVPlacement) { errs() << (GO->hasPrivateLinkage () ? "private_linkage " : "") << (GO->hasLocalLinkage () ? "local_linkage " : "") << (GO->hasInternalLinkage () ? "internal " : "") << (GO->hasExternalLinkage() ? "external " : "") << (GO->hasCommonLinkage() ? "common_linkage " : "") << (GO->hasCommonLinkage() ? "common " : "" ) << (Kind.isCommon() ? "kind_common " : "" ) << ( Kind.isBSS() ? "kind_bss " : "" ) << (Kind.isBSSLocal() ? "kind_bss_local " : "" ); } } while (false) | |||
133 | << (GO->hasLocalLinkage() ? "local_linkage " : "")do { if (TraceGVPlacement) { errs() << (GO->hasPrivateLinkage () ? "private_linkage " : "") << (GO->hasLocalLinkage () ? "local_linkage " : "") << (GO->hasInternalLinkage () ? "internal " : "") << (GO->hasExternalLinkage() ? "external " : "") << (GO->hasCommonLinkage() ? "common_linkage " : "") << (GO->hasCommonLinkage() ? "common " : "" ) << (Kind.isCommon() ? "kind_common " : "" ) << ( Kind.isBSS() ? "kind_bss " : "" ) << (Kind.isBSSLocal() ? "kind_bss_local " : "" ); } } while (false) | |||
134 | << (GO->hasInternalLinkage() ? "internal " : "")do { if (TraceGVPlacement) { errs() << (GO->hasPrivateLinkage () ? "private_linkage " : "") << (GO->hasLocalLinkage () ? "local_linkage " : "") << (GO->hasInternalLinkage () ? "internal " : "") << (GO->hasExternalLinkage() ? "external " : "") << (GO->hasCommonLinkage() ? "common_linkage " : "") << (GO->hasCommonLinkage() ? "common " : "" ) << (Kind.isCommon() ? "kind_common " : "" ) << ( Kind.isBSS() ? "kind_bss " : "" ) << (Kind.isBSSLocal() ? "kind_bss_local " : "" ); } } while (false) | |||
135 | << (GO->hasExternalLinkage() ? "external " : "")do { if (TraceGVPlacement) { errs() << (GO->hasPrivateLinkage () ? "private_linkage " : "") << (GO->hasLocalLinkage () ? "local_linkage " : "") << (GO->hasInternalLinkage () ? "internal " : "") << (GO->hasExternalLinkage() ? "external " : "") << (GO->hasCommonLinkage() ? "common_linkage " : "") << (GO->hasCommonLinkage() ? "common " : "" ) << (Kind.isCommon() ? "kind_common " : "" ) << ( Kind.isBSS() ? "kind_bss " : "" ) << (Kind.isBSSLocal() ? "kind_bss_local " : "" ); } } while (false) | |||
136 | << (GO->hasCommonLinkage() ? "common_linkage " : "")do { if (TraceGVPlacement) { errs() << (GO->hasPrivateLinkage () ? "private_linkage " : "") << (GO->hasLocalLinkage () ? "local_linkage " : "") << (GO->hasInternalLinkage () ? "internal " : "") << (GO->hasExternalLinkage() ? "external " : "") << (GO->hasCommonLinkage() ? "common_linkage " : "") << (GO->hasCommonLinkage() ? "common " : "" ) << (Kind.isCommon() ? "kind_common " : "" ) << ( Kind.isBSS() ? "kind_bss " : "" ) << (Kind.isBSSLocal() ? "kind_bss_local " : "" ); } } while (false) | |||
137 | << (GO->hasCommonLinkage() ? "common " : "" )do { if (TraceGVPlacement) { errs() << (GO->hasPrivateLinkage () ? "private_linkage " : "") << (GO->hasLocalLinkage () ? "local_linkage " : "") << (GO->hasInternalLinkage () ? "internal " : "") << (GO->hasExternalLinkage() ? "external " : "") << (GO->hasCommonLinkage() ? "common_linkage " : "") << (GO->hasCommonLinkage() ? "common " : "" ) << (Kind.isCommon() ? "kind_common " : "" ) << ( Kind.isBSS() ? "kind_bss " : "" ) << (Kind.isBSSLocal() ? "kind_bss_local " : "" ); } } while (false) | |||
138 | << (Kind.isCommon() ? "kind_common " : "" )do { if (TraceGVPlacement) { errs() << (GO->hasPrivateLinkage () ? "private_linkage " : "") << (GO->hasLocalLinkage () ? "local_linkage " : "") << (GO->hasInternalLinkage () ? "internal " : "") << (GO->hasExternalLinkage() ? "external " : "") << (GO->hasCommonLinkage() ? "common_linkage " : "") << (GO->hasCommonLinkage() ? "common " : "" ) << (Kind.isCommon() ? "kind_common " : "" ) << ( Kind.isBSS() ? "kind_bss " : "" ) << (Kind.isBSSLocal() ? "kind_bss_local " : "" ); } } while (false) | |||
139 | << (Kind.isBSS() ? "kind_bss " : "" )do { if (TraceGVPlacement) { errs() << (GO->hasPrivateLinkage () ? "private_linkage " : "") << (GO->hasLocalLinkage () ? "local_linkage " : "") << (GO->hasInternalLinkage () ? "internal " : "") << (GO->hasExternalLinkage() ? "external " : "") << (GO->hasCommonLinkage() ? "common_linkage " : "") << (GO->hasCommonLinkage() ? "common " : "" ) << (Kind.isCommon() ? "kind_common " : "" ) << ( Kind.isBSS() ? "kind_bss " : "" ) << (Kind.isBSSLocal() ? "kind_bss_local " : "" ); } } while (false) | |||
140 | << (Kind.isBSSLocal() ? "kind_bss_local " : "" ))do { if (TraceGVPlacement) { errs() << (GO->hasPrivateLinkage () ? "private_linkage " : "") << (GO->hasLocalLinkage () ? "local_linkage " : "") << (GO->hasInternalLinkage () ? "internal " : "") << (GO->hasExternalLinkage() ? "external " : "") << (GO->hasCommonLinkage() ? "common_linkage " : "") << (GO->hasCommonLinkage() ? "common " : "" ) << (Kind.isCommon() ? "kind_common " : "" ) << ( Kind.isBSS() ? "kind_bss " : "" ) << (Kind.isBSSLocal() ? "kind_bss_local " : "" ); } } while (false); | |||
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")do { if (TraceGVPlacement) { errs() << "default_ELF_section\n" ; } } while (false); | |||
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("do { if (TraceGVPlacement) { errs() << "[getExplicitSectionGlobal] GO(" << GO->getName() << ") from(" << GO-> getSection() << ") "; } } while (false) | |||
168 | << GO->getSection() << ") ")do { if (TraceGVPlacement) { errs() << "[getExplicitSectionGlobal] GO(" << GO->getName() << ") from(" << GO-> getSection() << ") "; } } while (false); | |||
169 | TRACE((GO->hasPrivateLinkage() ? "private_linkage " : "")do { if (TraceGVPlacement) { errs() << (GO->hasPrivateLinkage () ? "private_linkage " : "") << (GO->hasLocalLinkage () ? "local_linkage " : "") << (GO->hasInternalLinkage () ? "internal " : "") << (GO->hasExternalLinkage() ? "external " : "") << (GO->hasCommonLinkage() ? "common_linkage " : "") << (GO->hasCommonLinkage() ? "common " : "" ) << (Kind.isCommon() ? "kind_common " : "" ) << ( Kind.isBSS() ? "kind_bss " : "" ) << (Kind.isBSSLocal() ? "kind_bss_local " : "" ); } } while (false) | |||
170 | << (GO->hasLocalLinkage() ? "local_linkage " : "")do { if (TraceGVPlacement) { errs() << (GO->hasPrivateLinkage () ? "private_linkage " : "") << (GO->hasLocalLinkage () ? "local_linkage " : "") << (GO->hasInternalLinkage () ? "internal " : "") << (GO->hasExternalLinkage() ? "external " : "") << (GO->hasCommonLinkage() ? "common_linkage " : "") << (GO->hasCommonLinkage() ? "common " : "" ) << (Kind.isCommon() ? "kind_common " : "" ) << ( Kind.isBSS() ? "kind_bss " : "" ) << (Kind.isBSSLocal() ? "kind_bss_local " : "" ); } } while (false) | |||
171 | << (GO->hasInternalLinkage() ? "internal " : "")do { if (TraceGVPlacement) { errs() << (GO->hasPrivateLinkage () ? "private_linkage " : "") << (GO->hasLocalLinkage () ? "local_linkage " : "") << (GO->hasInternalLinkage () ? "internal " : "") << (GO->hasExternalLinkage() ? "external " : "") << (GO->hasCommonLinkage() ? "common_linkage " : "") << (GO->hasCommonLinkage() ? "common " : "" ) << (Kind.isCommon() ? "kind_common " : "" ) << ( Kind.isBSS() ? "kind_bss " : "" ) << (Kind.isBSSLocal() ? "kind_bss_local " : "" ); } } while (false) | |||
172 | << (GO->hasExternalLinkage() ? "external " : "")do { if (TraceGVPlacement) { errs() << (GO->hasPrivateLinkage () ? "private_linkage " : "") << (GO->hasLocalLinkage () ? "local_linkage " : "") << (GO->hasInternalLinkage () ? "internal " : "") << (GO->hasExternalLinkage() ? "external " : "") << (GO->hasCommonLinkage() ? "common_linkage " : "") << (GO->hasCommonLinkage() ? "common " : "" ) << (Kind.isCommon() ? "kind_common " : "" ) << ( Kind.isBSS() ? "kind_bss " : "" ) << (Kind.isBSSLocal() ? "kind_bss_local " : "" ); } } while (false) | |||
173 | << (GO->hasCommonLinkage() ? "common_linkage " : "")do { if (TraceGVPlacement) { errs() << (GO->hasPrivateLinkage () ? "private_linkage " : "") << (GO->hasLocalLinkage () ? "local_linkage " : "") << (GO->hasInternalLinkage () ? "internal " : "") << (GO->hasExternalLinkage() ? "external " : "") << (GO->hasCommonLinkage() ? "common_linkage " : "") << (GO->hasCommonLinkage() ? "common " : "" ) << (Kind.isCommon() ? "kind_common " : "" ) << ( Kind.isBSS() ? "kind_bss " : "" ) << (Kind.isBSSLocal() ? "kind_bss_local " : "" ); } } while (false) | |||
174 | << (GO->hasCommonLinkage() ? "common " : "" )do { if (TraceGVPlacement) { errs() << (GO->hasPrivateLinkage () ? "private_linkage " : "") << (GO->hasLocalLinkage () ? "local_linkage " : "") << (GO->hasInternalLinkage () ? "internal " : "") << (GO->hasExternalLinkage() ? "external " : "") << (GO->hasCommonLinkage() ? "common_linkage " : "") << (GO->hasCommonLinkage() ? "common " : "" ) << (Kind.isCommon() ? "kind_common " : "" ) << ( Kind.isBSS() ? "kind_bss " : "" ) << (Kind.isBSSLocal() ? "kind_bss_local " : "" ); } } while (false) | |||
175 | << (Kind.isCommon() ? "kind_common " : "" )do { if (TraceGVPlacement) { errs() << (GO->hasPrivateLinkage () ? "private_linkage " : "") << (GO->hasLocalLinkage () ? "local_linkage " : "") << (GO->hasInternalLinkage () ? "internal " : "") << (GO->hasExternalLinkage() ? "external " : "") << (GO->hasCommonLinkage() ? "common_linkage " : "") << (GO->hasCommonLinkage() ? "common " : "" ) << (Kind.isCommon() ? "kind_common " : "" ) << ( Kind.isBSS() ? "kind_bss " : "" ) << (Kind.isBSSLocal() ? "kind_bss_local " : "" ); } } while (false) | |||
176 | << (Kind.isBSS() ? "kind_bss " : "" )do { if (TraceGVPlacement) { errs() << (GO->hasPrivateLinkage () ? "private_linkage " : "") << (GO->hasLocalLinkage () ? "local_linkage " : "") << (GO->hasInternalLinkage () ? "internal " : "") << (GO->hasExternalLinkage() ? "external " : "") << (GO->hasCommonLinkage() ? "common_linkage " : "") << (GO->hasCommonLinkage() ? "common " : "" ) << (Kind.isCommon() ? "kind_common " : "" ) << ( Kind.isBSS() ? "kind_bss " : "" ) << (Kind.isBSSLocal() ? "kind_bss_local " : "" ); } } while (false) | |||
177 | << (Kind.isBSSLocal() ? "kind_bss_local " : "" ))do { if (TraceGVPlacement) { errs() << (GO->hasPrivateLinkage () ? "private_linkage " : "") << (GO->hasLocalLinkage () ? "local_linkage " : "") << (GO->hasInternalLinkage () ? "internal " : "") << (GO->hasExternalLinkage() ? "external " : "") << (GO->hasCommonLinkage() ? "common_linkage " : "") << (GO->hasCommonLinkage() ? "common " : "" ) << (Kind.isCommon() ? "kind_common " : "" ) << ( Kind.isBSS() ? "kind_bss " : "" ) << (Kind.isBSSLocal() ? "kind_bss_local " : "" ); } } while (false); | |||
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")do { if (TraceGVPlacement) { errs() << "default_ELF_section\n" ; } } while (false); | |||
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 "do { } while (false) | |||
204 | "may have explicit section assignments...\n")do { } while (false); | |||
205 | // Only global variables, not functions. | |||
206 | LLVM_DEBUG(dbgs() << "Checking if value is in small-data, -G"do { } while (false) | |||
207 | << SmallDataThreshold << ": \"" << GO->getName() << "\": ")do { } while (false); | |||
208 | const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GO); | |||
209 | if (!GVar) { | |||
210 | LLVM_DEBUG(dbgs() << "no, not a global variable\n")do { } while (false); | |||
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")do { } while (false) | |||
220 | << ", has section: " << GVar->getSection() << '\n')do { } while (false); | |||
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")do { } while (false); | |||
227 | return false; | |||
228 | } | |||
229 | ||||
230 | if (GVar->isConstant()) { | |||
231 | LLVM_DEBUG(dbgs() << "no, is a constant\n")do { } while (false); | |||
232 | return false; | |||
233 | } | |||
234 | ||||
235 | bool IsLocal = GVar->hasLocalLinkage(); | |||
236 | if (!StaticsInSData && IsLocal) { | |||
237 | LLVM_DEBUG(dbgs() << "no, is static\n")do { } while (false); | |||
238 | return false; | |||
239 | } | |||
240 | ||||
241 | Type *GType = GVar->getValueType(); | |||
242 | if (isa<ArrayType>(GType)) { | |||
243 | LLVM_DEBUG(dbgs() << "no, is an array\n")do { } while (false); | |||
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")do { } while (false); | |||
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")do { } while (false); | |||
261 | return false; | |||
262 | } | |||
263 | if (Size > SmallDataThreshold) { | |||
264 | LLVM_DEBUG(dbgs() << "no, size exceeds sdata threshold: " << Size << '\n')do { } while (false); | |||
265 | return false; | |||
266 | } | |||
267 | ||||
268 | LLVM_DEBUG(dbgs() << "yes\n")do { } while (false); | |||
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::FixedVectorTyID: | |||
312 | case Type::ScalableVectorTyID: { | |||
313 | const VectorType *PTy = cast<const VectorType>(Ty); | |||
314 | return getSmallestAddressableSize(PTy->getElementType(), GV, TM); | |||
315 | } | |||
316 | case Type::PointerTyID: | |||
317 | case Type::HalfTyID: | |||
318 | case Type::FloatTyID: | |||
319 | case Type::DoubleTyID: | |||
320 | case Type::IntegerTyID: { | |||
321 | const DataLayout &DL = GV->getParent()->getDataLayout(); | |||
322 | // It is unfortunate that DL's function take non-const Type*. | |||
323 | return DL.getTypeAllocSize(const_cast<Type*>(Ty)); | |||
324 | } | |||
325 | case Type::FunctionTyID: | |||
326 | case Type::VoidTyID: | |||
327 | case Type::BFloatTyID: | |||
328 | case Type::X86_FP80TyID: | |||
329 | case Type::FP128TyID: | |||
330 | case Type::PPC_FP128TyID: | |||
331 | case Type::LabelTyID: | |||
332 | case Type::MetadataTyID: | |||
333 | case Type::X86_MMXTyID: | |||
334 | case Type::X86_AMXTyID: | |||
335 | case Type::TokenTyID: | |||
336 | return 0; | |||
337 | } | |||
338 | ||||
339 | return 0; | |||
340 | } | |||
341 | ||||
342 | MCSection *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 << ")")do { if (TraceGVPlacement) { errs() << "Small data. Size(" << Size << ")"; } } while (false); | |||
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")do { if (TraceGVPlacement) { errs() << " default sbss\n" ; } } while (false); | |||
362 | return SmallBSSSection; | |||
363 | } | |||
364 | ||||
365 | StringRef Prefix(".sbss"); | |||
366 | SmallString<128> Name(Prefix); | |||
367 | Name.append(getSectionSuffixForSize(Size)); | |||
368 | ||||
369 | if (EmitUniquedSection) { | |||
370 | Name.append("."); | |||
371 | Name.append(GO->getName()); | |||
372 | } | |||
373 | TRACE(" unique sbss(" << Name << ")\n")do { if (TraceGVPlacement) { errs() << " unique sbss(" << Name << ")\n"; } } while (false); | |||
374 | return getContext().getELFSection(Name.str(), ELF::SHT_NOBITS, | |||
375 | ELF::SHF_WRITE | ELF::SHF_ALLOC | ELF::SHF_HEX_GPREL); | |||
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. | |||
383 | if (NoSmallDataSorting) | |||
384 | return BSSSection; | |||
385 | ||||
386 | Twine Name = Twine(".scommon") + getSectionSuffixForSize(Size); | |||
387 | TRACE(" small COMMON (" << Name << ")\n")do { if (TraceGVPlacement) { errs() << " small COMMON (" << Name << ")\n"; } } while (false); | |||
388 | ||||
389 | return getContext().getELFSection(Name.str(), ELF::SHT_NOBITS, | |||
390 | ELF::SHF_WRITE | ELF::SHF_ALLOC | | |||
391 | ELF::SHF_HEX_GPREL); | |||
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 ")do { if (TraceGVPlacement) { errs() << " const_object_as_data " ; } } while (false); | |||
398 | const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GO); | |||
399 | if (GVar->hasSection() && isSmallDataSection(GVar->getSection())) | |||
400 | Kind = SectionKind::getData(); | |||
401 | } | |||
402 | ||||
403 | if (Kind.isData()) { | |||
404 | if (NoSmallDataSorting) { | |||
405 | TRACE(" default sdata\n")do { if (TraceGVPlacement) { errs() << " default sdata\n" ; } } while (false); | |||
406 | return SmallDataSection; | |||
407 | } | |||
408 | ||||
409 | StringRef Prefix(".sdata"); | |||
410 | SmallString<128> Name(Prefix); | |||
411 | Name.append(getSectionSuffixForSize(Size)); | |||
412 | ||||
413 | if (EmitUniquedSection) { | |||
414 | Name.append("."); | |||
415 | Name.append(GO->getName()); | |||
416 | } | |||
417 | TRACE(" unique sdata(" << Name << ")\n")do { if (TraceGVPlacement) { errs() << " unique sdata(" << Name << ")\n"; } } while (false); | |||
418 | return getContext().getELFSection(Name.str(), ELF::SHT_PROGBITS, | |||
419 | ELF::SHF_WRITE | ELF::SHF_ALLOC | ELF::SHF_HEX_GPREL); | |||
420 | } | |||
421 | ||||
422 | TRACE("default ELF section\n")do { if (TraceGVPlacement) { errs() << "default ELF section\n" ; } } while (false); | |||
423 | // Otherwise, we work the same as ELF. | |||
424 | return TargetLoweringObjectFileELF::SelectSectionForGlobal(GO, Kind, TM); | |||
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. | |||
430 | const Function * | |||
431 | HexagonTargetObjectFile::getLutUsedFunction(const GlobalObject *GO) const { | |||
432 | const Function *ReturnFn = nullptr; | |||
433 | for (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 | ||||
450 | MCSection *HexagonTargetObjectFile::selectSectionForLookupTable( | |||
451 | const GlobalObject *GO, const TargetMachine &TM, const Function *Fn) const { | |||
452 | ||||
453 | SectionKind Kind = SectionKind::getText(); | |||
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 | } |