[WebAssembly] Add missing function exports and SYM_INFO to --relocatable output

When writing relocatable files we were exporting for all globals
(including file-local syms), but not for functions. Oops. To be
consistent with non-relocatable output, all symbols (file-local
and global) should be exported. Any symbol targetted by further
relocations needs to be exported. The lack of local function
exports was just an omission, I think.

Second bug: Local symbol names can collide, causing an illegal
Wasm file to be generated! Oops again. This only previously affected
producing relocatable output from two files, where each had a global
with the same name. We need to "budge" the symbol names for locals
that are exported on relocatable output.

Third bug: LLD's relocatable output wasn't writing out any symbol
flags! Thus the local globals weren't being marked as local, and
the hidden flag was also stripped...

Added tests to exercise colliding local names with/without
relocatable flag

Patch by Nicholas Wilson!

Differential Revision: https://reviews.llvm.org/D42105

llvm-svn: 322908
This commit is contained in:
Sam Clegg 2018-01-18 23:40:49 +00:00
parent a19b748f6d
commit d3052d5522
8 changed files with 794 additions and 40 deletions

View File

@ -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
}

View File

@ -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
}

View File

@ -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

View File

@ -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

View File

@ -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: ...

View File

@ -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

View File

@ -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

View File

@ -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)