Index: test/wasm/Inputs/locals-duplicate1.ll =================================================================== --- /dev/null +++ test/wasm/Inputs/locals-duplicate1.ll @@ -0,0 +1,49 @@ +; Will collide: local with public +@colliding_global1 = internal default global i32 0, align 4 +; Will collide: public with local +@colliding_global2 = default global i32 0, align 4 +; Will collide: local with local +@colliding_global3 = internal default global i32 0, align 4 + +; Will collide: local with public +define internal i32 @colliding_func1() { +entry: + ret i32 2 +} +; Will collide: public with local +define i32 @colliding_func2() { +entry: + ret i32 2 +} +; Will collide: local with local +define internal i32 @colliding_func3() { +entry: + ret i32 2 +} + + +define i32* @get_global1A() { +entry: + ret i32* @colliding_global1 +} +define i32* @get_global2A() { +entry: + ret i32* @colliding_global2 +} +define i32* @get_global3A() { +entry: + ret i32* @colliding_global3 +} + +define i32 ()* @get_func1A() { +entry: + ret i32 ()* @colliding_func1 +} +define i32 ()* @get_func2A() { +entry: + ret i32 ()* @colliding_func2 +} +define i32 ()* @get_func3A() { +entry: + ret i32 ()* @colliding_func3 +} Index: test/wasm/Inputs/locals-duplicate2.ll =================================================================== --- /dev/null +++ test/wasm/Inputs/locals-duplicate2.ll @@ -0,0 +1,49 @@ +; Will collide: local with public +@colliding_global1 = default global i32 0, align 4 +; Will collide: public with local +@colliding_global2 = internal default global i32 0, align 4 +; Will collide: local with local +@colliding_global3 = internal default global i32 0, align 4 + +; Will collide: local with public +define i32 @colliding_func1() { +entry: + ret i32 2 +} +; Will collide: public with local +define internal i32 @colliding_func2() { +entry: + ret i32 2 +} +; Will collide: local with local +define internal i32 @colliding_func3() { +entry: + ret i32 2 +} + + +define i32* @get_global1B() { +entry: + ret i32* @colliding_global1 +} +define i32* @get_global2B() { +entry: + ret i32* @colliding_global2 +} +define i32* @get_global3B() { +entry: + ret i32* @colliding_global3 +} + +define i32 ()* @get_func1B() { +entry: + ret i32 ()* @colliding_func1 +} +define i32 ()* @get_func2B() { +entry: + ret i32 ()* @colliding_func2 +} +define i32 ()* @get_func3B() { +entry: + ret i32 ()* @colliding_func3 +} Index: test/wasm/call-indirect.ll =================================================================== --- test/wasm/call-indirect.ll +++ test/wasm/call-indirect.ll @@ -79,15 +79,15 @@ ; CHECK-NEXT: - Name: _start ; CHECK-NEXT: Kind: FUNCTION ; CHECK-NEXT: Index: 3 -; CHECK-NEXT: - Name: foo -; CHECK-NEXT: Kind: FUNCTION -; CHECK-NEXT: Index: 2 ; CHECK-NEXT: - Name: bar ; CHECK-NEXT: Kind: FUNCTION ; CHECK-NEXT: Index: 0 ; CHECK-NEXT: - Name: call_bar_indirect ; CHECK-NEXT: Kind: FUNCTION ; CHECK-NEXT: Index: 1 +; CHECK-NEXT: - Name: foo +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Index: 2 ; CHECK-NEXT: - Name: call_ptr ; CHECK-NEXT: Kind: FUNCTION ; CHECK-NEXT: Index: 4 Index: test/wasm/init-fini.ll =================================================================== --- test/wasm/init-fini.ll +++ test/wasm/init-fini.ll @@ -107,7 +107,44 @@ ; RELOC: Name: linking ; RELOC-NEXT: DataSize: 0 -; RELOC-NEXT: InitFunctions: +; RELOC-NEXT: SymbolInfo: +; RELOC-NEXT: - Name: func1 +; RELOC-NEXT: Flags: [ VISIBILITY_HIDDEN ] +; RELOC-NEXT: - Name: func2 +; RELOC-NEXT: Flags: [ VISIBILITY_HIDDEN ] +; RELOC-NEXT: - Name: func3 +; RELOC-NEXT: Flags: [ VISIBILITY_HIDDEN ] +; RELOC-NEXT: - Name: func4 +; RELOC-NEXT: Flags: [ VISIBILITY_HIDDEN ] +; RELOC-NEXT: - Name: _start +; RELOC-NEXT: Flags: [ VISIBILITY_HIDDEN ] +; RELOC-NEXT: - Name: .Lcall_dtors.101 +; RELOC-NEXT: Flags: [ BINDING_LOCAL ] +; RELOC-NEXT: - Name: .Lregister_call_dtors.101 +; RELOC-NEXT: Flags: [ BINDING_LOCAL ] +; RELOC-NEXT: - Name: .Lbitcast +; RELOC-NEXT: Flags: [ BINDING_LOCAL ] +; RELOC-NEXT: - Name: .Lcall_dtors.1001 +; RELOC-NEXT: Flags: [ BINDING_LOCAL ] +; RELOC-NEXT: - Name: .Lregister_call_dtors.1001 +; RELOC-NEXT: Flags: [ BINDING_LOCAL ] +; RELOC-NEXT: - Name: myctor +; RELOC-NEXT: Flags: [ VISIBILITY_HIDDEN ] +; RELOC-NEXT: - Name: mydtor +; RELOC-NEXT: Flags: [ VISIBILITY_HIDDEN ] +; RELOC-NEXT: - Name: .Lcall_dtors.101.1 +; RELOC-NEXT: Flags: [ BINDING_LOCAL ] +; RELOC-NEXT: - Name: .Lregister_call_dtors.101.1 +; RELOC-NEXT: Flags: [ BINDING_LOCAL ] +; RELOC-NEXT: - Name: .Lcall_dtors.202 +; RELOC-NEXT: Flags: [ BINDING_LOCAL ] +; RELOC-NEXT: - Name: .Lregister_call_dtors.202 +; RELOC-NEXT: Flags: [ BINDING_LOCAL ] +; RELOC-NEXT: - Name: .Lcall_dtors.2002 +; RELOC-NEXT: Flags: [ BINDING_LOCAL ] +; RELOC-NEXT: - Name: .Lregister_call_dtors.2002 +; RELOC-NEXT: Flags: [ BINDING_LOCAL ] +; RELOC-NEXT: InitFunctions: ; RELOC-NEXT: - Priority: 101 ; RELOC-NEXT: FunctionIndex: 0 ; RELOC-NEXT: - Priority: 101 Index: test/wasm/locals-duplicate.test =================================================================== --- /dev/null +++ test/wasm/locals-duplicate.test @@ -0,0 +1,534 @@ +; RUN: llc -filetype=obj -mtriple=wasm32-unknown-unknown-wasm %p/Inputs/locals-duplicate1.ll -o %t1.o +; RUN: llc -filetype=obj -mtriple=wasm32-unknown-unknown-wasm %p/Inputs/locals-duplicate2.ll -o %t2.o +; RUN: lld -flavor wasm --no-entry -o %t.wasm %t1.o %t2.o +; RUN: obj2yaml %t.wasm | FileCheck %s + +; CHECK: --- !WASM +; CHECK-NEXT: FileHeader: +; CHECK-NEXT: Version: 0x00000001 +; CHECK-NEXT: Sections: +; CHECK-NEXT: - Type: TYPE +; CHECK-NEXT: Signatures: +; CHECK-NEXT: - Index: 0 +; CHECK-NEXT: ReturnType: I32 +; CHECK-NEXT: ParamTypes: +; CHECK-NEXT: - Index: 1 +; CHECK-NEXT: ReturnType: NORESULT +; CHECK-NEXT: ParamTypes: +; CHECK-NEXT: - Type: FUNCTION +; CHECK-NEXT: FunctionTypes: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +; CHECK-NEXT: 0, 0, 1 ] +; CHECK-NEXT: - Type: TABLE +; CHECK-NEXT: Tables: +; CHECK-NEXT: - ElemType: ANYFUNC +; CHECK-NEXT: Limits: +; CHECK-NEXT: Flags: [ HAS_MAX ] +; CHECK-NEXT: Initial: 0x00000007 +; CHECK-NEXT: Maximum: 0x00000007 +; CHECK-NEXT: - Type: MEMORY +; CHECK-NEXT: Memories: +; CHECK-NEXT: - Initial: 0x00000002 +; CHECK-NEXT: - Type: GLOBAL +; CHECK-NEXT: Globals: +; CHECK-NEXT: - Index: 0 +; CHECK-NEXT: Type: I32 +; CHECK-NEXT: Mutable: true +; CHECK-NEXT: InitExpr: +; CHECK-NEXT: Opcode: I32_CONST +; CHECK-NEXT: Value: 66592 +; CHECK-NEXT: - Type: EXPORT +; CHECK-NEXT: Exports: +; CHECK-NEXT: - Name: memory +; CHECK-NEXT: Kind: MEMORY +; CHECK-NEXT: Index: 0 +; CHECK-NEXT: - Name: colliding_func2 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Index: 1 +; CHECK-NEXT: - Name: get_global1A +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Index: 3 +; CHECK-NEXT: - Name: get_global2A +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Index: 4 +; CHECK-NEXT: - Name: get_global3A +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Index: 5 +; CHECK-NEXT: - Name: get_func1A +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Index: 6 +; CHECK-NEXT: - Name: get_func2A +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Index: 7 +; CHECK-NEXT: - Name: get_func3A +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Index: 8 +; CHECK-NEXT: - Name: colliding_func1 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Index: 9 +; CHECK-NEXT: - Name: get_global1B +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Index: 12 +; CHECK-NEXT: - Name: get_global2B +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Index: 13 +; CHECK-NEXT: - Name: get_global3B +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Index: 14 +; CHECK-NEXT: - Name: get_func1B +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Index: 15 +; CHECK-NEXT: - Name: get_func2B +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Index: 16 +; CHECK-NEXT: - Name: get_func3B +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Index: 17 +; CHECK-NEXT: - Type: ELEM +; CHECK-NEXT: Segments: +; CHECK-NEXT: - Offset: +; CHECK-NEXT: Opcode: I32_CONST +; CHECK-NEXT: Value: 1 +; CHECK-NEXT: Functions: [ 0, 1, 2, 9, 10, 11 ] +; CHECK-NEXT: - Type: CODE +; CHECK-NEXT: Functions: +; CHECK-NEXT: - Index: 0 +; CHECK-NEXT: Locals: +; CHECK-NEXT: Body: 41020B +; CHECK-NEXT: - Index: 1 +; CHECK-NEXT: Locals: +; CHECK-NEXT: Body: 41020B +; CHECK-NEXT: - Index: 2 +; CHECK-NEXT: Locals: +; CHECK-NEXT: Body: 41020B +; CHECK-NEXT: - Index: 3 +; CHECK-NEXT: Locals: +; CHECK-NEXT: Body: 4180888080000B +; CHECK-NEXT: - Index: 4 +; CHECK-NEXT: Locals: +; CHECK-NEXT: Body: 4184888080000B +; CHECK-NEXT: - Index: 5 +; CHECK-NEXT: Locals: +; CHECK-NEXT: Body: 4188888080000B +; CHECK-NEXT: - Index: 6 +; CHECK-NEXT: Locals: +; CHECK-NEXT: Body: 4181808080000B +; CHECK-NEXT: - Index: 7 +; CHECK-NEXT: Locals: +; CHECK-NEXT: Body: 4182808080000B +; CHECK-NEXT: - Index: 8 +; CHECK-NEXT: Locals: +; CHECK-NEXT: Body: 4183808080000B +; CHECK-NEXT: - Index: 9 +; CHECK-NEXT: Locals: +; CHECK-NEXT: Body: 41020B +; CHECK-NEXT: - Index: 10 +; CHECK-NEXT: Locals: +; CHECK-NEXT: Body: 41020B +; CHECK-NEXT: - Index: 11 +; CHECK-NEXT: Locals: +; CHECK-NEXT: Body: 41020B +; CHECK-NEXT: - Index: 12 +; CHECK-NEXT: Locals: +; CHECK-NEXT: Body: 418C888080000B +; CHECK-NEXT: - Index: 13 +; CHECK-NEXT: Locals: +; CHECK-NEXT: Body: 4190888080000B +; CHECK-NEXT: - Index: 14 +; CHECK-NEXT: Locals: +; CHECK-NEXT: Body: 4194888080000B +; CHECK-NEXT: - Index: 15 +; CHECK-NEXT: Locals: +; CHECK-NEXT: Body: 4184808080000B +; CHECK-NEXT: - Index: 16 +; CHECK-NEXT: Locals: +; CHECK-NEXT: Body: 4185808080000B +; CHECK-NEXT: - Index: 17 +; CHECK-NEXT: Locals: +; CHECK-NEXT: Body: 4186808080000B +; CHECK-NEXT: - Index: 18 +; CHECK-NEXT: Locals: +; CHECK-NEXT: Body: 0B +; CHECK-NEXT: - Type: DATA +; CHECK-NEXT: Segments: +; CHECK-NEXT: - SectionOffset: 7 +; CHECK-NEXT: MemoryIndex: 0 +; CHECK-NEXT: Offset: +; CHECK-NEXT: Opcode: I32_CONST +; CHECK-NEXT: Value: 1024 +; CHECK-NEXT: Content: '000000000000000000000000000000000000000000000000' +; CHECK-NEXT: - Type: CUSTOM +; CHECK-NEXT: Name: linking +; CHECK-NEXT: DataSize: 24 +; CHECK-NEXT: - Type: CUSTOM +; CHECK-NEXT: Name: name +; CHECK-NEXT: FunctionNames: +; CHECK-NEXT: - Index: 0 +; CHECK-NEXT: Name: colliding_func1 +; CHECK-NEXT: - Index: 1 +; CHECK-NEXT: Name: colliding_func2 +; CHECK-NEXT: - Index: 2 +; CHECK-NEXT: Name: colliding_func3 +; CHECK-NEXT: - Index: 3 +; CHECK-NEXT: Name: get_global1A +; CHECK-NEXT: - Index: 4 +; CHECK-NEXT: Name: get_global2A +; CHECK-NEXT: - Index: 5 +; CHECK-NEXT: Name: get_global3A +; CHECK-NEXT: - Index: 6 +; CHECK-NEXT: Name: get_func1A +; CHECK-NEXT: - Index: 7 +; CHECK-NEXT: Name: get_func2A +; CHECK-NEXT: - Index: 8 +; CHECK-NEXT: Name: get_func3A +; CHECK-NEXT: - Index: 9 +; CHECK-NEXT: Name: colliding_func1 +; CHECK-NEXT: - Index: 10 +; CHECK-NEXT: Name: colliding_func2 +; CHECK-NEXT: - Index: 11 +; CHECK-NEXT: Name: colliding_func3 +; CHECK-NEXT: - Index: 12 +; CHECK-NEXT: Name: get_global1B +; CHECK-NEXT: - Index: 13 +; CHECK-NEXT: Name: get_global2B +; CHECK-NEXT: - Index: 14 +; CHECK-NEXT: Name: get_global3B +; CHECK-NEXT: - Index: 15 +; CHECK-NEXT: Name: get_func1B +; CHECK-NEXT: - Index: 16 +; CHECK-NEXT: Name: get_func2B +; CHECK-NEXT: - Index: 17 +; CHECK-NEXT: Name: get_func3B +; CHECK-NEXT: - Index: 18 +; CHECK-NEXT: Name: __wasm_call_ctors +; CHECK-NEXT: ... + + +; RUN: lld -flavor wasm -r --no-entry -o %t.reloc.wasm %t1.o %t2.o +; RUN: obj2yaml %t.reloc.wasm | FileCheck -check-prefix=RELOC %s + +; RELOC: --- !WASM +; RELOC-NEXT: FileHeader: +; RELOC-NEXT: Version: 0x00000001 +; RELOC-NEXT: Sections: +; RELOC-NEXT: - Type: TYPE +; RELOC-NEXT: Signatures: +; RELOC-NEXT: - Index: 0 +; RELOC-NEXT: ReturnType: I32 +; RELOC-NEXT: ParamTypes: +; RELOC-NEXT: - Type: FUNCTION +; RELOC-NEXT: FunctionTypes: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +; RELOC-NEXT: 0, 0 ] +; RELOC-NEXT: - Type: TABLE +; RELOC-NEXT: Tables: +; RELOC-NEXT: - ElemType: ANYFUNC +; RELOC-NEXT: Limits: +; RELOC-NEXT: Flags: [ HAS_MAX ] +; RELOC-NEXT: Initial: 0x00000007 +; RELOC-NEXT: Maximum: 0x00000007 +; 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: +; RELOC-NEXT: Opcode: I32_CONST +; RELOC-NEXT: Value: 1 +; RELOC-NEXT: Functions: [ 0, 1, 2, 9, 10, 11 ] +; RELOC-NEXT: - Type: CODE +; RELOC-NEXT: Relocations: +; RELOC-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_SLEB +; RELOC-NEXT: Index: 0 +; RELOC-NEXT: Offset: 0x00000013 +; RELOC-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_SLEB +; RELOC-NEXT: Index: 1 +; RELOC-NEXT: Offset: 0x0000001C +; RELOC-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_SLEB +; RELOC-NEXT: Index: 2 +; RELOC-NEXT: Offset: 0x00000025 +; RELOC-NEXT: - Type: R_WEBASSEMBLY_TABLE_INDEX_SLEB +; RELOC-NEXT: Index: 0 +; RELOC-NEXT: Offset: 0x0000002E +; RELOC-NEXT: - Type: R_WEBASSEMBLY_TABLE_INDEX_SLEB +; RELOC-NEXT: Index: 1 +; RELOC-NEXT: Offset: 0x00000037 +; RELOC-NEXT: - Type: R_WEBASSEMBLY_TABLE_INDEX_SLEB +; RELOC-NEXT: Index: 2 +; RELOC-NEXT: Offset: 0x00000040 +; RELOC-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_SLEB +; RELOC-NEXT: Index: 3 +; RELOC-NEXT: Offset: 0x00000058 +; RELOC-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_SLEB +; RELOC-NEXT: Index: 4 +; RELOC-NEXT: Offset: 0x00000061 +; RELOC-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_SLEB +; RELOC-NEXT: Index: 5 +; RELOC-NEXT: Offset: 0x0000006A +; RELOC-NEXT: - Type: R_WEBASSEMBLY_TABLE_INDEX_SLEB +; RELOC-NEXT: Index: 9 +; RELOC-NEXT: Offset: 0x00000073 +; RELOC-NEXT: - Type: R_WEBASSEMBLY_TABLE_INDEX_SLEB +; RELOC-NEXT: Index: 10 +; RELOC-NEXT: Offset: 0x0000007C +; RELOC-NEXT: - Type: R_WEBASSEMBLY_TABLE_INDEX_SLEB +; RELOC-NEXT: Index: 11 +; RELOC-NEXT: Offset: 0x00000085 +; RELOC-NEXT: Functions: +; RELOC-NEXT: - Index: 0 +; RELOC-NEXT: Locals: +; RELOC-NEXT: Body: 41020B +; RELOC-NEXT: - Index: 1 +; RELOC-NEXT: Locals: +; RELOC-NEXT: Body: 41020B +; RELOC-NEXT: - Index: 2 +; RELOC-NEXT: Locals: +; RELOC-NEXT: Body: 41020B +; RELOC-NEXT: - Index: 3 +; RELOC-NEXT: Locals: +; RELOC-NEXT: Body: 4180808080000B +; RELOC-NEXT: - Index: 4 +; RELOC-NEXT: Locals: +; RELOC-NEXT: Body: 4188808080000B +; RELOC-NEXT: - Index: 5 +; RELOC-NEXT: Locals: +; RELOC-NEXT: Body: 4190808080000B +; RELOC-NEXT: - Index: 6 +; RELOC-NEXT: Locals: +; RELOC-NEXT: Body: 4181808080000B +; RELOC-NEXT: - Index: 7 +; RELOC-NEXT: Locals: +; RELOC-NEXT: Body: 4182808080000B +; RELOC-NEXT: - Index: 8 +; RELOC-NEXT: Locals: +; RELOC-NEXT: Body: 4183808080000B +; RELOC-NEXT: - Index: 9 +; RELOC-NEXT: Locals: +; RELOC-NEXT: Body: 41020B +; RELOC-NEXT: - Index: 10 +; RELOC-NEXT: Locals: +; RELOC-NEXT: Body: 41020B +; RELOC-NEXT: - Index: 11 +; RELOC-NEXT: Locals: +; RELOC-NEXT: Body: 41020B +; RELOC-NEXT: - Index: 12 +; RELOC-NEXT: Locals: +; RELOC-NEXT: Body: 4184808080000B +; RELOC-NEXT: - Index: 13 +; RELOC-NEXT: Locals: +; RELOC-NEXT: Body: 418C808080000B +; RELOC-NEXT: - Index: 14 +; RELOC-NEXT: Locals: +; RELOC-NEXT: Body: 4194808080000B +; RELOC-NEXT: - Index: 15 +; RELOC-NEXT: Locals: +; RELOC-NEXT: Body: 4184808080000B +; RELOC-NEXT: - Index: 16 +; RELOC-NEXT: Locals: +; RELOC-NEXT: Body: 4185808080000B +; RELOC-NEXT: - Index: 17 +; RELOC-NEXT: Locals: +; RELOC-NEXT: Body: 4186808080000B +; RELOC-NEXT: - Type: DATA +; RELOC-NEXT: Segments: +; RELOC-NEXT: - SectionOffset: 6 +; RELOC-NEXT: MemoryIndex: 0 +; RELOC-NEXT: Offset: +; RELOC-NEXT: Opcode: I32_CONST +; RELOC-NEXT: Value: 0 +; RELOC-NEXT: Content: '0000000000000000' +; RELOC-NEXT: - SectionOffset: 19 +; RELOC-NEXT: MemoryIndex: 0 +; RELOC-NEXT: Offset: +; RELOC-NEXT: Opcode: I32_CONST +; RELOC-NEXT: Value: 8 +; RELOC-NEXT: Content: '0000000000000000' +; RELOC-NEXT: - SectionOffset: 32 +; RELOC-NEXT: MemoryIndex: 0 +; RELOC-NEXT: Offset: +; RELOC-NEXT: Opcode: I32_CONST +; RELOC-NEXT: Value: 16 +; RELOC-NEXT: Content: '0000000000000000' +; RELOC-NEXT: - Type: CUSTOM +; RELOC-NEXT: Name: linking +; RELOC-NEXT: DataSize: 24 +; RELOC-NEXT: SymbolInfo: +; RELOC-NEXT: - Name: colliding_func1.1 +; RELOC-NEXT: Flags: [ BINDING_LOCAL ] +; RELOC-NEXT: - Name: colliding_func3 +; RELOC-NEXT: Flags: [ BINDING_LOCAL ] +; RELOC-NEXT: - Name: colliding_func2.1 +; RELOC-NEXT: Flags: [ BINDING_LOCAL ] +; RELOC-NEXT: - Name: colliding_func3.1 +; RELOC-NEXT: Flags: [ BINDING_LOCAL ] +; RELOC-NEXT: - Name: colliding_global1.1 +; RELOC-NEXT: Flags: [ BINDING_LOCAL ] +; RELOC-NEXT: - Name: colliding_global3 +; RELOC-NEXT: Flags: [ BINDING_LOCAL ] +; RELOC-NEXT: - Name: colliding_global2.1 +; RELOC-NEXT: Flags: [ BINDING_LOCAL ] +; RELOC-NEXT: - Name: colliding_global3.1 +; RELOC-NEXT: Flags: [ BINDING_LOCAL ] +; RELOC-NEXT: SegmentInfo: +; RELOC-NEXT: - Index: 0 +; RELOC-NEXT: Name: .bss.colliding_global1 +; RELOC-NEXT: Alignment: 4 +; RELOC-NEXT: Flags: [ ] +; RELOC-NEXT: - Index: 1 +; RELOC-NEXT: Name: .bss.colliding_global2 +; RELOC-NEXT: Alignment: 4 +; RELOC-NEXT: Flags: [ ] +; RELOC-NEXT: - Index: 2 +; RELOC-NEXT: Name: .bss.colliding_global3 +; RELOC-NEXT: Alignment: 4 +; RELOC-NEXT: Flags: [ ] +; RELOC-NEXT: - Type: CUSTOM +; RELOC-NEXT: Name: name +; RELOC-NEXT: FunctionNames: +; RELOC-NEXT: - Index: 0 +; RELOC-NEXT: Name: colliding_func1 +; RELOC-NEXT: - Index: 1 +; RELOC-NEXT: Name: colliding_func2 +; RELOC-NEXT: - Index: 2 +; RELOC-NEXT: Name: colliding_func3 +; RELOC-NEXT: - Index: 3 +; RELOC-NEXT: Name: get_global1A +; RELOC-NEXT: - Index: 4 +; RELOC-NEXT: Name: get_global2A +; RELOC-NEXT: - Index: 5 +; RELOC-NEXT: Name: get_global3A +; RELOC-NEXT: - Index: 6 +; RELOC-NEXT: Name: get_func1A +; RELOC-NEXT: - Index: 7 +; RELOC-NEXT: Name: get_func2A +; RELOC-NEXT: - Index: 8 +; RELOC-NEXT: Name: get_func3A +; RELOC-NEXT: - Index: 9 +; RELOC-NEXT: Name: colliding_func1 +; RELOC-NEXT: - Index: 10 +; RELOC-NEXT: Name: colliding_func2 +; RELOC-NEXT: - Index: 11 +; RELOC-NEXT: Name: colliding_func3 +; RELOC-NEXT: - Index: 12 +; RELOC-NEXT: Name: get_global1B +; RELOC-NEXT: - Index: 13 +; RELOC-NEXT: Name: get_global2B +; RELOC-NEXT: - Index: 14 +; RELOC-NEXT: Name: get_global3B +; RELOC-NEXT: - Index: 15 +; RELOC-NEXT: Name: get_func1B +; RELOC-NEXT: - Index: 16 +; RELOC-NEXT: Name: get_func2B +; RELOC-NEXT: - Index: 17 +; RELOC-NEXT: Name: get_func3B +; RELOC-NEXT: ... Index: test/wasm/relocatable.ll =================================================================== --- test/wasm/relocatable.ll +++ test/wasm/relocatable.ll @@ -200,6 +200,17 @@ ; CHECK-NEXT: - Type: CUSTOM ; CHECK-NEXT: Name: linking ; CHECK-NEXT: DataSize: 23 +; CHECK-NEXT: SymbolInfo: +; CHECK-NEXT: - Name: hello +; CHECK-NEXT: Flags: [ VISIBILITY_HIDDEN ] +; CHECK-NEXT: - Name: my_func +; CHECK-NEXT: Flags: [ VISIBILITY_HIDDEN ] +; CHECK-NEXT: - Name: func_addr1 +; CHECK-NEXT: Flags: [ VISIBILITY_HIDDEN ] +; CHECK-NEXT: - Name: func_addr2 +; CHECK-NEXT: Flags: [ VISIBILITY_HIDDEN ] +; CHECK-NEXT: - Name: data_addr1 +; CHECK-NEXT: Flags: [ VISIBILITY_HIDDEN ] ; CHECK-NEXT: SegmentInfo: ; CHECK-NEXT: - Index: 0 ; CHECK-NEXT: Name: .rodata.hello_str Index: test/wasm/visibility-hidden.ll =================================================================== --- test/wasm/visibility-hidden.ll +++ test/wasm/visibility-hidden.ll @@ -37,10 +37,10 @@ ; CHECK-NEXT: - Name: _start ; CHECK-NEXT: Kind: FUNCTION ; CHECK-NEXT: Index: 2 -; CHECK-NEXT: - Name: archiveDefault -; CHECK-NEXT: Kind: FUNCTION -; CHECK-NEXT: Index: 4 ; CHECK-NEXT: - Name: objectDefault ; CHECK-NEXT: Kind: FUNCTION ; CHECK-NEXT: Index: 1 +; CHECK-NEXT: - Name: archiveDefault +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Index: 4 ; CHECK-NEXT: - Type: Index: wasm/Writer.cpp =================================================================== --- wasm/Writer.cpp +++ wasm/Writer.cpp @@ -26,6 +26,7 @@ #include #include +#include #define DEBUG_TYPE "lld" @@ -62,6 +63,12 @@ } }; +// A Wasm export to be written into the export section. +struct WasmExportEntry { + const Symbol *Symbol; + std::string FieldName; // may not match the Symbol name +}; + // The writer writes a SymbolTable result to a file. class Writer { public: @@ -76,6 +83,7 @@ void calculateInitFunctions(); void assignIndexes(); void calculateImports(); + void calculateExports(); void calculateTypes(); void createOutputSegments(); void layoutMemory(); @@ -114,6 +122,7 @@ DenseMap TypeIndices; std::vector ImportedFunctions; std::vector ImportedGlobals; + std::vector ExportedSymbols; std::vector DefinedGlobals; std::vector DefinedFunctions; std::vector IndirectFunctions; @@ -259,35 +268,8 @@ void Writer::createExportSection() { bool ExportMemory = !Config->Relocatable && !Config->ImportMemory; - Symbol *EntrySym = Symtab->find(Config->Entry); - bool ExportEntry = !Config->Relocatable && EntrySym && EntrySym->isDefined(); - bool ExportHidden = Config->EmitRelocs; - uint32_t NumExports = ExportMemory ? 1 : 0; - - std::vector SymbolExports; - if (ExportEntry) - SymbolExports.emplace_back(EntrySym); - - for (const Symbol *Sym : Symtab->getSymbols()) { - if (Sym->isUndefined() || Sym->isGlobal()) - continue; - if (Sym->isHidden() && !ExportHidden) - continue; - if (ExportEntry && Sym == EntrySym) - continue; - SymbolExports.emplace_back(Sym); - } - - for (const Symbol *Sym : DefinedGlobals) { - // Can't export the SP right now because it mutable and mutable globals - // connot be exported. - if (Sym == Config->StackPointerSymbol) - continue; - SymbolExports.emplace_back(Sym); - } - - NumExports += SymbolExports.size(); + uint32_t NumExports = (ExportMemory ? 1 : 0) + ExportedSymbols.size(); if (!NumExports) return; @@ -304,12 +286,12 @@ writeExport(OS, MemoryExport); } - for (const Symbol *Sym : SymbolExports) { - DEBUG(dbgs() << "Export: " << Sym->getName() << "\n"); + for (const WasmExportEntry &E : ExportedSymbols) { + DEBUG(dbgs() << "Export: " << E.Symbol->getName() << "\n"); WasmExport Export; - Export.Name = Sym->getName(); - Export.Index = Sym->getOutputIndex(); - if (Sym->isFunction()) + Export.Name = E.FieldName; + Export.Index = E.Symbol->getOutputIndex(); + if (E.Symbol->isFunction()) Export.Kind = WASM_EXTERNAL_FUNCTION; else Export.Kind = WASM_EXTERNAL_GLOBAL; @@ -404,6 +386,26 @@ if (!Config->Relocatable) return; + std::vector> SymbolInfo; + for (const WasmExportEntry &E : ExportedSymbols) { + // Don't export the weak flag: we've handled that in this link. For the + // next link, the symbol is either gone or has become strong. + uint32_t Flags = (E.Symbol->isLocal() ? WASM_SYMBOL_BINDING_LOCAL : 0) | + (E.Symbol->isHidden() ? WASM_SYMBOL_VISIBILITY_HIDDEN : 0); + if (Flags) + SymbolInfo.emplace_back(E.FieldName, Flags); + } + 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"); + } + SubSection.finalizeContents(); + SubSection.writeToStream(OS); + } + if (Segments.size()) { SubSection SubSection(WASM_SEGMENT_INFO); writeUleb128(SubSection.getStream(), Segments.size(), "num data segments"); @@ -593,6 +595,61 @@ } } +void Writer::calculateExports() { + Symbol *EntrySym = Symtab->find(Config->Entry); + bool ExportEntry = !Config->Relocatable && EntrySym && EntrySym->isDefined(); + bool ExportHidden = Config->EmitRelocs; + std::set UsedNames; + auto BudgeName = [&](const Symbol *Sym) { + StringRef SymName = Sym->getName(); + // We can't budge non-local names. + if (!Sym->isLocal()) + return SymName.str(); + // 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.str(); + for (unsigned i = 1; ; ++i) { + std::string Name = (SymName + "." + Twine(i)).str(); + if (UsedNames.insert(Name).second) + return Name; + } + }; + + if (ExportEntry) + ExportedSymbols.emplace_back(WasmExportEntry{EntrySym, EntrySym->getName()}); + + if (Config->CtorSymbol && ExportHidden && + !(ExportEntry && Config->CtorSymbol == EntrySym)) + ExportedSymbols.emplace_back( + WasmExportEntry{Config->CtorSymbol, Config->CtorSymbol->getName()}); + + for (ObjFile *File : Symtab->ObjectFiles) { + for (Symbol *Sym : File->getSymbols()) { + if (!Sym->isDefined() || File != Sym->getFile()) + continue; + if (Sym->isGlobal()) + continue; + if (Sym->getFunction()->Discarded) + continue; + + if ((Sym->isHidden() || Sym->isLocal()) && !ExportHidden) + continue; + if (ExportEntry && Sym == EntrySym) + continue; + ExportedSymbols.emplace_back(WasmExportEntry{Sym, BudgeName(Sym)}); + } + } + + for (const Symbol *Sym : DefinedGlobals) { + // Can't export the SP right now because it's mutable and mutable globals + // cannot be exported. + if (Sym == Config->StackPointerSymbol) + continue; + ExportedSymbols.emplace_back(WasmExportEntry{Sym, BudgeName(Sym)}); + } +} + uint32_t Writer::lookupType(const WasmSignature &Sig) { auto It = TypeIndices.find(Sig); if (It == TypeIndices.end()) { @@ -786,6 +843,8 @@ calculateImports(); log("-- assignIndexes"); assignIndexes(); + log("-- calculateExports"); + calculateExports(); log("-- calculateInitFunctions"); calculateInitFunctions(); if (!Config->Relocatable)