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/MC/MCAsmInfo.h"
33 #include "llvm/MC/MCContext.h"
34 #include "llvm/MC/MCExpr.h"
35 #include "llvm/MC/MCInst.h"
36 #include "llvm/MC/MCParser/MCAsmParser.h"
37 #include "llvm/MC/MCStreamer.h"
38 #include "llvm/MC/MCSubtargetInfo.h"
39 #include "llvm/MC/MCSymbol.h"
40 #include "llvm/MC/SubtargetFeature.h"
41 #include "llvm/Target/TargetAsmParser.h"
42 #include "llvm/Target/TargetMachine.h"
43 #include "llvm/Target/TargetRegistry.h"
44 #include "llvm/Target/TargetSelect.h"
48 bool LTOModule::isBitcodeFile(const void *mem
, size_t length
) {
49 return llvm::sys::IdentifyFileType((char*)mem
, length
)
50 == llvm::sys::Bitcode_FileType
;
53 bool LTOModule::isBitcodeFile(const char *path
) {
54 return llvm::sys::Path(path
).isBitcodeFile();
57 bool LTOModule::isBitcodeFileForTarget(const void *mem
, size_t length
,
58 const char *triplePrefix
) {
59 MemoryBuffer
*buffer
= makeBuffer(mem
, length
);
62 return isTargetMatch(buffer
, triplePrefix
);
66 bool LTOModule::isBitcodeFileForTarget(const char *path
,
67 const char *triplePrefix
) {
68 OwningPtr
<MemoryBuffer
> buffer
;
69 if (MemoryBuffer::getFile(path
, buffer
))
71 return isTargetMatch(buffer
.take(), triplePrefix
);
74 // Takes ownership of buffer.
75 bool LTOModule::isTargetMatch(MemoryBuffer
*buffer
, const char *triplePrefix
) {
76 std::string Triple
= getBitcodeTargetTriple(buffer
, getGlobalContext());
78 return (strncmp(Triple
.c_str(), triplePrefix
,
79 strlen(triplePrefix
)) == 0);
83 LTOModule::LTOModule(Module
*m
, TargetMachine
*t
)
84 : _module(m
), _target(t
)
88 LTOModule
*LTOModule::makeLTOModule(const char *path
,
89 std::string
&errMsg
) {
90 OwningPtr
<MemoryBuffer
> buffer
;
91 if (error_code ec
= MemoryBuffer::getFile(path
, buffer
)) {
92 errMsg
= ec
.message();
95 return makeLTOModule(buffer
.take(), errMsg
);
98 LTOModule
*LTOModule::makeLTOModule(int fd
, const char *path
,
100 std::string
&errMsg
) {
101 return makeLTOModule(fd
, path
, size
, size
, 0, errMsg
);
104 LTOModule
*LTOModule::makeLTOModule(int fd
, const char *path
,
108 std::string
&errMsg
) {
109 OwningPtr
<MemoryBuffer
> buffer
;
110 if (error_code ec
= MemoryBuffer::getOpenFile(fd
, path
, buffer
, file_size
,
111 map_size
, offset
, false)) {
112 errMsg
= ec
.message();
115 return makeLTOModule(buffer
.take(), errMsg
);
118 /// makeBuffer - Create a MemoryBuffer from a memory range.
119 MemoryBuffer
*LTOModule::makeBuffer(const void *mem
, size_t length
) {
120 const char *startPtr
= (char*)mem
;
121 return MemoryBuffer::getMemBuffer(StringRef(startPtr
, length
), "", false);
125 LTOModule
*LTOModule::makeLTOModule(const void *mem
, size_t length
,
126 std::string
&errMsg
) {
127 OwningPtr
<MemoryBuffer
> buffer(makeBuffer(mem
, length
));
130 return makeLTOModule(buffer
.take(), errMsg
);
133 LTOModule
*LTOModule::makeLTOModule(MemoryBuffer
*buffer
,
134 std::string
&errMsg
) {
135 static bool Initialized
= false;
137 InitializeAllTargets();
138 InitializeAllAsmParsers();
142 // parse bitcode buffer
143 OwningPtr
<Module
> m(getLazyBitcodeModule(buffer
, getGlobalContext(),
150 std::string Triple
= m
->getTargetTriple();
152 Triple
= sys::getHostTriple();
154 // find machine architecture for this module
155 const Target
*march
= TargetRegistry::lookupTarget(Triple
, errMsg
);
159 // construct LTOModule, hand over ownership of module and target
160 SubtargetFeatures Features
;
161 Features
.getDefaultSubtargetFeatures(llvm::Triple(Triple
));
162 std::string FeatureStr
= Features
.getString();
164 TargetMachine
*target
= march
->createTargetMachine(Triple
, CPU
, FeatureStr
);
165 LTOModule
*Ret
= new LTOModule(m
.take(), target
);
166 bool Err
= Ret
->ParseSymbols();
175 const char *LTOModule::getTargetTriple() {
176 return _module
->getTargetTriple().c_str();
179 void LTOModule::setTargetTriple(const char *triple
) {
180 _module
->setTargetTriple(triple
);
183 void LTOModule::addDefinedFunctionSymbol(Function
*f
, Mangler
&mangler
) {
184 // add to list of defined symbols
185 addDefinedSymbol(f
, mangler
, true);
188 // Get string that data pointer points to.
189 bool LTOModule::objcClassNameFromExpression(Constant
*c
, std::string
&name
) {
190 if (ConstantExpr
*ce
= dyn_cast
<ConstantExpr
>(c
)) {
191 Constant
*op
= ce
->getOperand(0);
192 if (GlobalVariable
*gvn
= dyn_cast
<GlobalVariable
>(op
)) {
193 Constant
*cn
= gvn
->getInitializer();
194 if (ConstantArray
*ca
= dyn_cast
<ConstantArray
>(cn
)) {
195 if (ca
->isCString()) {
196 name
= ".objc_class_name_" + ca
->getAsCString();
205 // Parse i386/ppc ObjC class data structure.
206 void LTOModule::addObjCClass(GlobalVariable
*clgv
) {
207 if (ConstantStruct
*c
= dyn_cast
<ConstantStruct
>(clgv
->getInitializer())) {
208 // second slot in __OBJC,__class is pointer to superclass name
209 std::string superclassName
;
210 if (objcClassNameFromExpression(c
->getOperand(1), superclassName
)) {
211 NameAndAttributes info
;
212 StringMap
<NameAndAttributes
>::value_type
&entry
=
213 _undefines
.GetOrCreateValue(superclassName
);
214 if (!entry
.getValue().name
) {
215 const char *symbolName
= entry
.getKey().data();
216 info
.name
= symbolName
;
217 info
.attributes
= LTO_SYMBOL_DEFINITION_UNDEFINED
;
218 entry
.setValue(info
);
221 // third slot in __OBJC,__class is pointer to class name
222 std::string className
;
223 if (objcClassNameFromExpression(c
->getOperand(2), className
)) {
224 StringSet::value_type
&entry
=
225 _defines
.GetOrCreateValue(className
);
227 NameAndAttributes info
;
228 info
.name
= entry
.getKey().data();
229 info
.attributes
= (lto_symbol_attributes
)
230 (LTO_SYMBOL_PERMISSIONS_DATA
|
231 LTO_SYMBOL_DEFINITION_REGULAR
|
232 LTO_SYMBOL_SCOPE_DEFAULT
);
233 _symbols
.push_back(info
);
239 // Parse i386/ppc ObjC category data structure.
240 void LTOModule::addObjCCategory(GlobalVariable
*clgv
) {
241 if (ConstantStruct
*c
= dyn_cast
<ConstantStruct
>(clgv
->getInitializer())) {
242 // second slot in __OBJC,__category is pointer to target class name
243 std::string targetclassName
;
244 if (objcClassNameFromExpression(c
->getOperand(1), targetclassName
)) {
245 NameAndAttributes info
;
247 StringMap
<NameAndAttributes
>::value_type
&entry
=
248 _undefines
.GetOrCreateValue(targetclassName
);
250 if (entry
.getValue().name
)
253 const char *symbolName
= entry
.getKey().data();
254 info
.name
= symbolName
;
255 info
.attributes
= LTO_SYMBOL_DEFINITION_UNDEFINED
;
256 entry
.setValue(info
);
262 // Parse i386/ppc ObjC class list data structure.
263 void LTOModule::addObjCClassRef(GlobalVariable
*clgv
) {
264 std::string targetclassName
;
265 if (objcClassNameFromExpression(clgv
->getInitializer(), targetclassName
)) {
266 NameAndAttributes info
;
268 StringMap
<NameAndAttributes
>::value_type
&entry
=
269 _undefines
.GetOrCreateValue(targetclassName
);
270 if (entry
.getValue().name
)
273 const char *symbolName
= entry
.getKey().data();
274 info
.name
= symbolName
;
275 info
.attributes
= LTO_SYMBOL_DEFINITION_UNDEFINED
;
276 entry
.setValue(info
);
281 void LTOModule::addDefinedDataSymbol(GlobalValue
*v
, Mangler
&mangler
) {
282 // Add to list of defined symbols.
283 addDefinedSymbol(v
, mangler
, false);
285 // Special case i386/ppc ObjC data structures in magic sections:
286 // The issue is that the old ObjC object format did some strange
287 // contortions to avoid real linker symbols. For instance, the
288 // ObjC class data structure is allocated statically in the executable
289 // that defines that class. That data structures contains a pointer to
290 // its superclass. But instead of just initializing that part of the
291 // struct to the address of its superclass, and letting the static and
292 // dynamic linkers do the rest, the runtime works by having that field
293 // instead point to a C-string that is the name of the superclass.
294 // At runtime the objc initialization updates that pointer and sets
295 // it to point to the actual super class. As far as the linker
296 // knows it is just a pointer to a string. But then someone wanted the
297 // linker to issue errors at build time if the superclass was not found.
298 // So they figured out a way in mach-o object format to use an absolute
299 // symbols (.objc_class_name_Foo = 0) and a floating reference
300 // (.reference .objc_class_name_Bar) to cause the linker into erroring when
301 // a class was missing.
302 // The following synthesizes the implicit .objc_* symbols for the linker
303 // from the ObjC data structures generated by the front end.
304 if (v
->hasSection() /* && isTargetDarwin */) {
305 // special case if this data blob is an ObjC class definition
306 if (v
->getSection().compare(0, 15, "__OBJC,__class,") == 0) {
307 if (GlobalVariable
*gv
= dyn_cast
<GlobalVariable
>(v
)) {
312 // special case if this data blob is an ObjC category definition
313 else if (v
->getSection().compare(0, 18, "__OBJC,__category,") == 0) {
314 if (GlobalVariable
*gv
= dyn_cast
<GlobalVariable
>(v
)) {
319 // special case if this data blob is the list of referenced classes
320 else if (v
->getSection().compare(0, 18, "__OBJC,__cls_refs,") == 0) {
321 if (GlobalVariable
*gv
= dyn_cast
<GlobalVariable
>(v
)) {
329 void LTOModule::addDefinedSymbol(GlobalValue
*def
, Mangler
&mangler
,
331 // ignore all llvm.* symbols
332 if (def
->getName().startswith("llvm."))
335 // string is owned by _defines
336 SmallString
<64> Buffer
;
337 mangler
.getNameWithPrefix(Buffer
, def
, false);
339 // set alignment part log2() can have rounding errors
340 uint32_t align
= def
->getAlignment();
341 uint32_t attr
= align
? CountTrailingZeros_32(def
->getAlignment()) : 0;
343 // set permissions part
345 attr
|= LTO_SYMBOL_PERMISSIONS_CODE
;
347 GlobalVariable
*gv
= dyn_cast
<GlobalVariable
>(def
);
348 if (gv
&& gv
->isConstant())
349 attr
|= LTO_SYMBOL_PERMISSIONS_RODATA
;
351 attr
|= LTO_SYMBOL_PERMISSIONS_DATA
;
354 // set definition part
355 if (def
->hasWeakLinkage() || def
->hasLinkOnceLinkage() ||
356 def
->hasLinkerPrivateWeakLinkage() ||
357 def
->hasLinkerPrivateWeakDefAutoLinkage())
358 attr
|= LTO_SYMBOL_DEFINITION_WEAK
;
359 else if (def
->hasCommonLinkage())
360 attr
|= LTO_SYMBOL_DEFINITION_TENTATIVE
;
362 attr
|= LTO_SYMBOL_DEFINITION_REGULAR
;
365 if (def
->hasHiddenVisibility())
366 attr
|= LTO_SYMBOL_SCOPE_HIDDEN
;
367 else if (def
->hasProtectedVisibility())
368 attr
|= LTO_SYMBOL_SCOPE_PROTECTED
;
369 else if (def
->hasExternalLinkage() || def
->hasWeakLinkage() ||
370 def
->hasLinkOnceLinkage() || def
->hasCommonLinkage() ||
371 def
->hasLinkerPrivateWeakLinkage())
372 attr
|= LTO_SYMBOL_SCOPE_DEFAULT
;
373 else if (def
->hasLinkerPrivateWeakDefAutoLinkage())
374 attr
|= LTO_SYMBOL_SCOPE_DEFAULT_CAN_BE_HIDDEN
;
376 attr
|= LTO_SYMBOL_SCOPE_INTERNAL
;
378 // add to table of symbols
379 NameAndAttributes info
;
380 StringSet::value_type
&entry
= _defines
.GetOrCreateValue(Buffer
);
383 StringRef Name
= entry
.getKey();
384 info
.name
= Name
.data();
385 assert(info
.name
[Name
.size()] == '\0');
386 info
.attributes
= (lto_symbol_attributes
)attr
;
387 _symbols
.push_back(info
);
390 void LTOModule::addAsmGlobalSymbol(const char *name
,
391 lto_symbol_attributes scope
) {
392 StringSet::value_type
&entry
= _defines
.GetOrCreateValue(name
);
394 // only add new define if not already defined
395 if (entry
.getValue())
399 const char *symbolName
= entry
.getKey().data();
400 uint32_t attr
= LTO_SYMBOL_DEFINITION_REGULAR
;
402 NameAndAttributes info
;
403 info
.name
= symbolName
;
404 info
.attributes
= (lto_symbol_attributes
)attr
;
405 _symbols
.push_back(info
);
408 void LTOModule::addAsmGlobalSymbolUndef(const char *name
) {
409 StringMap
<NameAndAttributes
>::value_type
&entry
=
410 _undefines
.GetOrCreateValue(name
);
412 _asm_undefines
.push_back(entry
.getKey().data());
414 // we already have the symbol
415 if (entry
.getValue().name
)
418 uint32_t attr
= LTO_SYMBOL_DEFINITION_UNDEFINED
;;
419 attr
|= LTO_SYMBOL_SCOPE_DEFAULT
;
420 NameAndAttributes info
;
421 info
.name
= entry
.getKey().data();
422 info
.attributes
= (lto_symbol_attributes
)attr
;
424 entry
.setValue(info
);
427 void LTOModule::addPotentialUndefinedSymbol(GlobalValue
*decl
,
429 // ignore all llvm.* symbols
430 if (decl
->getName().startswith("llvm."))
433 // ignore all aliases
434 if (isa
<GlobalAlias
>(decl
))
437 SmallString
<64> name
;
438 mangler
.getNameWithPrefix(name
, decl
, false);
440 StringMap
<NameAndAttributes
>::value_type
&entry
=
441 _undefines
.GetOrCreateValue(name
);
443 // we already have the symbol
444 if (entry
.getValue().name
)
447 NameAndAttributes info
;
449 info
.name
= entry
.getKey().data();
450 if (decl
->hasExternalWeakLinkage())
451 info
.attributes
= LTO_SYMBOL_DEFINITION_WEAKUNDEF
;
453 info
.attributes
= LTO_SYMBOL_DEFINITION_UNDEFINED
;
455 entry
.setValue(info
);
460 class RecordStreamer
: public MCStreamer
{
462 enum State
{ NeverSeen
, Global
, Defined
, DefinedGlobal
, Used
};
465 StringMap
<State
> Symbols
;
467 void markDefined(const MCSymbol
&Symbol
) {
468 State
&S
= Symbols
[Symbol
.getName()];
481 void markGlobal(const MCSymbol
&Symbol
) {
482 State
&S
= Symbols
[Symbol
.getName()];
496 void markUsed(const MCSymbol
&Symbol
) {
497 State
&S
= Symbols
[Symbol
.getName()];
511 // FIXME: mostly copied for the obj streamer.
512 void AddValueSymbols(const MCExpr
*Value
) {
513 switch (Value
->getKind()) {
515 // FIXME: What should we do in here?
518 case MCExpr::Constant
:
521 case MCExpr::Binary
: {
522 const MCBinaryExpr
*BE
= cast
<MCBinaryExpr
>(Value
);
523 AddValueSymbols(BE
->getLHS());
524 AddValueSymbols(BE
->getRHS());
528 case MCExpr::SymbolRef
:
529 markUsed(cast
<MCSymbolRefExpr
>(Value
)->getSymbol());
533 AddValueSymbols(cast
<MCUnaryExpr
>(Value
)->getSubExpr());
539 typedef StringMap
<State
>::const_iterator const_iterator
;
541 const_iterator
begin() {
542 return Symbols
.begin();
545 const_iterator
end() {
546 return Symbols
.end();
549 RecordStreamer(MCContext
&Context
) : MCStreamer(Context
) {}
551 virtual void ChangeSection(const MCSection
*Section
) {}
552 virtual void InitSections() {}
553 virtual void EmitLabel(MCSymbol
*Symbol
) {
554 Symbol
->setSection(*getCurrentSection());
555 markDefined(*Symbol
);
557 virtual void EmitAssemblerFlag(MCAssemblerFlag Flag
) {}
558 virtual void EmitThumbFunc(MCSymbol
*Func
) {}
559 virtual void EmitAssignment(MCSymbol
*Symbol
, const MCExpr
*Value
) {
560 // FIXME: should we handle aliases?
561 markDefined(*Symbol
);
563 virtual void EmitSymbolAttribute(MCSymbol
*Symbol
, MCSymbolAttr Attribute
) {
564 if (Attribute
== MCSA_Global
)
567 virtual void EmitSymbolDesc(MCSymbol
*Symbol
, unsigned DescValue
) {}
568 virtual void EmitWeakReference(MCSymbol
*Alias
, const MCSymbol
*Symbol
) {}
569 virtual void BeginCOFFSymbolDef(const MCSymbol
*Symbol
) {}
570 virtual void EmitCOFFSymbolStorageClass(int StorageClass
) {}
571 virtual void EmitZerofill(const MCSection
*Section
, MCSymbol
*Symbol
,
572 unsigned Size
, unsigned ByteAlignment
) {
573 markDefined(*Symbol
);
575 virtual void EmitCOFFSymbolType(int Type
) {}
576 virtual void EndCOFFSymbolDef() {}
577 virtual void EmitCommonSymbol(MCSymbol
*Symbol
, uint64_t Size
,
578 unsigned ByteAlignment
) {
579 markDefined(*Symbol
);
581 virtual void EmitELFSize(MCSymbol
*Symbol
, const MCExpr
*Value
) {}
582 virtual void EmitLocalCommonSymbol(MCSymbol
*Symbol
, uint64_t Size
) {}
583 virtual void EmitTBSSSymbol(const MCSection
*Section
, MCSymbol
*Symbol
,
584 uint64_t Size
, unsigned ByteAlignment
) {}
585 virtual void EmitBytes(StringRef Data
, unsigned AddrSpace
) {}
586 virtual void EmitValueImpl(const MCExpr
*Value
, unsigned Size
,
587 unsigned AddrSpace
) {}
588 virtual void EmitULEB128Value(const MCExpr
*Value
) {}
589 virtual void EmitSLEB128Value(const MCExpr
*Value
) {}
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
<MCSubtargetInfo
> STI(_target
->getTarget().
623 createMCSubtargetInfo(_target
->getTargetTriple(),
624 _target
->getTargetCPU(),
625 _target
->getTargetFeatureString()));
626 OwningPtr
<TargetAsmParser
>
627 TAP(_target
->getTarget().createAsmParser(*STI
, *Parser
.get()));
628 Parser
->setTargetParser(*TAP
);
629 int Res
= Parser
->Run(false);
633 for (RecordStreamer::const_iterator i
= Streamer
->begin(),
634 e
= Streamer
->end(); i
!= e
; ++i
) {
635 StringRef Key
= i
->first();
636 RecordStreamer::State Value
= i
->second
;
637 if (Value
== RecordStreamer::DefinedGlobal
)
638 addAsmGlobalSymbol(Key
.data(), LTO_SYMBOL_SCOPE_DEFAULT
);
639 else if (Value
== RecordStreamer::Defined
)
640 addAsmGlobalSymbol(Key
.data(), LTO_SYMBOL_SCOPE_INTERNAL
);
641 else if (Value
== RecordStreamer::Global
||
642 Value
== RecordStreamer::Used
)
643 addAsmGlobalSymbolUndef(Key
.data());
648 static bool isDeclaration(const GlobalValue
&V
) {
649 if (V
.hasAvailableExternallyLinkage())
651 if (V
.isMaterializable())
653 return V
.isDeclaration();
656 static bool isAliasToDeclaration(const GlobalAlias
&V
) {
657 return isDeclaration(*V
.getAliasedGlobal());
660 bool LTOModule::ParseSymbols() {
661 // Use mangler to add GlobalPrefix to names to match linker names.
662 MCContext
Context(*_target
->getMCAsmInfo(), NULL
);
663 Mangler
mangler(Context
, *_target
->getTargetData());
666 for (Module::iterator f
= _module
->begin(); f
!= _module
->end(); ++f
) {
667 if (isDeclaration(*f
))
668 addPotentialUndefinedSymbol(f
, mangler
);
670 addDefinedFunctionSymbol(f
, mangler
);
674 for (Module::global_iterator v
= _module
->global_begin(),
675 e
= _module
->global_end(); v
!= e
; ++v
) {
676 if (isDeclaration(*v
))
677 addPotentialUndefinedSymbol(v
, mangler
);
679 addDefinedDataSymbol(v
, mangler
);
683 if (addAsmGlobalSymbols(Context
))
687 for (Module::alias_iterator i
= _module
->alias_begin(),
688 e
= _module
->alias_end(); i
!= e
; ++i
) {
689 if (isAliasToDeclaration(*i
))
690 addPotentialUndefinedSymbol(i
, mangler
);
692 addDefinedDataSymbol(i
, mangler
);
695 // make symbols for all undefines
696 for (StringMap
<NameAndAttributes
>::iterator it
=_undefines
.begin();
697 it
!= _undefines
.end(); ++it
) {
698 // if this symbol also has a definition, then don't make an undefine
699 // because it is a tentative definition
700 if (_defines
.count(it
->getKey()) == 0) {
701 NameAndAttributes info
= it
->getValue();
702 _symbols
.push_back(info
);
709 uint32_t LTOModule::getSymbolCount() {
710 return _symbols
.size();
714 lto_symbol_attributes
LTOModule::getSymbolAttributes(uint32_t index
) {
715 if (index
< _symbols
.size())
716 return _symbols
[index
].attributes
;
718 return lto_symbol_attributes(0);
721 const char *LTOModule::getSymbolName(uint32_t index
) {
722 if (index
< _symbols
.size())
723 return _symbols
[index
].name
;