forked from OSchip/llvm-project
[WebAssembly] Create synthetic __wasm_call_ctors function
This change create a new synthetic function in the final output binary which calls the static constructors in sequence. See: https://github.com/WebAssembly/tool-conventions/issues/25 Differential Revision: https://reviews.llvm.org/D41893 llvm-svn: 322388
This commit is contained in:
parent
3d139c527b
commit
5068685678
|
@ -9,6 +9,14 @@ entry:
|
|||
ret void
|
||||
}
|
||||
|
||||
@llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @myctor, i8* null }]
|
||||
@llvm.global_ctors = appending global [3 x { i32, void ()*, i8* }] [
|
||||
{ i32, void ()*, i8* } { i32 2002, void ()* @myctor, i8* null },
|
||||
{ i32, void ()*, i8* } { i32 101, void ()* @myctor, i8* null },
|
||||
{ i32, void ()*, i8* } { i32 202, void ()* @myctor, i8* null }
|
||||
]
|
||||
|
||||
@llvm.global_dtors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @mydtor, i8* null }]
|
||||
@llvm.global_dtors = appending global [3 x { i32, void ()*, i8* }] [
|
||||
{ i32, void ()*, i8* } { i32 2002, void ()* @mydtor, i8* null },
|
||||
{ i32, void ()*, i8* } { i32 101, void ()* @mydtor, i8* null },
|
||||
{ i32, void ()*, i8* } { i32 202, void ()* @mydtor, i8* null }
|
||||
]
|
||||
|
|
|
@ -19,8 +19,11 @@ entry:
|
|||
; CHECK-NEXT: - Index: 0
|
||||
; CHECK-NEXT: ReturnType: I32
|
||||
; CHECK-NEXT: ParamTypes:
|
||||
; CHECK-NEXT: - Index: 1
|
||||
; CHECK-NEXT: ReturnType: NORESULT
|
||||
; CHECK-NEXT: ParamTypes:
|
||||
; CHECK-NEXT: - Type: FUNCTION
|
||||
; CHECK-NEXT: FunctionTypes: [ 0 ]
|
||||
; CHECK-NEXT: FunctionTypes: [ 0, 1 ]
|
||||
; CHECK-NEXT: - Type: TABLE
|
||||
; CHECK-NEXT: Tables:
|
||||
; CHECK-NEXT: - ElemType: ANYFUNC
|
||||
|
@ -55,6 +58,9 @@ entry:
|
|||
; CHECK-NEXT: - Index: 0
|
||||
; CHECK-NEXT: Locals:
|
||||
; CHECK-NEXT: Body: 41000B
|
||||
; CHECK-NEXT: - Index: 1
|
||||
; CHECK-NEXT: Locals:
|
||||
; CHECK-NEXT: Body: 0B
|
||||
; CHECK-NEXT: - Type: CUSTOM
|
||||
; CHECK-NEXT: Name: linking
|
||||
; CHECK-NEXT: DataSize: 0
|
||||
|
@ -63,4 +69,6 @@ entry:
|
|||
; CHECK-NEXT: FunctionNames:
|
||||
; CHECK-NEXT: - Index: 0
|
||||
; CHECK-NEXT: Name: start_alias
|
||||
; CHECK-NEXT: - Index: 1
|
||||
; CHECK-NEXT: Name: __wasm_call_ctors
|
||||
; CHECK-NEXT: ...
|
||||
|
|
|
@ -52,7 +52,7 @@ define void @call_ptr(i64 (i64)* %arg) {
|
|||
; CHECK-NEXT: ParamTypes:
|
||||
; CHECK-NEXT: - I64
|
||||
; CHECK-NEXT: - Type: FUNCTION
|
||||
; CHECK-NEXT: FunctionTypes: [ 0, 1, 0, 0, 2 ]
|
||||
; CHECK-NEXT: FunctionTypes: [ 0, 1, 0, 0, 2, 1 ]
|
||||
; CHECK-NEXT: - Type: TABLE
|
||||
; CHECK-NEXT: Tables:
|
||||
; CHECK-NEXT: - ElemType: ANYFUNC
|
||||
|
@ -114,6 +114,9 @@ define void @call_ptr(i64 (i64)* %arg) {
|
|||
; CHECK-NEXT: - Index: 4
|
||||
; CHECK-NEXT: Locals:
|
||||
; CHECK-NEXT: Body: 42012000118380808000001A0B
|
||||
; CHECK-NEXT: - Index: 5
|
||||
; CHECK-NEXT: Locals:
|
||||
; CHECK-NEXT: Body: 0B
|
||||
; CHECK-NEXT: - Type: DATA
|
||||
; CHECK-NEXT: Segments:
|
||||
; CHECK-NEXT: - SectionOffset: 7
|
||||
|
|
|
@ -22,7 +22,7 @@ declare i32 @ret32(float) local_unnamed_addr #1
|
|||
; CHECK-NEXT: ParamTypes:
|
||||
; CHECK-NEXT: - F32
|
||||
; CHECK: - Type: FUNCTION
|
||||
; CHECK-NEXT: FunctionTypes: [ 0, 1 ]
|
||||
; CHECK-NEXT: FunctionTypes: [ 0, 1, 0 ]
|
||||
; CHECK: - Type: CODE
|
||||
; CHECK-NEXT: Functions:
|
||||
; CHECK-NEXT: - Index: 0
|
||||
|
@ -31,6 +31,9 @@ declare i32 @ret32(float) local_unnamed_addr #1
|
|||
; CHECK-NEXT: - Index: 1
|
||||
; CHECK-NEXT: Locals:
|
||||
; CHECK-NEXT: Body: 41000B
|
||||
; CHECK-NEXT: - Index: 2
|
||||
; CHECK-NEXT: Locals:
|
||||
; CHECK-NEXT: Body: 0B
|
||||
; CHECK-NEXT: - Type: CUSTOM
|
||||
; CHECK-NEXT: Name: linking
|
||||
; CHECK-NEXT: DataSize: 0
|
||||
|
@ -41,4 +44,6 @@ declare i32 @ret32(float) local_unnamed_addr #1
|
|||
; CHECK-NEXT: Name: _start
|
||||
; CHECK-NEXT: - Index: 1
|
||||
; CHECK-NEXT: Name: ret32
|
||||
; CHECK-NEXT: - Index: 2
|
||||
; CHECK-NEXT: Name: __wasm_call_ctors
|
||||
; CHECK-NEXT: ...
|
||||
|
|
|
@ -23,15 +23,18 @@ declare i32 @ret32(float) local_unnamed_addr #1
|
|||
; CHECK-NEXT: ReturnType: NORESULT
|
||||
; CHECK-NEXT: ParamTypes:
|
||||
; CHECK-NEXT: - Type: FUNCTION
|
||||
; CHECK-NEXT: FunctionTypes: [ 0, 1 ]
|
||||
; CHECK-NEXT: FunctionTypes: [ 0, 1, 1 ]
|
||||
; CHECK: - Type: CODE
|
||||
; CHECK-NEXT: Functions:
|
||||
; CHECK: - Index: 0
|
||||
; CHECK: - Index: 1
|
||||
; CHECK: - Index: 2
|
||||
; CHECK: Name: name
|
||||
; CHECK-NEXT: FunctionNames:
|
||||
; CHECK-NEXT: - Index: 0
|
||||
; CHECK-NEXT: Name: ret32
|
||||
; CHECK-NEXT: - Index: 1
|
||||
; CHECK-NEXT: Name: _start
|
||||
; CHECK-NEXT: - Index: 2
|
||||
; CHECK-NEXT: Name: __wasm_call_ctors
|
||||
; CHECK-NEXT: ...
|
||||
|
|
|
@ -11,6 +11,16 @@ entry:
|
|||
ret void
|
||||
}
|
||||
|
||||
define hidden void @func3() {
|
||||
entry:
|
||||
ret void
|
||||
}
|
||||
|
||||
define hidden void @func4() {
|
||||
entry:
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @__cxa_atexit() {
|
||||
ret void
|
||||
}
|
||||
|
@ -20,14 +30,31 @@ entry:
|
|||
ret void
|
||||
}
|
||||
|
||||
@llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @func1, i8* null }]
|
||||
@llvm.global_ctors = appending global [3 x { i32, void ()*, i8* }] [
|
||||
{ i32, void ()*, i8* } { i32 1001, void ()* @func1, i8* null },
|
||||
{ i32, void ()*, i8* } { i32 101, void ()* @func1, i8* null },
|
||||
{ i32, void ()*, i8* } { i32 101, void ()* @func2, i8* null }
|
||||
]
|
||||
|
||||
@llvm.global_dtors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @func2, i8* null }]
|
||||
@llvm.global_dtors = appending global [3 x { i32, void ()*, i8* }] [
|
||||
{ i32, void ()*, i8* } { i32 1001, void ()* @func3, i8* null },
|
||||
{ i32, void ()*, i8* } { i32 101, void ()* @func3, i8* null },
|
||||
{ i32, void ()*, i8* } { i32 101, void ()* @func4, i8* null }
|
||||
]
|
||||
|
||||
; RUN: lld -flavor wasm %t.o %t.global-ctor-dtor.o -o %t.wasm
|
||||
; RUN: obj2yaml %t.wasm | FileCheck %s
|
||||
|
||||
; CHECK: Name: linking
|
||||
; CHECK: - Type: ELEM
|
||||
; CHECK-NEXT: Segments:
|
||||
; CHECK-NEXT: - Offset:
|
||||
; CHECK-NEXT: Opcode: I32_CONST
|
||||
; CHECK-NEXT: Value: 1
|
||||
; CHECK-NEXT: Functions: [ 6, 9, 13, 15, 17 ]
|
||||
|
||||
; CHECK: Body: 100010011007100B100E100B10101000100A100B10120B
|
||||
; CHECK-NEXT: - Type: CUSTOM
|
||||
; CHECK-NEXT: Name: linking
|
||||
; CHECK-NEXT: DataSize: 0
|
||||
; CHECK-NEXT: - Type: CUSTOM
|
||||
; CHECK-NEXT: Name: name
|
||||
|
@ -37,23 +64,41 @@ entry:
|
|||
; CHECK-NEXT: - Index: 1
|
||||
; CHECK-NEXT: Name: func2
|
||||
; CHECK-NEXT: - Index: 2
|
||||
; CHECK-NEXT: Name: __cxa_atexit
|
||||
; CHECK-NEXT: Name: func3
|
||||
; CHECK-NEXT: - Index: 3
|
||||
; CHECK-NEXT: Name: _start
|
||||
; CHECK-NEXT: Name: func4
|
||||
; CHECK-NEXT: - Index: 4
|
||||
; CHECK-NEXT: Name: .Lcall_dtors
|
||||
; CHECK-NEXT: Name: __cxa_atexit
|
||||
; CHECK-NEXT: - Index: 5
|
||||
; CHECK-NEXT: Name: .Lregister_call_dtors
|
||||
; CHECK-NEXT: Name: _start
|
||||
; CHECK-NEXT: - Index: 6
|
||||
; CHECK-NEXT: Name: .Lbitcast
|
||||
; CHECK-NEXT: Name: .Lcall_dtors.101
|
||||
; CHECK-NEXT: - Index: 7
|
||||
; CHECK-NEXT: Name: myctor
|
||||
; CHECK-NEXT: Name: .Lregister_call_dtors.101
|
||||
; CHECK-NEXT: - Index: 8
|
||||
; CHECK-NEXT: Name: mydtor
|
||||
; CHECK-NEXT: Name: .Lbitcast
|
||||
; CHECK-NEXT: - Index: 9
|
||||
; CHECK-NEXT: Name: .Lcall_dtors
|
||||
; CHECK-NEXT: Name: .Lcall_dtors.1001
|
||||
; CHECK-NEXT: - Index: 10
|
||||
; CHECK-NEXT: Name: .Lregister_call_dtors
|
||||
; CHECK-NEXT: Name: .Lregister_call_dtors.1001
|
||||
; CHECK-NEXT: - Index: 11
|
||||
; CHECK-NEXT: Name: myctor
|
||||
; CHECK-NEXT: - Index: 12
|
||||
; CHECK-NEXT: Name: mydtor
|
||||
; CHECK-NEXT: - Index: 13
|
||||
; CHECK-NEXT: Name: .Lcall_dtors.101
|
||||
; CHECK-NEXT: - Index: 14
|
||||
; CHECK-NEXT: Name: .Lregister_call_dtors.101
|
||||
; CHECK-NEXT: - Index: 15
|
||||
; CHECK-NEXT: Name: .Lcall_dtors.202
|
||||
; CHECK-NEXT: - Index: 16
|
||||
; CHECK-NEXT: Name: .Lregister_call_dtors.202
|
||||
; CHECK-NEXT: - Index: 17
|
||||
; CHECK-NEXT: Name: .Lcall_dtors.2002
|
||||
; CHECK-NEXT: - Index: 18
|
||||
; CHECK-NEXT: Name: .Lregister_call_dtors.2002
|
||||
; CHECK-NEXT: - Index: 19
|
||||
; CHECK-NEXT: Name: __wasm_call_ctors
|
||||
; CHECK-NEXT: ...
|
||||
|
||||
|
||||
|
@ -63,14 +108,28 @@ entry:
|
|||
; RELOC: Name: linking
|
||||
; RELOC-NEXT: DataSize: 0
|
||||
; RELOC-NEXT: InitFunctions:
|
||||
; RELOC-NEXT: - Priority: 65535
|
||||
; RELOC-NEXT: - Priority: 101
|
||||
; RELOC-NEXT: FunctionIndex: 0
|
||||
; RELOC-NEXT: - Priority: 65535
|
||||
; RELOC-NEXT: FunctionIndex: 5
|
||||
; RELOC-NEXT: - Priority: 65535
|
||||
; RELOC-NEXT: - Priority: 101
|
||||
; RELOC-NEXT: FunctionIndex: 1
|
||||
; RELOC-NEXT: - Priority: 101
|
||||
; RELOC-NEXT: FunctionIndex: 7
|
||||
; RELOC-NEXT: - Priority: 65535
|
||||
; RELOC-NEXT: - Priority: 101
|
||||
; RELOC-NEXT: FunctionIndex: 11
|
||||
; RELOC-NEXT: - Priority: 101
|
||||
; RELOC-NEXT: FunctionIndex: 14
|
||||
; RELOC-NEXT: - Priority: 202
|
||||
; RELOC-NEXT: FunctionIndex: 11
|
||||
; RELOC-NEXT: - Priority: 202
|
||||
; RELOC-NEXT: FunctionIndex: 16
|
||||
; RELOC-NEXT: - Priority: 1001
|
||||
; RELOC-NEXT: FunctionIndex: 0
|
||||
; RELOC-NEXT: - Priority: 1001
|
||||
; RELOC-NEXT: FunctionIndex: 10
|
||||
; RELOC-NEXT: - Priority: 2002
|
||||
; RELOC-NEXT: FunctionIndex: 11
|
||||
; RELOC-NEXT: - Priority: 2002
|
||||
; RELOC-NEXT: FunctionIndex: 18
|
||||
; RELOC-NEXT: - Type: CUSTOM
|
||||
; RELOC-NEXT: Name: name
|
||||
; RELOC-NEXT: FunctionNames:
|
||||
|
@ -79,21 +138,37 @@ entry:
|
|||
; RELOC-NEXT: - Index: 1
|
||||
; RELOC-NEXT: Name: func2
|
||||
; RELOC-NEXT: - Index: 2
|
||||
; RELOC-NEXT: Name: __cxa_atexit
|
||||
; RELOC-NEXT: Name: func3
|
||||
; RELOC-NEXT: - Index: 3
|
||||
; RELOC-NEXT: Name: _start
|
||||
; RELOC-NEXT: Name: func4
|
||||
; RELOC-NEXT: - Index: 4
|
||||
; RELOC-NEXT: Name: .Lcall_dtors
|
||||
; RELOC-NEXT: Name: __cxa_atexit
|
||||
; RELOC-NEXT: - Index: 5
|
||||
; RELOC-NEXT: Name: .Lregister_call_dtors
|
||||
; RELOC-NEXT: Name: _start
|
||||
; RELOC-NEXT: - Index: 6
|
||||
; RELOC-NEXT: Name: .Lbitcast
|
||||
; RELOC-NEXT: Name: .Lcall_dtors.101
|
||||
; RELOC-NEXT: - Index: 7
|
||||
; RELOC-NEXT: Name: myctor
|
||||
; RELOC-NEXT: Name: .Lregister_call_dtors.101
|
||||
; RELOC-NEXT: - Index: 8
|
||||
; RELOC-NEXT: Name: mydtor
|
||||
; RELOC-NEXT: Name: .Lbitcast
|
||||
; RELOC-NEXT: - Index: 9
|
||||
; RELOC-NEXT: Name: .Lcall_dtors
|
||||
; RELOC-NEXT: Name: .Lcall_dtors.1001
|
||||
; RELOC-NEXT: - Index: 10
|
||||
; RELOC-NEXT: Name: .Lregister_call_dtors
|
||||
; RELOC-NEXT: Name: .Lregister_call_dtors.1001
|
||||
; RELOC-NEXT: - Index: 11
|
||||
; RELOC-NEXT: Name: myctor
|
||||
; RELOC-NEXT: - Index: 12
|
||||
; RELOC-NEXT: Name: mydtor
|
||||
; RELOC-NEXT: - Index: 13
|
||||
; RELOC-NEXT: Name: .Lcall_dtors.101
|
||||
; RELOC-NEXT: - Index: 14
|
||||
; RELOC-NEXT: Name: .Lregister_call_dtors.101
|
||||
; RELOC-NEXT: - Index: 15
|
||||
; RELOC-NEXT: Name: .Lcall_dtors.202
|
||||
; RELOC-NEXT: - Index: 16
|
||||
; RELOC-NEXT: Name: .Lregister_call_dtors.202
|
||||
; RELOC-NEXT: - Index: 17
|
||||
; RELOC-NEXT: Name: .Lcall_dtors.2002
|
||||
; RELOC-NEXT: - Index: 18
|
||||
; RELOC-NEXT: Name: .Lregister_call_dtors.2002
|
||||
; RELOC-NEXT: ...
|
||||
|
|
|
@ -24,8 +24,11 @@ entry:
|
|||
; CHECK-NEXT: - Index: 0
|
||||
; CHECK-NEXT: ReturnType: I32
|
||||
; CHECK-NEXT: ParamTypes:
|
||||
; CHECK-NEXT: - Index: 1
|
||||
; CHECK-NEXT: ReturnType: NORESULT
|
||||
; CHECK-NEXT: ParamTypes:
|
||||
; CHECK-NEXT: - Type: FUNCTION
|
||||
; CHECK-NEXT: FunctionTypes: [ 0, 0 ]
|
||||
; CHECK-NEXT: FunctionTypes: [ 0, 0, 1 ]
|
||||
; CHECK-NEXT: - Type: TABLE
|
||||
; CHECK-NEXT: Tables:
|
||||
; CHECK-NEXT: - ElemType: ANYFUNC
|
||||
|
@ -60,6 +63,9 @@ entry:
|
|||
; CHECK-NEXT: - Index: 1
|
||||
; CHECK-NEXT: Locals:
|
||||
; CHECK-NEXT: Body: 41010B
|
||||
; CHECK-NEXT: - Index: 2
|
||||
; CHECK-NEXT: Locals:
|
||||
; CHECK-NEXT: Body: 0B
|
||||
; CHECK-NEXT: - Type: DATA
|
||||
; CHECK-NEXT: Segments:
|
||||
; CHECK-NEXT: - SectionOffset: 7
|
||||
|
@ -78,4 +84,6 @@ entry:
|
|||
; CHECK-NEXT: Name: baz
|
||||
; CHECK-NEXT: - Index: 1
|
||||
; CHECK-NEXT: Name: _start
|
||||
; CHECK-NEXT: - Index: 2
|
||||
; CHECK-NEXT: Name: __wasm_call_ctors
|
||||
; CHECK-NEXT: ...
|
||||
|
|
|
@ -18,8 +18,11 @@ entry:
|
|||
; CHECK-NEXT: - Index: 0
|
||||
; CHECK-NEXT: ReturnType: I32
|
||||
; CHECK-NEXT: ParamTypes:
|
||||
; CHECK-NEXT: - Index: 1
|
||||
; CHECK-NEXT: ReturnType: NORESULT
|
||||
; CHECK-NEXT: ParamTypes:
|
||||
; CHECK-NEXT: - Type: FUNCTION
|
||||
; CHECK-NEXT: FunctionTypes: [ 0 ]
|
||||
; CHECK-NEXT: FunctionTypes: [ 0, 1 ]
|
||||
; CHECK-NEXT: - Type: TABLE
|
||||
; CHECK-NEXT: Tables:
|
||||
; CHECK-NEXT: - ElemType: ANYFUNC
|
||||
|
@ -46,6 +49,9 @@ entry:
|
|||
; CHECK-NEXT: - Name: _start
|
||||
; CHECK-NEXT: Kind: FUNCTION
|
||||
; CHECK-NEXT: Index: 0
|
||||
; CHECK-NEXT: - Name: __wasm_call_ctors
|
||||
; CHECK-NEXT: Kind: FUNCTION
|
||||
; CHECK-NEXT: Index: 1
|
||||
; CHECK-NEXT: - Type: CODE
|
||||
; CHECK-NEXT: Relocations:
|
||||
; CHECK-NEXT: - Type: R_WEBASSEMBLY_GLOBAL_INDEX_LEB
|
||||
|
@ -55,6 +61,9 @@ entry:
|
|||
; CHECK-NEXT: - Index: 0
|
||||
; CHECK-NEXT: Locals:
|
||||
; CHECK-NEXT: Body: 23808080800041106B1A41000B
|
||||
; CHECK-NEXT: - Index: 1
|
||||
; CHECK-NEXT: Locals:
|
||||
; CHECK-NEXT: Body: 0B
|
||||
; CHECK-NEXT: - Type: CUSTOM
|
||||
; CHECK-NEXT: Name: linking
|
||||
; CHECK-NEXT: DataSize: 0
|
||||
|
@ -63,4 +72,6 @@ entry:
|
|||
; CHECK-NEXT: FunctionNames:
|
||||
; CHECK-NEXT: - Index: 0
|
||||
; CHECK-NEXT: Name: _start
|
||||
; CHECK-NEXT: - Index: 1
|
||||
; CHECK-NEXT: Name: __wasm_call_ctors
|
||||
; CHECK-NEXT: ...
|
||||
|
|
|
@ -30,7 +30,7 @@ entry:
|
|||
; CHECK-NEXT: ReturnType: NORESULT
|
||||
; CHECK-NEXT: ParamTypes:
|
||||
; CHECK-NEXT: - Type: FUNCTION
|
||||
; CHECK-NEXT: FunctionTypes: [ 0, 1, 0, 0, 0, 0, 0 ]
|
||||
; CHECK-NEXT: FunctionTypes: [ 0, 1, 0, 0, 0, 0, 0, 1 ]
|
||||
; CHECK-NEXT: - Type: TABLE
|
||||
; CHECK-NEXT: Tables:
|
||||
; CHECK-NEXT: - ElemType: ANYFUNC
|
||||
|
@ -108,6 +108,9 @@ entry:
|
|||
; CHECK-NEXT: - Type: I32
|
||||
; CHECK-NEXT: Count: 2
|
||||
; CHECK-NEXT: Body: 23808080800041106B220024808080800020004182808080003602081082808080002101200041106A24808080800020010B
|
||||
; CHECK-NEXT: - Index: 7
|
||||
; CHECK-NEXT: Locals:
|
||||
; CHECK-NEXT: Body: 0B
|
||||
; CHECK-NEXT: - Type: CUSTOM
|
||||
; CHECK-NEXT: Name: linking
|
||||
; CHECK-NEXT: DataSize: 0
|
||||
|
@ -128,4 +131,6 @@ entry:
|
|||
; CHECK-NEXT: Name: call_alias_ptr
|
||||
; CHECK-NEXT: - Index: 6
|
||||
; CHECK-NEXT: Name: call_direct_ptr
|
||||
; CHECK-NEXT: - Index: 7
|
||||
; CHECK-NEXT: Name: __wasm_call_ctors
|
||||
; CHECK-NEXT: ...
|
||||
|
|
|
@ -23,8 +23,11 @@ entry:
|
|||
; CHECK-NEXT: - Index: 0
|
||||
; CHECK-NEXT: ReturnType: I32
|
||||
; CHECK-NEXT: ParamTypes:
|
||||
; CHECK-NEXT: - Index: 1
|
||||
; CHECK-NEXT: ReturnType: NORESULT
|
||||
; CHECK-NEXT: ParamTypes:
|
||||
; CHECK-NEXT: - Type: FUNCTION
|
||||
; CHECK-NEXT: FunctionTypes: [ 0, 0, 0, 0, 0, 0 ]
|
||||
; CHECK-NEXT: FunctionTypes: [ 0, 0, 0, 0, 0, 0, 1 ]
|
||||
; CHECK-NEXT: - Type: TABLE
|
||||
; CHECK-NEXT: Tables:
|
||||
; CHECK-NEXT: - ElemType: ANYFUNC
|
||||
|
@ -99,6 +102,9 @@ entry:
|
|||
; CHECK-NEXT: - Type: I32
|
||||
; CHECK-NEXT: Count: 2
|
||||
; CHECK-NEXT: Body: 23808080800041106B220024808080800020004182808080003602081081808080002101200041106A24808080800020010B
|
||||
; CHECK-NEXT: - Index: 6
|
||||
; CHECK-NEXT: Locals:
|
||||
; CHECK-NEXT: Body: 0B
|
||||
; CHECK-NEXT: - Type: CUSTOM
|
||||
; CHECK-NEXT: Name: linking
|
||||
; CHECK-NEXT: DataSize: 0
|
||||
|
@ -117,4 +123,6 @@ entry:
|
|||
; CHECK-NEXT: Name: call_alias_ptr
|
||||
; CHECK-NEXT: - Index: 5
|
||||
; CHECK-NEXT: Name: call_direct_ptr
|
||||
; CHECK-NEXT: - Index: 6
|
||||
; CHECK-NEXT: Name: __wasm_call_ctors
|
||||
; CHECK-NEXT: ...
|
||||
|
|
|
@ -23,8 +23,11 @@ entry:
|
|||
; CHECK-NEXT: - Index: 0
|
||||
; CHECK-NEXT: ReturnType: I32
|
||||
; CHECK-NEXT: ParamTypes:
|
||||
; CHECK-NEXT: - Index: 1
|
||||
; CHECK-NEXT: ReturnType: NORESULT
|
||||
; CHECK-NEXT: ParamTypes:
|
||||
; CHECK-NEXT: - Type: FUNCTION
|
||||
; CHECK-NEXT: FunctionTypes: [ 0, 0, 0, 0, 0 ]
|
||||
; CHECK-NEXT: FunctionTypes: [ 0, 0, 0, 0, 0, 1 ]
|
||||
; CHECK-NEXT: - Type: TABLE
|
||||
; CHECK-NEXT: Tables:
|
||||
; CHECK-NEXT: - ElemType: ANYFUNC
|
||||
|
@ -83,6 +86,9 @@ entry:
|
|||
; CHECK-NEXT: - Index: 4
|
||||
; CHECK-NEXT: Locals:
|
||||
; CHECK-NEXT: Body: 4181808080000B
|
||||
; CHECK-NEXT: - Index: 5
|
||||
; CHECK-NEXT: Locals:
|
||||
; CHECK-NEXT: Body: 0B
|
||||
; CHECK-NEXT: - Type: DATA
|
||||
; CHECK-NEXT: Segments:
|
||||
; CHECK-NEXT: - SectionOffset: 7
|
||||
|
@ -103,4 +109,6 @@ entry:
|
|||
; CHECK-NEXT: Name: exportWeak1
|
||||
; CHECK-NEXT: - Index: 4
|
||||
; CHECK-NEXT: Name: exportWeak2
|
||||
; CHECK-NEXT: - Index: 5
|
||||
; CHECK-NEXT: Name: __wasm_call_ctors
|
||||
; CHECK-NEXT: ...
|
||||
|
|
|
@ -33,8 +33,11 @@ entry:
|
|||
; CHECK-NEXT: - Index: 0
|
||||
; CHECK-NEXT: ReturnType: I32
|
||||
; CHECK-NEXT: ParamTypes:
|
||||
; CHECK-NEXT: - Index: 1
|
||||
; CHECK-NEXT: ReturnType: NORESULT
|
||||
; CHECK-NEXT: ParamTypes:
|
||||
; CHECK-NEXT: - Type: FUNCTION
|
||||
; CHECK-NEXT: FunctionTypes: [ 0, 0, 0 ]
|
||||
; CHECK-NEXT: FunctionTypes: [ 0, 0, 0, 1 ]
|
||||
; CHECK-NEXT: - Type: TABLE
|
||||
; CHECK-NEXT: Tables:
|
||||
; CHECK-NEXT: - ElemType: ANYFUNC
|
||||
|
@ -78,6 +81,9 @@ entry:
|
|||
; CHECK-NEXT: - Index: 2
|
||||
; CHECK-NEXT: Locals:
|
||||
; CHECK-NEXT: Body: 4100280280808080000B
|
||||
; CHECK-NEXT: - Index: 3
|
||||
; CHECK-NEXT: Locals:
|
||||
; CHECK-NEXT: Body: 0B
|
||||
; CHECK-NEXT: - Type: CUSTOM
|
||||
; CHECK-NEXT: Name: linking
|
||||
; CHECK-NEXT: DataSize: 0
|
||||
|
|
|
@ -40,6 +40,7 @@ struct Configuration {
|
|||
llvm::StringSet<> AllowUndefinedSymbols;
|
||||
std::vector<llvm::StringRef> SearchPaths;
|
||||
Symbol *StackPointerSymbol = nullptr;
|
||||
Symbol *CtorSymbol = nullptr;
|
||||
};
|
||||
|
||||
// The only instance of Configuration struct.
|
||||
|
|
|
@ -291,15 +291,16 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
|
|||
error("undefined symbols specified for relocatable output file");
|
||||
|
||||
if (!Config->Relocatable) {
|
||||
if (!Config->Entry.empty()) {
|
||||
static WasmSignature Signature = {{}, WASM_TYPE_NORESULT};
|
||||
static WasmSignature Signature = {{}, WASM_TYPE_NORESULT};
|
||||
if (!Config->Entry.empty())
|
||||
addSyntheticUndefinedFunction(Config->Entry, &Signature);
|
||||
}
|
||||
|
||||
// Handle the `--undefined <sym>` options.
|
||||
for (StringRef S : args::getStrings(Args, OPT_undefined))
|
||||
addSyntheticUndefinedFunction(S, nullptr);
|
||||
|
||||
Config->CtorSymbol = Symtab->addDefinedFunction(
|
||||
"__wasm_call_ctors", &Signature, WASM_SYMBOL_VISIBILITY_HIDDEN);
|
||||
Config->StackPointerSymbol = Symtab->addDefinedGlobal("__stack_pointer");
|
||||
}
|
||||
|
||||
|
|
|
@ -30,6 +30,8 @@ uint32_t InputSegment::translateVA(uint32_t Address) const {
|
|||
}
|
||||
|
||||
void InputChunk::copyRelocations(const WasmSection &Section) {
|
||||
if (Section.Relocations.empty())
|
||||
return;
|
||||
size_t Start = getInputSectionOffset();
|
||||
size_t Size = getSize();
|
||||
for (const WasmRelocation &R : Section.Relocations)
|
||||
|
@ -92,8 +94,10 @@ void InputChunk::writeTo(uint8_t *SectionStart) const {
|
|||
// output section. Calculates the updated index and offset for each relocation
|
||||
// as well as the value to write out in the final binary.
|
||||
void InputChunk::calcRelocations() {
|
||||
if (Relocations.empty())
|
||||
return;
|
||||
int32_t Off = getOutputOffset() - getInputSectionOffset();
|
||||
DEBUG(dbgs() << "calcRelocations: " << File.getName()
|
||||
DEBUG(dbgs() << "calcRelocations: " << File->getName()
|
||||
<< " offset=" << Twine(Off) << "\n");
|
||||
for (const WasmRelocation &Reloc : Relocations) {
|
||||
OutputRelocation NewReloc;
|
||||
|
@ -105,19 +109,25 @@ void InputChunk::calcRelocations() {
|
|||
<< " newOffset=" << NewReloc.Reloc.Offset << "\n");
|
||||
|
||||
if (Config->EmitRelocs)
|
||||
NewReloc.NewIndex = File.calcNewIndex(Reloc);
|
||||
NewReloc.NewIndex = File->calcNewIndex(Reloc);
|
||||
|
||||
switch (Reloc.Type) {
|
||||
case R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
|
||||
case R_WEBASSEMBLY_MEMORY_ADDR_I32:
|
||||
case R_WEBASSEMBLY_MEMORY_ADDR_LEB:
|
||||
NewReloc.Value = File.getRelocatedAddress(Reloc.Index) + Reloc.Addend;
|
||||
NewReloc.Value = File->getRelocatedAddress(Reloc.Index) + Reloc.Addend;
|
||||
break;
|
||||
default:
|
||||
NewReloc.Value = File.calcNewIndex(Reloc);
|
||||
NewReloc.Value = File->calcNewIndex(Reloc);
|
||||
break;
|
||||
}
|
||||
|
||||
OutRelocations.emplace_back(NewReloc);
|
||||
}
|
||||
}
|
||||
|
||||
void InputFunction::setOutputIndex(uint32_t Index) {
|
||||
DEBUG(dbgs() << "InputFunction::setOutputIndex: " << Index << "\n");
|
||||
assert(!hasOutputIndex());
|
||||
OutputIndex = Index;
|
||||
};
|
||||
|
|
|
@ -50,7 +50,7 @@ public:
|
|||
std::vector<OutputRelocation> OutRelocations;
|
||||
|
||||
protected:
|
||||
InputChunk(const ObjFile &F) : File(F) {}
|
||||
InputChunk(const ObjFile *F) : File(F) {}
|
||||
virtual ~InputChunk() = default;
|
||||
void calcRelocations();
|
||||
virtual const uint8_t *getData() const = 0;
|
||||
|
@ -58,7 +58,7 @@ protected:
|
|||
|
||||
std::vector<WasmRelocation> Relocations;
|
||||
int32_t OutputOffset = 0;
|
||||
const ObjFile &File;
|
||||
const ObjFile *File;
|
||||
};
|
||||
|
||||
// Represents a WebAssembly data segment which can be included as part of
|
||||
|
@ -71,7 +71,7 @@ protected:
|
|||
// each global variable.
|
||||
class InputSegment : public InputChunk {
|
||||
public:
|
||||
InputSegment(const WasmSegment &Seg, const ObjFile &F)
|
||||
InputSegment(const WasmSegment &Seg, const ObjFile *F)
|
||||
: InputChunk(F), Segment(Seg) {}
|
||||
|
||||
// Translate an offset in the input segment to an offset in the output
|
||||
|
@ -108,21 +108,18 @@ protected:
|
|||
// combined to create the final output CODE section.
|
||||
class InputFunction : public InputChunk {
|
||||
public:
|
||||
InputFunction(const WasmSignature &S, const WasmFunction &Func,
|
||||
const ObjFile &F)
|
||||
InputFunction(const WasmSignature &S, const WasmFunction *Func,
|
||||
const ObjFile *F)
|
||||
: InputChunk(F), Signature(S), WrittenToNameSec(false), Function(Func) {}
|
||||
|
||||
uint32_t getSize() const override { return Function.Size; }
|
||||
uint32_t getSize() const override { return Function->Size; }
|
||||
const uint8_t *getData() const override {
|
||||
return File.CodeSection->Content.data() + getInputSectionOffset();
|
||||
return File->CodeSection->Content.data() + getInputSectionOffset();
|
||||
}
|
||||
|
||||
uint32_t getOutputIndex() const { return OutputIndex.getValue(); };
|
||||
bool hasOutputIndex() const { return OutputIndex.hasValue(); };
|
||||
void setOutputIndex(uint32_t Index) {
|
||||
assert(!hasOutputIndex());
|
||||
OutputIndex = Index;
|
||||
};
|
||||
void setOutputIndex(uint32_t Index);
|
||||
|
||||
const WasmSignature &Signature;
|
||||
|
||||
|
@ -130,12 +127,26 @@ public:
|
|||
|
||||
protected:
|
||||
uint32_t getInputSectionOffset() const override {
|
||||
return Function.CodeSectionOffset;
|
||||
return Function->CodeSectionOffset;
|
||||
}
|
||||
const WasmFunction &Function;
|
||||
const WasmFunction *Function;
|
||||
llvm::Optional<uint32_t> OutputIndex;
|
||||
};
|
||||
|
||||
class SyntheticFunction : public InputFunction {
|
||||
public:
|
||||
SyntheticFunction(const WasmSignature &S, StringRef Body)
|
||||
: InputFunction(S, nullptr, nullptr), Body(Body) {}
|
||||
|
||||
uint32_t getSize() const override { return Body.size(); }
|
||||
const uint8_t *getData() const override {
|
||||
return reinterpret_cast<const uint8_t *>(Body.data());
|
||||
}
|
||||
|
||||
protected:
|
||||
StringRef Body;
|
||||
};
|
||||
|
||||
} // namespace wasm
|
||||
} // namespace lld
|
||||
|
||||
|
|
|
@ -188,7 +188,7 @@ void ObjFile::initializeSymbols() {
|
|||
GlobalSymbols.resize(NumGlobalImports + WasmObj->globals().size());
|
||||
|
||||
for (const WasmSegment &S : WasmObj->dataSegments()) {
|
||||
InputSegment *Seg = make<InputSegment>(S, *this);
|
||||
InputSegment *Seg = make<InputSegment>(S, this);
|
||||
Seg->copyRelocations(*DataSection);
|
||||
Segments.emplace_back(Seg);
|
||||
}
|
||||
|
@ -199,7 +199,7 @@ void ObjFile::initializeSymbols() {
|
|||
for (size_t I = 0; I < Funcs.size(); ++I) {
|
||||
const WasmFunction &Func = Funcs[I];
|
||||
const WasmSignature &Sig = Types[FuncTypes[I]];
|
||||
InputFunction *F = make<InputFunction>(Sig, Func, *this);
|
||||
InputFunction *F = make<InputFunction>(Sig, &Func, this);
|
||||
F->copyRelocations(*CodeSection);
|
||||
Functions.emplace_back(F);
|
||||
}
|
||||
|
@ -232,14 +232,10 @@ void ObjFile::initializeSymbols() {
|
|||
|
||||
Symbols.push_back(S);
|
||||
if (WasmSym.isFunction()) {
|
||||
DEBUG(dbgs() << "Function: " << WasmSym.ElementIndex << " -> "
|
||||
<< toString(*S) << "\n");
|
||||
FunctionSymbols[WasmSym.ElementIndex] = S;
|
||||
if (WasmSym.HasAltIndex)
|
||||
FunctionSymbols[WasmSym.AltIndex] = S;
|
||||
} else {
|
||||
DEBUG(dbgs() << "Global: " << WasmSym.ElementIndex << " -> "
|
||||
<< toString(*S) << "\n");
|
||||
GlobalSymbols[WasmSym.ElementIndex] = S;
|
||||
if (WasmSym.HasAltIndex)
|
||||
GlobalSymbols[WasmSym.AltIndex] = S;
|
||||
|
|
|
@ -119,6 +119,22 @@ static void checkSymbolTypes(const Symbol &Existing, const InputFile &F,
|
|||
" in " + F.getName());
|
||||
}
|
||||
|
||||
Symbol *SymbolTable::addDefinedFunction(StringRef Name,
|
||||
const WasmSignature *Type,
|
||||
uint32_t Flags) {
|
||||
DEBUG(dbgs() << "addDefinedFunction: " << Name << "\n");
|
||||
Symbol *S;
|
||||
bool WasInserted;
|
||||
std::tie(S, WasInserted) = insert(Name);
|
||||
if (WasInserted) {
|
||||
S->update(Symbol::DefinedFunctionKind, nullptr, Flags);
|
||||
S->setFunctionType(Type);
|
||||
} else if (!S->isFunction()) {
|
||||
error("symbol type mismatch: " + Name);
|
||||
}
|
||||
return S;
|
||||
}
|
||||
|
||||
Symbol *SymbolTable::addDefinedGlobal(StringRef Name) {
|
||||
DEBUG(dbgs() << "addDefinedGlobal: " << Name << "\n");
|
||||
Symbol *S;
|
||||
|
|
|
@ -55,6 +55,8 @@ public:
|
|||
InputFile *F, const WasmSignature *Signature = nullptr);
|
||||
Symbol *addUndefinedFunction(StringRef Name, const WasmSignature *Type);
|
||||
Symbol *addDefinedGlobal(StringRef Name);
|
||||
Symbol *addDefinedFunction(StringRef Name, const WasmSignature *Type,
|
||||
uint32_t Flags);
|
||||
void addLazy(ArchiveFile *F, const Archive::Symbol *Sym);
|
||||
|
||||
private:
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#include "Writer.h"
|
||||
|
||||
#include "llvm/ADT/DenseSet.h"
|
||||
#include "Config.h"
|
||||
#include "InputChunks.h"
|
||||
#include "OutputSections.h"
|
||||
|
@ -70,6 +71,8 @@ private:
|
|||
|
||||
uint32_t lookupType(const WasmSignature &Sig);
|
||||
uint32_t registerType(const WasmSignature &Sig);
|
||||
void createCtorFunction();
|
||||
void calculateInitFunctions();
|
||||
void assignIndexes();
|
||||
void calculateImports();
|
||||
void calculateOffsets();
|
||||
|
@ -114,12 +117,15 @@ private:
|
|||
std::vector<const Symbol *> DefinedGlobals;
|
||||
std::vector<InputFunction *> DefinedFunctions;
|
||||
std::vector<const Symbol *> IndirectFunctions;
|
||||
std::vector<WasmInitFunc> InitFunctions;
|
||||
|
||||
// Elements that are used to construct the final output
|
||||
std::string Header;
|
||||
std::vector<OutputSection *> OutputSections;
|
||||
|
||||
std::unique_ptr<FileOutputBuffer> Buffer;
|
||||
std::unique_ptr<SyntheticFunction> CtorFunction;
|
||||
std::string CtorFunctionBody;
|
||||
|
||||
std::vector<OutputSegment *> Segments;
|
||||
llvm::SmallDenseMap<StringRef, OutputSegment *> SegmentMap;
|
||||
|
@ -410,15 +416,6 @@ void Writer::createLinkingSection() {
|
|||
SubSection.writeToStream(OS);
|
||||
}
|
||||
|
||||
std::vector<WasmInitFunc> InitFunctions;
|
||||
for (ObjFile *File : Symtab->ObjectFiles) {
|
||||
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)});
|
||||
}
|
||||
|
||||
if (!InitFunctions.empty()) {
|
||||
SubSection SubSection(WASM_INIT_FUNCS);
|
||||
writeUleb128(SubSection.getStream(), InitFunctions.size(),
|
||||
|
@ -437,25 +434,40 @@ void Writer::createNameSection() {
|
|||
// Create an array of all function sorted by function index space
|
||||
std::vector<const Symbol *> Names;
|
||||
|
||||
auto AddToNames = [&](Symbol* S) {
|
||||
if (!S->isFunction() || S->WrittenToNameSec)
|
||||
return;
|
||||
// We also need to guard against two different symbols (two different
|
||||
// names) for the same wasm function. While this is possible (aliases)
|
||||
// it is not legal in the "name" section.
|
||||
InputFunction *Function = S->getFunction();
|
||||
if (Function) {
|
||||
if (Function->WrittenToNameSec)
|
||||
return;
|
||||
Function->WrittenToNameSec = true;
|
||||
}
|
||||
S->WrittenToNameSec = true;
|
||||
Names.emplace_back(S);
|
||||
};
|
||||
|
||||
for (ObjFile *File : Symtab->ObjectFiles) {
|
||||
Names.reserve(Names.size() + File->getSymbols().size());
|
||||
DEBUG(dbgs() << "adding names from: " << File->getName() << "\n");
|
||||
for (Symbol *S : File->getSymbols()) {
|
||||
if (!S->isFunction() || S->isWeak() || S->WrittenToNameSec)
|
||||
if (S->isWeak())
|
||||
continue;
|
||||
// We also need to guard against two different symbols (two different
|
||||
// names) for the same wasm function. While this is possible (aliases)
|
||||
// it is not legal in the "name" section.
|
||||
InputFunction *Function = S->getFunction();
|
||||
if (Function) {
|
||||
if (Function->WrittenToNameSec)
|
||||
continue;
|
||||
Function->WrittenToNameSec = true;
|
||||
}
|
||||
S->WrittenToNameSec = true;
|
||||
Names.emplace_back(S);
|
||||
AddToNames(S);
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG(dbgs() << "adding symtab names\n");
|
||||
for (Symbol *S : Symtab->getSymbols()) {
|
||||
DEBUG(dbgs() << "sym: " << S->getName() << "\n");
|
||||
if (S->getFile())
|
||||
continue;
|
||||
AddToNames(S);
|
||||
}
|
||||
|
||||
SyntheticSection *Section = createSyntheticSection(WASM_SEC_CUSTOM, "name");
|
||||
|
||||
std::sort(Names.begin(), Names.end(), [](const Symbol *A, const Symbol *B) {
|
||||
|
@ -603,11 +615,15 @@ void Writer::calculateTypes() {
|
|||
for (const WasmSignature &Sig : File->getWasmObj()->types())
|
||||
File->TypeMap.push_back(registerType(Sig));
|
||||
}
|
||||
|
||||
for (Symbol *Sym : Symtab->getSymbols())
|
||||
if (Sym->isFunction())
|
||||
registerType(Sym->getFunctionType());
|
||||
}
|
||||
|
||||
void Writer::assignIndexes() {
|
||||
uint32_t GlobalIndex = ImportedGlobals.size();
|
||||
uint32_t FunctionIndex = ImportedFunctions.size();
|
||||
uint32_t GlobalIndex = ImportedGlobals.size() + DefinedGlobals.size();
|
||||
uint32_t FunctionIndex = ImportedFunctions.size() + DefinedFunctions.size();
|
||||
|
||||
if (Config->StackPointerSymbol) {
|
||||
DefinedGlobals.emplace_back(Config->StackPointerSymbol);
|
||||
|
@ -686,6 +702,57 @@ void Writer::createOutputSegments() {
|
|||
}
|
||||
}
|
||||
|
||||
static const int OPCODE_CALL = 0x10;
|
||||
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() + DefinedFunctions.size();
|
||||
Config->CtorSymbol->setOutputIndex(FunctionIndex);
|
||||
|
||||
// First write the body bytes to a string.
|
||||
std::string FunctionBody;
|
||||
static WasmSignature Signature = {{}, WASM_TYPE_NORESULT};
|
||||
{
|
||||
raw_string_ostream OS(FunctionBody);
|
||||
writeUleb128(OS, 0, "num locals");
|
||||
for (const WasmInitFunc &F : InitFunctions) {
|
||||
writeU8(OS, OPCODE_CALL, "CALL");
|
||||
writeUleb128(OS, F.FunctionIndex, "function index");
|
||||
}
|
||||
writeU8(OS, OPCODE_END, "END");
|
||||
}
|
||||
|
||||
// Once we know the size of the body we can create the final function body
|
||||
raw_string_ostream OS(CtorFunctionBody);
|
||||
writeUleb128(OS, FunctionBody.size(), "function size");
|
||||
OS.flush();
|
||||
CtorFunctionBody += FunctionBody;
|
||||
CtorFunction =
|
||||
llvm::make_unique<SyntheticFunction>(Signature, CtorFunctionBody);
|
||||
DefinedFunctions.emplace_back(CtorFunction.get());
|
||||
}
|
||||
|
||||
// Populate InitFunctions vector with init functions from all input objects.
|
||||
// This is then used either when creating the output linking section or to
|
||||
// synthesize the "__wasm_call_ctors" function.
|
||||
void Writer::calculateInitFunctions() {
|
||||
for (ObjFile *File : Symtab->ObjectFiles) {
|
||||
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)});
|
||||
}
|
||||
// Sort in order of priority (lowest first) so that they are called
|
||||
// in the correct order.
|
||||
std::sort(InitFunctions.begin(), InitFunctions.end(),
|
||||
[](const WasmInitFunc &L, const WasmInitFunc &R) {
|
||||
return L.Priority < R.Priority;
|
||||
});
|
||||
}
|
||||
|
||||
void Writer::run() {
|
||||
if (!Config->Relocatable)
|
||||
InitialTableOffset = 1;
|
||||
|
@ -696,6 +763,10 @@ void Writer::run() {
|
|||
calculateImports();
|
||||
log("-- assignIndexes");
|
||||
assignIndexes();
|
||||
log("-- calculateInitFunctions");
|
||||
calculateInitFunctions();
|
||||
if (!Config->Relocatable)
|
||||
createCtorFunction();
|
||||
|
||||
if (errorHandler().Verbose) {
|
||||
log("Defined Functions: " + Twine(DefinedFunctions.size()));
|
||||
|
|
Loading…
Reference in New Issue