diff options
-rw-r--r-- | include/llvm-c/lto.h | 9 | ||||
-rw-r--r-- | include/llvm/LTO/LTOCodeGenerator.h | 6 | ||||
-rw-r--r-- | include/llvm/Transforms/IPO.h | 18 | ||||
-rw-r--r-- | lib/LTO/LTOCodeGenerator.cpp | 12 | ||||
-rw-r--r-- | lib/LTO/LTOModule.cpp | 26 | ||||
-rw-r--r-- | lib/Transforms/IPO/IPO.cpp | 2 | ||||
-rw-r--r-- | lib/Transforms/IPO/Internalize.cpp | 64 | ||||
-rw-r--r-- | lib/Transforms/IPO/PassManagerBuilder.cpp | 2 | ||||
-rw-r--r-- | test/LTO/linkonce_odr_func.ll (renamed from test/Transforms/Internalize/linkonce_odr_func.ll) | 17 | ||||
-rw-r--r-- | test/Transforms/Internalize/lists.ll | 16 | ||||
-rw-r--r-- | tools/gold/gold-plugin.cpp | 21 | ||||
-rw-r--r-- | tools/llvm-lto/llvm-lto.cpp | 28 | ||||
-rw-r--r-- | tools/lto/lto.cpp | 4 | ||||
-rw-r--r-- | tools/lto/lto.exports | 1 |
14 files changed, 96 insertions, 130 deletions
diff --git a/include/llvm-c/lto.h b/include/llvm-c/lto.h index a09db24..89f54b7 100644 --- a/include/llvm-c/lto.h +++ b/include/llvm-c/lto.h @@ -270,15 +270,6 @@ lto_codegen_set_assembler_args(lto_code_gen_t cg, const char **args, extern void lto_codegen_add_must_preserve_symbol(lto_code_gen_t cg, const char* symbol); - -/** - * Tells LTO optimization passes that a dynamic shared library is being - * built and this symbol may be exported. Unless IR semantics allow the symbol - * to be made local to the library, it should remain so it can be exported by - * the shared library. - */ -extern void lto_codegen_add_dso_symbol(lto_code_gen_t cg, const char *symbol); - /** * Writes a new object file at the specified path that contains the * merged contents of all modules added so far. diff --git a/include/llvm/LTO/LTOCodeGenerator.h b/include/llvm/LTO/LTOCodeGenerator.h index 9f50770..97a5066 100644 --- a/include/llvm/LTO/LTOCodeGenerator.h +++ b/include/llvm/LTO/LTOCodeGenerator.h @@ -73,10 +73,6 @@ struct LTOCodeGenerator { void addMustPreserveSymbol(const char *sym) { MustPreserveSymbols[sym] = 1; } - void addDSOSymbol(const char* Sym) { - DSOSymbols[Sym] = 1; - } - // To pass options to the driver and optimization passes. These options are // not necessarily for debugging purpose (The function name is misleading). // This function should be called before LTOCodeGenerator::compilexxx(), @@ -130,7 +126,6 @@ private: void applyScopeRestrictions(); void applyRestriction(llvm::GlobalValue &GV, std::vector<const char*> &MustPreserveList, - std::vector<const char*> &SymtabList, llvm::SmallPtrSet<llvm::GlobalValue*, 8> &AsmUsed, llvm::Mangler &Mangler); bool determineTarget(std::string &errMsg); @@ -143,7 +138,6 @@ private: bool EmitDwarfDebugInfo; bool ScopeRestrictionsDone; lto_codegen_model CodeModel; - StringSet DSOSymbols; StringSet MustPreserveSymbols; StringSet AsmUndefinedRefs; llvm::MemoryBuffer *NativeObjectFile; diff --git a/include/llvm/Transforms/IPO.h b/include/llvm/Transforms/IPO.h index ed28230..7f51c51 100644 --- a/include/llvm/Transforms/IPO.h +++ b/include/llvm/Transforms/IPO.h @@ -111,25 +111,9 @@ Pass *createPruneEHPass(); /// The symbol in DSOList are internalized if it is safe to drop them from /// the symbol table. /// -/// For example of the difference, consider a dynamic library being built from -/// two translation units. The first one compiled to a native object -/// (ELF/MachO/COFF) and second one compiled to IL. Translation unit A has a -/// copy of linkonce_odr unnamed_addr function F. The translation unit B has a -/// copy of the linkonce_odr unnamed_addr functions F and G. -/// -/// Assume the linker decides to keep the copy of F in B. This means that LLVM -/// must produce F in the object file it passes to the linker, otherwise we -/// will have an undefined reference. For G the situation is different. The -/// linker puts the function in the DSOList, since it is only wanted for the -/// symbol table. With this information internalize can now reason that since -/// the function is a linkonce_odr and its address is not important, it can be -/// omitted. Any other shared library needing this function will have a copy of -/// it. -/// /// Note that commandline options that are used with the above function are not /// used now! -ModulePass *createInternalizePass(ArrayRef<const char *> ExportList, - ArrayRef<const char *> DSOList); +ModulePass *createInternalizePass(ArrayRef<const char *> ExportList); /// createInternalizePass - Same as above, but with an empty exportList. ModulePass *createInternalizePass(); diff --git a/lib/LTO/LTOCodeGenerator.cpp b/lib/LTO/LTOCodeGenerator.cpp index c55eccb..3c9a378 100644 --- a/lib/LTO/LTOCodeGenerator.cpp +++ b/lib/LTO/LTOCodeGenerator.cpp @@ -313,7 +313,6 @@ bool LTOCodeGenerator::determineTarget(std::string &errMsg) { void LTOCodeGenerator:: applyRestriction(GlobalValue &GV, std::vector<const char*> &MustPreserveList, - std::vector<const char*> &DSOList, SmallPtrSet<GlobalValue*, 8> &AsmUsed, Mangler &Mangler) { SmallString<64> Buffer; @@ -323,8 +322,6 @@ applyRestriction(GlobalValue &GV, return; if (MustPreserveSymbols.count(Buffer)) MustPreserveList.push_back(GV.getName().data()); - if (DSOSymbols.count(Buffer)) - DSOList.push_back(GV.getName().data()); if (AsmUndefinedRefs.count(Buffer)) AsmUsed.insert(&GV); } @@ -352,18 +349,17 @@ void LTOCodeGenerator::applyScopeRestrictions() { // mark which symbols can not be internalized Mangler Mangler(TargetMach); std::vector<const char*> MustPreserveList; - std::vector<const char*> DSOList; SmallPtrSet<GlobalValue*, 8> AsmUsed; for (Module::iterator f = mergedModule->begin(), e = mergedModule->end(); f != e; ++f) - applyRestriction(*f, MustPreserveList, DSOList, AsmUsed, Mangler); + applyRestriction(*f, MustPreserveList, AsmUsed, Mangler); for (Module::global_iterator v = mergedModule->global_begin(), e = mergedModule->global_end(); v != e; ++v) - applyRestriction(*v, MustPreserveList, DSOList, AsmUsed, Mangler); + applyRestriction(*v, MustPreserveList, AsmUsed, Mangler); for (Module::alias_iterator a = mergedModule->alias_begin(), e = mergedModule->alias_end(); a != e; ++a) - applyRestriction(*a, MustPreserveList, DSOList, AsmUsed, Mangler); + applyRestriction(*a, MustPreserveList, AsmUsed, Mangler); GlobalVariable *LLVMCompilerUsed = mergedModule->getGlobalVariable("llvm.compiler.used"); @@ -391,7 +387,7 @@ void LTOCodeGenerator::applyScopeRestrictions() { LLVMCompilerUsed->setSection("llvm.metadata"); } - passes.add(createInternalizePass(MustPreserveList, DSOList)); + passes.add(createInternalizePass(MustPreserveList)); // apply scope restrictions passes.run(*mergedModule); diff --git a/lib/LTO/LTOModule.cpp b/lib/LTO/LTOModule.cpp index db9b9c9..91240aa 100644 --- a/lib/LTO/LTOModule.cpp +++ b/lib/LTO/LTOModule.cpp @@ -38,6 +38,7 @@ #include "llvm/Support/TargetSelect.h" #include "llvm/Support/system_error.h" #include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Transforms/Utils/GlobalStatus.h" using namespace llvm; LTOModule::LTOModule(llvm::Module *m, llvm::TargetMachine *t) @@ -162,6 +163,8 @@ LTOModule *LTOModule::makeLTOModule(MemoryBuffer *buffer, TargetMachine *target = march->createTargetMachine(TripleStr, CPU, FeatureStr, options); + m->MaterializeAllPermanently(); + LTOModule *Ret = new LTOModule(m.take(), target); if (Ret->parseSymbols(errMsg)) { delete Ret; @@ -333,6 +336,25 @@ void LTOModule::addDefinedFunctionSymbol(const Function *f) { addDefinedSymbol(f, true); } +static bool canBeHidden(const GlobalValue *GV) { + GlobalValue::LinkageTypes L = GV->getLinkage(); + + if (L == GlobalValue::LinkOnceODRAutoHideLinkage) + return true; + + if (L != GlobalValue::LinkOnceODRLinkage) + return false; + + if (GV->hasUnnamedAddr()) + return true; + + GlobalStatus GS; + if (GlobalStatus::analyzeGlobal(GV, GS)) + return false; + + return !GS.IsCompared; +} + /// addDefinedSymbol - Add a defined symbol to the list. void LTOModule::addDefinedSymbol(const GlobalValue *def, bool isFunction) { // ignore all llvm.* symbols @@ -372,12 +394,12 @@ void LTOModule::addDefinedSymbol(const GlobalValue *def, bool isFunction) { attr |= LTO_SYMBOL_SCOPE_HIDDEN; else if (def->hasProtectedVisibility()) attr |= LTO_SYMBOL_SCOPE_PROTECTED; + else if (canBeHidden(def)) + attr |= LTO_SYMBOL_SCOPE_DEFAULT_CAN_BE_HIDDEN; else if (def->hasExternalLinkage() || def->hasWeakLinkage() || def->hasLinkOnceLinkage() || def->hasCommonLinkage() || def->hasLinkerPrivateWeakLinkage()) attr |= LTO_SYMBOL_SCOPE_DEFAULT; - else if (def->hasLinkOnceODRAutoHideLinkage()) - attr |= LTO_SYMBOL_SCOPE_DEFAULT_CAN_BE_HIDDEN; else attr |= LTO_SYMBOL_SCOPE_INTERNAL; diff --git a/lib/Transforms/IPO/IPO.cpp b/lib/Transforms/IPO/IPO.cpp index 5f26bac..5d563d8 100644 --- a/lib/Transforms/IPO/IPO.cpp +++ b/lib/Transforms/IPO/IPO.cpp @@ -98,7 +98,7 @@ void LLVMAddInternalizePass(LLVMPassManagerRef PM, unsigned AllButMain) { std::vector<const char *> Export; if (AllButMain) Export.push_back("main"); - unwrap(PM)->add(createInternalizePass(Export, None)); + unwrap(PM)->add(createInternalizePass(Export)); } void LLVMAddStripDeadPrototypesPass(LLVMPassManagerRef PM) { diff --git a/lib/Transforms/IPO/Internalize.cpp b/lib/Transforms/IPO/Internalize.cpp index e615918..64e2ced 100644 --- a/lib/Transforms/IPO/Internalize.cpp +++ b/lib/Transforms/IPO/Internalize.cpp @@ -11,18 +11,11 @@ // If the function or variable is not in the list of external names given to // the pass it is marked as internal. // -// This transformation would not be legal or profitable in a regular -// compilation, but it gets extra information from the linker about what is safe -// or profitable. +// This transformation would not be legal in a regular compilation, but it gets +// extra information from the linker about what is safe. // -// As an example of a normally illegal transformation: Internalizing a function -// with external linkage. Only if we are told it is only used from within this -// module, it is safe to do it. -// -// On the profitability side: It is always legal to internalize a linkonce_odr -// whose address is not used. Doing so normally would introduce code bloat, but -// if we are told by the linker that the only use of this would be for a -// DSO symbol table, it is profitable to hide it. +// For example: Internalizing a function with external linkage. Only if we are +// told it is only used from within this module, it is safe to do it. // //===----------------------------------------------------------------------===// @@ -58,20 +51,13 @@ APIList("internalize-public-api-list", cl::value_desc("list"), cl::desc("A list of symbol names to preserve"), cl::CommaSeparated); -static cl::list<std::string> -DSOList("internalize-dso-list", cl::value_desc("list"), - cl::desc("A list of symbol names need for a dso symbol table"), - cl::CommaSeparated); - namespace { class InternalizePass : public ModulePass { std::set<std::string> ExternalNames; - std::set<std::string> DSONames; public: static char ID; // Pass identification, replacement for typeid explicit InternalizePass(); - explicit InternalizePass(ArrayRef<const char *> ExportList, - ArrayRef<const char *> DSOList); + explicit InternalizePass(ArrayRef<const char *> ExportList); void LoadFile(const char *Filename); virtual bool runOnModule(Module &M); @@ -92,21 +78,15 @@ InternalizePass::InternalizePass() if (!APIFile.empty()) // If a filename is specified, use it. LoadFile(APIFile.c_str()); ExternalNames.insert(APIList.begin(), APIList.end()); - DSONames.insert(DSOList.begin(), DSOList.end()); } -InternalizePass::InternalizePass(ArrayRef<const char *> ExportList, - ArrayRef<const char *> DSOList) +InternalizePass::InternalizePass(ArrayRef<const char *> ExportList) : ModulePass(ID){ initializeInternalizePassPass(*PassRegistry::getPassRegistry()); for(ArrayRef<const char *>::const_iterator itr = ExportList.begin(); itr != ExportList.end(); itr++) { ExternalNames.insert(*itr); } - for(ArrayRef<const char *>::const_iterator itr = DSOList.begin(); - itr != DSOList.end(); itr++) { - DSONames.insert(*itr); - } } void InternalizePass::LoadFile(const char *Filename) { @@ -126,8 +106,7 @@ void InternalizePass::LoadFile(const char *Filename) { } static bool shouldInternalize(const GlobalValue &GV, - const std::set<std::string> &ExternalNames, - const std::set<std::string> &DSONames) { + const std::set<std::string> &ExternalNames) { // Function must be defined here if (GV.isDeclaration()) return false; @@ -144,23 +123,7 @@ static bool shouldInternalize(const GlobalValue &GV, if (ExternalNames.count(GV.getName())) return false; - // Not needed for the symbol table? - if (!DSONames.count(GV.getName())) - return true; - - // Not a linkonce. Someone can depend on it being on the symbol table. - if (!GV.hasLinkOnceLinkage()) - return false; - - // The address is not important, we can hide it. - if (GV.hasUnnamedAddr()) - return true; - - GlobalStatus GS; - if (GlobalStatus::analyzeGlobal(&GV, GS)) - return false; - - return !GS.IsCompared; + return true; } bool InternalizePass::runOnModule(Module &M) { @@ -189,7 +152,7 @@ bool InternalizePass::runOnModule(Module &M) { // Mark all functions not in the api as internal. // FIXME: maybe use private linkage? for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) { - if (!shouldInternalize(*I, ExternalNames, DSONames)) + if (!shouldInternalize(*I, ExternalNames)) continue; I->setLinkage(GlobalValue::InternalLinkage); @@ -226,7 +189,7 @@ bool InternalizePass::runOnModule(Module &M) { // FIXME: maybe use private linkage? for (Module::global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I) { - if (!shouldInternalize(*I, ExternalNames, DSONames)) + if (!shouldInternalize(*I, ExternalNames)) continue; I->setLinkage(GlobalValue::InternalLinkage); @@ -238,7 +201,7 @@ bool InternalizePass::runOnModule(Module &M) { // Mark all aliases that are not in the api as internal as well. for (Module::alias_iterator I = M.alias_begin(), E = M.alias_end(); I != E; ++I) { - if (!shouldInternalize(*I, ExternalNames, DSONames)) + if (!shouldInternalize(*I, ExternalNames)) continue; I->setLinkage(GlobalValue::InternalLinkage); @@ -254,7 +217,6 @@ ModulePass *llvm::createInternalizePass() { return new InternalizePass(); } -ModulePass *llvm::createInternalizePass(ArrayRef<const char *> ExportList, - ArrayRef<const char *> DSOList) { - return new InternalizePass(ExportList, DSOList); +ModulePass *llvm::createInternalizePass(ArrayRef<const char *> ExportList) { + return new InternalizePass(ExportList); } diff --git a/lib/Transforms/IPO/PassManagerBuilder.cpp b/lib/Transforms/IPO/PassManagerBuilder.cpp index 0017c1b..1386201 100644 --- a/lib/Transforms/IPO/PassManagerBuilder.cpp +++ b/lib/Transforms/IPO/PassManagerBuilder.cpp @@ -277,7 +277,7 @@ void PassManagerBuilder::populateLTOPassManager(PassManagerBase &PM, // for a main function. If main is defined, mark all other functions // internal. if (Internalize) - PM.add(createInternalizePass("main", None)); + PM.add(createInternalizePass("main")); // Propagate constants at call sites into the functions they call. This // opens opportunities for globalopt (and inlining) by substituting function diff --git a/test/Transforms/Internalize/linkonce_odr_func.ll b/test/LTO/linkonce_odr_func.ll index c82acc0..ab96fca 100644 --- a/test/Transforms/Internalize/linkonce_odr_func.ll +++ b/test/LTO/linkonce_odr_func.ll @@ -1,27 +1,32 @@ -; RUN: opt < %s -internalize -internalize-dso-list foo1,foo2,foo3,foo4 -S | FileCheck %s +; RUN: llvm-as < %s >%t1 +; RUN: llvm-lto -o %t2 -dso-symbol=foo1 -dso-symbol=foo2 -dso-symbol=foo3 \ +; RUN: -dso-symbol=foo4 %t1 -disable-opt +; RUN: llvm-nm %t2 | FileCheck %s -; CHECK: define internal void @foo1( +; CHECK: t foo1 define linkonce_odr void @foo1() noinline { ret void } -; CHECK: define linkonce_odr void @foo2( +; CHECK: W foo2 define linkonce_odr void @foo2() noinline { ret void } -; CHECK: define internal void @foo3( +; CHECK: t foo3 define linkonce_odr void @foo3() noinline { ret void } -; CHECK: define linkonce_odr void @foo4( +; CHECK: W foo4 define linkonce_odr void @foo4() noinline { ret void } declare void @f(void()*) +declare void @p() + define void @bar() { bb0: call void @foo1() @@ -32,6 +37,6 @@ bb1: bb2: ret void clean: - landingpad i32 personality i8* null cleanup + landingpad {i32, i32} personality void()* @p cleanup ret void } diff --git a/test/Transforms/Internalize/lists.ll b/test/Transforms/Internalize/lists.ll index 3ebf0ed..83e441a2 100644 --- a/test/Transforms/Internalize/lists.ll +++ b/test/Transforms/Internalize/lists.ll @@ -13,10 +13,6 @@ ; -file and -list options should be merged, the apifile contains foo and j ; RUN: opt < %s -internalize -internalize-public-api-list bar -internalize-public-api-file %S/apifile -S | FileCheck --check-prefix=FOO_J_AND_BAR %s -; Put zed1 and zed2 in the symbol table. If the address is not relevant, we -; internalize them. -; RUN: opt < %s -internalize -internalize-dso-list zed1,zed2,zed3 -S | FileCheck --check-prefix=ZEDS %s - ; ALL: @i = internal global ; FOO_AND_J: @i = internal global ; FOO_AND_BAR: @i = internal global @@ -29,18 +25,6 @@ ; FOO_J_AND_BAR: @j = global @j = global i32 0 -; ZEDS: @zed1 = internal global i32 42 -@zed1 = linkonce_odr global i32 42 - -; ZEDS: @zed2 = internal unnamed_addr global i32 42 -@zed2 = linkonce_odr unnamed_addr global i32 42 - -; ZEDS: @zed3 = linkonce_odr global i32 42 -@zed3 = linkonce_odr global i32 42 -define i32* @get_zed3() { - ret i32* @zed3 -} - ; ALL: define internal void @main() { ; FOO_AND_J: define internal void @main() { ; FOO_AND_BAR: define internal void @main() { diff --git a/tools/gold/gold-plugin.cpp b/tools/gold/gold-plugin.cpp index 360ec07..0e3bad2 100644 --- a/tools/gold/gold-plugin.cpp +++ b/tools/gold/gold-plugin.cpp @@ -15,6 +15,7 @@ #include "llvm/Config/config.h" // plugin-api.h requires HAVE_STDINT_H #include "plugin-api.h" #include "llvm-c/lto.h" +#include "llvm/ADT/StringSet.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/Support/Errno.h" #include "llvm/Support/FileSystem.h" @@ -67,6 +68,7 @@ namespace { std::list<claimed_file> Modules; std::vector<std::string> Cleanup; lto_code_gen_t code_gen = NULL; + StringSet<> CannotBeHidden; } namespace options { @@ -297,6 +299,9 @@ static ld_plugin_status claim_file_hook(const ld_plugin_input_file *file, sym.version = NULL; int scope = attrs & LTO_SYMBOL_SCOPE_MASK; + bool CanBeHidden = scope == LTO_SYMBOL_SCOPE_DEFAULT_CAN_BE_HIDDEN; + if (!CanBeHidden) + CannotBeHidden.insert(sym.name); switch (scope) { case LTO_SYMBOL_SCOPE_HIDDEN: sym.visibility = LDPV_HIDDEN; @@ -306,6 +311,7 @@ static ld_plugin_status claim_file_hook(const ld_plugin_input_file *file, break; case 0: // extern case LTO_SYMBOL_SCOPE_DEFAULT: + case LTO_SYMBOL_SCOPE_DEFAULT_CAN_BE_HIDDEN: sym.visibility = LDPV_DEFAULT; break; default: @@ -364,6 +370,14 @@ static ld_plugin_status claim_file_hook(const ld_plugin_input_file *file, return LDPS_OK; } +static bool mustPreserve(const claimed_file &F, int i) { + if (F.syms[i].resolution == LDPR_PREVAILING_DEF) + return true; + if (F.syms[i].resolution == LDPR_PREVAILING_DEF_IRONLY_EXP) + return CannotBeHidden.count(F.syms[i].name); + return false; +} + /// all_symbols_read_hook - gold informs us that all symbols have been read. /// At this point, we use get_symbols to see if any of our definitions have /// been overridden by a native object file. Then, perform optimization and @@ -386,16 +400,11 @@ static ld_plugin_status all_symbols_read_hook(void) { continue; (*get_symbols)(I->handle, I->syms.size(), &I->syms[0]); for (unsigned i = 0, e = I->syms.size(); i != e; i++) { - if (I->syms[i].resolution == LDPR_PREVAILING_DEF) { + if (mustPreserve(*I, i)) { lto_codegen_add_must_preserve_symbol(code_gen, I->syms[i].name); if (options::generate_api_file) api_file << I->syms[i].name << "\n"; - } else if (I->syms[i].resolution == LDPR_PREVAILING_DEF_IRONLY_EXP) { - lto_codegen_add_dso_symbol(code_gen, I->syms[i].name); - - if (options::generate_api_file) - api_file << I->syms[i].name << " dso only\n"; } } } diff --git a/tools/llvm-lto/llvm-lto.cpp b/tools/llvm-lto/llvm-lto.cpp index bce903f..0fc68ae 100644 --- a/tools/llvm-lto/llvm-lto.cpp +++ b/tools/llvm-lto/llvm-lto.cpp @@ -12,6 +12,7 @@ // //===----------------------------------------------------------------------===// +#include "llvm/ADT/StringSet.h" #include "llvm/CodeGen/CommandFlags.h" #include "llvm/LTO/LTOCodeGenerator.h" #include "llvm/LTO/LTOModule.h" @@ -55,6 +56,12 @@ DSOSymbols("dso-symbol", cl::desc("Symbol to put in the symtab in the resulting dso"), cl::ZeroOrMore); +namespace { +struct ModuleInfo { + std::vector<bool> CanBeHidden; +}; +} + int main(int argc, char **argv) { // Print a stack trace if we signal out. sys::PrintStackTraceOnErrorSignal(); @@ -99,6 +106,12 @@ int main(int argc, char **argv) { CodeGen.setDebugInfo(LTO_DEBUG_MODEL_DWARF); CodeGen.setTargetOptions(Options); + llvm::StringSet<llvm::MallocAllocator> DSOSymbolsSet; + for (unsigned i = 0; i < DSOSymbols.size(); ++i) + DSOSymbolsSet.insert(DSOSymbols[i]); + + std::vector<std::string> KeptDSOSyms; + for (unsigned i = BaseArg; i < InputFilenames.size(); ++i) { std::string error; OwningPtr<LTOModule> Module(LTOModule::makeLTOModule(InputFilenames[i].c_str(), @@ -115,6 +128,17 @@ int main(int argc, char **argv) { << "': " << error << "\n"; return 1; } + + unsigned NumSyms = Module->getSymbolCount(); + for (unsigned I = 0; I < NumSyms; ++I) { + StringRef Name = Module->getSymbolName(I); + if (!DSOSymbolsSet.count(Name)) + continue; + lto_symbol_attributes Attrs = Module->getSymbolAttributes(I); + unsigned Scope = Attrs & LTO_SYMBOL_SCOPE_MASK; + if (Scope != LTO_SYMBOL_SCOPE_DEFAULT_CAN_BE_HIDDEN) + KeptDSOSyms.push_back(Name); + } } // Add all the exported symbols to the table of symbols to preserve. @@ -122,8 +146,8 @@ int main(int argc, char **argv) { CodeGen.addMustPreserveSymbol(ExportedSymbols[i].c_str()); // Add all the dso symbols to the table of symbols to expose. - for (unsigned i = 0; i < DSOSymbols.size(); ++i) - CodeGen.addDSOSymbol(DSOSymbols[i].c_str()); + for (unsigned i = 0; i < KeptDSOSyms.size(); ++i) + CodeGen.addMustPreserveSymbol(KeptDSOSyms[i].c_str()); if (!OutputFilename.empty()) { size_t len = 0; diff --git a/tools/lto/lto.cpp b/tools/lto/lto.cpp index a3acd4c..7bfddcd 100644 --- a/tools/lto/lto.cpp +++ b/tools/lto/lto.cpp @@ -260,10 +260,6 @@ void lto_codegen_add_must_preserve_symbol(lto_code_gen_t cg, cg->addMustPreserveSymbol(symbol); } -void lto_codegen_add_dso_symbol(lto_code_gen_t cg, const char *symbol) { - cg->addDSOSymbol(symbol); -} - /// lto_codegen_write_merged_modules - Writes a new file at the specified path /// that contains the merged contents of all modules added so far. Returns true /// on error (check lto_get_error_message() for details). diff --git a/tools/lto/lto.exports b/tools/lto/lto.exports index c0e220b..46d0d74 100644 --- a/tools/lto/lto.exports +++ b/tools/lto/lto.exports @@ -15,7 +15,6 @@ lto_module_is_object_file_for_target lto_module_is_object_file_in_memory lto_module_is_object_file_in_memory_for_target lto_module_dispose -lto_codegen_add_dso_symbol lto_codegen_add_module lto_codegen_add_must_preserve_symbol lto_codegen_compile |