[lld] r325861 - [WebAssembly] Add explicit symbol table
Sam Clegg via llvm-commits
llvm-commits at lists.llvm.org
Thu Feb 22 21:08:54 PST 2018
Author: sbc
Date: Thu Feb 22 21:08:53 2018
New Revision: 325861
URL: http://llvm.org/viewvc/llvm-project?rev=325861&view=rev
Log:
[WebAssembly] Add explicit symbol table
This change modified lld to in response the llvm change which
moved to a more explicit symbol table in the object format.
Based on patches by Nicholas Wilson:
1. https://reviews.llvm.org/D41955
2. https://reviews.llvm.org/D42585
The primary difference that we see in the test output is that
for relocatable (-r) output we now have symbol table which
replaces exports/imports and globals.
See: https://github.com/WebAssembly/tool-conventions/issues/38
Differential Revision: https://reviews.llvm.org/D43264
Added:
lld/trunk/wasm/InputGlobal.h (with props)
Modified:
lld/trunk/test/wasm/alias.ll
lld/trunk/test/wasm/archive.ll
lld/trunk/test/wasm/data-layout.ll
lld/trunk/test/wasm/init-fini.ll
lld/trunk/test/wasm/locals-duplicate.test
lld/trunk/test/wasm/many-functions.ll
lld/trunk/test/wasm/relocatable.ll
lld/trunk/test/wasm/signature-mismatch-weak.ll
lld/trunk/test/wasm/signature-mismatch.ll
lld/trunk/test/wasm/stack-pointer.ll
lld/trunk/test/wasm/weak-alias.ll
lld/trunk/wasm/Driver.cpp
lld/trunk/wasm/InputChunks.cpp
lld/trunk/wasm/InputChunks.h
lld/trunk/wasm/InputFiles.cpp
lld/trunk/wasm/InputFiles.h
lld/trunk/wasm/MarkLive.cpp
lld/trunk/wasm/OutputSegment.h
lld/trunk/wasm/SymbolTable.cpp
lld/trunk/wasm/SymbolTable.h
lld/trunk/wasm/Symbols.cpp
lld/trunk/wasm/Symbols.h
lld/trunk/wasm/Writer.cpp
lld/trunk/wasm/WriterUtils.cpp
lld/trunk/wasm/WriterUtils.h
Modified: lld/trunk/test/wasm/alias.ll
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/alias.ll?rev=325861&r1=325860&r2=325861&view=diff
==============================================================================
--- lld/trunk/test/wasm/alias.ll (original)
+++ lld/trunk/test/wasm/alias.ll Thu Feb 22 21:08:53 2018
@@ -58,10 +58,10 @@ entry:
; 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
Modified: lld/trunk/test/wasm/archive.ll
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/archive.ll?rev=325861&r1=325860&r2=325861&view=diff
==============================================================================
--- lld/trunk/test/wasm/archive.ll (original)
+++ lld/trunk/test/wasm/archive.ll Thu Feb 22 21:08:53 2018
@@ -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 @@ entry:
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
Modified: lld/trunk/test/wasm/data-layout.ll
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/data-layout.ll?rev=325861&r1=325860&r2=325861&view=diff
==============================================================================
--- lld/trunk/test/wasm/data-layout.ll (original)
+++ lld/trunk/test/wasm/data-layout.ll Thu Feb 22 21:08:53 2018
@@ -46,25 +46,10 @@ target triple = "wasm32-unknown-unknown-
; 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 @@ target triple = "wasm32-unknown-unknown-
; 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
Modified: lld/trunk/test/wasm/init-fini.ll
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/init-fini.ll?rev=325861&r1=325860&r2=325861&view=diff
==============================================================================
--- lld/trunk/test/wasm/init-fini.ll (original)
+++ lld/trunk/test/wasm/init-fini.ll Thu Feb 22 21:08:53 2018
@@ -107,66 +107,129 @@ entry:
; 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: 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: .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: 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: Function: 0
+; RELOC-NEXT: - Index: 2
+; RELOC-NEXT: Kind: FUNCTION
+; RELOC-NEXT: Name: func2
+; RELOC-NEXT: Flags: [ VISIBILITY_HIDDEN ]
+; RELOC-NEXT: Function: 1
+; RELOC-NEXT: - Index: 3
+; RELOC-NEXT: Kind: FUNCTION
+; RELOC-NEXT: Name: func3
+; RELOC-NEXT: Flags: [ VISIBILITY_HIDDEN ]
+; RELOC-NEXT: Function: 2
+; RELOC-NEXT: - Index: 4
+; RELOC-NEXT: Kind: FUNCTION
+; RELOC-NEXT: Name: func4
+; RELOC-NEXT: Flags: [ VISIBILITY_HIDDEN ]
+; 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: Function: 5
+; RELOC-NEXT: - Index: 7
+; RELOC-NEXT: Kind: FUNCTION
+; RELOC-NEXT: Name: .Lcall_dtors.101
+; RELOC-NEXT: Flags: [ BINDING_LOCAL ]
+; 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: Function: 7
+; RELOC-NEXT: - Index: 9
+; RELOC-NEXT: Kind: FUNCTION
+; RELOC-NEXT: Name: .Lcall_dtors.1001
+; RELOC-NEXT: Flags: [ BINDING_LOCAL ]
+; 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: 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: Function: 10
+; RELOC-NEXT: - Index: 13
+; RELOC-NEXT: Kind: FUNCTION
+; RELOC-NEXT: Name: mydtor
+; RELOC-NEXT: Flags: [ VISIBILITY_HIDDEN ]
+; 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: Function: 12
+; RELOC-NEXT: - Index: 15
+; RELOC-NEXT: Kind: FUNCTION
+; RELOC-NEXT: Name: .Lregister_call_dtors.101
+; RELOC-NEXT: Flags: [ BINDING_LOCAL ]
+; 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: Function: 14
+; RELOC-NEXT: - Index: 17
+; RELOC-NEXT: Kind: FUNCTION
+; RELOC-NEXT: Name: .Lregister_call_dtors.202
+; RELOC-NEXT: Flags: [ BINDING_LOCAL ]
+; 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: 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:
Modified: lld/trunk/test/wasm/locals-duplicate.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/locals-duplicate.test?rev=325861&r1=325860&r2=325861&view=diff
==============================================================================
--- lld/trunk/test/wasm/locals-duplicate.test (original)
+++ lld/trunk/test/wasm/locals-duplicate.test Thu Feb 22 21:08:53 2018
@@ -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
Modified: lld/trunk/test/wasm/many-functions.ll
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/many-functions.ll?rev=325861&r1=325860&r2=325861&view=diff
==============================================================================
--- lld/trunk/test/wasm/many-functions.ll (original)
+++ lld/trunk/test/wasm/many-functions.ll Thu Feb 22 21:08:53 2018
@@ -19,394 +19,394 @@ entry:
; 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 @@ entry:
; 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
Modified: lld/trunk/test/wasm/relocatable.ll
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/relocatable.ll?rev=325861&r1=325860&r2=325861&view=diff
==============================================================================
--- lld/trunk/test/wasm/relocatable.ll (original)
+++ lld/trunk/test/wasm/relocatable.ll Thu Feb 22 21:08:53 2018
@@ -59,11 +59,6 @@ entry:
; 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 @@ entry:
; 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 @@ entry:
; 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 @@ entry:
; 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 @@ entry:
; 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: Flags: [ VISIBILITY_HIDDEN ]
-; CHECK-NEXT: - Name: func_addr2
-; CHECK-NEXT: Flags: [ VISIBILITY_HIDDEN ]
-; CHECK-NEXT: - Name: func_addr3
-; CHECK-NEXT: Flags: [ VISIBILITY_HIDDEN ]
-; CHECK-NEXT: - Name: data_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: 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: 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: 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
Modified: lld/trunk/test/wasm/signature-mismatch-weak.ll
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/signature-mismatch-weak.ll?rev=325861&r1=325860&r2=325861&view=diff
==============================================================================
--- lld/trunk/test/wasm/signature-mismatch-weak.ll (original)
+++ lld/trunk/test/wasm/signature-mismatch-weak.ll Thu Feb 22 21:08:53 2018
@@ -14,6 +14,6 @@ entry:
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
Modified: lld/trunk/test/wasm/signature-mismatch.ll
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/signature-mismatch.ll?rev=325861&r1=325860&r2=325861&view=diff
==============================================================================
--- lld/trunk/test/wasm/signature-mismatch.ll (original)
+++ lld/trunk/test/wasm/signature-mismatch.ll Thu Feb 22 21:08:53 2018
@@ -17,10 +17,10 @@ entry:
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
Modified: lld/trunk/test/wasm/stack-pointer.ll
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/stack-pointer.ll?rev=325861&r1=325860&r2=325861&view=diff
==============================================================================
--- lld/trunk/test/wasm/stack-pointer.ll (original)
+++ lld/trunk/test/wasm/stack-pointer.ll Thu Feb 22 21:08:53 2018
@@ -26,7 +26,7 @@ entry:
; 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 @@ entry:
; 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 @@ entry:
; 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:
Modified: lld/trunk/test/wasm/weak-alias.ll
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/weak-alias.ll?rev=325861&r1=325860&r2=325861&view=diff
==============================================================================
--- lld/trunk/test/wasm/weak-alias.ll (original)
+++ lld/trunk/test/wasm/weak-alias.ll Thu Feb 22 21:08:53 2018
@@ -68,9 +68,6 @@ entry:
; 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 @@ entry:
; 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 @@ entry:
; 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 @@ entry:
; 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 @@ entry:
; 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 @@ entry:
; 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:
Modified: lld/trunk/wasm/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/Driver.cpp?rev=325861&r1=325860&r2=325861&view=diff
==============================================================================
--- lld/trunk/wasm/Driver.cpp (original)
+++ lld/trunk/wasm/Driver.cpp Thu Feb 22 21:08:53 2018
@@ -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 @@ private:
void addFile(StringRef Path);
void addLibrary(StringRef Name);
std::vector<InputFile *> Files;
+ llvm::wasm::WasmGlobal StackPointerGlobal;
};
} // anonymous namespace
@@ -222,8 +224,8 @@ static StringRef getEntry(opt::InputArgL
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 @@ void LinkerDriver::link(ArrayRef<const c
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<InputGlobal>(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())
Modified: lld/trunk/wasm/InputChunks.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/InputChunks.cpp?rev=325861&r1=325860&r2=325861&view=diff
==============================================================================
--- lld/trunk/wasm/InputChunks.cpp (original)
+++ lld/trunk/wasm/InputChunks.cpp Thu Feb 22 21:08:53 2018
@@ -27,12 +27,10 @@ std::string lld::toString(const InputChu
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) {
Modified: lld/trunk/wasm/InputChunks.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/InputChunks.h?rev=325861&r1=325860&r2=325861&view=diff
==============================================================================
--- lld/trunk/wasm/InputChunks.h (original)
+++ lld/trunk/wasm/InputChunks.h Thu Feb 22 21:08:53 2018
@@ -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 @@ public:
// 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 @@ public:
}
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; }
Modified: lld/trunk/wasm/InputFiles.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/InputFiles.cpp?rev=325861&r1=325860&r2=325861&view=diff
==============================================================================
--- lld/trunk/wasm/InputFiles.cpp (original)
+++ lld/trunk/wasm/InputFiles.cpp Thu Feb 22 21:08:53 2018
@@ -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 @@ Optional<MemoryBufferRef> lld::wasm::rea
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::relocateTypeIndex(uint
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::relocateTableIndex(uin
}
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 @@ void ObjFile::parse() {
// 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<FunctionSymbol>(Symbols[Index]);
+}
+
+GlobalSymbol *ObjFile::getGlobalSymbol(uint32_t Index) const {
+ return cast<GlobalSymbol>(Symbols[Index]);
+}
+
+DataSymbol *ObjFile::getDataSymbol(uint32_t Index) const {
+ return cast<DataSymbol>(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<WasmFunction> Funcs = WasmObj->functions();
ArrayRef<uint32_t> FuncTypes = WasmObj->functionTypes();
ArrayRef<WasmSignature> Types = WasmObj->types();
- ArrayRef<WasmGlobal> 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<InputSegment>(S, this);
Seg->copyRelocations(*DataSection);
Segments.emplace_back(Seg);
}
+ for (const WasmGlobal &G : WasmObj->globals())
+ Globals.emplace_back(make<InputGlobal>(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 @@ void ObjFile::initializeSymbols() {
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<WasmSymbolType>(Sym.Info.Kind), Sym.Info.Flags,
+ this, Sym.FunctionType, Sym.GlobalType);
}
Symbol *ObjFile::createDefinedFunction(const WasmSymbol &Sym,
InputFunction *Function) {
if (Sym.isBindingLocal())
- return make<DefinedFunction>(Sym.Name, Sym.Flags, this, Function);
- return Symtab->addDefinedFunction(Sym.Name, Sym.Flags, this, Function);
+ return make<DefinedFunction>(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<DefinedData>(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<DefinedData>(Sym.Name, Sym.Flags, this, Segment, Address);
- return Symtab->addDefinedData(Sym.Name, Sym.Flags, this, Segment, Address);
+ return make<DefinedGlobal>(Sym.Info.Name, Sym.Info.Flags, this, Global);
+ return Symtab->addDefinedGlobal(Sym.Info.Name, Sym.Info.Flags, this, Global);
}
void ArchiveFile::parse() {
Modified: lld/trunk/wasm/InputFiles.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/InputFiles.h?rev=325861&r1=325860&r2=325861&view=diff
==============================================================================
--- lld/trunk/wasm/InputFiles.h (original)
+++ lld/trunk/wasm/InputFiles.h Thu Feb 22 21:08:53 2018
@@ -23,6 +23,7 @@ using llvm::object::Archive;
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 @@ namespace wasm {
class InputChunk;
class InputFunction;
class InputSegment;
+class InputGlobal;
class InputFile {
public:
@@ -90,7 +92,6 @@ public:
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 @@ public:
std::vector<bool> TypeIsUsed;
std::vector<InputSegment *> Segments;
std::vector<InputFunction *> Functions;
+ std::vector<InputGlobal *> Globals;
ArrayRef<Symbol *> getSymbols() const { return Symbols; }
-
- FunctionSymbol *getFunctionSymbol(uint32_t Index) const {
- return cast<FunctionSymbol>(FunctionSymbols[Index]);
- }
-
- DataSymbol *getDataSymbol(uint32_t Index) const {
- return cast<DataSymbol>(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<Symbol *> Symbols;
- // List of all function symbols indexed by the function index space
- std::vector<Symbol *> FunctionSymbols;
-
- // List of all global symbols indexed by the global index space
- std::vector<Symbol *> DataSymbols;
-
uint32_t NumGlobalImports = 0;
uint32_t NumFunctionImports = 0;
std::unique_ptr<WasmObjectFile> WasmObj;
Added: lld/trunk/wasm/InputGlobal.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/InputGlobal.h?rev=325861&view=auto
==============================================================================
--- lld/trunk/wasm/InputGlobal.h (added)
+++ lld/trunk/wasm/InputGlobal.h Thu Feb 22 21:08:53 2018
@@ -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<uint32_t> OutputIndex;
+};
+
+} // namespace wasm
+
+} // namespace lld
+
+#endif // LLD_WASM_INPUT_GLOBAL_H
Propchange: lld/trunk/wasm/InputGlobal.h
------------------------------------------------------------------------------
svn:eol-style = LF
Modified: lld/trunk/wasm/MarkLive.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/MarkLive.cpp?rev=325861&r1=325860&r2=325861&view=diff
==============================================================================
--- lld/trunk/wasm/MarkLive.cpp (original)
+++ lld/trunk/wasm/MarkLive.cpp Thu Feb 22 21:08:53 2018
@@ -65,7 +65,7 @@ void lld::wasm::markLive() {
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 @@ void lld::wasm::markLive() {
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));
}
}
Modified: lld/trunk/wasm/OutputSegment.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/OutputSegment.h?rev=325861&r1=325860&r2=325861&view=diff
==============================================================================
--- lld/trunk/wasm/OutputSegment.h (original)
+++ lld/trunk/wasm/OutputSegment.h Thu Feb 22 21:08:53 2018
@@ -21,7 +21,7 @@ class InputSegment;
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 @@ public:
void setSectionOffset(uint32_t Offset) { SectionOffset = Offset; }
StringRef Name;
+ const uint32_t Index;
uint32_t Alignment = 0;
uint32_t StartVA = 0;
std::vector<InputSegment *> InputSegments;
Modified: lld/trunk/wasm/SymbolTable.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/SymbolTable.cpp?rev=325861&r1=325860&r2=325861&view=diff
==============================================================================
--- lld/trunk/wasm/SymbolTable.cpp (original)
+++ lld/trunk/wasm/SymbolTable.cpp Thu Feb 22 21:08:53 2018
@@ -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 @@ std::pair<Symbol *, bool> SymbolTable::i
// 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<FunctionSymbol>(Existing) != NewIsFunction) {
+ if (NewType != ExistingType) {
error("symbol type mismatch: " + Existing.getName() + "\n>>> defined as " +
- (isa<FunctionSymbol>(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<FunctionSymbol>(&Existing);
- if (!ExistingFunc || !Config->CheckSignatures)
- return;
-
- const WasmSignature *OldSig = ExistingFunc->getFunctionType();
-
- // 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)
+ // For function/global symbols, optionally check the type matches too.
+ if (NewType == WASM_SYMBOL_TYPE_DATA || !Config->CheckSignatures)
return;
- DEBUG(dbgs() << "checkSymbolTypes: " << ExistingFunc->getName() << "\n");
- assert(NewSig);
-
- if (*NewSig == *OldSig)
- return;
+ DEBUG(dbgs() << "checkSymbolTypes: " << Existing.getName() << "\n");
- error("function signature mismatch: " + ExistingFunc->getName() +
- "\n>>> defined as " + toString(*OldSig) + " in " +
- toString(ExistingFunc->getFile()) + "\n>>> defined as " +
- toString(*NewSig) + " in " + F.getName());
-}
+ 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());
+ };
+
+ 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<FunctionSymbol>(Existing);
+ const WasmSignature *OldSig = Sym.getFunctionType();
+ if (!OldSig)
+ return;
+
+ assert(NewFunctionSig);
+ if (*NewFunctionSig == *OldSig)
+ return;
+
+ ReportError(toString(*OldSig), toString(*NewFunctionSig));
+ } else {
+ auto &Sym = cast<GlobalSymbol>(Existing);
+
+ assert(NewGlobalType != nullptr);
+ const WasmGlobalType *OldType = Sym.getGlobalType();
+ if (*NewGlobalType == *OldType)
+ return;
-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<InputFunction>(Chunk))
- Sig = &F->Signature;
- return checkSymbolTypes(Existing, F, IsFunction, Sig);
+ ReportError(toString(*OldType), toString(*NewGlobalType));
+ }
}
DefinedFunction *SymbolTable::addSyntheticFunction(StringRef Name,
@@ -140,9 +149,21 @@ DefinedData *SymbolTable::addSyntheticDa
return replaceSymbol<DefinedData>(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<DefinedGlobal>(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 @@ static bool shouldReplace(const Symbol &
// 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 *SymbolTable::addDefinedFunction(
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<DefinedFunction>(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<DefinedData>(S, Name, Flags, F, Segment, Address);
+ if (WasInserted || shouldReplace(*S, F, WASM_SYMBOL_TYPE_DATA, Flags))
+ replaceSymbol<DefinedData>(S, Name, Flags, F, Segment, Address, Size);
+ return S;
+}
+
+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<DefinedGlobal>(S, Name, Flags, F, Global);
return S;
}
-Symbol *SymbolTable::addUndefined(StringRef Name, Symbol::Kind Kind,
+Symbol *SymbolTable::addUndefined(StringRef Name, WasmSymbolType Type,
uint32_t Flags, InputFile *F,
- const WasmSignature *Type) {
- DEBUG(dbgs() << "addUndefined: " << Name << "\n");
+ const WasmSignature *FunctionType,
+ const WasmGlobalType *GlobalType) {
+ DEBUG(dbgs() << "addUndefined type=" << Type << ": " << Name << "\n");
Symbol *S;
bool WasInserted;
std::tie(S, WasInserted) = insert(Name);
- bool IsFunction = Kind == Symbol::UndefinedFunctionKind;
if (WasInserted) {
- if (IsFunction)
- replaceSymbol<UndefinedFunction>(S, Name, Flags, F, Type);
- else
+ switch (Type) {
+ case WASM_SYMBOL_TYPE_FUNCTION:
+ replaceSymbol<UndefinedFunction>(S, Name, Flags, F, FunctionType);
+ break;
+ case WASM_SYMBOL_TYPE_GLOBAL:
+ replaceSymbol<UndefinedGlobal>(S, Name, Flags, F, GlobalType);
+ break;
+ case WASM_SYMBOL_TYPE_DATA:
replaceSymbol<UndefinedData>(S, Name, Flags, F);
+ break;
+ }
return S;
}
@@ -231,8 +272,9 @@ Symbol *SymbolTable::addUndefined(String
if (S->isDefined()) {
DEBUG(dbgs() << "resolved by existing\n");
- checkSymbolTypes(*S, *F, IsFunction, Type);
+ checkSymbolTypes(*S, *F, Type, FunctionType, GlobalType);
}
+
return S;
}
Modified: lld/trunk/wasm/SymbolTable.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/SymbolTable.h?rev=325861&r1=325860&r2=325861&view=diff
==============================================================================
--- lld/trunk/wasm/SymbolTable.h (original)
+++ lld/trunk/wasm/SymbolTable.h Thu Feb 22 21:08:53 2018
@@ -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 @@ public:
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<Symbol *, bool> insert(StringRef Name);
Modified: lld/trunk/wasm/Symbols.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/Symbols.cpp?rev=325861&r1=325860&r2=325861&view=diff
==============================================================================
--- lld/trunk/wasm/Symbols.cpp (original)
+++ lld/trunk/wasm/Symbols.cpp Thu Feb 22 21:08:53 2018
@@ -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 @@ DefinedFunction *WasmSym::CallCtors;
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<DefinedFunction>(this))
if (F->Function)
return F->Function->hasOutputIndex();
+ if (auto *G = dyn_cast<DefinedGlobal>(this))
+ if (G->Global)
+ return G->Global->hasOutputIndex();
return OutputIndex != INVALID_INDEX;
}
uint32_t Symbol::getOutputIndex() const {
+ assert(!isa<DataSymbol>(this));
if (auto *F = dyn_cast<DefinedFunction>(this))
if (F->Function)
return F->Function->getOutputIndex();
+ if (auto *G = dyn_cast<DefinedGlobal>(this))
+ if (G->Global)
+ return G->Global->getOutputIndex();
assert(OutputIndex != INVALID_INDEX);
return OutputIndex;
}
@@ -45,13 +70,34 @@ uint32_t Symbol::getOutputIndex() const
InputChunk *Symbol::getChunk() const {
if (auto *F = dyn_cast<DefinedFunction>(this))
return F->Function;
- if (auto *G = dyn_cast<DefinedData>(this))
- return G->Segment;
+ if (auto *D = dyn_cast<DefinedData>(this))
+ return D->Segment;
return nullptr;
}
+bool Symbol::isLive() const {
+ if (auto *G = dyn_cast<DefinedGlobal>(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<DataSymbol>(this));
assert(OutputIndex == INVALID_INDEX);
OutputIndex = Index;
}
@@ -111,14 +157,31 @@ DefinedFunction::DefinedFunction(StringR
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<std::string> S = demangleItanium(Sym.getName()))
@@ -132,12 +195,28 @@ std::string lld::toString(wasm::Symbol::
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");
}
Modified: lld/trunk/wasm/Symbols.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/Symbols.h?rev=325861&r1=325860&r2=325861&view=diff
==============================================================================
--- lld/trunk/wasm/Symbols.h (original)
+++ lld/trunk/wasm/Symbols.h Thu Feb 22 21:08:53 2018
@@ -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 InputFile;
class InputChunk;
class InputSegment;
class InputFunction;
+class InputGlobal;
#define INVALID_INDEX UINT32_MAX
@@ -33,12 +38,14 @@ public:
enum Kind {
DefinedFunctionKind,
DefinedDataKind,
+ DefinedGlobalKind,
LazyKind,
UndefinedFunctionKind,
UndefinedDataKind,
+ UndefinedGlobalKind,
- LastDefinedKind = DefinedDataKind,
+ LastDefinedKind = DefinedGlobalKind,
InvalidKind,
};
@@ -47,8 +54,8 @@ public:
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 @@ public:
// 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 @@ public:
// 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 @@ protected:
uint32_t Flags;
InputFile *File;
uint32_t OutputIndex = INVALID_INDEX;
+ uint32_t OutputSymbolIndex = INVALID_INDEX;
};
class FunctionSymbol : public Symbol {
@@ -112,9 +132,11 @@ protected:
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) {}
@@ -149,22 +171,32 @@ protected:
class DefinedData : public DataSymbol {
public:
- DefinedData(StringRef Name, uint32_t Flags, InputFile *F = nullptr,
- InputSegment *Segment = nullptr, uint32_t Address = 0)
+ // Constructor for for regular data symbols originating from input files.
+ DefinedData(StringRef Name, uint32_t Flags, InputFile *F,
+ InputSegment *Segment, uint32_t Offset, uint32_t Size)
: DataSymbol(Name, DefinedDataKind, Flags, F), Segment(Segment),
- VirtualAddress(Address) {}
+ Offset(Offset), Size(Size) {}
- static bool classof(const Symbol *S) {
- return S->kind() == DefinedDataKind;
- }
+ // Constructor for linker synthetic data symbols.
+ DefinedData(StringRef Name, uint32_t Flags)
+ : DataSymbol(Name, DefinedDataKind, Flags, nullptr) {}
+ 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);
- InputSegment *Segment;
+ // 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 = nullptr;
protected:
- uint32_t VirtualAddress;
+ uint32_t Offset = 0;
+ uint32_t Size = 0;
};
class UndefinedData : public DataSymbol {
@@ -176,6 +208,47 @@ public:
}
};
+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 +267,7 @@ struct WasmSym {
// __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 +294,11 @@ struct WasmSym {
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 <typename T, typename... ArgT>
@@ -243,6 +318,7 @@ T *replaceSymbol(Symbol *S, ArgT &&... A
// 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
Modified: lld/trunk/wasm/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/Writer.cpp?rev=325861&r1=325860&r2=325861&view=diff
==============================================================================
--- lld/trunk/wasm/Writer.cpp (original)
+++ lld/trunk/wasm/Writer.cpp Thu Feb 22 21:08:53 2018
@@ -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 @@ struct WasmSignatureDenseMapInfo {
}
};
-// 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 @@ private:
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 @@ private:
std::vector<const WasmSignature *> Types;
DenseMap<WasmSignature, int32_t, WasmSignatureDenseMapInfo> TypeIndices;
- std::vector<const FunctionSymbol *> ImportedFunctions;
- std::vector<const DataSymbol *> ImportedGlobals;
- std::vector<WasmExportEntry> ExportedSymbols;
- std::vector<const DefinedData *> DefinedDataSymbols;
+ std::vector<const Symbol *> ImportedSymbols;
+ unsigned NumImportedFunctions = 0;
+ unsigned NumImportedGlobals = 0;
+ std::vector<Symbol *> ExportedSymbols;
+ std::vector<const DefinedData *> DefinedFakeGlobals;
+ std::vector<InputGlobal *> InputGlobals;
std::vector<InputFunction *> InputFunctions;
std::vector<const FunctionSymbol *> IndirectFunctions;
- std::vector<WasmInitFunc> InitFunctions;
+ std::vector<const Symbol *> SymtabEntries;
+ std::vector<WasmInitEntry> InitFunctions;
// Elements that are used to construct the final output
std::string Header;
@@ -150,7 +158,7 @@ static void debugPrint(const char *fmt,
}
void Writer::createImportSection() {
- uint32_t NumImports = ImportedFunctions.size() + ImportedGlobals.size();
+ uint32_t NumImports = ImportedSymbols.size();
if (Config->ImportMemory)
++NumImports;
@@ -162,15 +170,6 @@ void Writer::createImportSection() {
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 @@ void Writer::createImportSection() {
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<FunctionSymbol>(Sym)) {
+ Import.Kind = WASM_EXTERNAL_FUNCTION;
+ Import.SigIndex = lookupType(*FunctionSym->getFunctionType());
+ } else {
+ auto *GlobalSym = cast<GlobalSymbol>(Sym);
+ Import.Kind = WASM_EXTERNAL_GLOBAL;
+ Import.Global = *GlobalSym->getGlobalType();
+ }
writeImport(OS, Import);
}
}
@@ -225,17 +229,19 @@ void Writer::createMemorySection() {
}
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 @@ void Writer::createExportSection() {
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<FunctionSymbol>(E.Sym))
+ Export.Name = Sym->getName();
+ if (isa<FunctionSymbol>(Sym)) {
+ Export.Index = Sym->getOutputIndex();
Export.Kind = WASM_EXTERNAL_FUNCTION;
- else
+ } else if (isa<GlobalSymbol>(Sym)) {
+ Export.Index = Sym->getOutputIndex();
Export.Kind = WASM_EXTERNAL_GLOBAL;
+ } else if (isa<DataSymbol>(Sym)) {
+ Export.Index = FakeGlobalIndex++;
+ Export.Kind = WASM_EXTERNAL_GLOBAL;
+ } else {
+ llvm_unreachable("unexpected symbol type");
+ }
writeExport(OS, Export);
}
}
@@ -383,28 +397,39 @@ void Writer::createLinkingSection() {
if (!Config->Relocatable)
return;
- std::vector<std::pair<StringRef, uint32_t>> 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<DefinedData>(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 @@ void Writer::createLinkingSection() {
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 @@ void Writer::createLinkingSection() {
// 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 @@ void Writer::createNameSection() {
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<FunctionSymbol>(S))
+ continue;
writeUleb128(OS, S->getOutputIndex(), "import index");
writeStr(OS, S->getName(), "symbol name");
}
@@ -562,8 +590,9 @@ void Writer::layoutMemory() {
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::createSections() {
void Writer::calculateImports() {
for (Symbol *Sym : Symtab->getSymbols()) {
- if (!Sym->isUndefined() || (Sym->isWeak() && !Config->Relocatable))
+ if (!Sym->isUndefined())
+ continue;
+ if (isa<DataSymbol>(Sym))
+ continue;
+ if (Sym->isWeak() && !Config->Relocatable)
continue;
- if (auto *F = dyn_cast<FunctionSymbol>(Sym)) {
- F->setOutputIndex(ImportedFunctions.size());
- ImportedFunctions.push_back(F);
- } else if (auto *G = dyn_cast<DataSymbol>(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<FunctionSymbol>(Sym))
+ ++NumImportedFunctions;
+ else
+ ++NumImportedGlobals;
}
}
void Writer::calculateExports() {
- bool ExportHidden = Config->Relocatable;
- StringSet<> UsedNames;
+ if (Config->Relocatable)
+ return;
- 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;
- }
+ 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<DefinedData>(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<FunctionSymbol>(Sym))
- continue;
- if (!Sym->getChunk()->Live)
- continue;
-
- if ((Sym->isHidden() || Sym->isLocal()) && !ExportHidden)
+ if (Sym->getFile() != File)
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 @@ void Writer::calculateTypes() {
File->TypeMap[I] = registerType(Types[I]);
}
- for (const FunctionSymbol *Sym : ImportedFunctions)
- registerType(*Sym->getFunctionType());
+ for (const Symbol *Sym : ImportedSymbols)
+ if (auto *F = dyn_cast<FunctionSymbol>(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<DefinedData>(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 @@ void Writer::assignIndexes() {
}
}
+ uint32_t TableIndex = kInitialTableOffset;
auto HandleRelocs = [&](InputChunk *Chunk) {
if (!Chunk->Live)
return;
ObjFile *File = Chunk->File;
ArrayRef<WasmSignature> 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 @@ void Writer::assignIndexes() {
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<DefinedGlobal>(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 @@ void Writer::createOutputSegments() {
OutputSegment *&S = SegmentMap[Name];
if (S == nullptr) {
DEBUG(dbgs() << "new segment: " << Name << "\n");
- S = make<OutputSegment>(Name);
+ S = make<OutputSegment>(Name, Segments.size());
Segments.push_back(S);
}
S->addInputSegment(Segment);
@@ -829,18 +871,18 @@ static const int OPCODE_END = 0xb;
// 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 @@ void Writer::createCtorFunction() {
ArrayRef<uint8_t> BodyArray(
reinterpret_cast<const uint8_t *>(CtorFunctionBody.data()),
CtorFunctionBody.size());
- SyntheticFunction *F = make<SyntheticFunction>(Signature, BodyArray,
+ SyntheticFunction *F = make<SyntheticFunction>(*Signature, BodyArray,
WasmSym::CallCtors->getName());
F->setOutputIndex(FunctionIndex);
+ F->Live = true;
+ WasmSym::CallCtors->Function = F;
InputFunctions.emplace_back(F);
}
@@ -867,13 +911,13 @@ void Writer::calculateInitFunctions() {
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 @@ void Writer::run() {
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();
Modified: lld/trunk/wasm/WriterUtils.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/WriterUtils.cpp?rev=325861&r1=325860&r2=325861&view=diff
==============================================================================
--- lld/trunk/wasm/WriterUtils.cpp (original)
+++ lld/trunk/wasm/WriterUtils.cpp Thu Feb 22 21:08:53 2018
@@ -190,3 +190,10 @@ std::string lld::toString(const WasmSign
S += toString(static_cast<ValType>(Sig.ReturnType));
return S.str();
}
+
+std::string lld::toString(const WasmGlobalType &Sig) {
+ std::string S = toString(static_cast<ValType>(Sig.Type));
+ if (Sig.Mutable)
+ return "mutable " + S;
+ return S;
+}
Modified: lld/trunk/wasm/WriterUtils.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/WriterUtils.h?rev=325861&r1=325860&r2=325861&view=diff
==============================================================================
--- lld/trunk/wasm/WriterUtils.h (original)
+++ lld/trunk/wasm/WriterUtils.h Thu Feb 22 21:08:53 2018
@@ -28,6 +28,17 @@ inline bool operator!=(const llvm::wasm:
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 @@ void writeExport(raw_ostream &OS, const
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
More information about the llvm-commits
mailing list