Skip to content

[lld][WebAssembly] Fix bitcode LTO order in archive parsing #73095

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Nov 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions lld/test/wasm/lto/Inputs/comdat_ordering1.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128"
target triple = "wasm32-unknown-unknown"

; Generated from this C++ code and simplified manually:
;
; int foo();
; inline int unused = foo();
;
; int main() {
; return foo();
; }

$unused = comdat any

@unused = linkonce_odr global i32 0, comdat, align 4
@_ZGV6unused = linkonce_odr global i32 0, comdat($unused), align 4
@llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 65535, ptr @__cxx_global_var_init, ptr @unused }]

define internal void @__cxx_global_var_init() comdat($unused) {
entry:
%0 = load i8, ptr @_ZGV6unused, align 4
%1 = and i8 %0, 1
%guard.uninitialized = icmp eq i8 %1, 0
br i1 %guard.uninitialized, label %init.check, label %init.end

init.check: ; preds = %entry
store i8 1, ptr @_ZGV6unused, align 4
%call = call i32 @foo()
store i32 %call, ptr @unused, align 4
br label %init.end

init.end: ; preds = %init.check, %entry
ret void
}

declare i32 @foo()

define i32 @main() {
entry:
%call = call i32 @foo()
ret i32 %call
}
39 changes: 39 additions & 0 deletions lld/test/wasm/lto/Inputs/comdat_ordering2.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128"
target triple = "wasm32-unknown-unknown"

; Generated from this C++ code and simplified manually:
;
; int foo();
; inline int unused = foo();
;
; int foo() {
; return 42;
; }

$unused = comdat any

@unused = linkonce_odr global i32 0, comdat, align 4
@_ZGV6unused = linkonce_odr global i32 0, comdat($unused), align 4
@llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 65535, ptr @__cxx_global_var_init, ptr @unused }]

define internal void @__cxx_global_var_init() comdat($unused) {
entry:
%0 = load i8, ptr @_ZGV6unused, align 4
%1 = and i8 %0, 1
%guard.uninitialized = icmp eq i8 %1, 0
br i1 %guard.uninitialized, label %init.check, label %init.end

init.check: ; preds = %entry
store i8 1, ptr @_ZGV6unused, align 4
%call = call i32 @foo()
store i32 %call, ptr @unused, align 4
br label %init.end

init.end: ; preds = %init.check, %entry
ret void
}

define i32 @foo() {
entry:
ret i32 42
}
19 changes: 19 additions & 0 deletions lld/test/wasm/lto/comdat_ordering.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
; Check if we handle a variable (here __cxx_global_var_init) in different LTO
; bitcode modules sharing a comdat.

; RUN: llvm-as %S/Inputs/comdat_ordering1.ll -o %t1.o
; RUN: llvm-as %S/Inputs/comdat_ordering2.ll -o %t2.o
; RUN: llvm-ar rcs %t1.a %t1.o
; RUN: llvm-ar rcs %t2.a %t2.o
; RUN: wasm-ld %t1.a %t2.a -o %t.wasm --no-entry --export=main --export=__wasm_call_ctors
; RUN: obj2yaml %t.wasm | FileCheck %s

; CHECK: - Type: CUSTOM
; CHECK-NEXT: Name: name
; CHECK-NEXT: FunctionNames:
; CHECK-NEXT: - Index: 0
; CHECK-NEXT: Name: __wasm_call_ctors
; CHECK-NEXT: - Index: 1
; CHECK-NEXT: Name: __cxx_global_var_init

; CHECK-NOT: Name: __cxx_global_var_init.2
4 changes: 3 additions & 1 deletion lld/wasm/SymbolTable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,10 @@ void SymbolTable::addFile(InputFile *file, StringRef symName) {

// LLVM bitcode file
if (auto *f = dyn_cast<BitcodeFile>(file)) {
f->parse(symName);
// This order, first adding to `bitcodeFiles` and then parsing is necessary.
// See https://github.com/llvm/llvm-project/pull/73095
bitcodeFiles.push_back(f);
f->parse(symName);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like a good change to me. The fact that ELF does it this way makes me even more confident this is correct:

ctx.bitcodeFiles.push_back(f);
f->parse();

return;
}

Expand Down