[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