Index: docs/ReleaseNotes.rst =================================================================== --- docs/ReleaseNotes.rst +++ docs/ReleaseNotes.rst @@ -64,4 +64,7 @@ WebAssembly Improvements ------------------------ -* ... +* `__data_end` and `__heap_base` are no longer exported by default, + as it's best to keep them internal when possible. They can be + explicitly exported with `--export=__data_end` and + `--export=__heap_base`, respectively. Index: docs/WebAssembly.rst =================================================================== --- docs/WebAssembly.rst +++ docs/WebAssembly.rst @@ -84,6 +84,13 @@ By default the function table is neither imported nor exported, but defined for internal use only. +.. option:: --emscripten + + Enable Emscripten mode. + +This option enables Emscripten mode, which exports symbols needed by +Emscripten and enables options related to dynamic linking. + Behaviour --------- @@ -109,24 +116,23 @@ and use these stub functions at the otherwise invalid call sites. The default behaviour is to generate these stub function and to produce -a warning. The ``--falal-warnings`` flag can be used to disable this behaviour +a warning. The ``--fatal-warnings`` flag can be used to disable this behaviour and error out if mismatched are found. Imports and Exports ~~~~~~~~~~~~~~~~~~~ -When building a shared library any symbols marked as ``visibility=default`` will -be exported. When building an executable, only the entry point and symbols -flagged as ``WASM_SYMBOL_EXPORTED`` are exported by default. In LLVM the -``WASM_SYMBOL_EXPORTED`` flag is applied to any symbol in the ``llvm.used`` list -which corresponds to ``__attribute__((used))`` in C/C++ sources. +By default, the only symbols exported from the WebAssembly module are the +entry-point symbol and the primary linear memory, named "memory". These ABI +details are not yet stable. In addition, symbols can be exported via the linker command line using -``--export``. +``--export``. ``--export-dynamic`` exports all symbols with "default" +visibility. ``--export-all`` exports all symbols with global binding. -Finally, just like with native ELF linker the ``--export-dynamic`` flag can be -used to export symbol in the executable which are marked as -``visibility=default``. +With ``--emscripten``, the ``--shared`` option implies ``--export-dynamic``, +and symbols marked with ``__attribute__((used))`` are also exported from +the WebAssembly module. Garbage Collection ~~~~~~~~~~~~~~~~~~ Index: test/wasm/alias.ll =================================================================== --- test/wasm/alias.ll +++ test/wasm/alias.ll @@ -1,7 +1,12 @@ ; RUN: llc -filetype=obj -o %t.o %s + ; RUN: wasm-ld --export=start_alias %t.o -o %t.wasm ; RUN: obj2yaml %t.wasm | FileCheck %s +; Same thing, now with --emscripten. +; RUN: wasm-ld --export=start_alias --emscripten %t.o -o %t.wasm +; RUN: obj2yaml %t.wasm | FileCheck %s --check-prefixes=CHECK,EMSCRIPTEN + target triple = "wasm32-unknown-unknown" @start_alias = alias void (), void ()* @_start @@ -41,29 +46,29 @@ ; CHECK-NEXT: InitExpr: ; CHECK-NEXT: Opcode: I32_CONST ; CHECK-NEXT: Value: 66560 -; CHECK-NEXT: - Index: 1 -; CHECK-NEXT: Type: I32 -; CHECK-NEXT: Mutable: false -; CHECK-NEXT: InitExpr: -; CHECK-NEXT: Opcode: I32_CONST -; CHECK-NEXT: Value: 66560 -; CHECK-NEXT: - Index: 2 -; CHECK-NEXT: Type: I32 -; CHECK-NEXT: Mutable: false -; CHECK-NEXT: InitExpr: -; CHECK-NEXT: Opcode: I32_CONST -; CHECK-NEXT: Value: 1024 +; EMSCRIPTEN-NEXT: - Index: 1 +; EMSCRIPTEN-NEXT: Type: I32 +; EMSCRIPTEN-NEXT: Mutable: false +; EMSCRIPTEN-NEXT: InitExpr: +; EMSCRIPTEN-NEXT: Opcode: I32_CONST +; EMSCRIPTEN-NEXT: Value: 66560 +; EMSCRIPTEN-NEXT: - Index: 2 +; EMSCRIPTEN-NEXT: Type: I32 +; EMSCRIPTEN-NEXT: Mutable: false +; EMSCRIPTEN-NEXT: InitExpr: +; EMSCRIPTEN-NEXT: Opcode: I32_CONST +; EMSCRIPTEN-NEXT: Value: 1024 ; CHECK-NEXT: - Type: EXPORT ; CHECK-NEXT: Exports: ; CHECK-NEXT: - Name: memory ; CHECK-NEXT: Kind: MEMORY ; CHECK-NEXT: Index: 0 -; CHECK-NEXT: - Name: __heap_base -; CHECK-NEXT: Kind: GLOBAL -; CHECK-NEXT: Index: 1 -; CHECK-NEXT: - Name: __data_end -; CHECK-NEXT: Kind: GLOBAL -; CHECK-NEXT: Index: 2 +; EMSCRIPTEN-NEXT: - Name: __heap_base +; EMSCRIPTEN-NEXT: Kind: GLOBAL +; EMSCRIPTEN-NEXT: Index: 1 +; EMSCRIPTEN-NEXT: - Name: __data_end +; EMSCRIPTEN-NEXT: Kind: GLOBAL +; EMSCRIPTEN-NEXT: Index: 2 ; CHECK-NEXT: - Name: _start ; CHECK-NEXT: Kind: FUNCTION ; CHECK-NEXT: Index: 0 Index: test/wasm/archive-export.ll =================================================================== --- test/wasm/archive-export.ll +++ test/wasm/archive-export.ll @@ -14,12 +14,6 @@ CHECK-NEXT: - Name: memory CHECK-NEXT: Kind: MEMORY CHECK-NEXT: Index: 0 -CHECK-NEXT: - Name: __heap_base -CHECK-NEXT: Kind: GLOBAL -CHECK-NEXT: Index: 1 -CHECK-NEXT: - Name: __data_end -CHECK-NEXT: Kind: GLOBAL -CHECK-NEXT: Index: 2 CHECK-NEXT: - Name: foo CHECK-NEXT: Kind: FUNCTION CHECK-NEXT: Index: 1 @@ -38,12 +32,6 @@ NOEXPORT-NEXT: - Name: memory NOEXPORT-NEXT: Kind: MEMORY NOEXPORT-NEXT: Index: 0 -NOEXPORT-NEXT: - Name: __heap_base -NOEXPORT-NEXT: Kind: GLOBAL -NOEXPORT-NEXT: Index: 1 -NOEXPORT-NEXT: - Name: __data_end -NOEXPORT-NEXT: Kind: GLOBAL -NOEXPORT-NEXT: Index: 2 NOEXPORT-NEXT: - Name: _start NOEXPORT-NEXT: Kind: FUNCTION NOEXPORT-NEXT: Index: 0 Index: test/wasm/call-indirect.ll =================================================================== --- test/wasm/call-indirect.ll +++ test/wasm/call-indirect.ll @@ -81,30 +81,12 @@ ; CHECK-NEXT: Mutable: false ; CHECK-NEXT: InitExpr: ; CHECK-NEXT: Opcode: I32_CONST -; CHECK-NEXT: Value: 66576 -; CHECK-NEXT: - Index: 2 -; CHECK-NEXT: Type: I32 -; CHECK-NEXT: Mutable: false -; CHECK-NEXT: InitExpr: -; CHECK-NEXT: Opcode: I32_CONST -; CHECK-NEXT: Value: 1036 -; CHECK-NEXT: - Index: 3 -; CHECK-NEXT: Type: I32 -; CHECK-NEXT: Mutable: false -; CHECK-NEXT: InitExpr: -; CHECK-NEXT: Opcode: I32_CONST ; CHECK-NEXT: Value: 1032 ; CHECK-NEXT: - Type: EXPORT ; CHECK-NEXT: Exports: ; CHECK-NEXT: - Name: memory ; CHECK-NEXT: Kind: MEMORY ; CHECK-NEXT: Index: 0 -; CHECK-NEXT: - Name: __heap_base -; CHECK-NEXT: Kind: GLOBAL -; CHECK-NEXT: Index: 1 -; CHECK-NEXT: - Name: __data_end -; CHECK-NEXT: Kind: GLOBAL -; CHECK-NEXT: Index: 2 ; CHECK-NEXT: - Name: bar ; CHECK-NEXT: Kind: FUNCTION ; CHECK-NEXT: Index: 0 @@ -119,7 +101,7 @@ ; CHECK-NEXT: Index: 3 ; CHECK-NEXT: - Name: indirect_func ; CHECK-NEXT: Kind: GLOBAL -; CHECK-NEXT: Index: 3 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: - Name: call_ptr ; CHECK-NEXT: Kind: FUNCTION ; CHECK-NEXT: Index: 4 Index: test/wasm/comdats.ll =================================================================== --- test/wasm/comdats.ll +++ test/wasm/comdats.ll @@ -27,30 +27,12 @@ ; CHECK-NEXT: Mutable: false ; CHECK-NEXT: InitExpr: ; CHECK-NEXT: Opcode: I32_CONST -; CHECK-NEXT: Value: 66576 -; CHECK-NEXT: - Index: 2 -; CHECK-NEXT: Type: I32 -; CHECK-NEXT: Mutable: false -; CHECK-NEXT: InitExpr: -; CHECK-NEXT: Opcode: I32_CONST -; CHECK-NEXT: Value: 1027 -; CHECK-NEXT: - Index: 3 -; CHECK-NEXT: Type: I32 -; CHECK-NEXT: Mutable: false -; CHECK-NEXT: InitExpr: -; CHECK-NEXT: Opcode: I32_CONST ; CHECK-NEXT: Value: 1024 ; CHECK-NEXT: - Type: EXPORT ; CHECK-NEXT: Exports: ; CHECK-NEXT: - Name: memory ; CHECK-NEXT: Kind: MEMORY ; CHECK-NEXT: Index: 0 -; CHECK-NEXT: - Name: __heap_base -; CHECK-NEXT: Kind: GLOBAL -; CHECK-NEXT: Index: 1 -; CHECK-NEXT: - Name: __data_end -; CHECK-NEXT: Kind: GLOBAL -; CHECK-NEXT: Index: 2 ; CHECK-NEXT: - Name: _start ; CHECK-NEXT: Kind: FUNCTION ; CHECK-NEXT: Index: 0 @@ -59,7 +41,7 @@ ; CHECK-NEXT: Index: 1 ; CHECK-NEXT: - Name: constantData ; CHECK-NEXT: Kind: GLOBAL -; CHECK-NEXT: Index: 3 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: - Name: callInline1 ; CHECK-NEXT: Kind: FUNCTION ; CHECK-NEXT: Index: 2 Index: test/wasm/cxx-mangling.ll =================================================================== --- test/wasm/cxx-mangling.ll +++ test/wasm/cxx-mangling.ll @@ -1,9 +1,16 @@ ; RUN: llc -filetype=obj %s -o %t.o + ; RUN: wasm-ld --export=_Z3fooi --demangle -o %t_demangle.wasm %t.o ; RUN: obj2yaml %t_demangle.wasm | FileCheck --check-prefixes=CHECK,DEMANGLE %s ; RUN: wasm-ld --export=_Z3fooi --no-demangle -o %t_nodemangle.wasm %t.o ; RUN: obj2yaml %t_nodemangle.wasm | FileCheck --check-prefixes=CHECK,MANGLE %s +; Same thing, now with --emscripten. +; RUN: wasm-ld --emscripten --export=_Z3fooi --demangle -o %t_demangle.wasm %t.o +; RUN: obj2yaml %t_demangle.wasm | FileCheck --check-prefixes=CHECK,DEMANGLE,EMSCRIPTEN %s +; RUN: wasm-ld --emscripten --export=_Z3fooi --no-demangle -o %t_nodemangle.wasm %t.o +; RUN: obj2yaml %t_nodemangle.wasm | FileCheck --check-prefixes=CHECK,MANGLE,EMSCRIPTEN %s + target triple = "wasm32-unknown-unknown" ; Check that the EXPORT name is still mangled, but that the "name" custom @@ -26,12 +33,12 @@ ; CHECK-NEXT: - Name: memory ; CHECK-NEXT: Kind: MEMORY ; CHECK-NEXT: Index: 0 -; CHECK-NEXT: - Name: __heap_base -; CHECK-NEXT: Kind: GLOBAL -; CHECK-NEXT: Index: 1 -; CHECK-NEXT: - Name: __data_end -; CHECK-NEXT: Kind: GLOBAL -; CHECK-NEXT: Index: 2 +; EMSCRIPTEN-NEXT: - Name: __heap_base +; EMSCRIPTEN-NEXT: Kind: GLOBAL +; EMSCRIPTEN-NEXT: Index: 1 +; EMSCRIPTEN-NEXT: - Name: __data_end +; EMSCRIPTEN-NEXT: Kind: GLOBAL +; EMSCRIPTEN-NEXT: Index: 2 ; CHECK-NEXT: - Name: _Z3fooi ; CHECK-NEXT: Kind: FUNCTION ; CHECK-NEXT: Index: 1 Index: test/wasm/data-layout.ll =================================================================== --- test/wasm/data-layout.ll +++ test/wasm/data-layout.ll @@ -16,6 +16,10 @@ ; RUN: wasm-ld -no-gc-sections --allow-undefined --no-entry -o %t.wasm %t.o %t.hello.o ; RUN: obj2yaml %t.wasm | FileCheck %s +; Same thing, now with --emscripten. +; RUN: wasm-ld --emscripten -no-gc-sections --allow-undefined --no-entry -o %t.wasm %t.o %t.hello.o +; RUN: obj2yaml %t.wasm | FileCheck %s --check-prefixes=CHECK,EMSCRIPTEN + ; CHECK: - Type: MEMORY ; CHECK-NEXT: Memories: ; CHECK-NEXT: - Initial: 0x00000002 @@ -27,12 +31,12 @@ ; CHECK-NEXT: InitExpr: ; CHECK-NEXT: Opcode: I32_CONST ; CHECK-NEXT: Value: 66608 -; CHECK-NEXT: - Index: 1 -; CHECK-NEXT: Type: I32 -; CHECK-NEXT: Mutable: false -; CHECK-NEXT: InitExpr: -; CHECK-NEXT: Opcode: I32_CONST -; CHECK-NEXT: Value: 66608 +; EMSCRIPTEN-NEXT: - Index: 1 +; EMSCRIPTEN-NEXT: Type: I32 +; EMSCRIPTEN-NEXT: Mutable: false +; EMSCRIPTEN-NEXT: InitExpr: +; EMSCRIPTEN-NEXT: Opcode: I32_CONST +; EMSCRIPTEN-NEXT: Value: 66608 ; CHECK: - Type: DATA ; CHECK-NEXT: Segments: Index: test/wasm/entry.ll =================================================================== --- test/wasm/entry.ll +++ test/wasm/entry.ll @@ -12,17 +12,23 @@ ; RUN: wasm-ld --entry=entry -o %t2.wasm %t.o ; RUN: obj2yaml %t2.wasm | FileCheck %s +; Same thing, now with --emscripten. +; RUN: wasm-ld --emscripten -e entry -o %t1.wasm %t.o +; RUN: obj2yaml %t1.wasm | FileCheck %s --check-prefixes=CHECK,EMSCRIPTEN +; RUN: wasm-ld --emscripten --entry=entry -o %t2.wasm %t.o +; RUN: obj2yaml %t2.wasm | FileCheck %s --check-prefixes=CHECK,EMSCRIPTEN + ; CHECK: - Type: EXPORT ; CHECK-NEXT: Exports: ; CHECK-NEXT: - Name: memory ; CHECK-NEXT: Kind: MEMORY ; CHECK-NEXT: Index: 0 -; CHECK-NEXT: - Name: __heap_base -; CHECK-NEXT: Kind: GLOBAL -; CHECK-NEXT: Index: 1 -; CHECK-NEXT: - Name: __data_end -; CHECK-NEXT: Kind: GLOBAL -; CHECK-NEXT: Index: 2 +; EMSCRIPTEN-NEXT: - Name: __heap_base +; EMSCRIPTEN-NEXT: Kind: GLOBAL +; EMSCRIPTEN-NEXT: Index: 1 +; EMSCRIPTEN-NEXT: - Name: __data_end +; EMSCRIPTEN-NEXT: Kind: GLOBAL +; EMSCRIPTEN-NEXT: Index: 2 ; CHECK-NEXT: - Name: entry ; CHECK-NEXT: Kind: FUNCTION ; CHECK-NEXT: Index: 0 @@ -33,6 +39,10 @@ ; RUN: wasm-ld --entry=__wasm_call_ctors -o %t3.wasm %t.o ; RUN: obj2yaml %t3.wasm | FileCheck %s -check-prefix=CHECK-CTOR +; Same thing, now with --emscripten. +; RUN: wasm-ld --emscripten --entry=__wasm_call_ctors -o %t3.wasm %t.o +; RUN: obj2yaml %t3.wasm | FileCheck %s -check-prefixes=CHECK-CTOR,EMSCRIPTEN-CTOR + ; CHECK-CTOR: - Type: EXPORT ; CHECK-CTOR-NEXT: Exports: ; CHECK-CTOR-NEXT: - Name: memory @@ -41,10 +51,10 @@ ; CHECK-CTOR-NEXT: - Name: __wasm_call_ctors ; CHECK-CTOR-NEXT: Kind: FUNCTION ; CHECK-CTOR-NEXT: Index: 0 -; CHECK-CTOR-NEXT: - Name: __heap_base -; CHECK-CTOR-NEXT: Kind: GLOBAL -; CHECK-CTOR-NEXT: Index: 1 -; CHECK-CTOR-NEXT: - Name: __data_end -; CHECK-CTOR-NEXT: Kind: GLOBAL -; CHECK-CTOR-NEXT: Index: 2 +; EMSCRIPTEN-CTOR-NEXT: - Name: __heap_base +; EMSCRIPTEN-CTOR-NEXT: Kind: GLOBAL +; EMSCRIPTEN-CTOR-NEXT: Index: 1 +; EMSCRIPTEN-CTOR-NEXT: - Name: __data_end +; EMSCRIPTEN-CTOR-NEXT: Kind: GLOBAL +; EMSCRIPTEN-CTOR-NEXT: Index: 2 ; CHECK-CTOR-NEXT: - Type: Index: test/wasm/export.ll =================================================================== --- test/wasm/export.ll +++ test/wasm/export.ll @@ -1,8 +1,14 @@ ; RUN: llc -filetype=obj %s -o %t.o ; RUN: not wasm-ld --export=missing -o %t.wasm %t.o 2>&1 | FileCheck -check-prefix=CHECK-ERROR %s + ; RUN: wasm-ld --export=hidden_function -o %t.wasm %t.o ; RUN: obj2yaml %t.wasm | FileCheck %s +; Same thing, now with --emscripten. +; RUN: llc -filetype=obj %s -o %t.o -mtriple=wasm32-unknown-emscripten +; RUN: wasm-ld --emscripten --export=hidden_function -o %t.wasm %t.o +; RUN: obj2yaml %t.wasm | FileCheck %s --check-prefixes=CHECK,EMSCRIPTEN + @llvm.used = appending global [1 x i8*] [i8* bitcast (i32 ()* @used_function to i8*)], section "llvm.metadata" target triple = "wasm32-unknown-unknown" @@ -40,18 +46,18 @@ ; CHECK-NEXT: - Name: memory ; CHECK-NEXT: Kind: MEMORY ; CHECK-NEXT: Index: 0 -; CHECK-NEXT: - Name: __heap_base -; CHECK-NEXT: Kind: GLOBAL -; CHECK-NEXT: Index: 1 -; CHECK-NEXT: - Name: __data_end -; CHECK-NEXT: Kind: GLOBAL -; CHECK-NEXT: Index: 2 +; EMSCRIPTEN-NEXT: - Name: __heap_base +; EMSCRIPTEN-NEXT: Kind: GLOBAL +; EMSCRIPTEN-NEXT: Index: 1 +; EMSCRIPTEN-NEXT: - Name: __data_end +; EMSCRIPTEN-NEXT: Kind: GLOBAL +; EMSCRIPTEN-NEXT: Index: 2 ; CHECK-NEXT: - Name: hidden_function ; CHECK-NEXT: Kind: FUNCTION ; CHECK-NEXT: Index: 0 -; CHECK-NEXT: - Name: used_function -; CHECK-NEXT: Kind: FUNCTION -; CHECK-NEXT: Index: 1 +; EMSCRIPTEN-NEXT: - Name: used_function +; EMSCRIPTEN-NEXT: Kind: FUNCTION +; EMSCRIPTEN-NEXT: Index: 1 ; CHECK-NEXT: - Name: _start ; CHECK-NEXT: Kind: FUNCTION ; CHECK-NEXT: Index: 2 Index: test/wasm/local-symbols.ll =================================================================== --- test/wasm/local-symbols.ll +++ test/wasm/local-symbols.ll @@ -57,36 +57,18 @@ ; CHECK-NEXT: Mutable: false ; CHECK-NEXT: InitExpr: ; CHECK-NEXT: Opcode: I32_CONST -; CHECK-NEXT: Value: 66576 -; CHECK-NEXT: - Index: 2 -; CHECK-NEXT: Type: I32 -; CHECK-NEXT: Mutable: false -; CHECK-NEXT: InitExpr: -; CHECK-NEXT: Opcode: I32_CONST -; CHECK-NEXT: Value: 1032 -; CHECK-NEXT: - Index: 3 -; CHECK-NEXT: Type: I32 -; CHECK-NEXT: Mutable: false -; CHECK-NEXT: InitExpr: -; CHECK-NEXT: Opcode: I32_CONST ; CHECK-NEXT: Value: 1024 ; CHECK-NEXT: - Type: EXPORT ; CHECK-NEXT: Exports: ; CHECK-NEXT: - Name: memory ; CHECK-NEXT: Kind: MEMORY ; CHECK-NEXT: Index: 0 -; CHECK-NEXT: - Name: __heap_base -; CHECK-NEXT: Kind: GLOBAL -; CHECK-NEXT: Index: 1 -; CHECK-NEXT: - Name: __data_end -; CHECK-NEXT: Kind: GLOBAL -; CHECK-NEXT: Index: 2 ; CHECK-NEXT: - Name: _start ; CHECK-NEXT: Kind: FUNCTION ; CHECK-NEXT: Index: 1 ; CHECK-NEXT: - Name: foo ; CHECK-NEXT: Kind: GLOBAL -; CHECK-NEXT: Index: 3 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: - Type: CODE ; CHECK-NEXT: Functions: ; CHECK-NEXT: - Index: 0 Index: test/wasm/locals-duplicate.test =================================================================== --- test/wasm/locals-duplicate.test +++ test/wasm/locals-duplicate.test @@ -38,20 +38,8 @@ ; CHECK-NEXT: Mutable: false ; CHECK-NEXT: InitExpr: ; CHECK-NEXT: Opcode: I32_CONST -; CHECK-NEXT: Value: 66592 -; CHECK-NEXT: - Index: 2 -; CHECK-NEXT: Type: I32 -; CHECK-NEXT: Mutable: false -; CHECK-NEXT: InitExpr: -; CHECK-NEXT: Opcode: I32_CONST -; CHECK-NEXT: Value: 1048 -; CHECK-NEXT: - Index: 3 -; CHECK-NEXT: Type: I32 -; CHECK-NEXT: Mutable: false -; CHECK-NEXT: InitExpr: -; CHECK-NEXT: Opcode: I32_CONST ; CHECK-NEXT: Value: 1028 -; CHECK-NEXT: - Index: 4 +; CHECK-NEXT: - Index: 2 ; CHECK-NEXT: Type: I32 ; CHECK-NEXT: Mutable: false ; CHECK-NEXT: InitExpr: @@ -62,12 +50,6 @@ ; CHECK-NEXT: - Name: memory ; CHECK-NEXT: Kind: MEMORY ; CHECK-NEXT: Index: 0 -; CHECK-NEXT: - Name: __heap_base -; CHECK-NEXT: Kind: GLOBAL -; CHECK-NEXT: Index: 1 -; CHECK-NEXT: - Name: __data_end -; CHECK-NEXT: Kind: GLOBAL -; CHECK-NEXT: Index: 2 ; CHECK-NEXT: - Name: colliding_func2 ; CHECK-NEXT: Kind: FUNCTION ; CHECK-NEXT: Index: 1 @@ -79,7 +61,7 @@ ; CHECK-NEXT: Index: 4 ; CHECK-NEXT: - Name: colliding_global2 ; CHECK-NEXT: Kind: GLOBAL -; CHECK-NEXT: Index: 3 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: - Name: get_global3A ; CHECK-NEXT: Kind: FUNCTION ; CHECK-NEXT: Index: 5 @@ -100,7 +82,7 @@ ; CHECK-NEXT: Index: 12 ; CHECK-NEXT: - Name: colliding_global1 ; CHECK-NEXT: Kind: GLOBAL -; CHECK-NEXT: Index: 4 +; CHECK-NEXT: Index: 2 ; CHECK-NEXT: - Name: get_global2B ; CHECK-NEXT: Kind: FUNCTION ; CHECK-NEXT: Index: 13 Index: test/wasm/lto/export.ll =================================================================== --- test/wasm/lto/export.ll +++ test/wasm/lto/export.ll @@ -1,8 +1,13 @@ ; RUN: llvm-as -o %t.bc %s ; RUN: not wasm-ld --export=missing -o %t.wasm %t.bc 2>&1 | FileCheck -check-prefix=CHECK-ERROR %s + ; RUN: wasm-ld --export=hidden_function -o %t.wasm %t.bc ; RUN: obj2yaml %t.wasm | FileCheck %s +; Same thing, now with --emscripten. +; RUN: wasm-ld --emscripten --export=hidden_function -o %t.wasm %t.bc +; RUN: obj2yaml %t.wasm | FileCheck %s --check-prefixes=CHECK,EMSCRIPTEN + target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" target triple = "wasm32-unknown-unknown" @@ -23,12 +28,12 @@ ; CHECK-NEXT: - Name: memory ; CHECK-NEXT: Kind: MEMORY ; CHECK-NEXT: Index: 0 -; CHECK-NEXT: - Name: __heap_base -; CHECK-NEXT: Kind: GLOBAL -; CHECK-NEXT: Index: 1 -; CHECK-NEXT: - Name: __data_end -; CHECK-NEXT: Kind: GLOBAL -; CHECK-NEXT: Index: 2 +; EMSCRIPTEN-NEXT: - Name: __heap_base +; EMSCRIPTEN-NEXT: Kind: GLOBAL +; EMSCRIPTEN-NEXT: Index: 1 +; EMSCRIPTEN-NEXT: - Name: __data_end +; EMSCRIPTEN-NEXT: Kind: GLOBAL +; EMSCRIPTEN-NEXT: Index: 2 ; CHECK-NEXT: - Name: hidden_function ; CHECK-NEXT: Kind: FUNCTION ; CHECK-NEXT: Index: 0 Index: test/wasm/pie.ll =================================================================== --- test/wasm/pie.ll +++ test/wasm/pie.ll @@ -1,8 +1,8 @@ ; RUN: llc -relocation-model=pic -filetype=obj %s -o %t.o -; RUN: wasm-ld --no-gc-sections --allow-undefined -pie -o %t.wasm %t.o +; RUN: wasm-ld --emscripten --no-gc-sections --allow-undefined -pie -o %t.wasm %t.o ; RUN: obj2yaml %t.wasm | FileCheck %s -target triple = "wasm32-unknown-unknown" +target triple = "wasm32-unknown-emscripten" @data = global i32 2, align 4 @data_external = external global i32 Index: test/wasm/shared-needed.ll =================================================================== --- test/wasm/shared-needed.ll +++ test/wasm/shared-needed.ll @@ -1,13 +1,13 @@ ; RUN: llc -filetype=obj %s -o %t.o ; RUN: llc -filetype=obj %p/Inputs/ret32.ll -o %t.ret32.o -; RUN: wasm-ld -shared -o %t1.so %t.o +; RUN: wasm-ld --emscripten -shared -o %t1.so %t.o ; RUN: obj2yaml %t1.so | FileCheck %s -check-prefix=SO1 -; RUN: wasm-ld -shared -o %t2.so %t1.so %t.ret32.o +; RUN: wasm-ld --emscripten -shared -o %t2.so %t1.so %t.ret32.o ; RUN: obj2yaml %t2.so | FileCheck %s -check-prefix=SO2 -target triple = "wasm32-unknown-unknown" +target triple = "wasm32-unknown-emscripten" @data = global i32 2, align 4 Index: test/wasm/shared.ll =================================================================== --- test/wasm/shared.ll +++ test/wasm/shared.ll @@ -1,8 +1,8 @@ ; RUN: llc -relocation-model=pic -filetype=obj %s -o %t.o -; RUN: wasm-ld -shared -o %t.wasm %t.o +; RUN: wasm-ld --emscripten -shared -o %t.wasm %t.o ; RUN: obj2yaml %t.wasm | FileCheck %s -target triple = "wasm32-unknown-unknown" +target triple = "wasm32-unknown-emscripten" @data = hidden global i32 2, align 4 @data_external = external global i32 Index: test/wasm/stack-first.test =================================================================== --- test/wasm/stack-first.test +++ test/wasm/stack-first.test @@ -8,6 +8,10 @@ RUN: wasm-ld -z stack-size=512 --stack-first --allow-undefined -o %t.wasm %t.o RUN: obj2yaml %t.wasm | FileCheck %s +; Same thing, now with --emscripten. +RUN: wasm-ld --emscripten -z stack-size=512 --stack-first --allow-undefined -o %t.wasm %t.o +RUN: obj2yaml %t.wasm | FileCheck %s --check-prefixes=CHECK,EMSCRIPTEN + CHECK: - Type: GLOBAL CHECK-NEXT: Globals: CHECK-NEXT: - Index: 0 @@ -16,27 +20,27 @@ CHECK-NEXT: InitExpr: CHECK-NEXT: Opcode: I32_CONST CHECK-NEXT: Value: 512 -CHECK-NEXT: - Index: 1 -CHECK-NEXT: Type: I32 -CHECK-NEXT: Mutable: false -CHECK-NEXT: InitExpr: -CHECK-NEXT: Opcode: I32_CONST -CHECK-NEXT: Value: 512 -CHECK-NEXT: - Index: 2 -CHECK-NEXT: Type: I32 -CHECK-NEXT: Mutable: false -CHECK-NEXT: InitExpr: -CHECK-NEXT: Opcode: I32_CONST -CHECK-NEXT: Value: 512 +EMSCRIPTEN-NEXT: - Index: 1 +EMSCRIPTEN-NEXT: Type: I32 +EMSCRIPTEN-NEXT: Mutable: false +EMSCRIPTEN-NEXT: InitExpr: +EMSCRIPTEN-NEXT: Opcode: I32_CONST +EMSCRIPTEN-NEXT: Value: 512 +EMSCRIPTEN-NEXT: - Index: 2 +EMSCRIPTEN-NEXT: Type: I32 +EMSCRIPTEN-NEXT: Mutable: false +EMSCRIPTEN-NEXT: InitExpr: +EMSCRIPTEN-NEXT: Opcode: I32_CONST +EMSCRIPTEN-NEXT: Value: 512 CHECK-NEXT: - Type: EXPORT CHECK-NEXT: Exports: CHECK-NEXT: - Name: memory CHECK-NEXT: Kind: MEMORY CHECK-NEXT: Index: 0 -CHECK-NEXT: - Name: __heap_base -CHECK-NEXT: Kind: GLOBAL -CHECK-NEXT: Index: 1 -CHECK-NEXT: - Name: __data_end -CHECK-NEXT: Kind: GLOBAL -CHECK-NEXT: Index: 2 +EMSCRIPTEN-NEXT: - Name: __heap_base +EMSCRIPTEN-NEXT: Kind: GLOBAL +EMSCRIPTEN-NEXT: Index: 1 +EMSCRIPTEN-NEXT: - Name: __data_end +EMSCRIPTEN-NEXT: Kind: GLOBAL +EMSCRIPTEN-NEXT: Index: 2 Index: test/wasm/undefined-data.ll =================================================================== --- test/wasm/undefined-data.ll +++ test/wasm/undefined-data.ll @@ -1,7 +1,7 @@ ; RUN: llc -filetype=obj %s -o %t.o ; RUN: not wasm-ld -o %t.wasm %t.o 2>&1 | FileCheck %s -check-prefix=UNDEF ; RUN: not wasm-ld --allow-undefined -o %t.wasm %t.o 2>&1 | FileCheck %s -check-prefix=ALLOW -; RUN: not wasm-ld --shared -o %t.wasm %t.o 2>&1 | FileCheck %s -check-prefix=SHARED +; RUN: not wasm-ld --emscripten --shared -o %t.wasm %t.o 2>&1 | FileCheck %s -check-prefix=SHARED target triple = "wasm32-unknown-unknown" Index: test/wasm/undefined-weak-call.ll =================================================================== --- test/wasm/undefined-weak-call.ll +++ test/wasm/undefined-weak-call.ll @@ -1,8 +1,14 @@ ; RUN: llc -filetype=obj %s -o %t.o + ; RUN: wasm-ld --entry=callWeakFuncs --print-gc-sections %t.o \ ; RUN: -o %t.wasm 2>&1 | FileCheck -check-prefix=CHECK-GC %s ; RUN: obj2yaml %t.wasm | FileCheck %s +; Test with --emscripten +; RUN: wasm-ld --emscripten --entry=callWeakFuncs --print-gc-sections %t.o \ +; RUN: -o %t.wasm +; RUN: obj2yaml %t.wasm | FileCheck %s --check-prefixes=CHECK,EMSCRIPTEN + ; Check that calling an undefined weak function generates an appropriate stub ; that will fail at runtime with "unreachable". @@ -61,29 +67,29 @@ ; CHECK-NEXT: InitExpr: ; CHECK-NEXT: Opcode: I32_CONST ; CHECK-NEXT: Value: 66560 -; CHECK-NEXT: - Index: 1 -; CHECK-NEXT: Type: I32 -; CHECK-NEXT: Mutable: false -; CHECK-NEXT: InitExpr: -; CHECK-NEXT: Opcode: I32_CONST -; CHECK-NEXT: Value: 66560 -; CHECK-NEXT: - Index: 2 -; CHECK-NEXT: Type: I32 -; CHECK-NEXT: Mutable: false -; CHECK-NEXT: InitExpr: -; CHECK-NEXT: Opcode: I32_CONST -; CHECK-NEXT: Value: 1024 +; EMSCRIPTEN-NEXT: - Index: 1 +; EMSCRIPTEN-NEXT: Type: I32 +; EMSCRIPTEN-NEXT: Mutable: false +; EMSCRIPTEN-NEXT: InitExpr: +; EMSCRIPTEN-NEXT: Opcode: I32_CONST +; EMSCRIPTEN-NEXT: Value: 66560 +; EMSCRIPTEN-NEXT: - Index: 2 +; EMSCRIPTEN-NEXT: Type: I32 +; EMSCRIPTEN-NEXT: Mutable: false +; EMSCRIPTEN-NEXT: InitExpr: +; EMSCRIPTEN-NEXT: Opcode: I32_CONST +; EMSCRIPTEN-NEXT: Value: 1024 ; CHECK-NEXT: - Type: EXPORT ; CHECK-NEXT: Exports: ; CHECK-NEXT: - Name: memory ; CHECK-NEXT: Kind: MEMORY ; CHECK-NEXT: Index: 0 -; CHECK-NEXT: - Name: __heap_base -; CHECK-NEXT: Kind: GLOBAL -; CHECK-NEXT: Index: 1 -; CHECK-NEXT: - Name: __data_end -; CHECK-NEXT: Kind: GLOBAL -; CHECK-NEXT: Index: 2 +; EMSCRIPTEN-NEXT: - Name: __heap_base +; EMSCRIPTEN-NEXT: Kind: GLOBAL +; EMSCRIPTEN-NEXT: Index: 1 +; EMSCRIPTEN-NEXT: - Name: __data_end +; EMSCRIPTEN-NEXT: Kind: GLOBAL +; EMSCRIPTEN-NEXT: Index: 2 ; CHECK-NEXT: - Name: callWeakFuncs ; CHECK-NEXT: Kind: FUNCTION ; CHECK-NEXT: Index: 3 Index: test/wasm/visibility-hidden.ll =================================================================== --- test/wasm/visibility-hidden.ll +++ test/wasm/visibility-hidden.ll @@ -43,12 +43,6 @@ ; CHECK-NEXT: - Name: memory ; CHECK-NEXT: Kind: MEMORY ; CHECK-NEXT: Index: 0 -; CHECK-NEXT: - Name: __heap_base -; CHECK-NEXT: Kind: GLOBAL -; CHECK-NEXT: Index: 1 -; CHECK-NEXT: - Name: __data_end -; CHECK-NEXT: Kind: GLOBAL -; CHECK-NEXT: Index: 2 ; CHECK-NEXT: - Name: objectDefault ; CHECK-NEXT: Kind: FUNCTION ; CHECK-NEXT: Index: 1 @@ -66,12 +60,6 @@ ; NO-DEFAULT-NEXT: - Name: memory ; NO-DEFAULT-NEXT: Kind: MEMORY ; NO-DEFAULT-NEXT: Index: 0 -; NO-DEFAULT-NEXT: - Name: __heap_base -; NO-DEFAULT-NEXT: Kind: GLOBAL -; NO-DEFAULT-NEXT: Index: 1 -; NO-DEFAULT-NEXT: - Name: __data_end -; NO-DEFAULT-NEXT: Kind: GLOBAL -; NO-DEFAULT-NEXT: Index: 2 ; NO-DEFAULT-NEXT: - Name: _start ; NO-DEFAULT-NEXT: Kind: FUNCTION ; NO-DEFAULT-NEXT: Index: 2 Index: test/wasm/weak-alias-overide.ll =================================================================== --- test/wasm/weak-alias-overide.ll +++ test/wasm/weak-alias-overide.ll @@ -51,29 +51,11 @@ ; CHECK-NEXT: InitExpr: ; CHECK-NEXT: Opcode: I32_CONST ; CHECK-NEXT: Value: 66560 -; CHECK-NEXT: - Index: 1 -; CHECK-NEXT: Type: I32 -; CHECK-NEXT: Mutable: false -; CHECK-NEXT: InitExpr: -; CHECK-NEXT: Opcode: I32_CONST -; CHECK-NEXT: Value: 66560 -; CHECK-NEXT: - Index: 2 -; CHECK-NEXT: Type: I32 -; CHECK-NEXT: Mutable: false -; CHECK-NEXT: InitExpr: -; CHECK-NEXT: Opcode: I32_CONST -; CHECK-NEXT: Value: 1024 ; CHECK-NEXT: - Type: EXPORT ; CHECK-NEXT: Exports: ; CHECK-NEXT: - Name: memory ; CHECK-NEXT: Kind: MEMORY ; CHECK-NEXT: Index: 0 -; CHECK-NEXT: - Name: __heap_base -; CHECK-NEXT: Kind: GLOBAL -; CHECK-NEXT: Index: 1 -; CHECK-NEXT: - Name: __data_end -; CHECK-NEXT: Kind: GLOBAL -; CHECK-NEXT: Index: 2 ; CHECK-NEXT: - Name: alias_fn ; CHECK-NEXT: Kind: FUNCTION ; CHECK-NEXT: Index: 0 Index: test/wasm/weak-alias.ll =================================================================== --- test/wasm/weak-alias.ll +++ test/wasm/weak-alias.ll @@ -48,29 +48,11 @@ ; CHECK-NEXT: InitExpr: ; CHECK-NEXT: Opcode: I32_CONST ; CHECK-NEXT: Value: 66560 -; CHECK-NEXT: - Index: 1 -; CHECK-NEXT: Type: I32 -; CHECK-NEXT: Mutable: false -; CHECK-NEXT: InitExpr: -; CHECK-NEXT: Opcode: I32_CONST -; CHECK-NEXT: Value: 66560 -; CHECK-NEXT: - Index: 2 -; CHECK-NEXT: Type: I32 -; CHECK-NEXT: Mutable: false -; CHECK-NEXT: InitExpr: -; CHECK-NEXT: Opcode: I32_CONST -; CHECK-NEXT: Value: 1024 ; CHECK-NEXT: - Type: EXPORT ; CHECK-NEXT: Exports: ; CHECK-NEXT: - Name: memory ; CHECK-NEXT: Kind: MEMORY ; CHECK-NEXT: Index: 0 -; CHECK-NEXT: - Name: __heap_base -; CHECK-NEXT: Kind: GLOBAL -; CHECK-NEXT: Index: 1 -; CHECK-NEXT: - Name: __data_end -; CHECK-NEXT: Kind: GLOBAL -; CHECK-NEXT: Index: 2 ; CHECK-NEXT: - Name: _start ; CHECK-NEXT: Kind: FUNCTION ; CHECK-NEXT: Index: 0 Index: test/wasm/weak-symbols.ll =================================================================== --- test/wasm/weak-symbols.ll +++ test/wasm/weak-symbols.ll @@ -53,30 +53,12 @@ ; CHECK-NEXT: Mutable: false ; CHECK-NEXT: InitExpr: ; CHECK-NEXT: Opcode: I32_CONST -; CHECK-NEXT: Value: 66576 -; CHECK-NEXT: - Index: 2 -; CHECK-NEXT: Type: I32 -; CHECK-NEXT: Mutable: false -; CHECK-NEXT: InitExpr: -; CHECK-NEXT: Opcode: I32_CONST -; CHECK-NEXT: Value: 1028 -; CHECK-NEXT: - Index: 3 -; CHECK-NEXT: Type: I32 -; CHECK-NEXT: Mutable: false -; CHECK-NEXT: InitExpr: -; CHECK-NEXT: Opcode: I32_CONST ; CHECK-NEXT: Value: 1024 ; CHECK-NEXT: - Type: EXPORT ; CHECK-NEXT: Exports: ; CHECK-NEXT: - Name: memory ; CHECK-NEXT: Kind: MEMORY ; CHECK-NEXT: Index: 0 -; CHECK-NEXT: - Name: __heap_base -; CHECK-NEXT: Kind: GLOBAL -; CHECK-NEXT: Index: 1 -; CHECK-NEXT: - Name: __data_end -; CHECK-NEXT: Kind: GLOBAL -; CHECK-NEXT: Index: 2 ; CHECK-NEXT: - Name: _start ; CHECK-NEXT: Kind: FUNCTION ; CHECK-NEXT: Index: 0 @@ -88,7 +70,7 @@ ; CHECK-NEXT: Index: 2 ; CHECK-NEXT: - Name: weakGlobal ; CHECK-NEXT: Kind: GLOBAL -; CHECK-NEXT: Index: 3 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: - Name: exportWeak2 ; CHECK-NEXT: Kind: FUNCTION ; CHECK-NEXT: Index: 3 Index: test/wasm/weak-undefined.ll =================================================================== --- test/wasm/weak-undefined.ll +++ test/wasm/weak-undefined.ll @@ -1,7 +1,12 @@ ; RUN: llc -filetype=obj -o %t.o %s + ; RUN: wasm-ld -strip-debug %t.o -o %t.wasm ; RUN: obj2yaml %t.wasm | FileCheck %s +; Same thing, now with --emscripten +; RUN: wasm-ld --emscripten -strip-debug %t.o -o %t.wasm +; RUN: obj2yaml %t.wasm | FileCheck %s --check-prefixes=CHECK,EMSCRIPTEN + ; Test that undefined weak externals (global_var) and (foo) don't cause ; link failures and resolve to zero. @@ -59,29 +64,29 @@ ; CHECK-NEXT: InitExpr: ; CHECK-NEXT: Opcode: I32_CONST ; CHECK-NEXT: Value: 66560 -; CHECK-NEXT: - Index: 1 -; CHECK-NEXT: Type: I32 -; CHECK-NEXT: Mutable: false -; CHECK-NEXT: InitExpr: -; CHECK-NEXT: Opcode: I32_CONST -; CHECK-NEXT: Value: 66560 -; CHECK-NEXT: - Index: 2 -; CHECK-NEXT: Type: I32 -; CHECK-NEXT: Mutable: false -; CHECK-NEXT: InitExpr: -; CHECK-NEXT: Opcode: I32_CONST -; CHECK-NEXT: Value: 1024 +; EMSCRIPTEN-NEXT: - Index: 1 +; EMSCRIPTEN-NEXT: Type: I32 +; EMSCRIPTEN-NEXT: Mutable: false +; EMSCRIPTEN-NEXT: InitExpr: +; EMSCRIPTEN-NEXT: Opcode: I32_CONST +; EMSCRIPTEN-NEXT: Value: 66560 +; EMSCRIPTEN-NEXT: - Index: 2 +; EMSCRIPTEN-NEXT: Type: I32 +; EMSCRIPTEN-NEXT: Mutable: false +; EMSCRIPTEN-NEXT: InitExpr: +; EMSCRIPTEN-NEXT: Opcode: I32_CONST +; EMSCRIPTEN-NEXT: Value: 1024 ; CHECK-NEXT: - Type: EXPORT ; CHECK-NEXT: Exports: ; CHECK-NEXT: - Name: memory ; CHECK-NEXT: Kind: MEMORY ; CHECK-NEXT: Index: 0 -; CHECK-NEXT: - Name: __heap_base -; CHECK-NEXT: Kind: GLOBAL -; CHECK-NEXT: Index: 1 -; CHECK-NEXT: - Name: __data_end -; CHECK-NEXT: Kind: GLOBAL -; CHECK-NEXT: Index: 2 +; EMSCRIPTEN-NEXT: - Name: __heap_base +; EMSCRIPTEN-NEXT: Kind: GLOBAL +; EMSCRIPTEN-NEXT: Index: 1 +; EMSCRIPTEN-NEXT: - Name: __data_end +; EMSCRIPTEN-NEXT: Kind: GLOBAL +; EMSCRIPTEN-NEXT: Index: 2 ; CHECK-NEXT: - Name: _start ; CHECK-NEXT: Kind: FUNCTION ; CHECK-NEXT: Index: 2 Index: wasm/Config.h =================================================================== --- wasm/Config.h +++ wasm/Config.h @@ -27,6 +27,7 @@ bool CompressRelocations; bool Demangle; bool DisableVerify; + bool Emscripten; bool EmitRelocs; bool ExportAll; bool ExportDynamic; Index: wasm/Driver.cpp =================================================================== --- wasm/Driver.cpp +++ wasm/Driver.cpp @@ -338,6 +338,7 @@ parseCachePruningPolicy(Args.getLastArgValue(OPT_thinlto_cache_policy)), "--thinlto-cache-policy: invalid cache policy"); Config->ThinLTOJobs = args::getInteger(Args, OPT_thinlto_jobs, -1u); + Config->Emscripten = Args.hasArg(OPT_emscripten); errorHandler().Verbose = Args.hasArg(OPT_verbose); LLVM_DEBUG(errorHandler().Verbose = true); ThreadsEnabled = Args.hasFlag(OPT_threads, OPT_no_threads, true); @@ -370,6 +371,8 @@ } if (Config->Shared) { + // -shared is only supported in Emscripten mode, where it means the + // following options: Config->ImportMemory = true; Config->ExportDynamic = true; Config->AllowUndefined = true; @@ -411,6 +414,13 @@ if (Config->Pie) error("-r and -pie may not be used together"); } + + if (!Config->Emscripten) { + if (Config->Shared) + error("-shared is currently only supported under Emscripten"); + if (Config->Pie) + error("-pie is currently only supported under Emscripten"); + } } // Force Sym to be entered in the output. Used for -u or equivalent. @@ -481,13 +491,18 @@ // See: https://github.com/WebAssembly/mutable-global WasmSym::StackPointer = Symtab->addSyntheticGlobal( "__stack_pointer", WASM_SYMBOL_VISIBILITY_HIDDEN, StackPointer); - WasmSym::HeapBase = Symtab->addSyntheticDataSymbol("__heap_base", 0); - WasmSym::DataEnd = Symtab->addSyntheticDataSymbol("__data_end", 0); - - // These two synthetic symbols exist purely for the embedder so we always - // want to export them. - WasmSym::HeapBase->ForceExport = true; - WasmSym::DataEnd->ForceExport = true; + WasmSym::HeapBase = + Symtab->addSyntheticDataSymbol("__heap_base", + WASM_SYMBOL_VISIBILITY_HIDDEN); + WasmSym::DataEnd = + Symtab->addSyntheticDataSymbol("__data_end", + WASM_SYMBOL_VISIBILITY_HIDDEN); + + if (Config->Emscripten) { + // Emscripten requires these symbols be exported. + WasmSym::HeapBase->ForceExport = true; + WasmSym::DataEnd->ForceExport = true; + } } if (Config->Pic) { Index: wasm/LTO.cpp =================================================================== --- wasm/LTO.cpp +++ wasm/LTO.cpp @@ -105,6 +105,7 @@ // be removed. R.Prevailing = !ObjSym.isUndefined() && Sym->getFile() == &F; R.VisibleToRegularObj = Config->Relocatable || Sym->IsUsedInRegularObj || + Sym->isImplicitlyUsed() || (R.Prevailing && Sym->isExported()); if (R.Prevailing) undefine(Sym); Index: wasm/MarkLive.cpp =================================================================== --- wasm/MarkLive.cpp +++ wasm/MarkLive.cpp @@ -64,7 +64,7 @@ // We need to preserve any exported symbol for (Symbol *Sym : Symtab->getSymbols()) - if (Sym->isExported()) + if (Sym->isImplicitlyUsed() || Sym->isExported()) Enqueue(Sym); // For relocatable output, we need to preserve all the ctor functions Index: wasm/Options.td =================================================================== --- wasm/Options.td +++ wasm/Options.td @@ -34,8 +34,8 @@ def emit_relocs: F<"emit-relocs">, HelpText<"Generate relocations in output">; defm export_dynamic: B<"export-dynamic", - "Put symbols in the dynamic symbol table", - "Do not put symbols in the dynamic symbol table (default)">; + "Export all global symbols with visibility \"default\"", + "Do not automatically export global symbols with visibility \"default\" (default)">; def entry: S<"entry">, MetaVarName<"">, HelpText<"Name of entry point symbol">; @@ -158,6 +158,9 @@ def stack_first: F<"stack-first">, HelpText<"Place stack at start of linear memory rather than after data">; +def emscripten: F<"emscripten">, + HelpText<"Enable Emscripten support">; + defm whole_archive: B<"whole-archive", "Force load of all members in a static library", "Do not force load of all members in a static library (default)">; Index: wasm/Symbols.h =================================================================== --- wasm/Symbols.h +++ wasm/Symbols.h @@ -104,6 +104,10 @@ WasmSymbolType getWasmType() const; bool isExported() const; + // Indicates that the symbol is used in an __attribute__((used)) directive + // or similar. + bool isImplicitlyUsed() const; + // True if the symbol was used for linking and thus need to be added to the // output file's symbol table. This is true for all symbols except for // unreferenced DSO symbols, lazy (archive) symbols, and bitcode symbols that Index: wasm/Symbols.cpp =================================================================== --- wasm/Symbols.cpp +++ wasm/Symbols.cpp @@ -138,6 +138,10 @@ return Flags & WASM_SYMBOL_EXPORTED; } +bool Symbol::isImplicitlyUsed() const { + return Flags & WASM_SYMBOL_IMPLICITLY_USED; +} + uint32_t FunctionSymbol::getFunctionIndex() const { if (auto *F = dyn_cast(this)) return F->Function->getFunctionIndex();