Index: ELF/LTO.h =================================================================== --- ELF/LTO.h +++ ELF/LTO.h @@ -23,6 +23,7 @@ #include "lld/Core/LLVM.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringSet.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" #include "llvm/Linker/IRMover.h" @@ -44,6 +45,7 @@ llvm::IRMover Mover{Combined}; SmallString<0> OwningData; std::unique_ptr MB; + llvm::StringSet<> Internalize; }; } } Index: ELF/LTO.cpp =================================================================== --- ELF/LTO.cpp +++ ELF/LTO.cpp @@ -15,6 +15,7 @@ #include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/Analysis/TargetTransformInfo.h" #include "llvm/Bitcode/ReaderWriter.h" +#include "llvm/IR/AutoUpgrade.h" #include "llvm/IR/LegacyPassManager.h" #include "llvm/Linker/IRMover.h" #include "llvm/Support/StringSaver.h" @@ -22,6 +23,7 @@ #include "llvm/Target/TargetMachine.h" #include "llvm/Transforms/IPO.h" #include "llvm/Transforms/IPO/PassManagerBuilder.h" +#include "llvm/Transforms/Utils/ModuleUtils.h" using namespace llvm; using namespace llvm::object; @@ -75,6 +77,10 @@ unsigned BodyIndex = 0; ArrayRef Bodies = F.getSymbols(); + SmallPtrSet Used; + Module &M = Obj->getModule(); + collectUsedGlobalVariables(M, Used, /* CompilerUsed */ false); + for (const BasicSymbolRef &Sym : Obj->symbols()) { GlobalValue *GV = Obj->getSymbolGV(Sym.getRawDataRefImpl()); assert(GV); @@ -95,6 +101,10 @@ GV->setLinkage(GlobalValue::WeakODRLinkage); break; } + // FIXME: Is the check for shared libraries correct? + if (!Config->Shared && !Used.count(GV) && !B->isUsedInRegularObj()) + Internalize.insert(GV->getName()); + Keep.push_back(GV); } } @@ -104,10 +114,22 @@ [](GlobalValue &, IRMover::ValueAdder) {}); } +static void internalize(GlobalValue &GV) { + if (!GV.hasLocalLinkage()) + GV.setLinkage(GlobalValue::InternalLinkage); +} + // Merge all the bitcode files we have seen, codegen the result // and return the resulting ObjectFile. template std::unique_ptr> BitcodeCompiler::compile() { + + for (const auto &Name : Internalize) { + GlobalValue *GV = Combined.getNamedValue(Name.first()); + if (GV) + internalize(*GV); + } + if (Config->SaveTemps) saveBCFile(Combined, ".lto.bc"); Index: ELF/SymbolTable.cpp =================================================================== --- ELF/SymbolTable.cpp +++ ELF/SymbolTable.cpp @@ -214,6 +214,14 @@ SymbolBody *Existing = Sym->Body; + // Needed for internalize step of symbols. + if (auto *BC = dyn_cast(Existing)) + if (auto *U = dyn_cast(New)) + BC->setUsedInRegularObj(); + if (auto *U = dyn_cast(Existing)) + if (auto *BC = dyn_cast(New)) + BC->setUsedInRegularObj(); + if (Lazy *L = dyn_cast(Existing)) { if (auto *Undef = dyn_cast(New)) { addMemberFile(Undef, L); Index: ELF/Symbols.h =================================================================== --- ELF/Symbols.h +++ ELF/Symbols.h @@ -93,6 +93,8 @@ template typename ELFT::uint getVA(typename ELFT::uint Addend = 0) const; + void setUsedInRegularObj() { IsUsedInRegularObj = true; } + template typename ELFT::uint getGotVA() const; template typename ELFT::uint getGotPltVA() const; template typename ELFT::uint getPltVA() const; @@ -120,7 +122,8 @@ MustBeInDynSym(false), NeedsCopyOrPltAddr(false), Name(Name) { IsFunc = Type == llvm::ELF::STT_FUNC; IsTls = Type == llvm::ELF::STT_TLS; - IsUsedInRegularObj = K != SharedKind && K != LazyKind; + IsUsedInRegularObj = K != SharedKind && K != LazyKind && + K != DefinedBitcodeKind; } const unsigned SymbolKind : 8; @@ -317,7 +320,6 @@ std::unique_ptr getMember(); void setWeak() { IsWeak = true; } - void setUsedInRegularObj() { IsUsedInRegularObj = true; } private: ArchiveFile *File; Index: test/ELF/lto/internalize-basic.ll =================================================================== --- /dev/null +++ test/ELF/lto/internalize-basic.ll @@ -0,0 +1,18 @@ +; REQUIRES: x86 +; RUN: llvm-as %s -o %t.o +; RUN: ld.lld -m elf_x86_64 %t.o -o %t2 -save-temps +; RUN: llvm-dis %t2.lto.opt.bc -o - | FileCheck %s + +target triple = "x86_64-unknown-linux-gnu" +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" + +define void @_start() { + ret void +} + +define hidden void @foo() { + ret void +} + +; Check that foo function is correctly internalized. +; CHECK: define internal void @foo()