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

Sam Clegg via llvm-commits llvm-commits at lists.llvm.org
Thu Jan 18 15:40:49 PST 2018


Author: sbc
Date: Thu Jan 18 15:40:49 2018
New Revision: 322908

URL: http://llvm.org/viewvc/llvm-project?rev=322908&view=rev
Log:
[WebAssembly] Add missing function exports and SYM_INFO to --relocatable output

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

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

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

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

Patch by Nicholas Wilson!

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

Added:
    lld/trunk/test/wasm/Inputs/locals-duplicate1.ll
    lld/trunk/test/wasm/Inputs/locals-duplicate2.ll
    lld/trunk/test/wasm/locals-duplicate.test
Modified:
    lld/trunk/test/wasm/call-indirect.ll
    lld/trunk/test/wasm/init-fini.ll
    lld/trunk/test/wasm/relocatable.ll
    lld/trunk/test/wasm/visibility-hidden.ll
    lld/trunk/wasm/Writer.cpp

Added: lld/trunk/test/wasm/Inputs/locals-duplicate1.ll
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/Inputs/locals-duplicate1.ll?rev=322908&view=auto
==============================================================================
--- lld/trunk/test/wasm/Inputs/locals-duplicate1.ll (added)
+++ lld/trunk/test/wasm/Inputs/locals-duplicate1.ll Thu Jan 18 15:40:49 2018
@@ -0,0 +1,49 @@
+; Will collide: local (internal linkage) with global (external) linkage
+ at colliding_global1 = internal default global i32 0, align 4
+; Will collide: global with local
+ at colliding_global2 = default global i32 0, align 4
+; Will collide: local with local
+ at colliding_global3 = internal default global i32 0, align 4
+
+; Will collide: local with global
+define internal i32 @colliding_func1() {
+entry:
+  ret i32 2
+}
+; Will collide: global with local
+define i32 @colliding_func2() {
+entry:
+  ret i32 2
+}
+; Will collide: local with local
+define internal i32 @colliding_func3() {
+entry:
+  ret i32 2
+}
+
+
+define i32* @get_global1A() {
+entry:
+  ret i32* @colliding_global1
+}
+define i32* @get_global2A() {
+entry:
+  ret i32* @colliding_global2
+}
+define i32* @get_global3A() {
+entry:
+  ret i32* @colliding_global3
+}
+
+define i32 ()* @get_func1A() {
+entry:
+  ret i32 ()* @colliding_func1
+}
+define i32 ()* @get_func2A() {
+entry:
+  ret i32 ()* @colliding_func2
+}
+define i32 ()* @get_func3A() {
+entry:
+  ret i32 ()* @colliding_func3
+}

Added: lld/trunk/test/wasm/Inputs/locals-duplicate2.ll
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/Inputs/locals-duplicate2.ll?rev=322908&view=auto
==============================================================================
--- lld/trunk/test/wasm/Inputs/locals-duplicate2.ll (added)
+++ lld/trunk/test/wasm/Inputs/locals-duplicate2.ll Thu Jan 18 15:40:49 2018
@@ -0,0 +1,49 @@
+; Will collide: local (internal linkage) with global (external) linkage
+ at colliding_global1 = default global i32 0, align 4
+; Will collide: global with local
+ at colliding_global2 = internal default global i32 0, align 4
+; Will collide: local with local
+ at colliding_global3 = internal default global i32 0, align 4
+
+; Will collide: local with global
+define i32 @colliding_func1() {
+entry:
+  ret i32 2
+}
+; Will collide: global with local
+define internal i32 @colliding_func2() {
+entry:
+  ret i32 2
+}
+; Will collide: local with local
+define internal i32 @colliding_func3() {
+entry:
+  ret i32 2
+}
+
+
+define i32* @get_global1B() {
+entry:
+  ret i32* @colliding_global1
+}
+define i32* @get_global2B() {
+entry:
+  ret i32* @colliding_global2
+}
+define i32* @get_global3B() {
+entry:
+  ret i32* @colliding_global3
+}
+
+define i32 ()* @get_func1B() {
+entry:
+  ret i32 ()* @colliding_func1
+}
+define i32 ()* @get_func2B() {
+entry:
+  ret i32 ()* @colliding_func2
+}
+define i32 ()* @get_func3B() {
+entry:
+  ret i32 ()* @colliding_func3
+}

