[lld][WebAssembly] Fix handling of comdat functions in init array.

When hidden symbols are discarded by comdat rules we still want to
create a local defined symbol, otherwise `Symbol::isDiscarded()` relies
on begin able to check `getChunk->discarded`.

This is a followup on rL362769. The comdat.ll test was previously GC'ing
the `__wasm_call_ctors` functions so `do_init` was not actually being
included in the link.  Once that function was included in triggered the
crash bug that this change addresses.

Fixes: https://github.com/emscripten-core/emscripten/issues/8981

Differential Revision: https://reviews.llvm.org/D64872

llvm-svn: 366358
This commit is contained in:
Sam Clegg 2019-07-17 18:43:36 +00:00
parent 48f5a43bcc
commit accad76c14
5 changed files with 25 additions and 18 deletions

View File

@ -12,8 +12,8 @@ define internal void @do_init() comdat($foo) {
ret void
}
@llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void
()*, i8* } { i32 65535, void ()* @do_init, i8* null }]
%0 = type { i32, void ()*, i8* }
@llvm.global_ctors = appending global [1 x %0 ] [%0 { i32 65535, void ()* @do_init, i8* null }]
; Everything above this is part of the `foo` comdat group

View File

@ -12,8 +12,8 @@ define internal void @do_init() comdat($foo) {
ret void
}
@llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void
()*, i8* } { i32 65535, void ()* @do_init, i8* null }]
%0 = type { i32, void ()*, i8* }
@llvm.global_ctors = appending global [1 x %0] [ %0 { i32 65535, void ()* @do_init, i8* getelementptr inbounds ([3 x i8], [3 x i8]* @constantData, i32 0, i32 0) }]
; Everything above this is part of the `foo` comdat group

View File

@ -6,10 +6,12 @@
target triple = "wasm32-unknown-unknown"
declare void @__wasm_call_ctors()
declare i32 @comdatFn()
define void @_start() {
entry:
call void @__wasm_call_ctors()
%call = call i32 @comdatFn()
ret void
}
@ -35,38 +37,44 @@ entry:
; CHECK-NEXT: Index: 0
; CHECK-NEXT: - Name: _start
; CHECK-NEXT: Kind: FUNCTION
; CHECK-NEXT: Index: 0
; CHECK-NEXT: Index: 1
; CHECK-NEXT: - Name: comdatFn
; CHECK-NEXT: Kind: FUNCTION
; CHECK-NEXT: Index: 1
; CHECK-NEXT: Index: 2
; CHECK-NEXT: - Name: constantData
; CHECK-NEXT: Kind: GLOBAL
; CHECK-NEXT: Index: 1
; CHECK-NEXT: - Name: callComdatFn1
; CHECK-NEXT: Kind: FUNCTION
; CHECK-NEXT: Index: 2
; CHECK-NEXT: Index: 4
; CHECK-NEXT: - Name: callComdatFn2
; CHECK-NEXT: Kind: FUNCTION
; CHECK-NEXT: Index: 3
; CHECK-NEXT: Index: 5
; CHECK-NEXT: - Type: ELEM
; CHECK-NEXT: Segments:
; CHECK-NEXT: - Offset:
; CHECK-NEXT: Opcode: I32_CONST
; CHECK-NEXT: Value: 1
; CHECK-NEXT: Functions: [ 1 ]
; CHECK-NEXT: Functions: [ 2 ]
; CHECK-NEXT: - Type: CODE
; CHECK-NEXT: Functions:
; CHECK-NEXT: - Index: 0
; CHECK-NEXT: Locals:
; CHECK-NEXT: Body: 1081808080001A0B
; CHECK-NEXT: Body: 10030B
; CHECK-NEXT: - Index: 1
; CHECK-NEXT: Locals:
; CHECK-NEXT: Body: 4180888080000B
; CHECK-NEXT: Body: 1080808080001082808080001A0B
; CHECK-NEXT: - Index: 2
; CHECK-NEXT: Locals:
; CHECK-NEXT: Body: 4181808080000B
; CHECK-NEXT: Body: 4180888080000B
; CHECK-NEXT: - Index: 3
; CHECK-NEXT: Locals:
; CHECK-NEXT: Body: 0B
; CHECK-NEXT: - Index: 4
; CHECK-NEXT: Locals:
; CHECK-NEXT: Body: 4181808080000B
; CHECK-NEXT: - Index: 5
; CHECK-NEXT: Locals:
; CHECK-NEXT: Body: 4181808080000B
; CHECK-NEXT: - Type: DATA
; CHECK-NEXT: Segments:

View File

@ -380,22 +380,20 @@ Symbol *ObjFile::createDefined(const WasmSymbol &sym) {
case WASM_SYMBOL_TYPE_FUNCTION: {
InputFunction *func =
functions[sym.Info.ElementIndex - wasmObj->getNumImportedFunctions()];
if (func->discarded)
return nullptr;
if (sym.isBindingLocal())
return make<DefinedFunction>(name, flags, this, func);
if (func->discarded)
return nullptr;
return symtab->addDefinedFunction(name, flags, this, func);
}
case WASM_SYMBOL_TYPE_DATA: {
InputSegment *seg = segments[sym.Info.DataRef.Segment];
if (seg->discarded)
return nullptr;
uint32_t offset = sym.Info.DataRef.Offset;
uint32_t size = sym.Info.DataRef.Size;
if (sym.isBindingLocal())
return make<DefinedData>(name, flags, this, seg, offset, size);
if (seg->discarded)
return nullptr;
return symtab->addDefinedData(name, flags, this, seg, offset, size);
}
case WASM_SYMBOL_TYPE_GLOBAL: {

View File

@ -821,6 +821,7 @@ void Writer::calculateInitFunctions() {
assert(sym->isLive());
if (*sym->signature != WasmSignature{{}, {}})
error("invalid signature for init func: " + toString(*sym));
LLVM_DEBUG(dbgs() << "initFunctions: " << toString(*sym) << "\n");
initFunctions.emplace_back(WasmInitEntry{sym, f.Priority});
}
}