[lld] r322388 - [WebAssembly] Create synthetic __wasm_call_ctors function

Sam Clegg via llvm-commits llvm-commits at lists.llvm.org
Fri Jan 12 10:35:13 PST 2018


Author: sbc
Date: Fri Jan 12 10:35:13 2018
New Revision: 322388

URL: http://llvm.org/viewvc/llvm-project?rev=322388&view=rev
Log:
[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

Modified:
    lld/trunk/test/wasm/Inputs/global-ctor-dtor.ll
    lld/trunk/test/wasm/alias.ll
    lld/trunk/test/wasm/call-indirect.ll
    lld/trunk/test/wasm/function-imports-first.ll
    lld/trunk/test/wasm/function-imports.ll
    lld/trunk/test/wasm/init-fini.ll
    lld/trunk/test/wasm/local-symbols.ll
    lld/trunk/test/wasm/stack-pointer.ll
    lld/trunk/test/wasm/weak-alias-overide.ll
    lld/trunk/test/wasm/weak-alias.ll
    lld/trunk/test/wasm/weak-symbols.ll
    lld/trunk/test/wasm/weak-undefined.ll
    lld/trunk/wasm/Config.h
    lld/trunk/wasm/Driver.cpp
    lld/trunk/wasm/InputChunks.cpp
    lld/trunk/wasm/InputChunks.h
    lld/trunk/wasm/InputFiles.cpp
    lld/trunk/wasm/SymbolTable.cpp
    lld/trunk/wasm/SymbolTable.h
    lld/trunk/wasm/Writer.cpp

Modified: lld/trunk/test/wasm/Inputs/global-ctor-dtor.ll
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/Inputs/global-ctor-dtor.ll?rev=322388&r1=322387&r2=322388&view=diff
==============================================================================
--- lld/trunk/test/wasm/Inputs/global-ctor-dtor.ll (original)
+++ lld/trunk/test/wasm/Inputs/global-ctor-dtor.ll Fri Jan 12 10:35:13 2018
@@ -9,6 +9,14 @@ entry:
   ret void
 }
 
- at llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @myctor, i8* null }]
+ at 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 }
+]
 
- at llvm.global_dtors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @mydtor, i8* null }]
+ at 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 }
+]

Modified: lld/trunk/test/wasm/alias.ll
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/alias.ll?rev=322388&r1=322387&r2=322388&view=diff
==============================================================================
--- lld/trunk/test/wasm/alias.ll (original)
+++ lld/trunk/test/wasm/alias.ll Fri Jan 12 10:35:13 2018
@@ -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: ...

Modified: lld/trunk/test/wasm/call-indirect.ll
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/call-indirect.ll?rev=322388&r1=322387&r2=322388&view=diff
==============================================================================
--- lld/trunk/test/wasm/call-indirect.ll (original)
+++ lld/trunk/test/wasm/call-indirect.ll Fri Jan 12 10:35:13 2018
@@ -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

Modified: lld/trunk/test/wasm/function-imports-first.ll
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/function-imports-first.ll?rev=322388&r1=322387&r2=322388&view=diff
==============================================================================
--- lld/trunk/test/wasm/function-imports-first.ll (original)
+++ lld/trunk/test/wasm/function-imports-first.ll Fri Jan 12 10:35:13 2018
@@ -22,7 +22,7 @@ declare i32 @ret32(float) local_unnamed_
 ; 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_
 ; 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_
 ; CHECK-NEXT:         Name:            _start
 ; CHECK-NEXT:       - Index:           1
 ; CHECK-NEXT:         Name:            ret32
+; CHECK-NEXT:       - Index:           2
+; CHECK-NEXT:         Name:            __wasm_call_ctors
 ; CHECK-NEXT: ...

Modified: lld/trunk/test/wasm/function-imports.ll
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/function-imports.ll?rev=322388&r1=322387&r2=322388&view=diff
==============================================================================
--- lld/trunk/test/wasm/function-imports.ll (original)
+++ lld/trunk/test/wasm/function-imports.ll Fri Jan 12 10:35:13 2018
@@ -23,15 +23,18 @@ declare i32 @ret32(float) local_unnamed_
 ; 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: ...

Modified: lld/trunk/test/wasm/init-fini.ll
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/init-fini.ll?rev=322388&r1=322387&r2=322388&view=diff
==============================================================================
--- lld/trunk/test/wasm/init-fini.ll (original)
+++ lld/trunk/test/wasm/init-fini.ll Fri Jan 12 10:35:13 2018
@@ -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
 }
 
- at llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @func1, i8* null }]
-
- at llvm.global_dtors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @func2, i8* null }]
+ at 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 }
+]
+
+ at 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: ...

Modified: lld/trunk/test/wasm/local-symbols.ll
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/local-symbols.ll?rev=322388&r1=322387&r2=322388&view=diff
==============================================================================
--- lld/trunk/test/wasm/local-symbols.ll (original)
+++ lld/trunk/test/wasm/local-symbols.ll Fri Jan 12 10:35:13 2018
@@ -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: ...

