diff --git a/lld/wasm/LTO.cpp b/lld/wasm/LTO.cpp --- a/lld/wasm/LTO.cpp +++ b/lld/wasm/LTO.cpp @@ -35,6 +35,8 @@ #include #include +#define DEBUG_TYPE "lld" + using namespace llvm; namespace lld::wasm { @@ -105,6 +107,10 @@ r.VisibleToRegularObj = config->relocatable || sym->isUsedInRegularObj || sym->isNoStrip() || (r.Prevailing && sym->isExported()); + LLVM_DEBUG(llvm::dbgs() + << "LTO: VisibleToRegularObj: " << r.VisibleToRegularObj + << " Prevailing: " << r.Prevailing << " " << sym->getName() + << " (" << toString(*sym) << ")\n"); if (r.Prevailing) undefine(sym); diff --git a/lld/wasm/Writer.cpp b/lld/wasm/Writer.cpp --- a/lld/wasm/Writer.cpp +++ b/lld/wasm/Writer.cpp @@ -1636,6 +1636,9 @@ const WasmLinkingData &l = file->getWasmObj()->linkingData(); for (const WasmInitFunc &f : l.InitFunctions) { FunctionSymbol *sym = file->getFunctionSymbol(f.Symbol); + LLVM_DEBUG(llvm::dbgs() << "calculateInitFunctions: " << file->getName() + << ": " << toString(*sym) << "\n"); + assert(sym->isDefined()); // comdat exclusions can cause init functions be discarded. if (sym->isDiscarded() || !sym->isLive()) continue; diff --git a/llvm/lib/MC/WasmObjectWriter.cpp b/llvm/lib/MC/WasmObjectWriter.cpp --- a/llvm/lib/MC/WasmObjectWriter.cpp +++ b/llvm/lib/MC/WasmObjectWriter.cpp @@ -1907,8 +1907,14 @@ report_fatal_error("symbols in .init_array should exist in symtab"); if (!TargetSym.isFunction()) report_fatal_error("symbols in .init_array should be for functions"); - InitFuncs.push_back( - std::make_pair(Priority, TargetSym.getIndex())); + // For now, ignore init functions that are not defined within the module. + // Ideally undefined init functions should not occur, but they do seem + // to be showing up in some hard to reproduce cases involving LTO. + // FIXME: Remove this once we find the root cause of + // https://github.com/llvm/llvm-project/issues/62243 + if (TargetSym.isDefined()) { + InitFuncs.push_back(std::make_pair(Priority, TargetSym.getIndex())); + } } } diff --git a/llvm/test/MC/WebAssembly/basic-assembly.s b/llvm/test/MC/WebAssembly/basic-assembly.s --- a/llvm/test/MC/WebAssembly/basic-assembly.s +++ b/llvm/test/MC/WebAssembly/basic-assembly.s @@ -1,10 +1,12 @@ # RUN: llvm-mc -triple=wasm32-unknown-unknown -mattr=+tail-call,+reference-types,atomics,+simd128,+nontrapping-fptoint,+exception-handling < %s | FileCheck %s # Check that it converts to .o without errors, but don't check any output: # RUN: llvm-mc -triple=wasm32-unknown-unknown -filetype=obj -mattr=+tail-call,+reference-types,+atomics,+simd128,+nontrapping-fptoint,+exception-handling -o %t.o < %s +# RUN: obj2yaml %t.o | FileCheck %s --check-prefix=OBJ .functype something1 () -> () .functype something2 (i64) -> (i32, f64) .functype something3 () -> (i32) +.functype undefined_func () -> (i32) .globaltype __stack_pointer, i32 empty_func: @@ -143,6 +145,7 @@ .section .init_array.42,"",@ .p2align 2 .int32 test0 + .int32 undefined_func .ident "clang version 9.0.0 (trunk 364502) (llvm/trunk 364571)" @@ -282,9 +285,15 @@ # CHECK: .section .init_array.42,"",@ # CHECK-NEXT: .p2align 2 # CHECK-NEXT: .int32 test0 +# CHECK-NEXT: .int32 undefined_func # CHECK: .tabletype empty_eref_table, externref # CHECK-NEXT: empty_eref_table: # CHECK: .tabletype empty_fref_table, funcref # CHECK-NEXT: empty_fref_table: + +# OBJ: InitFunctions: +# OBJ-NEXT: - Priority: 42 +# OBJ-NEXT: Symbol: 1 +# OBJ-NEXT: ...