forked from OSchip/llvm-project
[lld][WebAssembly] Handle duplicate archive member names in ThinLTO
This entire change, including the test case, comes almost verbatim from the ELF driver. Fixes: https://github.com/emscripten-core/emscripten/issues/12763 Differential Revision: https://reviews.llvm.org/D112723
This commit is contained in:
parent
4da38c14d0
commit
28848e9e1b
|
@ -0,0 +1,14 @@
|
|||
; Copied from lld/test/ELF/lto/Inputs/thin1.ll
|
||||
|
||||
target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128"
|
||||
target triple = "wasm32-unknown-unknown"
|
||||
|
||||
define i32 @foo(i32 %goo) {
|
||||
entry:
|
||||
%goo.addr = alloca i32, align 4
|
||||
store i32 %goo, i32* %goo.addr, align 4
|
||||
%0 = load i32, i32* %goo.addr, align 4
|
||||
%1 = load i32, i32* %goo.addr, align 4
|
||||
%mul = mul nsw i32 %0, %1
|
||||
ret i32 %mul
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
; Copied from lld/test/ELF/lto/Inputs/thin2.ll
|
||||
|
||||
target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128"
|
||||
target triple = "wasm32-unknown-unknown"
|
||||
|
||||
define i32 @blah(i32 %meh) #0 {
|
||||
entry:
|
||||
%meh.addr = alloca i32, align 4
|
||||
store i32 %meh, i32* %meh.addr, align 4
|
||||
%0 = load i32, i32* %meh.addr, align 4
|
||||
%sub = sub nsw i32 %0, 48
|
||||
ret i32 %sub
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
; Copied from lld/test/ELF/lto/thinlto-thin-archive-collision.ll
|
||||
|
||||
; RUN: rm -fr %t && mkdir %t && cd %t
|
||||
; RUN: mkdir thinlto-archives thinlto-archives/a thinlto-archives/b
|
||||
; RUN: opt -thinlto-bc -o thinlto-archives/main.o %s
|
||||
; RUN: opt -thinlto-bc -o thinlto-archives/a/thin.o %S/Inputs/thin1.ll
|
||||
; RUN: opt -thinlto-bc -o thinlto-archives/b/thin.o %S/Inputs/thin2.ll
|
||||
; RUN: llvm-ar qcT thinlto-archives/thin.a thinlto-archives/a/thin.o thinlto-archives/b/thin.o
|
||||
; RUN: wasm-ld thinlto-archives/main.o thinlto-archives/thin.a -o thinlto-archives/main.exe --save-temps
|
||||
; RUN: FileCheck %s < thinlto-archives/main.exe.resolution.txt
|
||||
|
||||
; CHECK: thinlto-archives/main.o
|
||||
; CHECK: thinlto-archives/thin.a(thin.o at {{[1-9][0-9]+}})
|
||||
; CHECK-NEXT: -r=thinlto-archives/thin.a(thin.o at {{[1-9][0-9]+}}),foo,p
|
||||
; CHECK: thinlto-archives/thin.a(thin.o at {{[1-9][0-9]+}})
|
||||
; CHECK-NEXT: -r=thinlto-archives/thin.a(thin.o at {{[1-9][0-9]+}}),blah,p
|
||||
|
||||
target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128"
|
||||
target triple = "wasm32-unknown-unknown"
|
||||
|
||||
declare i32 @blah(i32 %meh)
|
||||
declare i32 @foo(i32 %goo)
|
||||
|
||||
define i32 @_start() {
|
||||
call i32 @foo(i32 0)
|
||||
call i32 @blah(i32 0)
|
||||
ret i32 0
|
||||
}
|
|
@ -17,6 +17,7 @@
|
|||
#include "lld/Common/Reproduce.h"
|
||||
#include "llvm/Object/Binary.h"
|
||||
#include "llvm/Object/Wasm.h"
|
||||
#include "llvm/Support/Path.h"
|
||||
#include "llvm/Support/TarWriter.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
|
@ -25,6 +26,7 @@
|
|||
using namespace llvm;
|
||||
using namespace llvm::object;
|
||||
using namespace llvm::wasm;
|
||||
using namespace llvm::sys;
|
||||
|
||||
namespace lld {
|
||||
|
||||
|
@ -71,7 +73,8 @@ Optional<MemoryBufferRef> readFile(StringRef path) {
|
|||
return mbref;
|
||||
}
|
||||
|
||||
InputFile *createObjectFile(MemoryBufferRef mb, StringRef archiveName) {
|
||||
InputFile *createObjectFile(MemoryBufferRef mb, StringRef archiveName,
|
||||
uint64_t offsetInArchive) {
|
||||
file_magic magic = identify_magic(mb.getBuffer());
|
||||
if (magic == file_magic::wasm_object) {
|
||||
std::unique_ptr<Binary> bin =
|
||||
|
@ -83,7 +86,7 @@ InputFile *createObjectFile(MemoryBufferRef mb, StringRef archiveName) {
|
|||
}
|
||||
|
||||
if (magic == file_magic::bitcode)
|
||||
return make<BitcodeFile>(mb, archiveName);
|
||||
return make<BitcodeFile>(mb, archiveName, offsetInArchive);
|
||||
|
||||
fatal("unknown file type: " + mb.getBufferIdentifier());
|
||||
}
|
||||
|
@ -709,7 +712,7 @@ void ArchiveFile::addMember(const Archive::Symbol *sym) {
|
|||
"could not get the buffer for the member defining symbol " +
|
||||
sym->getName());
|
||||
|
||||
InputFile *obj = createObjectFile(mb, getName());
|
||||
InputFile *obj = createObjectFile(mb, getName(), c.getChildOffset());
|
||||
symtab->addFile(obj);
|
||||
}
|
||||
|
||||
|
@ -748,6 +751,32 @@ static Symbol *createBitcodeSymbol(const std::vector<bool> &keptComdats,
|
|||
return symtab->addDefinedData(name, flags, &f, nullptr, 0, 0);
|
||||
}
|
||||
|
||||
BitcodeFile::BitcodeFile(MemoryBufferRef m, StringRef archiveName,
|
||||
uint64_t offsetInArchive)
|
||||
: InputFile(BitcodeKind, m) {
|
||||
this->archiveName = std::string(archiveName);
|
||||
|
||||
std::string path = mb.getBufferIdentifier().str();
|
||||
|
||||
// ThinLTO assumes that all MemoryBufferRefs given to it have a unique
|
||||
// name. If two archives define two members with the same name, this
|
||||
// causes a collision which result in only one of the objects being taken
|
||||
// into consideration at LTO time (which very likely causes undefined
|
||||
// symbols later in the link stage). So we append file offset to make
|
||||
// filename unique.
|
||||
StringRef name = archiveName.empty()
|
||||
? saver.save(path)
|
||||
: saver.save(archiveName + "(" + path::filename(path) +
|
||||
" at " + utostr(offsetInArchive) + ")");
|
||||
MemoryBufferRef mbref(mb.getBuffer(), name);
|
||||
|
||||
obj = check(lto::InputFile::create(mbref));
|
||||
|
||||
// If this isn't part of an archive, it's eagerly linked, so mark it live.
|
||||
if (archiveName.empty())
|
||||
markLive();
|
||||
}
|
||||
|
||||
bool BitcodeFile::doneLTO = false;
|
||||
|
||||
void BitcodeFile::parse() {
|
||||
|
@ -756,8 +785,6 @@ void BitcodeFile::parse() {
|
|||
return;
|
||||
}
|
||||
|
||||
obj = check(lto::InputFile::create(MemoryBufferRef(
|
||||
mb.getBuffer(), saver.save(archiveName + mb.getBufferIdentifier()))));
|
||||
Triple t(obj->getTargetTriple());
|
||||
if (!t.isWasm()) {
|
||||
error(toString(this) + ": machine type must be wasm32 or wasm64");
|
||||
|
|
|
@ -170,14 +170,8 @@ public:
|
|||
// .bc file
|
||||
class BitcodeFile : public InputFile {
|
||||
public:
|
||||
explicit BitcodeFile(MemoryBufferRef m, StringRef archiveName)
|
||||
: InputFile(BitcodeKind, m) {
|
||||
this->archiveName = std::string(archiveName);
|
||||
|
||||
// If this isn't part of an archive, it's eagerly linked, so mark it live.
|
||||
if (archiveName.empty())
|
||||
markLive();
|
||||
}
|
||||
BitcodeFile(MemoryBufferRef m, StringRef archiveName,
|
||||
uint64_t offsetInArchive);
|
||||
static bool classof(const InputFile *f) { return f->kind() == BitcodeKind; }
|
||||
|
||||
void parse();
|
||||
|
@ -194,7 +188,8 @@ inline bool isBitcode(MemoryBufferRef mb) {
|
|||
|
||||
// Will report a fatal() error if the input buffer is not a valid bitcode
|
||||
// or wasm object file.
|
||||
InputFile *createObjectFile(MemoryBufferRef mb, StringRef archiveName = "");
|
||||
InputFile *createObjectFile(MemoryBufferRef mb, StringRef archiveName = "",
|
||||
uint64_t offsetInArchive = 0);
|
||||
|
||||
// Opens a given file.
|
||||
llvm::Optional<MemoryBufferRef> readFile(StringRef path);
|
||||
|
|
Loading…
Reference in New Issue