summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lld/test/wasm/Inputs/locals-duplicate1.ll49
-rw-r--r--lld/test/wasm/Inputs/locals-duplicate2.ll49
-rw-r--r--lld/test/wasm/call-indirect.ll6
-rw-r--r--lld/test/wasm/init-fini.ll39
-rw-r--r--lld/test/wasm/locals-duplicate.test543
-rw-r--r--lld/test/wasm/relocatable.ll15
-rw-r--r--lld/test/wasm/visibility-hidden.ll6
-rw-r--r--lld/wasm/Writer.cpp127
8 files changed, 794 insertions, 40 deletions
diff --git a/lld/test/wasm/Inputs/locals-duplicate1.ll b/lld/test/wasm/Inputs/locals-duplicate1.ll
new file mode 100644
index 00000000000..64ac5a4975e
--- /dev/null
+++ b/lld/test/wasm/Inputs/locals-duplicate1.ll
@@ -0,0 +1,49 @@
+; Will collide: local (internal linkage) with global (external) linkage
+@colliding_global1 = internal default global i32 0, align 4
+; Will collide: global 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 global
+define internal i32 @colliding_func1() {
+entry:
+ ret i32 2
+}
+; Will collide: global 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
+}
diff --git a/lld/test/wasm/Inputs/locals-duplicate2.ll b/lld/test/wasm/Inputs/locals-duplicate2.ll
new file mode 100644
index 00000000000..20a4cc3daea
--- /dev/null
+++ b/lld/test/wasm/Inputs/locals-duplicate2.ll
@@ -0,0 +1,49 @@
+; Will collide: local (internal linkage) with global (external) linkage
+@colliding_global1 = default global i32 0, align 4
+; Will collide: global 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 global
+define i32 @colliding_func1() {
+entry:
+ ret i32 2
+}
+; Will collide: global 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
+}
diff --git a/lld/test/wasm/call-indirect.ll b/lld/test/wasm/call-indirect.ll
index 267a65bae51..53c05d7b67e 100644
--- a/lld/test/wasm/call-indirect.ll
+++ b/lld/test/wasm/call-indirect.ll
@@ -85,15 +85,15 @@ define void @call_ptr(i64 (i64)* %arg) {
; 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
diff --git a/lld/test/wasm/init-fini.ll b/lld/test/wasm/init-fini.ll
index 2b9ef05b53a..0fa9b20a3f8 100644
--- a/lld/test/wasm/init-fini.ll
+++ b/lld/test/wasm/init-fini.ll
@@ -107,7 +107,44 @@ entry:
; 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
diff --git a/lld/test/wasm/locals-duplicate.test b/lld/test/wasm/locals-duplicate.test
new file mode 100644
index 00000000000..bb62b9fdf94
--- /dev/null
+++ b/lld/test/wasm/locals-duplicate.test
@@ -0,0 +1,543 @@
+; 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: - Index: 1
+; CHECK-NEXT: Type: I32
+; CHECK-NEXT: Mutable: false
+; 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: - Name: __heap_base
+; CHECK-NEXT: Kind: GLOBAL
+; CHECK-NEXT: Index: 1
+; 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: 0x00000006
+; RELOC-NEXT: Maximum: 0x00000006
+; 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: 0
+; 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: 3
+; RELOC-NEXT: Offset: 0x00000073
+; RELOC-NEXT: - Type: R_WEBASSEMBLY_TABLE_INDEX_SLEB
+; RELOC-NEXT: Index: 4
+; RELOC-NEXT: Offset: 0x0000007C
+; RELOC-NEXT: - Type: R_WEBASSEMBLY_TABLE_INDEX_SLEB
+; RELOC-NEXT: Index: 5
+; 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: 4180808080000B
+; RELOC-NEXT: - Index: 7
+; RELOC-NEXT: Locals:
+; RELOC-NEXT: Body: 4181808080000B
+; RELOC-NEXT: - Index: 8
+; RELOC-NEXT: Locals:
+; RELOC-NEXT: Body: 4182808080000B
+; 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: 4183808080000B
+; RELOC-NEXT: - Index: 16
+; RELOC-NEXT: Locals:
+; RELOC-NEXT: Body: 4184808080000B
+; RELOC-NEXT: - Index: 17
+; RELOC-NEXT: Locals:
+; RELOC-NEXT: Body: 4185808080000B
+; 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: ...
diff --git a/lld/test/wasm/relocatable.ll b/lld/test/wasm/relocatable.ll
index 8803fd91d74..5b391c3025b 100644
--- a/lld/test/wasm/relocatable.ll
+++ b/lld/test/wasm/relocatable.ll
@@ -200,6 +200,21 @@ entry:
; 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_comdat
+; CHECK-NEXT: Flags: [ BINDING_WEAK ]
+; CHECK-NEXT: - Name: data_comdat
+; CHECK-NEXT: Flags: [ BINDING_WEAK ]
+; 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
diff --git a/lld/test/wasm/visibility-hidden.ll b/lld/test/wasm/visibility-hidden.ll
index e405e97af33..f8c5575c935 100644
--- a/lld/test/wasm/visibility-hidden.ll
+++ b/lld/test/wasm/visibility-hidden.ll
@@ -37,12 +37,12 @@ entry:
; 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: - Name: __heap_base
; CHECK-NEXT: Kind: GLOBAL
; CHECK-NEXT: Index: 1
diff --git a/lld/wasm/Writer.cpp b/lld/wasm/Writer.cpp
index 14fc90e9751..4cefe3a473e 100644
--- a/lld/wasm/Writer.cpp
+++ b/lld/wasm/Writer.cpp
@@ -62,6 +62,12 @@ struct WasmSignatureDenseMapInfo {
}
};
+// A Wasm export to be written into the export section.
+struct WasmExportEntry {
+ const Symbol *Symbol;
+ StringRef FieldName; // may not match the Symbol name
+};
+
// The writer writes a SymbolTable result to a file.
class Writer {
public:
@@ -76,6 +82,7 @@ private:
void calculateInitFunctions();
void assignIndexes();
void calculateImports();
+ void calculateExports();
void calculateTypes();
void createOutputSegments();
void layoutMemory();
@@ -114,6 +121,7 @@ private:
DenseMap<WasmSignature, int32_t, WasmSignatureDenseMapInfo> TypeIndices;
std::vector<const Symbol *> ImportedFunctions;
std::vector<const Symbol *> ImportedGlobals;
+ std::vector<WasmExportEntry> ExportedSymbols;
std::vector<const Symbol *> DefinedGlobals;
std::vector<InputFunction *> DefinedFunctions;
std::vector<const Symbol *> IndirectFunctions;
@@ -259,35 +267,8 @@ void Writer::createTableSection() {
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<const Symbol *> 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 +285,12 @@ void Writer::createExportSection() {
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 +385,26 @@ void Writer::createLinkingSection() {
if (!Config->Relocatable)
return;
+ std::vector<std::pair<StringRef, uint32_t>> SymbolInfo;
+ for (const WasmExportEntry &E : ExportedSymbols) {
+ uint32_t Flags =
+ (E.Symbol->isLocal() ? WASM_SYMBOL_BINDING_LOCAL :
+ E.Symbol->isWeak() ? WASM_SYMBOL_BINDING_WEAK : 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");
@@ -608,6 +609,64 @@ void Writer::calculateImports() {
}
}
+void Writer::calculateExports() {
+ Symbol *EntrySym = Symtab->find(Config->Entry);
+ bool ExportEntry = !Config->Relocatable && EntrySym && EntrySym->isDefined();
+ bool ExportHidden = Config->EmitRelocs;
+ 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 (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, BudgeLocalName(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, BudgeLocalName(Sym)});
+ }
+}
+
uint32_t Writer::lookupType(const WasmSignature &Sig) {
auto It = TypeIndices.find(Sig);
if (It == TypeIndices.end()) {
@@ -793,6 +852,8 @@ void Writer::run() {
calculateImports();
log("-- assignIndexes");
assignIndexes();
+ log("-- calculateExports");
+ calculateExports();
log("-- calculateInitFunctions");
calculateInitFunctions();
if (!Config->Relocatable)
OpenPOWER on IntegriCloud