diff --git a/lld/test/wasm/lto/Inputs/libcall-truncsfhf2.ll b/lld/test/wasm/lto/Inputs/libcall-truncsfhf2.ll new file mode 100644 --- /dev/null +++ b/lld/test/wasm/lto/Inputs/libcall-truncsfhf2.ll @@ -0,0 +1,6 @@ +target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" +target triple = "wasm32-unknown-unknown" + +define half @__truncsfhf2(float) { + ret half 0.0 +} diff --git a/lld/test/wasm/lto/libcall-truncsfhf2.ll b/lld/test/wasm/lto/libcall-truncsfhf2.ll new file mode 100644 --- /dev/null +++ b/lld/test/wasm/lto/libcall-truncsfhf2.ll @@ -0,0 +1,20 @@ +; RUN: llvm-as %s -o %t.o +; RUN: llvm-as %p/Inputs/libcall-truncsfhf2.ll -o %t.truncsfhf2.o +; RUN: rm -f %t.a +; RUN: llvm-ar rcs %t.a %t.truncsfhf2.o +; RUN: not wasm-ld --export-all %t.o %t.a -o %t.wasm 2>&1 | FileCheck %s + +target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" +target triple = "wasm32-unknown-unknown" + +@g_float = global float 0.0 +@g_half = global half 0.0 + +define void @_start() { + %val1 = load float, float* @g_float + %v0 = fptrunc float %val1 to half + store half %v0, half* @g_half + ret void +} + +; CHECK: wasm-ld: error: {{.*}}truncsfhf2.o: attempt to add bitcode file after LTO. diff --git a/lld/wasm/Driver.cpp b/lld/wasm/Driver.cpp --- a/lld/wasm/Driver.cpp +++ b/lld/wasm/Driver.cpp @@ -735,6 +735,8 @@ // This works like --undefined but also exports the symbol if its found for (auto *arg : args.filtered(OPT_export)) handleUndefined(arg->getValue()); + if (errorCount()) + return; Symbol *entrySym = nullptr; if (!config->relocatable && !config->entry.empty()) { diff --git a/lld/wasm/InputFiles.h b/lld/wasm/InputFiles.h --- a/lld/wasm/InputFiles.h +++ b/lld/wasm/InputFiles.h @@ -160,6 +160,10 @@ void parse(); std::unique_ptr obj; + + // Set to true once LTO is complete in order prevent further bitcode objects + // being added. + static bool doneLTO; }; inline bool isBitcode(MemoryBufferRef mb) { diff --git a/lld/wasm/InputFiles.cpp b/lld/wasm/InputFiles.cpp --- a/lld/wasm/InputFiles.cpp +++ b/lld/wasm/InputFiles.cpp @@ -536,7 +536,15 @@ return symtab->addDefinedData(name, flags, &f, nullptr, 0, 0); } +bool BitcodeFile::doneLTO = false; + void BitcodeFile::parse() { + if (doneLTO) { + error(toString(mb.getBufferIdentifier()) + + ": attempt to add bitcode file after LTO."); + return; + } + obj = check(lto::InputFile::create(MemoryBufferRef( mb.getBuffer(), saver.save(archiveName + mb.getBufferIdentifier())))); Triple t(obj->getTargetTriple()); diff --git a/lld/wasm/SymbolTable.cpp b/lld/wasm/SymbolTable.cpp --- a/lld/wasm/SymbolTable.cpp +++ b/lld/wasm/SymbolTable.cpp @@ -65,6 +65,9 @@ // Because all bitcode files that the program consists of are passed // to the compiler at once, it can do whole-program optimization. void SymbolTable::addCombinedLTOObject() { + // Prevent further LTO objects being included + BitcodeFile::doneLTO = true; + if (bitcodeFiles.empty()) return;