diff --git a/lld/COFF/COFFLinkerContext.h b/lld/COFF/COFFLinkerContext.h index bdd625b8c3916..8322f829d4055 100644 --- a/lld/COFF/COFFLinkerContext.h +++ b/lld/COFF/COFFLinkerContext.h @@ -56,7 +56,6 @@ class COFFLinkerContext : public CommonLinkerContext { std::vector objFileInstances; std::map pdbInputFileInstances; std::vector importFileInstances; - std::vector bitcodeFileInstances; MergeChunk *mergeChunkInstances[Log2MaxSectionAlignment + 1] = {}; diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp index 8b1a8dc3e5af7..898c6c17d2062 100644 --- a/lld/COFF/Driver.cpp +++ b/lld/COFF/Driver.cpp @@ -218,7 +218,7 @@ void LinkerDriver::addFile(InputFile *file) { << " linked in after " "doing LTO compilation."; } - ctx.bitcodeFileInstances.push_back(f); + f->symtab.bitcodeFileInstances.push_back(f); } else if (auto *f = dyn_cast(file)) { ctx.importFileInstances.push_back(f); } @@ -285,7 +285,7 @@ void LinkerDriver::addBuffer(std::unique_ptr mb, addFile(make(ctx, mbref)); break; case file_magic::bitcode: - addFile(make(ctx, mbref, "", 0, lazy)); + addFile(BitcodeFile::create(ctx, mbref, "", 0, lazy)); break; case file_magic::coff_object: case file_magic::coff_import_library: @@ -374,8 +374,8 @@ void LinkerDriver::addArchiveBuffer(MemoryBufferRef mb, StringRef symName, if (magic == file_magic::coff_object) { obj = ObjFile::create(ctx, mb); } else if (magic == file_magic::bitcode) { - obj = - make(ctx, mb, parentName, offsetInArchive, /*lazy=*/false); + obj = BitcodeFile::create(ctx, mb, parentName, offsetInArchive, + /*lazy=*/false); } else if (magic == file_magic::coff_cl_gl_object) { Err(ctx) << mb.getBufferIdentifier() << ": is not a native COFF file. Recompile without /GL?"; @@ -2571,19 +2571,19 @@ void LinkerDriver::linkerMain(ArrayRef argsArr) { } } - // If any inputs are bitcode files, the LTO code generator may create - // references to library functions that are not explicit in the bitcode - // file's symbol table. If any of those library functions are defined in a - // bitcode file in an archive member, we need to arrange to use LTO to - // compile those archive members by adding them to the link beforehand. - if (!ctx.bitcodeFileInstances.empty()) { - llvm::Triple TT( - ctx.bitcodeFileInstances.front()->obj->getTargetTriple()); - for (auto *s : lto::LTO::getRuntimeLibcallSymbols(TT)) - ctx.symtab.addLibcall(s); - } - ctx.forEachSymtab([&](SymbolTable &symtab) { + // If any inputs are bitcode files, the LTO code generator may create + // references to library functions that are not explicit in the bitcode + // file's symbol table. If any of those library functions are defined in + // a bitcode file in an archive member, we need to arrange to use LTO to + // compile those archive members by adding them to the link beforehand. + if (!symtab.bitcodeFileInstances.empty()) { + llvm::Triple TT( + symtab.bitcodeFileInstances.front()->obj->getTargetTriple()); + for (auto *s : lto::LTO::getRuntimeLibcallSymbols(TT)) + symtab.addLibcall(s); + } + // Windows specific -- if __load_config_used can be resolved, resolve // it. if (symtab.findUnderscore("_load_config_used")) @@ -2639,8 +2639,11 @@ void LinkerDriver::linkerMain(ArrayRef argsArr) { // If we are going to do codegen for link-time optimization, check for // unresolvable symbols first, so we don't spend time generating code that // will fail to link anyway. - if (!ctx.bitcodeFileInstances.empty() && !config->forceUnresolved) - ctx.symtab.reportUnresolvable(); + if (!config->forceUnresolved) + ctx.forEachSymtab([](SymbolTable &symtab) { + if (!symtab.bitcodeFileInstances.empty()) + symtab.reportUnresolvable(); + }); if (errorCount()) return; @@ -2655,7 +2658,7 @@ void LinkerDriver::linkerMain(ArrayRef argsArr) { // link those files (unless -thinlto-index-only was given, in which case we // resolve symbols and write indices, but don't generate native code or link). ltoCompilationDone = true; - ctx.symtab.compileBitcodeFiles(); + ctx.forEachSymtab([](SymbolTable &symtab) { symtab.compileBitcodeFiles(); }); if (Defined *d = dyn_cast_or_null(ctx.symtab.findUnderscore("_tls_used"))) diff --git a/lld/COFF/InputFiles.cpp b/lld/COFF/InputFiles.cpp index 66641ff9dcc1f..5ee73d4dc4f8b 100644 --- a/lld/COFF/InputFiles.cpp +++ b/lld/COFF/InputFiles.cpp @@ -1229,10 +1229,15 @@ void ImportFile::parse() { } } -BitcodeFile::BitcodeFile(COFFLinkerContext &ctx, MemoryBufferRef mb, - StringRef archiveName, uint64_t offsetInArchive, - bool lazy) - : InputFile(ctx.symtab, BitcodeKind, mb, lazy) { +BitcodeFile::BitcodeFile(SymbolTable &symtab, MemoryBufferRef mb, + std::unique_ptr &o, bool lazy) + : InputFile(symtab, BitcodeKind, mb, lazy) { + obj.swap(o); +} + +BitcodeFile *BitcodeFile::create(COFFLinkerContext &ctx, MemoryBufferRef mb, + StringRef archiveName, + uint64_t offsetInArchive, bool lazy) { std::string path = mb.getBufferIdentifier().str(); if (ctx.config.thinLTOIndexOnly) path = replaceThinLTOSuffix(mb.getBufferIdentifier(), @@ -1252,7 +1257,9 @@ BitcodeFile::BitcodeFile(COFFLinkerContext &ctx, MemoryBufferRef mb, sys::path::filename(path) + utostr(offsetInArchive))); - obj = check(lto::InputFile::create(mbref)); + std::unique_ptr obj = check(lto::InputFile::create(mbref)); + return make(ctx.getSymtab(getMachineType(obj.get())), mb, obj, + lazy); } BitcodeFile::~BitcodeFile() = default; @@ -1329,7 +1336,7 @@ void BitcodeFile::parseLazy() { } } -MachineTypes BitcodeFile::getMachineType() const { +MachineTypes BitcodeFile::getMachineType(const llvm::lto::InputFile *obj) { Triple t(obj->getTargetTriple()); switch (t.getArch()) { case Triple::x86_64: diff --git a/lld/COFF/InputFiles.h b/lld/COFF/InputFiles.h index d3075c5e0a338..823561cda247a 100644 --- a/lld/COFF/InputFiles.h +++ b/lld/COFF/InputFiles.h @@ -386,13 +386,19 @@ class ImportFile : public InputFile { // Used for LTO. class BitcodeFile : public InputFile { public: - explicit BitcodeFile(COFFLinkerContext &ctx, MemoryBufferRef mb, - StringRef archiveName, uint64_t offsetInArchive, - bool lazy); + explicit BitcodeFile(SymbolTable &symtab, MemoryBufferRef mb, + std::unique_ptr &obj, bool lazy); ~BitcodeFile(); + + static BitcodeFile *create(COFFLinkerContext &ctx, MemoryBufferRef mb, + StringRef archiveName, uint64_t offsetInArchive, + bool lazy); static bool classof(const InputFile *f) { return f->kind() == BitcodeKind; } ArrayRef getSymbols() { return symbols; } - MachineTypes getMachineType() const override; + MachineTypes getMachineType() const override { + return getMachineType(obj.get()); + } + static MachineTypes getMachineType(const llvm::lto::InputFile *obj); void parseLazy(); std::unique_ptr obj; diff --git a/lld/COFF/SymbolTable.cpp b/lld/COFF/SymbolTable.cpp index 36dcd0dfe1389..bf965e8a2332d 100644 --- a/lld/COFF/SymbolTable.cpp +++ b/lld/COFF/SymbolTable.cpp @@ -347,8 +347,8 @@ bool SymbolTable::handleMinGWAutomaticImport(Symbol *sym, StringRef name) { /// defined symbol imported" diagnostic for symbols in localImports. /// objFiles and bitcodeFiles (if not nullptr) are used to report where /// undefined symbols are referenced. -static void reportProblemSymbols( - COFFLinkerContext &ctx, const SmallPtrSetImpl &undefs, +void SymbolTable::reportProblemSymbols( + const SmallPtrSetImpl &undefs, const DenseMap *localImports, bool needBitcodeFiles) { // Return early if there is nothing to report (which should be // the common case). @@ -392,7 +392,7 @@ static void reportProblemSymbols( processFile(file, file->getSymbols()); if (needBitcodeFiles) - for (BitcodeFile *file : ctx.bitcodeFileInstances) + for (BitcodeFile *file : bitcodeFileInstances) processFile(file, file->getSymbols()); for (const UndefinedDiag &undefDiag : undefDiags) @@ -423,8 +423,7 @@ void SymbolTable::reportUnresolvable() { undefs.insert(sym); } - reportProblemSymbols(ctx, undefs, - /* localImports */ nullptr, true); + reportProblemSymbols(undefs, /*localImports=*/nullptr, true); } bool SymbolTable::resolveRemainingUndefines() { @@ -506,8 +505,8 @@ bool SymbolTable::resolveRemainingUndefines() { } reportProblemSymbols( - ctx, undefs, - ctx.config.warnLocallyDefinedImported ? &localImports : nullptr, false); + undefs, ctx.config.warnLocallyDefinedImported ? &localImports : nullptr, + false); return foundLazy; } @@ -1124,13 +1123,13 @@ Symbol *SymbolTable::addUndefined(StringRef name) { } void SymbolTable::compileBitcodeFiles() { - if (ctx.bitcodeFileInstances.empty()) + if (bitcodeFileInstances.empty()) return; llvm::TimeTraceScope timeScope("Compile bitcode"); ScopedTimer t(ctx.ltoTimer); lto.reset(new BitcodeCompiler(ctx)); - for (BitcodeFile *f : ctx.bitcodeFileInstances) + for (BitcodeFile *f : bitcodeFileInstances) lto->add(*f); for (InputFile *newObj : lto->compile()) { ObjFile *obj = cast(newObj); diff --git a/lld/COFF/SymbolTable.h b/lld/COFF/SymbolTable.h index 9e316fcdbe630..66bca0d63e5ff 100644 --- a/lld/COFF/SymbolTable.h +++ b/lld/COFF/SymbolTable.h @@ -14,6 +14,7 @@ #include "llvm/ADT/CachedHashString.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseMapInfo.h" +#include "llvm/ADT/SmallPtrSet.h" #include "llvm/Support/raw_ostream.h" namespace llvm { @@ -155,6 +156,8 @@ class SymbolTable { callback(pair.second); } + std::vector bitcodeFileInstances; + DefinedRegular *loadConfigSym = nullptr; uint32_t loadConfigSize = 0; void initializeLoadConfig(); @@ -175,6 +178,11 @@ class SymbolTable { std::unique_ptr lto; std::vector> entryThunks; llvm::DenseMap exitThunks; + + void + reportProblemSymbols(const llvm::SmallPtrSetImpl &undefs, + const llvm::DenseMap *localImports, + bool needBitcodeFiles); }; std::vector getSymbolLocations(ObjFile *file, uint32_t symIndex); diff --git a/lld/test/COFF/lto-arm64x.ll b/lld/test/COFF/lto-arm64x.ll new file mode 100644 index 0000000000000..bbfc6b64c6fce --- /dev/null +++ b/lld/test/COFF/lto-arm64x.ll @@ -0,0 +1,47 @@ +; REQUIRES: aarch64, x86 +; RUN: split-file %s %t.dir && cd %t.dir + +; RUN: llvm-as arm64ec.ll -o arm64ec.obj +; RUN: llvm-as aarch64.ll -o aarch64.obj +; RUN: llvm-mc -filetype=obj -triple=aarch64-windows %S/Inputs/loadconfig-arm64.s -o loadconfig-arm64.obj +; RUN: llvm-mc -filetype=obj -triple=arm64ec-windows %S/Inputs/loadconfig-arm64ec.s -o loadconfig-arm64ec.obj + +; RUN: lld-link -machine:arm64x aarch64.obj arm64ec.obj loadconfig-arm64.obj loadconfig-arm64ec.obj -out:out.exe -subsystem:console +; RUN: llvm-objdump -d out.exe | FileCheck %s + +; CHECK: 0000000140001000 <.text>: +; CHECK-NEXT: 140001000: 52800020 mov w0, #0x1 // =1 +; CHECK-NEXT: 140001004: d65f03c0 ret +; CHECK-NEXT: ... +; CHECK-NEXT: 140002000: 00000009 udf #0x9 +; CHECK-NEXT: 140002004: 52800040 mov w0, #0x2 // =2 +; CHECK-NEXT: 140002008: d65f03c0 ret + +; CHECK: 0000000140003000 <.hexpthk>: +; CHECK-NEXT: 140003000: 48 8b c4 movq %rsp, %rax +; CHECK-NEXT: 140003003: 48 89 58 20 movq %rbx, 0x20(%rax) +; CHECK-NEXT: 140003007: 55 pushq %rbp +; CHECK-NEXT: 140003008: 5d popq %rbp +; CHECK-NEXT: 140003009: e9 f6 ef ff ff jmp 0x140002004 <.text+0x1004> +; CHECK-NEXT: 14000300e: cc int3 +; CHECK-NEXT: 14000300f: cc int3 + +#--- arm64ec.ll + +target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-p:64:64-i32:32-i64:64-i128:128-n32:64-S128-Fn32" +target triple = "arm64ec-unknown-windows-msvc" + +define dso_local i32 @mainCRTStartup() { +entry: + ret i32 2 +} + +#--- aarch64.ll + +target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-p:64:64-i32:32-i64:64-i128:128-n32:64-S128-Fn32" +target triple = "aarch64-unknown-windows-msvc" + +define dso_local i32 @mainCRTStartup() { +entry: + ret i32 1 +}