Modified: lld/trunk/test/wasm/call-indirect.ll
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/call-indirect.ll?rev=322908&r1=322907&r2=322908&view=diff
==============================================================================
--- lld/trunk/test/wasm/call-indirect.ll (original)
+++ lld/trunk/test/wasm/call-indirect.ll Thu Jan 18 15:40:49 2018
@@ -85,15 +85,15 @@ define void @call_ptr(i64 (i64)* %arg) {
 ; CHECK-NEXT:       - Name:            _start
 ; CHECK-NEXT:         Kind:            FUNCTION
 ; CHECK-NEXT:         Index:           3
-; CHECK-NEXT:       - Name:            foo
-; CHECK-NEXT:         Kind:            FUNCTION
-; CHECK-NEXT:         Index:           2
 ; CHECK-NEXT:       - Name:            bar
 ; CHECK-NEXT:         Kind:            FUNCTION
 ; CHECK-NEXT:         Index:           0
 ; CHECK-NEXT:       - Name:            call_bar_indirect
 ; CHECK-NEXT:         Kind:            FUNCTION
 ; CHECK-NEXT:         Index:           1
+; CHECK-NEXT:       - Name:            foo
+; CHECK-NEXT:         Kind:            FUNCTION
+; CHECK-NEXT:         Index:           2
 ; CHECK-NEXT:       - Name:            call_ptr
 ; CHECK-NEXT:         Kind:            FUNCTION
 ; CHECK-NEXT:         Index:           4

Modified: lld/trunk/test/wasm/init-fini.ll
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/init-fini.ll?rev=322908&r1=322907&r2=322908&view=diff
==============================================================================
--- lld/trunk/test/wasm/init-fini.ll (original)
+++ lld/trunk/test/wasm/init-fini.ll Thu Jan 18 15:40:49 2018
@@ -107,7 +107,44 @@ entry:
 
 ; RELOC:          Name:            linking
 ; RELOC-NEXT:     DataSize:        0
-; RELOC-NEXT:     InitFunctions:   
+; RELOC-NEXT:     SymbolInfo:      
+; RELOC-NEXT:       - Name:            func1
+; RELOC-NEXT:         Flags:           [ VISIBILITY_HIDDEN ]
+; RELOC-NEXT:       - Name:            func2
+; RELOC-NEXT:         Flags:           [ VISIBILITY_HIDDEN ]
+; RELOC-NEXT:       - Name:            func3
+; RELOC-NEXT:         Flags:           [ VISIBILITY_HIDDEN ]
+; RELOC-NEXT:       - Name:            func4
+; RELOC-NEXT:         Flags:           [ VISIBILITY_HIDDEN ]
+; RELOC-NEXT:       - Name:            _start
+; RELOC-NEXT:         Flags:           [ VISIBILITY_HIDDEN ]
+; RELOC-NEXT:       - Name:            .Lcall_dtors.101
+; RELOC-NEXT:         Flags:           [ BINDING_LOCAL ]
+; RELOC-NEXT:       - Name:            .Lregister_call_dtors.101
+; RELOC-NEXT:         Flags:           [ BINDING_LOCAL ]
+; RELOC-NEXT:       - Name:            .Lbitcast
+; RELOC-NEXT:         Flags:           [ BINDING_LOCAL ]
+; RELOC-NEXT:       - Name:            .Lcall_dtors.1001
+; RELOC-NEXT:         Flags:           [ BINDING_LOCAL ]
+; RELOC-NEXT:       - Name:            .Lregister_call_dtors.1001
+; RELOC-NEXT:         Flags:           [ BINDING_LOCAL ]
+; RELOC-NEXT:       - Name:            myctor
+; RELOC-NEXT:         Flags:           [ VISIBILITY_HIDDEN ]
+; RELOC-NEXT:       - Name:            mydtor
+; RELOC-NEXT:         Flags:           [ VISIBILITY_HIDDEN ]
+; RELOC-NEXT:       - Name:            .Lcall_dtors.101.1
+; RELOC-NEXT:         Flags:           [ BINDING_LOCAL ]
+; RELOC-NEXT:       - Name:            .Lregister_call_dtors.101.1
+; RELOC-NEXT:         Flags:           [ BINDING_LOCAL ]
+; RELOC-NEXT:       - Name:            .Lcall_dtors.202
+; RELOC-NEXT:         Flags:           [ BINDING_LOCAL ]
+; RELOC-NEXT:       - Name:            .Lregister_call_dtors.202
+; RELOC-NEXT:         Flags:           [ BINDING_LOCAL ]
+; RELOC-NEXT:       - Name:            .Lcall_dtors.2002
+; RELOC-NEXT:         Flags:           [ BINDING_LOCAL ]
+; RELOC-NEXT:       - Name:            .Lregister_call_dtors.2002
+; RELOC-NEXT:         Flags:           [ BINDING_LOCAL ]
+; RELOC-NEXT:     InitFunctions:
 ; RELOC-NEXT:       - Priority:        101
 ; RELOC-NEXT:         FunctionIndex:   0
 ; RELOC-NEXT:       - Priority:        101

Added: lld/trunk/test/wasm/locals-duplicate.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/locals-duplicate.test?rev=322908&view=auto
==============================================================================
--- lld/trunk/test/wasm/locals-duplicate.test (added)
+++ lld/trunk/test/wasm/locals-duplicate.test Thu Jan 18 15:40:49 2018
@@ -0,0 +1,543 @@
+; RUN: llc -filetype=obj -mtriple=wasm32-unknown-unknown-wasm %p/Inputs/locals-duplicate1.ll -o %t1.o
+; RUN: llc -filetype=obj -mtriple=wasm32-unknown-unknown-wasm %p/Inputs/locals-duplicate2.ll -o %t2.o
+; RUN: lld -flavor wasm --no-entry -o %t.wasm %t1.o %t2.o
+; RUN: obj2yaml %t.wasm | FileCheck %s
+
+; CHECK:      --- !WASM
+; CHECK-NEXT: FileHeader:      
+; CHECK-NEXT:   Version:         0x00000001
+; CHECK-NEXT: Sections:        
+; CHECK-NEXT:   - Type:            TYPE
+; CHECK-NEXT:     Signatures:      
+; CHECK-NEXT:       - Index:           0
+; CHECK-NEXT:         ReturnType:      I32
+; CHECK-NEXT:         ParamTypes:      
+; CHECK-NEXT:       - Index:           1
+; CHECK-NEXT:         ReturnType:      NORESULT
+; CHECK-NEXT:         ParamTypes:      
+; CHECK-NEXT:   - Type:            FUNCTION
+; CHECK-NEXT:     FunctionTypes:   [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+; CHECK-NEXT:                        0, 0, 1 ]
+; CHECK-NEXT:   - Type:            TABLE
+; CHECK-NEXT:     Tables:          
+; CHECK-NEXT:       - ElemType:        ANYFUNC
+; CHECK-NEXT:         Limits:          
+; CHECK-NEXT:           Flags:           [ HAS_MAX ]
+; CHECK-NEXT:           Initial:         0x00000007
+; CHECK-NEXT:           Maximum:         0x00000007
+; CHECK-NEXT:   - Type:            MEMORY
+; CHECK-NEXT:     Memories:        
+; CHECK-NEXT:       - Initial:         0x00000002
+; CHECK-NEXT:   - Type:            GLOBAL
+; CHECK-NEXT:     Globals:         
+; CHECK-NEXT:       - Index:           0
+; CHECK-NEXT:         Type:            I32
+; CHECK-NEXT:         Mutable:         true
+; CHECK-NEXT:         InitExpr:        
+; CHECK-NEXT:           Opcode:          I32_CONST
+; CHECK-NEXT:           Value:           66592
+; CHECK-NEXT:       - Index:           1
+; CHECK-NEXT:         Type:            I32
+; CHECK-NEXT:         Mutable:         false
+; CHECK-NEXT:         InitExpr:
+; CHECK-NEXT:           Opcode:          I32_CONST
+; CHECK-NEXT:           Value:           66592
+; CHECK-NEXT:   - Type:            EXPORT
+; CHECK-NEXT:     Exports:         
+; CHECK-NEXT:       - Name:            memory
+; CHECK-NEXT:         Kind:            MEMORY
+; CHECK-NEXT:         Index:           0
+; CHECK-NEXT:       - Name:            colliding_func2
+; CHECK-NEXT:         Kind:            FUNCTION
+; CHECK-NEXT:         Index:           1
+; CHECK-NEXT:       - Name:            get_global1A
+; CHECK-NEXT:         Kind:            FUNCTION
+; CHECK-NEXT:         Index:           3
+; CHECK-NEXT:       - Name:            get_global2A
+; CHECK-NEXT:         Kind:            FUNCTION
+; CHECK-NEXT:         Index:           4
+; CHECK-NEXT:       - Name:            get_global3A
+; CHECK-NEXT:         Kind:            FUNCTION
+; CHECK-NEXT:         Index:           5
+; CHECK-NEXT:       - Name:            get_func1A
+; CHECK-NEXT:         Kind:            FUNCTION
+; CHECK-NEXT:         Index:           6
+; CHECK-NEXT:       - Name:            get_func2A
+; CHECK-NEXT:         Kind:            FUNCTION
+; CHECK-NEXT:         Index:           7
+; CHECK-NEXT:       - Name:            get_func3A
+; CHECK-NEXT:         Kind:            FUNCTION
+; CHECK-NEXT:         Index:           8
+; CHECK-NEXT:       - Name:            colliding_func1
+; CHECK-NEXT:         Kind:            FUNCTION
+; CHECK-NEXT:         Index:           9
+; CHECK-NEXT:       - Name:            get_global1B
+; CHECK-NEXT:         Kind:            FUNCTION
+; CHECK-NEXT:         Index:           12
+; CHECK-NEXT:       - Name:            get_global2B
+; CHECK-NEXT:         Kind:            FUNCTION
+; CHECK-NEXT:         Index:           13
+; CHECK-NEXT:       - Name:            get_global3B
+; CHECK-NEXT:         Kind:            FUNCTION
+; CHECK-NEXT:         Index:           14
+; CHECK-NEXT:       - Name:            get_func1B
+; CHECK-NEXT:         Kind:            FUNCTION
+; CHECK-NEXT:         Index:           15
+; CHECK-NEXT:       - Name:            get_func2B
+; CHECK-NEXT:         Kind:            FUNCTION
+; CHECK-NEXT:         Index:           16
+; CHECK-NEXT:       - Name:            get_func3B
+; CHECK-NEXT:         Kind:            FUNCTION
+; CHECK-NEXT:         Index:           17
+; CHECK-NEXT:       - Name:            __heap_base
+; CHECK-NEXT:         Kind:            GLOBAL
+; CHECK-NEXT:         Index:           1
+; CHECK-NEXT:   - Type:            ELEM
+; CHECK-NEXT:     Segments:        
+; CHECK-NEXT:       - Offset:          
+; CHECK-NEXT:           Opcode:          I32_CONST
+; CHECK-NEXT:           Value:           1
+; CHECK-NEXT:         Functions:       [ 0, 1, 2, 9, 10, 11 ]
+; CHECK-NEXT:   - Type:            CODE
+; CHECK-NEXT:     Functions:       
+; CHECK-NEXT:       - Index:           0
+; CHECK-NEXT:         Locals:          
+; CHECK-NEXT:         Body:            41020B
+; CHECK-NEXT:       - Index:           1
+; CHECK-NEXT:         Locals:          
+; CHECK-NEXT:         Body:            41020B
+; CHECK-NEXT:       - Index:           2
+; CHECK-NEXT:         Locals:          
+; CHECK-NEXT:         Body:            41020B
+; CHECK-NEXT:       - Index:           3
+; CHECK-NEXT:         Locals:          
+; CHECK-NEXT:         Body:            4180888080000B
+; CHECK-NEXT:       - Index:           4
+; CHECK-NEXT:         Locals:          
+; CHECK-NEXT:         Body:            4184888080000B
+; CHECK-NEXT:       - Index:           5
+; CHECK-NEXT:         Locals:          
+; CHECK-NEXT:         Body:            4188888080000B
+; CHECK-NEXT:       - Index:           6
+; CHECK-NEXT:         Locals:          
+; CHECK-NEXT:         Body:            4181808080000B
+; CHECK-NEXT:       - Index:           7
+; CHECK-NEXT:         Locals:          
+; CHECK-NEXT:         Body:            4182808080000B
+; CHECK-NEXT:       - Index:           8
+; CHECK-NEXT:         Locals:          
+; CHECK-NEXT:         Body:            4183808080000B
+; CHECK-NEXT:       - Index:           9
+; CHECK-NEXT:         Locals:          
+; CHECK-NEXT:         Body:            41020B
+; CHECK-NEXT:       - Index:           10
+; CHECK-NEXT:         Locals:          
+; CHECK-NEXT:         Body:            41020B
+; CHECK-NEXT:       - Index:           11
+; CHECK-NEXT:         Locals:          
+; CHECK-NEXT:         Body:            41020B
+; CHECK-NEXT:       - Index:           12
+; CHECK-NEXT:         Locals:          
+; CHECK-NEXT:         Body:            418C888080000B
+; CHECK-NEXT:       - Index:           13
+; CHECK-NEXT:         Locals:          
+; CHECK-NEXT:         Body:            4190888080000B
+; CHECK-NEXT:       - Index:           14
+; CHECK-NEXT:         Locals:          
+; CHECK-NEXT:         Body:            4194888080000B
+; CHECK-NEXT:       - Index:           15
+; CHECK-NEXT:         Locals:          
+; CHECK-NEXT:         Body:            4184808080000B
+; CHECK-NEXT:       - Index:           16
+; CHECK-NEXT:         Locals:          
+; CHECK-NEXT:         Body:            4185808080000B
+; CHECK-NEXT:       - Index:           17
+; CHECK-NEXT:         Locals:          
+; CHECK-NEXT:         Body:            4186808080000B
+; CHECK-NEXT:       - Index:           18
+; CHECK-NEXT:         Locals:          
+; CHECK-NEXT:         Body:            0B
+; CHECK-NEXT:   - Type:            DATA
+; CHECK-NEXT:     Segments:        
+; CHECK-NEXT:       - SectionOffset:   7
+; CHECK-NEXT:         MemoryIndex:     0
+; CHECK-NEXT:         Offset:          
+; CHECK-NEXT:           Opcode:          I32_CONST
+; CHECK-NEXT:           Value:           1024
+; CHECK-NEXT:         Content:         '000000000000000000000000000000000000000000000000'
+; CHECK-NEXT:   - Type:            CUSTOM
+; CHECK-NEXT:     Name:            linking
+; CHECK-NEXT:     DataSize:        24
+; CHECK-NEXT:   - Type:            CUSTOM
+; CHECK-NEXT:     Name:            name
+; CHECK-NEXT:     FunctionNames:   
+; CHECK-NEXT:       - Index:           0
+; CHECK-NEXT:         Name:            colliding_func1
+; CHECK-NEXT:       - Index:           1
+; CHECK-NEXT:         Name:            colliding_func2
+; CHECK-NEXT:       - Index:           2
+; CHECK-NEXT:         Name:            colliding_func3
+; CHECK-NEXT:       - Index:           3
+; CHECK-NEXT:         Name:            get_global1A
+; CHECK-NEXT:       - Index:           4
+; CHECK-NEXT:         Name:            get_global2A
+; CHECK-NEXT:       - Index:           5
+; CHECK-NEXT:         Name:            get_global3A
+; CHECK-NEXT:       - Index:           6
+; CHECK-NEXT:         Name:            get_func1A
+; CHECK-NEXT:       - Index:           7
+; CHECK-NEXT:         Name:            get_func2A
+; CHECK-NEXT:       - Index:           8
+; CHECK-NEXT:         Name:            get_func3A
+; CHECK-NEXT:       - Index:           9
+; CHECK-NEXT:         Name:            colliding_func1
+; CHECK-NEXT:       - Index:           10
+; CHECK-NEXT:         Name:            colliding_func2
+; CHECK-NEXT:       - Index:           11
+; CHECK-NEXT:         Name:            colliding_func3
+; CHECK-NEXT:       - Index:           12
+; CHECK-NEXT:         Name:            get_global1B
+; CHECK-NEXT:       - Index:           13
+; CHECK-NEXT:         Name:            get_global2B
+; CHECK-NEXT:       - Index:           14
+; CHECK-NEXT:         Name:            get_global3B
+; CHECK-NEXT:       - Index:           15
+; CHECK-NEXT:         Name:            get_func1B
+; CHECK-NEXT:       - Index:           16
+; CHECK-NEXT:         Name:            get_func2B
+; CHECK-NEXT:       - Index:           17
+; CHECK-NEXT:         Name:            get_func3B
+; CHECK-NEXT:       - Index:           18
+; CHECK-NEXT:         Name:            __wasm_call_ctors
+; CHECK-NEXT: ...
+
+
+; RUN: lld -flavor wasm -r --no-entry -o %t.reloc.wasm %t1.o %t2.o
+; RUN: obj2yaml %t.reloc.wasm | FileCheck -check-prefix=RELOC %s
+
+; RELOC:      --- !WASM
+; RELOC-NEXT: FileHeader:      
+; RELOC-NEXT:   Version:         0x00000001
+; RELOC-NEXT: Sections:        
+; RELOC-NEXT:   - Type:            TYPE
+; RELOC-NEXT:     Signatures:      
+; RELOC-NEXT:       - Index:           0
+; RELOC-NEXT:         ReturnType:      I32
+; RELOC-NEXT:         ParamTypes:      
+; RELOC-NEXT:   - Type:            FUNCTION
+; RELOC-NEXT:     FunctionTypes:   [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+; RELOC-NEXT:                        0, 0 ]
+; RELOC-NEXT:   - Type:            TABLE
+; RELOC-NEXT:     Tables:          
+; RELOC-NEXT:       - ElemType:        ANYFUNC
+; RELOC-NEXT:         Limits:          
+; RELOC-NEXT:           Flags:           [ HAS_MAX ]
+; RELOC-NEXT:           Initial:         0x00000006
+; RELOC-NEXT:           Maximum:         0x00000006
+; RELOC-NEXT:   - Type:            MEMORY
+; RELOC-NEXT:     Memories:        
+; RELOC-NEXT:       - Initial:         0x00000001
+; RELOC-NEXT:   - Type:            GLOBAL
+; RELOC-NEXT:     Globals:         
+; RELOC-NEXT:       - Index:           0
+; RELOC-NEXT:         Type:            I32
+; RELOC-NEXT:         Mutable:         false
+; RELOC-NEXT:         InitExpr:        
+; RELOC-NEXT:           Opcode:          I32_CONST
+; RELOC-NEXT:           Value:           0
+; RELOC-NEXT:       - Index:           1
+; RELOC-NEXT:         Type:            I32
+; RELOC-NEXT:         Mutable:         false
+; RELOC-NEXT:         InitExpr:        
+; RELOC-NEXT:           Opcode:          I32_CONST
+; RELOC-NEXT:           Value:           8
+; RELOC-NEXT:       - Index:           2
+; RELOC-NEXT:         Type:            I32
+; RELOC-NEXT:         Mutable:         false
+; RELOC-NEXT:         InitExpr:        
+; RELOC-NEXT:           Opcode:          I32_CONST
+; RELOC-NEXT:           Value:           16
+; RELOC-NEXT:       - Index:           3
+; RELOC-NEXT:         Type:            I32
+; RELOC-NEXT:         Mutable:         false
+; RELOC-NEXT:         InitExpr:        
+; RELOC-NEXT:           Opcode:          I32_CONST
+; RELOC-NEXT:           Value:           4
+; RELOC-NEXT:       - Index:           4
+; RELOC-NEXT:         Type:            I32
+; RELOC-NEXT:         Mutable:         false
+; RELOC-NEXT:         InitExpr:        
+; RELOC-NEXT:           Opcode:          I32_CONST
+; RELOC-NEXT:           Value:           12
+; RELOC-NEXT:       - Index:           5
+; RELOC-NEXT:         Type:            I32
+; RELOC-NEXT:         Mutable:         false
+; RELOC-NEXT:         InitExpr:        
+; RELOC-NEXT:           Opcode:          I32_CONST
+; RELOC-NEXT:           Value:           20
+; RELOC-NEXT:   - Type:            EXPORT
+; RELOC-NEXT:     Exports:         
+; RELOC-NEXT:       - Name:            colliding_func1.1
+; RELOC-NEXT:         Kind:            FUNCTION
+; RELOC-NEXT:         Index:           0
+; RELOC-NEXT:       - Name:            colliding_func2
+; RELOC-NEXT:         Kind:            FUNCTION
+; RELOC-NEXT:         Index:           1
+; RELOC-NEXT:       - Name:            colliding_func3
+; RELOC-NEXT:         Kind:            FUNCTION
+; RELOC-NEXT:         Index:           2
+; RELOC-NEXT:       - Name:            get_global1A
+; RELOC-NEXT:         Kind:            FUNCTION
+; RELOC-NEXT:         Index:           3
+; RELOC-NEXT:       - Name:            get_global2A
+; RELOC-NEXT:         Kind:            FUNCTION
+; RELOC-NEXT:         Index:           4
+; RELOC-NEXT:       - Name:            get_global3A
+; RELOC-NEXT:         Kind:            FUNCTION
+; RELOC-NEXT:         Index:           5
+; RELOC-NEXT:       - Name:            get_func1A
+; RELOC-NEXT:         Kind:            FUNCTION
+; RELOC-NEXT:         Index:           6
+; RELOC-NEXT:       - Name:            get_func2A
+; RELOC-NEXT:         Kind:            FUNCTION
+; RELOC-NEXT:         Index:           7
+; RELOC-NEXT:       - Name:            get_func3A
+; RELOC-NEXT:         Kind:            FUNCTION
+; RELOC-NEXT:         Index:           8
+; RELOC-NEXT:       - Name:            colliding_func1
+; RELOC-NEXT:         Kind:            FUNCTION
+; RELOC-NEXT:         Index:           9
+; RELOC-NEXT:       - Name:            colliding_func2.1
+; RELOC-NEXT:         Kind:            FUNCTION
+; RELOC-NEXT:         Index:           10
+; RELOC-NEXT:       - Name:            colliding_func3.1
+; RELOC-NEXT:         Kind:            FUNCTION
+; RELOC-NEXT:         Index:           11
+; RELOC-NEXT:       - Name:            get_global1B
+; RELOC-NEXT:         Kind:            FUNCTION
+; RELOC-NEXT:         Index:           12
+; RELOC-NEXT:       - Name:            get_global2B
+; RELOC-NEXT:         Kind:            FUNCTION
+; RELOC-NEXT:         Index:           13
+; RELOC-NEXT:       - Name:            get_global3B
+; RELOC-NEXT:         Kind:            FUNCTION
+; RELOC-NEXT:         Index:           14
+; RELOC-NEXT:       - Name:            get_func1B
+; RELOC-NEXT:         Kind:            FUNCTION
+; RELOC-NEXT:         Index:           15
+; RELOC-NEXT:       - Name:            get_func2B
+; RELOC-NEXT:         Kind:            FUNCTION
+; RELOC-NEXT:         Index:           16
+; RELOC-NEXT:       - Name:            get_func3B
+; RELOC-NEXT:         Kind:            FUNCTION
+; RELOC-NEXT:         Index:           17
+; RELOC-NEXT:       - Name:            colliding_global1.1
+; RELOC-NEXT:         Kind:            GLOBAL
+; RELOC-NEXT:         Index:           0
+; RELOC-NEXT:       - Name:            colliding_global2
+; RELOC-NEXT:         Kind:            GLOBAL
+; RELOC-NEXT:         Index:           1
+; RELOC-NEXT:       - Name:            colliding_global3
+; RELOC-NEXT:         Kind:            GLOBAL
+; RELOC-NEXT:         Index:           2
+; RELOC-NEXT:       - Name:            colliding_global1
+; RELOC-NEXT:         Kind:            GLOBAL
+; RELOC-NEXT:         Index:           3
+; RELOC-NEXT:       - Name:            colliding_global2.1
+; RELOC-NEXT:         Kind:            GLOBAL
+; RELOC-NEXT:         Index:           4
+; RELOC-NEXT:       - Name:            colliding_global3.1
+; RELOC-NEXT:         Kind:            GLOBAL
+; RELOC-NEXT:         Index:           5
+; RELOC-NEXT:   - Type:            ELEM
+; RELOC-NEXT:     Segments:        
+; RELOC-NEXT:       - Offset:          
+; RELOC-NEXT:           Opcode:          I32_CONST
+; RELOC-NEXT:           Value:           0
+; RELOC-NEXT:         Functions:       [ 0, 1, 2, 9, 10, 11 ]
+; RELOC-NEXT:   - Type:            CODE
+; RELOC-NEXT:     Relocations:     
+; RELOC-NEXT:       - Type:            R_WEBASSEMBLY_MEMORY_ADDR_SLEB
+; RELOC-NEXT:         Index:           0
+; RELOC-NEXT:         Offset:          0x00000013
+; RELOC-NEXT:       - Type:            R_WEBASSEMBLY_MEMORY_ADDR_SLEB
+; RELOC-NEXT:         Index:           1
+; RELOC-NEXT:         Offset:          0x0000001C
+; RELOC-NEXT:       - Type:            R_WEBASSEMBLY_MEMORY_ADDR_SLEB
+; RELOC-NEXT:         Index:           2
+; RELOC-NEXT:         Offset:          0x00000025
+; RELOC-NEXT:       - Type:            R_WEBASSEMBLY_TABLE_INDEX_SLEB
+; RELOC-NEXT:         Index:           0
+; RELOC-NEXT:         Offset:          0x0000002E
+; RELOC-NEXT:       - Type:            R_WEBASSEMBLY_TABLE_INDEX_SLEB
+; RELOC-NEXT:         Index:           1
+; RELOC-NEXT:         Offset:          0x00000037
+; RELOC-NEXT:       - Type:            R_WEBASSEMBLY_TABLE_INDEX_SLEB
+; RELOC-NEXT:         Index:           2
+; RELOC-NEXT:         Offset:          0x00000040
+; RELOC-NEXT:       - Type:            R_WEBASSEMBLY_MEMORY_ADDR_SLEB
+; RELOC-NEXT:         Index:           3
+; RELOC-NEXT:         Offset:          0x00000058
+; RELOC-NEXT:       - Type:            R_WEBASSEMBLY_MEMORY_ADDR_SLEB
+; RELOC-NEXT:         Index:           4
+; RELOC-NEXT:         Offset:          0x00000061
+; RELOC-NEXT:       - Type:            R_WEBASSEMBLY_MEMORY_ADDR_SLEB
+; RELOC-NEXT:         Index:           5
+; RELOC-NEXT:         Offset:          0x0000006A
+; RELOC-NEXT:       - Type:            R_WEBASSEMBLY_TABLE_INDEX_SLEB
+; RELOC-NEXT:         Index:           3
+; RELOC-NEXT:         Offset:          0x00000073
+; RELOC-NEXT:       - Type:            R_WEBASSEMBLY_TABLE_INDEX_SLEB
+; RELOC-NEXT:         Index:           4
+; RELOC-NEXT:         Offset:          0x0000007C
+; RELOC-NEXT:       - Type:            R_WEBASSEMBLY_TABLE_INDEX_SLEB
+; RELOC-NEXT:         Index:           5
+; RELOC-NEXT:         Offset:          0x00000085
+; RELOC-NEXT:     Functions:       
+; RELOC-NEXT:       - Index:           0
+; RELOC-NEXT:         Locals:          
+; RELOC-NEXT:         Body:            41020B
+; RELOC-NEXT:       - Index:           1
+; RELOC-NEXT:         Locals:          
+; RELOC-NEXT:         Body:            41020B
+; RELOC-NEXT:       - Index:           2
+; RELOC-NEXT:         Locals:          
+; RELOC-NEXT:         Body:            41020B
+; RELOC-NEXT:       - Index:           3
+; RELOC-NEXT:         Locals:          
+; RELOC-NEXT:         Body:            4180808080000B
+; RELOC-NEXT:       - Index:           4
+; RELOC-NEXT:         Locals:          
+; RELOC-NEXT:         Body:            4188808080000B
+; RELOC-NEXT:       - Index:           5
+; RELOC-NEXT:         Locals:          
+; RELOC-NEXT:         Body:            4190808080000B
+; RELOC-NEXT:       - Index:           6
+; RELOC-NEXT:         Locals:          
+; RELOC-NEXT:         Body:            4180808080000B
+; RELOC-NEXT:       - Index:           7
+; RELOC-NEXT:         Locals:          
+; RELOC-NEXT:         Body:            4181808080000B
+; RELOC-NEXT:       - Index:           8
+; RELOC-NEXT:         Locals:          
+; RELOC-NEXT:         Body:            4182808080000B
+; RELOC-NEXT:       - Index:           9
+; RELOC-NEXT:         Locals:          
+; RELOC-NEXT:         Body:            41020B
+; RELOC-NEXT:       - Index:           10
+; RELOC-NEXT:         Locals:          
+; RELOC-NEXT:         Body:            41020B
+; RELOC-NEXT:       - Index:           11
+; RELOC-NEXT:         Locals:          
+; RELOC-NEXT:         Body:            41020B
+; RELOC-NEXT:       - Index:           12
+; RELOC-NEXT:         Locals:          
+; RELOC-NEXT:         Body:            4184808080000B
+; RELOC-NEXT:       - Index:           13
+; RELOC-NEXT:         Locals:          
+; RELOC-NEXT:         Body:            418C808080000B
+; RELOC-NEXT:       - Index:           14
+; RELOC-NEXT:         Locals:          
+; RELOC-NEXT:         Body:            4194808080000B
+; RELOC-NEXT:       - Index:           15
+; RELOC-NEXT:         Locals:          
+; RELOC-NEXT:         Body:            4183808080000B
+; RELOC-NEXT:       - Index:           16
+; RELOC-NEXT:         Locals:          
+; RELOC-NEXT:         Body:            4184808080000B
+; RELOC-NEXT:       - Index:           17
+; RELOC-NEXT:         Locals:          
+; RELOC-NEXT:         Body:            4185808080000B
+; RELOC-NEXT:   - Type:            DATA
+; RELOC-NEXT:     Segments:        
+; RELOC-NEXT:       - SectionOffset:   6
+; RELOC-NEXT:         MemoryIndex:     0
+; RELOC-NEXT:         Offset:          
+; RELOC-NEXT:           Opcode:          I32_CONST
+; RELOC-NEXT:           Value:           0
+; RELOC-NEXT:         Content:         '0000000000000000'
+; RELOC-NEXT:       - SectionOffset:   19
+; RELOC-NEXT:         MemoryIndex:     0
+; RELOC-NEXT:         Offset:          
+; RELOC-NEXT:           Opcode:          I32_CONST
+; RELOC-NEXT:           Value:           8
+; RELOC-NEXT:         Content:         '0000000000000000'
+; RELOC-NEXT:       - SectionOffset:   32
+; RELOC-NEXT:         MemoryIndex:     0
+; RELOC-NEXT:         Offset:          
+; RELOC-NEXT:           Opcode:          I32_CONST
+; RELOC-NEXT:           Value:           16
+; RELOC-NEXT:         Content:         '0000000000000000'
+; RELOC-NEXT:   - Type:            CUSTOM
+; RELOC-NEXT:     Name:            linking
+; RELOC-NEXT:     DataSize:        24
+; RELOC-NEXT:     SymbolInfo:      
+; RELOC-NEXT:       - Name:            colliding_func1.1
+; RELOC-NEXT:         Flags:           [ BINDING_LOCAL ]
+; RELOC-NEXT:       - Name:            colliding_func3
+; RELOC-NEXT:         Flags:           [ BINDING_LOCAL ]
+; RELOC-NEXT:       - Name:            colliding_func2.1
+; RELOC-NEXT:         Flags:           [ BINDING_LOCAL ]
+; RELOC-NEXT:       - Name:            colliding_func3.1
+; RELOC-NEXT:         Flags:           [ BINDING_LOCAL ]
+; RELOC-NEXT:       - Name:            colliding_global1.1
+; RELOC-NEXT:         Flags:           [ BINDING_LOCAL ]
+; RELOC-NEXT:       - Name:            colliding_global3
+; RELOC-NEXT:         Flags:           [ BINDING_LOCAL ]
+; RELOC-NEXT:       - Name:            colliding_global2.1
+; RELOC-NEXT:         Flags:           [ BINDING_LOCAL ]
+; RELOC-NEXT:       - Name:            colliding_global3.1
+; RELOC-NEXT:         Flags:           [ BINDING_LOCAL ]
+; RELOC-NEXT:     SegmentInfo:     
+; RELOC-NEXT:       - Index:           0
+; RELOC-NEXT:         Name:            .bss.colliding_global1
+; RELOC-NEXT:         Alignment:       4
+; RELOC-NEXT:         Flags:           [  ]
+; RELOC-NEXT:       - Index:           1
+; RELOC-NEXT:         Name:            .bss.colliding_global2
+; RELOC-NEXT:         Alignment:       4
+; RELOC-NEXT:         Flags:           [  ]
+; RELOC-NEXT:       - Index:           2
+; RELOC-NEXT:         Name:            .bss.colliding_global3
+; RELOC-NEXT:         Alignment:       4
+; RELOC-NEXT:         Flags:           [  ]
+; RELOC-NEXT:   - Type:            CUSTOM
+; RELOC-NEXT:     Name:            name
+; RELOC-NEXT:     FunctionNames:   
+; RELOC-NEXT:       - Index:           0
+; RELOC-NEXT:         Name:            colliding_func1
+; RELOC-NEXT:       - Index:           1
+; RELOC-NEXT:         Name:            colliding_func2
+; RELOC-NEXT:       - Index:           2
+; RELOC-NEXT:         Name:            colliding_func3
+; RELOC-NEXT:       - Index:           3
+; RELOC-NEXT:         Name:            get_global1A
+; RELOC-NEXT:       - Index:           4
+; RELOC-NEXT:         Name:            get_global2A
+; RELOC-NEXT:       - Index:           5
+; RELOC-NEXT:         Name:            get_global3A
+; RELOC-NEXT:       - Index:           6
+; RELOC-NEXT:         Name:            get_func1A
+; RELOC-NEXT:       - Index:           7
+; RELOC-NEXT:         Name:            get_func2A
+; RELOC-NEXT:       - Index:           8
+; RELOC-NEXT:         Name:            get_func3A
+; RELOC-NEXT:       - Index:           9
+; RELOC-NEXT:         Name:            colliding_func1
+; RELOC-NEXT:       - Index:           10
+; RELOC-NEXT:         Name:            colliding_func2
+; RELOC-NEXT:       - Index:           11
+; RELOC-NEXT:         Name:            colliding_func3
+; RELOC-NEXT:       - Index:           12
+; RELOC-NEXT:         Name:            get_global1B
+; RELOC-NEXT:       - Index:           13
+; RELOC-NEXT:         Name:            get_global2B
+; RELOC-NEXT:       - Index:           14
+; RELOC-NEXT:         Name:            get_global3B
+; RELOC-NEXT:       - Index:           15
+; RELOC-NEXT:         Name:            get_func1B
+; RELOC-NEXT:       - Index:           16
+; RELOC-NEXT:         Name:            get_func2B
+; RELOC-NEXT:       - Index:           17
+; RELOC-NEXT:         Name:            get_func3B
+; RELOC-NEXT: ...

Modified: lld/trunk/test/wasm/relocatable.ll
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/relocatable.ll?rev=322908&r1=322907&r2=322908&view=diff
==============================================================================
--- lld/trunk/test/wasm/relocatable.ll (original)
+++ lld/trunk/test/wasm/relocatable.ll Thu Jan 18 15:40:49 2018
@@ -200,6 +200,21 @@ entry:
 ; CHECK-NEXT:   - Type:            CUSTOM
 ; CHECK-NEXT:     Name:            linking
 ; CHECK-NEXT:     DataSize:        23
+; CHECK-NEXT:     SymbolInfo:
+; CHECK-NEXT:       - Name:            hello
+; CHECK-NEXT:         Flags:           [ VISIBILITY_HIDDEN ]
+; CHECK-NEXT:       - Name:            my_func
+; CHECK-NEXT:         Flags:           [ VISIBILITY_HIDDEN ]
+; CHECK-NEXT:       - Name:            func_comdat
+; CHECK-NEXT:         Flags:           [ BINDING_WEAK ]
+; CHECK-NEXT:       - Name:            data_comdat
+; CHECK-NEXT:         Flags:           [ BINDING_WEAK ]
+; CHECK-NEXT:       - Name:            func_addr1
+; CHECK-NEXT:         Flags:           [ VISIBILITY_HIDDEN ]
+; CHECK-NEXT:       - Name:            func_addr2
+; CHECK-NEXT:         Flags:           [ VISIBILITY_HIDDEN ]
+; CHECK-NEXT:       - Name:            data_addr1
+; CHECK-NEXT:         Flags:           [ VISIBILITY_HIDDEN ]
 ; CHECK-NEXT:     SegmentInfo:
 ; CHECK-NEXT:       - Index:           0
 ; CHECK-NEXT:         Name:            .rodata.hello_str

Modified: lld/trunk/test/wasm/visibility-hidden.ll
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/visibility-hidden.ll?rev=322908&r1=322907&r2=322908&view=diff
==============================================================================
--- lld/trunk/test/wasm/visibility-hidden.ll (original)
+++ lld/trunk/test/wasm/visibility-hidden.ll Thu Jan 18 15:40:49 2018
@@ -37,12 +37,12 @@ entry:
 ; CHECK-NEXT:       - Name:            _start
 ; CHECK-NEXT:         Kind:            FUNCTION
 ; CHECK-NEXT:         Index:           2
-; CHECK-NEXT:       - Name:            archiveDefault
-; CHECK-NEXT:         Kind:            FUNCTION
-; CHECK-NEXT:         Index:           4
 ; CHECK-NEXT:       - Name:            objectDefault
 ; CHECK-NEXT:         Kind:            FUNCTION
 ; CHECK-NEXT:         Index:           1
+; CHECK-NEXT:       - Name:            archiveDefault
+; CHECK-NEXT:         Kind:            FUNCTION
+; CHECK-NEXT:         Index:           4
 ; CHECK-NEXT:       - Name:            __heap_base
 ; CHECK-NEXT:         Kind:            GLOBAL
 ; CHECK-NEXT:         Index:           1

Modified: lld/trunk/wasm/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/Writer.cpp?rev=322908&r1=322907&r2=322908&view=diff
==============================================================================
--- lld/trunk/wasm/Writer.cpp (original)
+++ lld/trunk/wasm/Writer.cpp Thu Jan 18 15:40:49 2018
@@ -62,6 +62,12 @@ struct WasmSignatureDenseMapInfo {
   }
 };
 