Modified: lld/trunk/test/wasm/stack-pointer.ll
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/stack-pointer.ll?rev=322388&r1=322387&r2=322388&view=diff
==============================================================================
--- lld/trunk/test/wasm/stack-pointer.ll (original)
+++ lld/trunk/test/wasm/stack-pointer.ll Fri Jan 12 10:35:13 2018
@@ -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: ...

Modified: lld/trunk/test/wasm/weak-alias-overide.ll
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/weak-alias-overide.ll?rev=322388&r1=322387&r2=322388&view=diff
==============================================================================
--- lld/trunk/test/wasm/weak-alias-overide.ll (original)
+++ lld/trunk/test/wasm/weak-alias-overide.ll Fri Jan 12 10:35:13 2018
@@ -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: ...

Modified: lld/trunk/test/wasm/weak-alias.ll
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/weak-alias.ll?rev=322388&r1=322387&r2=322388&view=diff
==============================================================================
--- lld/trunk/test/wasm/weak-alias.ll (original)
+++ lld/trunk/test/wasm/weak-alias.ll Fri Jan 12 10:35:13 2018
@@ -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: ...

Modified: lld/trunk/test/wasm/weak-symbols.ll
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/weak-symbols.ll?rev=322388&r1=322387&r2=322388&view=diff
==============================================================================
--- lld/trunk/test/wasm/weak-symbols.ll (original)
+++ lld/trunk/test/wasm/weak-symbols.ll Fri Jan 12 10:35:13 2018
@@ -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: ...

Modified: lld/trunk/test/wasm/weak-undefined.ll
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/weak-undefined.ll?rev=322388&r1=322387&r2=322388&view=diff
==============================================================================
--- lld/trunk/test/wasm/weak-undefined.ll (original)
+++ lld/trunk/test/wasm/weak-undefined.ll Fri Jan 12 10:35:13 2018
@@ -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

Modified: lld/trunk/wasm/Config.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/Config.h?rev=322388&r1=322387&r2=322388&view=diff
==============================================================================
--- lld/trunk/wasm/Config.h (original)
+++ lld/trunk/wasm/Config.h Fri Jan 12 10:35:13 2018
@@ -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.

Modified: lld/trunk/wasm/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/Driver.cpp?rev=322388&r1=322387&r2=322388&view=diff
==============================================================================
--- lld/trunk/wasm/Driver.cpp (original)
+++ lld/trunk/wasm/Driver.cpp Fri Jan 12 10:35:13 2018
@@ -291,15 +291,16 @@ void LinkerDriver::link(ArrayRef<const c
     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");
   }
 

Modified: lld/trunk/wasm/InputChunks.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/InputChunks.cpp?rev=322388&r1=322387&r2=322388&view=diff
==============================================================================
--- lld/trunk/wasm/InputChunks.cpp (original)
+++ lld/trunk/wasm/InputChunks.cpp Fri Jan 12 10:35:13 2018
@@ -30,6 +30,8 @@ uint32_t InputSegment::translateVA(uint3
 }
 
 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 *Sectio
 // 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;
+};

Modified: lld/trunk/wasm/InputChunks.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/InputChunks.h?rev=322388&r1=322387&r2=322388&view=diff
==============================================================================
--- lld/trunk/wasm/InputChunks.h (original)
+++ lld/trunk/wasm/InputChunks.h Fri Jan 12 10:35:13 2018
@@ -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
 

Modified: lld/trunk/wasm/InputFiles.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/InputFiles.cpp?rev=322388&r1=322387&r2=322388&view=diff
==============================================================================
--- lld/trunk/wasm/InputFiles.cpp (original)
+++ lld/trunk/wasm/InputFiles.cpp Fri Jan 12 10:35:13 2018
@@ -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;

Modified: lld/trunk/wasm/SymbolTable.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/SymbolTable.cpp?rev=322388&r1=322387&r2=322388&view=diff
==============================================================================
--- lld/trunk/wasm/SymbolTable.cpp (original)
+++ lld/trunk/wasm/SymbolTable.cpp Fri Jan 12 10:35:13 2018
@@ -119,6 +119,22 @@ static void checkSymbolTypes(const Symbo
         " 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;

Modified: lld/trunk/wasm/SymbolTable.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/SymbolTable.h?rev=322388&r1=322387&r2=322388&view=diff
==============================================================================
--- lld/trunk/wasm/SymbolTable.h (original)
+++ lld/trunk/wasm/SymbolTable.h Fri Jan 12 10:35:13 2018
@@ -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:

Modified: lld/trunk/wasm/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/Writer.cpp?rev=322388&r1=322387&r2=322388&view=diff
==============================================================================
--- lld/trunk/wasm/Writer.cpp (original)
+++ lld/trunk/wasm/Writer.cpp Fri Jan 12 10:35:13 2018
@@ -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()));




More information about the llvm-commits mailing list