diff --git a/lld/test/wasm/undefined-data.ll b/lld/test/wasm/undefined-data.ll deleted file mode 100644 --- a/lld/test/wasm/undefined-data.ll +++ /dev/null @@ -1,17 +0,0 @@ -; RUN: llc -filetype=obj %s -o %t.o -; RUN: not wasm-ld -o %t.wasm %t.o 2>&1 | FileCheck %s -check-prefix=UNDEF -; RUN: wasm-ld --allow-undefined -o %t.wasm %t.o -; RUN: not wasm-ld --shared -o %t.wasm %t.o 2>&1 | FileCheck %s -check-prefix=SHARED - -target triple = "wasm32-unknown-unknown" - -@data_external = external global i32 - -define i32 @_start() { -entry: - %0 = load i32, i32* @data_external, align 4 - ret i32 %0 -} - -; UNDEF: error: {{.*}}undefined-data.ll.tmp.o: undefined symbol: data_external -; SHARED: error: {{.*}}undefined-data.ll.tmp.o: relocation R_WASM_MEMORY_ADDR_LEB cannot be used against symbol data_external; recompile with -fPIC diff --git a/lld/test/wasm/undefined-data.s b/lld/test/wasm/undefined-data.s new file mode 100644 --- /dev/null +++ b/lld/test/wasm/undefined-data.s @@ -0,0 +1,15 @@ +# RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown -o %t.o %s +# RUN: not wasm-ld -o %t.wasm %t.o 2>&1 | FileCheck %s -check-prefix=UNDEF +# RUN: wasm-ld --allow-undefined -o %t.wasm %t.o +# RUN: not wasm-ld --shared -o %t.wasm %t.o 2>&1 | FileCheck %s -check-prefix=SHARED + +.globl _start +_start: + .functype _start () -> (i32) + i32.load data_external + end_function + +.size data_external, 4 + +# UNDEF: error: {{.*}}undefined-data.s.tmp.o: undefined symbol: data_external +# SHARED: error: {{.*}}undefined-data.s.tmp.o: relocation R_WASM_MEMORY_ADDR_LEB cannot be used against symbol data_external; recompile with -fPIC diff --git a/lld/test/wasm/undefined-weak-call.ll b/lld/test/wasm/undefined-weak-call.ll deleted file mode 100644 --- a/lld/test/wasm/undefined-weak-call.ll +++ /dev/null @@ -1,102 +0,0 @@ -; RUN: llc -filetype=obj %s -o %t.o -; RUN: wasm-ld --entry=callWeakFuncs --print-gc-sections %t.o \ -; RUN: -o %t.wasm 2>&1 | FileCheck -check-prefix=CHECK-GC %s -; RUN: obj2yaml %t.wasm | FileCheck %s - -; Check that calling an undefined weak function generates an appropriate stub -; that will fail at runtime with "unreachable". - -target triple = "wasm32-unknown-unknown" - -declare extern_weak void @weakFunc1() -declare extern_weak void @weakFunc2() ; same signature -declare extern_weak void @weakFunc3(i32 %arg) ; different -declare extern_weak void @weakFunc4() ; should be GC'd as not called - -; CHECK-GC: removing unused section {{.*}}:(weakFunc4) - -define i32 @callWeakFuncs() { - call void @weakFunc1() - call void @weakFunc2() - call void @weakFunc3(i32 2) - %addr1 = ptrtoint void ()* @weakFunc1 to i32 - %addr4 = ptrtoint void ()* @weakFunc4 to i32 - %sum = add i32 %addr1, %addr4 - ret i32 %sum -} - -; CHECK: --- !WASM -; CHECK-NEXT: FileHeader: -; CHECK-NEXT: Version: 0x1 -; CHECK-NEXT: Sections: -; CHECK-NEXT: - Type: TYPE -; CHECK-NEXT: Signatures: -; CHECK-NEXT: - Index: 0 -; CHECK-NEXT: ParamTypes: -; CHECK-NEXT: ReturnTypes: [] -; CHECK-NEXT: - Index: 1 -; CHECK-NEXT: ParamTypes: -; CHECK-NEXT: - I32 -; CHECK-NEXT: ReturnTypes: [] -; CHECK-NEXT: - Index: 2 -; CHECK-NEXT: ParamTypes: -; CHECK-NEXT: ReturnTypes: -; CHECK-NEXT: - I32 -; CHECK-NEXT: - Type: FUNCTION -; CHECK-NEXT: FunctionTypes: [ 0, 0, 1, 2 ] -; CHECK-NEXT: - Type: TABLE -; CHECK-NEXT: Tables: -; CHECK-NEXT: - Index: 0 -; CHECK-NEXT: ElemType: FUNCREF -; CHECK-NEXT: Limits: -; CHECK-NEXT: Flags: [ HAS_MAX ] -; CHECK-NEXT: Initial: 0x1 -; CHECK-NEXT: Maximum: 0x1 -; CHECK-NEXT: - Type: MEMORY -; CHECK-NEXT: Memories: -; CHECK-NEXT: - Initial: 0x2 -; CHECK-NEXT: - Type: GLOBAL -; CHECK-NEXT: Globals: -; CHECK-NEXT: - Index: 0 -; CHECK-NEXT: Type: I32 -; CHECK-NEXT: Mutable: true -; CHECK-NEXT: InitExpr: -; CHECK-NEXT: Opcode: I32_CONST -; CHECK-NEXT: Value: 66560 -; CHECK-NEXT: - Type: EXPORT -; CHECK-NEXT: Exports: -; CHECK-NEXT: - Name: memory -; CHECK-NEXT: Kind: MEMORY -; CHECK-NEXT: Index: 0 -; CHECK-NEXT: - Name: callWeakFuncs -; CHECK-NEXT: Kind: FUNCTION -; CHECK-NEXT: Index: 3 -; CHECK-NEXT: - Type: CODE -; CHECK-NEXT: Functions: -; CHECK-NEXT: - Index: 0 -; CHECK-NEXT: Locals: -; CHECK-NEXT: Body: 000B -; CHECK-NEXT: - Index: 1 -; CHECK-NEXT: Locals: -; CHECK-NEXT: Body: 000B -; CHECK-NEXT: - Index: 2 -; CHECK-NEXT: Locals: -; CHECK-NEXT: Body: 000B -; CHECK-NEXT: - Index: 3 -; CHECK-NEXT: Locals: -; CHECK-NEXT: Body: 10808080800010818080800041021082808080004180808080004180808080006A0B -; CHECK-NEXT: - Type: CUSTOM -; CHECK-NEXT: Name: name -; CHECK-NEXT: FunctionNames: -; CHECK-NEXT: - Index: 0 -; CHECK-NEXT: Name: 'undefined_weak:weakFunc1' -; CHECK-NEXT: - Index: 1 -; CHECK-NEXT: Name: 'undefined_weak:weakFunc2' -; CHECK-NEXT: - Index: 2 -; CHECK-NEXT: Name: 'undefined_weak:weakFunc3' -; CHECK-NEXT: - Index: 3 -; CHECK-NEXT: Name: callWeakFuncs -; CHECK-NEXT: GlobalNames: -; CHECK-NEXT: - Index: 0 -; CHECK-NEXT: Name: __stack_pointer -; CHECK-NEXT: ... diff --git a/lld/test/wasm/undefined-weak-call.s b/lld/test/wasm/undefined-weak-call.s new file mode 100644 --- /dev/null +++ b/lld/test/wasm/undefined-weak-call.s @@ -0,0 +1,108 @@ +# RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown -o %t.o %s +# RUN: wasm-ld --entry=callWeakFuncs --print-gc-sections %t.o \ +# RUN: -o %t.wasm 2>&1 | FileCheck -check-prefix=CHECK-GC %s +# RUN: obj2yaml %t.wasm | FileCheck %s + + +# Check that calling an undefined weak function generates an appropriate stub +# that will fail at runtime with "unreachable". + +.globl callWeakFuncs + +callWeakFuncs: + .functype callWeakFuncs () -> (i32) + call weakFunc1 + call weakFunc2 + i32.const 2 + call weakFunc3 + i32.const weakFunc1 + i32.const weakFunc4 + i32.add + end_function + +.weak weakFunc1 +.weak weakFunc2 +.weak weakFunc3 +.weak weakFunc4 +.functype weakFunc1 () -> () +.functype weakFunc2 () -> () +.functype weakFunc3 (i32) -> () +.functype weakFunc4 () -> () + +# CHECK-GC: removing unused section {{.*}}:(weakFunc4) + +# CHECK: --- !WASM +# CHECK-NEXT: FileHeader: +# CHECK-NEXT: Version: 0x1 +# CHECK-NEXT: Sections: +# CHECK-NEXT: - Type: TYPE +# CHECK-NEXT: Signatures: +# CHECK-NEXT: - Index: 0 +# CHECK-NEXT: ParamTypes: +# CHECK-NEXT: ReturnTypes: [] +# CHECK-NEXT: - Index: 1 +# CHECK-NEXT: ParamTypes: +# CHECK-NEXT: - I32 +# CHECK-NEXT: ReturnTypes: [] +# CHECK-NEXT: - Index: 2 +# CHECK-NEXT: ParamTypes: +# CHECK-NEXT: ReturnTypes: +# CHECK-NEXT: - I32 +# CHECK-NEXT: - Type: FUNCTION +# CHECK-NEXT: FunctionTypes: [ 0, 0, 1, 2 ] +# CHECK-NEXT: - Type: TABLE +# CHECK-NEXT: Tables: +# CHECK-NEXT: - Index: 0 +# CHECK-NEXT: ElemType: FUNCREF +# CHECK-NEXT: Limits: +# CHECK-NEXT: Flags: [ HAS_MAX ] +# CHECK-NEXT: Initial: 0x1 +# CHECK-NEXT: Maximum: 0x1 +# CHECK-NEXT: - Type: MEMORY +# CHECK-NEXT: Memories: +# CHECK-NEXT: - Initial: 0x2 +# CHECK-NEXT: - Type: GLOBAL +# CHECK-NEXT: Globals: +# CHECK-NEXT: - Index: 0 +# CHECK-NEXT: Type: I32 +# CHECK-NEXT: Mutable: true +# CHECK-NEXT: InitExpr: +# CHECK-NEXT: Opcode: I32_CONST +# CHECK-NEXT: Value: 66560 +# CHECK-NEXT: - Type: EXPORT +# CHECK-NEXT: Exports: +# CHECK-NEXT: - Name: memory +# CHECK-NEXT: Kind: MEMORY +# CHECK-NEXT: Index: 0 +# CHECK-NEXT: - Name: callWeakFuncs +# CHECK-NEXT: Kind: FUNCTION +# CHECK-NEXT: Index: 3 +# CHECK-NEXT: - Type: CODE +# CHECK-NEXT: Functions: +# CHECK-NEXT: - Index: 0 +# CHECK-NEXT: Locals: +# CHECK-NEXT: Body: 000B +# CHECK-NEXT: - Index: 1 +# CHECK-NEXT: Locals: +# CHECK-NEXT: Body: 000B +# CHECK-NEXT: - Index: 2 +# CHECK-NEXT: Locals: +# CHECK-NEXT: Body: 000B +# CHECK-NEXT: - Index: 3 +# CHECK-NEXT: Locals: +# CHECK-NEXT: Body: 10808080800010818080800041021082808080004180808080004180808080006A0B +# CHECK-NEXT: - Type: CUSTOM +# CHECK-NEXT: Name: name +# CHECK-NEXT: FunctionNames: +# CHECK-NEXT: - Index: 0 +# CHECK-NEXT: Name: 'undefined_weak:weakFunc1' +# CHECK-NEXT: - Index: 1 +# CHECK-NEXT: Name: 'undefined_weak:weakFunc2' +# CHECK-NEXT: - Index: 2 +# CHECK-NEXT: Name: 'undefined_weak:weakFunc3' +# CHECK-NEXT: - Index: 3 +# CHECK-NEXT: Name: callWeakFuncs +# CHECK-NEXT: GlobalNames: +# CHECK-NEXT: - Index: 0 +# CHECK-NEXT: Name: __stack_pointer +# CHECK-NEXT: ... diff --git a/lld/test/wasm/weak-symbols.ll b/lld/test/wasm/weak-symbols.ll deleted file mode 100644 --- a/lld/test/wasm/weak-symbols.ll +++ /dev/null @@ -1,121 +0,0 @@ -; RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown %p/Inputs/weak-symbol1.s -o %t1.o -; RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown %p/Inputs/weak-symbol2.s -o %t2.o -; RUN: llc -filetype=obj %s -o %t.o -; RUN: wasm-ld --export-dynamic -o %t.wasm %t.o %t1.o %t2.o -; RUN: obj2yaml %t.wasm | FileCheck %s - -target triple = "wasm32-unknown-unknown" - -declare i32 @weakFn() local_unnamed_addr -@weakGlobal = external global i32 - -define void @_start() local_unnamed_addr { -entry: - %call = call i32 @weakFn() - %val = load i32, i32* @weakGlobal, align 4 - ret void -} - -; CHECK: --- !WASM -; CHECK-NEXT: FileHeader: -; CHECK-NEXT: Version: 0x1 -; CHECK-NEXT: Sections: -; CHECK-NEXT: - Type: TYPE -; CHECK-NEXT: Signatures: -; CHECK-NEXT: - Index: 0 -; CHECK-NEXT: ParamTypes: [] -; CHECK-NEXT: ReturnTypes: [] -; CHECK-NEXT: - Index: 1 -; CHECK-NEXT: ParamTypes: [] -; CHECK-NEXT: ReturnTypes: -; CHECK-NEXT: - I32 -; CHECK-NEXT: - Type: FUNCTION -; CHECK-NEXT: FunctionTypes: [ 0, 1, 1, 1 ] -; CHECK-NEXT: - Type: TABLE -; CHECK-NEXT: Tables: -; CHECK-NEXT: - Index: 0 -; CHECK-NEXT: ElemType: FUNCREF -; CHECK-NEXT: Limits: -; CHECK-NEXT: Flags: [ HAS_MAX ] -; CHECK-NEXT: Initial: 0x2 -; CHECK-NEXT: Maximum: 0x2 -; CHECK-NEXT: - Type: MEMORY -; CHECK-NEXT: Memories: -; CHECK-NEXT: - Initial: 0x2 -; CHECK-NEXT: - Type: GLOBAL -; CHECK-NEXT: Globals: -; CHECK-NEXT: - Index: 0 -; CHECK-NEXT: Type: I32 -; CHECK-NEXT: Mutable: true -; CHECK-NEXT: InitExpr: -; CHECK-NEXT: Opcode: I32_CONST -; CHECK-NEXT: Value: 66576 -; CHECK-NEXT: - Index: 1 -; CHECK-NEXT: Type: I32 -; CHECK-NEXT: Mutable: false -; CHECK-NEXT: InitExpr: -; CHECK-NEXT: Opcode: I32_CONST -; CHECK-NEXT: Value: 1024 -; CHECK-NEXT: - Type: EXPORT -; CHECK-NEXT: Exports: -; CHECK-NEXT: - Name: memory -; CHECK-NEXT: Kind: MEMORY -; CHECK-NEXT: Index: 0 -; CHECK-NEXT: - Name: _start -; CHECK-NEXT: Kind: FUNCTION -; CHECK-NEXT: Index: 0 -; CHECK-NEXT: - Name: weakFn -; CHECK-NEXT: Kind: FUNCTION -; CHECK-NEXT: Index: 1 -; CHECK-NEXT: - Name: exportWeak1 -; CHECK-NEXT: Kind: FUNCTION -; CHECK-NEXT: Index: 2 -; CHECK-NEXT: - Name: weakGlobal -; CHECK-NEXT: Kind: GLOBAL -; CHECK-NEXT: Index: 1 -; CHECK-NEXT: - Name: exportWeak2 -; CHECK-NEXT: Kind: FUNCTION -; CHECK-NEXT: Index: 3 -; 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: - Type: CODE -; CHECK-NEXT: Functions: -; CHECK-NEXT: - Index: 0 -; CHECK-NEXT: Locals: -; CHECK-NEXT: Body: 1081808080001A0B -; CHECK-NEXT: - Index: 1 -; CHECK-NEXT: Locals: -; CHECK-NEXT: Body: 41010B -; CHECK-NEXT: - Index: 2 -; CHECK-NEXT: Locals: -; CHECK-NEXT: Body: 4181808080000B -; CHECK-NEXT: - Index: 3 -; CHECK-NEXT: Locals: -; CHECK-NEXT: Body: 4181808080000B -; CHECK-NEXT: - Type: DATA -; CHECK-NEXT: Segments: -; CHECK-NEXT: - SectionOffset: 7 -; CHECK-NEXT: InitFlags: 0 -; CHECK-NEXT: Offset: -; CHECK-NEXT: Opcode: I32_CONST -; CHECK-NEXT: Value: 1024 -; CHECK-NEXT: Content: '01000000' -; CHECK-NEXT: - Type: CUSTOM -; CHECK-NEXT: Name: name -; CHECK-NEXT: FunctionNames: -; CHECK-NEXT: - Index: 0 -; CHECK-NEXT: Name: _start -; CHECK-NEXT: - Index: 1 -; CHECK-NEXT: Name: weakFn -; CHECK-NEXT: - Index: 2 -; CHECK-NEXT: Name: exportWeak1 -; CHECK-NEXT: - Index: 3 -; CHECK-NEXT: Name: exportWeak2 -; CHECK-NEXT: GlobalNames: -; CHECK-NEXT: - Index: 0 -; CHECK-NEXT: Name: __stack_pointer -; CHECK-NEXT: ... diff --git a/lld/test/wasm/weak-symbols.s b/lld/test/wasm/weak-symbols.s new file mode 100644 --- /dev/null +++ b/lld/test/wasm/weak-symbols.s @@ -0,0 +1,119 @@ +# RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown %p/Inputs/weak-symbol1.s -o %t1.o +# RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown %p/Inputs/weak-symbol2.s -o %t2.o +# RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown %s -o %t.o +# RUN: wasm-ld --export-dynamic -o %t.wasm %t.o %t1.o %t2.o +# RUN: obj2yaml %t.wasm | FileCheck %s + +.globl _start +_start: + .functype _start () -> () + call weakFn + drop + end_function + +.functype weakFn () -> (i32) +.size weakGlobal, 4 + +# CHECK: --- !WASM +# CHECK-NEXT: FileHeader: +# CHECK-NEXT: Version: 0x1 +# CHECK-NEXT: Sections: +# CHECK-NEXT: - Type: TYPE +# CHECK-NEXT: Signatures: +# CHECK-NEXT: - Index: 0 +# CHECK-NEXT: ParamTypes: [] +# CHECK-NEXT: ReturnTypes: [] +# CHECK-NEXT: - Index: 1 +# CHECK-NEXT: ParamTypes: [] +# CHECK-NEXT: ReturnTypes: +# CHECK-NEXT: - I32 +# CHECK-NEXT: - Type: FUNCTION +# CHECK-NEXT: FunctionTypes: [ 0, 1, 1, 1 ] +# CHECK-NEXT: - Type: TABLE +# CHECK-NEXT: Tables: +# CHECK-NEXT: - Index: 0 +# CHECK-NEXT: ElemType: FUNCREF +# CHECK-NEXT: Limits: +# CHECK-NEXT: Flags: [ HAS_MAX ] +# CHECK-NEXT: Initial: 0x2 +# CHECK-NEXT: Maximum: 0x2 +# CHECK-NEXT: - Type: MEMORY +# CHECK-NEXT: Memories: +# CHECK-NEXT: - Initial: 0x2 +# CHECK-NEXT: - Type: GLOBAL +# CHECK-NEXT: Globals: +# CHECK-NEXT: - Index: 0 +# CHECK-NEXT: Type: I32 +# CHECK-NEXT: Mutable: true +# CHECK-NEXT: InitExpr: +# CHECK-NEXT: Opcode: I32_CONST +# CHECK-NEXT: Value: 66576 +# CHECK-NEXT: - Index: 1 +# CHECK-NEXT: Type: I32 +# CHECK-NEXT: Mutable: false +# CHECK-NEXT: InitExpr: +# CHECK-NEXT: Opcode: I32_CONST +# CHECK-NEXT: Value: 1024 +# CHECK-NEXT: - Type: EXPORT +# CHECK-NEXT: Exports: +# CHECK-NEXT: - Name: memory +# CHECK-NEXT: Kind: MEMORY +# CHECK-NEXT: Index: 0 +# CHECK-NEXT: - Name: _start +# CHECK-NEXT: Kind: FUNCTION +# CHECK-NEXT: Index: 0 +# CHECK-NEXT: - Name: weakFn +# CHECK-NEXT: Kind: FUNCTION +# CHECK-NEXT: Index: 1 +# CHECK-NEXT: - Name: exportWeak1 +# CHECK-NEXT: Kind: FUNCTION +# CHECK-NEXT: Index: 2 +# CHECK-NEXT: - Name: weakGlobal +# CHECK-NEXT: Kind: GLOBAL +# CHECK-NEXT: Index: 1 +# CHECK-NEXT: - Name: exportWeak2 +# CHECK-NEXT: Kind: FUNCTION +# CHECK-NEXT: Index: 3 +# 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: - Type: CODE +# CHECK-NEXT: Functions: +# CHECK-NEXT: - Index: 0 +# CHECK-NEXT: Locals: +# CHECK-NEXT: Body: 1081808080001A0B +# CHECK-NEXT: - Index: 1 +# CHECK-NEXT: Locals: +# CHECK-NEXT: Body: 41010B +# CHECK-NEXT: - Index: 2 +# CHECK-NEXT: Locals: +# CHECK-NEXT: Body: 4181808080000B +# CHECK-NEXT: - Index: 3 +# CHECK-NEXT: Locals: +# CHECK-NEXT: Body: 4181808080000B +# CHECK-NEXT: - Type: DATA +# CHECK-NEXT: Segments: +# CHECK-NEXT: - SectionOffset: 7 +# CHECK-NEXT: InitFlags: 0 +# CHECK-NEXT: Offset: +# CHECK-NEXT: Opcode: I32_CONST +# CHECK-NEXT: Value: 1024 +# CHECK-NEXT: Content: '01000000' +# CHECK-NEXT: - Type: CUSTOM +# CHECK-NEXT: Name: name +# CHECK-NEXT: FunctionNames: +# CHECK-NEXT: - Index: 0 +# CHECK-NEXT: Name: _start +# CHECK-NEXT: - Index: 1 +# CHECK-NEXT: Name: weakFn +# CHECK-NEXT: - Index: 2 +# CHECK-NEXT: Name: exportWeak1 +# CHECK-NEXT: - Index: 3 +# CHECK-NEXT: Name: exportWeak2 +# CHECK-NEXT: GlobalNames: +# CHECK-NEXT: - Index: 0 +# CHECK-NEXT: Name: __stack_pointer +# CHECK-NEXT: ... diff --git a/lld/test/wasm/weak-undefined.ll b/lld/test/wasm/weak-undefined.ll deleted file mode 100644 --- a/lld/test/wasm/weak-undefined.ll +++ /dev/null @@ -1,87 +0,0 @@ -; RUN: llc -filetype=obj -o %t.o %s -; RUN: wasm-ld -strip-debug %t.o -o %t.wasm -; RUN: obj2yaml %t.wasm | FileCheck %s - -; Test that undefined weak externals (global_var) and (foo) don't cause -; link failures and resolve to zero. - -target triple = "wasm32-unknown-unknown" - -@global_var = extern_weak global i32, align 4 - -declare extern_weak i32 @foo() - -define i8* @get_address_of_foo() #0 { -entry: - ret i8* bitcast (i32 ()* @foo to i8*) -} - -define i32* @get_address_of_global_var() #0 { - ret i32* @global_var -} - -define void @_start() #0 { -entry: - %call1 = call i32* @get_address_of_global_var() - %call2 = call i8* @get_address_of_foo() - call i32 @foo() - ret void -} - -; CHECK: --- !WASM -; CHECK-NEXT: FileHeader: -; CHECK-NEXT: Version: 0x1 -; CHECK-NEXT: Sections: -; CHECK-NEXT: - Type: TYPE -; CHECK-NEXT: Signatures: -; CHECK-NEXT: - Index: 0 -; CHECK-NEXT: ParamTypes: [] -; CHECK-NEXT: ReturnTypes: -; CHECK-NEXT: - I32 -; CHECK-NEXT: - Index: 1 -; CHECK-NEXT: ParamTypes: [] -; CHECK-NEXT: ReturnTypes: [] -; CHECK-NEXT: - Type: FUNCTION -; CHECK-NEXT: FunctionTypes: [ 0, 0, 0, 1 ] -; CHECK-NEXT: - Type: TABLE -; CHECK-NEXT: Tables: -; CHECK-NEXT: - Index: 0 -; CHECK-NEXT: ElemType: FUNCREF -; CHECK-NEXT: Limits: -; CHECK-NEXT: Flags: [ HAS_MAX ] -; CHECK-NEXT: Initial: 0x1 -; CHECK-NEXT: Maximum: 0x1 -; CHECK-NEXT: - Type: MEMORY -; CHECK-NEXT: Memories: -; CHECK-NEXT: - Initial: 0x2 -; CHECK-NEXT: - Type: GLOBAL -; CHECK-NEXT: Globals: -; CHECK-NEXT: - Index: 0 -; CHECK-NEXT: Type: I32 -; CHECK-NEXT: Mutable: true -; CHECK-NEXT: InitExpr: -; CHECK-NEXT: Opcode: I32_CONST -; CHECK-NEXT: Value: 66560 -; CHECK-NEXT: - Type: EXPORT -; CHECK-NEXT: Exports: -; CHECK-NEXT: - Name: memory -; CHECK-NEXT: Kind: MEMORY -; CHECK-NEXT: Index: 0 -; CHECK-NEXT: - Name: _start -; CHECK-NEXT: Kind: FUNCTION -; CHECK-NEXT: Index: 3 -; CHECK-NEXT: - Type: CODE -; CHECK-NEXT: Functions: -; CHECK-NEXT: - Index: 0 -; CHECK-NEXT: Locals: -; CHECK-NEXT: Body: 000B -; CHECK-NEXT: - Index: 1 -; CHECK-NEXT: Locals: -; CHECK-NEXT: Body: 4180808080000B -; CHECK-NEXT: - Index: 2 -; CHECK-NEXT: Locals: -; CHECK-NEXT: Body: 4180808080000B -; CHECK-NEXT: - Index: 3 -; CHECK-NEXT: Locals: -; CHECK-NEXT: Body: 1082808080001A1081808080001A1080808080001A0B -; CHECK-NEXT: ... diff --git a/lld/test/wasm/weak-undefined.s b/lld/test/wasm/weak-undefined.s new file mode 100644 --- /dev/null +++ b/lld/test/wasm/weak-undefined.s @@ -0,0 +1,92 @@ +# RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown -o %t.o %s +# RUN: wasm-ld -strip-debug %t.o -o %t.wasm +# RUN: obj2yaml %t.wasm | FileCheck %s + +# Test that undefined weak externals (global_var) and (foo) don't cause +# link failures and resolve to zero. + +.globl get_address_of_foo +get_address_of_foo: + .functype get_address_of_foo () -> (i32) + i32.const foo + end_function + +.globl get_address_of_global_var +get_address_of_global_var: + .functype get_address_of_global_var () -> (i32) + i32.const global_var + end_function + +.globl _start +_start: + .functype _start () -> () + call get_address_of_global_var + drop + call get_address_of_foo + drop + call foo + drop + end_function + +.weak foo +.weak global_var +.functype foo () -> (i32) + + +# CHECK: --- !WASM +# CHECK-NEXT: FileHeader: +# CHECK-NEXT: Version: 0x1 +# CHECK-NEXT: Sections: +# CHECK-NEXT: - Type: TYPE +# CHECK-NEXT: Signatures: +# CHECK-NEXT: - Index: 0 +# CHECK-NEXT: ParamTypes: [] +# CHECK-NEXT: ReturnTypes: +# CHECK-NEXT: - I32 +# CHECK-NEXT: - Index: 1 +# CHECK-NEXT: ParamTypes: [] +# CHECK-NEXT: ReturnTypes: [] +# CHECK-NEXT: - Type: FUNCTION +# CHECK-NEXT: FunctionTypes: [ 0, 0, 0, 1 ] +# CHECK-NEXT: - Type: TABLE +# CHECK-NEXT: Tables: +# CHECK-NEXT: - Index: 0 +# CHECK-NEXT: ElemType: FUNCREF +# CHECK-NEXT: Limits: +# CHECK-NEXT: Flags: [ HAS_MAX ] +# CHECK-NEXT: Initial: 0x1 +# CHECK-NEXT: Maximum: 0x1 +# CHECK-NEXT: - Type: MEMORY +# CHECK-NEXT: Memories: +# CHECK-NEXT: - Initial: 0x2 +# CHECK-NEXT: - Type: GLOBAL +# CHECK-NEXT: Globals: +# CHECK-NEXT: - Index: 0 +# CHECK-NEXT: Type: I32 +# CHECK-NEXT: Mutable: true +# CHECK-NEXT: InitExpr: +# CHECK-NEXT: Opcode: I32_CONST +# CHECK-NEXT: Value: 66560 +# CHECK-NEXT: - Type: EXPORT +# CHECK-NEXT: Exports: +# CHECK-NEXT: - Name: memory +# CHECK-NEXT: Kind: MEMORY +# CHECK-NEXT: Index: 0 +# CHECK-NEXT: - Name: _start +# CHECK-NEXT: Kind: FUNCTION +# CHECK-NEXT: Index: 3 +# CHECK-NEXT: - Type: CODE +# CHECK-NEXT: Functions: +# CHECK-NEXT: - Index: 0 +# CHECK-NEXT: Locals: +# CHECK-NEXT: Body: 000B +# CHECK-NEXT: - Index: 1 +# CHECK-NEXT: Locals: +# CHECK-NEXT: Body: 4180808080000B +# CHECK-NEXT: - Index: 2 +# CHECK-NEXT: Locals: +# CHECK-NEXT: Body: 4180808080000B +# CHECK-NEXT: - Index: 3 +# CHECK-NEXT: Locals: +# CHECK-NEXT: Body: 1082808080001A1081808080001A1080808080001A0B +# CHECK-NEXT: ... diff --git a/llvm/test/CodeGen/WebAssembly/weak.ll b/llvm/test/CodeGen/WebAssembly/weak.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/WebAssembly/weak.ll @@ -0,0 +1,27 @@ +; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck %s + +target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" +target triple = "wasm32-unknown-unknown" + +; CHECK: .weak f +define weak i32 @f() { + unreachable +} + +; CHECK: g: +; CHECK: call h +define void @g() { + tail call void @h( ) + ret void +} + +; CHECK: bar: +; CHECK: .int32 foo +; CHECK: .size bar, 4 +@bar = global i32* @foo + +; CHECK: .weak h +declare extern_weak void @h() + +; CHECK: .weak foo +@foo = extern_weak global i32