[lld] [LLD][COFF] Process bitcode files separately for each symbol table on ARM64X (PR #123194)
Jacek Caban via llvm-commits
llvm-commits at lists.llvm.org
Thu Jan 16 04:35:52 PST 2025
https://github.com/cjacek created https://github.com/llvm/llvm-project/pull/123194
None
>From 4055dc3ab07f6a42508f29f36670346d20b8b014 Mon Sep 17 00:00:00 2001
From: Jacek Caban <jacek at codeweavers.com>
Date: Tue, 24 Dec 2024 23:40:55 +0100
Subject: [PATCH] [LLD][COFF] Process bitcode files separately for each symbol
table on ARM64X
---
lld/COFF/COFFLinkerContext.h | 1 -
lld/COFF/Driver.cpp | 41 ++++++++++++++++---------------
lld/COFF/InputFiles.cpp | 19 ++++++++++-----
lld/COFF/InputFiles.h | 14 ++++++++---
lld/COFF/SymbolTable.cpp | 17 ++++++-------
lld/COFF/SymbolTable.h | 8 ++++++
lld/test/COFF/lto-arm64x.ll | 47 ++++++++++++++++++++++++++++++++++++
7 files changed, 108 insertions(+), 39 deletions(-)
create mode 100644 lld/test/COFF/lto-arm64x.ll
diff --git a/lld/COFF/COFFLinkerContext.h b/lld/COFF/COFFLinkerContext.h
index bdd625b8c3916b..8322f829d40554 100644
--- a/lld/COFF/COFFLinkerContext.h
+++ b/lld/COFF/COFFLinkerContext.h
@@ -56,7 +56,6 @@ class COFFLinkerContext : public CommonLinkerContext {
std::vector<ObjFile *> objFileInstances;
std::map<std::string, PDBInputFile *> pdbInputFileInstances;
std::vector<ImportFile *> importFileInstances;
- std::vector<BitcodeFile *> bitcodeFileInstances;
MergeChunk *mergeChunkInstances[Log2MaxSectionAlignment + 1] = {};
diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp
index 8b1a8dc3e5af79..898c6c17d2062a 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<ImportFile>(file)) {
ctx.importFileInstances.push_back(f);
}
@@ -285,7 +285,7 @@ void LinkerDriver::addBuffer(std::unique_ptr<MemoryBuffer> mb,
addFile(make<ArchiveFile>(ctx, mbref));
break;
case file_magic::bitcode:
- addFile(make<BitcodeFile>(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<BitcodeFile>(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<const char *> 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<const char *> 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<const char *> 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<Defined>(ctx.symtab.findUnderscore("_tls_used")))
diff --git a/lld/COFF/InputFiles.cpp b/lld/COFF/InputFiles.cpp
index 66641ff9dcc1f0..5ee73d4dc4f8b7 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<lto::InputFile> &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<lto::InputFile> obj = check(lto::InputFile::create(mbref));
+ return make<BitcodeFile>(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 d3075c5e0a3380..823561cda247a0 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<llvm::lto::InputFile> &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<Symbol *> 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<llvm::lto::InputFile> obj;
diff --git a/lld/COFF/SymbolTable.cpp b/lld/COFF/SymbolTable.cpp
index 36dcd0dfe1389c..bf965e8a2332db 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<Symbol *> &undefs,
+void SymbolTable::reportProblemSymbols(
+ const SmallPtrSetImpl<Symbol *> &undefs,
const DenseMap<Symbol *, Symbol *> *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<ObjFile>(newObj);
diff --git a/lld/COFF/SymbolTable.h b/lld/COFF/SymbolTable.h
index 9e316fcdbe6301..66bca0d63e5ffc 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<BitcodeFile *> bitcodeFileInstances;
+
DefinedRegular *loadConfigSym = nullptr;
uint32_t loadConfigSize = 0;
void initializeLoadConfig();
@@ -175,6 +178,11 @@ class SymbolTable {
std::unique_ptr<BitcodeCompiler> lto;
std::vector<std::pair<Symbol *, Symbol *>> entryThunks;
llvm::DenseMap<Symbol *, Symbol *> exitThunks;
+
+ void
+ reportProblemSymbols(const llvm::SmallPtrSetImpl<Symbol *> &undefs,
+ const llvm::DenseMap<Symbol *, Symbol *> *localImports,
+ bool needBitcodeFiles);
};
std::vector<std::string> 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 00000000000000..bbfc6b64c6fcef
--- /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
+}
More information about the llvm-commits
mailing list