summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/llvm-c/lto.h9
-rw-r--r--include/llvm/LTO/LTOCodeGenerator.h6
-rw-r--r--include/llvm/Transforms/IPO.h18
-rw-r--r--lib/LTO/LTOCodeGenerator.cpp12
-rw-r--r--lib/LTO/LTOModule.cpp26
-rw-r--r--lib/Transforms/IPO/IPO.cpp2
-rw-r--r--lib/Transforms/IPO/Internalize.cpp64
-rw-r--r--lib/Transforms/IPO/PassManagerBuilder.cpp2
-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.ll16
-rw-r--r--tools/gold/gold-plugin.cpp21
-rw-r--r--tools/llvm-lto/llvm-lto.cpp28
-rw-r--r--tools/lto/lto.cpp4
-rw-r--r--tools/lto/lto.exports1
14 files changed, 96 insertions, 130 deletions
diff --git a/include/llvm-c/lto.h b/include/llvm-c/lto.h
index a09db24f98..89f54b7a7b 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 9f50770dcd..97a5066339 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 ed2823098a..7f51c516b9 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 c55eccb7e3..3c9a378962 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 db9b9c9dee..91240aa5a0 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 5f26bac2c8..5d563d8bbf 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 e61591870b..64e2cedfb1 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 0017c1b822..1386201094 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 c82acc0174..ab96fca477 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 3ebf0edf82..83e441a2df 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 360ec07e79..0e3bad2599 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 bce903fa16..0fc68ae3ad 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 a3acd4c950..7bfddcd9ec 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 c0e220bb24..46d0d74c82 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