1 //===-- LTOModule.cpp - LLVM Link Time Optimizer --------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
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.
13 //===----------------------------------------------------------------------===//
15 #include "LTOModule.h"
17 #include "llvm/Constants.h"
18 #include "llvm/LLVMContext.h"
19 #include "llvm/Module.h"
20 #include "llvm/ADT/OwningPtr.h"
21 #include "llvm/ADT/Triple.h"
22 #include "llvm/Bitcode/ReaderWriter.h"
23 #include "llvm/Support/SystemUtils.h"
24 #include "llvm/Support/MemoryBuffer.h"
25 #include "llvm/Support/MathExtras.h"
26 #include "llvm/Support/Host.h"
27 #include "llvm/Support/Path.h"
28 #include "llvm/Support/Process.h"
29 #include "llvm/Support/SourceMgr.h"
30 #include "llvm/Support/system_error.h"
31 #include "llvm/Target/Mangler.h"
32 #include "llvm/Target/SubtargetFeature.h"
33 #include "llvm/MC/MCAsmInfo.h"
34 #include "llvm/MC/MCContext.h"
35 #include "llvm/MC/MCExpr.h"
36 #include "llvm/MC/MCInst.h"
37 #include "llvm/MC/MCParser/MCAsmParser.h"
38 #include "llvm/MC/MCStreamer.h"
39 #include "llvm/MC/MCSymbol.h"
40 #include "llvm/Target/TargetAsmParser.h"
41 #include "llvm/Target/TargetMachine.h"
42 #include "llvm/Target/TargetRegistry.h"
43 #include "llvm/Target/TargetSelect.h"
47 bool LTOModule::isBitcodeFile(const void *mem
, size_t length
) {
48 return llvm::sys::IdentifyFileType((char*)mem
, length
)
49 == llvm::sys::Bitcode_FileType
;
52 bool LTOModule::isBitcodeFile(const char *path
) {
53 return llvm::sys::Path(path
).isBitcodeFile();
56 bool LTOModule::isBitcodeFileForTarget(const void *mem
, size_t length
,
57 const char *triplePrefix
) {
58 MemoryBuffer
*buffer
= makeBuffer(mem
, length
);
61 return isTargetMatch(buffer
, triplePrefix
);
65 bool LTOModule::isBitcodeFileForTarget(const char *path
,
66 const char *triplePrefix
) {
67 OwningPtr
<MemoryBuffer
> buffer
;
68 if (MemoryBuffer::getFile(path
, buffer
))
70 return isTargetMatch(buffer
.take(), triplePrefix
);
73 // Takes ownership of buffer.
74 bool LTOModule::isTargetMatch(MemoryBuffer
*buffer
, const char *triplePrefix
) {
75 std::string Triple
= getBitcodeTargetTriple(buffer
, getGlobalContext());
77 return (strncmp(Triple
.c_str(), triplePrefix
,
78 strlen(triplePrefix
)) == 0);
82 LTOModule::LTOModule(Module
*m
, TargetMachine
*t
)
83 : _module(m
), _target(t
)
87 LTOModule
*LTOModule::makeLTOModule(const char *path
,
88 std::string
&errMsg
) {
89 OwningPtr
<MemoryBuffer
> buffer
;
90 if (error_code ec
= MemoryBuffer::getFile(path
, buffer
)) {
91 errMsg
= ec
.message();
94 return makeLTOModule(buffer
.take(), errMsg
);
97 LTOModule
*LTOModule::makeLTOModule(int fd
, const char *path
,
99 std::string
&errMsg
) {
100 return makeLTOModule(fd
, path
, size
, size
, 0, errMsg
);
103 LTOModule
*LTOModule::makeLTOModule(int fd
, const char *path
,
107 std::string
&errMsg
) {
108 OwningPtr
<MemoryBuffer
> buffer
;
109 if (error_code ec
= MemoryBuffer::getOpenFile(fd
, path
, buffer
, file_size
,
110 map_size
, offset
, false)) {
111 errMsg
= ec
.message();
114 return makeLTOModule(buffer
.take(), errMsg
);
117 /// makeBuffer - Create a MemoryBuffer from a memory range.
118 MemoryBuffer
*LTOModule::makeBuffer(const void *mem
, size_t length
) {
119 const char *startPtr
= (char*)mem
;
120 return MemoryBuffer::getMemBuffer(StringRef(startPtr
, length
), "", false);
124 LTOModule
*LTOModule::makeLTOModule(const void *mem
, size_t length
,
125 std::string
&errMsg
) {
126 OwningPtr
<MemoryBuffer
> buffer(makeBuffer(mem
, length
));
129 return makeLTOModule(buffer
.take(), errMsg
);
132 LTOModule
*LTOModule::makeLTOModule(MemoryBuffer
*buffer
,
133 std::string
&errMsg
) {
134 static bool Initialized
= false;
136 InitializeAllTargets();
137 InitializeAllAsmParsers();
141 // parse bitcode buffer
142 OwningPtr
<Module
> m(getLazyBitcodeModule(buffer
, getGlobalContext(),
149 std::string Triple
= m
->getTargetTriple();
151 Triple
= sys::getHostTriple();
153 // find machine architecture for this module
154 const Target
*march
= TargetRegistry::lookupTarget(Triple
, errMsg
);
158 // construct LTOModule, hand over ownership of module and target
159 SubtargetFeatures Features
;
160 Features
.getDefaultSubtargetFeatures("" /* cpu */, llvm::Triple(Triple
));
161 std::string FeatureStr
= Features
.getString();
162 TargetMachine
*target
= march
->createTargetMachine(Triple
, FeatureStr
);
163 LTOModule
*Ret
= new LTOModule(m
.take(), target
);
164 bool Err
= Ret
->ParseSymbols();
173 const char *LTOModule::getTargetTriple() {
174 return _module
->getTargetTriple().c_str();
177 void LTOModule::setTargetTriple(const char *triple
) {
178 _module
->setTargetTriple(triple
);
181 void LTOModule::addDefinedFunctionSymbol(Function
*f
, Mangler
&mangler
) {
182 // add to list of defined symbols
183 addDefinedSymbol(f
, mangler
, true);
186 // Get string that data pointer points to.
187 bool LTOModule::objcClassNameFromExpression(Constant
*c
, std::string
&name
) {
188 if (ConstantExpr
*ce
= dyn_cast
<ConstantExpr
>(c
)) {
189 Constant
*op
= ce
->getOperand(0);
190 if (GlobalVariable
*gvn
= dyn_cast
<GlobalVariable
>(op
)) {
191 Constant
*cn
= gvn
->getInitializer();
192 if (ConstantArray
*ca
= dyn_cast
<ConstantArray
>(cn
)) {
193 if (ca
->isCString()) {
194 name
= ".objc_class_name_" + ca
->getAsString();
203 // Parse i386/ppc ObjC class data structure.
204 void LTOModule::addObjCClass(GlobalVariable
*clgv
) {
205 if (ConstantStruct
*c
= dyn_cast
<ConstantStruct
>(clgv
->getInitializer())) {
206 // second slot in __OBJC,__class is pointer to superclass name
207 std::string superclassName
;
208 if (objcClassNameFromExpression(c
->getOperand(1), superclassName
)) {
209 NameAndAttributes info
;
210 StringMap
<NameAndAttributes
>::value_type
&entry
=
211 _undefines
.GetOrCreateValue(superclassName
.c_str());
212 if (!entry
.getValue().name
) {
213 const char *symbolName
= entry
.getKey().data();
214 info
.name
= symbolName
;
215 info
.attributes
= LTO_SYMBOL_DEFINITION_UNDEFINED
;
216 entry
.setValue(info
);
219 // third slot in __OBJC,__class is pointer to class name
220 std::string className
;
221 if (objcClassNameFromExpression(c
->getOperand(2), className
)) {
222 StringSet::value_type
&entry
=
223 _defines
.GetOrCreateValue(className
.c_str());
225 NameAndAttributes info
;
226 info
.name
= entry
.getKey().data();
227 info
.attributes
= (lto_symbol_attributes
)
228 (LTO_SYMBOL_PERMISSIONS_DATA
|
229 LTO_SYMBOL_DEFINITION_REGULAR
|
230 LTO_SYMBOL_SCOPE_DEFAULT
);
231 _symbols
.push_back(info
);
237 // Parse i386/ppc ObjC category data structure.
238 void LTOModule::addObjCCategory(GlobalVariable
*clgv
) {
239 if (ConstantStruct
*c
= dyn_cast
<ConstantStruct
>(clgv
->getInitializer())) {
240 // second slot in __OBJC,__category is pointer to target class name
241 std::string targetclassName
;
242 if (objcClassNameFromExpression(c
->getOperand(1), targetclassName
)) {
243 NameAndAttributes info
;
245 StringMap
<NameAndAttributes
>::value_type
&entry
=
246 _undefines
.GetOrCreateValue(targetclassName
.c_str());
248 if (entry
.getValue().name
)
251 const char *symbolName
= entry
.getKey().data();
252 info
.name
= symbolName
;
253 info
.attributes
= LTO_SYMBOL_DEFINITION_UNDEFINED
;
254 entry
.setValue(info
);
260 // Parse i386/ppc ObjC class list data structure.
261 void LTOModule::addObjCClassRef(GlobalVariable
*clgv
) {
262 std::string targetclassName
;
263 if (objcClassNameFromExpression(clgv
->getInitializer(), targetclassName
)) {
264 NameAndAttributes info
;
266 StringMap
<NameAndAttributes
>::value_type
&entry
=
267 _undefines
.GetOrCreateValue(targetclassName
.c_str());
268 if (entry
.getValue().name
)
271 const char *symbolName
= entry
.getKey().data();
272 info
.name
= symbolName
;
273 info
.attributes
= LTO_SYMBOL_DEFINITION_UNDEFINED
;
274 entry
.setValue(info
);
279 void LTOModule::addDefinedDataSymbol(GlobalValue
*v
, Mangler
&mangler
) {
280 // Add to list of defined symbols.
281 addDefinedSymbol(v
, mangler
, false);
283 // Special case i386/ppc ObjC data structures in magic sections:
284 // The issue is that the old ObjC object format did some strange
285 // contortions to avoid real linker symbols. For instance, the
286 // ObjC class data structure is allocated statically in the executable
287 // that defines that class. That data structures contains a pointer to
288 // its superclass. But instead of just initializing that part of the
289 // struct to the address of its superclass, and letting the static and
290 // dynamic linkers do the rest, the runtime works by having that field
291 // instead point to a C-string that is the name of the superclass.
292 // At runtime the objc initialization updates that pointer and sets
293 // it to point to the actual super class. As far as the linker
294 // knows it is just a pointer to a string. But then someone wanted the
295 // linker to issue errors at build time if the superclass was not found.
296 // So they figured out a way in mach-o object format to use an absolute
297 // symbols (.objc_class_name_Foo = 0) and a floating reference
298 // (.reference .objc_class_name_Bar) to cause the linker into erroring when
299 // a class was missing.
300 // The following synthesizes the implicit .objc_* symbols for the linker
301 // from the ObjC data structures generated by the front end.
302 if (v
->hasSection() /* && isTargetDarwin */) {
303 // special case if this data blob is an ObjC class definition
304 if (v
->getSection().compare(0, 15, "__OBJC,__class,") == 0) {
305 if (GlobalVariable
*gv
= dyn_cast
<GlobalVariable
>(v
)) {
310 // special case if this data blob is an ObjC category definition
311 else if (v
->getSection().compare(0, 18, "__OBJC,__category,") == 0) {
312 if (GlobalVariable
*gv
= dyn_cast
<GlobalVariable
>(v
)) {
317 // special case if this data blob is the list of referenced classes
318 else if (v
->getSection().compare(0, 18, "__OBJC,__cls_refs,") == 0) {
319 if (GlobalVariable
*gv
= dyn_cast
<GlobalVariable
>(v
)) {
327 void LTOModule::addDefinedSymbol(GlobalValue
*def
, Mangler
&mangler
,
329 // ignore all llvm.* symbols
330 if (def
->getName().startswith("llvm."))
333 // string is owned by _defines
334 SmallString
<64> Buffer
;
335 mangler
.getNameWithPrefix(Buffer
, def
, false);
337 // set alignment part log2() can have rounding errors
338 uint32_t align
= def
->getAlignment();
339 uint32_t attr
= align
? CountTrailingZeros_32(def
->getAlignment()) : 0;
341 // set permissions part
343 attr
|= LTO_SYMBOL_PERMISSIONS_CODE
;
345 GlobalVariable
*gv
= dyn_cast
<GlobalVariable
>(def
);
346 if (gv
&& gv
->isConstant())
347 attr
|= LTO_SYMBOL_PERMISSIONS_RODATA
;
349 attr
|= LTO_SYMBOL_PERMISSIONS_DATA
;
352 // set definition part
353 if (def
->hasWeakLinkage() || def
->hasLinkOnceLinkage() ||
354 def
->hasLinkerPrivateWeakLinkage() ||
355 def
->hasLinkerPrivateWeakDefAutoLinkage())
356 attr
|= LTO_SYMBOL_DEFINITION_WEAK
;
357 else if (def
->hasCommonLinkage())
358 attr
|= LTO_SYMBOL_DEFINITION_TENTATIVE
;
360 attr
|= LTO_SYMBOL_DEFINITION_REGULAR
;
363 if (def
->hasHiddenVisibility())
364 attr
|= LTO_SYMBOL_SCOPE_HIDDEN
;
365 else if (def
->hasProtectedVisibility())
366 attr
|= LTO_SYMBOL_SCOPE_PROTECTED
;
367 else if (def
->hasExternalLinkage() || def
->hasWeakLinkage() ||
368 def
->hasLinkOnceLinkage() || def
->hasCommonLinkage() ||
369 def
->hasLinkerPrivateWeakLinkage())
370 attr
|= LTO_SYMBOL_SCOPE_DEFAULT
;
371 else if (def
->hasLinkerPrivateWeakDefAutoLinkage())
372 attr
|= LTO_SYMBOL_SCOPE_DEFAULT_CAN_BE_HIDDEN
;
374 attr
|= LTO_SYMBOL_SCOPE_INTERNAL
;
376 // add to table of symbols
377 NameAndAttributes info
;
378 StringSet::value_type
&entry
= _defines
.GetOrCreateValue(Buffer
.c_str());
381 StringRef Name
= entry
.getKey();
382 info
.name
= Name
.data();
383 assert(info
.name
[Name
.size()] == '\0');
384 info
.attributes
= (lto_symbol_attributes
)attr
;
385 _symbols
.push_back(info
);
388 void LTOModule::addAsmGlobalSymbol(const char *name
,
389 lto_symbol_attributes scope
) {
390 StringSet::value_type
&entry
= _defines
.GetOrCreateValue(name
);
392 // only add new define if not already defined
393 if (entry
.getValue())
397 const char *symbolName
= entry
.getKey().data();
398 uint32_t attr
= LTO_SYMBOL_DEFINITION_REGULAR
;
400 NameAndAttributes info
;
401 info
.name
= symbolName
;
402 info
.attributes
= (lto_symbol_attributes
)attr
;
403 _symbols
.push_back(info
);
406 void LTOModule::addAsmGlobalSymbolUndef(const char *name
) {
407 StringMap
<NameAndAttributes
>::value_type
&entry
=
408 _undefines
.GetOrCreateValue(name
);
410 _asm_undefines
.push_back(entry
.getKey().data());
412 // we already have the symbol
413 if (entry
.getValue().name
)
416 uint32_t attr
= LTO_SYMBOL_DEFINITION_UNDEFINED
;;
417 attr
|= LTO_SYMBOL_SCOPE_DEFAULT
;
418 NameAndAttributes info
;
419 info
.name
= entry
.getKey().data();
420 info
.attributes
= (lto_symbol_attributes
)attr
;
422 entry
.setValue(info
);
425 void LTOModule::addPotentialUndefinedSymbol(GlobalValue
*decl
,
427 // ignore all llvm.* symbols
428 if (decl
->getName().startswith("llvm."))
431 // ignore all aliases
432 if (isa
<GlobalAlias
>(decl
))
435 SmallString
<64> name
;
436 mangler
.getNameWithPrefix(name
, decl
, false);
438 StringMap
<NameAndAttributes
>::value_type
&entry
=
439 _undefines
.GetOrCreateValue(name
.c_str());
441 // we already have the symbol
442 if (entry
.getValue().name
)
445 NameAndAttributes info
;
447 info
.name
= entry
.getKey().data();
448 if (decl
->hasExternalWeakLinkage())
449 info
.attributes
= LTO_SYMBOL_DEFINITION_WEAKUNDEF
;
451 info
.attributes
= LTO_SYMBOL_DEFINITION_UNDEFINED
;
453 entry
.setValue(info
);
458 class RecordStreamer
: public MCStreamer
{
460 enum State
{ NeverSeen
, Global
, Defined
, DefinedGlobal
, Used
};
463 StringMap
<State
> Symbols
;
465 void markDefined(const MCSymbol
&Symbol
) {
466 State
&S
= Symbols
[Symbol
.getName()];
479 void markGlobal(const MCSymbol
&Symbol
) {
480 State
&S
= Symbols
[Symbol
.getName()];
494 void markUsed(const MCSymbol
&Symbol
) {
495 State
&S
= Symbols
[Symbol
.getName()];
509 // FIXME: mostly copied for the obj streamer.
510 void AddValueSymbols(const MCExpr
*Value
) {
511 switch (Value
->getKind()) {
513 // FIXME: What should we do in here?
516 case MCExpr::Constant
:
519 case MCExpr::Binary
: {
520 const MCBinaryExpr
*BE
= cast
<MCBinaryExpr
>(Value
);
521 AddValueSymbols(BE
->getLHS());
522 AddValueSymbols(BE
->getRHS());
526 case MCExpr::SymbolRef
:
527 markUsed(cast
<MCSymbolRefExpr
>(Value
)->getSymbol());
531 AddValueSymbols(cast
<MCUnaryExpr
>(Value
)->getSubExpr());
537 typedef StringMap
<State
>::const_iterator const_iterator
;
539 const_iterator
begin() {
540 return Symbols
.begin();
543 const_iterator
end() {
544 return Symbols
.end();
547 RecordStreamer(MCContext
&Context
) : MCStreamer(Context
) {}
549 virtual void ChangeSection(const MCSection
*Section
) {}
550 virtual void InitSections() {}
551 virtual void EmitLabel(MCSymbol
*Symbol
) {
552 Symbol
->setSection(*getCurrentSection());
553 markDefined(*Symbol
);
555 virtual void EmitAssemblerFlag(MCAssemblerFlag Flag
) {}
556 virtual void EmitThumbFunc(MCSymbol
*Func
) {}
557 virtual void EmitAssignment(MCSymbol
*Symbol
, const MCExpr
*Value
) {
558 // FIXME: should we handle aliases?
559 markDefined(*Symbol
);
561 virtual void EmitSymbolAttribute(MCSymbol
*Symbol
, MCSymbolAttr Attribute
) {
562 if (Attribute
== MCSA_Global
)
565 virtual void EmitSymbolDesc(MCSymbol
*Symbol
, unsigned DescValue
) {}
566 virtual void EmitWeakReference(MCSymbol
*Alias
, const MCSymbol
*Symbol
) {}
567 virtual void BeginCOFFSymbolDef(const MCSymbol
*Symbol
) {}
568 virtual void EmitCOFFSymbolStorageClass(int StorageClass
) {}
569 virtual void EmitZerofill(const MCSection
*Section
, MCSymbol
*Symbol
,
570 unsigned Size
, unsigned ByteAlignment
) {
571 markDefined(*Symbol
);
573 virtual void EmitCOFFSymbolType(int Type
) {}
574 virtual void EndCOFFSymbolDef() {}
575 virtual void EmitCommonSymbol(MCSymbol
*Symbol
, uint64_t Size
,
576 unsigned ByteAlignment
) {
577 markDefined(*Symbol
);
579 virtual void EmitELFSize(MCSymbol
*Symbol
, const MCExpr
*Value
) {}
580 virtual void EmitLocalCommonSymbol(MCSymbol
*Symbol
, uint64_t Size
) {}
581 virtual void EmitTBSSSymbol(const MCSection
*Section
, MCSymbol
*Symbol
,
582 uint64_t Size
, unsigned ByteAlignment
) {}
583 virtual void EmitBytes(StringRef Data
, unsigned AddrSpace
) {}
584 virtual void EmitValueImpl(const MCExpr
*Value
, unsigned Size
,
585 bool isPCRel
, unsigned AddrSpace
) {}
586 virtual void EmitULEB128Value(const MCExpr
*Value
,
587 unsigned AddrSpace
= 0) {}
588 virtual void EmitSLEB128Value(const MCExpr
*Value
,
589 unsigned AddrSpace
= 0) {}
590 virtual void EmitValueToAlignment(unsigned ByteAlignment
, int64_t Value
,
592 unsigned MaxBytesToEmit
) {}
593 virtual void EmitCodeAlignment(unsigned ByteAlignment
,
594 unsigned MaxBytesToEmit
) {}
595 virtual void EmitValueToOffset(const MCExpr
*Offset
,
596 unsigned char Value
) {}
597 virtual void EmitFileDirective(StringRef Filename
) {}
598 virtual void EmitDwarfAdvanceLineAddr(int64_t LineDelta
,
599 const MCSymbol
*LastLabel
,
600 const MCSymbol
*Label
) {}
602 virtual void EmitInstruction(const MCInst
&Inst
) {
604 for (unsigned i
= Inst
.getNumOperands(); i
--; )
605 if (Inst
.getOperand(i
).isExpr())
606 AddValueSymbols(Inst
.getOperand(i
).getExpr());
608 virtual void Finish() {}
612 bool LTOModule::addAsmGlobalSymbols(MCContext
&Context
) {
613 const std::string
&inlineAsm
= _module
->getModuleInlineAsm();
615 OwningPtr
<RecordStreamer
> Streamer(new RecordStreamer(Context
));
616 MemoryBuffer
*Buffer
= MemoryBuffer::getMemBuffer(inlineAsm
);
618 SrcMgr
.AddNewSourceBuffer(Buffer
, SMLoc());
619 OwningPtr
<MCAsmParser
> Parser(createMCAsmParser(_target
->getTarget(), SrcMgr
,
621 *_target
->getMCAsmInfo()));
622 OwningPtr
<TargetAsmParser
>
623 TAP(_target
->getTarget().createAsmParser(*Parser
.get(), *_target
.get()));
624 Parser
->setTargetParser(*TAP
);
625 int Res
= Parser
->Run(false);
629 for (RecordStreamer::const_iterator i
= Streamer
->begin(),
630 e
= Streamer
->end(); i
!= e
; ++i
) {
631 StringRef Key
= i
->first();
632 RecordStreamer::State Value
= i
->second
;
633 if (Value
== RecordStreamer::DefinedGlobal
)
634 addAsmGlobalSymbol(Key
.data(), LTO_SYMBOL_SCOPE_DEFAULT
);
635 else if (Value
== RecordStreamer::Defined
)
636 addAsmGlobalSymbol(Key
.data(), LTO_SYMBOL_SCOPE_INTERNAL
);
637 else if (Value
== RecordStreamer::Global
||
638 Value
== RecordStreamer::Used
)
639 addAsmGlobalSymbolUndef(Key
.data());
644 static bool isDeclaration(const GlobalValue
&V
) {
645 if (V
.hasAvailableExternallyLinkage())
647 if (V
.isMaterializable())
649 return V
.isDeclaration();
652 static bool isAliasToDeclaration(const GlobalAlias
&V
) {
653 return isDeclaration(*V
.getAliasedGlobal());
656 bool LTOModule::ParseSymbols() {
657 // Use mangler to add GlobalPrefix to names to match linker names.
658 MCContext
Context(*_target
->getMCAsmInfo(), NULL
);
659 Mangler
mangler(Context
, *_target
->getTargetData());
662 for (Module::iterator f
= _module
->begin(); f
!= _module
->end(); ++f
) {
663 if (isDeclaration(*f
))
664 addPotentialUndefinedSymbol(f
, mangler
);
666 addDefinedFunctionSymbol(f
, mangler
);
670 for (Module::global_iterator v
= _module
->global_begin(),
671 e
= _module
->global_end(); v
!= e
; ++v
) {
672 if (isDeclaration(*v
))
673 addPotentialUndefinedSymbol(v
, mangler
);
675 addDefinedDataSymbol(v
, mangler
);
679 if (addAsmGlobalSymbols(Context
))
683 for (Module::alias_iterator i
= _module
->alias_begin(),
684 e
= _module
->alias_end(); i
!= e
; ++i
) {
685 if (isAliasToDeclaration(*i
))
686 addPotentialUndefinedSymbol(i
, mangler
);
688 addDefinedDataSymbol(i
, mangler
);
691 // make symbols for all undefines
692 for (StringMap
<NameAndAttributes
>::iterator it
=_undefines
.begin();
693 it
!= _undefines
.end(); ++it
) {
694 // if this symbol also has a definition, then don't make an undefine
695 // because it is a tentative definition
696 if (_defines
.count(it
->getKey()) == 0) {
697 NameAndAttributes info
= it
->getValue();
698 _symbols
.push_back(info
);
705 uint32_t LTOModule::getSymbolCount() {
706 return _symbols
.size();
710 lto_symbol_attributes
LTOModule::getSymbolAttributes(uint32_t index
) {
711 if (index
< _symbols
.size())
712 return _symbols
[index
].attributes
;
714 return lto_symbol_attributes(0);
717 const char *LTOModule::getSymbolName(uint32_t index
) {
718 if (index
< _symbols
.size())
719 return _symbols
[index
].name
;