/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/llvm/lib/LTO/LTOModule.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===-- LTOModule.cpp - LLVM Link Time Optimizer --------------------------===// |
2 | | // |
3 | | // The LLVM Compiler Infrastructure |
4 | | // |
5 | | // This file is distributed under the University of Illinois Open Source |
6 | | // License. See LICENSE.TXT for details. |
7 | | // |
8 | | //===----------------------------------------------------------------------===// |
9 | | // |
10 | | // This file implements the Link Time Optimization library. This library is |
11 | | // intended to be used by linker to optimize code at link time. |
12 | | // |
13 | | //===----------------------------------------------------------------------===// |
14 | | |
15 | | #include "llvm/LTO/legacy/LTOModule.h" |
16 | | #include "llvm/ADT/Triple.h" |
17 | | #include "llvm/Bitcode/BitcodeReader.h" |
18 | | #include "llvm/CodeGen/Analysis.h" |
19 | | #include "llvm/IR/Constants.h" |
20 | | #include "llvm/IR/DiagnosticPrinter.h" |
21 | | #include "llvm/IR/LLVMContext.h" |
22 | | #include "llvm/IR/Metadata.h" |
23 | | #include "llvm/IR/Module.h" |
24 | | #include "llvm/MC/MCExpr.h" |
25 | | #include "llvm/MC/MCInst.h" |
26 | | #include "llvm/MC/MCInstrInfo.h" |
27 | | #include "llvm/MC/MCParser/MCAsmParser.h" |
28 | | #include "llvm/MC/MCParser/MCTargetAsmParser.h" |
29 | | #include "llvm/MC/MCSection.h" |
30 | | #include "llvm/MC/MCSubtargetInfo.h" |
31 | | #include "llvm/MC/MCSymbol.h" |
32 | | #include "llvm/MC/SubtargetFeature.h" |
33 | | #include "llvm/Object/IRObjectFile.h" |
34 | | #include "llvm/Object/ObjectFile.h" |
35 | | #include "llvm/Support/FileSystem.h" |
36 | | #include "llvm/Support/Host.h" |
37 | | #include "llvm/Support/MemoryBuffer.h" |
38 | | #include "llvm/Support/Path.h" |
39 | | #include "llvm/Support/SourceMgr.h" |
40 | | #include "llvm/Support/TargetRegistry.h" |
41 | | #include "llvm/Support/TargetSelect.h" |
42 | | #include "llvm/Target/TargetLowering.h" |
43 | | #include "llvm/Target/TargetLoweringObjectFile.h" |
44 | | #include "llvm/Target/TargetRegisterInfo.h" |
45 | | #include "llvm/Target/TargetSubtargetInfo.h" |
46 | | #include "llvm/Transforms/Utils/GlobalStatus.h" |
47 | | #include <system_error> |
48 | | using namespace llvm; |
49 | | using namespace llvm::object; |
50 | | |
51 | | LTOModule::LTOModule(std::unique_ptr<Module> M, MemoryBufferRef MBRef, |
52 | | llvm::TargetMachine *TM) |
53 | 85 | : Mod(std::move(M)), MBRef(MBRef), _target(TM) { |
54 | 85 | SymTab.addModule(Mod.get()); |
55 | 85 | } |
56 | | |
57 | 84 | LTOModule::~LTOModule() {} |
58 | | |
59 | | /// isBitcodeFile - Returns 'true' if the file (or memory contents) is LLVM |
60 | | /// bitcode. |
61 | 0 | bool LTOModule::isBitcodeFile(const void *Mem, size_t Length) { |
62 | 0 | ErrorOr<MemoryBufferRef> BCData = IRObjectFile::findBitcodeInMemBuffer( |
63 | 0 | MemoryBufferRef(StringRef((const char *)Mem, Length), "<mem>")); |
64 | 0 | return bool(BCData); |
65 | 0 | } |
66 | | |
67 | 0 | bool LTOModule::isBitcodeFile(StringRef Path) { |
68 | 0 | ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr = |
69 | 0 | MemoryBuffer::getFile(Path); |
70 | 0 | if (!BufferOrErr) |
71 | 0 | return false; |
72 | 0 |
|
73 | 0 | ErrorOr<MemoryBufferRef> BCData = IRObjectFile::findBitcodeInMemBuffer( |
74 | 0 | BufferOrErr.get()->getMemBufferRef()); |
75 | 0 | return bool(BCData); |
76 | 0 | } |
77 | | |
78 | 0 | bool LTOModule::isThinLTO() { |
79 | 0 | // Right now the detection is only based on the summary presence. We may want |
80 | 0 | // to add a dedicated flag at some point. |
81 | 0 | Expected<bool> Result = hasGlobalValueSummary(MBRef); |
82 | 0 | if (!Result0 ) {0 |
83 | 0 | logAllUnhandledErrors(Result.takeError(), errs(), ""); |
84 | 0 | return false; |
85 | 0 | } |
86 | 0 | return *Result; |
87 | 0 | } |
88 | | |
89 | | bool LTOModule::isBitcodeForTarget(MemoryBuffer *Buffer, |
90 | 3 | StringRef TriplePrefix) { |
91 | 3 | ErrorOr<MemoryBufferRef> BCOrErr = |
92 | 3 | IRObjectFile::findBitcodeInMemBuffer(Buffer->getMemBufferRef()); |
93 | 3 | if (!BCOrErr) |
94 | 0 | return false; |
95 | 3 | LLVMContext Context; |
96 | 3 | ErrorOr<std::string> TripleOrErr = |
97 | 3 | expectedToErrorOrAndEmitErrors(Context, getBitcodeTargetTriple(*BCOrErr)); |
98 | 3 | if (!TripleOrErr) |
99 | 0 | return false; |
100 | 3 | return StringRef(*TripleOrErr).startswith(TriplePrefix); |
101 | 3 | } |
102 | | |
103 | 0 | std::string LTOModule::getProducerString(MemoryBuffer *Buffer) { |
104 | 0 | ErrorOr<MemoryBufferRef> BCOrErr = |
105 | 0 | IRObjectFile::findBitcodeInMemBuffer(Buffer->getMemBufferRef()); |
106 | 0 | if (!BCOrErr) |
107 | 0 | return ""; |
108 | 0 | LLVMContext Context; |
109 | 0 | ErrorOr<std::string> ProducerOrErr = expectedToErrorOrAndEmitErrors( |
110 | 0 | Context, getBitcodeProducerString(*BCOrErr)); |
111 | 0 | if (!ProducerOrErr) |
112 | 0 | return ""; |
113 | 0 | return *ProducerOrErr; |
114 | 0 | } |
115 | | |
116 | | ErrorOr<std::unique_ptr<LTOModule>> |
117 | | LTOModule::createFromFile(LLVMContext &Context, StringRef path, |
118 | 42 | const TargetOptions &options) { |
119 | 42 | ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr = |
120 | 42 | MemoryBuffer::getFile(path); |
121 | 42 | if (std::error_code EC42 = BufferOrErr.getError()) {1 |
122 | 1 | Context.emitError(EC.message()); |
123 | 1 | return EC; |
124 | 1 | } |
125 | 41 | std::unique_ptr<MemoryBuffer> Buffer = std::move(BufferOrErr.get()); |
126 | 41 | return makeLTOModule(Buffer->getMemBufferRef(), options, Context, |
127 | 41 | /* ShouldBeLazy*/ false); |
128 | 42 | } |
129 | | |
130 | | ErrorOr<std::unique_ptr<LTOModule>> |
131 | | LTOModule::createFromOpenFile(LLVMContext &Context, int fd, StringRef path, |
132 | 0 | size_t size, const TargetOptions &options) { |
133 | 0 | return createFromOpenFileSlice(Context, fd, path, size, 0, options); |
134 | 0 | } |
135 | | |
136 | | ErrorOr<std::unique_ptr<LTOModule>> |
137 | | LTOModule::createFromOpenFileSlice(LLVMContext &Context, int fd, StringRef path, |
138 | | size_t map_size, off_t offset, |
139 | 0 | const TargetOptions &options) { |
140 | 0 | ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr = |
141 | 0 | MemoryBuffer::getOpenFileSlice(fd, path, map_size, offset); |
142 | 0 | if (std::error_code EC0 = BufferOrErr.getError()) {0 |
143 | 0 | Context.emitError(EC.message()); |
144 | 0 | return EC; |
145 | 0 | } |
146 | 0 | std::unique_ptr<MemoryBuffer> Buffer = std::move(BufferOrErr.get()); |
147 | 0 | return makeLTOModule(Buffer->getMemBufferRef(), options, Context, |
148 | 0 | /* ShouldBeLazy */ false); |
149 | 0 | } |
150 | | |
151 | | ErrorOr<std::unique_ptr<LTOModule>> |
152 | | LTOModule::createFromBuffer(LLVMContext &Context, const void *mem, |
153 | | size_t length, const TargetOptions &options, |
154 | 39 | StringRef path) { |
155 | 39 | StringRef Data((const char *)mem, length); |
156 | 39 | MemoryBufferRef Buffer(Data, path); |
157 | 39 | return makeLTOModule(Buffer, options, Context, /* ShouldBeLazy */ false); |
158 | 39 | } |
159 | | |
160 | | ErrorOr<std::unique_ptr<LTOModule>> |
161 | | LTOModule::createInLocalContext(std::unique_ptr<LLVMContext> Context, |
162 | | const void *mem, size_t length, |
163 | 7 | const TargetOptions &options, StringRef path) { |
164 | 7 | StringRef Data((const char *)mem, length); |
165 | 7 | MemoryBufferRef Buffer(Data, path); |
166 | 7 | // If we own a context, we know this is being used only for symbol extraction, |
167 | 7 | // not linking. Be lazy in that case. |
168 | 7 | ErrorOr<std::unique_ptr<LTOModule>> Ret = |
169 | 7 | makeLTOModule(Buffer, options, *Context, /* ShouldBeLazy */ true); |
170 | 7 | if (Ret) |
171 | 6 | (*Ret)->OwnedContext = std::move(Context); |
172 | 7 | return Ret; |
173 | 7 | } |
174 | | |
175 | | static ErrorOr<std::unique_ptr<Module>> |
176 | | parseBitcodeFileImpl(MemoryBufferRef Buffer, LLVMContext &Context, |
177 | 87 | bool ShouldBeLazy) { |
178 | 87 | |
179 | 87 | // Find the buffer. |
180 | 87 | ErrorOr<MemoryBufferRef> MBOrErr = |
181 | 87 | IRObjectFile::findBitcodeInMemBuffer(Buffer); |
182 | 87 | if (std::error_code EC87 = MBOrErr.getError()) {1 |
183 | 1 | Context.emitError(EC.message()); |
184 | 1 | return EC; |
185 | 1 | } |
186 | 87 | |
187 | 86 | if (86 !ShouldBeLazy86 ) {80 |
188 | 80 | // Parse the full file. |
189 | 80 | return expectedToErrorOrAndEmitErrors(Context, |
190 | 80 | parseBitcodeFile(*MBOrErr, Context)); |
191 | 80 | } |
192 | 86 | |
193 | 86 | // Parse lazily. |
194 | 6 | return expectedToErrorOrAndEmitErrors( |
195 | 6 | Context, |
196 | 6 | getLazyBitcodeModule(*MBOrErr, Context, true /*ShouldLazyLoadMetadata*/)); |
197 | 86 | } |
198 | | |
199 | | ErrorOr<std::unique_ptr<LTOModule>> |
200 | | LTOModule::makeLTOModule(MemoryBufferRef Buffer, const TargetOptions &options, |
201 | 87 | LLVMContext &Context, bool ShouldBeLazy) { |
202 | 87 | ErrorOr<std::unique_ptr<Module>> MOrErr = |
203 | 87 | parseBitcodeFileImpl(Buffer, Context, ShouldBeLazy); |
204 | 87 | if (std::error_code EC = MOrErr.getError()) |
205 | 0 | return EC; |
206 | 87 | std::unique_ptr<Module> &M = *MOrErr; |
207 | 87 | |
208 | 87 | std::string TripleStr = M->getTargetTriple(); |
209 | 87 | if (TripleStr.empty()) |
210 | 9 | TripleStr = sys::getDefaultTargetTriple(); |
211 | 87 | llvm::Triple Triple(TripleStr); |
212 | 87 | |
213 | 87 | // find machine architecture for this module |
214 | 87 | std::string errMsg; |
215 | 87 | const Target *march = TargetRegistry::lookupTarget(TripleStr, errMsg); |
216 | 87 | if (!march) |
217 | 0 | return std::unique_ptr<LTOModule>(nullptr); |
218 | 87 | |
219 | 87 | // construct LTOModule, hand over ownership of module and target |
220 | 87 | SubtargetFeatures Features; |
221 | 87 | Features.getDefaultSubtargetFeatures(Triple); |
222 | 87 | std::string FeatureStr = Features.getString(); |
223 | 87 | // Set a default CPU for Darwin triples. |
224 | 87 | std::string CPU; |
225 | 87 | if (Triple.isOSDarwin()87 ) {28 |
226 | 28 | if (Triple.getArch() == llvm::Triple::x86_64) |
227 | 27 | CPU = "core2"; |
228 | 1 | else if (1 Triple.getArch() == llvm::Triple::x861 ) |
229 | 0 | CPU = "yonah"; |
230 | 1 | else if (1 Triple.getArch() == llvm::Triple::aarch641 ) |
231 | 0 | CPU = "cyclone"; |
232 | 28 | } |
233 | 87 | |
234 | 87 | TargetMachine *target = |
235 | 87 | march->createTargetMachine(TripleStr, CPU, FeatureStr, options, None); |
236 | 87 | |
237 | 87 | std::unique_ptr<LTOModule> Ret(new LTOModule(std::move(M), Buffer, target)); |
238 | 87 | Ret->parseSymbols(); |
239 | 87 | Ret->parseMetadata(); |
240 | 87 | |
241 | 87 | return std::move(Ret); |
242 | 87 | } |
243 | | |
244 | | /// Create a MemoryBuffer from a memory range with an optional name. |
245 | | std::unique_ptr<MemoryBuffer> |
246 | 3 | LTOModule::makeBuffer(const void *mem, size_t length, StringRef name) { |
247 | 3 | const char *startPtr = (const char*)mem; |
248 | 3 | return MemoryBuffer::getMemBuffer(StringRef(startPtr, length), name, false); |
249 | 3 | } |
250 | | |
251 | | /// objcClassNameFromExpression - Get string that the data pointer points to. |
252 | | bool |
253 | 0 | LTOModule::objcClassNameFromExpression(const Constant *c, std::string &name) { |
254 | 0 | if (const ConstantExpr *ce0 = dyn_cast<ConstantExpr>(c)) {0 |
255 | 0 | Constant *op = ce->getOperand(0); |
256 | 0 | if (GlobalVariable *gvn0 = dyn_cast<GlobalVariable>(op)) {0 |
257 | 0 | Constant *cn = gvn->getInitializer(); |
258 | 0 | if (ConstantDataArray *ca0 = dyn_cast<ConstantDataArray>(cn)) {0 |
259 | 0 | if (ca->isCString()0 ) {0 |
260 | 0 | name = (".objc_class_name_" + ca->getAsCString()).str(); |
261 | 0 | return true; |
262 | 0 | } |
263 | 0 | } |
264 | 0 | } |
265 | 0 | } |
266 | 0 | return false; |
267 | 0 | } |
268 | | |
269 | | /// addObjCClass - Parse i386/ppc ObjC class data structure. |
270 | 0 | void LTOModule::addObjCClass(const GlobalVariable *clgv) { |
271 | 0 | const ConstantStruct *c = dyn_cast<ConstantStruct>(clgv->getInitializer()); |
272 | 0 | if (!c0 ) return0 ; |
273 | 0 |
|
274 | 0 | // second slot in __OBJC,__class is pointer to superclass name |
275 | 0 | std::string superclassName; |
276 | 0 | if (objcClassNameFromExpression(c->getOperand(1), superclassName)0 ) {0 |
277 | 0 | auto IterBool = |
278 | 0 | _undefines.insert(std::make_pair(superclassName, NameAndAttributes())); |
279 | 0 | if (IterBool.second0 ) {0 |
280 | 0 | NameAndAttributes &info = IterBool.first->second; |
281 | 0 | info.name = IterBool.first->first(); |
282 | 0 | info.attributes = LTO_SYMBOL_DEFINITION_UNDEFINED; |
283 | 0 | info.isFunction = false; |
284 | 0 | info.symbol = clgv; |
285 | 0 | } |
286 | 0 | } |
287 | 0 |
|
288 | 0 | // third slot in __OBJC,__class is pointer to class name |
289 | 0 | std::string className; |
290 | 0 | if (objcClassNameFromExpression(c->getOperand(2), className)0 ) {0 |
291 | 0 | auto Iter = _defines.insert(className).first; |
292 | 0 |
|
293 | 0 | NameAndAttributes info; |
294 | 0 | info.name = Iter->first(); |
295 | 0 | info.attributes = LTO_SYMBOL_PERMISSIONS_DATA | |
296 | 0 | LTO_SYMBOL_DEFINITION_REGULAR | LTO_SYMBOL_SCOPE_DEFAULT; |
297 | 0 | info.isFunction = false; |
298 | 0 | info.symbol = clgv; |
299 | 0 | _symbols.push_back(info); |
300 | 0 | } |
301 | 0 | } |
302 | | |
303 | | /// addObjCCategory - Parse i386/ppc ObjC category data structure. |
304 | 0 | void LTOModule::addObjCCategory(const GlobalVariable *clgv) { |
305 | 0 | const ConstantStruct *c = dyn_cast<ConstantStruct>(clgv->getInitializer()); |
306 | 0 | if (!c0 ) return0 ; |
307 | 0 |
|
308 | 0 | // second slot in __OBJC,__category is pointer to target class name |
309 | 0 | std::string targetclassName; |
310 | 0 | if (!objcClassNameFromExpression(c->getOperand(1), targetclassName)) |
311 | 0 | return; |
312 | 0 |
|
313 | 0 | auto IterBool = |
314 | 0 | _undefines.insert(std::make_pair(targetclassName, NameAndAttributes())); |
315 | 0 |
|
316 | 0 | if (!IterBool.second) |
317 | 0 | return; |
318 | 0 |
|
319 | 0 | NameAndAttributes &info = IterBool.first->second; |
320 | 0 | info.name = IterBool.first->first(); |
321 | 0 | info.attributes = LTO_SYMBOL_DEFINITION_UNDEFINED; |
322 | 0 | info.isFunction = false; |
323 | 0 | info.symbol = clgv; |
324 | 0 | } |
325 | | |
326 | | /// addObjCClassRef - Parse i386/ppc ObjC class list data structure. |
327 | 0 | void LTOModule::addObjCClassRef(const GlobalVariable *clgv) { |
328 | 0 | std::string targetclassName; |
329 | 0 | if (!objcClassNameFromExpression(clgv->getInitializer(), targetclassName)) |
330 | 0 | return; |
331 | 0 |
|
332 | 0 | auto IterBool = |
333 | 0 | _undefines.insert(std::make_pair(targetclassName, NameAndAttributes())); |
334 | 0 |
|
335 | 0 | if (!IterBool.second) |
336 | 0 | return; |
337 | 0 |
|
338 | 0 | NameAndAttributes &info = IterBool.first->second; |
339 | 0 | info.name = IterBool.first->first(); |
340 | 0 | info.attributes = LTO_SYMBOL_DEFINITION_UNDEFINED; |
341 | 0 | info.isFunction = false; |
342 | 0 | info.symbol = clgv; |
343 | 0 | } |
344 | | |
345 | 27 | void LTOModule::addDefinedDataSymbol(ModuleSymbolTable::Symbol Sym) { |
346 | 27 | SmallString<64> Buffer; |
347 | 27 | { |
348 | 27 | raw_svector_ostream OS(Buffer); |
349 | 27 | SymTab.printSymbolName(OS, Sym); |
350 | 27 | Buffer.c_str(); |
351 | 27 | } |
352 | 27 | |
353 | 27 | const GlobalValue *V = Sym.get<GlobalValue *>(); |
354 | 27 | addDefinedDataSymbol(Buffer, V); |
355 | 27 | } |
356 | | |
357 | 27 | void LTOModule::addDefinedDataSymbol(StringRef Name, const GlobalValue *v) { |
358 | 27 | // Add to list of defined symbols. |
359 | 27 | addDefinedSymbol(Name, v, false); |
360 | 27 | |
361 | 27 | if (!v->hasSection() /* || !isTargetDarwin */) |
362 | 27 | return; |
363 | 27 | |
364 | 27 | // Special case i386/ppc ObjC data structures in magic sections: |
365 | 27 | // The issue is that the old ObjC object format did some strange |
366 | 27 | // contortions to avoid real linker symbols. For instance, the |
367 | 27 | // ObjC class data structure is allocated statically in the executable |
368 | 27 | // that defines that class. That data structures contains a pointer to |
369 | 27 | // its superclass. But instead of just initializing that part of the |
370 | 27 | // struct to the address of its superclass, and letting the static and |
371 | 27 | // dynamic linkers do the rest, the runtime works by having that field |
372 | 27 | // instead point to a C-string that is the name of the superclass. |
373 | 27 | // At runtime the objc initialization updates that pointer and sets |
374 | 27 | // it to point to the actual super class. As far as the linker |
375 | 27 | // knows it is just a pointer to a string. But then someone wanted the |
376 | 27 | // linker to issue errors at build time if the superclass was not found. |
377 | 27 | // So they figured out a way in mach-o object format to use an absolute |
378 | 27 | // symbols (.objc_class_name_Foo = 0) and a floating reference |
379 | 27 | // (.reference .objc_class_name_Bar) to cause the linker into erroring when |
380 | 27 | // a class was missing. |
381 | 27 | // The following synthesizes the implicit .objc_* symbols for the linker |
382 | 27 | // from the ObjC data structures generated by the front end. |
383 | 27 | |
384 | 27 | // special case if this data blob is an ObjC class definition |
385 | 0 | std::string Section = v->getSection(); |
386 | 0 | if (Section.compare(0, 15, "__OBJC,__class,") == 00 ) {0 |
387 | 0 | if (const GlobalVariable *gv0 = dyn_cast<GlobalVariable>(v)) {0 |
388 | 0 | addObjCClass(gv); |
389 | 0 | } |
390 | 0 | } |
391 | 0 |
|
392 | 0 | // special case if this data blob is an ObjC category definition |
393 | 0 | else if (0 Section.compare(0, 18, "__OBJC,__category,") == 00 ) {0 |
394 | 0 | if (const GlobalVariable *gv0 = dyn_cast<GlobalVariable>(v)) {0 |
395 | 0 | addObjCCategory(gv); |
396 | 0 | } |
397 | 0 | } |
398 | 0 |
|
399 | 0 | // special case if this data blob is the list of referenced classes |
400 | 0 | else if (0 Section.compare(0, 18, "__OBJC,__cls_refs,") == 00 ) {0 |
401 | 0 | if (const GlobalVariable *gv0 = dyn_cast<GlobalVariable>(v)) {0 |
402 | 0 | addObjCClassRef(gv); |
403 | 0 | } |
404 | 0 | } |
405 | 0 | } |
406 | | |
407 | 148 | void LTOModule::addDefinedFunctionSymbol(ModuleSymbolTable::Symbol Sym) { |
408 | 148 | SmallString<64> Buffer; |
409 | 148 | { |
410 | 148 | raw_svector_ostream OS(Buffer); |
411 | 148 | SymTab.printSymbolName(OS, Sym); |
412 | 148 | Buffer.c_str(); |
413 | 148 | } |
414 | 148 | |
415 | 148 | const Function *F = cast<Function>(Sym.get<GlobalValue *>()); |
416 | 148 | addDefinedFunctionSymbol(Buffer, F); |
417 | 148 | } |
418 | | |
419 | 151 | void LTOModule::addDefinedFunctionSymbol(StringRef Name, const Function *F) { |
420 | 151 | // add to list of defined symbols |
421 | 151 | addDefinedSymbol(Name, F, true); |
422 | 151 | } |
423 | | |
424 | | void LTOModule::addDefinedSymbol(StringRef Name, const GlobalValue *def, |
425 | 178 | bool isFunction) { |
426 | 178 | // set alignment part log2() can have rounding errors |
427 | 178 | uint32_t align = def->getAlignment(); |
428 | 174 | uint32_t attr = align ? countTrailingZeros(align)4 : 0174 ; |
429 | 178 | |
430 | 178 | // set permissions part |
431 | 178 | if (isFunction178 ) {151 |
432 | 151 | attr |= LTO_SYMBOL_PERMISSIONS_CODE; |
433 | 27 | } else { |
434 | 27 | const GlobalVariable *gv = dyn_cast<GlobalVariable>(def); |
435 | 27 | if (gv && 27 gv->isConstant()25 ) |
436 | 10 | attr |= LTO_SYMBOL_PERMISSIONS_RODATA; |
437 | 27 | else |
438 | 17 | attr |= LTO_SYMBOL_PERMISSIONS_DATA; |
439 | 27 | } |
440 | 178 | |
441 | 178 | // set definition part |
442 | 178 | if (def->hasWeakLinkage() || 178 def->hasLinkOnceLinkage()176 ) |
443 | 36 | attr |= LTO_SYMBOL_DEFINITION_WEAK; |
444 | 142 | else if (142 def->hasCommonLinkage()142 ) |
445 | 0 | attr |= LTO_SYMBOL_DEFINITION_TENTATIVE; |
446 | 142 | else |
447 | 142 | attr |= LTO_SYMBOL_DEFINITION_REGULAR; |
448 | 178 | |
449 | 178 | // set scope part |
450 | 178 | if (def->hasLocalLinkage()) |
451 | 178 | // Ignore visibility if linkage is local. |
452 | 17 | attr |= LTO_SYMBOL_SCOPE_INTERNAL; |
453 | 161 | else if (161 def->hasHiddenVisibility()161 ) |
454 | 2 | attr |= LTO_SYMBOL_SCOPE_HIDDEN; |
455 | 159 | else if (159 def->hasProtectedVisibility()159 ) |
456 | 0 | attr |= LTO_SYMBOL_SCOPE_PROTECTED; |
457 | 159 | else if (159 canBeOmittedFromSymbolTable(def)159 ) |
458 | 10 | attr |= LTO_SYMBOL_SCOPE_DEFAULT_CAN_BE_HIDDEN; |
459 | 159 | else |
460 | 149 | attr |= LTO_SYMBOL_SCOPE_DEFAULT; |
461 | 178 | |
462 | 178 | if (def->hasComdat()) |
463 | 20 | attr |= LTO_SYMBOL_COMDAT; |
464 | 178 | |
465 | 178 | if (isa<GlobalAlias>(def)) |
466 | 2 | attr |= LTO_SYMBOL_ALIAS; |
467 | 178 | |
468 | 178 | auto Iter = _defines.insert(Name).first; |
469 | 178 | |
470 | 178 | // fill information structure |
471 | 178 | NameAndAttributes info; |
472 | 178 | StringRef NameRef = Iter->first(); |
473 | 178 | info.name = NameRef; |
474 | 178 | assert(NameRef.data()[NameRef.size()] == '\0'); |
475 | 178 | info.attributes = attr; |
476 | 178 | info.isFunction = isFunction; |
477 | 178 | info.symbol = def; |
478 | 178 | |
479 | 178 | // add to table of symbols |
480 | 178 | _symbols.push_back(info); |
481 | 178 | } |
482 | | |
483 | | /// addAsmGlobalSymbol - Add a global symbol from module-level ASM to the |
484 | | /// defined list. |
485 | | void LTOModule::addAsmGlobalSymbol(StringRef name, |
486 | 4 | lto_symbol_attributes scope) { |
487 | 4 | auto IterBool = _defines.insert(name); |
488 | 4 | |
489 | 4 | // only add new define if not already defined |
490 | 4 | if (!IterBool.second) |
491 | 0 | return; |
492 | 4 | |
493 | 4 | NameAndAttributes &info = _undefines[IterBool.first->first()]; |
494 | 4 | |
495 | 4 | if (info.symbol == nullptr4 ) {1 |
496 | 1 | // FIXME: This is trying to take care of module ASM like this: |
497 | 1 | // |
498 | 1 | // module asm ".zerofill __FOO, __foo, _bar_baz_qux, 0" |
499 | 1 | // |
500 | 1 | // but is gross and its mother dresses it funny. Have the ASM parser give us |
501 | 1 | // more details for this type of situation so that we're not guessing so |
502 | 1 | // much. |
503 | 1 | |
504 | 1 | // fill information structure |
505 | 1 | info.name = IterBool.first->first(); |
506 | 1 | info.attributes = |
507 | 1 | LTO_SYMBOL_PERMISSIONS_DATA | LTO_SYMBOL_DEFINITION_REGULAR | scope; |
508 | 1 | info.isFunction = false; |
509 | 1 | info.symbol = nullptr; |
510 | 1 | |
511 | 1 | // add to table of symbols |
512 | 1 | _symbols.push_back(info); |
513 | 1 | return; |
514 | 1 | } |
515 | 4 | |
516 | 3 | if (3 info.isFunction3 ) |
517 | 3 | addDefinedFunctionSymbol(info.name, cast<Function>(info.symbol)); |
518 | 3 | else |
519 | 0 | addDefinedDataSymbol(info.name, info.symbol); |
520 | 3 | |
521 | 3 | _symbols.back().attributes &= ~LTO_SYMBOL_SCOPE_MASK; |
522 | 3 | _symbols.back().attributes |= scope; |
523 | 3 | } |
524 | | |
525 | | /// addAsmGlobalSymbolUndef - Add a global symbol from module-level ASM to the |
526 | | /// undefined list. |
527 | 1 | void LTOModule::addAsmGlobalSymbolUndef(StringRef name) { |
528 | 1 | auto IterBool = _undefines.insert(std::make_pair(name, NameAndAttributes())); |
529 | 1 | |
530 | 1 | _asm_undefines.push_back(IterBool.first->first()); |
531 | 1 | |
532 | 1 | // we already have the symbol |
533 | 1 | if (!IterBool.second) |
534 | 0 | return; |
535 | 1 | |
536 | 1 | uint32_t attr = LTO_SYMBOL_DEFINITION_UNDEFINED; |
537 | 1 | attr |= LTO_SYMBOL_SCOPE_DEFAULT; |
538 | 1 | NameAndAttributes &info = IterBool.first->second; |
539 | 1 | info.name = IterBool.first->first(); |
540 | 1 | info.attributes = attr; |
541 | 1 | info.isFunction = false; |
542 | 1 | info.symbol = nullptr; |
543 | 1 | } |
544 | | |
545 | | /// Add a symbol which isn't defined just yet to a list to be resolved later. |
546 | | void LTOModule::addPotentialUndefinedSymbol(ModuleSymbolTable::Symbol Sym, |
547 | 29 | bool isFunc) { |
548 | 29 | SmallString<64> name; |
549 | 29 | { |
550 | 29 | raw_svector_ostream OS(name); |
551 | 29 | SymTab.printSymbolName(OS, Sym); |
552 | 29 | name.c_str(); |
553 | 29 | } |
554 | 29 | |
555 | 29 | auto IterBool = _undefines.insert(std::make_pair(name, NameAndAttributes())); |
556 | 29 | |
557 | 29 | // we already have the symbol |
558 | 29 | if (!IterBool.second) |
559 | 0 | return; |
560 | 29 | |
561 | 29 | NameAndAttributes &info = IterBool.first->second; |
562 | 29 | |
563 | 29 | info.name = IterBool.first->first(); |
564 | 29 | |
565 | 29 | const GlobalValue *decl = Sym.dyn_cast<GlobalValue *>(); |
566 | 29 | |
567 | 29 | if (decl->hasExternalWeakLinkage()) |
568 | 0 | info.attributes = LTO_SYMBOL_DEFINITION_WEAKUNDEF; |
569 | 29 | else |
570 | 29 | info.attributes = LTO_SYMBOL_DEFINITION_UNDEFINED; |
571 | 29 | |
572 | 29 | info.isFunction = isFunc; |
573 | 29 | info.symbol = decl; |
574 | 29 | } |
575 | | |
576 | 85 | void LTOModule::parseSymbols() { |
577 | 217 | for (auto Sym : SymTab.symbols()) { |
578 | 217 | auto *GV = Sym.dyn_cast<GlobalValue *>(); |
579 | 217 | uint32_t Flags = SymTab.getSymbolFlags(Sym); |
580 | 217 | if (Flags & object::BasicSymbolRef::SF_FormatSpecific) |
581 | 8 | continue; |
582 | 217 | |
583 | 209 | bool IsUndefined = Flags & object::BasicSymbolRef::SF_Undefined; |
584 | 209 | |
585 | 209 | if (!GV209 ) {5 |
586 | 5 | SmallString<64> Buffer; |
587 | 5 | { |
588 | 5 | raw_svector_ostream OS(Buffer); |
589 | 5 | SymTab.printSymbolName(OS, Sym); |
590 | 5 | Buffer.c_str(); |
591 | 5 | } |
592 | 5 | StringRef Name(Buffer); |
593 | 5 | |
594 | 5 | if (IsUndefined) |
595 | 1 | addAsmGlobalSymbolUndef(Name); |
596 | 4 | else if (4 Flags & object::BasicSymbolRef::SF_Global4 ) |
597 | 0 | addAsmGlobalSymbol(Name, LTO_SYMBOL_SCOPE_DEFAULT); |
598 | 4 | else |
599 | 4 | addAsmGlobalSymbol(Name, LTO_SYMBOL_SCOPE_INTERNAL); |
600 | 5 | continue; |
601 | 5 | } |
602 | 209 | |
603 | 204 | auto *F = dyn_cast<Function>(GV); |
604 | 204 | if (IsUndefined204 ) {29 |
605 | 29 | addPotentialUndefinedSymbol(Sym, F != nullptr); |
606 | 29 | continue; |
607 | 29 | } |
608 | 204 | |
609 | 175 | if (175 F175 ) {148 |
610 | 148 | addDefinedFunctionSymbol(Sym); |
611 | 148 | continue; |
612 | 148 | } |
613 | 175 | |
614 | 27 | if (27 isa<GlobalVariable>(GV)27 ) {25 |
615 | 25 | addDefinedDataSymbol(Sym); |
616 | 25 | continue; |
617 | 25 | } |
618 | 27 | |
619 | 2 | assert(isa<GlobalAlias>(GV)); |
620 | 2 | addDefinedDataSymbol(Sym); |
621 | 2 | } |
622 | 85 | |
623 | 85 | // make symbols for all undefines |
624 | 85 | for (StringMap<NameAndAttributes>::iterator u =_undefines.begin(), |
625 | 116 | e = _undefines.end(); u != e116 ; ++u31 ) {31 |
626 | 31 | // If this symbol also has a definition, then don't make an undefine because |
627 | 31 | // it is a tentative definition. |
628 | 31 | if (_defines.count(u->getKey())31 ) continue5 ; |
629 | 26 | NameAndAttributes info = u->getValue(); |
630 | 26 | _symbols.push_back(info); |
631 | 26 | } |
632 | 85 | } |
633 | | |
634 | | /// parseMetadata - Parse metadata from the module |
635 | 85 | void LTOModule::parseMetadata() { |
636 | 85 | raw_string_ostream OS(LinkerOpts); |
637 | 85 | |
638 | 85 | // Linker Options |
639 | 85 | if (Metadata *Val85 = getModule().getModuleFlag("Linker Options")) {2 |
640 | 2 | MDNode *LinkerOptions = cast<MDNode>(Val); |
641 | 4 | for (unsigned i = 0, e = LinkerOptions->getNumOperands(); i != e4 ; ++i2 ) {2 |
642 | 2 | MDNode *MDOptions = cast<MDNode>(LinkerOptions->getOperand(i)); |
643 | 4 | for (unsigned ii = 0, ie = MDOptions->getNumOperands(); ii != ie4 ; ++ii2 ) {2 |
644 | 2 | MDString *MDOption = cast<MDString>(MDOptions->getOperand(ii)); |
645 | 2 | OS << " " << MDOption->getString(); |
646 | 2 | } |
647 | 2 | } |
648 | 2 | } |
649 | 85 | |
650 | 85 | // Globals |
651 | 205 | for (const NameAndAttributes &Sym : _symbols) { |
652 | 205 | if (!Sym.symbol) |
653 | 1 | continue; |
654 | 204 | _target->getObjFileLowering()->emitLinkerFlagsForGlobal(OS, Sym.symbol); |
655 | 204 | } |
656 | 85 | |
657 | 85 | // Add other interesting metadata here. |
658 | 85 | } |