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: wasm-ld --check-signatures %t.a %t.o -o %t.wasm +; RUN: wasm-ld --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: wasm-ld --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: Segment: 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: Segment: 1 +; RELOC-NEXT: Size: 4 +; RELOC-NEXT: - Index: 2 +; RELOC-NEXT: Kind: DATA +; RELOC-NEXT: Name: external_ref +; RELOC-NEXT: Flags: [ ] +; RELOC-NEXT: Segment: 2 +; RELOC-NEXT: Size: 4 +; RELOC: - Index: 5 +; RELOC-NEXT: Kind: DATA +; RELOC-NEXT: Name: hello_str +; RELOC-NEXT: Flags: [ ] +; RELOC-NEXT: Segment: 3 +; RELOC-NEXT: Size: 7 Index: test/wasm/init-fini.ll =================================================================== --- test/wasm/init-fini.ll +++ test/wasm/init-fini.ll @@ -107,66 +107,129 @@ ; 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: Function: 0 +; RELOC-NEXT: - Index: 2 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: func2 ; RELOC-NEXT: Flags: [ VISIBILITY_HIDDEN ] -; RELOC-NEXT: - Name: func3 +; RELOC-NEXT: Function: 1 +; RELOC-NEXT: - Index: 3 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: func3 ; RELOC-NEXT: Flags: [ VISIBILITY_HIDDEN ] -; RELOC-NEXT: - Name: func4 +; RELOC-NEXT: Function: 2 +; RELOC-NEXT: - Index: 4 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: func4 ; RELOC-NEXT: Flags: [ VISIBILITY_HIDDEN ] -; RELOC-NEXT: - Name: _start +; RELOC-NEXT: Function: 3 +; RELOC-NEXT: - Index: 5 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: __cxa_atexit +; RELOC-NEXT: Flags: [ ] +; RELOC-NEXT: Function: 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: Function: 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: Function: 6 +; RELOC-NEXT: - Index: 8 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: .Lregister_call_dtors.101 ; RELOC-NEXT: Flags: [ BINDING_LOCAL ] -; RELOC-NEXT: - Name: .Lcall_dtors.1001 +; RELOC-NEXT: Function: 7 +; RELOC-NEXT: - Index: 9 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: .Lcall_dtors.1001 ; RELOC-NEXT: Flags: [ BINDING_LOCAL ] -; RELOC-NEXT: - Name: .Lregister_call_dtors.1001 +; RELOC-NEXT: Function: 8 +; RELOC-NEXT: - Index: 10 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: .Lregister_call_dtors.1001 ; RELOC-NEXT: Flags: [ BINDING_LOCAL ] -; RELOC-NEXT: - Name: myctor +; RELOC-NEXT: Function: 9 +; RELOC-NEXT: - Index: 11 +; RELOC-NEXT: Kind: GLOBAL +; RELOC-NEXT: Name: __stack_pointer +; RELOC-NEXT: Flags: [ UNDEFINED ] +; RELOC-NEXT: Global: 0 +; RELOC-NEXT: - Index: 12 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: myctor ; RELOC-NEXT: Flags: [ VISIBILITY_HIDDEN ] -; RELOC-NEXT: - Name: mydtor +; RELOC-NEXT: Function: 10 +; RELOC-NEXT: - Index: 13 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: mydtor ; RELOC-NEXT: Flags: [ VISIBILITY_HIDDEN ] -; RELOC-NEXT: - Name: .Lcall_dtors.101.1 +; RELOC-NEXT: Function: 11 +; RELOC-NEXT: - Index: 14 +; 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: Function: 12 +; RELOC-NEXT: - Index: 15 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: .Lregister_call_dtors.101 ; RELOC-NEXT: Flags: [ BINDING_LOCAL ] -; RELOC-NEXT: - Name: .Lcall_dtors.202 +; RELOC-NEXT: Function: 13 +; RELOC-NEXT: - Index: 16 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: .Lcall_dtors.202 ; RELOC-NEXT: Flags: [ BINDING_LOCAL ] -; RELOC-NEXT: - Name: .Lregister_call_dtors.202 +; RELOC-NEXT: Function: 14 +; RELOC-NEXT: - Index: 17 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: .Lregister_call_dtors.202 ; RELOC-NEXT: Flags: [ BINDING_LOCAL ] -; RELOC-NEXT: - Name: .Lcall_dtors.2002 +; RELOC-NEXT: Function: 15 +; RELOC-NEXT: - Index: 18 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: .Lcall_dtors.2002 ; RELOC-NEXT: Flags: [ BINDING_LOCAL ] -; RELOC-NEXT: - Name: .Lregister_call_dtors.2002 +; RELOC-NEXT: Function: 16 +; RELOC-NEXT: - Index: 19 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: .Lregister_call_dtors.2002 ; RELOC-NEXT: Flags: [ BINDING_LOCAL ] +; RELOC-NEXT: Function: 17 ; 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: 10 +; RELOC-NEXT: Symbol: 12 ; RELOC-NEXT: - Priority: 101 -; RELOC-NEXT: FunctionIndex: 13 +; RELOC-NEXT: Symbol: 15 ; RELOC-NEXT: - Priority: 202 -; RELOC-NEXT: FunctionIndex: 10 +; RELOC-NEXT: Symbol: 12 ; RELOC-NEXT: - Priority: 202 -; RELOC-NEXT: FunctionIndex: 15 +; RELOC-NEXT: Symbol: 17 ; RELOC-NEXT: - Priority: 1001 -; RELOC-NEXT: FunctionIndex: 0 +; RELOC-NEXT: Symbol: 1 ; RELOC-NEXT: - Priority: 1001 -; RELOC-NEXT: FunctionIndex: 9 +; RELOC-NEXT: Symbol: 10 ; RELOC-NEXT: - Priority: 2002 -; RELOC-NEXT: FunctionIndex: 10 +; RELOC-NEXT: Symbol: 12 ; RELOC-NEXT: - Priority: 2002 -; RELOC-NEXT: FunctionIndex: 17 +; RELOC-NEXT: Symbol: 19 ; 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: Function: 0 +; RELOC-NEXT: - Index: 1 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: colliding_func2 +; RELOC-NEXT: Flags: [ ] +; RELOC-NEXT: Function: 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: Function: 2 +; RELOC-NEXT: - Index: 3 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: get_global1A +; RELOC-NEXT: Flags: [ ] +; RELOC-NEXT: Function: 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: Segment: 0 +; RELOC-NEXT: Size: 4 +; RELOC-NEXT: - Index: 5 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: get_global2A +; RELOC-NEXT: Flags: [ ] +; RELOC-NEXT: Function: 4 +; RELOC-NEXT: - Index: 6 +; RELOC-NEXT: Kind: DATA +; RELOC-NEXT: Name: colliding_global2 +; RELOC-NEXT: Flags: [ ] +; RELOC-NEXT: Segment: 1 +; RELOC-NEXT: Size: 4 +; RELOC-NEXT: - Index: 7 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: get_global3A +; RELOC-NEXT: Flags: [ ] +; RELOC-NEXT: Function: 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: Segment: 2 +; RELOC-NEXT: Size: 4 +; RELOC-NEXT: - Index: 9 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: get_func1A +; RELOC-NEXT: Flags: [ ] +; RELOC-NEXT: Function: 6 +; RELOC-NEXT: - Index: 10 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: get_func2A +; RELOC-NEXT: Flags: [ ] +; RELOC-NEXT: Function: 7 +; RELOC-NEXT: - Index: 11 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: get_func3A +; RELOC-NEXT: Flags: [ ] +; RELOC-NEXT: Function: 8 +; RELOC-NEXT: - Index: 12 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: colliding_func1 +; RELOC-NEXT: Flags: [ ] +; RELOC-NEXT: Function: 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: Function: 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: Function: 11 +; RELOC-NEXT: - Index: 15 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: get_global1B +; RELOC-NEXT: Flags: [ ] +; RELOC-NEXT: Function: 12 +; RELOC-NEXT: - Index: 16 +; RELOC-NEXT: Kind: DATA +; RELOC-NEXT: Name: colliding_global1 +; RELOC-NEXT: Flags: [ ] +; RELOC-NEXT: Segment: 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: Function: 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: Segment: 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: Function: 14 +; RELOC-NEXT: - Index: 20 +; RELOC-NEXT: Kind: DATA +; RELOC-NEXT: Name: colliding_global3 ; RELOC-NEXT: Flags: [ BINDING_LOCAL ] +; RELOC-NEXT: Segment: 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: Function: 15 +; RELOC-NEXT: - Index: 22 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: get_func2B +; RELOC-NEXT: Flags: [ ] +; RELOC-NEXT: Function: 16 +; RELOC-NEXT: - Index: 23 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: get_func3B +; RELOC-NEXT: Flags: [ ] +; RELOC-NEXT: Function: 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: Function: 0 +; CHECK-NEXT: - Index: 1 +; CHECK-NEXT: Kind: DATA +; CHECK-NEXT: Name: foo +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Segment: 1 +; CHECK-NEXT: Size: 4 +; CHECK-NEXT: - Index: 2 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f2 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 1 +; CHECK-NEXT: - Index: 3 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f3 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 2 +; CHECK-NEXT: - Index: 4 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f4 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 3 +; CHECK-NEXT: - Index: 5 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f5 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 4 +; CHECK-NEXT: - Index: 6 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f6 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 5 +; CHECK-NEXT: - Index: 7 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f7 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 6 +; CHECK-NEXT: - Index: 8 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f8 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 7 +; CHECK-NEXT: - Index: 9 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f9 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 8 +; CHECK-NEXT: - Index: 10 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f10 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 9 +; CHECK-NEXT: - Index: 11 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f11 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 10 +; CHECK-NEXT: - Index: 12 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f12 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 11 +; CHECK-NEXT: - Index: 13 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f13 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 12 +; CHECK-NEXT: - Index: 14 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f14 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 13 +; CHECK-NEXT: - Index: 15 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f15 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 14 +; CHECK-NEXT: - Index: 16 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f16 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 15 +; CHECK-NEXT: - Index: 17 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f17 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 16 +; CHECK-NEXT: - Index: 18 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f18 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 17 +; CHECK-NEXT: - Index: 19 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f19 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 18 +; CHECK-NEXT: - Index: 20 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f20 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 19 +; CHECK-NEXT: - Index: 21 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f21 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 20 +; CHECK-NEXT: - Index: 22 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f22 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 21 +; CHECK-NEXT: - Index: 23 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f23 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 22 +; CHECK-NEXT: - Index: 24 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f24 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 23 +; CHECK-NEXT: - Index: 25 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f25 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 24 +; CHECK-NEXT: - Index: 26 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f26 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 25 +; CHECK-NEXT: - Index: 27 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f27 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 26 +; CHECK-NEXT: - Index: 28 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f28 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 27 +; CHECK-NEXT: - Index: 29 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f29 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 28 +; CHECK-NEXT: - Index: 30 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f30 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 29 +; CHECK-NEXT: - Index: 31 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f31 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 30 +; CHECK-NEXT: - Index: 32 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f32 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 31 +; CHECK-NEXT: - Index: 33 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f33 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 32 +; CHECK-NEXT: - Index: 34 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f34 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 33 +; CHECK-NEXT: - Index: 35 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f35 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 34 +; CHECK-NEXT: - Index: 36 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f36 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 35 +; CHECK-NEXT: - Index: 37 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f37 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 36 +; CHECK-NEXT: - Index: 38 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f38 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 37 +; CHECK-NEXT: - Index: 39 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f39 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 38 +; CHECK-NEXT: - Index: 40 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f40 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 39 +; CHECK-NEXT: - Index: 41 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f41 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 40 +; CHECK-NEXT: - Index: 42 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f42 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 41 +; CHECK-NEXT: - Index: 43 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f43 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 42 +; CHECK-NEXT: - Index: 44 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f44 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 43 +; CHECK-NEXT: - Index: 45 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f45 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 44 +; CHECK-NEXT: - Index: 46 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f46 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 45 +; CHECK-NEXT: - Index: 47 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f47 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 46 +; CHECK-NEXT: - Index: 48 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f48 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 47 +; CHECK-NEXT: - Index: 49 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f49 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 48 +; CHECK-NEXT: - Index: 50 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f50 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 49 +; CHECK-NEXT: - Index: 51 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f51 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 50 +; CHECK-NEXT: - Index: 52 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f52 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 51 +; CHECK-NEXT: - Index: 53 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f53 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 52 +; CHECK-NEXT: - Index: 54 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f54 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 53 +; CHECK-NEXT: - Index: 55 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f55 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 54 +; CHECK-NEXT: - Index: 56 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f56 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 55 +; CHECK-NEXT: - Index: 57 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f57 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 56 +; CHECK-NEXT: - Index: 58 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f58 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 57 +; CHECK-NEXT: - Index: 59 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f59 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 58 +; CHECK-NEXT: - Index: 60 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f60 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 59 +; CHECK-NEXT: - Index: 61 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f61 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 60 +; CHECK-NEXT: - Index: 62 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f62 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 61 +; CHECK-NEXT: - Index: 63 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f63 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 62 +; CHECK-NEXT: - Index: 64 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f64 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 63 +; CHECK-NEXT: - Index: 65 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f65 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 64 +; CHECK-NEXT: - Index: 66 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f66 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 65 +; CHECK-NEXT: - Index: 67 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f67 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 66 +; CHECK-NEXT: - Index: 68 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f68 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 67 +; CHECK-NEXT: - Index: 69 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f69 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 68 +; CHECK-NEXT: - Index: 70 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f70 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 69 +; CHECK-NEXT: - Index: 71 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f71 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 70 +; CHECK-NEXT: - Index: 72 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f72 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 71 +; CHECK-NEXT: - Index: 73 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f73 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 72 +; CHECK-NEXT: - Index: 74 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f74 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 73 +; CHECK-NEXT: - Index: 75 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f75 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 74 +; CHECK-NEXT: - Index: 76 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f76 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 75 +; CHECK-NEXT: - Index: 77 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f77 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 76 +; CHECK-NEXT: - Index: 78 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f78 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 77 +; CHECK-NEXT: - Index: 79 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f79 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 78 +; CHECK-NEXT: - Index: 80 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f80 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 79 +; CHECK-NEXT: - Index: 81 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f81 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 80 +; CHECK-NEXT: - Index: 82 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f82 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 81 +; CHECK-NEXT: - Index: 83 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f83 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 82 +; CHECK-NEXT: - Index: 84 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f84 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 83 +; CHECK-NEXT: - Index: 85 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f85 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 84 +; CHECK-NEXT: - Index: 86 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f86 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 85 +; CHECK-NEXT: - Index: 87 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f87 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 86 +; CHECK-NEXT: - Index: 88 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f88 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 87 +; CHECK-NEXT: - Index: 89 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f89 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 88 +; CHECK-NEXT: - Index: 90 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f90 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 89 +; CHECK-NEXT: - Index: 91 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f91 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 90 +; CHECK-NEXT: - Index: 92 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f92 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 91 +; CHECK-NEXT: - Index: 93 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f93 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 92 +; CHECK-NEXT: - Index: 94 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f94 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 93 +; CHECK-NEXT: - Index: 95 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f95 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 94 +; CHECK-NEXT: - Index: 96 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f96 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 95 +; CHECK-NEXT: - Index: 97 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f97 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 96 +; CHECK-NEXT: - Index: 98 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f98 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 97 +; CHECK-NEXT: - Index: 99 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f99 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 98 +; CHECK-NEXT: - Index: 100 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f100 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 99 +; CHECK-NEXT: - Index: 101 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f101 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 100 +; CHECK-NEXT: - Index: 102 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f102 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 101 +; CHECK-NEXT: - Index: 103 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f103 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 102 +; CHECK-NEXT: - Index: 104 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f104 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 103 +; CHECK-NEXT: - Index: 105 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f105 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 104 +; CHECK-NEXT: - Index: 106 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f106 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 105 +; CHECK-NEXT: - Index: 107 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f107 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 106 +; CHECK-NEXT: - Index: 108 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f108 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 107 +; CHECK-NEXT: - Index: 109 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f109 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 108 +; CHECK-NEXT: - Index: 110 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f110 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 109 +; CHECK-NEXT: - Index: 111 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f111 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 110 +; CHECK-NEXT: - Index: 112 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f112 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 111 +; CHECK-NEXT: - Index: 113 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f113 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 112 +; CHECK-NEXT: - Index: 114 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f114 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 113 +; CHECK-NEXT: - Index: 115 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f115 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 114 +; CHECK-NEXT: - Index: 116 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f116 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 115 +; CHECK-NEXT: - Index: 117 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f117 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 116 +; CHECK-NEXT: - Index: 118 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f118 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 117 +; CHECK-NEXT: - Index: 119 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f119 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 118 +; CHECK-NEXT: - Index: 120 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f120 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 119 +; CHECK-NEXT: - Index: 121 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f121 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 120 +; CHECK-NEXT: - Index: 122 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f122 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 121 +; CHECK-NEXT: - Index: 123 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f123 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 122 +; CHECK-NEXT: - Index: 124 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f124 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 123 +; CHECK-NEXT: - Index: 125 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f125 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 124 +; CHECK-NEXT: - Index: 126 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f126 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 125 +; CHECK-NEXT: - Index: 127 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f127 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 126 +; CHECK-NEXT: - Index: 128 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f128 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 127 +; CHECK-NEXT: - Index: 129 +; CHECK-NEXT: Kind: DATA +; CHECK-NEXT: Name: g0 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Segment: 0 +; CHECK-NEXT: Size: 4 +; CHECK-NEXT: - Index: 130 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: f129 +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 128 +; CHECK-NEXT: - Index: 131 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: func +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 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: Function: 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: Function: 3 +; CHECK-NEXT: - Index: 2 +; CHECK-NEXT: Kind: DATA +; CHECK-NEXT: Name: hello_str +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Segment: 0 +; CHECK-NEXT: Size: 7 +; CHECK-NEXT: - Index: 3 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: foo_import +; CHECK-NEXT: Flags: [ UNDEFINED ] +; CHECK-NEXT: Function: 1 +; CHECK-NEXT: - Index: 4 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: bar_import +; CHECK-NEXT: Flags: [ BINDING_WEAK, UNDEFINED ] +; CHECK-NEXT: Function: 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: Function: 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: Function: 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: Segment: 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: Segment: 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: Segment: 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: Segment: 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: Segment: 4 +; CHECK-NEXT: Size: 4 ; CHECK-NEXT: SegmentInfo: ; CHECK-NEXT: - Index: 0 ; CHECK-NEXT: Name: .rodata.hello_str Index: test/wasm/signature-mismatch-weak.ll =================================================================== --- test/wasm/signature-mismatch-weak.ll +++ test/wasm/signature-mismatch-weak.ll @@ -14,6 +14,6 @@ ret void } -; CHECK: error: function signature mismatch: weakFn +; CHECK: error: Function type mismatch: weakFn ; CHECK-NEXT: >>> defined as () -> I32 in {{.*}}signature-mismatch-weak.ll.tmp.o ; CHECK-NEXT: >>> defined as () -> I64 in {{.*}}signature-mismatch-weak.ll.tmp.strong.o Index: test/wasm/signature-mismatch.ll =================================================================== --- test/wasm/signature-mismatch.ll +++ test/wasm/signature-mismatch.ll @@ -17,10 +17,10 @@ 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 -; REVERSE: error: function signature mismatch: ret32 +; REVERSE: error: Function type mismatch: ret32 ; REVERSE-NEXT: >>> defined as (F32) -> I32 in {{.*}}.ret32.o ; REVERSE-NEXT: >>> defined as (I32, I64, I32) -> I32 in {{.*}}.main.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: Global: 0 +; CHECK-NEXT: - Index: 1 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: _start +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 0 ; CHECK-NEXT: - Type: CUSTOM ; CHECK-NEXT: Name: name ; CHECK-NEXT: FunctionNames: 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: Function: 0 +; RELOC-NEXT: - Index: 1 +; RELOC-NEXT: Kind: GLOBAL +; RELOC-NEXT: Name: __stack_pointer +; RELOC-NEXT: Flags: [ UNDEFINED ] +; RELOC-NEXT: Global: 0 +; RELOC-NEXT: - Index: 2 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: direct_fn +; RELOC-NEXT: Flags: [ ] +; RELOC-NEXT: Function: 1 +; RELOC-NEXT: - Index: 3 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: call_direct +; RELOC-NEXT: Flags: [ ] +; RELOC-NEXT: Function: 2 +; RELOC-NEXT: - Index: 4 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: call_alias +; RELOC-NEXT: Flags: [ ] +; RELOC-NEXT: Function: 3 +; RELOC-NEXT: - Index: 5 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: call_alias_ptr +; RELOC-NEXT: Flags: [ ] +; RELOC-NEXT: Function: 4 +; RELOC-NEXT: - Index: 6 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: call_direct_ptr +; RELOC-NEXT: Flags: [ ] +; RELOC-NEXT: Function: 5 +; RELOC-NEXT: - Index: 7 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: alias_fn ; RELOC-NEXT: Flags: [ BINDING_WEAK ] +; RELOC-NEXT: Function: 1 ; RELOC-NEXT: - Type: CUSTOM ; RELOC-NEXT: Name: name ; RELOC-NEXT: FunctionNames: Index: wasm/Driver.cpp =================================================================== --- wasm/Driver.cpp +++ wasm/Driver.cpp @@ -9,6 +9,7 @@ #include "lld/Common/Driver.h" #include "Config.h" +#include "InputGlobal.h" #include "MarkLive.h" #include "SymbolTable.h" #include "Writer.h" @@ -59,6 +60,7 @@ void addFile(StringRef Path); void addLibrary(StringRef Name); std::vector Files; + llvm::wasm::WasmGlobal StackPointerGlobal; }; } // anonymous namespace @@ -222,8 +224,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); } @@ -296,14 +298,25 @@ Symbol *EntrySym = nullptr; if (!Config->Relocatable) { - static WasmSignature NullSignature = {{}, WASM_TYPE_NORESULT}; + // 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. + StackPointerGlobal.Type = {WASM_TYPE_I32, true}; + StackPointerGlobal.InitExpr.Value.Int32 = 0; + StackPointerGlobal.InitExpr.Opcode = WASM_OPCODE_I32_CONST; + InputGlobal *StackPointer = make(StackPointerGlobal); + StackPointer->Live = true; + static WasmSignature NullSignature = {{}, WASM_TYPE_NORESULT}; // Add synthetic symbols before any others WasmSym::CallCtors = Symtab->addSyntheticFunction( "__wasm_call_ctors", &NullSignature, WASM_SYMBOL_VISIBILITY_HIDDEN); - WasmSym::StackPointer = Symtab->addSyntheticDataSymbol("__stack_pointer"); + WasmSym::StackPointer = Symtab->addSyntheticGlobal( + "__stack_pointer", WASM_SYMBOL_VISIBILITY_HIDDEN, StackPointer); WasmSym::HeapBase = Symtab->addSyntheticDataSymbol("__heap_base"); - WasmSym::DsoHandle = Symtab->addSyntheticDataSymbol("__dso_handle"); + WasmSym::DsoHandle = Symtab->addSyntheticDataSymbol( + "__dso_handle", WASM_SYMBOL_VISIBILITY_HIDDEN); WasmSym::DataEnd = Symtab->addSyntheticDataSymbol("__data_end"); if (!Config->Entry.empty()) Index: wasm/InputChunks.h =================================================================== --- wasm/InputChunks.h +++ wasm/InputChunks.h @@ -7,8 +7,14 @@ // //===----------------------------------------------------------------------===// // -// An input chunk represents an indivisible blocks of code or data from an input -// file. i.e. a single wasm data segment or a single wasm function. +// An InputChunks represents an indivisible opaque region of a input wasm file. +// i.e. a single wasm data segment or a single wasm function. +// +// They are written directly to the mmap'd output file after which relocations +// are applied. Because each Chunk is independent they can be written in +// parallel. +// +// Chunks are also unit on which garbage collection (--gc-sections) operates. // //===----------------------------------------------------------------------===// @@ -92,7 +98,7 @@ // Translate an offset in the input segment to an offset in the output // segment. - uint32_t translateVA(uint32_t Address) const; + uint32_t translateVA(uint32_t Offset) const; const OutputSegment *getOutputSegment() const { return OutputSeg; } @@ -102,8 +108,6 @@ } uint32_t getAlignment() const { return Segment.Data.Alignment; } - uint32_t startVA() const { return Segment.Data.Offset.Value.Int32; } - uint32_t endVA() const { return startVA() + getSize(); } StringRef getName() const override { return Segment.Data.Name; } StringRef getComdat() const override { return Segment.Data.Comdat; } Index: wasm/InputChunks.cpp =================================================================== --- wasm/InputChunks.cpp +++ wasm/InputChunks.cpp @@ -27,12 +27,10 @@ return (toString(C->File) + ":(" + C->getName() + ")").str(); } -uint32_t InputSegment::translateVA(uint32_t Address) const { - assert(Address >= startVA() && Address < endVA()); - int32_t Delta = OutputSeg->StartVA + OutputSegmentOffset - startVA(); - DEBUG(dbgs() << "translateVA: " << getName() << " Delta=" << Delta - << " Address=" << Address << "\n"); - return Address + Delta; +uint32_t InputSegment::translateVA(uint32_t Offset) const { + assert(Offset <= getSize()); + DEBUG(dbgs() << "translateVA: " << getName() << " Offset=" << Offset << "\n"); + return OutputSeg->StartVA + OutputSegmentOffset + Offset; } void InputChunk::copyRelocations(const WasmSection &Section) { Index: wasm/InputFiles.h =================================================================== --- wasm/InputFiles.h +++ wasm/InputFiles.h @@ -23,6 +23,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; @@ -33,6 +34,7 @@ class InputChunk; class InputFunction; class InputSegment; +class InputGlobal; class InputFile { public: @@ -90,7 +92,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; @@ -101,44 +102,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]); - } - - DataSymbol *getDataSymbol(uint32_t Index) const { - return cast(DataSymbols[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 *createDefinedData(const WasmSymbol &Sym, InputSegment *Segment, - uint32_t Address); + uint32_t Offset, uint32_t DataSize); Symbol *createDefinedFunction(const WasmSymbol &Sym, InputFunction *Function); - Symbol *createUndefined(const WasmSymbol &Sym, Symbol::Kind Kind, - const WasmSignature *Signature = nullptr); + Symbol *createDefinedGlobal(const WasmSymbol &Sym, InputGlobal *Global); + 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 DataSymbols; - uint32_t NumGlobalImports = 0; uint32_t NumFunctionImports = 0; std::unique_ptr WasmObj; Index: wasm/InputFiles.cpp =================================================================== --- wasm/InputFiles.cpp +++ wasm/InputFiles.cpp @@ -10,6 +10,7 @@ #include "InputFiles.h" #include "Config.h" #include "InputChunks.h" +#include "InputGlobal.h" #include "SymbolTable.h" #include "lld/Common/ErrorHandler.h" #include "lld/Common/Memory.h" @@ -43,8 +44,7 @@ void ObjFile::dumpInfo() const { log("info for: " + getName() + "\n" + - " Total Functions : " + Twine(FunctionSymbols.size()) + "\n" + - " Total Data Symbols : " + Twine(DataSymbols.size()) + "\n" + + " Symbols : " + Twine(Symbols.size()) + "\n" + " Function Imports : " + Twine(NumFunctionImports) + "\n" + " Global Imports : " + Twine(NumGlobalImports) + "\n"); } @@ -71,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"); @@ -78,33 +80,30 @@ } uint32_t ObjFile::relocateGlobalIndex(uint32_t Original) const { - const Symbol *Sym = getDataSymbol(Original); + const Symbol *Sym = getGlobalSymbol(Original); uint32_t Index = Sym->getOutputIndex(); DEBUG(dbgs() << "relocateGlobalIndex: " << toString(*Sym) << ": " << Original << " -> " << Index << "\n"); 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. @@ -160,80 +159,60 @@ // 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()); - DataSymbols.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()); - DataSymbols.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()) + Globals.emplace_back(make(G)); + for (size_t I = 0; I < Funcs.size(); ++I) { const WasmFunction &Func = Funcs[I]; const WasmSignature &Sig = Types[FuncTypes[I]]; @@ -242,77 +221,80 @@ Functions.emplace_back(F); } - // Populate `FunctionSymbols` and `DataSymbols` 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); + bool IsDefined = WasmSym.isDefined(); + + if (IsDefined) { + switch (WasmSym.Info.Kind) { + case WASM_SYMBOL_TYPE_FUNCTION: { + InputFunction *Function = getFunction(WasmSym); + if (isExcludedByComdat(Function)) { + Function->Live = false; + IsDefined = false; + break; + } + Symbols.push_back(createDefinedFunction(WasmSym, Function)); break; } - Function->Live = false; - LLVM_FALLTHROUGH; // Exclude function, and add the symbol as undefined - } - case WasmSymbol::SymbolType::FUNCTION_IMPORT: - S = createUndefined(WasmSym, Symbol::Kind::UndefinedFunctionKind, - getFunctionSig(WasmSym)); - break; - case WasmSymbol::SymbolType::GLOBAL_EXPORT: { - InputSegment *Segment = getSegment(WasmSym); - if (!isExcludedByComdat(Segment)) { - S = createDefinedData(WasmSym, Segment, getGlobalValue(WasmSym)); + case WASM_SYMBOL_TYPE_DATA: { + InputSegment *Segment = getSegment(WasmSym); + if (isExcludedByComdat(Segment)) { + Segment->Live = false; + IsDefined = false; + break; + } + Symbols.push_back(createDefinedData(WasmSym, Segment, + WasmSym.Info.DataRef.Offset, + WasmSym.Info.DataRef.Size)); + break; + } + case WASM_SYMBOL_TYPE_GLOBAL: + Symbols.push_back(createDefinedGlobal(WasmSym, getGlobal(WasmSym))); + break; + default: + llvm_unreachable("unkown symbol kind"); break; } - Segment->Live = false; - LLVM_FALLTHROUGH; // Exclude global, and add the symbol as undefined - } - case WasmSymbol::SymbolType::GLOBAL_IMPORT: - S = createUndefined(WasmSym, Symbol::Kind::UndefinedDataKind); - break; } - Symbols.push_back(S); - if (WasmSym.isTypeFunction()) { - FunctionSymbols[WasmSym.ElementIndex] = S; - if (WasmSym.HasAltIndex) - FunctionSymbols[WasmSym.AltIndex] = S; - } else { - DataSymbols[WasmSym.ElementIndex] = S; - if (WasmSym.HasAltIndex) - DataSymbols[WasmSym.AltIndex] = S; - } + // Either the the symbol itself was undefined, or was excluded via comdat + // in which case this simply insertes the existing symbol into the correct + // slot in the Symbols array. + if (!IsDefined) + Symbols.push_back(createUndefined(WasmSym)); } - - DEBUG(for (size_t I = 0; I < FunctionSymbols.size(); ++I) - assert(FunctionSymbols[I] != nullptr); - for (size_t I = 0; I < DataSymbols.size(); ++I) - assert(DataSymbols[I] != nullptr);); - - DEBUG(dbgs() << "Functions : " << FunctionSymbols.size() << "\n"); - DEBUG(dbgs() << "Globals : " << DataSymbols.size() << "\n"); } -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, static_cast(Sym.Info.Kind), Sym.Info.Flags, + this, Sym.FunctionType, Sym.GlobalType); } Symbol *ObjFile::createDefinedFunction(const WasmSymbol &Sym, InputFunction *Function) { if (Sym.isBindingLocal()) - return make(Sym.Name, Sym.Flags, this, Function); - return Symtab->addDefinedFunction(Sym.Name, Sym.Flags, this, Function); + return make(Sym.Info.Name, Sym.Info.Flags, this, Function); + return Symtab->addDefinedFunction(Sym.Info.Name, Sym.Info.Flags, this, + Function); } Symbol *ObjFile::createDefinedData(const WasmSymbol &Sym, InputSegment *Segment, - uint32_t Address) { + uint32_t Offset, uint32_t Size) { + if (Sym.isBindingLocal()) + return make(Sym.Info.Name, Sym.Info.Flags, this, Segment, + Offset, Size); + return Symtab->addDefinedData(Sym.Info.Name, Sym.Info.Flags, this, Segment, + Offset, Size); +} + +Symbol *ObjFile::createDefinedGlobal(const WasmSymbol &Sym, + InputGlobal *Global) { if (Sym.isBindingLocal()) - return make(Sym.Name, Sym.Flags, this, Segment, Address); - return Symtab->addDefinedData(Sym.Name, Sym.Flags, this, Segment, Address); + return make(Sym.Info.Name, Sym.Info.Flags, this, Global); + return Symtab->addDefinedGlobal(Sym.Info.Name, Sym.Info.Flags, this, Global); } void ArchiveFile::parse() { Index: wasm/InputGlobal.h =================================================================== --- /dev/null +++ wasm/InputGlobal.h @@ -0,0 +1,52 @@ +//===- InputGlobal.h --------------------------------------------*- C++ -*-===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLD_WASM_INPUT_GLOBAL_H +#define LLD_WASM_INPUT_GLOBAL_H + +#include "Config.h" +#include "InputFiles.h" +#include "WriterUtils.h" +#include "lld/Common/ErrorHandler.h" +#include "llvm/Object/Wasm.h" + +using llvm::wasm::WasmGlobal; +using llvm::wasm::WasmInitExpr; + +namespace lld { +namespace wasm { + +// Represents a single Wasm Global Variable within an input file. These are +// combined to form the final GLOBALS section. +class InputGlobal { +public: + InputGlobal(const WasmGlobal &G) : Global(G) {} + + const WasmGlobalType &getType() const { return Global.Type; } + + uint32_t getOutputIndex() const { return OutputIndex.getValue(); } + bool hasOutputIndex() const { return OutputIndex.hasValue(); } + void setOutputIndex(uint32_t Index) { + assert(!hasOutputIndex()); + OutputIndex = Index; + } + + bool Live = false; + + WasmGlobal Global; + +protected: + llvm::Optional OutputIndex; +}; + +} // namespace wasm + +} // namespace lld + +#endif // LLD_WASM_INPUT_GLOBAL_H Index: wasm/MarkLive.cpp =================================================================== --- wasm/MarkLive.cpp +++ wasm/MarkLive.cpp @@ -65,7 +65,7 @@ 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)); } // Follow relocations to mark all reachable chunks. @@ -73,19 +73,8 @@ InputChunk *C = Q.pop_back_val(); for (const WasmRelocation Reloc : C->getRelocations()) { - switch (Reloc.Type) { - case R_WEBASSEMBLY_FUNCTION_INDEX_LEB: - case R_WEBASSEMBLY_TABLE_INDEX_I32: - case R_WEBASSEMBLY_TABLE_INDEX_SLEB: - Enqueue(C->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(C->File->getDataSymbol(Reloc.Index)); - break; - } + if (Reloc.Type != R_WEBASSEMBLY_TYPE_INDEX_LEB) + Enqueue(C->File->getSymbol(Reloc.Index)); } } 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 @@ -17,6 +17,7 @@ #include "llvm/Support/raw_ostream.h" using llvm::wasm::WasmSignature; +using llvm::wasm::WasmGlobalType; namespace lld { namespace wasm { @@ -50,17 +51,26 @@ Symbol *addDefinedFunction(StringRef Name, uint32_t Flags, InputFile *F, InputFunction *Function = nullptr); Symbol *addDefinedData(StringRef Name, uint32_t Flags, InputFile *F, - InputSegment *Segment = nullptr, uint32_t Address = 0); + InputSegment *Segment = nullptr, uint32_t Address = 0, + uint32_t Size = 0); + Symbol *addDefinedGlobal(StringRef Name, uint32_t Flags, InputFile *F, + InputGlobal *G); Symbol *addUndefined(StringRef Name, Symbol::Kind Kind, uint32_t Flags, InputFile *F, const WasmSignature *Signature = nullptr); Symbol *addUndefinedFunction(StringRef Name, const WasmSignature *Type); + Symbol *addUndefined(StringRef Name, WasmSymbolType Type, uint32_t Flags, + InputFile *F, const WasmSignature *Signature = nullptr, + const WasmGlobalType *GlobalType = nullptr); void addLazy(ArchiveFile *F, const Archive::Symbol *Sym); bool addComdat(StringRef Name, ObjFile *); DefinedData *addSyntheticDataSymbol(StringRef Name, uint32_t Flags = 0); + DefinedGlobal *addSyntheticGlobal(StringRef Name, uint32_t Flags, + InputGlobal *Global); 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 @@ -10,6 +10,7 @@ #include "SymbolTable.h" #include "Config.h" #include "InputChunks.h" +#include "InputGlobal.h" #include "WriterUtils.h" #include "lld/Common/ErrorHandler.h" #include "lld/Common/Memory.h" @@ -73,50 +74,58 @@ // 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 (isa(Existing) != NewIsFunction) { + if (NewType != ExistingType) { error("symbol type mismatch: " + Existing.getName() + "\n>>> defined as " + - (isa(Existing) ? "Function" : "Data") + " in " + - toString(Existing.getFile()) + "\n>>> defined as " + - (NewIsFunction ? "Function" : "Data") + " 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; - const WasmSignature *OldSig = ExistingFunc->getFunctionType(); + DEBUG(dbgs() << "checkSymbolTypes: " << Existing.getName() << "\n"); - // 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 (OldSig == nullptr) - return; + 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()); + }; - DEBUG(dbgs() << "checkSymbolTypes: " << ExistingFunc->getName() << "\n"); - assert(NewSig); + 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); + const WasmSignature *OldSig = Sym.getFunctionType(); + if (!OldSig) + return; - if (*NewSig == *OldSig) - return; + assert(NewFunctionSig); + if (*NewFunctionSig == *OldSig) + return; - error("function signature mismatch: " + ExistingFunc->getName() + - "\n>>> defined as " + toString(*OldSig) + " in " + - toString(ExistingFunc->getFile()) + "\n>>> defined as " + - toString(*NewSig) + " in " + F.getName()); -} + ReportError(toString(*OldSig), toString(*NewFunctionSig)); + } else { + auto &Sym = cast(Existing); -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); + assert(NewGlobalType != nullptr); + const WasmGlobalType *OldType = Sym.getGlobalType(); + if (*NewGlobalType == *OldType) + return; + + ReportError(toString(*OldType), toString(*NewGlobalType)); + } } DefinedFunction *SymbolTable::addSyntheticFunction(StringRef Name, @@ -140,9 +149,21 @@ return replaceSymbol(S, Name, Flags); } +DefinedGlobal *SymbolTable::addSyntheticGlobal(StringRef Name, uint32_t Flags, + InputGlobal *Global) { + DEBUG(dbgs() << "addSyntheticGlobal: " << Name << " -> " << Global << "\n"); + Symbol *S; + bool WasInserted; + std::tie(S, WasInserted) = insert(Name); + assert(WasInserted); + return replaceSymbol(S, Name, Flags, nullptr, Global); +} + static bool shouldReplace(const Symbol &Existing, InputFile *NewFile, - uint32_t NewFlags, InputChunk *NewChunk, - bool NewIsFunction) { + WasmSymbolType NewType, uint32_t NewFlags, + const WasmSignature *NewFuncType = nullptr, + const WasmGlobalType *NewGlobalType = nullptr) { + // If existing symbol is lazy, replace it without checking types since // lazy symbols don't have any type information. if (Existing.isLazy()) { @@ -155,7 +176,7 @@ // symbol name must have the same type, even if they are undefined. This // is different from ELF because symbol types are not that significant // in ELF, and undefined symbols in ELF don't have type in the first place. - checkSymbolTypes(Existing, *NewFile, NewIsFunction, NewChunk); + checkSymbolTypes(Existing, *NewFile, NewType, NewFuncType, NewGlobalType); // If existing symbol is undefined, replace it. if (!Existing.isDefined()) { @@ -188,38 +209,58 @@ Symbol *S; bool WasInserted; std::tie(S, WasInserted) = insert(Name); - if (WasInserted || shouldReplace(*S, F, Flags, Function, true)) + if (WasInserted || shouldReplace(*S, F, WASM_SYMBOL_TYPE_FUNCTION, Flags, + &Function->Signature)) replaceSymbol(S, Name, Flags, F, Function); return S; } Symbol *SymbolTable::addDefinedData(StringRef Name, uint32_t Flags, - InputFile *F, InputSegment *Segment, - uint32_t Address) { + InputFile *F, InputSegment *Segment, + uint32_t Address, uint32_t Size) { DEBUG(dbgs() << "addDefinedData:" << Name << " addr:" << Address << "\n"); Symbol *S; bool WasInserted; std::tie(S, WasInserted) = insert(Name); - if (WasInserted || shouldReplace(*S, F, Flags, Segment, false)) - replaceSymbol(S, Name, Flags, F, Segment, Address); + if (WasInserted || shouldReplace(*S, F, WASM_SYMBOL_TYPE_DATA, Flags)) + replaceSymbol(S, Name, Flags, F, Segment, Address, Size); return S; } -Symbol *SymbolTable::addUndefined(StringRef Name, Symbol::Kind Kind, +Symbol *SymbolTable::addDefinedGlobal(StringRef Name, uint32_t Flags, + InputFile *F, InputGlobal *Global) { + DEBUG(dbgs() << "addDefinedGlobal:" << Name << "\n"); + Symbol *S; + bool WasInserted; + std::tie(S, WasInserted) = insert(Name); + if (WasInserted || shouldReplace(*S, F, WASM_SYMBOL_TYPE_GLOBAL, Flags, + nullptr, &Global->getType())) + replaceSymbol(S, Name, Flags, F, Global); + return S; +} + +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 + 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; + } return S; } @@ -231,8 +272,9 @@ 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 { @@ -24,6 +28,7 @@ class InputChunk; class InputSegment; class InputFunction; +class InputGlobal; #define INVALID_INDEX UINT32_MAX @@ -33,12 +38,14 @@ enum Kind { DefinedFunctionKind, DefinedDataKind, + DefinedGlobalKind, LazyKind, UndefinedFunctionKind, UndefinedDataKind, + UndefinedGlobalKind, - LastDefinedKind = DefinedDataKind, + LastDefinedKind = DefinedGlobalKind, InvalidKind, }; @@ -47,8 +54,8 @@ bool isLazy() const { return SymbolKind == LazyKind; } bool isDefined() const { return SymbolKind <= LastDefinedKind; } bool isUndefined() const { - return SymbolKind == UndefinedDataKind || - SymbolKind == UndefinedFunctionKind; + return SymbolKind == UndefinedFunctionKind || + SymbolKind == UndefinedDataKind || SymbolKind == UndefinedGlobalKind; } bool isLocal() const; bool isWeak() const; @@ -59,8 +66,12 @@ // Returns the file from which this symbol was created. InputFile *getFile() const { return File; } + InputChunk *getChunk() const; + // Indicates that this symbol will be included in the final image. + bool isLive() const; + void setHidden(bool IsHidden); uint32_t getOutputIndex() const; @@ -68,10 +79,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) : Name(Name), SymbolKind(K), Flags(Flags), File(F) {} @@ -81,6 +100,7 @@ uint32_t Flags; InputFile *File; uint32_t OutputIndex = INVALID_INDEX; + uint32_t OutputSymbolIndex = INVALID_INDEX; }; class FunctionSymbol : public Symbol { @@ -112,9 +132,11 @@ class DefinedFunction : public FunctionSymbol { public: + // Primary constructor for file-defined functions. DefinedFunction(StringRef Name, uint32_t Flags, InputFile *F, InputFunction *Function); + // Second constructor used when creating synthetic functions. DefinedFunction(StringRef Name, uint32_t Flags, const WasmSignature *Type) : FunctionSymbol(Name, DefinedFunctionKind, Flags, nullptr, Type) {} @@ -150,21 +172,27 @@ class DefinedData : public DataSymbol { public: DefinedData(StringRef Name, uint32_t Flags, InputFile *F = nullptr, - InputSegment *Segment = nullptr, uint32_t Address = 0) + InputSegment *Segment = nullptr, uint32_t Offset = 0, + uint32_t Size = 0) : DataSymbol(Name, DefinedDataKind, Flags, F), Segment(Segment), - VirtualAddress(Address) {} + Offset(Offset), Size(Size) {} - static bool classof(const Symbol *S) { - return S->kind() == DefinedDataKind; - } + 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; } + InputSegment *Segment; protected: - uint32_t VirtualAddress; + uint32_t Offset; + uint32_t Size; }; class UndefinedData : public DataSymbol { @@ -176,6 +204,47 @@ } }; +class GlobalSymbol : public Symbol { +public: + static bool classof(const Symbol *S) { + return S->kind() == DefinedGlobalKind || S->kind() == UndefinedGlobalKind; + } + + const WasmGlobalType *getGlobalType() const { return GlobalType; } + +protected: + GlobalSymbol(StringRef Name, Kind K, uint32_t Flags, InputFile *F, + const WasmGlobalType *GlobalType) + : Symbol(Name, K, Flags, F), GlobalType(GlobalType) {} + + // Explicit function type, needed for undefined or synthetic functions only. + // For regular defined globals this information comes from the InputChunk. + const WasmGlobalType *GlobalType; +}; + +class DefinedGlobal : public GlobalSymbol { +public: + DefinedGlobal(StringRef Name, uint32_t Flags, InputFile *File, + InputGlobal *Global); + + static bool classof(const Symbol *S) { + return S->kind() == DefinedGlobalKind; + } + + InputGlobal *Global; +}; + +class UndefinedGlobal : public GlobalSymbol { +public: + UndefinedGlobal(StringRef Name, uint32_t Flags, InputFile *File = nullptr, + const WasmGlobalType *Type = nullptr) + : GlobalSymbol(Name, UndefinedGlobalKind, Flags, File, Type) {} + + static bool classof(const Symbol *S) { + return S->kind() == UndefinedGlobalKind; + } +}; + class LazySymbol : public Symbol { public: LazySymbol(StringRef Name, InputFile *File, const Archive::Symbol &Sym) @@ -194,7 +263,7 @@ // __stack_pointer // Global that holds the address of the top of the explicit value stack in // linear memory. - static DefinedData *StackPointer; + static DefinedGlobal *StackPointer; // __data_end // Symbol marking the end of the data and bss. @@ -221,9 +290,11 @@ union SymbolUnion { alignas(DefinedFunction) char A[sizeof(DefinedFunction)]; alignas(DefinedData) char B[sizeof(DefinedData)]; - alignas(LazySymbol) char C[sizeof(LazySymbol)]; - alignas(UndefinedFunction) char D[sizeof(UndefinedFunction)]; - alignas(UndefinedData) char E[sizeof(UndefinedFunction)]; + 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 @@ -243,6 +314,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 @@ -11,6 +11,8 @@ #include "Config.h" #include "InputChunks.h" #include "InputFiles.h" +#include "InputGlobal.h" +#include "OutputSegment.h" #include "lld/Common/ErrorHandler.h" #include "lld/Common/Strings.h" @@ -25,19 +27,42 @@ DefinedData *WasmSym::DsoHandle; DefinedData *WasmSym::DataEnd; DefinedData *WasmSym::HeapBase; -DefinedData *WasmSym::StackPointer; +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(this)) if (F->Function) return F->Function->hasOutputIndex(); + if (auto *G = dyn_cast(this)) + if (G->Global) + return G->Global->hasOutputIndex(); return OutputIndex != INVALID_INDEX; } uint32_t Symbol::getOutputIndex() const { + assert(!isa(this)); if (auto *F = dyn_cast(this)) if (F->Function) return F->Function->getOutputIndex(); + if (auto *G = dyn_cast(this)) + if (G->Global) + return G->Global->getOutputIndex(); assert(OutputIndex != INVALID_INDEX); return OutputIndex; } @@ -45,13 +70,34 @@ InputChunk *Symbol::getChunk() const { if (auto *F = dyn_cast(this)) return F->Function; - if (auto *G = dyn_cast(this)) - return G->Segment; + if (auto *D = dyn_cast(this)) + return D->Segment; return nullptr; } +bool Symbol::isLive() const { + if (auto *G = dyn_cast(this)) + return G->Global->Live; + if (InputChunk *C = getChunk()) + return C->Live; + // Assume any other kind of symbol is live. + return true; +} + +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(!isa(this)); assert(OutputIndex == INVALID_INDEX); OutputIndex = Index; } @@ -111,14 +157,31 @@ uint32_t DefinedData::getVirtualAddress() const { DEBUG(dbgs() << "getVirtualAddress: " << getName() << "\n"); - return Segment ? Segment->translateVA(VirtualAddress) : VirtualAddress; + return Segment ? Segment->translateVA(Offset) : Offset; } void DefinedData::setVirtualAddress(uint32_t Value) { DEBUG(dbgs() << "setVirtualAddress " << Name << " -> " << Value << "\n"); - VirtualAddress = Value; + assert(!Segment); + Offset = Value; } +uint32_t DefinedData::getOutputSegmentOffset() const { + DEBUG(dbgs() << "getOutputSegmentOffset: " << getName() << "\n"); + return Segment->OutputSegmentOffset + Offset; +} + +uint32_t DefinedData::getOutputSegmentIndex() const { + DEBUG(dbgs() << "getOutputSegmentIndex: " << getName() << "\n"); + return Segment->getOutputSegment()->Index; +} + +DefinedGlobal::DefinedGlobal(StringRef Name, uint32_t Flags, InputFile *File, + InputGlobal *Global) + : GlobalSymbol(Name, DefinedGlobalKind, Flags, File, + Global ? &Global->getType() : nullptr), + Global(Global) {} + std::string lld::toString(const wasm::Symbol &Sym) { if (Config->Demangle) if (Optional S = demangleItanium(Sym.getName())) @@ -132,12 +195,28 @@ 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 @@ -10,6 +10,7 @@ #include "Writer.h" #include "Config.h" #include "InputChunks.h" +#include "InputGlobal.h" #include "OutputSections.h" #include "OutputSegment.h" #include "SymbolTable.h" @@ -18,6 +19,7 @@ #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" @@ -62,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. @@ -78,11 +81,13 @@ uint32_t lookupType(const WasmSignature &Sig); uint32_t registerType(const WasmSignature &Sig); + void createCtorFunction(); void calculateInitFunctions(); void assignIndexes(); void calculateImports(); void calculateExports(); + void assignSymtab(); void calculateTypes(); void createOutputSegments(); void layoutMemory(); @@ -118,13 +123,16 @@ std::vector Types; DenseMap TypeIndices; - std::vector ImportedFunctions; - std::vector ImportedGlobals; - std::vector ExportedSymbols; - std::vector DefinedDataSymbols; + std::vector ImportedSymbols; + unsigned NumImportedFunctions = 0; + unsigned NumImportedGlobals = 0; + std::vector ExportedSymbols; + std::vector DefinedFakeGlobals; + std::vector InputGlobals; std::vector InputFunctions; std::vector IndirectFunctions; - std::vector InitFunctions; + std::vector SymtabEntries; + std::vector InitFunctions; // Elements that are used to construct the final output std::string Header; @@ -150,7 +158,7 @@ } void Writer::createImportSection() { - uint32_t NumImports = ImportedFunctions.size() + ImportedGlobals.size(); + uint32_t NumImports = ImportedSymbols.size(); if (Config->ImportMemory) ++NumImports; @@ -162,15 +170,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"; @@ -181,13 +180,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); } } @@ -225,17 +229,19 @@ } void Writer::createGlobalSection() { - if (DefinedDataSymbols.empty()) + unsigned NumGlobals = InputGlobals.size() + DefinedFakeGlobals.size(); + if (NumGlobals == 0) return; SyntheticSection *Section = createSyntheticSection(WASM_SEC_GLOBAL); raw_ostream &OS = Section->getStream(); - writeUleb128(OS, DefinedDataSymbols.size(), "global count"); - for (const DefinedData *Sym : DefinedDataSymbols) { + writeUleb128(OS, NumGlobals, "global count"); + for (const InputGlobal *G : InputGlobals) + writeGlobal(OS, G->Global); + for (const DefinedData *Sym : DefinedFakeGlobals) { WasmGlobal Global; - Global.Type.Type = WASM_TYPE_I32; - Global.Type.Mutable = Sym == WasmSym::StackPointer; + Global.Type = {WASM_TYPE_I32, false}; Global.InitExpr.Opcode = WASM_OPCODE_I32_CONST; Global.InitExpr.Value.Int32 = Sym->getVirtualAddress(); writeGlobal(OS, Global); @@ -283,15 +289,23 @@ writeExport(OS, MemoryExport); } - for (const WasmExportEntry &E : ExportedSymbols) { - DEBUG(dbgs() << "Export: " << E.Sym->getName() << "\n"); + unsigned FakeGlobalIndex = NumImportedGlobals + InputGlobals.size(); + for (const Symbol *Sym : ExportedSymbols) { + DEBUG(dbgs() << "Export: " << Sym->getName() << "\n"); WasmExport Export; - Export.Name = E.FieldName; - Export.Index = E.Sym->getOutputIndex(); - if (isa(E.Sym)) + Export.Name = Sym->getName(); + if (isa(Sym)) { + Export.Index = Sym->getOutputIndex(); Export.Kind = WASM_EXTERNAL_FUNCTION; - else + } else if (isa(Sym)) { + Export.Index = Sym->getOutputIndex(); Export.Kind = WASM_EXTERNAL_GLOBAL; + } else if (isa(Sym)) { + Export.Index = FakeGlobalIndex++; + Export.Kind = WASM_EXTERNAL_GLOBAL; + } else { + llvm_unreachable("unexpected symbol type"); + } writeExport(OS, Export); } } @@ -383,28 +397,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); @@ -426,9 +451,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); @@ -475,7 +501,7 @@ // Create the custom "name" section containing debug symbol names. void Writer::createNameSection() { - unsigned NumNames = ImportedFunctions.size(); + unsigned NumNames = NumImportedFunctions; for (const InputFunction *F : InputFunctions) if (!F->getName().empty()) ++NumNames; @@ -489,10 +515,12 @@ raw_ostream &OS = FunctionSubsection.getStream(); writeUleb128(OS, NumNames, "name count"); - // Names must appear in function index order. As it happens ImportedFunctions - // and InputFunctions are numbers in order with imported functions coming + // Names must appear in function index order. As it happens ImportedSymbols + // and InputFunctions are numbered in order with imported functions coming // first. - for (const Symbol *S : ImportedFunctions) { + for (const Symbol *S : ImportedSymbols) { + if (!isa(S)) + continue; writeUleb128(OS, S->getOutputIndex(), "import index"); writeStr(OS, S->getName(), "symbol name"); } @@ -562,8 +590,9 @@ debugPrint("mem: stack size = %d\n", Config->ZStackSize); debugPrint("mem: stack base = %d\n", MemoryPtr); MemoryPtr += Config->ZStackSize; - WasmSym::StackPointer->setVirtualAddress(MemoryPtr); + WasmSym::StackPointer->Global->Global.InitExpr.Value.Int32 = 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. @@ -614,69 +643,85 @@ void Writer::calculateImports() { for (Symbol *Sym : Symtab->getSymbols()) { - if (!Sym->isUndefined() || (Sym->isWeak() && !Config->Relocatable)) + if (!Sym->isUndefined()) + continue; + if (isa(Sym)) + 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 (isa(Sym)) + ++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; + if (!Sym->isLive()) + 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 (File == Sym->getFile()) + ExportSym(Sym); + for (Symbol *Sym : Symtab->getSymbols()) + if (Sym->getFile() == nullptr) + ExportSym(Sym); +} + +void Writer::assignSymtab() { + if (!Config->Relocatable) + return; + + unsigned SymbolIndex = SymtabEntries.size(); for (ObjFile *File : Symtab->ObjectFiles) { + DEBUG(dbgs() << "Symtab entries: " << File->getName() << "\n"); for (Symbol *Sym : File->getSymbols()) { - if (!Sym->isDefined() || File != Sym->getFile()) - continue; - if (!isa(Sym)) - continue; - if (!Sym->getChunk()->Live) + if (Sym->getFile() != File) continue; - - if ((Sym->isHidden() || Sym->isLocal()) && !ExportHidden) - continue; - ExportedSymbols.emplace_back(WasmExportEntry{Sym, BudgeLocalName(Sym)}); + if (!Sym->isLive()) + return; + Sym->setOutputSymbolIndex(SymbolIndex++); + SymtabEntries.emplace_back(Sym); } } - for (const Symbol *Sym : DefinedDataSymbols) { - // 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) { @@ -710,45 +755,16 @@ 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 : InputFunctions) registerType(F->Signature); } void Writer::assignIndexes() { - uint32_t GlobalIndex = ImportedGlobals.size() + DefinedDataSymbols.size(); - uint32_t FunctionIndex = ImportedFunctions.size() + InputFunctions.size(); - - auto AddDefinedData = [&](DefinedData *Sym) { - if (Sym) { - DefinedDataSymbols.emplace_back(Sym); - Sym->setOutputIndex(GlobalIndex++); - } - }; - AddDefinedData(WasmSym::StackPointer); - AddDefinedData(WasmSym::HeapBase); - AddDefinedData(WasmSym::DataEnd); - - if (Config->Relocatable) - DefinedDataSymbols.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)) - AddDefinedData(G); - } - } - } - + uint32_t FunctionIndex = NumImportedFunctions + InputFunctions.size(); for (ObjFile *File : Symtab->ObjectFiles) { DEBUG(dbgs() << "Functions: " << File->getName() << "\n"); for (InputFunction *Func : File->Functions) { @@ -759,12 +775,13 @@ } } + uint32_t TableIndex = kInitialTableOffset; auto HandleRelocs = [&](InputChunk *Chunk) { if (!Chunk->Live) return; ObjFile *File = Chunk->File; ArrayRef Types = File->getWasmObj()->types(); - for (const WasmRelocation& Reloc : Chunk->getRelocations()) { + for (const WasmRelocation &Reloc : Chunk->getRelocations()) { if (Reloc.Type == R_WEBASSEMBLY_TABLE_INDEX_I32 || Reloc.Type == R_WEBASSEMBLY_TABLE_INDEX_SLEB) { FunctionSymbol *Sym = File->getFunctionSymbol(Reloc.Index); @@ -773,20 +790,45 @@ Sym->setTableIndex(TableIndex++); IndirectFunctions.emplace_back(Sym); } else if (Reloc.Type == R_WEBASSEMBLY_TYPE_INDEX_LEB) { + // Mark target type as live File->TypeMap[Reloc.Index] = registerType(Types[Reloc.Index]); File->TypeIsUsed[Reloc.Index] = true; + } else if (Reloc.Type == R_WEBASSEMBLY_GLOBAL_INDEX_LEB) { + // Mark target global as live + GlobalSymbol *Sym = File->getGlobalSymbol(Reloc.Index); + if (auto *G = dyn_cast(Sym)) { + DEBUG(dbgs() << "marking global live: " << Sym->getName() << "\n"); + G->Global->Live = true; + } } } }; for (ObjFile *File : Symtab->ObjectFiles) { DEBUG(dbgs() << "Handle relocs: " << File->getName() << "\n"); - - for (InputChunk* Chunk : File->Functions) + for (InputChunk *Chunk : File->Functions) HandleRelocs(Chunk); - for (InputChunk* Chunk : File->Segments) + for (InputChunk *Chunk : File->Segments) HandleRelocs(Chunk); } + + uint32_t GlobalIndex = NumImportedGlobals + InputGlobals.size(); + auto AddDefinedGlobal = [&](InputGlobal *Global) { + if (Global->Live) { + DEBUG(dbgs() << "AddDefinedGlobal: " << GlobalIndex << "\n"); + Global->setOutputIndex(GlobalIndex++); + InputGlobals.push_back(Global); + } + }; + + if (WasmSym::StackPointer) + AddDefinedGlobal(WasmSym::StackPointer->Global); + + for (ObjFile *File : Symtab->ObjectFiles) { + DEBUG(dbgs() << "Globals: " << File->getName() << "\n"); + for (InputGlobal *Global : File->Globals) + AddDefinedGlobal(Global); + } } static StringRef getOutputDataSegmentName(StringRef Name) { @@ -814,7 +856,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 +871,18 @@ // Create synthetic "__wasm_call_ctors" function based on ctor functions // in input object. void Writer::createCtorFunction() { - uint32_t FunctionIndex = ImportedFunctions.size() + InputFunctions.size(); + uint32_t FunctionIndex = NumImportedFunctions + InputFunctions.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"); } @@ -853,9 +895,11 @@ ArrayRef BodyArray( reinterpret_cast(CtorFunctionBody.data()), CtorFunctionBody.size()); - SyntheticFunction *F = make(Signature, BodyArray, + SyntheticFunction *F = make(*Signature, BodyArray, WasmSym::CallCtors->getName()); F->setOutputIndex(FunctionIndex); + F->Live = true; + WasmSym::CallCtors->Function = F; InputFunctions.emplace_back(F); } @@ -867,13 +911,13 @@ 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::stable_sort(InitFunctions.begin(), InitFunctions.end(), - [](const WasmInitFunc &L, const WasmInitFunc &R) { + [](const WasmInitEntry &L, const WasmInitEntry &R) { return L.Priority < R.Priority; }); } @@ -883,29 +927,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(InputFunctions.size())); - log("Defined Data Syms: " + Twine(DefinedDataSymbols.size())); - log("Function Imports : " + Twine(ImportedFunctions.size())); - log("Global Imports : " + Twine(ImportedGlobals.size())); - log("Total Imports : " + - Twine(ImportedFunctions.size() + ImportedGlobals.size())); + log("Defined Globals : " + Twine(InputGlobals.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 @@ -28,6 +28,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 { @@ -65,6 +76,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 @@ -190,3 +190,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; +}