[lld] r370965 - [WebAssembly] Initialize memory in start function
Thomas Lively via llvm-commits
llvm-commits at lists.llvm.org
Wed Sep 4 12:50:39 PDT 2019
Author: tlively
Date: Wed Sep 4 12:50:39 2019
New Revision: 370965
URL: http://llvm.org/viewvc/llvm-project?rev=370965&view=rev
Log:
[WebAssembly] Initialize memory in start function
Summary:
- `__wasm_init_memory` is now the WebAssembly start function instead
of being called from `__wasm_call_ctors` or called directly by the
runtime.
- Adds a new synthetic data symbol `__wasm_init_memory_flag` that is
atomically incremented from zero to one by the thread responsible
for initializing memory.
- All threads now unconditionally perform data.drop on all passive
segments.
- Removes --passive-segments and --active-segments flags and controls
segment type based on --shared-memory instead. The deleted flags
were only present to ameliorate the upgrade path in Emscripten.
Reviewers: sbc100, aheejin
Subscribers: dschuff, jgravelle-google, sunfish, jfb, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D65783
Modified:
lld/trunk/test/wasm/data-layout.ll
lld/trunk/test/wasm/data-segment-merging.ll
lld/trunk/test/wasm/data-segments.ll
lld/trunk/test/wasm/import-memory.test
lld/trunk/test/wasm/no-tls.test
lld/trunk/test/wasm/relocatable.ll
lld/trunk/test/wasm/shared-memory.yaml
lld/trunk/test/wasm/tls-align.ll
lld/trunk/test/wasm/tls.ll
lld/trunk/wasm/Config.h
lld/trunk/wasm/Driver.cpp
lld/trunk/wasm/MarkLive.cpp
lld/trunk/wasm/Options.td
lld/trunk/wasm/Symbols.cpp
lld/trunk/wasm/Symbols.h
lld/trunk/wasm/SyntheticSections.cpp
lld/trunk/wasm/SyntheticSections.h
lld/trunk/wasm/Writer.cpp
lld/trunk/wasm/WriterUtils.cpp
lld/trunk/wasm/WriterUtils.h
Modified: lld/trunk/test/wasm/data-layout.ll
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/data-layout.ll?rev=370965&r1=370964&r2=370965&view=diff
==============================================================================
--- lld/trunk/test/wasm/data-layout.ll (original)
+++ lld/trunk/test/wasm/data-layout.ll Wed Sep 4 12:50:39 2019
@@ -75,8 +75,8 @@ target triple = "wasm32-unknown-unknown"
; CHECK-MAX-NEXT: Maximum: 0x00000002
; RUN: wasm-ld -no-gc-sections --allow-undefined --no-entry --shared-memory \
-; RUN: --initial-memory=131072 --max-memory=131072 -o %t_max.wasm %t.o \
-; RUN: --active-segments %t.hello.o
+; RUN: --features=atomics,bulk-memory --initial-memory=131072 \
+; RUN: --max-memory=131072 -o %t_max.wasm %t.o %t.hello.o
; RUN: obj2yaml %t_max.wasm | FileCheck %s -check-prefix=CHECK-SHARED
; CHECK-SHARED: - Type: MEMORY
Modified: lld/trunk/test/wasm/data-segment-merging.ll
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/data-segment-merging.ll?rev=370965&r1=370964&r2=370965&view=diff
==============================================================================
--- lld/trunk/test/wasm/data-segment-merging.ll (original)
+++ lld/trunk/test/wasm/data-segment-merging.ll Wed Sep 4 12:50:39 2019
@@ -8,7 +8,8 @@ target triple = "wasm32-unknown-unknown"
@e = private constant [9 x i8] c"constant\00", align 1
@f = private constant i8 43, align 4
-; RUN: llc -mattr=+bulk-memory -filetype=obj %s -o %t.o
+; RUN: llc -mattr=+bulk-memory,+atomics -filetype=obj %s -o %t.passive.o
+; RUN: llc -filetype=obj %s -o %t.o
; RUN: wasm-ld -no-gc-sections --no-entry -o %t.merged.wasm %t.o
; RUN: obj2yaml %t.merged.wasm | FileCheck %s --check-prefix=MERGE
@@ -67,7 +68,7 @@ target triple = "wasm32-unknown-unknown"
; SEPARATE-NEXT: Name: __wasm_call_ctors
; SEPARATE-NOT: - Index:
-; RUN: wasm-ld -no-gc-sections --no-entry --passive-segments -o %t.merged.passive.wasm %t.o
+; RUN: wasm-ld -no-gc-sections --no-entry --shared-memory --max-memory=131072 -o %t.merged.passive.wasm %t.passive.o
; RUN: obj2yaml %t.merged.passive.wasm | FileCheck %s --check-prefix=PASSIVE-MERGE
; PASSIVE-MERGE-LABEL: - Type: DATACOUNT
@@ -87,9 +88,10 @@ target triple = "wasm32-unknown-unknown"
; PASSIVE-MERGE-NEXT: Name: __wasm_call_ctors
; PASSIVE-MERGE-NEXT: - Index: 1
; PASSIVE-MERGE-NEXT: Name: __wasm_init_memory
-; PASSIVE-MERGE-NOT: - Index:
+; PASSIVE-MERGE-NEXT: - Index: 2
+; PASSIVE-MERGE-NEXT: Name: __wasm_init_tls
-; RUN: wasm-ld -no-gc-sections --no-entry --passive-segments -no-merge-data-segments -o %t.separate.passive.wasm %t.o
+; RUN: wasm-ld -no-gc-sections --no-entry --shared-memory --max-memory=131072 -no-merge-data-segments -o %t.separate.passive.wasm %t.passive.o
; RUN: obj2yaml %t.separate.passive.wasm | FileCheck %s --check-prefix=PASSIVE-SEPARATE
; PASSIVE-SEPARATE-LABEL: - Type: DATACOUNT
@@ -121,4 +123,5 @@ target triple = "wasm32-unknown-unknown"
; PASSIVE-SEPARATE-NEXT: Name: __wasm_call_ctors
; PASSIVE-SEPARATE-NEXT: - Index: 1
; PASSIVE-SEPARATE-NEXT: Name: __wasm_init_memory
-; PASSIVE-SEPARATE-NOT: - Index
+; PASSIVE-SEPARATE-NEXT: - Index: 2
+; PASSIVE-SEPARATE-NEXT: Name: __wasm_init_tls
Modified: lld/trunk/test/wasm/data-segments.ll
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/data-segments.ll?rev=370965&r1=370964&r2=370965&view=diff
==============================================================================
--- lld/trunk/test/wasm/data-segments.ll (original)
+++ lld/trunk/test/wasm/data-segments.ll Wed Sep 4 12:50:39 2019
@@ -2,39 +2,16 @@
; RUN: llc -filetype=obj %s -o %t.bulk-mem.o -mattr=+bulk-memory
; RUN: llc -filetype=obj %s -o %t.atomics.bulk-mem.o -mattr=+atomics,+bulk-memory
-; atomics => error
+; atomics, shared memory => error
; RUN: not wasm-ld -no-gc-sections --no-entry --shared-memory --max-memory=131072 %t.atomics.o -o %t.atomics.wasm 2>&1 | FileCheck %s --check-prefix ERROR
-; atomics, active segments => active segments
-; RUN: wasm-ld -no-gc-sections --no-entry --shared-memory --max-memory=131072 --active-segments %t.atomics.o -o %t.atomics.active.wasm
-; RUN: obj2yaml %t.atomics.active.wasm | FileCheck %s --check-prefixes ACTIVE,ACTIVE-TLS
-
-; atomics, passive segments => error
-; RUN: not wasm-ld -no-gc-sections --no-entry --shared-memory --max-memory=131072 --passive-segments %t.atomics.o -o %t.atomics.passive.wasm 2>&1 | FileCheck %s --check-prefix ERROR
-
-; bulk memory => active segments
+; bulk memory, unshared memory => active segments
; RUN: wasm-ld -no-gc-sections --no-entry %t.bulk-mem.o -o %t.bulk-mem.wasm
; RUN: obj2yaml %t.bulk-mem.wasm | FileCheck %s --check-prefix ACTIVE
-; bulk-memory, active segments => active segments
-; RUN: wasm-ld -no-gc-sections --no-entry --active-segments %t.bulk-mem.o -o %t.bulk-mem.active.wasm
-; RUN: obj2yaml %t.bulk-mem.active.wasm | FileCheck %s --check-prefix ACTIVE
-
-; bulk memory, passive segments => passive segments
-; RUN: wasm-ld -no-gc-sections --no-entry --passive-segments %t.bulk-mem.o -o %t.bulk-mem.passive.wasm
-; RUN: obj2yaml %t.bulk-mem.passive.wasm | FileCheck %s --check-prefix PASSIVE
-
-; atomics, bulk memory => passive segments
+; atomics, bulk memory, shared memory => passive segments
; RUN: wasm-ld -no-gc-sections --no-entry --shared-memory --max-memory=131072 %t.atomics.bulk-mem.o -o %t.atomics.bulk-mem.wasm
-; RUN: obj2yaml %t.atomics.bulk-mem.wasm | FileCheck %s --check-prefixes PASSIVE,PASSIVE-TLS
-
-; atomics, bulk memory, active segments => active segments
-; RUN: wasm-ld -no-gc-sections --no-entry --shared-memory --max-memory=131072 --active-segments %t.atomics.bulk-mem.o -o %t.atomics.bulk-mem.active.wasm
-; RUN: obj2yaml %t.atomics.bulk-mem.active.wasm | FileCheck %s --check-prefixes ACTIVE,ACTIVE-TLS
-
-; atomics, bulk memory, passive segments => passive segments
-; RUN: wasm-ld -no-gc-sections --no-entry --shared-memory --max-memory=131072 --passive-segments %t.atomics.bulk-mem.o -o %t.atomics.bulk-mem.passive.wasm
-; RUN: obj2yaml %t.atomics.bulk-mem.passive.wasm | FileCheck %s --check-prefixes PASSIVE,PASSIVE-TLS
+; RUN: obj2yaml %t.atomics.bulk-mem.wasm | FileCheck %s --check-prefixes PASSIVE
target triple = "wasm32-unknown-unknown"
@@ -46,16 +23,13 @@ target triple = "wasm32-unknown-unknown"
@e = private constant [9 x i8] c"constant\00", align 1
@f = private constant i8 43, align 4
-; ERROR: 'bulk-memory' feature must be used in order to emit passive segments
+; ERROR: 'bulk-memory' feature must be used in order to use shared memory
; ACTIVE-LABEL: - Type: CODE
; ACTIVE-NEXT: Functions:
; ACTIVE-NEXT: - Index: 0
; ACTIVE-NEXT: Locals: []
; ACTIVE-NEXT: Body: 0B
-; ACTIVE-TLS-NEXT: - Index: 1
-; ACTIVE-TLS-NEXT: Locals: []
-; ACTIVE-TLS-NEXT: Body: 0B
; ACTIVE-NEXT: - Type: DATA
; ACTIVE-NEXT: Segments:
; ACTIVE-NEXT: - SectionOffset: 7
@@ -82,20 +56,20 @@ target triple = "wasm32-unknown-unknown"
; ACTIVE-NEXT: FunctionNames:
; ACTIVE-NEXT: - Index: 0
; ACTIVE-NEXT: Name: __wasm_call_ctors
-; ACTIVE-TLS-NEXT: - Index: 1
-; ACTIVE-TLS-NEXT: Name: __wasm_init_tls
+; PASSIVE-LABEL: - Type: START
+; PASSIVE-NEXT: StartFunction: 1
; PASSIVE-LABEL: - Type: CODE
; PASSIVE-NEXT: Functions:
; PASSIVE-NEXT: - Index: 0
; PASSIVE-NEXT: Locals: []
-; PASSIVE-NEXT: Body: 10010B
+; PASSIVE-NEXT: Body: 0B
; PASSIVE-NEXT: - Index: 1
; PASSIVE-NEXT: Locals: []
-; PASSIVE-NEXT: Body: 41800841004114FC080000FC090041940841004190CE00FC080100FC090141A4D6004100410DFC080200FC09020B
-; PASSIVE-TLS-NEXT: - Index: 2
-; PASSIVE-TLS-NEXT: Locals: []
-; PASSIVE-TLS-NEXT: Body: 0B
+; PASSIVE-NEXT: Body: 41B4D60041004101FE480200044041B4D6004101427FFE0102001A0541800841004114FC08000041940841004190CE00FC08010041A4D6004100410DFC08020041B4D6004102FE17020041B4D600417FFE0002001A0BFC0900FC0901FC09020B
+; PASSIVE-NEXT: - Index: 2
+; PASSIVE-NEXT: Locals: []
+; PASSIVE-NEXT: Body: 0B
; PASSIVE-NEXT: - Type: DATA
; PASSIVE-NEXT: Segments:
; PASSIVE-NEXT: - SectionOffset: 3
@@ -115,5 +89,5 @@ target triple = "wasm32-unknown-unknown"
; PASSIVE-NEXT: Name: __wasm_call_ctors
; PASSIVE-NEXT: - Index: 1
; PASSIVE-NEXT: Name: __wasm_init_memory
-; PASSIVE-TLS-NEXT: - Index: 2
-; PASSIVE-TLS-NEXT: Name: __wasm_init_tls
+; PASSIVE-NEXT: - Index: 2
+; PASSIVE-NEXT: Name: __wasm_init_tls
Modified: lld/trunk/test/wasm/import-memory.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/import-memory.test?rev=370965&r1=370964&r2=370965&view=diff
==============================================================================
--- lld/trunk/test/wasm/import-memory.test (original)
+++ lld/trunk/test/wasm/import-memory.test Wed Sep 4 12:50:39 2019
@@ -32,7 +32,7 @@
# CHECK-MAX-NEXT: Maximum: 0x00000005
# CHECK-MAX-NEXT: - Type:
-# RUN: wasm-ld --import-memory --shared-memory --active-segments \
+# RUN: wasm-ld --import-memory --shared-memory --features=atomics,bulk-memory \
# RUN: --initial-memory=262144 --max-memory=327680 -o %t.max.wasm %t.start.o
# RUN: obj2yaml %t.max.wasm | FileCheck -check-prefix=CHECK-SHARED %s
Modified: lld/trunk/test/wasm/no-tls.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/no-tls.test?rev=370965&r1=370964&r2=370965&view=diff
==============================================================================
--- lld/trunk/test/wasm/no-tls.test (original)
+++ lld/trunk/test/wasm/no-tls.test Wed Sep 4 12:50:39 2019
@@ -1,7 +1,7 @@
; Testing that __tls_size and __tls_align are correctly emitted when there are
; no thread_local variables.
-RUN: llc -mattr=+bulk-memory -filetype=obj %p/Inputs/start.ll -o %t.o
+RUN: llc -mattr=+bulk-memory,+atomics -filetype=obj %p/Inputs/start.ll -o %t.o
RUN: wasm-ld -no-gc-sections --shared-memory --max-memory=131072 --allow-undefined -o %t.wasm %t.o
RUN: obj2yaml %t.wasm | FileCheck %s
@@ -14,7 +14,7 @@ CHECK-NEXT: Type: I32
CHECK-NEXT: Mutable: true
CHECK-NEXT: InitExpr:
CHECK-NEXT: Opcode: I32_CONST
-CHECK-NEXT: Value: 66560
+CHECK-NEXT: Value: 66576
; __tls_base
CHECK-NEXT: - Index: 1
Modified: lld/trunk/test/wasm/relocatable.ll
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/relocatable.ll?rev=370965&r1=370964&r2=370965&view=diff
==============================================================================
--- lld/trunk/test/wasm/relocatable.ll (original)
+++ lld/trunk/test/wasm/relocatable.ll Wed Sep 4 12:50:39 2019
@@ -3,7 +3,7 @@
; RUN: wasm-ld -r -o %t.wasm %t.hello.o %t.o
; RUN: obj2yaml %t.wasm | FileCheck %s --check-prefixes CHECK,NORMAL
-; RUN: llc -filetype=obj %p/Inputs/hello.ll -o %t.hello.bm.o -mattr=+bulk-memory
+; RUN: llc -filetype=obj %p/Inputs/hello.ll -o %t.hello.bm.o -mattr=+bulk-memory,+atomics
; RUN: llc -filetype=obj %s -o %t.bm.o -mattr=+bulk-memory
; RUN: wasm-ld -r -o %t.mt.wasm %t.hello.bm.o %t.bm.o --shared-memory --max-memory=131072
; RUN: obj2yaml %t.mt.wasm | FileCheck %s --check-prefixes CHECK,SHARED
Modified: lld/trunk/test/wasm/shared-memory.yaml
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/shared-memory.yaml?rev=370965&r1=370964&r2=370965&view=diff
==============================================================================
--- lld/trunk/test/wasm/shared-memory.yaml (original)
+++ lld/trunk/test/wasm/shared-memory.yaml Wed Sep 4 12:50:39 2019
@@ -1,19 +1,16 @@
# RUN: yaml2obj %s -o %t1.o
-# RUN: not wasm-ld --no-entry --shared-memory --active-segments %t1.o -o - 2>&1 | FileCheck %s --check-prefix SHARED-NO-MAX
+# RUN: not wasm-ld --no-entry --shared-memory %t1.o -o - 2>&1 | FileCheck %s --check-prefix SHARED-NO-MAX
-# RUN: not wasm-ld --no-entry --shared-memory --active-segments --max-memory=100000 %t1.o -o - 2>&1 | FileCheck %s --check-prefix SHARED-UNALIGNED
+# RUN: not wasm-ld --no-entry --shared-memory --max-memory=100000 %t1.o -o - 2>&1 | FileCheck %s --check-prefix SHARED-UNALIGNED
-# RUN: wasm-ld --no-entry --shared-memory --active-segments --max-memory=131072 %t1.o -o - | obj2yaml | FileCheck %s --check-prefix SHARED
+# RUN: not wasm-ld --no-entry --shared-memory --max-memory=131072 --features=bulk-memory %t1.o -o - 2>&1 | FileCheck %s --check-prefix SHARED-NO-ATOMICS
-# RUN: not wasm-ld --no-entry --features=atomics %t1.o -o - 2>&1 | FileCheck %s --check-prefix ATOMICS-NO-SHARED
-
-# RUN: not wasm-ld --no-entry --features=atomics --shared-memory --active-segments %t1.o -o - 2>&1 | FileCheck %s --check-prefix ATOMICS-NO-MAX
-
-# RUN: not wasm-ld --no-entry --features=atomics --shared-memory --active-segments --max-memory=100000 %t1.o -o - 2>&1 | FileCheck %s --check-prefix ATOMICS-UNALIGNED
+# RUN: not wasm-ld --no-entry --shared-memory --max-memory=131072 --features=atomics %t1.o -o - 2>&1 | FileCheck %s --check-prefix SHARED-NO-BULK-MEM
-# RUN: wasm-ld --no-entry --features=atomics --shared-memory --active-segments --max-memory=131072 %t1.o -o - | obj2yaml | FileCheck %s --check-prefix SHARED
+# RUN: not wasm-ld --no-entry --features=atomics %t1.o -o - 2>&1 | FileCheck %s --check-prefix ATOMICS-NO-SHARED
+# RUN: wasm-ld --no-entry --shared-memory --max-memory=131072 --features=atomics,bulk-memory %t1.o -o - | obj2yaml | FileCheck %s --check-prefix SHARED
--- !WASM
FileHeader:
@@ -58,18 +55,18 @@ Sections:
Flags: [ ]
...
-# SHARED-NO-MAX: maximum memory too small, 66560 bytes needed{{$}}
+# SHARED-NO-MAX: maximum memory too small, 66576 bytes needed{{$}}
# SHARED-UNALIGNED: maximum memory must be 65536-byte aligned{{$}}
+# SHARED-NO-ATOMICS: 'atomics' feature must be used in order to use shared memory
+
+# SHARED-NO-BULK-MEM: 'bulk-memory' feature must be used in order to use shared memory
+
+# ATOMICS-NO-SHARED: 'atomics' feature is used, so --shared-memory must be used{{$}}
+
# SHARED: - Type: MEMORY
# SHARED-NEXT: Memories:
# SHARED-NEXT: - Flags: [ HAS_MAX, IS_SHARED ]
# SHARED-NEXT: Initial: 0x00000002
# SHARED-NEXT: Maximum: 0x00000002
-
-# ATOMICS-NO-SHARED: 'atomics' feature is used, so --shared-memory must be used{{$}}
-
-# ATOMICS-NO-MAX: maximum memory too small, 66560 bytes needed{{$}}
-
-# ATOMICS-UNALIGNED: maximum memory must be 65536-byte aligned{{$}}
Modified: lld/trunk/test/wasm/tls-align.ll
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/tls-align.ll?rev=370965&r1=370964&r2=370965&view=diff
==============================================================================
--- lld/trunk/test/wasm/tls-align.ll (original)
+++ lld/trunk/test/wasm/tls-align.ll Wed Sep 4 12:50:39 2019
@@ -1,4 +1,4 @@
-; RUN: llc -mattr=+bulk-memory -filetype=obj %s -o %t.o
+; RUN: llc -mattr=+bulk-memory,+atomics -filetype=obj %s -o %t.o
target triple = "wasm32-unknown-unknown"
Modified: lld/trunk/test/wasm/tls.ll
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/tls.ll?rev=370965&r1=370964&r2=370965&view=diff
==============================================================================
--- lld/trunk/test/wasm/tls.ll (original)
+++ lld/trunk/test/wasm/tls.ll Wed Sep 4 12:50:39 2019
@@ -1,4 +1,4 @@
-; RUN: llc -mattr=+bulk-memory -filetype=obj %s -o %t.o
+; RUN: llc -mattr=+bulk-memory,+atomics -filetype=obj %s -o %t.o
target triple = "wasm32-unknown-unknown"
Modified: lld/trunk/wasm/Config.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/Config.h?rev=370965&r1=370964&r2=370965&view=diff
==============================================================================
--- lld/trunk/wasm/Config.h (original)
+++ lld/trunk/wasm/Config.h Wed Sep 4 12:50:39 2019
@@ -35,7 +35,6 @@ struct Configuration {
bool gcSections;
bool importMemory;
bool sharedMemory;
- bool passiveSegments;
bool importTable;
bool mergeDataSegments;
bool pie;
Modified: lld/trunk/wasm/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/Driver.cpp?rev=370965&r1=370964&r2=370965&view=diff
==============================================================================
--- lld/trunk/wasm/Driver.cpp (original)
+++ lld/trunk/wasm/Driver.cpp Wed Sep 4 12:50:39 2019
@@ -319,8 +319,6 @@ static void readConfigs(opt::InputArgLis
args.hasFlag(OPT_fatal_warnings, OPT_no_fatal_warnings, false);
config->importMemory = args.hasArg(OPT_import_memory);
config->sharedMemory = args.hasArg(OPT_shared_memory);
- config->passiveSegments = args.hasFlag(
- OPT_passive_segments, OPT_active_segments, config->sharedMemory);
config->importTable = args.hasArg(OPT_import_table);
config->ltoo = args::getInteger(args, OPT_lto_O, 2);
config->ltoPartitions = args::getInteger(args, OPT_lto_partitions, 1);
@@ -473,21 +471,10 @@ static void createSyntheticSymbols() {
static llvm::wasm::WasmGlobalType globalTypeI32 = {WASM_TYPE_I32, false};
static llvm::wasm::WasmGlobalType mutableGlobalTypeI32 = {WASM_TYPE_I32,
true};
-
WasmSym::callCtors = symtab->addSyntheticFunction(
"__wasm_call_ctors", WASM_SYMBOL_VISIBILITY_HIDDEN,
make<SyntheticFunction>(nullSignature, "__wasm_call_ctors"));
- if (config->passiveSegments) {
- // Passive segments are used to avoid memory being reinitialized on each
- // thread's instantiation. These passive segments are initialized and
- // dropped in __wasm_init_memory, which is the first function called from
- // __wasm_call_ctors.
- WasmSym::initMemory = symtab->addSyntheticFunction(
- "__wasm_init_memory", WASM_SYMBOL_VISIBILITY_HIDDEN,
- make<SyntheticFunction>(nullSignature, "__wasm_init_memory"));
- }
-
if (config->isPic) {
// For PIC code we create a synthetic function __wasm_apply_relocs which
// is called from __wasm_call_ctors before the user-level constructors.
@@ -517,6 +504,15 @@ static void createSyntheticSymbols() {
}
if (config->sharedMemory && !config->shared) {
+ // Passive segments are used to avoid memory being reinitialized on each
+ // thread's instantiation. These passive segments are initialized and
+ // dropped in __wasm_init_memory, which is registered as the start function
+ WasmSym::initMemory = symtab->addSyntheticFunction(
+ "__wasm_init_memory", WASM_SYMBOL_VISIBILITY_HIDDEN,
+ make<SyntheticFunction>(nullSignature, "__wasm_init_memory"));
+ WasmSym::initMemoryFlag = symtab->addSyntheticDataSymbol(
+ "__wasm_init_memory_flag", WASM_SYMBOL_VISIBILITY_HIDDEN);
+ assert(WasmSym::initMemoryFlag);
WasmSym::tlsBase = createGlobalVariable("__tls_base", true, 0);
WasmSym::tlsSize = createGlobalVariable("__tls_size", false, 0);
WasmSym::tlsAlign = createGlobalVariable("__tls_align", false, 1);
Modified: lld/trunk/wasm/MarkLive.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/MarkLive.cpp?rev=370965&r1=370964&r2=370965&view=diff
==============================================================================
--- lld/trunk/wasm/MarkLive.cpp (original)
+++ lld/trunk/wasm/MarkLive.cpp Wed Sep 4 12:50:39 2019
@@ -50,8 +50,6 @@ void lld::wasm::markLive() {
// function. However, this function does not contain relocations so we
// have to manually mark the ctors as live if callCtors itself is live.
if (sym == WasmSym::callCtors) {
- if (config->passiveSegments)
- enqueue(WasmSym::initMemory);
if (config->isPic)
enqueue(WasmSym::applyRelocs);
for (const ObjFile *obj : symtab->objectFiles) {
@@ -86,6 +84,9 @@ void lld::wasm::markLive() {
if (config->isPic)
enqueue(WasmSym::callCtors);
+ if (config->sharedMemory && !config->shared)
+ enqueue(WasmSym::initMemory);
+
// Follow relocations to mark all reachable chunks.
while (!q.empty()) {
InputChunk *c = q.pop_back_val();
Modified: lld/trunk/wasm/Options.td
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/Options.td?rev=370965&r1=370964&r2=370965&view=diff
==============================================================================
--- lld/trunk/wasm/Options.td (original)
+++ lld/trunk/wasm/Options.td Wed Sep 4 12:50:39 2019
@@ -146,12 +146,6 @@ def import_memory: F<"import-memory">,
def shared_memory: F<"shared-memory">,
HelpText<"Use shared linear memory">;
-def active_segments: F<"active-segments">,
- HelpText<"Force segments to be active (default with unshared memory)">;
-
-def passive_segments: F<"passive-segments">,
- HelpText<"Force segments to be passive (default with shared memory)">;
-
def import_table: F<"import-table">,
HelpText<"Import function table from the environment">;
Modified: lld/trunk/wasm/Symbols.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/Symbols.cpp?rev=370965&r1=370964&r2=370965&view=diff
==============================================================================
--- lld/trunk/wasm/Symbols.cpp (original)
+++ lld/trunk/wasm/Symbols.cpp Wed Sep 4 12:50:39 2019
@@ -32,6 +32,7 @@ DefinedData *WasmSym::dsoHandle;
DefinedData *WasmSym::dataEnd;
DefinedData *WasmSym::globalBase;
DefinedData *WasmSym::heapBase;
+DefinedData *WasmSym::initMemoryFlag;
GlobalSymbol *WasmSym::stackPointer;
GlobalSymbol *WasmSym::tlsBase;
GlobalSymbol *WasmSym::tlsSize;
Modified: lld/trunk/wasm/Symbols.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/Symbols.h?rev=370965&r1=370964&r2=370965&view=diff
==============================================================================
--- lld/trunk/wasm/Symbols.h (original)
+++ lld/trunk/wasm/Symbols.h Wed Sep 4 12:50:39 2019
@@ -453,14 +453,18 @@ struct WasmSym {
// therefore be used as a backing store for brk()/malloc() implementations.
static DefinedData *heapBase;
- // __wasm_call_ctors
- // Function that directly calls all ctors in priority order.
- static DefinedFunction *callCtors;
+ // __wasm_init_memory_flag
+ // Symbol whose contents are nonzero iff memory has already been initialized.
+ static DefinedData *initMemoryFlag;
// __wasm_init_memory
- // Function that initializes passive data segments post-instantiation.
+ // Function that initializes passive data segments during instantiation.
static DefinedFunction *initMemory;
+ // __wasm_call_ctors
+ // Function that directly calls all ctors in priority order.
+ static DefinedFunction *callCtors;
+
// __wasm_apply_relocs
// Function that applies relocations to data segment post-instantiation.
static DefinedFunction *applyRelocs;
Modified: lld/trunk/wasm/SyntheticSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/SyntheticSections.cpp?rev=370965&r1=370964&r2=370965&view=diff
==============================================================================
--- lld/trunk/wasm/SyntheticSections.cpp (original)
+++ lld/trunk/wasm/SyntheticSections.cpp Wed Sep 4 12:50:39 2019
@@ -314,6 +314,15 @@ void ExportSection::writeBody() {
writeExport(os, export_);
}
+bool StartSection::isNeeded() const {
+ return !config->relocatable && numSegments && config->sharedMemory;
+}
+
+void StartSection::writeBody() {
+ raw_ostream &os = bodyOutputStream;
+ writeUleb128(os, WasmSym::initMemory->getFunctionIndex(), "function index");
+}
+
void ElemSection::addEntry(FunctionSymbol *sym) {
if (sym->hasTableIndex())
return;
@@ -350,7 +359,7 @@ void DataCountSection::writeBody() {
}
bool DataCountSection::isNeeded() const {
- return numSegments && config->passiveSegments;
+ return numSegments && config->sharedMemory;
}
static uint32_t getWasmFlags(const Symbol *sym) {
Modified: lld/trunk/wasm/SyntheticSections.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/SyntheticSections.h?rev=370965&r1=370964&r2=370965&view=diff
==============================================================================
--- lld/trunk/wasm/SyntheticSections.h (original)
+++ lld/trunk/wasm/SyntheticSections.h Wed Sep 4 12:50:39 2019
@@ -217,6 +217,18 @@ public:
std::vector<llvm::wasm::WasmExport> exports;
};
+class StartSection : public SyntheticSection {
+public:
+ StartSection(uint32_t numSegments)
+ : SyntheticSection(llvm::wasm::WASM_SEC_START), numSegments(numSegments) {
+ }
+ bool isNeeded() const override;
+ void writeBody() override;
+
+protected:
+ uint32_t numSegments;
+};
+
class ElemSection : public SyntheticSection {
public:
ElemSection()
@@ -327,6 +339,7 @@ struct OutStruct {
GlobalSection *globalSec;
EventSection *eventSec;
ExportSection *exportSec;
+ StartSection *startSec;
ElemSection *elemSec;
DataCountSection *dataCountSec;
LinkingSection *linkingSec;
Modified: lld/trunk/wasm/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/Writer.cpp?rev=370965&r1=370964&r2=370965&view=diff
==============================================================================
--- lld/trunk/wasm/Writer.cpp (original)
+++ lld/trunk/wasm/Writer.cpp Wed Sep 4 12:50:39 2019
@@ -254,6 +254,15 @@ void Writer::layoutMemory() {
}
}
+ // Make space for the memory initialization flag
+ if (WasmSym::initMemoryFlag) {
+ memoryPtr = alignTo(memoryPtr, 4);
+ WasmSym::initMemoryFlag->setVirtualAddress(memoryPtr);
+ log(formatv("mem: {0,-15} offset={1,-8} size={2,-8} align={3}",
+ "__wasm_init_memory_flag", memoryPtr, 4, 4));
+ memoryPtr += 4;
+ }
+
// TODO: Add .bss space here.
if (WasmSym::dataEnd)
WasmSym::dataEnd->setVirtualAddress(memoryPtr);
@@ -333,6 +342,7 @@ void Writer::addSections() {
addSection(out.globalSec);
addSection(out.eventSec);
addSection(out.exportSec);
+ addSection(out.startSec);
addSection(out.elemSec);
addSection(out.dataCountSec);
@@ -363,15 +373,15 @@ void Writer::populateTargetFeatures() {
StringMap<std::string> used;
StringMap<std::string> required;
StringMap<std::string> disallowed;
+ SmallSet<std::string, 8> &allowed = out.targetFeaturesSec->features;
bool tlsUsed = false;
// Only infer used features if user did not specify features
bool inferFeatures = !config->features.hasValue();
if (!inferFeatures) {
- for (auto &feature : config->features.getValue())
- out.targetFeaturesSec->features.insert(feature);
- // No need to read or check features
+ auto &explicitFeatures = config->features.getValue();
+ allowed.insert(explicitFeatures.begin(), explicitFeatures.end());
if (!config->checkFeatures)
return;
}
@@ -397,21 +407,20 @@ void Writer::populateTargetFeatures() {
}
}
- for (InputSegment *segment : file->segments) {
- if (!segment->live)
- continue;
+ // Find TLS data segments
+ auto isTLS = [](InputSegment *segment) {
StringRef name = segment->getName();
- if (name.startswith(".tdata") || name.startswith(".tbss"))
- tlsUsed = true;
- }
+ return segment->live &&
+ (name.startswith(".tdata") || name.startswith(".tbss"));
+ };
+ tlsUsed = tlsUsed ||
+ std::any_of(file->segments.begin(), file->segments.end(), isTLS);
}
if (inferFeatures)
- out.targetFeaturesSec->features.insert(used.keys().begin(),
- used.keys().end());
+ allowed.insert(used.keys().begin(), used.keys().end());
- if (out.targetFeaturesSec->features.count("atomics") &&
- !config->sharedMemory) {
+ if (allowed.count("atomics") && !config->sharedMemory) {
if (inferFeatures)
error(Twine("'atomics' feature is used by ") + used["atomics"] +
", so --shared-memory must be used");
@@ -426,18 +435,22 @@ void Writer::populateTargetFeatures() {
error("'atomics' feature is disallowed by " + disallowed["atomics"] +
", so --shared-memory must not be used");
- if (!used.count("bulk-memory") && config->passiveSegments)
- error("'bulk-memory' feature must be used in order to emit passive "
- "segments");
+ if (!allowed.count("atomics") && config->sharedMemory)
+ error("'atomics' feature must be used in order to use shared "
+ "memory");
+
+ if (!allowed.count("bulk-memory") && config->sharedMemory)
+ error("'bulk-memory' feature must be used in order to use shared "
+ "memory");
- if (!used.count("bulk-memory") && tlsUsed)
+ if (!allowed.count("bulk-memory") && tlsUsed)
error("'bulk-memory' feature must be used in order to use thread-local "
"storage");
// Validate that used features are allowed in output
if (!inferFeatures) {
for (auto &feature : used.keys()) {
- if (!out.targetFeaturesSec->features.count(feature))
+ if (!allowed.count(feature))
error(Twine("Target feature '") + feature + "' used by " +
used[feature] + " is not allowed.");
}
@@ -655,7 +668,7 @@ void Writer::createOutputSegments() {
if (s == nullptr) {
LLVM_DEBUG(dbgs() << "new segment: " << name << "\n");
s = make<OutputSegment>(name, segments.size());
- if (config->passiveSegments || name == ".tdata")
+ if (config->sharedMemory || name == ".tdata")
s->initFlags = WASM_SEGMENT_IS_PASSIVE;
segments.push_back(s);
}
@@ -678,32 +691,119 @@ static void createFunction(DefinedFuncti
void Writer::createInitMemoryFunction() {
LLVM_DEBUG(dbgs() << "createInitMemoryFunction\n");
+ assert(WasmSym::initMemoryFlag);
+ uint32_t flagAddress = WasmSym::initMemoryFlag->getVirtualAddress();
std::string bodyContent;
{
raw_string_ostream os(bodyContent);
writeUleb128(os, 0, "num locals");
- // initialize passive data segments
- for (const OutputSegment *s : segments) {
- if (s->initFlags & WASM_SEGMENT_IS_PASSIVE && s->name != ".tdata") {
- // destination address
- writeU8(os, WASM_OPCODE_I32_CONST, "i32.const");
- writeSleb128(os, s->startVA, "destination address");
- // source segment offset
- writeU8(os, WASM_OPCODE_I32_CONST, "i32.const");
- writeSleb128(os, 0, "segment offset");
- // memory region size
- writeU8(os, WASM_OPCODE_I32_CONST, "i32.const");
- writeSleb128(os, s->size, "memory region size");
- // memory.init instruction
- writeU8(os, WASM_OPCODE_MISC_PREFIX, "bulk-memory prefix");
- writeUleb128(os, WASM_OPCODE_MEMORY_INIT, "MEMORY.INIT");
- writeUleb128(os, s->index, "segment index immediate");
- writeU8(os, 0, "memory index immediate");
- // data.drop instruction
- writeU8(os, WASM_OPCODE_MISC_PREFIX, "bulk-memory prefix");
- writeUleb128(os, WASM_OPCODE_DATA_DROP, "DATA.DROP");
- writeUleb128(os, s->index, "segment index immediate");
+ if (segments.size()) {
+ // Initialize memory in a thread-safe manner. The thread that successfully
+ // increments the flag from 0 to 1 is is responsible for performing the
+ // memory initialization. Other threads go sleep on the flag until the
+ // first thread finishing initializing memory, increments the flag to 2,
+ // and wakes all the other threads. Once the flag has been set to 2,
+ // subsequently started threads will skip the sleep. All threads
+ // unconditionally drop their passive data segments once memory has been
+ // initialized. The generated code is as follows:
+ //
+ // (func $__wasm_init_memory
+ // (if
+ // (i32.atomic.rmw.cmpxchg align=2 offset=0
+ // (i32.const $__init_memory_flag)
+ // (i32.const 0)
+ // (i32.const 1)
+ // )
+ // (then
+ // (drop
+ // (i32.atomic.wait align=2 offset=0
+ // (i32.const $__init_memory_flag)
+ // (i32.const 1)
+ // (i32.const -1)
+ // )
+ // )
+ // )
+ // (else
+ // ( ... initialize data segments ... )
+ // (i32.atomic.store align=2 offset=0
+ // (i32.const $__init_memory_flag)
+ // (i32.const 2)
+ // )
+ // (drop
+ // (i32.atomic.notify align=2 offset=0
+ // (i32.const $__init_memory_flag)
+ // (i32.const -1u)
+ // )
+ // )
+ // )
+ // )
+ // ( ... drop data segments ... )
+ // )
+
+ // Atomically check whether this is the main thread.
+ writeI32Const(os, flagAddress, "flag address");
+ writeI32Const(os, 0, "expected flag value");
+ writeI32Const(os, 1, "flag value");
+ writeU8(os, WASM_OPCODE_ATOMICS_PREFIX, "atomics prefix");
+ writeUleb128(os, WASM_OPCODE_I32_RMW_CMPXCHG, "i32.atomic.rmw.cmpxchg");
+ writeMemArg(os, 2, 0);
+ writeU8(os, WASM_OPCODE_IF, "IF");
+ writeU8(os, WASM_TYPE_NORESULT, "blocktype");
+
+ // Did not increment 0, so wait for main thread to initialize memory
+ writeI32Const(os, flagAddress, "flag address");
+ writeI32Const(os, 1, "expected flag value");
+ writeI64Const(os, -1, "timeout");
+ writeU8(os, WASM_OPCODE_ATOMICS_PREFIX, "atomics prefix");
+ writeUleb128(os, WASM_OPCODE_I32_ATOMIC_WAIT, "i32.atomic.wait");
+ writeMemArg(os, 2, 0);
+ writeU8(os, WASM_OPCODE_DROP, "drop");
+
+ writeU8(os, WASM_OPCODE_ELSE, "ELSE");
+
+ // Did increment 0, so conditionally initialize passive data segments
+ for (const OutputSegment *s : segments) {
+ if (s->initFlags & WASM_SEGMENT_IS_PASSIVE && s->name != ".tdata") {
+ // destination address
+ writeI32Const(os, s->startVA, "destination address");
+ // source segment offset
+ writeI32Const(os, 0, "segment offset");
+ // memory region size
+ writeI32Const(os, s->size, "memory region size");
+ // memory.init instruction
+ writeU8(os, WASM_OPCODE_MISC_PREFIX, "bulk-memory prefix");
+ writeUleb128(os, WASM_OPCODE_MEMORY_INIT, "memory.init");
+ writeUleb128(os, s->index, "segment index immediate");
+ writeU8(os, 0, "memory index immediate");
+ }
+ }
+
+ // Set flag to 2 to mark end of initialization
+ writeI32Const(os, flagAddress, "flag address");
+ writeI32Const(os, 2, "flag value");
+ writeU8(os, WASM_OPCODE_ATOMICS_PREFIX, "atomics prefix");
+ writeUleb128(os, WASM_OPCODE_I32_ATOMIC_STORE, "i32.atomic.store");
+ writeMemArg(os, 2, 0);
+
+ // Notify any waiters that memory initialization is complete
+ writeI32Const(os, flagAddress, "flag address");
+ writeI32Const(os, -1, "number of waiters");
+ writeU8(os, WASM_OPCODE_ATOMICS_PREFIX, "atomics prefix");
+ writeUleb128(os, WASM_OPCODE_ATOMIC_NOTIFY, "atomic.notify");
+ writeMemArg(os, 2, 0);
+ writeU8(os, WASM_OPCODE_DROP, "drop");
+
+ writeU8(os, WASM_OPCODE_END, "END");
+
+ // Unconditionally drop passive data segments
+ for (const OutputSegment *s : segments) {
+ if (s->initFlags & WASM_SEGMENT_IS_PASSIVE && s->name != ".tdata") {
+ // data.drop instruction
+ writeU8(os, WASM_OPCODE_MISC_PREFIX, "bulk-memory prefix");
+ writeUleb128(os, WASM_OPCODE_DATA_DROP, "data.drop");
+ writeUleb128(os, s->index, "segment index immediate");
+ }
}
}
writeU8(os, WASM_OPCODE_END, "END");
@@ -744,12 +844,6 @@ void Writer::createCallCtorsFunction() {
raw_string_ostream os(bodyContent);
writeUleb128(os, 0, "num locals");
- if (config->passiveSegments) {
- writeU8(os, WASM_OPCODE_CALL, "CALL");
- writeUleb128(os, WasmSym::initMemory->getFunctionIndex(),
- "function index");
- }
-
if (config->isPic) {
writeU8(os, WASM_OPCODE_CALL, "CALL");
writeUleb128(os, WasmSym::applyRelocs->getFunctionIndex(),
@@ -794,11 +888,9 @@ void Writer::createInitTLSFunction() {
writeU8(os, WASM_OPCODE_LOCAL_GET, "local.get");
writeUleb128(os, 0, "local index");
- writeU8(os, WASM_OPCODE_I32_CONST, "i32.const");
- writeSleb128(os, 0, "segment offset");
+ writeI32Const(os, 0, "segment offset");
- writeU8(os, WASM_OPCODE_I32_CONST, "i32.const");
- writeSleb128(os, tlsSeg->size, "memory region size");
+ writeI32Const(os, tlsSeg->size, "memory region size");
writeU8(os, WASM_OPCODE_MISC_PREFIX, "bulk-memory prefix");
writeUleb128(os, WASM_OPCODE_MEMORY_INIT, "MEMORY.INIT");
@@ -851,6 +943,7 @@ void Writer::createSyntheticSections() {
out.globalSec = make<GlobalSection>();
out.eventSec = make<EventSection>();
out.exportSec = make<ExportSection>();
+ out.startSec = make<StartSection>(segments.size());
out.elemSec = make<ElemSection>();
out.dataCountSec = make<DataCountSection>(segments.size());
out.linkingSec = make<LinkingSection>(initFunctions, segments);
@@ -900,7 +993,7 @@ void Writer::run() {
if (!config->relocatable) {
// Create linker synthesized functions
- if (config->passiveSegments)
+ if (config->sharedMemory)
createInitMemoryFunction();
if (config->isPic)
createApplyRelocationsFunction();
Modified: lld/trunk/wasm/WriterUtils.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/WriterUtils.cpp?rev=370965&r1=370964&r2=370965&view=diff
==============================================================================
--- lld/trunk/wasm/WriterUtils.cpp (original)
+++ lld/trunk/wasm/WriterUtils.cpp Wed Sep 4 12:50:39 2019
@@ -73,6 +73,21 @@ void wasm::writeSig(raw_ostream &os, con
}
}
+void wasm::writeI32Const(raw_ostream &os, int32_t number, const Twine &msg) {
+ writeU8(os, WASM_OPCODE_I32_CONST, "i32.const");
+ writeSleb128(os, number, msg);
+}
+
+void wasm::writeI64Const(raw_ostream &os, int32_t number, const Twine &msg) {
+ writeU8(os, WASM_OPCODE_I64_CONST, "i64.const");
+ writeSleb128(os, number, msg);
+}
+
+void wasm::writeMemArg(raw_ostream &os, uint32_t alignment, uint32_t offset) {
+ writeUleb128(os, alignment, "alignment");
+ writeUleb128(os, offset, "offset");
+}
+
void wasm::writeInitExpr(raw_ostream &os, const WasmInitExpr &initExpr) {
writeU8(os, initExpr.Opcode, "opcode");
switch (initExpr.Opcode) {
Modified: lld/trunk/wasm/WriterUtils.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/WriterUtils.h?rev=370965&r1=370964&r2=370965&view=diff
==============================================================================
--- lld/trunk/wasm/WriterUtils.h (original)
+++ lld/trunk/wasm/WriterUtils.h Wed Sep 4 12:50:39 2019
@@ -36,6 +36,12 @@ void writeValueType(raw_ostream &os, llv
void writeSig(raw_ostream &os, const llvm::wasm::WasmSignature &sig);
+void writeI32Const(raw_ostream &os, int32_t number, const Twine &msg);
+
+void writeI64Const(raw_ostream &os, int32_t number, const Twine &msg);
+
+void writeMemArg(raw_ostream &os, uint32_t alignment, uint32_t offset);
+
void writeInitExpr(raw_ostream &os, const llvm::wasm::WasmInitExpr &initExpr);
void writeLimits(raw_ostream &os, const llvm::wasm::WasmLimits &limits);
More information about the llvm-commits
mailing list