diff --git a/lld/MachO/LTO.cpp b/lld/MachO/LTO.cpp --- a/lld/MachO/LTO.cpp +++ b/lld/MachO/LTO.cpp @@ -36,6 +36,9 @@ c.PreCodeGenPassesHook = [](legacy::PassManager &pm) { pm.add(createObjCARCContractPass()); }; + if (config->saveTemps) + checkError(c.addSaveTemps(config->outputFile.str() + ".", + /*UseInputModulePath*/ true)); return c; } @@ -64,6 +67,8 @@ // be removed. r.Prevailing = !objSym.isUndefined() && sym->getFile() == &f; + r.VisibleToRegularObj = sym->isUsedInRegularObj; + // Un-define the symbol so that we don't get duplicate symbol errors when we // load the ObjFile emitted by LTO compilation. if (r.Prevailing) @@ -71,7 +76,6 @@ RefState::Strong); // TODO: set the other resolution configs properly - r.VisibleToRegularObj = true; } checkError(ltoObj->add(std::move(f.obj), resols)); } diff --git a/lld/MachO/SymbolTable.h b/lld/MachO/SymbolTable.h --- a/lld/MachO/SymbolTable.h +++ b/lld/MachO/SymbolTable.h @@ -59,7 +59,7 @@ Symbol *find(StringRef name) { return find(llvm::CachedHashStringRef(name)); } private: - std::pair insert(StringRef name); + std::pair insert(StringRef name, const InputFile *); llvm::DenseMap symMap; std::vector symVector; }; diff --git a/lld/MachO/SymbolTable.cpp b/lld/MachO/SymbolTable.cpp --- a/lld/MachO/SymbolTable.cpp +++ b/lld/MachO/SymbolTable.cpp @@ -24,17 +24,22 @@ return symVector[it->second]; } -std::pair SymbolTable::insert(StringRef name) { +std::pair SymbolTable::insert(StringRef name, + const InputFile *file) { auto p = symMap.insert({CachedHashStringRef(name), (int)symVector.size()}); - // Name already present in the symbol table. - if (!p.second) - return {symVector[p.first->second], false}; + Symbol *sym; + if (!p.second) { + // Name already present in the symbol table. + sym = symVector[p.first->second]; + } else { + // Name is a new symbol. + sym = reinterpret_cast(make()); + symVector.push_back(sym); + } - // Name is a new symbol. - Symbol *sym = reinterpret_cast(make()); - symVector.push_back(sym); - return {sym, true}; + sym->isUsedInRegularObj |= !file || isa(file); + return {sym, p.second}; } Defined *SymbolTable::addDefined(StringRef name, InputFile *file, @@ -43,7 +48,7 @@ Symbol *s; bool wasInserted; bool overridesWeakDef = false; - std::tie(s, wasInserted) = insert(name); + std::tie(s, wasInserted) = insert(name, file); if (!wasInserted) { if (auto *defined = dyn_cast(s)) { @@ -76,7 +81,7 @@ bool isWeakRef) { Symbol *s; bool wasInserted; - std::tie(s, wasInserted) = insert(name); + std::tie(s, wasInserted) = insert(name, file); RefState refState = isWeakRef ? RefState::Weak : RefState::Strong; @@ -95,7 +100,7 @@ uint32_t align, bool isPrivateExtern) { Symbol *s; bool wasInserted; - std::tie(s, wasInserted) = insert(name); + std::tie(s, wasInserted) = insert(name, file); if (!wasInserted) { if (auto *common = dyn_cast(s)) { @@ -116,7 +121,7 @@ bool isTlv) { Symbol *s; bool wasInserted; - std::tie(s, wasInserted) = insert(name); + std::tie(s, wasInserted) = insert(name, file); RefState refState = RefState::Unreferenced; if (!wasInserted) { @@ -148,7 +153,7 @@ const object::Archive::Symbol &sym) { Symbol *s; bool wasInserted; - std::tie(s, wasInserted) = insert(name); + std::tie(s, wasInserted) = insert(name, file); if (wasInserted) replaceSymbol(s, file, sym); diff --git a/lld/MachO/Symbols.h b/lld/MachO/Symbols.h --- a/lld/MachO/Symbols.h +++ b/lld/MachO/Symbols.h @@ -85,12 +85,17 @@ protected: Symbol(Kind k, StringRefZ name, InputFile *file) - : symbolKind(k), nameData(name.data), nameSize(name.size), file(file) {} + : symbolKind(k), nameData(name.data), nameSize(name.size), file(file), + isUsedInRegularObj(!file || isa(file)) {} Kind symbolKind; const char *nameData; mutable uint32_t nameSize; InputFile *file; + +public: + // True if this symbol was referenced by a regular (non-bitcode) object. + bool isUsedInRegularObj : 1; }; class Defined : public Symbol { @@ -246,7 +251,10 @@ assert(static_cast(static_cast(nullptr)) == nullptr && "Not a Symbol"); - return new (s) T(std::forward(arg)...); + bool isUsedInRegularObj = s->isUsedInRegularObj; + T *sym = new (s) T(std::forward(arg)...); + sym->isUsedInRegularObj |= isUsedInRegularObj; + return sym; } } // namespace macho diff --git a/lld/test/MachO/internalize.ll b/lld/test/MachO/internalize.ll new file mode 100644 --- /dev/null +++ b/lld/test/MachO/internalize.ll @@ -0,0 +1,72 @@ +; REQUIRES: x86 + +;; Check that we internalize bitcode symbols (only) where possible, i.e. when +;; they are not referenced by undefined symbols originating from non-bitcode +;; files. + +; RUN: rm -rf %t; split-file %s %t +; RUN: llvm-as %t/test.s -o %t/test.o +; RUN: llvm-as %t/baz.s -o %t/baz.o +; RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/regular.s -o %t/regular.o +; RUN: %lld -pie -lSystem %t/test.o %t/baz.o %t/regular.o -o %t/test -save-temps +; RUN: llvm-dis < %t/test.0.2.internalize.bc | FileCheck %s +; RUN: llvm-objdump --macho --syms %t/test | FileCheck %s --check-prefix=SYMTAB + +;; Check that main is not internalized. This covers the case of bitcode symbols +;; referenced by undefined symbols that don't belong to any InputFile. +; CHECK: define void @main() + +;; Check that the foo and bar functions are correctly internalized. +; CHECK: define internal void @bar() +; CHECK: define internal void @foo() + +;; Check that a bitcode symbol that is referenced by a regular object file isn't +;; internalized. +; CHECK: define void @used_in_regular_obj() + +;; Check that a bitcode symbol that is defined in another bitcode file gets +;; internalized. +; CHECK: define internal void @baz() + +; Check foo and bar are not emitted to the .symtab +; SYMTAB-LABEL: SYMBOL TABLE: +; SYMTAB-NEXT: g F __TEXT,__text _main +; SYMTAB-NEXT: g F __TEXT,__text _used_in_regular_obj +; SYMTAB-NEXT: g F __TEXT,__text __mh_execute_header +; SYMTAB-EMPTY: + +;--- test.s +target triple = "x86_64-apple-macosx10.15.0" +target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" + +declare void @baz() + +define void @main() { + call void @bar() + call void @baz() + ret void +} + +define void @bar() { + ret void +} + +define hidden void @foo() { + ret void +} + +define void @used_in_regular_obj() { + ret void +} + +;--- baz.s +target triple = "x86_64-apple-macosx10.15.0" +target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" + +define void @baz() { + ret void +} + +;--- regular.s +.data +.quad _used_in_regular_obj