+// A Wasm export to be written into the export section.
+struct WasmExportEntry {
+  const Symbol *Symbol;
+  StringRef FieldName; // may not match the Symbol name
+};
+
 // The writer writes a SymbolTable result to a file.
 class Writer {
 public:
@@ -76,6 +82,7 @@ private:
   void calculateInitFunctions();
   void assignIndexes();
   void calculateImports();
+  void calculateExports();
   void calculateTypes();
   void createOutputSegments();
   void layoutMemory();
@@ -114,6 +121,7 @@ private:
   DenseMap<WasmSignature, int32_t, WasmSignatureDenseMapInfo> TypeIndices;
   std::vector<const Symbol *> ImportedFunctions;
   std::vector<const Symbol *> ImportedGlobals;
+  std::vector<WasmExportEntry> ExportedSymbols;
   std::vector<const Symbol *> DefinedGlobals;
   std::vector<InputFunction *> DefinedFunctions;
   std::vector<const Symbol *> IndirectFunctions;
@@ -259,35 +267,8 @@ void Writer::createTableSection() {
 
 void Writer::createExportSection() {
   bool ExportMemory = !Config->Relocatable && !Config->ImportMemory;
-  Symbol *EntrySym = Symtab->find(Config->Entry);
-  bool ExportEntry = !Config->Relocatable && EntrySym && EntrySym->isDefined();
-  bool ExportHidden = Config->EmitRelocs;
-
-  uint32_t NumExports = ExportMemory ? 1 : 0;
-
-  std::vector<const Symbol *> SymbolExports;
-  if (ExportEntry)
-    SymbolExports.emplace_back(EntrySym);
-
-  for (const Symbol *Sym : Symtab->getSymbols()) {
-    if (Sym->isUndefined() || Sym->isGlobal())
-      continue;
-    if (Sym->isHidden() && !ExportHidden)
-      continue;
-    if (ExportEntry && Sym == EntrySym)
-      continue;
-    SymbolExports.emplace_back(Sym);
-  }
 
-  for (const Symbol *Sym : DefinedGlobals) {
-    // Can't export the SP right now because it mutable and mutable globals
-    // connot be exported.
-    if (Sym == Config->StackPointerSymbol)
-      continue;
-    SymbolExports.emplace_back(Sym);
-  }
-
-  NumExports += SymbolExports.size();
+  uint32_t NumExports = (ExportMemory ? 1 : 0) + ExportedSymbols.size();
   if (!NumExports)
     return;
 
@@ -304,12 +285,12 @@ void Writer::createExportSection() {
     writeExport(OS, MemoryExport);
   }
 
-  for (const Symbol *Sym : SymbolExports) {
-    DEBUG(dbgs() << "Export: " << Sym->getName() << "\n");
+  for (const WasmExportEntry &E : ExportedSymbols) {
+    DEBUG(dbgs() << "Export: " << E.Symbol->getName() << "\n");
     WasmExport Export;
-    Export.Name = Sym->getName();
-    Export.Index = Sym->getOutputIndex();
-    if (Sym->isFunction())
+    Export.Name = E.FieldName;
+    Export.Index = E.Symbol->getOutputIndex();
+    if (E.Symbol->isFunction())
       Export.Kind = WASM_EXTERNAL_FUNCTION;
     else
       Export.Kind = WASM_EXTERNAL_GLOBAL;
@@ -404,6 +385,26 @@ void Writer::createLinkingSection() {
   if (!Config->Relocatable)
     return;
 
+  std::vector<std::pair<StringRef, uint32_t>> SymbolInfo;
+  for (const WasmExportEntry &E : ExportedSymbols) {
+    uint32_t Flags =
+        (E.Symbol->isLocal() ? WASM_SYMBOL_BINDING_LOCAL :
+         E.Symbol->isWeak() ? WASM_SYMBOL_BINDING_WEAK : 0) |
+        (E.Symbol->isHidden() ? WASM_SYMBOL_VISIBILITY_HIDDEN : 0);
+    if (Flags)
+      SymbolInfo.emplace_back(E.FieldName, Flags);
+  }
+  if (!SymbolInfo.empty()) {
+    SubSection SubSection(WASM_SYMBOL_INFO);
+    writeUleb128(SubSection.getStream(), SymbolInfo.size(), "num sym info");
+    for (auto Pair: SymbolInfo) {
+      writeStr(SubSection.getStream(), Pair.first, "sym name");
+      writeUleb128(SubSection.getStream(), Pair.second, "sym flags");
+    }
+    SubSection.finalizeContents();
+    SubSection.writeToStream(OS);
+  }
+
   if (Segments.size()) {
     SubSection SubSection(WASM_SEGMENT_INFO);
     writeUleb128(SubSection.getStream(), Segments.size(), "num data segments");
@@ -608,6 +609,64 @@ void Writer::calculateImports() {
   }
 }
 
+void Writer::calculateExports() {
+  Symbol *EntrySym = Symtab->find(Config->Entry);
+  bool ExportEntry = !Config->Relocatable && EntrySym && EntrySym->isDefined();
+  bool ExportHidden = Config->EmitRelocs;
+  StringSet<> UsedNames;
+  auto BudgeLocalName = [&](const Symbol *Sym) {
+    StringRef SymName = Sym->getName();
+    // We can't budge non-local names.
+    if (!Sym->isLocal())
+      return SymName;
+    // We must budge local names that have a collision with a symbol that we
+    // haven't yet processed.
+    if (!Symtab->find(SymName) && UsedNames.insert(SymName).second)
+      return SymName;
+    for (unsigned I = 1; ; ++I) {
+      std::string NameBuf = (SymName + "." + Twine(I)).str();
+      if (!UsedNames.count(NameBuf)) {
+        StringRef Name = Saver.save(NameBuf);
+        UsedNames.insert(Name); // Insert must use safe StringRef from save()
+        return Name;
+      }
+    }
+  };
+
+  if (ExportEntry)
+    ExportedSymbols.emplace_back(WasmExportEntry{EntrySym, EntrySym->getName()});
+
+  if (Config->CtorSymbol && ExportHidden &&
+      !(ExportEntry && Config->CtorSymbol == EntrySym))
+    ExportedSymbols.emplace_back(
+        WasmExportEntry{Config->CtorSymbol, Config->CtorSymbol->getName()});
+
+  for (ObjFile *File : Symtab->ObjectFiles) {
+    for (Symbol *Sym : File->getSymbols()) {
+      if (!Sym->isDefined() || File != Sym->getFile())
+        continue;
+      if (Sym->isGlobal())
+        continue;
+      if (Sym->getFunction()->Discarded)
+        continue;
+
+      if ((Sym->isHidden() || Sym->isLocal()) && !ExportHidden)
+        continue;
+      if (ExportEntry && Sym == EntrySym)
+        continue;
+      ExportedSymbols.emplace_back(WasmExportEntry{Sym, BudgeLocalName(Sym)});
+    }
+  }
+
+  for (const Symbol *Sym : DefinedGlobals) {
+    // Can't export the SP right now because it's mutable and mutable globals
+    // cannot be exported.
+    if (Sym == Config->StackPointerSymbol)
+      continue;
+    ExportedSymbols.emplace_back(WasmExportEntry{Sym, BudgeLocalName(Sym)});
+  }
+}
+
 uint32_t Writer::lookupType(const WasmSignature &Sig) {
   auto It = TypeIndices.find(Sig);
   if (It == TypeIndices.end()) {
@@ -793,6 +852,8 @@ void Writer::run() {
   calculateImports();
   log("-- assignIndexes");
   assignIndexes();
+  log("-- calculateExports");
+  calculateExports();
   log("-- calculateInitFunctions");
   calculateInitFunctions();
   if (!Config->Relocatable)




More information about the llvm-commits mailing list