Index: test/wasm/alias.ll =================================================================== --- test/wasm/alias.ll +++ test/wasm/alias.ll @@ -58,10 +58,10 @@ ; CHECK-NEXT: - Name: memory ; CHECK-NEXT: Kind: MEMORY ; CHECK-NEXT: Index: 0 -; CHECK-NEXT: - Name: start_alias +; CHECK-NEXT: - Name: _start ; CHECK-NEXT: Kind: FUNCTION ; CHECK-NEXT: Index: 0 -; CHECK-NEXT: - Name: _start +; CHECK-NEXT: - Name: start_alias ; CHECK-NEXT: Kind: FUNCTION ; CHECK-NEXT: Index: 0 ; CHECK-NEXT: - Name: __heap_base Index: test/wasm/archive.ll =================================================================== --- test/wasm/archive.ll +++ test/wasm/archive.ll @@ -9,7 +9,7 @@ ; CHECK-UNDEFINED: undefined symbol: missing_func ; RUN: echo 'missing_func' > %t.imports -; RUN: lld -flavor wasm --check-signatures %t.a %t.o -o %t.wasm +; RUN: lld -flavor wasm --check-signatures -r %t.a %t.o -o %t.wasm ; RUN: llvm-nm -a %t.wasm | FileCheck %s @@ -25,12 +25,16 @@ ret void } -; Verify that multually dependant object files in an archive is handled -; correctly. +; Verify that mutually dependant object files in an archive is handled +; correctly. Since we're using llvm-nm, we must link with --relocatable. +; +; TODO(ncw): Update LLD so that the symbol table is written out for +; non-relocatable output (with an option to strip it) ; CHECK: 00000003 T _start ; CHECK-NEXT: 00000001 T bar ; CHECK-NEXT: 00000002 T foo +; CHECK-NEXT: U missing_func ; Verify that symbols from unused objects don't appear in the symbol table ; CHECK-NOT: hello Index: test/wasm/data-layout.ll =================================================================== --- test/wasm/data-layout.ll +++ test/wasm/data-layout.ll @@ -46,25 +46,10 @@ ; RUN: lld -flavor wasm --check-signatures --relocatable -o %t_reloc.wasm %t.o %t.hello.o ; RUN: obj2yaml %t_reloc.wasm | FileCheck %s -check-prefix=RELOC -; RELOC: - Type: GLOBAL -; RELOC-NEXT: Globals: -; RELOC-NEXT: - Index: 0 -; RELOC-NEXT: Type: I32 -; RELOC-NEXT: Mutable: false -; RELOC-NEXT: InitExpr: -; RELOC-NEXT: Opcode: I32_CONST -; RELOC-NEXT: Value: 0 -; RELOC-NEXT: - Index: 1 -; RELOC-NEXT: Type: I32 -; RELOC-NEXT: Mutable: false -; RELOC-NEXT: InitExpr: -; RELOC-NEXT: Opcode: I32_CONST -; RELOC-NEXT: Value: 16 - ; RELOC: - Type: DATA ; RELOC-NEXT: Relocations: ; RELOC-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_I32 -; RELOC-NEXT: Index: 3 +; RELOC-NEXT: Index: 5 ; RELOC-NEXT: Offset: 0x00000018 ; RELOC-NEXT: Segments: ; RELOC-NEXT: - SectionOffset: 6 @@ -92,6 +77,31 @@ ; RELOC-NEXT: Value: 28 ; RELOC-NEXT: Content: 68656C6C6F0A00 -; RELOC: - Type: CUSTOM +; RELOC: - Type: CUSTOM ; RELOC-NEXT: Name: linking ; RELOC-NEXT: DataSize: 35 +; RELOC-NEXT: SymbolTable: +; RELOC-NEXT: - Index: 0 +; RELOC-NEXT: Kind: DATA +; RELOC-NEXT: Name: foo +; RELOC-NEXT: Flags: [ VISIBILITY_HIDDEN ] +; RELOC-NEXT: SegmentIndex: 0 +; RELOC-NEXT: Size: 4 +; RELOC-NEXT: - Index: 1 +; RELOC-NEXT: Kind: DATA +; RELOC-NEXT: Name: aligned_bar +; RELOC-NEXT: Flags: [ VISIBILITY_HIDDEN ] +; RELOC-NEXT: SegmentIndex: 1 +; RELOC-NEXT: Size: 4 +; RELOC-NEXT: - Index: 2 +; RELOC-NEXT: Kind: DATA +; RELOC-NEXT: Name: external_ref +; RELOC-NEXT: Flags: [ ] +; RELOC-NEXT: SegmentIndex: 2 +; RELOC-NEXT: Size: 4 +; RELOC: - Index: 5 +; RELOC-NEXT: Kind: DATA +; RELOC-NEXT: Name: hello_str +; RELOC-NEXT: Flags: [ ] +; RELOC-NEXT: SegmentIndex: 3 +; RELOC-NEXT: Size: 7 Index: test/wasm/init-fini.ll =================================================================== --- test/wasm/init-fini.ll +++ test/wasm/init-fini.ll @@ -109,68 +109,134 @@ ; RELOC: Name: linking ; RELOC-NEXT: DataSize: 0 -; RELOC-NEXT: SymbolInfo: -; RELOC-NEXT: - Name: __dso_handle -; RELOC-NEXT: Flags: [ BINDING_WEAK, VISIBILITY_HIDDEN ] -; RELOC-NEXT: - Name: func1 +; RELOC-NEXT: SymbolTable: +; RELOC-NEXT: - Index: 0 +; RELOC-NEXT: Kind: DATA +; RELOC-NEXT: Name: __dso_handle +; RELOC-NEXT: Flags: [ BINDING_WEAK, VISIBILITY_HIDDEN, UNDEFINED ] +; RELOC-NEXT: - Index: 1 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: func1 ; RELOC-NEXT: Flags: [ VISIBILITY_HIDDEN ] -; RELOC-NEXT: - Name: func2 +; RELOC-NEXT: FunctionIndex: 0 +; RELOC-NEXT: - Index: 2 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: func2 ; RELOC-NEXT: Flags: [ VISIBILITY_HIDDEN ] -; RELOC-NEXT: - Name: func3 +; RELOC-NEXT: FunctionIndex: 1 +; RELOC-NEXT: - Index: 3 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: func3 ; RELOC-NEXT: Flags: [ VISIBILITY_HIDDEN ] -; RELOC-NEXT: - Name: func4 +; RELOC-NEXT: FunctionIndex: 2 +; RELOC-NEXT: - Index: 4 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: func4 ; RELOC-NEXT: Flags: [ VISIBILITY_HIDDEN ] -; RELOC-NEXT: - Name: _start +; RELOC-NEXT: FunctionIndex: 3 +; RELOC-NEXT: - Index: 5 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: __cxa_atexit +; RELOC-NEXT: Flags: [ ] +; RELOC-NEXT: FunctionIndex: 4 +; RELOC-NEXT: - Index: 6 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: _start ; RELOC-NEXT: Flags: [ VISIBILITY_HIDDEN ] -; RELOC-NEXT: - Name: .Lcall_dtors.101 +; RELOC-NEXT: FunctionIndex: 5 +; RELOC-NEXT: - Index: 7 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: .Lcall_dtors.101 ; RELOC-NEXT: Flags: [ BINDING_LOCAL ] -; RELOC-NEXT: - Name: .Lregister_call_dtors.101 +; RELOC-NEXT: FunctionIndex: 6 +; RELOC-NEXT: - Index: 8 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: .Lregister_call_dtors.101 ; RELOC-NEXT: Flags: [ BINDING_LOCAL ] -; RELOC-NEXT: - Name: .Lbitcast +; RELOC-NEXT: FunctionIndex: 7 +; RELOC-NEXT: - Index: 9 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: .Lbitcast ; RELOC-NEXT: Flags: [ BINDING_LOCAL ] -; RELOC-NEXT: - Name: .Lcall_dtors.1001 +; RELOC-NEXT: FunctionIndex: 8 +; RELOC-NEXT: - Index: 10 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: .Lcall_dtors.1001 ; RELOC-NEXT: Flags: [ BINDING_LOCAL ] -; RELOC-NEXT: - Name: .Lregister_call_dtors.1001 +; RELOC-NEXT: FunctionIndex: 9 +; RELOC-NEXT: - Index: 11 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: .Lregister_call_dtors.1001 ; RELOC-NEXT: Flags: [ BINDING_LOCAL ] -; RELOC-NEXT: - Name: myctor +; RELOC-NEXT: FunctionIndex: 10 +; RELOC-NEXT: - Index: 12 +; RELOC-NEXT: Kind: GLOBAL +; RELOC-NEXT: Name: __stack_pointer +; RELOC-NEXT: Flags: [ UNDEFINED ] +; RELOC-NEXT: GlobalIndex: 0 +; RELOC-NEXT: - Index: 13 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: myctor ; RELOC-NEXT: Flags: [ VISIBILITY_HIDDEN ] -; RELOC-NEXT: - Name: mydtor +; RELOC-NEXT: FunctionIndex: 11 +; RELOC-NEXT: - Index: 14 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: mydtor ; RELOC-NEXT: Flags: [ VISIBILITY_HIDDEN ] -; RELOC-NEXT: - Name: .Lcall_dtors.101.1 +; RELOC-NEXT: FunctionIndex: 12 +; RELOC-NEXT: - Index: 15 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: .Lcall_dtors.101 ; RELOC-NEXT: Flags: [ BINDING_LOCAL ] -; RELOC-NEXT: - Name: .Lregister_call_dtors.101.1 +; RELOC-NEXT: FunctionIndex: 13 +; RELOC-NEXT: - Index: 16 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: .Lregister_call_dtors.101 ; RELOC-NEXT: Flags: [ BINDING_LOCAL ] -; RELOC-NEXT: - Name: .Lcall_dtors.202 +; RELOC-NEXT: FunctionIndex: 14 +; RELOC-NEXT: - Index: 17 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: .Lcall_dtors.202 ; RELOC-NEXT: Flags: [ BINDING_LOCAL ] -; RELOC-NEXT: - Name: .Lregister_call_dtors.202 +; RELOC-NEXT: FunctionIndex: 15 +; RELOC-NEXT: - Index: 18 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: .Lregister_call_dtors.202 ; RELOC-NEXT: Flags: [ BINDING_LOCAL ] -; RELOC-NEXT: - Name: .Lcall_dtors.2002 +; RELOC-NEXT: FunctionIndex: 16 +; RELOC-NEXT: - Index: 19 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: .Lcall_dtors.2002 ; RELOC-NEXT: Flags: [ BINDING_LOCAL ] -; RELOC-NEXT: - Name: .Lregister_call_dtors.2002 +; RELOC-NEXT: FunctionIndex: 17 +; RELOC-NEXT: - Index: 20 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: .Lregister_call_dtors.2002 ; RELOC-NEXT: Flags: [ BINDING_LOCAL ] +; RELOC-NEXT: FunctionIndex: 18 ; RELOC-NEXT: InitFunctions: ; RELOC-NEXT: - Priority: 101 -; RELOC-NEXT: FunctionIndex: 0 +; RELOC-NEXT: Symbol: 1 ; RELOC-NEXT: - Priority: 101 -; RELOC-NEXT: FunctionIndex: 1 +; RELOC-NEXT: Symbol: 2 ; RELOC-NEXT: - Priority: 101 -; RELOC-NEXT: FunctionIndex: 7 +; RELOC-NEXT: Symbol: 8 ; RELOC-NEXT: - Priority: 101 -; RELOC-NEXT: FunctionIndex: 11 +; RELOC-NEXT: Symbol: 13 ; RELOC-NEXT: - Priority: 101 -; RELOC-NEXT: FunctionIndex: 14 +; RELOC-NEXT: Symbol: 16 ; RELOC-NEXT: - Priority: 202 -; RELOC-NEXT: FunctionIndex: 11 +; RELOC-NEXT: Symbol: 13 ; RELOC-NEXT: - Priority: 202 -; RELOC-NEXT: FunctionIndex: 16 +; RELOC-NEXT: Symbol: 18 ; RELOC-NEXT: - Priority: 1001 -; RELOC-NEXT: FunctionIndex: 0 +; RELOC-NEXT: Symbol: 1 ; RELOC-NEXT: - Priority: 1001 -; RELOC-NEXT: FunctionIndex: 10 +; RELOC-NEXT: Symbol: 11 ; RELOC-NEXT: - Priority: 2002 -; RELOC-NEXT: FunctionIndex: 11 +; RELOC-NEXT: Symbol: 13 ; RELOC-NEXT: - Priority: 2002 -; RELOC-NEXT: FunctionIndex: 18 +; RELOC-NEXT: Symbol: 20 ; RELOC-NEXT: - Type: CUSTOM ; RELOC-NEXT: Name: name ; RELOC-NEXT: FunctionNames: Index: test/wasm/locals-duplicate.test =================================================================== --- test/wasm/locals-duplicate.test +++ test/wasm/locals-duplicate.test @@ -246,118 +246,6 @@ ; RELOC-NEXT: - Type: MEMORY ; RELOC-NEXT: Memories: ; RELOC-NEXT: - Initial: 0x00000001 -; RELOC-NEXT: - Type: GLOBAL -; RELOC-NEXT: Globals: -; RELOC-NEXT: - Index: 0 -; RELOC-NEXT: Type: I32 -; RELOC-NEXT: Mutable: false -; RELOC-NEXT: InitExpr: -; RELOC-NEXT: Opcode: I32_CONST -; RELOC-NEXT: Value: 0 -; RELOC-NEXT: - Index: 1 -; RELOC-NEXT: Type: I32 -; RELOC-NEXT: Mutable: false -; RELOC-NEXT: InitExpr: -; RELOC-NEXT: Opcode: I32_CONST -; RELOC-NEXT: Value: 8 -; RELOC-NEXT: - Index: 2 -; RELOC-NEXT: Type: I32 -; RELOC-NEXT: Mutable: false -; RELOC-NEXT: InitExpr: -; RELOC-NEXT: Opcode: I32_CONST -; RELOC-NEXT: Value: 16 -; RELOC-NEXT: - Index: 3 -; RELOC-NEXT: Type: I32 -; RELOC-NEXT: Mutable: false -; RELOC-NEXT: InitExpr: -; RELOC-NEXT: Opcode: I32_CONST -; RELOC-NEXT: Value: 4 -; RELOC-NEXT: - Index: 4 -; RELOC-NEXT: Type: I32 -; RELOC-NEXT: Mutable: false -; RELOC-NEXT: InitExpr: -; RELOC-NEXT: Opcode: I32_CONST -; RELOC-NEXT: Value: 12 -; RELOC-NEXT: - Index: 5 -; RELOC-NEXT: Type: I32 -; RELOC-NEXT: Mutable: false -; RELOC-NEXT: InitExpr: -; RELOC-NEXT: Opcode: I32_CONST -; RELOC-NEXT: Value: 20 -; RELOC-NEXT: - Type: EXPORT -; RELOC-NEXT: Exports: -; RELOC-NEXT: - Name: colliding_func1.1 -; RELOC-NEXT: Kind: FUNCTION -; RELOC-NEXT: Index: 0 -; RELOC-NEXT: - Name: colliding_func2 -; RELOC-NEXT: Kind: FUNCTION -; RELOC-NEXT: Index: 1 -; RELOC-NEXT: - Name: colliding_func3 -; RELOC-NEXT: Kind: FUNCTION -; RELOC-NEXT: Index: 2 -; RELOC-NEXT: - Name: get_global1A -; RELOC-NEXT: Kind: FUNCTION -; RELOC-NEXT: Index: 3 -; RELOC-NEXT: - Name: get_global2A -; RELOC-NEXT: Kind: FUNCTION -; RELOC-NEXT: Index: 4 -; RELOC-NEXT: - Name: get_global3A -; RELOC-NEXT: Kind: FUNCTION -; RELOC-NEXT: Index: 5 -; RELOC-NEXT: - Name: get_func1A -; RELOC-NEXT: Kind: FUNCTION -; RELOC-NEXT: Index: 6 -; RELOC-NEXT: - Name: get_func2A -; RELOC-NEXT: Kind: FUNCTION -; RELOC-NEXT: Index: 7 -; RELOC-NEXT: - Name: get_func3A -; RELOC-NEXT: Kind: FUNCTION -; RELOC-NEXT: Index: 8 -; RELOC-NEXT: - Name: colliding_func1 -; RELOC-NEXT: Kind: FUNCTION -; RELOC-NEXT: Index: 9 -; RELOC-NEXT: - Name: colliding_func2.1 -; RELOC-NEXT: Kind: FUNCTION -; RELOC-NEXT: Index: 10 -; RELOC-NEXT: - Name: colliding_func3.1 -; RELOC-NEXT: Kind: FUNCTION -; RELOC-NEXT: Index: 11 -; RELOC-NEXT: - Name: get_global1B -; RELOC-NEXT: Kind: FUNCTION -; RELOC-NEXT: Index: 12 -; RELOC-NEXT: - Name: get_global2B -; RELOC-NEXT: Kind: FUNCTION -; RELOC-NEXT: Index: 13 -; RELOC-NEXT: - Name: get_global3B -; RELOC-NEXT: Kind: FUNCTION -; RELOC-NEXT: Index: 14 -; RELOC-NEXT: - Name: get_func1B -; RELOC-NEXT: Kind: FUNCTION -; RELOC-NEXT: Index: 15 -; RELOC-NEXT: - Name: get_func2B -; RELOC-NEXT: Kind: FUNCTION -; RELOC-NEXT: Index: 16 -; RELOC-NEXT: - Name: get_func3B -; RELOC-NEXT: Kind: FUNCTION -; RELOC-NEXT: Index: 17 -; RELOC-NEXT: - Name: colliding_global1.1 -; RELOC-NEXT: Kind: GLOBAL -; RELOC-NEXT: Index: 0 -; RELOC-NEXT: - Name: colliding_global2 -; RELOC-NEXT: Kind: GLOBAL -; RELOC-NEXT: Index: 1 -; RELOC-NEXT: - Name: colliding_global3 -; RELOC-NEXT: Kind: GLOBAL -; RELOC-NEXT: Index: 2 -; RELOC-NEXT: - Name: colliding_global1 -; RELOC-NEXT: Kind: GLOBAL -; RELOC-NEXT: Index: 3 -; RELOC-NEXT: - Name: colliding_global2.1 -; RELOC-NEXT: Kind: GLOBAL -; RELOC-NEXT: Index: 4 -; RELOC-NEXT: - Name: colliding_global3.1 -; RELOC-NEXT: Kind: GLOBAL -; RELOC-NEXT: Index: 5 ; RELOC-NEXT: - Type: ELEM ; RELOC-NEXT: Segments: ; RELOC-NEXT: - Offset: @@ -367,13 +255,13 @@ ; RELOC-NEXT: - Type: CODE ; RELOC-NEXT: Relocations: ; RELOC-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_SLEB -; RELOC-NEXT: Index: 0 +; RELOC-NEXT: Index: 4 ; RELOC-NEXT: Offset: 0x00000013 ; RELOC-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_SLEB -; RELOC-NEXT: Index: 1 +; RELOC-NEXT: Index: 6 ; RELOC-NEXT: Offset: 0x0000001C ; RELOC-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_SLEB -; RELOC-NEXT: Index: 2 +; RELOC-NEXT: Index: 8 ; RELOC-NEXT: Offset: 0x00000025 ; RELOC-NEXT: - Type: R_WEBASSEMBLY_TABLE_INDEX_SLEB ; RELOC-NEXT: Index: 0 @@ -385,22 +273,22 @@ ; RELOC-NEXT: Index: 2 ; RELOC-NEXT: Offset: 0x00000040 ; RELOC-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_SLEB -; RELOC-NEXT: Index: 3 +; RELOC-NEXT: Index: 16 ; RELOC-NEXT: Offset: 0x00000058 ; RELOC-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_SLEB -; RELOC-NEXT: Index: 4 +; RELOC-NEXT: Index: 18 ; RELOC-NEXT: Offset: 0x00000061 ; RELOC-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_SLEB -; RELOC-NEXT: Index: 5 +; RELOC-NEXT: Index: 20 ; RELOC-NEXT: Offset: 0x0000006A ; RELOC-NEXT: - Type: R_WEBASSEMBLY_TABLE_INDEX_SLEB -; RELOC-NEXT: Index: 9 +; RELOC-NEXT: Index: 12 ; RELOC-NEXT: Offset: 0x00000073 ; RELOC-NEXT: - Type: R_WEBASSEMBLY_TABLE_INDEX_SLEB -; RELOC-NEXT: Index: 10 +; RELOC-NEXT: Index: 13 ; RELOC-NEXT: Offset: 0x0000007C ; RELOC-NEXT: - Type: R_WEBASSEMBLY_TABLE_INDEX_SLEB -; RELOC-NEXT: Index: 11 +; RELOC-NEXT: Index: 14 ; RELOC-NEXT: Offset: 0x00000085 ; RELOC-NEXT: Functions: ; RELOC-NEXT: - Index: 0 @@ -480,23 +368,136 @@ ; RELOC-NEXT: - Type: CUSTOM ; RELOC-NEXT: Name: linking ; RELOC-NEXT: DataSize: 24 -; RELOC-NEXT: SymbolInfo: -; RELOC-NEXT: - Name: colliding_func1.1 +; RELOC-NEXT: SymbolTable: +; RELOC-NEXT: - Index: 0 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: colliding_func1 ; RELOC-NEXT: Flags: [ BINDING_LOCAL ] -; RELOC-NEXT: - Name: colliding_func3 +; RELOC-NEXT: FunctionIndex: 0 +; RELOC-NEXT: - Index: 1 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: colliding_func2 +; RELOC-NEXT: Flags: [ ] +; RELOC-NEXT: FunctionIndex: 1 +; RELOC-NEXT: - Index: 2 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: colliding_func3 ; RELOC-NEXT: Flags: [ BINDING_LOCAL ] -; RELOC-NEXT: - Name: colliding_func2.1 +; RELOC-NEXT: FunctionIndex: 2 +; RELOC-NEXT: - Index: 3 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: get_global1A +; RELOC-NEXT: Flags: [ ] +; RELOC-NEXT: FunctionIndex: 3 +; RELOC-NEXT: - Index: 4 +; RELOC-NEXT: Kind: DATA +; RELOC-NEXT: Name: colliding_global1 ; RELOC-NEXT: Flags: [ BINDING_LOCAL ] -; RELOC-NEXT: - Name: colliding_func3.1 +; RELOC-NEXT: SegmentIndex: 0 +; RELOC-NEXT: Size: 4 +; RELOC-NEXT: - Index: 5 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: get_global2A +; RELOC-NEXT: Flags: [ ] +; RELOC-NEXT: FunctionIndex: 4 +; RELOC-NEXT: - Index: 6 +; RELOC-NEXT: Kind: DATA +; RELOC-NEXT: Name: colliding_global2 +; RELOC-NEXT: Flags: [ ] +; RELOC-NEXT: SegmentIndex: 1 +; RELOC-NEXT: Size: 4 +; RELOC-NEXT: - Index: 7 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: get_global3A +; RELOC-NEXT: Flags: [ ] +; RELOC-NEXT: FunctionIndex: 5 +; RELOC-NEXT: - Index: 8 +; RELOC-NEXT: Kind: DATA +; RELOC-NEXT: Name: colliding_global3 ; RELOC-NEXT: Flags: [ BINDING_LOCAL ] -; RELOC-NEXT: - Name: colliding_global1.1 +; RELOC-NEXT: SegmentIndex: 2 +; RELOC-NEXT: Size: 4 +; RELOC-NEXT: - Index: 9 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: get_func1A +; RELOC-NEXT: Flags: [ ] +; RELOC-NEXT: FunctionIndex: 6 +; RELOC-NEXT: - Index: 10 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: get_func2A +; RELOC-NEXT: Flags: [ ] +; RELOC-NEXT: FunctionIndex: 7 +; RELOC-NEXT: - Index: 11 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: get_func3A +; RELOC-NEXT: Flags: [ ] +; RELOC-NEXT: FunctionIndex: 8 +; RELOC-NEXT: - Index: 12 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: colliding_func1 +; RELOC-NEXT: Flags: [ ] +; RELOC-NEXT: FunctionIndex: 9 +; RELOC-NEXT: - Index: 13 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: colliding_func2 ; RELOC-NEXT: Flags: [ BINDING_LOCAL ] -; RELOC-NEXT: - Name: colliding_global3 +; RELOC-NEXT: FunctionIndex: 10 +; RELOC-NEXT: - Index: 14 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: colliding_func3 ; RELOC-NEXT: Flags: [ BINDING_LOCAL ] -; RELOC-NEXT: - Name: colliding_global2.1 +; RELOC-NEXT: FunctionIndex: 11 +; RELOC-NEXT: - Index: 15 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: get_global1B +; RELOC-NEXT: Flags: [ ] +; RELOC-NEXT: FunctionIndex: 12 +; RELOC-NEXT: - Index: 16 +; RELOC-NEXT: Kind: DATA +; RELOC-NEXT: Name: colliding_global1 +; RELOC-NEXT: Flags: [ ] +; RELOC-NEXT: SegmentIndex: 0 +; RELOC-NEXT: Offset: 4 +; RELOC-NEXT: Size: 4 +; RELOC-NEXT: - Index: 17 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: get_global2B +; RELOC-NEXT: Flags: [ ] +; RELOC-NEXT: FunctionIndex: 13 +; RELOC-NEXT: - Index: 18 +; RELOC-NEXT: Kind: DATA +; RELOC-NEXT: Name: colliding_global2 ; RELOC-NEXT: Flags: [ BINDING_LOCAL ] -; RELOC-NEXT: - Name: colliding_global3.1 +; RELOC-NEXT: SegmentIndex: 1 +; RELOC-NEXT: Offset: 4 +; RELOC-NEXT: Size: 4 +; RELOC-NEXT: - Index: 19 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: get_global3B +; RELOC-NEXT: Flags: [ ] +; RELOC-NEXT: FunctionIndex: 14 +; RELOC-NEXT: - Index: 20 +; RELOC-NEXT: Kind: DATA +; RELOC-NEXT: Name: colliding_global3 ; RELOC-NEXT: Flags: [ BINDING_LOCAL ] +; RELOC-NEXT: SegmentIndex: 2 +; RELOC-NEXT: Offset: 4 +; RELOC-NEXT: Size: 4 +; RELOC-NEXT: - Index: 21 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: get_func1B +; RELOC-NEXT: Flags: [ ] +; RELOC-NEXT: FunctionIndex: 15 +; RELOC-NEXT: - Index: 22 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: get_func2B +; RELOC-NEXT: Flags: [ ] +; RELOC-NEXT: FunctionIndex: 16 +; RELOC-NEXT: - Index: 23 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: get_func3B +; RELOC-NEXT: Flags: [ ] +; RELOC-NEXT: FunctionIndex: 17 ; RELOC-NEXT: SegmentInfo: ; RELOC-NEXT: - Index: 0 ; RELOC-NEXT: Name: .bss.colliding_global1 Index: test/wasm/many-functions.ll =================================================================== --- test/wasm/many-functions.ll +++ test/wasm/many-functions.ll @@ -19,394 +19,394 @@ ; CHECK: - Type: CODE ; CHECK-NEXT: Relocations: ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x00000008 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x00000014 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x00000020 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x0000002C ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x00000038 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x00000044 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x00000050 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x0000005C ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x00000068 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x00000074 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x00000080 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x0000008C ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x00000098 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x000000A4 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x000000B0 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x000000BC ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x000000C8 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x000000D4 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x000000E0 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x000000EC ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x000000F8 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x00000104 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x00000110 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x0000011C ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x00000128 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x00000134 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x00000140 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x0000014C ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x00000158 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x00000164 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x00000170 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x0000017C ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x00000188 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x00000194 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x000001A0 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x000001AC ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x000001B8 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x000001C4 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x000001D0 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x000001DC ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x000001E8 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x000001F4 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x00000200 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x0000020C ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x00000218 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x00000224 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x00000230 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x0000023C ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x00000248 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x00000254 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x00000260 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x0000026C ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x00000278 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x00000284 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x00000290 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x0000029C ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x000002A8 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x000002B4 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x000002C0 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x000002CC ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x000002D8 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x000002E4 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x000002F0 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x000002FC ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x00000308 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x00000314 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x00000320 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x0000032C ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x00000338 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x00000344 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x00000350 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x0000035C ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x00000368 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x00000374 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x00000380 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x0000038C ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x00000398 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x000003A4 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x000003B0 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x000003BC ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x000003C8 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x000003D4 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x000003E0 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x000003EC ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x000003F8 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x00000404 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x00000410 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x0000041C ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x00000428 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x00000434 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x00000440 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x0000044C ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x00000458 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x00000464 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x00000470 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x0000047C ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x00000488 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x00000494 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x000004A0 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x000004AC ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x000004B8 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x000004C4 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x000004D0 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x000004DC ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x000004E8 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x000004F4 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x00000500 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x0000050C ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x00000518 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x00000524 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x00000530 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x0000053C ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x00000548 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x00000554 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x00000560 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x0000056C ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x00000578 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x00000584 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x00000590 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x0000059C ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x000005A8 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x000005B4 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x000005C0 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x000005CC ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x000005D8 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x000005E4 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x000005F0 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 1 +; CHECK-NEXT: Index: 129 ; CHECK-NEXT: Offset: 0x000005FC ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 1 +; CHECK-NEXT: Index: 129 ; CHECK-NEXT: Offset: 0x00000608 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_FUNCTION_INDEX_LEB -; CHECK-NEXT: Index: 129 +; CHECK-NEXT: Index: 131 ; CHECK-NEXT: Offset: 0x00000611 ; CHECK-NEXT: Functions: ; CHECK-NEXT: - Index: 0 @@ -816,6 +816,669 @@ ; CHECK-NEXT: - Type: CUSTOM ; CHECK-NEXT: Name: linking ; CHECK-NEXT: DataSize: 8 +; CHECK-NEXT: SymbolTable: +; CHECK-NEXT: - Index: 0 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f1 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 0 +; CHECK-NEXT: - Index: 1 +; CHECK-NEXT: Kind: DATA +; CHECK-NEXT: Name: foo +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: SegmentIndex: 1 +; CHECK-NEXT: Size: 4 +; CHECK-NEXT: - Index: 2 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f2 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 1 +; CHECK-NEXT: - Index: 3 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f3 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 2 +; CHECK-NEXT: - Index: 4 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f4 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 3 +; CHECK-NEXT: - Index: 5 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f5 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 4 +; CHECK-NEXT: - Index: 6 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f6 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 5 +; CHECK-NEXT: - Index: 7 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f7 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 6 +; CHECK-NEXT: - Index: 8 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f8 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 7 +; CHECK-NEXT: - Index: 9 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f9 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 8 +; CHECK-NEXT: - Index: 10 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f10 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 9 +; CHECK-NEXT: - Index: 11 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f11 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 10 +; CHECK-NEXT: - Index: 12 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f12 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 11 +; CHECK-NEXT: - Index: 13 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f13 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 12 +; CHECK-NEXT: - Index: 14 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f14 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 13 +; CHECK-NEXT: - Index: 15 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f15 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 14 +; CHECK-NEXT: - Index: 16 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f16 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 15 +; CHECK-NEXT: - Index: 17 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f17 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 16 +; CHECK-NEXT: - Index: 18 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f18 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 17 +; CHECK-NEXT: - Index: 19 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f19 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 18 +; CHECK-NEXT: - Index: 20 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f20 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 19 +; CHECK-NEXT: - Index: 21 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f21 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 20 +; CHECK-NEXT: - Index: 22 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f22 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 21 +; CHECK-NEXT: - Index: 23 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f23 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 22 +; CHECK-NEXT: - Index: 24 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f24 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 23 +; CHECK-NEXT: - Index: 25 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f25 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 24 +; CHECK-NEXT: - Index: 26 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f26 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 25 +; CHECK-NEXT: - Index: 27 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f27 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 26 +; CHECK-NEXT: - Index: 28 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f28 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 27 +; CHECK-NEXT: - Index: 29 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f29 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 28 +; CHECK-NEXT: - Index: 30 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f30 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 29 +; CHECK-NEXT: - Index: 31 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f31 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 30 +; CHECK-NEXT: - Index: 32 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f32 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 31 +; CHECK-NEXT: - Index: 33 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f33 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 32 +; CHECK-NEXT: - Index: 34 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f34 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 33 +; CHECK-NEXT: - Index: 35 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f35 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 34 +; CHECK-NEXT: - Index: 36 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f36 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 35 +; CHECK-NEXT: - Index: 37 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f37 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 36 +; CHECK-NEXT: - Index: 38 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f38 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 37 +; CHECK-NEXT: - Index: 39 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f39 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 38 +; CHECK-NEXT: - Index: 40 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f40 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 39 +; CHECK-NEXT: - Index: 41 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f41 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 40 +; CHECK-NEXT: - Index: 42 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f42 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 41 +; CHECK-NEXT: - Index: 43 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f43 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 42 +; CHECK-NEXT: - Index: 44 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f44 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 43 +; CHECK-NEXT: - Index: 45 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f45 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 44 +; CHECK-NEXT: - Index: 46 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f46 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 45 +; CHECK-NEXT: - Index: 47 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f47 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 46 +; CHECK-NEXT: - Index: 48 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f48 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 47 +; CHECK-NEXT: - Index: 49 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f49 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 48 +; CHECK-NEXT: - Index: 50 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f50 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 49 +; CHECK-NEXT: - Index: 51 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f51 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 50 +; CHECK-NEXT: - Index: 52 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f52 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 51 +; CHECK-NEXT: - Index: 53 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f53 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 52 +; CHECK-NEXT: - Index: 54 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f54 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 53 +; CHECK-NEXT: - Index: 55 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f55 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 54 +; CHECK-NEXT: - Index: 56 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f56 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 55 +; CHECK-NEXT: - Index: 57 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f57 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 56 +; CHECK-NEXT: - Index: 58 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f58 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 57 +; CHECK-NEXT: - Index: 59 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f59 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 58 +; CHECK-NEXT: - Index: 60 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f60 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 59 +; CHECK-NEXT: - Index: 61 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f61 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 60 +; CHECK-NEXT: - Index: 62 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f62 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 61 +; CHECK-NEXT: - Index: 63 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f63 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 62 +; CHECK-NEXT: - Index: 64 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f64 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 63 +; CHECK-NEXT: - Index: 65 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f65 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 64 +; CHECK-NEXT: - Index: 66 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f66 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 65 +; CHECK-NEXT: - Index: 67 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f67 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 66 +; CHECK-NEXT: - Index: 68 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f68 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 67 +; CHECK-NEXT: - Index: 69 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f69 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 68 +; CHECK-NEXT: - Index: 70 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f70 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 69 +; CHECK-NEXT: - Index: 71 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f71 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 70 +; CHECK-NEXT: - Index: 72 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f72 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 71 +; CHECK-NEXT: - Index: 73 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f73 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 72 +; CHECK-NEXT: - Index: 74 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f74 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 73 +; CHECK-NEXT: - Index: 75 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f75 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 74 +; CHECK-NEXT: - Index: 76 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f76 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 75 +; CHECK-NEXT: - Index: 77 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f77 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 76 +; CHECK-NEXT: - Index: 78 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f78 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 77 +; CHECK-NEXT: - Index: 79 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f79 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 78 +; CHECK-NEXT: - Index: 80 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f80 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 79 +; CHECK-NEXT: - Index: 81 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f81 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 80 +; CHECK-NEXT: - Index: 82 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f82 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 81 +; CHECK-NEXT: - Index: 83 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f83 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 82 +; CHECK-NEXT: - Index: 84 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f84 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 83 +; CHECK-NEXT: - Index: 85 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f85 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 84 +; CHECK-NEXT: - Index: 86 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f86 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 85 +; CHECK-NEXT: - Index: 87 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f87 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 86 +; CHECK-NEXT: - Index: 88 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f88 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 87 +; CHECK-NEXT: - Index: 89 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f89 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 88 +; CHECK-NEXT: - Index: 90 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f90 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 89 +; CHECK-NEXT: - Index: 91 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f91 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 90 +; CHECK-NEXT: - Index: 92 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f92 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 91 +; CHECK-NEXT: - Index: 93 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f93 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 92 +; CHECK-NEXT: - Index: 94 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f94 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 93 +; CHECK-NEXT: - Index: 95 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f95 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 94 +; CHECK-NEXT: - Index: 96 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f96 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 95 +; CHECK-NEXT: - Index: 97 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f97 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 96 +; CHECK-NEXT: - Index: 98 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f98 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 97 +; CHECK-NEXT: - Index: 99 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f99 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 98 +; CHECK-NEXT: - Index: 100 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f100 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 99 +; CHECK-NEXT: - Index: 101 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f101 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 100 +; CHECK-NEXT: - Index: 102 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f102 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 101 +; CHECK-NEXT: - Index: 103 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f103 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 102 +; CHECK-NEXT: - Index: 104 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f104 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 103 +; CHECK-NEXT: - Index: 105 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f105 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 104 +; CHECK-NEXT: - Index: 106 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f106 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 105 +; CHECK-NEXT: - Index: 107 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f107 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 106 +; CHECK-NEXT: - Index: 108 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f108 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 107 +; CHECK-NEXT: - Index: 109 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f109 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 108 +; CHECK-NEXT: - Index: 110 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f110 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 109 +; CHECK-NEXT: - Index: 111 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f111 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 110 +; CHECK-NEXT: - Index: 112 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f112 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 111 +; CHECK-NEXT: - Index: 113 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f113 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 112 +; CHECK-NEXT: - Index: 114 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f114 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 113 +; CHECK-NEXT: - Index: 115 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f115 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 114 +; CHECK-NEXT: - Index: 116 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f116 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 115 +; CHECK-NEXT: - Index: 117 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f117 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 116 +; CHECK-NEXT: - Index: 118 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f118 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 117 +; CHECK-NEXT: - Index: 119 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f119 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 118 +; CHECK-NEXT: - Index: 120 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f120 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 119 +; CHECK-NEXT: - Index: 121 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f121 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 120 +; CHECK-NEXT: - Index: 122 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f122 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 121 +; CHECK-NEXT: - Index: 123 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f123 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 122 +; CHECK-NEXT: - Index: 124 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f124 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 123 +; CHECK-NEXT: - Index: 125 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f125 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 124 +; CHECK-NEXT: - Index: 126 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f126 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 125 +; CHECK-NEXT: - Index: 127 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f127 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 126 +; CHECK-NEXT: - Index: 128 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f128 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 127 +; CHECK-NEXT: - Index: 129 +; CHECK-NEXT: Kind: DATA +; CHECK-NEXT: Name: g0 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: SegmentIndex: 0 +; CHECK-NEXT: Size: 4 +; CHECK-NEXT: - Index: 130 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f129 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 128 +; CHECK-NEXT: - Index: 131 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: func +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 129 ; CHECK-NEXT: SegmentInfo: ; CHECK-NEXT: - Index: 0 ; CHECK-NEXT: Name: .data.g0 Index: test/wasm/relocatable.ll =================================================================== --- test/wasm/relocatable.ll +++ test/wasm/relocatable.ll @@ -59,11 +59,6 @@ ; CHECK-NEXT: Field: bar_import ; CHECK-NEXT: Kind: FUNCTION ; CHECK-NEXT: SigIndex: 1 -; CHECK-NEXT: - Module: env -; CHECK-NEXT: Field: data_import -; CHECK-NEXT: Kind: GLOBAL -; CHECK-NEXT: GlobalType: I32 -; CHECK-NEXT: GlobalMutable: false ; CHECK-NEXT: - Type: FUNCTION ; CHECK-NEXT: FunctionTypes: [ 2, 1, 1 ] ; CHECK-NEXT: - Type: TABLE @@ -76,73 +71,6 @@ ; CHECK-NEXT: - Type: MEMORY ; CHECK-NEXT: Memories: ; CHECK-NEXT: - Initial: 0x00000001 -; CHECK-NEXT: - Type: GLOBAL -; CHECK-NEXT: Globals: -; CHECK-NEXT: - Index: 1 -; CHECK-NEXT: Type: I32 -; CHECK-NEXT: Mutable: false -; CHECK-NEXT: InitExpr: -; CHECK-NEXT: Opcode: I32_CONST -; CHECK-NEXT: Value: 0 -; CHECK-NEXT: - Index: 2 -; CHECK-NEXT: Type: I32 -; CHECK-NEXT: Mutable: false -; CHECK-NEXT: InitExpr: -; CHECK-NEXT: Opcode: I32_CONST -; CHECK-NEXT: Value: 28 -; CHECK-NEXT: - Index: 3 -; CHECK-NEXT: Type: I32 -; CHECK-NEXT: Mutable: false -; CHECK-NEXT: InitExpr: -; CHECK-NEXT: Opcode: I32_CONST -; CHECK-NEXT: Value: 8 -; CHECK-NEXT: - Index: 4 -; CHECK-NEXT: Type: I32 -; CHECK-NEXT: Mutable: false -; CHECK-NEXT: InitExpr: -; CHECK-NEXT: Opcode: I32_CONST -; CHECK-NEXT: Value: 12 -; CHECK-NEXT: - Index: 5 -; CHECK-NEXT: Type: I32 -; CHECK-NEXT: Mutable: false -; CHECK-NEXT: InitExpr: -; CHECK-NEXT: Opcode: I32_CONST -; CHECK-NEXT: Value: 16 -; CHECK-NEXT: - Index: 6 -; CHECK-NEXT: Type: I32 -; CHECK-NEXT: Mutable: false -; CHECK-NEXT: InitExpr: -; CHECK-NEXT: Opcode: I32_CONST -; CHECK-NEXT: Value: 24 -; CHECK-NEXT: - Type: EXPORT -; CHECK-NEXT: Exports: -; CHECK-NEXT: - Name: hello -; CHECK-NEXT: Kind: FUNCTION -; CHECK-NEXT: Index: 3 -; CHECK-NEXT: - Name: my_func -; CHECK-NEXT: Kind: FUNCTION -; CHECK-NEXT: Index: 4 -; CHECK-NEXT: - Name: func_comdat -; CHECK-NEXT: Kind: FUNCTION -; CHECK-NEXT: Index: 5 -; CHECK-NEXT: - Name: hello_str -; CHECK-NEXT: Kind: GLOBAL -; CHECK-NEXT: Index: 1 -; CHECK-NEXT: - Name: data_comdat -; CHECK-NEXT: Kind: GLOBAL -; CHECK-NEXT: Index: 2 -; CHECK-NEXT: - Name: func_addr1 -; CHECK-NEXT: Kind: GLOBAL -; CHECK-NEXT: Index: 3 -; CHECK-NEXT: - Name: func_addr2 -; CHECK-NEXT: Kind: GLOBAL -; CHECK-NEXT: Index: 4 -; CHECK-NEXT: - Name: func_addr3 -; CHECK-NEXT: Kind: GLOBAL -; CHECK-NEXT: Index: 5 -; CHECK-NEXT: - Name: data_addr1 -; CHECK-NEXT: Kind: GLOBAL -; CHECK-NEXT: Index: 6 ; CHECK-NEXT: - Type: ELEM ; CHECK-NEXT: Segments: ; CHECK-NEXT: - Offset: @@ -152,19 +80,19 @@ ; CHECK-NEXT: - Type: CODE ; CHECK-NEXT: Relocations: ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_SLEB -; CHECK-NEXT: Index: 1 +; CHECK-NEXT: Index: 2 ; CHECK-NEXT: Offset: 0x00000004 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_FUNCTION_INDEX_LEB ; CHECK-NEXT: Index: 0 ; CHECK-NEXT: Offset: 0x0000000A ; CHECK-NEXT: - Type: R_WEBASSEMBLY_FUNCTION_INDEX_LEB -; CHECK-NEXT: Index: 1 +; CHECK-NEXT: Index: 3 ; CHECK-NEXT: Offset: 0x00000013 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_FUNCTION_INDEX_LEB -; CHECK-NEXT: Index: 2 +; CHECK-NEXT: Index: 4 ; CHECK-NEXT: Offset: 0x0000001A ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_SLEB -; CHECK-NEXT: Index: 2 +; CHECK-NEXT: Index: 8 ; CHECK-NEXT: Offset: 0x00000026 ; CHECK-NEXT: Functions: ; CHECK-NEXT: - Index: 3 @@ -179,16 +107,16 @@ ; CHECK-NEXT: - Type: DATA ; CHECK-NEXT: Relocations: ; CHECK-NEXT: - Type: R_WEBASSEMBLY_TABLE_INDEX_I32 -; CHECK-NEXT: Index: 4 +; CHECK-NEXT: Index: 6 ; CHECK-NEXT: Offset: 0x00000012 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_TABLE_INDEX_I32 -; CHECK-NEXT: Index: 1 +; CHECK-NEXT: Index: 3 ; CHECK-NEXT: Offset: 0x0000001B ; CHECK-NEXT: - Type: R_WEBASSEMBLY_TABLE_INDEX_I32 -; CHECK-NEXT: Index: 2 +; CHECK-NEXT: Index: 4 ; CHECK-NEXT: Offset: 0x00000024 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_I32 -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 5 ; CHECK-NEXT: Offset: 0x0000002D ; CHECK-NEXT: Segments: ; CHECK-NEXT: - SectionOffset: 6 @@ -230,25 +158,77 @@ ; CHECK-NEXT: - Type: CUSTOM ; CHECK-NEXT: Name: linking ; CHECK-NEXT: DataSize: 31 -; CHECK-NEXT: SymbolInfo: -; CHECK-NEXT: - Name: bar_import -; CHECK-NEXT: Flags: [ BINDING_WEAK ] -; CHECK-NEXT: - Name: hello +; CHECK-NEXT: SymbolTable: +; CHECK-NEXT: - Index: 0 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: puts +; CHECK-NEXT: Flags: [ UNDEFINED ] +; CHECK-NEXT: FunctionIndex: 0 +; CHECK-NEXT: - Index: 1 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: hello ; CHECK-NEXT: Flags: [ VISIBILITY_HIDDEN ] -; CHECK-NEXT: - Name: my_func +; CHECK-NEXT: FunctionIndex: 3 +; CHECK-NEXT: - Index: 2 +; CHECK-NEXT: Kind: DATA +; CHECK-NEXT: Name: hello_str +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: SegmentIndex: 0 +; CHECK-NEXT: Size: 7 +; CHECK-NEXT: - Index: 3 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: foo_import +; CHECK-NEXT: Flags: [ UNDEFINED ] +; CHECK-NEXT: FunctionIndex: 1 +; CHECK-NEXT: - Index: 4 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: bar_import +; CHECK-NEXT: Flags: [ BINDING_WEAK, UNDEFINED ] +; CHECK-NEXT: FunctionIndex: 2 +; CHECK-NEXT: - Index: 5 +; CHECK-NEXT: Kind: DATA +; CHECK-NEXT: Name: data_import +; CHECK-NEXT: Flags: [ UNDEFINED ] +; CHECK-NEXT: - Index: 6 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: my_func ; CHECK-NEXT: Flags: [ VISIBILITY_HIDDEN ] -; CHECK-NEXT: - Name: func_comdat +; CHECK-NEXT: FunctionIndex: 4 +; CHECK-NEXT: - Index: 7 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: func_comdat ; CHECK-NEXT: Flags: [ BINDING_WEAK ] -; CHECK-NEXT: - Name: data_comdat +; CHECK-NEXT: FunctionIndex: 5 +; CHECK-NEXT: - Index: 8 +; CHECK-NEXT: Kind: DATA +; CHECK-NEXT: Name: data_comdat ; CHECK-NEXT: Flags: [ BINDING_WEAK ] -; CHECK-NEXT: - Name: func_addr1 +; CHECK-NEXT: SegmentIndex: 5 +; CHECK-NEXT: Size: 3 +; CHECK-NEXT: - Index: 9 +; CHECK-NEXT: Kind: DATA +; CHECK-NEXT: Name: func_addr1 ; CHECK-NEXT: Flags: [ VISIBILITY_HIDDEN ] -; CHECK-NEXT: - Name: func_addr2 +; CHECK-NEXT: SegmentIndex: 1 +; CHECK-NEXT: Size: 4 +; CHECK-NEXT: - Index: 10 +; CHECK-NEXT: Kind: DATA +; CHECK-NEXT: Name: func_addr2 ; CHECK-NEXT: Flags: [ VISIBILITY_HIDDEN ] -; CHECK-NEXT: - Name: func_addr3 +; CHECK-NEXT: SegmentIndex: 2 +; CHECK-NEXT: Size: 4 +; CHECK-NEXT: - Index: 11 +; CHECK-NEXT: Kind: DATA +; CHECK-NEXT: Name: func_addr3 ; CHECK-NEXT: Flags: [ VISIBILITY_HIDDEN ] -; CHECK-NEXT: - Name: data_addr1 +; CHECK-NEXT: SegmentIndex: 3 +; CHECK-NEXT: Size: 4 +; CHECK-NEXT: - Index: 12 +; CHECK-NEXT: Kind: DATA +; CHECK-NEXT: Name: data_addr1 ; CHECK-NEXT: Flags: [ VISIBILITY_HIDDEN ] +; CHECK-NEXT: SegmentIndex: 4 +; CHECK-NEXT: Size: 4 ; CHECK-NEXT: SegmentInfo: ; CHECK-NEXT: - Index: 0 ; CHECK-NEXT: Name: .rodata.hello_str Index: test/wasm/signature-mismatch.ll =================================================================== --- test/wasm/signature-mismatch.ll +++ test/wasm/signature-mismatch.ll @@ -13,6 +13,6 @@ declare i32 @ret32(i32, i64, i32) local_unnamed_addr #1 -; CHECK: error: function signature mismatch: ret32 +; CHECK: error: Function type mismatch: ret32 ; CHECK-NEXT: >>> defined as (I32, I64, I32) -> I32 in {{.*}}.main.o ; CHECK-NEXT: >>> defined as (F32) -> I32 in {{.*}}.ret32.o Index: test/wasm/stack-pointer.ll =================================================================== --- test/wasm/stack-pointer.ll +++ test/wasm/stack-pointer.ll @@ -26,7 +26,7 @@ ; CHECK-NEXT: Field: __stack_pointer ; CHECK-NEXT: Kind: GLOBAL ; CHECK-NEXT: GlobalType: I32 -; CHECK-NEXT: GlobalMutable: false +; CHECK-NEXT: GlobalMutable: true ; CHECK-NEXT: - Type: FUNCTION ; CHECK-NEXT: FunctionTypes: [ 0 ] ; CHECK-NEXT: - Type: TABLE @@ -39,11 +39,6 @@ ; CHECK-NEXT: - Type: MEMORY ; CHECK-NEXT: Memories: ; CHECK-NEXT: - Initial: 0x00000000 -; CHECK-NEXT: - Type: EXPORT -; CHECK-NEXT: Exports: -; CHECK-NEXT: - Name: _start -; CHECK-NEXT: Kind: FUNCTION -; CHECK-NEXT: Index: 0 ; CHECK-NEXT: - Type: CODE ; CHECK-NEXT: Relocations: ; CHECK-NEXT: - Type: R_WEBASSEMBLY_GLOBAL_INDEX_LEB @@ -56,6 +51,17 @@ ; CHECK-NEXT: - Type: CUSTOM ; CHECK-NEXT: Name: linking ; CHECK-NEXT: DataSize: 0 +; CHECK-NEXT: SymbolTable: +; CHECK-NEXT: - Index: 0 +; CHECK-NEXT: Kind: GLOBAL +; CHECK-NEXT: Name: __stack_pointer +; CHECK-NEXT: Flags: [ UNDEFINED ] +; CHECK-NEXT: GlobalIndex: 0 +; CHECK-NEXT: - Index: 1 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: _start +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: FunctionIndex: 0 ; CHECK-NEXT: - Type: CUSTOM ; CHECK-NEXT: Name: name ; CHECK-NEXT: FunctionNames: Index: test/wasm/symbol-type-mismatch.ll =================================================================== --- test/wasm/symbol-type-mismatch.ll +++ test/wasm/symbol-type-mismatch.ll @@ -7,5 +7,5 @@ @ret32 = extern_weak global i32, align 4 ; CHECK: error: symbol type mismatch: ret32 -; CHECK: >>> defined as Global in {{.*}}symbol-type-mismatch.ll.tmp.o +; CHECK: >>> defined as Data in {{.*}}symbol-type-mismatch.ll.tmp.o ; CHECK: >>> defined as Function in {{.*}}.ret32.o Index: test/wasm/weak-alias.ll =================================================================== --- test/wasm/weak-alias.ll +++ test/wasm/weak-alias.ll @@ -68,9 +68,6 @@ ; CHECK-NEXT: - Name: _start ; CHECK-NEXT: Kind: FUNCTION ; CHECK-NEXT: Index: 0 -; CHECK-NEXT: - Name: alias_fn -; CHECK-NEXT: Kind: FUNCTION -; CHECK-NEXT: Index: 1 ; CHECK-NEXT: - Name: direct_fn ; CHECK-NEXT: Kind: FUNCTION ; CHECK-NEXT: Index: 1 @@ -86,6 +83,9 @@ ; CHECK-NEXT: - Name: call_direct_ptr ; CHECK-NEXT: Kind: FUNCTION ; CHECK-NEXT: Index: 5 +; CHECK-NEXT: - Name: alias_fn +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: - Name: __heap_base ; CHECK-NEXT: Kind: GLOBAL ; CHECK-NEXT: Index: 1 @@ -168,7 +168,7 @@ ; RELOC-NEXT: Field: __stack_pointer ; RELOC-NEXT: Kind: GLOBAL ; RELOC-NEXT: GlobalType: I32 -; RELOC-NEXT: GlobalMutable: false +; RELOC-NEXT: GlobalMutable: true ; RELOC-NEXT: - Type: FUNCTION ; RELOC-NEXT: FunctionTypes: [ 0, 1, 1, 1, 1, 1 ] ; RELOC-NEXT: - Type: TABLE @@ -181,29 +181,6 @@ ; RELOC-NEXT: - Type: MEMORY ; RELOC-NEXT: Memories: ; RELOC-NEXT: - Initial: 0x00000000 -; RELOC-NEXT: - Type: EXPORT -; RELOC-NEXT: Exports: -; RELOC-NEXT: - Name: _start -; RELOC-NEXT: Kind: FUNCTION -; RELOC-NEXT: Index: 0 -; RELOC-NEXT: - Name: alias_fn -; RELOC-NEXT: Kind: FUNCTION -; RELOC-NEXT: Index: 1 -; RELOC-NEXT: - Name: direct_fn -; RELOC-NEXT: Kind: FUNCTION -; RELOC-NEXT: Index: 1 -; RELOC-NEXT: - Name: call_direct -; RELOC-NEXT: Kind: FUNCTION -; RELOC-NEXT: Index: 2 -; RELOC-NEXT: - Name: call_alias -; RELOC-NEXT: Kind: FUNCTION -; RELOC-NEXT: Index: 3 -; RELOC-NEXT: - Name: call_alias_ptr -; RELOC-NEXT: Kind: FUNCTION -; RELOC-NEXT: Index: 4 -; RELOC-NEXT: - Name: call_direct_ptr -; RELOC-NEXT: Kind: FUNCTION -; RELOC-NEXT: Index: 5 ; RELOC-NEXT: - Type: ELEM ; RELOC-NEXT: Segments: ; RELOC-NEXT: - Offset: @@ -213,43 +190,43 @@ ; RELOC-NEXT: - Type: CODE ; RELOC-NEXT: Relocations: ; RELOC-NEXT: - Type: R_WEBASSEMBLY_FUNCTION_INDEX_LEB -; RELOC-NEXT: Index: 1 +; RELOC-NEXT: Index: 7 ; RELOC-NEXT: Offset: 0x00000004 ; RELOC-NEXT: - Type: R_WEBASSEMBLY_FUNCTION_INDEX_LEB -; RELOC-NEXT: Index: 1 +; RELOC-NEXT: Index: 2 ; RELOC-NEXT: Offset: 0x00000013 ; RELOC-NEXT: - Type: R_WEBASSEMBLY_FUNCTION_INDEX_LEB -; RELOC-NEXT: Index: 1 +; RELOC-NEXT: Index: 7 ; RELOC-NEXT: Offset: 0x0000001C ; RELOC-NEXT: - Type: R_WEBASSEMBLY_GLOBAL_INDEX_LEB -; RELOC-NEXT: Index: 0 +; RELOC-NEXT: Index: 1 ; RELOC-NEXT: Offset: 0x00000027 ; RELOC-NEXT: - Type: R_WEBASSEMBLY_GLOBAL_INDEX_LEB -; RELOC-NEXT: Index: 0 +; RELOC-NEXT: Index: 1 ; RELOC-NEXT: Offset: 0x00000032 ; RELOC-NEXT: - Type: R_WEBASSEMBLY_TABLE_INDEX_SLEB -; RELOC-NEXT: Index: 1 +; RELOC-NEXT: Index: 7 ; RELOC-NEXT: Offset: 0x0000003A ; RELOC-NEXT: - Type: R_WEBASSEMBLY_FUNCTION_INDEX_LEB -; RELOC-NEXT: Index: 1 +; RELOC-NEXT: Index: 7 ; RELOC-NEXT: Offset: 0x00000043 ; RELOC-NEXT: - Type: R_WEBASSEMBLY_GLOBAL_INDEX_LEB -; RELOC-NEXT: Index: 0 +; RELOC-NEXT: Index: 1 ; RELOC-NEXT: Offset: 0x00000050 ; RELOC-NEXT: - Type: R_WEBASSEMBLY_GLOBAL_INDEX_LEB -; RELOC-NEXT: Index: 0 +; RELOC-NEXT: Index: 1 ; RELOC-NEXT: Offset: 0x0000005D ; RELOC-NEXT: - Type: R_WEBASSEMBLY_GLOBAL_INDEX_LEB -; RELOC-NEXT: Index: 0 +; RELOC-NEXT: Index: 1 ; RELOC-NEXT: Offset: 0x00000068 ; RELOC-NEXT: - Type: R_WEBASSEMBLY_TABLE_INDEX_SLEB -; RELOC-NEXT: Index: 1 +; RELOC-NEXT: Index: 2 ; RELOC-NEXT: Offset: 0x00000070 ; RELOC-NEXT: - Type: R_WEBASSEMBLY_FUNCTION_INDEX_LEB -; RELOC-NEXT: Index: 1 +; RELOC-NEXT: Index: 2 ; RELOC-NEXT: Offset: 0x00000079 ; RELOC-NEXT: - Type: R_WEBASSEMBLY_GLOBAL_INDEX_LEB -; RELOC-NEXT: Index: 0 +; RELOC-NEXT: Index: 1 ; RELOC-NEXT: Offset: 0x00000086 ; RELOC-NEXT: Functions: ; RELOC-NEXT: - Index: 0 @@ -277,9 +254,47 @@ ; RELOC-NEXT: - Type: CUSTOM ; RELOC-NEXT: Name: linking ; RELOC-NEXT: DataSize: 0 -; RELOC-NEXT: SymbolInfo: -; RELOC-NEXT: - Name: alias_fn +; RELOC-NEXT: SymbolTable: +; RELOC-NEXT: - Index: 0 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: _start +; RELOC-NEXT: Flags: [ ] +; RELOC-NEXT: FunctionIndex: 0 +; RELOC-NEXT: - Index: 1 +; RELOC-NEXT: Kind: GLOBAL +; RELOC-NEXT: Name: __stack_pointer +; RELOC-NEXT: Flags: [ UNDEFINED ] +; RELOC-NEXT: GlobalIndex: 0 +; RELOC-NEXT: - Index: 2 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: direct_fn +; RELOC-NEXT: Flags: [ ] +; RELOC-NEXT: FunctionIndex: 1 +; RELOC-NEXT: - Index: 3 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: call_direct +; RELOC-NEXT: Flags: [ ] +; RELOC-NEXT: FunctionIndex: 2 +; RELOC-NEXT: - Index: 4 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: call_alias +; RELOC-NEXT: Flags: [ ] +; RELOC-NEXT: FunctionIndex: 3 +; RELOC-NEXT: - Index: 5 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: call_alias_ptr +; RELOC-NEXT: Flags: [ ] +; RELOC-NEXT: FunctionIndex: 4 +; RELOC-NEXT: - Index: 6 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: call_direct_ptr +; RELOC-NEXT: Flags: [ ] +; RELOC-NEXT: FunctionIndex: 5 +; RELOC-NEXT: - Index: 7 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: alias_fn ; RELOC-NEXT: Flags: [ BINDING_WEAK ] +; RELOC-NEXT: FunctionIndex: 1 ; RELOC-NEXT: - Type: CUSTOM ; RELOC-NEXT: Name: name ; RELOC-NEXT: FunctionNames: Index: wasm/Driver.cpp =================================================================== --- wasm/Driver.cpp +++ wasm/Driver.cpp @@ -225,8 +225,8 @@ return Arg->getValue(); } -static Symbol* addUndefinedFunction(StringRef Name, const WasmSignature *Type) { - return Symtab->addUndefined(Name, Symbol::UndefinedFunctionKind, 0, nullptr, +static Symbol *addUndefinedFunction(StringRef Name, const WasmSignature *Type) { + return Symtab->addUndefined(Name, WASM_SYMBOL_TYPE_FUNCTION, 0, nullptr, Type); } @@ -298,14 +298,21 @@ Symbol *EntrySym = nullptr; if (!Config->Relocatable) { static WasmSignature NullSignature = {{}, WASM_TYPE_NORESULT}; + static WasmGlobalType StackPointerType = {WASM_TYPE_I32, true}; // Add synthetic symbols before any others WasmSym::CallCtors = Symtab->addSyntheticFunction( "__wasm_call_ctors", &NullSignature, WASM_SYMBOL_VISIBILITY_HIDDEN); - WasmSym::StackPointer = Symtab->addSyntheticGlobal("__stack_pointer"); - WasmSym::HeapBase = Symtab->addSyntheticGlobal("__heap_base"); - WasmSym::DsoHandle = Symtab->addSyntheticGlobal("__dso_handle"); - WasmSym::DataEnd = Symtab->addSyntheticGlobal("__data_end"); + // Can't export the SP right now because it's mutable, and mutable + // globals aren't yet supported in the official binary format. + // TODO(sbc): Remove WASM_SYMBOL_VISIBILITY_HIDDEN if/when the + // "mutable global" proposal is accepted. + WasmSym::StackPointer = Symtab->addSyntheticGlobal( + "__stack_pointer", WASM_SYMBOL_VISIBILITY_HIDDEN, &StackPointerType); + WasmSym::HeapBase = Symtab->addSyntheticData("__heap_base"); + WasmSym::DsoHandle = + Symtab->addSyntheticData("__dso_handle", WASM_SYMBOL_VISIBILITY_HIDDEN); + WasmSym::DataEnd = Symtab->addSyntheticData("__data_end"); if (!Config->Entry.empty()) EntrySym = addUndefinedFunction(Config->Entry, &NullSignature); Index: wasm/InputChunks.h =================================================================== --- wasm/InputChunks.h +++ wasm/InputChunks.h @@ -23,8 +23,10 @@ using llvm::object::WasmSegment; using llvm::wasm::WasmFunction; +using llvm::wasm::WasmGlobal; using llvm::wasm::WasmRelocation; using llvm::wasm::WasmSignature; +using llvm::wasm::WasmInitExpr; using llvm::object::WasmSection; namespace lld { @@ -35,7 +37,7 @@ class InputChunk { public: - enum Kind { DataSegment, Function }; + enum Kind { DataSegment, Function, Global }; Kind kind() const { return SectionKind; } @@ -163,7 +165,9 @@ public: SyntheticFunction(const WasmSignature &S, ArrayRef Body, StringRef Name) - : InputFunction(S, nullptr, nullptr), Name(Name), Body(Body) {} + : InputFunction(S, nullptr, nullptr), Name(Name), Body(Body) { + Live = true; + } StringRef getName() const override { return Name; } @@ -174,6 +178,51 @@ ArrayRef Body; }; +// Represents a single Wasm Global within an input file. These are combined to +// form the final GLOBALS section. +class InputGlobal : public InputChunk { +public: + InputGlobal(const WasmGlobal *G, ObjFile *F) + : InputChunk(F, InputChunk::Global), Global(G) {} + + static bool classof(const InputChunk *C) { + return C->kind() == InputChunk::Global; + } + + StringRef getComdat() const override { return StringRef(); } + uint32_t getOutputIndex() const { return OutputIndex.getValue(); } + bool hasOutputIndex() const { return OutputIndex.hasValue(); } + void setOutputIndex(uint32_t Index); + + virtual const WasmInitExpr &getInitExpr() const { return Global->InitExpr; } + virtual const WasmGlobalType &getType() const { return Global->Type; } + +protected: + // TODO(sbc): Globals don't really belong in this class heirarchy. + // Refactor so to avoid this ugliness. + StringRef getName() const override { return {}; } + ArrayRef data() const override { return {}; } + uint32_t getInputSectionOffset() const override { return 0; } + + const WasmGlobal *Global; + llvm::Optional OutputIndex; +}; + +class SyntheticGlobal : public InputGlobal { +public: + SyntheticGlobal(const WasmGlobalType &Type, const WasmInitExpr &InitExpr) + : InputGlobal(nullptr, nullptr), InitExpr(InitExpr), Type(Type) { + Live = true; + } + + const WasmInitExpr &getInitExpr() const override { return InitExpr; } + const WasmGlobalType &getType() const override { return Type; } + +protected: + WasmInitExpr InitExpr; + const WasmGlobalType Type; +}; + } // namespace wasm } // namespace lld Index: wasm/InputChunks.cpp =================================================================== --- wasm/InputChunks.cpp +++ wasm/InputChunks.cpp @@ -22,7 +22,7 @@ using namespace lld::wasm; uint32_t InputSegment::translateVA(uint32_t Address) const { - assert(Address >= startVA() && Address < endVA()); + assert(Address >= startVA() && Address <= endVA()); int32_t Delta = OutputSeg->StartVA + OutputSegmentOffset - startVA(); DEBUG(dbgs() << "translateVA: " << getName() << " Delta=" << Delta << " Address=" << Address << "\n"); @@ -47,16 +47,17 @@ int64_t ExistingValue; switch (Reloc.Reloc.Type) { case R_WEBASSEMBLY_TYPE_INDEX_LEB: - case R_WEBASSEMBLY_FUNCTION_INDEX_LEB: - case R_WEBASSEMBLY_GLOBAL_INDEX_LEB: ExistingValue = decodeULEB128(Buf); // Additional check to verify that the existing value that the location // matches our expectations. + // TODO(sbc): Perform this extra check for other reloc types too. if (ExistingValue != Reloc.Reloc.Index) { - DEBUG(dbgs() << "existing value: " << decodeULEB128(Buf) << "\n"); - assert(decodeULEB128(Buf) == Reloc.Reloc.Index); + DEBUG(dbgs() << "existing value: " << ExistingValue << "\n"); + assert(ExistingValue == Reloc.Reloc.Index); } LLVM_FALLTHROUGH; + case R_WEBASSEMBLY_FUNCTION_INDEX_LEB: + case R_WEBASSEMBLY_GLOBAL_INDEX_LEB: case R_WEBASSEMBLY_MEMORY_ADDR_LEB: encodeULEB128(Reloc.Value, Buf, 5); break; @@ -123,3 +124,10 @@ assert(!hasTableIndex()); TableIndex = Index; } + +void InputGlobal::setOutputIndex(uint32_t Index) { + DEBUG(dbgs() << "InputGlobal::setOutputIndex: " << getName() << " -> " + << Index << "\n"); + assert(!hasOutputIndex()); + OutputIndex = Index; +} Index: wasm/InputFiles.h =================================================================== --- wasm/InputFiles.h +++ wasm/InputFiles.h @@ -26,6 +26,7 @@ using llvm::object::WasmObjectFile; using llvm::object::WasmSection; using llvm::object::WasmSymbol; +using llvm::wasm::WasmGlobal; using llvm::wasm::WasmImport; using llvm::wasm::WasmSignature; using llvm::wasm::WasmRelocation; @@ -36,6 +37,7 @@ class InputChunk; class InputFunction; class InputSegment; +class InputGlobal; class InputFile { public: @@ -93,7 +95,6 @@ void dumpInfo() const; - uint32_t relocateFunctionIndex(uint32_t Original) const; uint32_t calcNewIndex(const WasmRelocation &Reloc) const; uint32_t calcNewValue(const WasmRelocation &Reloc) const; @@ -104,44 +105,37 @@ std::vector TypeIsUsed; std::vector Segments; std::vector Functions; + std::vector Globals; ArrayRef getSymbols() const { return Symbols; } - - FunctionSymbol *getFunctionSymbol(uint32_t Index) const { - return cast(FunctionSymbols[Index]); - } - - GlobalSymbol *getGlobalSymbol(uint32_t Index) const { - return cast(GlobalSymbols[Index]); - } + Symbol *getSymbol(uint32_t Index) const { return Symbols[Index]; } + FunctionSymbol *getFunctionSymbol(uint32_t Index) const; + DataSymbol *getDataSymbol(uint32_t Index) const; + GlobalSymbol *getGlobalSymbol(uint32_t Index) const; private: uint32_t relocateVirtualAddress(uint32_t Index) const; + uint32_t relocateFunctionIndex(uint32_t Original) const; uint32_t relocateTypeIndex(uint32_t Original) const; uint32_t relocateGlobalIndex(uint32_t Original) const; uint32_t relocateTableIndex(uint32_t Original) const; + uint32_t relocateSymbolIndex(uint32_t Original) const; - Symbol *createDefinedGlobal(const WasmSymbol &Sym, InputChunk *Chunk, - uint32_t Address); + Symbol *createDefinedData(const WasmSymbol &Sym, InputChunk *Chunk, + uint32_t Address, uint32_t DataSize); Symbol *createDefinedFunction(const WasmSymbol &Sym, InputChunk *Chunk); - Symbol *createUndefined(const WasmSymbol &Sym, Symbol::Kind Kind, - const WasmSignature *Signature = nullptr); + Symbol *createDefinedGlobal(const WasmSymbol &Sym, InputChunk *Chunk); + Symbol *createUndefined(const WasmSymbol &Sym); + void initializeSymbols(); InputSegment *getSegment(const WasmSymbol &WasmSym) const; - const WasmSignature *getFunctionSig(const WasmSymbol &Sym) const; - uint32_t getGlobalValue(const WasmSymbol &Sym) const; InputFunction *getFunction(const WasmSymbol &Sym) const; + InputGlobal *getGlobal(const WasmSymbol &Sym) const; bool isExcludedByComdat(InputChunk *Chunk) const; // List of all symbols referenced or defined by this file. std::vector Symbols; - // List of all function symbols indexed by the function index space - std::vector FunctionSymbols; - - // List of all global symbols indexed by the global index space - std::vector GlobalSymbols; - uint32_t NumGlobalImports = 0; uint32_t NumFunctionImports = 0; std::unique_ptr WasmObj; Index: wasm/InputFiles.cpp =================================================================== --- wasm/InputFiles.cpp +++ wasm/InputFiles.cpp @@ -44,14 +44,13 @@ void ObjFile::dumpInfo() const { log("info for: " + getName() + "\n" + - " Total Functions : " + Twine(FunctionSymbols.size()) + "\n" + - " Total Globals : " + Twine(GlobalSymbols.size()) + "\n" + + " Symbols : " + Twine(Symbols.size()) + "\n" + " Function Imports : " + Twine(NumFunctionImports) + "\n" + " Global Imports : " + Twine(NumGlobalImports) + "\n"); } uint32_t ObjFile::relocateVirtualAddress(uint32_t GlobalIndex) const { - if (auto *DG = dyn_cast(getGlobalSymbol(GlobalIndex))) + if (auto *DG = dyn_cast(getDataSymbol(GlobalIndex))) return DG->getVirtualAddress(); else return 0; @@ -72,6 +71,8 @@ uint32_t ObjFile::relocateTableIndex(uint32_t Original) const { const FunctionSymbol *Sym = getFunctionSymbol(Original); + // The null case is possible, if you take the address of a weak function + // that's simply not supplied. uint32_t Index = Sym->hasTableIndex() ? Sym->getTableIndex() : 0; DEBUG(dbgs() << "relocateTableIndex: " << toString(*Sym) << ": " << Original << " -> " << Index << "\n"); @@ -86,26 +87,23 @@ return Index; } +uint32_t ObjFile::relocateSymbolIndex(uint32_t Original) const { + Symbol *Sym = getSymbol(Original); + uint32_t Index = Sym->getOutputSymbolIndex(); + DEBUG(dbgs() << "relocateSymbolIndex: " << toString(*Sym) << ": " << Original + << " -> " << Index << "\n"); + return Index; +} + // Relocations contain an index into the function, global or table index // space of the input file. This function takes a relocation and returns the // relocated index (i.e. translates from the input index space to the output // index space). uint32_t ObjFile::calcNewIndex(const WasmRelocation &Reloc) const { - switch (Reloc.Type) { - case R_WEBASSEMBLY_TYPE_INDEX_LEB: + if (Reloc.Type == R_WEBASSEMBLY_TYPE_INDEX_LEB) return relocateTypeIndex(Reloc.Index); - case R_WEBASSEMBLY_FUNCTION_INDEX_LEB: - case R_WEBASSEMBLY_TABLE_INDEX_I32: - case R_WEBASSEMBLY_TABLE_INDEX_SLEB: - return relocateFunctionIndex(Reloc.Index); - case R_WEBASSEMBLY_GLOBAL_INDEX_LEB: - case R_WEBASSEMBLY_MEMORY_ADDR_LEB: - case R_WEBASSEMBLY_MEMORY_ADDR_SLEB: - case R_WEBASSEMBLY_MEMORY_ADDR_I32: - return relocateGlobalIndex(Reloc.Index); - default: - llvm_unreachable("unknown relocation type"); - } + + return relocateSymbolIndex(Reloc.Index); } // Translate from the relocation's index into the final linked output value. @@ -161,80 +159,62 @@ // Return the InputSegment in which a given symbol is defined. InputSegment *ObjFile::getSegment(const WasmSymbol &WasmSym) const { - uint32_t Address = WasmObj->getWasmSymbolValue(WasmSym); - for (InputSegment *Segment : Segments) { - if (Address >= Segment->startVA() && Address < Segment->endVA()) { - DEBUG(dbgs() << "Found symbol in segment: " << WasmSym.Name << " -> " - << Segment->getName() << "\n"); - - return Segment; - } - } - error("symbol not found in any segment: " + WasmSym.Name); - return nullptr; -} - -// Get the value stored in the wasm global represented by this symbol. -// This represents the virtual address of the symbol in the input file. -uint32_t ObjFile::getGlobalValue(const WasmSymbol &Sym) const { - const WasmGlobal &Global = - getWasmObj()->globals()[Sym.ElementIndex - NumGlobalImports]; - assert(Global.Type.Type == llvm::wasm::WASM_TYPE_I32); - return Global.InitExpr.Value.Int32; -} - -// Get the signature for a given function symbol, either by looking -// it up in function sections (for defined functions), of the imports section -// (for imported functions). -const WasmSignature *ObjFile::getFunctionSig(const WasmSymbol &Sym) const { - DEBUG(dbgs() << "getFunctionSig: " << Sym.Name << "\n"); - return &WasmObj->types()[Sym.FunctionType]; + return Segments[WasmSym.Info.DataRef.Segment]; } InputFunction *ObjFile::getFunction(const WasmSymbol &Sym) const { - uint32_t FunctionIndex = Sym.ElementIndex - NumFunctionImports; + assert(Sym.Info.ElementIndex >= NumFunctionImports); + uint32_t FunctionIndex = Sym.Info.ElementIndex - NumFunctionImports; return Functions[FunctionIndex]; } +InputGlobal *ObjFile::getGlobal(const WasmSymbol &Sym) const { + assert(Sym.Info.ElementIndex >= NumGlobalImports); + uint32_t GlobalIndex = Sym.Info.ElementIndex - NumGlobalImports; + return Globals[GlobalIndex]; +} + bool ObjFile::isExcludedByComdat(InputChunk *Chunk) const { StringRef Comdat = Chunk->getComdat(); return !Comdat.empty() && Symtab->findComdat(Comdat) != this; } +FunctionSymbol *ObjFile::getFunctionSymbol(uint32_t Index) const { + return cast(Symbols[Index]); +} + +GlobalSymbol *ObjFile::getGlobalSymbol(uint32_t Index) const { + return cast(Symbols[Index]); +} + +DataSymbol *ObjFile::getDataSymbol(uint32_t Index) const { + return cast(Symbols[Index]); +} + void ObjFile::initializeSymbols() { Symbols.reserve(WasmObj->getNumberOfSymbols()); - for (const WasmImport &Import : WasmObj->imports()) { - switch (Import.Kind) { - case WASM_EXTERNAL_FUNCTION: - ++NumFunctionImports; - break; - case WASM_EXTERNAL_GLOBAL: - ++NumGlobalImports; - break; - } - } - - FunctionSymbols.resize(NumFunctionImports + WasmObj->functions().size()); - GlobalSymbols.resize(NumGlobalImports + WasmObj->globals().size()); + NumFunctionImports = WasmObj->getNumImportedFunctions(); + NumGlobalImports = WasmObj->getNumImportedGlobals(); ArrayRef Funcs = WasmObj->functions(); ArrayRef FuncTypes = WasmObj->functionTypes(); ArrayRef Types = WasmObj->types(); - ArrayRef Globals = WasmObj->globals(); for (const auto &C : WasmObj->comdats()) Symtab->addComdat(C, this); - FunctionSymbols.resize(NumFunctionImports + Funcs.size()); - GlobalSymbols.resize(NumGlobalImports + Globals.size()); - for (const WasmSegment &S : WasmObj->dataSegments()) { InputSegment *Seg = make(S, this); Seg->copyRelocations(*DataSection); Segments.emplace_back(Seg); } + for (const WasmGlobal &G : WasmObj->globals()) { + InputGlobal *Global = make(&G, this); + Globals.emplace_back(Global); + } + for (size_t I = 0; I < Funcs.size(); ++I) { const WasmFunction &Func = Funcs[I]; const WasmSignature &Sig = Types[FuncTypes[I]]; @@ -243,79 +223,82 @@ Functions.emplace_back(F); } - // Populate `FunctionSymbols` and `GlobalSymbols` based on the WasmSymbols - // in the object + // Populate `Symbols` based on the WasmSymbols in the object for (const SymbolRef &Sym : WasmObj->symbols()) { const WasmSymbol &WasmSym = WasmObj->getWasmSymbol(Sym.getRawDataRefImpl()); Symbol *S; - switch (WasmSym.Type) { - case WasmSymbol::SymbolType::FUNCTION_EXPORT: { - InputFunction *Function = getFunction(WasmSym); - if (!isExcludedByComdat(Function)) { - S = createDefinedFunction(WasmSym, Function); - break; - } else { - Function->Live = false; - LLVM_FALLTHROUGH; // Exclude function, and add the symbol as undefined + switch (WasmSym.Info.Kind) { + case WASM_SYMBOL_TYPE_FUNCTION: + if (WasmSym.isDefined()) { + InputFunction *Function = getFunction(WasmSym); + if (!isExcludedByComdat(Function)) { + S = createDefinedFunction(WasmSym, Function); + break; + } else { + Function->Live = false; + // Exclude function, and add the symbol as undefined + } } - } - case WasmSymbol::SymbolType::FUNCTION_IMPORT: - S = createUndefined(WasmSym, Symbol::Kind::UndefinedFunctionKind, - getFunctionSig(WasmSym)); + S = createUndefined(WasmSym); break; - case WasmSymbol::SymbolType::GLOBAL_EXPORT: { - InputSegment *Segment = getSegment(WasmSym); - if (!isExcludedByComdat(Segment)) { - S = createDefinedGlobal(WasmSym, Segment, getGlobalValue(WasmSym)); - break; - } else { - Segment->Live = false; - LLVM_FALLTHROUGH; // Exclude global, and add the symbol as undefined + case WASM_SYMBOL_TYPE_DATA: + if (WasmSym.isDefined()) { + InputSegment *Segment = getSegment(WasmSym); + if (!isExcludedByComdat(Segment)) { + uint32_t Address = Segment->startVA() + WasmSym.Info.DataRef.Offset; + uint32_t Size = WasmSym.Info.DataRef.Size; + S = createDefinedData(WasmSym, Segment, Address, Size); + break; + } else { + Segment->Live = false; + // Exclude data, and add the symbol as undefined + } } - } - case WasmSymbol::SymbolType::GLOBAL_IMPORT: - S = createUndefined(WasmSym, Symbol::Kind::UndefinedGlobalKind); + S = createUndefined(WasmSym); + break; + case WASM_SYMBOL_TYPE_GLOBAL: + if (WasmSym.isDefined()) + S = createDefinedGlobal(WasmSym, getGlobal(WasmSym)); + else + S = createUndefined(WasmSym); break; } Symbols.push_back(S); - if (WasmSym.isTypeFunction()) { - FunctionSymbols[WasmSym.ElementIndex] = S; - if (WasmSym.HasAltIndex) - FunctionSymbols[WasmSym.AltIndex] = S; - } else { - GlobalSymbols[WasmSym.ElementIndex] = S; - if (WasmSym.HasAltIndex) - GlobalSymbols[WasmSym.AltIndex] = S; - } } +} - DEBUG(for (size_t I = 0; I < FunctionSymbols.size(); ++I) - assert(FunctionSymbols[I] != nullptr); - for (size_t I = 0; I < GlobalSymbols.size(); ++I) - assert(GlobalSymbols[I] != nullptr);); - - DEBUG(dbgs() << "Functions : " << FunctionSymbols.size() << "\n"); - DEBUG(dbgs() << "Globals : " << GlobalSymbols.size() << "\n"); +static WasmSymbolType getType(const WasmSymbol &Sym) { + return static_cast(Sym.Info.Kind); } -Symbol *ObjFile::createUndefined(const WasmSymbol &Sym, Symbol::Kind Kind, - const WasmSignature *Signature) { - return Symtab->addUndefined(Sym.Name, Kind, Sym.Flags, this, Signature); +Symbol *ObjFile::createUndefined(const WasmSymbol &Sym) { + return Symtab->addUndefined(Sym.Info.Name, getType(Sym), Sym.Info.Flags, this, + Sym.FunctionType, Sym.GlobalType); } Symbol *ObjFile::createDefinedFunction(const WasmSymbol &Sym, InputChunk *Chunk) { if (Sym.isBindingLocal()) - return make(Sym.Name, Sym.Flags, this, Chunk); - return Symtab->addDefined(true, Sym.Name, Sym.Flags, this, Chunk); + return make(Sym.Info.Name, Sym.Info.Flags, this, Chunk); + return Symtab->addDefined(Sym.Info.Name, getType(Sym), Sym.Info.Flags, this, + Chunk); +} + +Symbol *ObjFile::createDefinedData(const WasmSymbol &Sym, InputChunk *Chunk, + uint32_t Address, uint32_t Size) { + if (Sym.isBindingLocal()) + return make(Sym.Info.Name, Sym.Info.Flags, this, Chunk, + Address, Size); + return Symtab->addDefined(Sym.Info.Name, getType(Sym), Sym.Info.Flags, this, + Chunk, Address, Size); } -Symbol *ObjFile::createDefinedGlobal(const WasmSymbol &Sym, InputChunk *Chunk, - uint32_t Address) { +Symbol *ObjFile::createDefinedGlobal(const WasmSymbol &Sym, InputChunk *Chunk) { if (Sym.isBindingLocal()) - return make(Sym.Name, Sym.Flags, this, Chunk, Address); - return Symtab->addDefined(false, Sym.Name, Sym.Flags, this, Chunk, Address); + return make(Sym.Info.Name, Sym.Info.Flags, this, Chunk); + return Symtab->addDefined(Sym.Info.Name, getType(Sym), Sym.Info.Flags, this, + Chunk); } void ArchiveFile::parse() { Index: wasm/MarkLive.cpp =================================================================== --- wasm/MarkLive.cpp +++ wasm/MarkLive.cpp @@ -65,25 +65,13 @@ for (const ObjFile *Obj : Symtab->ObjectFiles) { const WasmLinkingData &L = Obj->getWasmObj()->linkingData(); for (const WasmInitFunc &F : L.InitFunctions) - Enqueue(Obj->getFunctionSymbol(F.FunctionIndex)); + Enqueue(Obj->getFunctionSymbol(F.Symbol)); } auto EnqueueSuccessors = [Enqueue](InputChunk &Chunk) { - for (const WasmRelocation Reloc : Chunk.getRelocations()) { - switch (Reloc.Type) { - case R_WEBASSEMBLY_FUNCTION_INDEX_LEB: - case R_WEBASSEMBLY_TABLE_INDEX_I32: - case R_WEBASSEMBLY_TABLE_INDEX_SLEB: - Enqueue(Chunk.File->getFunctionSymbol(Reloc.Index)); - break; - case R_WEBASSEMBLY_GLOBAL_INDEX_LEB: - case R_WEBASSEMBLY_MEMORY_ADDR_LEB: - case R_WEBASSEMBLY_MEMORY_ADDR_SLEB: - case R_WEBASSEMBLY_MEMORY_ADDR_I32: - Enqueue(Chunk.File->getGlobalSymbol(Reloc.Index)); - break; - } - } + for (const WasmRelocation Reloc : Chunk.getRelocations()) + if (Reloc.Type != R_WEBASSEMBLY_TYPE_INDEX_LEB) + Enqueue(Chunk.File->getSymbol(Reloc.Index)); }; while (!Q.empty()) Index: wasm/OutputSegment.h =================================================================== --- wasm/OutputSegment.h +++ wasm/OutputSegment.h @@ -21,7 +21,7 @@ class OutputSegment { public: - OutputSegment(StringRef N) : Name(N) {} + OutputSegment(StringRef N, uint32_t Index) : Name(N), Index(Index) {} void addInputSegment(InputSegment *Segment) { Alignment = std::max(Alignment, Segment->getAlignment()); @@ -36,6 +36,7 @@ void setSectionOffset(uint32_t Offset) { SectionOffset = Offset; } StringRef Name; + const uint32_t Index; uint32_t Alignment = 0; uint32_t StartVA = 0; std::vector InputSegments; Index: wasm/SymbolTable.h =================================================================== --- wasm/SymbolTable.h +++ wasm/SymbolTable.h @@ -18,6 +18,7 @@ #include "llvm/Support/raw_ostream.h" using llvm::wasm::WasmSignature; +using llvm::wasm::WasmGlobalType; namespace lld { namespace wasm { @@ -49,19 +50,23 @@ Symbol *find(StringRef Name); ObjFile *findComdat(StringRef Name) const; - Symbol *addDefined(bool IsFunction, StringRef Name, uint32_t Flags, + Symbol *addDefined(StringRef Name, WasmSymbolType Type, uint32_t Flags, InputFile *F, InputChunk *Chunk = nullptr, - uint32_t Address = 0); - Symbol *addUndefined(StringRef Name, Symbol::Kind Kind, uint32_t Flags, - InputFile *F, const WasmSignature *Signature = nullptr); - Symbol *addUndefinedFunction(StringRef Name, const WasmSignature *Type); + uint32_t Address = 0, uint32_t DataSize = 0); + Symbol *addUndefined(StringRef Name, WasmSymbolType Type, uint32_t Flags, + InputFile *F, const WasmSignature *Signature = nullptr, + const WasmGlobalType *GlobalType = nullptr); + DefinedData *addDefinedData(StringRef Name, uint32_t Flags = 0); void addLazy(ArchiveFile *F, const Archive::Symbol *Sym); bool addComdat(StringRef Name, ObjFile *); - DefinedGlobal *addSyntheticGlobal(StringRef Name, uint32_t Flags = 0); + DefinedData *addSyntheticData(StringRef Name, uint32_t Flags = 0); + DefinedGlobal *addSyntheticGlobal(StringRef Name, uint32_t Flags = 0, + const WasmGlobalType *Type = nullptr); DefinedFunction *addSyntheticFunction(StringRef Name, const WasmSignature *Type, uint32_t Flags = 0); + private: std::pair insert(StringRef Name); Index: wasm/SymbolTable.cpp =================================================================== --- wasm/SymbolTable.cpp +++ wasm/SymbolTable.cpp @@ -80,49 +80,69 @@ // Check the type of new symbol matches that of the symbol is replacing. // For functions this can also involve verifying that the signatures match. static void checkSymbolTypes(const Symbol &Existing, const InputFile &F, - bool NewIsFunction, const WasmSignature *NewSig) { + WasmSymbolType NewType, + const WasmSignature *NewFunctionSig, + const WasmGlobalType *NewGlobalType) { if (Existing.isLazy()) return; + WasmSymbolType ExistingType = Existing.getWasmType(); + // First check the symbol types match (i.e. either both are function // symbols or both are data symbols). - if (Existing.isFunction() != NewIsFunction) { + if (NewType != ExistingType) { error("symbol type mismatch: " + Existing.getName() + "\n>>> defined as " + - (Existing.isFunction() ? "Function" : "Global") + " in " + - toString(Existing.getFile()) + "\n>>> defined as " + - (NewIsFunction ? "Function" : "Global") + " in " + F.getName()); + toString(ExistingType) + " in " + toString(Existing.getFile()) + + "\n>>> defined as " + toString(NewType) + " in " + F.getName()); return; } - // For function symbols, optionally check the function signature matches too. - auto *ExistingFunc = dyn_cast(&Existing); - if (!ExistingFunc || !Config->CheckSignatures) + // For function/global symbols, optionally check the type matches too. + if (NewType == WASM_SYMBOL_TYPE_DATA || !Config->CheckSignatures) return; - // Skip the signature check if the existing function has no signature (e.g. - // if it is an undefined symbol generated by --undefined command line flag). - if (!ExistingFunc->hasFunctionType()) - return; + DEBUG(dbgs() << "checkSymbolTypes: " << Existing.getName() << "\n"); - DEBUG(dbgs() << "checkSymbolTypes: " << ExistingFunc->getName() << "\n"); - assert(NewSig); + auto ReportError = [&](const Twine &Old, const Twine &New) { + error(toString(NewType) + " type mismatch: " + Existing.getName() + + "\n>>> defined as " + Old + " in " + toString(Existing.getFile()) + + "\n>>> defined as " + New + " in " + F.getName()); + }; - const WasmSignature &OldSig = ExistingFunc->getFunctionType(); - if (*NewSig == OldSig) - return; + if (NewType == WASM_SYMBOL_TYPE_FUNCTION) { + // Skip the signature check if the existing function has no signature (e.g. + // if it is an undefined symbol generated by --undefined command line flag). + auto &Sym = cast(Existing); + if (!Sym.hasFunctionType()) + return; - error("function signature mismatch: " + ExistingFunc->getName() + - "\n>>> defined as " + toString(OldSig) + " in " + - toString(ExistingFunc->getFile()) + "\n>>> defined as " + - toString(*NewSig) + " in " + F.getName()); + assert(NewFunctionSig != nullptr); + const WasmSignature &OldSig = Sym.getFunctionType(); + if (*NewFunctionSig == OldSig) + return; + + ReportError(toString(OldSig), toString(*NewFunctionSig)); + } else { + auto &Sym = cast(Existing); + + assert(NewGlobalType != nullptr); + const WasmGlobalType &OldType = Sym.getGlobalType(); + if (*NewGlobalType == OldType) + return; + + ReportError(toString(OldType), toString(*NewGlobalType)); + } } static void checkSymbolTypes(const Symbol &Existing, const InputFile &F, - bool IsFunction, const InputChunk *Chunk) { - const WasmSignature *Sig = nullptr; - if (auto *F = dyn_cast_or_null(Chunk)) - Sig = &F->Signature; - return checkSymbolTypes(Existing, F, IsFunction, Sig); + WasmSymbolType NewType, const InputChunk *Chunk) { + const WasmSignature *FunctionSig = nullptr; + const WasmGlobalType *GlobalType = nullptr; + if (auto *Function = dyn_cast_or_null(Chunk)) + FunctionSig = &Function->Signature; + if (auto *Global = dyn_cast_or_null(Chunk)) + GlobalType = &Global->getType(); + return checkSymbolTypes(Existing, F, NewType, FunctionSig, GlobalType); } DefinedFunction *SymbolTable::addSyntheticFunction(StringRef Name, @@ -136,19 +156,27 @@ return replaceSymbol(S, Name, Flags, Type); } -DefinedGlobal *SymbolTable::addSyntheticGlobal(StringRef Name, uint32_t Flags) { +DefinedData *SymbolTable::addSyntheticData(StringRef Name, uint32_t Flags) { + DEBUG(dbgs() << "addSyntheticData: " << Name << "\n"); + Symbol *S; + bool WasInserted; + std::tie(S, WasInserted) = insert(Name); + return replaceSymbol(S, Name, Flags); +} + +DefinedGlobal *SymbolTable::addSyntheticGlobal(StringRef Name, uint32_t Flags, + const WasmGlobalType *Type) { DEBUG(dbgs() << "addSyntheticGlobal: " << Name << "\n"); Symbol *S; bool WasInserted; std::tie(S, WasInserted) = insert(Name); - assert(WasInserted); - return replaceSymbol(S, Name, Flags); + return replaceSymbol(S, Name, Flags, Type); } -Symbol *SymbolTable::addDefined(bool IsFunction, StringRef Name, uint32_t Flags, - InputFile *F, InputChunk *Chunk, - uint32_t Address) { - if (IsFunction) +Symbol *SymbolTable::addDefined(StringRef Name, WasmSymbolType Type, + uint32_t Flags, InputFile *F, InputChunk *Chunk, + uint32_t Address, uint32_t DataSize) { + if (Type == WASM_SYMBOL_TYPE_FUNCTION) DEBUG(dbgs() << "addDefined: func:" << Name << "\n"); else DEBUG(dbgs() << "addDefined: global:" << Name << " addr:" << Address @@ -186,36 +214,51 @@ if (Replace) { if (CheckTypes) - checkSymbolTypes(*S, *F, IsFunction, Chunk); - if (IsFunction) + checkSymbolTypes(*S, *F, Type, Chunk); + switch (Type) { + case WASM_SYMBOL_TYPE_FUNCTION: replaceSymbol(S, Name, Flags, F, Chunk); - else - replaceSymbol(S, Name, Flags, F, Chunk, Address); + break; + case WASM_SYMBOL_TYPE_DATA: + replaceSymbol(S, Name, Flags, F, Chunk, Address, DataSize); + break; + case WASM_SYMBOL_TYPE_GLOBAL: + replaceSymbol(S, Name, Flags, F, Chunk); + break; + } } return S; } -Symbol *SymbolTable::addUndefined(StringRef Name, Symbol::Kind Kind, +Symbol *SymbolTable::addUndefined(StringRef Name, WasmSymbolType Type, uint32_t Flags, InputFile *F, - const WasmSignature *Type) { - DEBUG(dbgs() << "addUndefined: " << Name << "\n"); + const WasmSignature *FunctionType, + const WasmGlobalType *GlobalType) { + DEBUG(dbgs() << "addUndefined type=" << Type << ": " << Name << "\n"); Symbol *S; bool WasInserted; std::tie(S, WasInserted) = insert(Name); - bool IsFunction = Kind == Symbol::UndefinedFunctionKind; if (WasInserted) { - if (IsFunction) - replaceSymbol(S, Name, Flags, F, Type); - else - replaceSymbol(S, Name, Flags, F); + switch (Type) { + case WASM_SYMBOL_TYPE_FUNCTION: + replaceSymbol(S, Name, Flags, F, FunctionType); + break; + case WASM_SYMBOL_TYPE_GLOBAL: + replaceSymbol(S, Name, Flags, F, GlobalType); + break; + case WASM_SYMBOL_TYPE_DATA: + replaceSymbol(S, Name, Flags, F); + break; + } } else if (auto *LazySym = dyn_cast(S)) { DEBUG(dbgs() << "resolved by existing lazy\n"); auto *AF = cast(LazySym->getFile()); AF->addMember(&LazySym->getArchiveSymbol()); } else if (S->isDefined()) { DEBUG(dbgs() << "resolved by existing\n"); - checkSymbolTypes(*S, *F, IsFunction, Type); + checkSymbolTypes(*S, *F, Type, FunctionType, GlobalType); } + return S; } Index: wasm/Symbols.h =================================================================== --- wasm/Symbols.h +++ wasm/Symbols.h @@ -15,7 +15,11 @@ #include "llvm/Object/Wasm.h" using llvm::object::Archive; +using llvm::object::WasmSymbol; using llvm::wasm::WasmSignature; +using llvm::wasm::WasmGlobal; +using llvm::wasm::WasmGlobalType; +using llvm::wasm::WasmSymbolType; namespace lld { namespace wasm { @@ -30,29 +34,36 @@ public: enum Kind { DefinedFunctionKind, + DefinedDataKind, DefinedGlobalKind, LazyKind, UndefinedFunctionKind, + UndefinedDataKind, UndefinedGlobalKind, LastDefinedKind = DefinedGlobalKind, InvalidKind, }; - Kind kind() const { return static_cast(SymbolKind); } + Kind kind() const { return SymbolKind; } bool isLazy() const { return SymbolKind == LazyKind; } bool isDefined() const { return SymbolKind <= LastDefinedKind; } bool isUndefined() const { - return SymbolKind == UndefinedGlobalKind || - SymbolKind == UndefinedFunctionKind; + return SymbolKind == UndefinedFunctionKind || + SymbolKind == UndefinedDataKind || SymbolKind == UndefinedGlobalKind; } bool isFunction() const { return SymbolKind == DefinedFunctionKind || SymbolKind == UndefinedFunctionKind; } - bool isGlobal() const { return !isFunction(); } + bool isData() const { + return SymbolKind == DefinedDataKind || SymbolKind == UndefinedDataKind; + } + bool isGlobal() const { + return SymbolKind == DefinedGlobalKind || SymbolKind == UndefinedGlobalKind; + } bool isLocal() const; bool isWeak() const; bool isHidden() const; @@ -71,10 +82,18 @@ // Returns true if an output index has been set for this symbol bool hasOutputIndex() const; - // Set the output index of the symbol (in the function or global index - // space of the output object. + // Set the output index of the symbol, in the Wasm index space of the output + // object - that is, for defined symbols only, its position in the list of + // Wasm imports+code for functions, imports+globals for globals. void setOutputIndex(uint32_t Index); + // Get/set the output symbol index, in the Symbol index space. This is + // only used for relocatable output. + uint32_t getOutputSymbolIndex() const; + void setOutputSymbolIndex(uint32_t Index); + + WasmSymbolType getWasmType() const; + protected: Symbol(StringRef Name, Kind K, uint32_t Flags, InputFile *F, InputChunk *C) : Name(Name), SymbolKind(K), Flags(Flags), File(F), Chunk(C) {} @@ -85,6 +104,7 @@ InputFile *File; InputChunk *Chunk; uint32_t OutputIndex = INVALID_INDEX; + uint32_t OutputSymbolIndex = INVALID_INDEX; }; class FunctionSymbol : public Symbol { @@ -114,16 +134,19 @@ uint32_t TableIndex = INVALID_INDEX; - // Explict function type, needed for undefined or synthetic functions only. + // Explicit function type, needed for undefined or synthetic functions only. + // For regular defined functions this information comes from the InputChunk. const WasmSignature *FunctionType = nullptr; }; class DefinedFunction : public FunctionSymbol { public: + // Primary constructor for file-defined functions. DefinedFunction(StringRef Name, uint32_t Flags, InputFile *F = nullptr, InputChunk *C = nullptr) : FunctionSymbol(Name, DefinedFunctionKind, Flags, F, C) {} + // Second constructor used when creating synthetic functions. DefinedFunction(StringRef Name, uint32_t Flags, const WasmSignature *Type) : FunctionSymbol(Name, DefinedFunctionKind, Flags, nullptr, nullptr) { setFunctionType(Type); @@ -132,6 +155,11 @@ static bool classof(const Symbol *S) { return S->kind() == DefinedFunctionKind; } + + // This is used when constructing the __wasm_call_ctors function + // which happens after the DefinedSymbol has been created. + // TODO(sbc): Refactor to avoid the need to handling this special case. + void setChunk(InputChunk *C) { Chunk = C; } }; class UndefinedFunction : public FunctionSymbol { @@ -147,41 +175,94 @@ } }; -class GlobalSymbol : public Symbol { +class DataSymbol : public Symbol { public: static bool classof(const Symbol *S) { - return S->kind() == DefinedGlobalKind || S->kind() == UndefinedGlobalKind; + return S->kind() == DefinedDataKind || S->kind() == UndefinedDataKind; } protected: - GlobalSymbol(StringRef Name, Kind K, uint32_t Flags, InputFile *F, - InputChunk *C) + DataSymbol(StringRef Name, Kind K, uint32_t Flags, InputFile *F, + InputChunk *C) : Symbol(Name, K, Flags, F, C) {} }; -class DefinedGlobal : public GlobalSymbol { +class DefinedData : public DataSymbol { public: - DefinedGlobal(StringRef Name, uint32_t Flags, InputFile *F = nullptr, - InputChunk *C = nullptr, uint32_t Address = 0) - : GlobalSymbol(Name, DefinedGlobalKind, Flags, F, C), - VirtualAddress(Address) {} + DefinedData(StringRef Name, uint32_t Flags, InputFile *F = nullptr, + InputChunk *C = nullptr, uint32_t Address = 0, uint32_t Size = 0) + : DataSymbol(Name, DefinedDataKind, Flags, F, C), VirtualAddress(Address), + Size(Size) {} - static bool classof(const Symbol *S) { - return S->kind() == DefinedGlobalKind; - } + static bool classof(const Symbol *S) { return S->kind() == DefinedDataKind; } + // Returns the output virtual address of a defined data symbol. uint32_t getVirtualAddress() const; void setVirtualAddress(uint32_t VA); + // Returns the offset of a defined data symbol within its OutputSegment. + uint32_t getOutputSegmentOffset() const; + uint32_t getOutputSegmentIndex() const; + uint32_t getSize() const { return Size; } + protected: uint32_t VirtualAddress; + uint32_t Size; +}; + +class UndefinedData : public DataSymbol { +public: + UndefinedData(StringRef Name, uint32_t Flags, InputFile *File = nullptr) + : DataSymbol(Name, UndefinedDataKind, Flags, File, nullptr) {} + static bool classof(const Symbol *S) { + return S->kind() == UndefinedDataKind; + } +}; + +class GlobalSymbol : public Symbol { +public: + static bool classof(const Symbol *S) { + return S->kind() == DefinedGlobalKind || S->kind() == UndefinedGlobalKind; + } + + const WasmGlobalType &getGlobalType() const; + +protected: + void setGlobalType(const WasmGlobalType *Type); + + GlobalSymbol(StringRef Name, Kind K, uint32_t Flags, InputFile *F, + InputChunk *C) + : Symbol(Name, K, Flags, F, C) {} + + // Explicit function type, needed for undefined or synthetic functions only. + // For regular defined globals this information comes from the InputChunk. + const WasmGlobalType *GlobalType = nullptr; +}; + +class DefinedGlobal : public GlobalSymbol { +public: + // Primary constructor for file-defined globals. + DefinedGlobal(StringRef Name, uint32_t Flags, InputFile *File, InputChunk *C) + : GlobalSymbol(Name, DefinedGlobalKind, Flags, File, C) {} + + // Second constructor used when creating synthetic globals. + DefinedGlobal(StringRef Name, uint32_t Flags, const WasmGlobalType *Type) + : GlobalSymbol(Name, DefinedGlobalKind, Flags, nullptr, nullptr) { + setGlobalType(Type); + } + + void setChunk(InputChunk *C) { Chunk = C; } }; class UndefinedGlobal : public GlobalSymbol { public: - UndefinedGlobal(StringRef Name, uint32_t Flags, InputFile *File = nullptr) - : GlobalSymbol(Name, UndefinedGlobalKind, Flags, File, nullptr) {} + UndefinedGlobal(StringRef Name, uint32_t Flags, InputFile *File = nullptr, + const WasmGlobalType *Type = nullptr) + : GlobalSymbol(Name, UndefinedGlobalKind, Flags, File, nullptr) { + setGlobalType(Type); + } + static bool classof(const Symbol *S) { return S->kind() == UndefinedGlobalKind; } @@ -209,13 +290,13 @@ // __data_end // Symbol marking the end of the data and bss. - static DefinedGlobal *DataEnd; + static DefinedData *DataEnd; // __heap_base // Symbol marking the end of the data, bss and explicit stack. Any linear // memory following this address is not used by the linked code and can // therefore be used as a backing store for brk()/malloc() implementations. - static DefinedGlobal *HeapBase; + static DefinedData *HeapBase; // __wasm_call_ctors // Function that directly calls all ctors in priority order. @@ -223,7 +304,7 @@ // __dso_handle // Global used in calls to __cxa_atexit to determine current DLL - static DefinedGlobal *DsoHandle; + static DefinedData *DsoHandle; }; // A buffer class that is large enough to hold any Symbol-derived @@ -231,10 +312,12 @@ // using the placement new. union SymbolUnion { alignas(DefinedFunction) char A[sizeof(DefinedFunction)]; - alignas(DefinedGlobal) char B[sizeof(DefinedGlobal)]; - alignas(LazySymbol) char C[sizeof(LazySymbol)]; - alignas(UndefinedFunction) char D[sizeof(UndefinedFunction)]; - alignas(UndefinedGlobal) char E[sizeof(UndefinedFunction)]; + alignas(DefinedData) char B[sizeof(DefinedData)]; + alignas(DefinedGlobal) char C[sizeof(DefinedGlobal)]; + alignas(LazySymbol) char D[sizeof(LazySymbol)]; + alignas(UndefinedFunction) char E[sizeof(UndefinedFunction)]; + alignas(UndefinedData) char F[sizeof(UndefinedData)]; + alignas(UndefinedGlobal) char G[sizeof(UndefinedGlobal)]; }; template @@ -254,6 +337,7 @@ // Returns a symbol name for an error message. std::string toString(const wasm::Symbol &Sym); std::string toString(wasm::Symbol::Kind Kind); +std::string toString(WasmSymbolType Type); } // namespace lld Index: wasm/Symbols.cpp =================================================================== --- wasm/Symbols.cpp +++ wasm/Symbols.cpp @@ -12,6 +12,7 @@ #include "Config.h" #include "InputChunks.h" #include "InputFiles.h" +#include "OutputSegment.h" #include "lld/Common/ErrorHandler.h" #include "lld/Common/Strings.h" @@ -23,11 +24,27 @@ using namespace lld::wasm; DefinedFunction *WasmSym::CallCtors; -DefinedGlobal *WasmSym::DsoHandle; -DefinedGlobal *WasmSym::DataEnd; -DefinedGlobal *WasmSym::HeapBase; +DefinedData *WasmSym::DsoHandle; +DefinedData *WasmSym::DataEnd; +DefinedData *WasmSym::HeapBase; DefinedGlobal *WasmSym::StackPointer; +WasmSymbolType Symbol::getWasmType() const { + switch (SymbolKind) { + case Symbol::DefinedFunctionKind: + case Symbol::UndefinedFunctionKind: + return llvm::wasm::WASM_SYMBOL_TYPE_FUNCTION; + case Symbol::DefinedDataKind: + case Symbol::UndefinedDataKind: + return llvm::wasm::WASM_SYMBOL_TYPE_DATA; + case Symbol::DefinedGlobalKind: + case Symbol::UndefinedGlobalKind: + return llvm::wasm::WASM_SYMBOL_TYPE_GLOBAL; + default: + llvm_unreachable("invalid symbol kind"); + } +} + bool Symbol::hasOutputIndex() const { if (auto *F = dyn_cast_or_null(Chunk)) return F->hasOutputIndex(); @@ -35,15 +52,30 @@ } uint32_t Symbol::getOutputIndex() const { + assert(!isData()); if (auto *F = dyn_cast_or_null(Chunk)) return F->getOutputIndex(); + if (auto *G = dyn_cast_or_null(Chunk)) + return G->getOutputIndex(); assert(OutputIndex != INVALID_INDEX); return OutputIndex; } +uint32_t Symbol::getOutputSymbolIndex() const { + assert(OutputSymbolIndex != INVALID_INDEX); + return OutputSymbolIndex; +} + +void Symbol::setOutputSymbolIndex(uint32_t Index) { + DEBUG(dbgs() << "setOutputSymbolIndex " << Name << " -> " << Index << "\n"); + assert(OutputSymbolIndex == INVALID_INDEX); + OutputSymbolIndex = Index; +} + void Symbol::setOutputIndex(uint32_t Index) { DEBUG(dbgs() << "setOutputIndex " << Name << " -> " << Index << "\n"); - assert(!dyn_cast_or_null(Chunk)); + assert(!isData()); + assert(!Chunk); assert(OutputIndex == INVALID_INDEX); OutputIndex = Index; } @@ -109,19 +141,45 @@ TableIndex = Index; } -uint32_t DefinedGlobal::getVirtualAddress() const { - assert(isGlobal()); +uint32_t DefinedData::getVirtualAddress() const { DEBUG(dbgs() << "getVirtualAddress: " << getName() << "\n"); return Chunk ? dyn_cast(Chunk)->translateVA(VirtualAddress) : VirtualAddress; } -void DefinedGlobal::setVirtualAddress(uint32_t Value) { +void DefinedData::setVirtualAddress(uint32_t Value) { DEBUG(dbgs() << "setVirtualAddress " << Name << " -> " << Value << "\n"); - assert(isGlobal()); + assert(isData()); VirtualAddress = Value; } +uint32_t DefinedData::getOutputSegmentOffset() const { + DEBUG(dbgs() << "getOutputSegmentOffset: " << getName() << "\n"); + const InputSegment *Segment = dyn_cast(Chunk); + return Segment->OutputSegmentOffset + VirtualAddress - Segment->startVA(); +} + +uint32_t DefinedData::getOutputSegmentIndex() const { + DEBUG(dbgs() << "getOutputSegmentIndex: " << getName() << "\n"); + const InputSegment *Segment = dyn_cast(Chunk); + return Segment->getOutputSegment()->Index; +} + +const WasmGlobalType &GlobalSymbol::getGlobalType() const { + if (auto *G = dyn_cast_or_null(Chunk)) + return G->getType(); + + DEBUG(dbgs() << "getGlobalType: " << getName() << "\n"); + assert(GlobalType != nullptr); + return *GlobalType; +} + +void GlobalSymbol::setGlobalType(const WasmGlobalType *Type) { + assert(GlobalType == nullptr); + assert(!Chunk); + GlobalType = Type; +} + std::string lld::toString(const wasm::Symbol &Sym) { if (Config->Demangle) if (Optional S = demangleItanium(Sym.getName())) @@ -133,14 +191,30 @@ switch (Kind) { case wasm::Symbol::DefinedFunctionKind: return "DefinedFunction"; + case wasm::Symbol::DefinedDataKind: + return "DefinedData"; case wasm::Symbol::DefinedGlobalKind: return "DefinedGlobal"; case wasm::Symbol::UndefinedFunctionKind: return "UndefinedFunction"; + case wasm::Symbol::UndefinedDataKind: + return "UndefinedData"; case wasm::Symbol::UndefinedGlobalKind: return "UndefinedGlobal"; case wasm::Symbol::LazyKind: return "LazyKind"; } - llvm_unreachable("Invalid symbol kind!"); + llvm_unreachable("invalid symbol kind"); +} + +std::string lld::toString(WasmSymbolType Type) { + switch (Type) { + case llvm::wasm::WASM_SYMBOL_TYPE_FUNCTION: + return "Function"; + case llvm::wasm::WASM_SYMBOL_TYPE_DATA: + return "Data"; + case llvm::wasm::WASM_SYMBOL_TYPE_GLOBAL: + return "Global"; + } + llvm_unreachable("invalid symbol type"); } Index: wasm/Writer.cpp =================================================================== --- wasm/Writer.cpp +++ wasm/Writer.cpp @@ -9,7 +9,6 @@ #include "Writer.h" -#include "llvm/ADT/DenseSet.h" #include "Config.h" #include "InputChunks.h" #include "OutputSections.h" @@ -19,6 +18,8 @@ #include "lld/Common/ErrorHandler.h" #include "lld/Common/Memory.h" #include "lld/Common/Threads.h" +#include "llvm/ADT/DenseSet.h" +#include "llvm/BinaryFormat/Wasm.h" #include "llvm/Support/FileOutputBuffer.h" #include "llvm/Support/Format.h" #include "llvm/Support/FormatVariadic.h" @@ -63,10 +64,11 @@ } }; -// A Wasm export to be written into the export section. -struct WasmExportEntry { +// An init entry to be written to either the synthetic init func or the +// linking metadata. +struct WasmInitEntry { const Symbol *Sym; - StringRef FieldName; // may not match the Symbol name + uint32_t Priority; }; // The writer writes a SymbolTable result to a file. @@ -79,11 +81,15 @@ uint32_t lookupType(const WasmSignature &Sig); uint32_t registerType(const WasmSignature &Sig); + void createCtorFunction(); + void createStackPointer(uint32_t Address); + void calculateInitFunctions(); void assignIndexes(); void calculateImports(); void calculateExports(); + void assignSymtab(); void calculateTypes(); void createOutputSegments(); void layoutMemory(); @@ -119,13 +125,16 @@ std::vector Types; DenseMap TypeIndices; - std::vector ImportedFunctions; - std::vector ImportedGlobals; - std::vector ExportedSymbols; - std::vector DefinedGlobals; + std::vector ImportedSymbols; + unsigned NumImportedFunctions = 0; + unsigned NumImportedGlobals = 0; + std::vector ExportedSymbols; + std::vector DefinedFakeGlobals; + std::vector DefinedGlobals; std::vector DefinedFunctions; std::vector IndirectFunctions; - std::vector InitFunctions; + std::vector SymtabEntries; + std::vector InitFunctions; // Elements that are used to construct the final output std::string Header; @@ -134,6 +143,7 @@ std::unique_ptr Buffer; std::unique_ptr CtorFunction; std::string CtorFunctionBody; + std::unique_ptr StackPtrGlobal; std::vector Segments; llvm::SmallDenseMap SegmentMap; @@ -152,7 +162,7 @@ } void Writer::createImportSection() { - uint32_t NumImports = ImportedFunctions.size() + ImportedGlobals.size(); + uint32_t NumImports = ImportedSymbols.size(); if (Config->ImportMemory) ++NumImports; @@ -164,15 +174,6 @@ writeUleb128(OS, NumImports, "import count"); - for (const FunctionSymbol *Sym : ImportedFunctions) { - WasmImport Import; - Import.Module = "env"; - Import.Field = Sym->getName(); - Import.Kind = WASM_EXTERNAL_FUNCTION; - Import.SigIndex = lookupType(Sym->getFunctionType()); - writeImport(OS, Import); - } - if (Config->ImportMemory) { WasmImport Import; Import.Module = "env"; @@ -183,13 +184,18 @@ writeImport(OS, Import); } - for (const Symbol *Sym : ImportedGlobals) { + for (const Symbol *Sym : ImportedSymbols) { WasmImport Import; Import.Module = "env"; Import.Field = Sym->getName(); - Import.Kind = WASM_EXTERNAL_GLOBAL; - Import.Global.Mutable = false; - Import.Global.Type = WASM_TYPE_I32; + if (auto *FunctionSym = dyn_cast(Sym)) { + Import.Kind = WASM_EXTERNAL_FUNCTION; + Import.SigIndex = lookupType(FunctionSym->getFunctionType()); + } else { + auto *GlobalSym = cast(Sym); + Import.Kind = WASM_EXTERNAL_GLOBAL; + Import.Global = GlobalSym->getGlobalType(); + } writeImport(OS, Import); } } @@ -227,17 +233,23 @@ } void Writer::createGlobalSection() { - if (DefinedGlobals.empty()) + unsigned NumGlobals = DefinedGlobals.size() + DefinedFakeGlobals.size(); + if (NumGlobals == 0) return; SyntheticSection *Section = createSyntheticSection(WASM_SEC_GLOBAL); raw_ostream &OS = Section->getStream(); - writeUleb128(OS, DefinedGlobals.size(), "global count"); - for (const DefinedGlobal *Sym : DefinedGlobals) { + writeUleb128(OS, NumGlobals, "global count"); + for (const InputGlobal *G : DefinedGlobals) { WasmGlobal Global; - Global.Type.Type = WASM_TYPE_I32; - Global.Type.Mutable = Sym == WasmSym::StackPointer; + Global.Type = G->getType(); + Global.InitExpr = G->getInitExpr(); + writeGlobal(OS, Global); + } + for (const DefinedData *Sym : DefinedFakeGlobals) { + WasmGlobal Global; + Global.Type = {WASM_TYPE_I32, false}; Global.InitExpr.Opcode = WASM_OPCODE_I32_CONST; Global.InitExpr.Value.Int32 = Sym->getVirtualAddress(); writeGlobal(OS, Global); @@ -285,15 +297,21 @@ writeExport(OS, MemoryExport); } - for (const WasmExportEntry &E : ExportedSymbols) { - DEBUG(dbgs() << "Export: " << E.Sym->getName() << "\n"); + unsigned FakeGlobalIndex = NumImportedGlobals + DefinedGlobals.size(); + for (const Symbol *Sym : ExportedSymbols) { + DEBUG(dbgs() << "Export: " << Sym->getName() << "\n"); WasmExport Export; - Export.Name = E.FieldName; - Export.Index = E.Sym->getOutputIndex(); - if (E.Sym->isFunction()) + Export.Name = Sym->getName(); + if (Sym->isFunction()) { + Export.Index = Sym->getOutputIndex(); Export.Kind = WASM_EXTERNAL_FUNCTION; - else + } else if (Sym->isGlobal()) { + Export.Index = Sym->getOutputIndex(); Export.Kind = WASM_EXTERNAL_GLOBAL; + } else { + Export.Index = FakeGlobalIndex++; + Export.Kind = WASM_EXTERNAL_GLOBAL; + } writeExport(OS, Export); } } @@ -385,28 +403,39 @@ if (!Config->Relocatable) return; - std::vector> SymbolInfo; - auto addSymInfo = [&](const Symbol *Sym, StringRef ExternalName) { - uint32_t Flags = - (Sym->isLocal() ? WASM_SYMBOL_BINDING_LOCAL : - Sym->isWeak() ? WASM_SYMBOL_BINDING_WEAK : 0) | - (Sym->isHidden() ? WASM_SYMBOL_VISIBILITY_HIDDEN : 0); - if (Flags) - SymbolInfo.emplace_back(ExternalName, Flags); - }; - // (Imports can't have internal linkage, their names don't need to be budged.) - for (const Symbol *Sym : ImportedFunctions) - addSymInfo(Sym, Sym->getName()); - for (const Symbol *Sym : ImportedGlobals) - addSymInfo(Sym, Sym->getName()); - for (const WasmExportEntry &E : ExportedSymbols) - addSymInfo(E.Sym, E.FieldName); - if (!SymbolInfo.empty()) { - SubSection SubSection(WASM_SYMBOL_INFO); - writeUleb128(SubSection.getStream(), SymbolInfo.size(), "num sym info"); - for (auto Pair: SymbolInfo) { - writeStr(SubSection.getStream(), Pair.first, "sym name"); - writeUleb128(SubSection.getStream(), Pair.second, "sym flags"); + if (!SymtabEntries.empty()) { + SubSection SubSection(WASM_SYMBOL_TABLE); + writeUleb128(SubSection.getStream(), SymtabEntries.size(), "num symbols"); + for (const Symbol *Sym : SymtabEntries) { + assert(Sym->isDefined() || Sym->isUndefined()); + WasmSymbolType Kind = Sym->getWasmType(); + uint32_t Flags = Sym->isLocal() ? WASM_SYMBOL_BINDING_LOCAL : 0; + if (Sym->isWeak()) + Flags |= WASM_SYMBOL_BINDING_WEAK; + if (Sym->isHidden()) + Flags |= WASM_SYMBOL_VISIBILITY_HIDDEN; + if (Sym->isUndefined()) + Flags |= WASM_SYMBOL_UNDEFINED; + writeUleb128(SubSection.getStream(), Kind, "sym kind"); + writeUleb128(SubSection.getStream(), Flags, "sym flags"); + switch (Kind) { + case llvm::wasm::WASM_SYMBOL_TYPE_FUNCTION: + case llvm::wasm::WASM_SYMBOL_TYPE_GLOBAL: + writeUleb128(SubSection.getStream(), Sym->getOutputIndex(), "index"); + if (Sym->isDefined()) + writeStr(SubSection.getStream(), Sym->getName(), "sym name"); + break; + case llvm::wasm::WASM_SYMBOL_TYPE_DATA: + writeStr(SubSection.getStream(), Sym->getName(), "sym name"); + if (auto *DataSym = dyn_cast(Sym)) { + writeUleb128(SubSection.getStream(), DataSym->getOutputSegmentIndex(), + "index"); + writeUleb128(SubSection.getStream(), + DataSym->getOutputSegmentOffset(), "data offset"); + writeUleb128(SubSection.getStream(), DataSym->getSize(), "data size"); + } + break; + } } SubSection.finalizeContents(); SubSection.writeToStream(OS); @@ -428,9 +457,10 @@ SubSection SubSection(WASM_INIT_FUNCS); writeUleb128(SubSection.getStream(), InitFunctions.size(), "num init functions"); - for (const WasmInitFunc &F : InitFunctions) { + for (const WasmInitEntry &F : InitFunctions) { writeUleb128(SubSection.getStream(), F.Priority, "priority"); - writeUleb128(SubSection.getStream(), F.FunctionIndex, "function index"); + writeUleb128(SubSection.getStream(), F.Sym->getOutputSymbolIndex(), + "function index"); } SubSection.finalizeContents(); SubSection.writeToStream(OS); @@ -477,7 +507,7 @@ // Create the custom "name" section containing debug symbol names. void Writer::createNameSection() { - unsigned NumNames = ImportedFunctions.size(); + unsigned NumNames = NumImportedFunctions; for (const InputFunction *F : DefinedFunctions) if (!F->getName().empty()) ++NumNames; @@ -491,10 +521,12 @@ raw_ostream &OS = FunctionSubsection.getStream(); writeUleb128(OS, NumNames, "name count"); - // Names must appear in function index order. As it happens ImportedFunctions - // and DefinedFunctions are numbers in order with imported functions coming + // Names must appear in function index order. As it happens ImportedSymbols + // and DefinedFunctions are numbered in order with imported functions coming // first. - for (const Symbol *S : ImportedFunctions) { + for (const Symbol *S : ImportedSymbols) { + if (!S->isFunction()) + continue; writeUleb128(OS, S->getOutputIndex(), "import index"); writeStr(OS, S->getName(), "symbol name"); } @@ -564,8 +596,9 @@ debugPrint("mem: stack size = %d\n", Config->ZStackSize); debugPrint("mem: stack base = %d\n", MemoryPtr); MemoryPtr += Config->ZStackSize; - WasmSym::StackPointer->setVirtualAddress(MemoryPtr); + createStackPointer(MemoryPtr); debugPrint("mem: stack top = %d\n", MemoryPtr); + // Set `__heap_base` to directly follow the end of the stack. We don't // allocate any heap memory up front, but instead really on the malloc/brk // implementation growing the memory at runtime. @@ -616,69 +649,93 @@ void Writer::calculateImports() { for (Symbol *Sym : Symtab->getSymbols()) { - if (!Sym->isUndefined() || (Sym->isWeak() && !Config->Relocatable)) + if (!Sym->isUndefined()) + continue; + if (Sym->isData()) + continue; + if (Sym->isWeak() && !Config->Relocatable) continue; - if (auto *F = dyn_cast(Sym)) { - F->setOutputIndex(ImportedFunctions.size()); - ImportedFunctions.push_back(F); - } else if (auto *G = dyn_cast(Sym)) { - G->setOutputIndex(ImportedGlobals.size()); - ImportedGlobals.push_back(G); - } + DEBUG(dbgs() << "import: " << Sym->getName() << "\n"); + Sym->setOutputIndex(ImportedSymbols.size()); + ImportedSymbols.emplace_back(Sym); + if (Sym->isFunction()) + ++NumImportedFunctions; + else + ++NumImportedGlobals; } } void Writer::calculateExports() { - bool ExportHidden = Config->Relocatable; - StringSet<> UsedNames; - - auto BudgeLocalName = [&](const Symbol *Sym) { - StringRef SymName = Sym->getName(); - // We can't budge non-local names. - if (!Sym->isLocal()) - return SymName; - // We must budge local names that have a collision with a symbol that we - // haven't yet processed. - if (!Symtab->find(SymName) && UsedNames.insert(SymName).second) - return SymName; - for (unsigned I = 1; ; ++I) { - std::string NameBuf = (SymName + "." + Twine(I)).str(); - if (!UsedNames.count(NameBuf)) { - StringRef Name = Saver.save(NameBuf); - UsedNames.insert(Name); // Insert must use safe StringRef from save() - return Name; - } + if (Config->Relocatable) + return; + + auto ExportSym = [&](Symbol *Sym) { + if (!Sym->isDefined()) + return; + if (Sym->isHidden() || Sym->isLocal()) + return; + + InputChunk *Chunk = Sym->getChunk(); // null for synthetic data symbols + if (Chunk && !Chunk->Live) + return; + + DEBUG(dbgs() << "exporting sym: " << Sym->getName() << "\n"); + + if (auto *D = dyn_cast(Sym)) { + // TODO Remove this check here; for non-relocatable output we actually + // used only to create fake-global exports for the synthetic symbols. Fix + // this in a future commit + if (Sym != WasmSym::DataEnd && Sym != WasmSym::HeapBase) + return; + DefinedFakeGlobals.emplace_back(D); } + ExportedSymbols.emplace_back(Sym); }; - if (WasmSym::CallCtors && (!WasmSym::CallCtors->isHidden() || ExportHidden)) - ExportedSymbols.emplace_back( - WasmExportEntry{WasmSym::CallCtors, WasmSym::CallCtors->getName()}); + // TODO The two loops below should be replaced with this single loop, with + // ExportSym inlined: + // for (Symbol *Sym : Symtab->getSymbols()) + // ExportSym(Sym); + // Making that change would reorder the output though, so it should be done as + // a separate commit. for (ObjFile *File : Symtab->ObjectFiles) { for (Symbol *Sym : File->getSymbols()) { - if (!Sym->isDefined() || File != Sym->getFile()) - continue; - if (Sym->isGlobal()) - continue; - if (!Sym->getChunk()->Live) - continue; + if (File == Sym->getFile()) + ExportSym(Sym); + } + } + for (Symbol *Sym : Symtab->getSymbols()) { + if (Sym->getFile() == nullptr) + ExportSym(Sym); + } +} + +void Writer::assignSymtab() { + if (!Config->Relocatable) + return; - if ((Sym->isHidden() || Sym->isLocal()) && !ExportHidden) + unsigned SymbolIndex = SymtabEntries.size(); + for (ObjFile *File : Symtab->ObjectFiles) { + DEBUG(dbgs() << "Symtab entries: " << File->getName() << "\n"); + for (Symbol *Sym : File->getSymbols()) { + if (Sym->getFile() != File) continue; - ExportedSymbols.emplace_back(WasmExportEntry{Sym, BudgeLocalName(Sym)}); + if (Sym->isDefined()) { + if (!Sym->getChunk()->Live) + continue; + } else { + assert(Sym->isUndefined()); // Can't be lazy + } + Sym->setOutputSymbolIndex(SymbolIndex++); + SymtabEntries.emplace_back(Sym); } } - for (const Symbol *Sym : DefinedGlobals) { - // Can't export the SP right now because its mutable, and mutuable globals - // are yet supported in the official binary format. - // TODO(sbc): Remove this if/when the "mutable global" proposal is accepted. - if (Sym == WasmSym::StackPointer) - continue; - ExportedSymbols.emplace_back(WasmExportEntry{Sym, BudgeLocalName(Sym)}); - } + // For the moment, relocatable output doesn't contain any synthetic functions, + // so no need to look through the Symtab for symbols not referenced by + // Symtab->ObjectFiles. } uint32_t Writer::lookupType(const WasmSignature &Sig) { @@ -712,45 +769,27 @@ File->TypeMap[I] = registerType(Types[I]); } - for (const FunctionSymbol *Sym : ImportedFunctions) - registerType(Sym->getFunctionType()); + for (const Symbol *Sym : ImportedSymbols) + if (auto *F = dyn_cast(Sym)) + registerType(F->getFunctionType()); for (const InputFunction *F : DefinedFunctions) registerType(F->Signature); } void Writer::assignIndexes() { - uint32_t GlobalIndex = ImportedGlobals.size() + DefinedGlobals.size(); - uint32_t FunctionIndex = ImportedFunctions.size() + DefinedFunctions.size(); - - auto AddDefinedGlobal = [&](DefinedGlobal *Sym) { - if (Sym) { - DefinedGlobals.emplace_back(Sym); - Sym->setOutputIndex(GlobalIndex++); - } - }; - AddDefinedGlobal(WasmSym::StackPointer); - AddDefinedGlobal(WasmSym::HeapBase); - AddDefinedGlobal(WasmSym::DataEnd); - - if (Config->Relocatable) - DefinedGlobals.reserve(Symtab->getSymbols().size()); - - uint32_t TableIndex = kInitialTableOffset; - - if (Config->Relocatable) { - for (ObjFile *File : Symtab->ObjectFiles) { - DEBUG(dbgs() << "Globals: " << File->getName() << "\n"); - for (Symbol *Sym : File->getSymbols()) { - // Create wasm globals for data symbols defined in this file - if (File != Sym->getFile()) - continue; - if (auto *G = dyn_cast(Sym)) - AddDefinedGlobal(G); - } + uint32_t GlobalIndex = NumImportedGlobals + DefinedGlobals.size(); + for (ObjFile *File : Symtab->ObjectFiles) { + DEBUG(dbgs() << "Globals: " << File->getName() << "\n"); + for (InputGlobal *Global : File->Globals) { + if (!Global->Live) + continue; + Global->setOutputIndex(GlobalIndex++); + DefinedGlobals.push_back(Global); } } + uint32_t FunctionIndex = NumImportedFunctions + DefinedFunctions.size(); for (ObjFile *File : Symtab->ObjectFiles) { DEBUG(dbgs() << "Functions: " << File->getName() << "\n"); for (InputFunction *Func : File->Functions) { @@ -761,6 +800,7 @@ } } + uint32_t TableIndex = kInitialTableOffset; for (ObjFile *File : Symtab->ObjectFiles) { DEBUG(dbgs() << "Handle relocs: " << File->getName() << "\n"); auto HandleRelocs = [&](InputChunk *Chunk) { @@ -814,7 +854,7 @@ OutputSegment *&S = SegmentMap[Name]; if (S == nullptr) { DEBUG(dbgs() << "new segment: " << Name << "\n"); - S = make(Name); + S = make(Name, Segments.size()); Segments.push_back(S); } S->addInputSegment(Segment); @@ -829,18 +869,18 @@ // Create synthetic "__wasm_call_ctors" function based on ctor functions // in input object. void Writer::createCtorFunction() { - uint32_t FunctionIndex = ImportedFunctions.size() + DefinedFunctions.size(); + uint32_t FunctionIndex = NumImportedFunctions + DefinedFunctions.size(); WasmSym::CallCtors->setOutputIndex(FunctionIndex); // First write the body bytes to a string. std::string FunctionBody; - static WasmSignature Signature = {{}, WASM_TYPE_NORESULT}; + const WasmSignature &Signature = WasmSym::CallCtors->getFunctionType(); { raw_string_ostream OS(FunctionBody); writeUleb128(OS, 0, "num locals"); - for (const WasmInitFunc &F : InitFunctions) { + for (const WasmInitEntry &F : InitFunctions) { writeU8(OS, OPCODE_CALL, "CALL"); - writeUleb128(OS, F.FunctionIndex, "function index"); + writeUleb128(OS, F.Sym->getOutputIndex(), "function index"); } writeU8(OS, OPCODE_END, "END"); } @@ -856,6 +896,7 @@ CtorFunction = llvm::make_unique( Signature, BodyArray, WasmSym::CallCtors->getName()); CtorFunction->setOutputIndex(FunctionIndex); + WasmSym::CallCtors->setChunk(CtorFunction.get()); DefinedFunctions.emplace_back(CtorFunction.get()); } @@ -867,15 +908,26 @@ const WasmLinkingData &L = File->getWasmObj()->linkingData(); InitFunctions.reserve(InitFunctions.size() + L.InitFunctions.size()); for (const WasmInitFunc &F : L.InitFunctions) - InitFunctions.emplace_back(WasmInitFunc{ - F.Priority, File->relocateFunctionIndex(F.FunctionIndex)}); + InitFunctions.emplace_back( + WasmInitEntry{File->getFunctionSymbol(F.Symbol), F.Priority}); } // Sort in order of priority (lowest first) so that they are called // in the correct order. - std::sort(InitFunctions.begin(), InitFunctions.end(), - [](const WasmInitFunc &L, const WasmInitFunc &R) { - return L.Priority < R.Priority; - }); + std::stable_sort(InitFunctions.begin(), InitFunctions.end(), + [](const WasmInitEntry &L, const WasmInitEntry &R) { + return L.Priority < R.Priority; + }); +} + +void Writer::createStackPointer(uint32_t Address) { + WasmInitExpr InitExpr; + InitExpr.Opcode = WASM_OPCODE_I32_CONST; + InitExpr.Value.Int32 = Address; + StackPtrGlobal = make_unique( + WasmSym::StackPointer->getGlobalType(), InitExpr); + StackPtrGlobal->setOutputIndex(NumImportedGlobals + DefinedGlobals.size()); + DefinedGlobals.emplace_back(StackPtrGlobal.get()); + WasmSym::StackPointer->setChunk(StackPtrGlobal.get()); } void Writer::run() { @@ -883,29 +935,28 @@ calculateImports(); log("-- assignIndexes"); assignIndexes(); - log("-- calculateExports"); - calculateExports(); log("-- calculateInitFunctions"); calculateInitFunctions(); if (!Config->Relocatable) createCtorFunction(); log("-- calculateTypes"); calculateTypes(); + log("-- layoutMemory"); + layoutMemory(); + log("-- calculateExports"); + calculateExports(); + log("-- assignSymtab"); + assignSymtab(); if (errorHandler().Verbose) { log("Defined Functions: " + Twine(DefinedFunctions.size())); log("Defined Globals : " + Twine(DefinedGlobals.size())); - log("Function Imports : " + Twine(ImportedFunctions.size())); - log("Global Imports : " + Twine(ImportedGlobals.size())); - log("Total Imports : " + - Twine(ImportedFunctions.size() + ImportedGlobals.size())); + log("Function Imports : " + Twine(NumImportedFunctions)); + log("Global Imports : " + Twine(NumImportedGlobals)); for (ObjFile *File : Symtab->ObjectFiles) File->dumpInfo(); } - log("-- layoutMemory"); - layoutMemory(); - createHeader(); log("-- createSections"); createSections(); Index: wasm/WriterUtils.h =================================================================== --- wasm/WriterUtils.h +++ wasm/WriterUtils.h @@ -27,6 +27,17 @@ return !(LHS == RHS); } +// Used for general comparison +inline bool operator==(const llvm::wasm::WasmGlobalType &LHS, + const llvm::wasm::WasmGlobalType &RHS) { + return LHS.Type == RHS.Type && LHS.Mutable == RHS.Mutable; +} + +inline bool operator!=(const llvm::wasm::WasmGlobalType &LHS, + const llvm::wasm::WasmGlobalType &RHS) { + return !(LHS == RHS); +} + namespace lld { namespace wasm { @@ -74,6 +85,7 @@ std::string toString(const llvm::wasm::ValType Type); std::string toString(const llvm::wasm::WasmSignature &Sig); +std::string toString(const llvm::wasm::WasmGlobalType &Sig); } // namespace lld Index: wasm/WriterUtils.cpp =================================================================== --- wasm/WriterUtils.cpp +++ wasm/WriterUtils.cpp @@ -216,3 +216,10 @@ S += toString(static_cast(Sig.ReturnType)); return S.str(); } + +std::string lld::toString(const WasmGlobalType &Sig) { + std::string S = toString(static_cast(Sig.Type)); + if (Sig.Mutable) + return "mutable " + S; + return S; +}