
This matches the behavior of the ELF linker where -u/--undefined means symbols will get pulled in from archives but won't result in link error if they are missing. Also, don't actually great symbol table entries for the undefined symbols, again matching more closely the ELF linker. This also results in simplification of the code. Differential Revision: https://reviews.llvm.org/D50279 llvm-svn: 338938
108 lines
3.8 KiB
LLVM
108 lines
3.8 KiB
LLVM
; 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:
|
|
%call = call i32* @get_address_of_global_var()
|
|
ret void
|
|
}
|
|
|
|
; CHECK: --- !WASM
|
|
; CHECK-NEXT: FileHeader:
|
|
; CHECK-NEXT: Version: 0x00000001
|
|
; CHECK-NEXT: Sections:
|
|
; CHECK-NEXT: - Type: TYPE
|
|
; CHECK-NEXT: Signatures:
|
|
; CHECK-NEXT: - Index: 0
|
|
; CHECK-NEXT: ReturnType: NORESULT
|
|
; CHECK-NEXT: ParamTypes:
|
|
; CHECK-NEXT: - Index: 1
|
|
; CHECK-NEXT: ReturnType: I32
|
|
; CHECK-NEXT: ParamTypes:
|
|
; CHECK-NEXT: - Type: FUNCTION
|
|
; CHECK-NEXT: FunctionTypes: [ 0, 1, 1, 0 ]
|
|
; CHECK-NEXT: - Type: TABLE
|
|
; CHECK-NEXT: Tables:
|
|
; CHECK-NEXT: - ElemType: ANYFUNC
|
|
; CHECK-NEXT: Limits:
|
|
; CHECK-NEXT: Flags: [ HAS_MAX ]
|
|
; CHECK-NEXT: Initial: 0x00000001
|
|
; CHECK-NEXT: Maximum: 0x00000001
|
|
; CHECK-NEXT: - Type: MEMORY
|
|
; CHECK-NEXT: Memories:
|
|
; CHECK-NEXT: - Initial: 0x00000002
|
|
; 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: - Index: 1
|
|
; CHECK-NEXT: Type: I32
|
|
; CHECK-NEXT: Mutable: false
|
|
; CHECK-NEXT: InitExpr:
|
|
; CHECK-NEXT: Opcode: I32_CONST
|
|
; CHECK-NEXT: Value: 66560
|
|
; CHECK-NEXT: - Index: 2
|
|
; 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: __heap_base
|
|
; CHECK-NEXT: Kind: GLOBAL
|
|
; CHECK-NEXT: Index: 1
|
|
; CHECK-NEXT: - Name: __data_end
|
|
; CHECK-NEXT: Kind: GLOBAL
|
|
; CHECK-NEXT: Index: 2
|
|
; CHECK-NEXT: - Name: get_address_of_foo
|
|
; CHECK-NEXT: Kind: FUNCTION
|
|
; CHECK-NEXT: Index: 1
|
|
; CHECK-NEXT: - Name: get_address_of_global_var
|
|
; CHECK-NEXT: Kind: FUNCTION
|
|
; CHECK-NEXT: Index: 2
|
|
; 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: 0B
|
|
; 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: 1082808080001A0B
|
|
; CHECK-NEXT: ...
|