[WebAssembly] "atomics" feature requires shared memory
authorThomas Lively <tlively@google.com>
Fri, 29 Mar 2019 20:43:49 +0000 (20:43 +0000)
committerThomas Lively <tlively@google.com>
Fri, 29 Mar 2019 20:43:49 +0000 (20:43 +0000)
Summary:
Makes it a linker error if the "atomics" feature is used but the user
does not opt in to shared memory or if "atomics" is disallowed but the
user does opt in to shared memory. Also check that an appropriate max
memory size is supplied if shared memory is used.

Reviewers: sbc100, aheejin

Subscribers: dschuff, jgravelle-google, sunfish, jfb, llvm-commits

Tags: #llvm

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

llvm-svn: 357310

lld/test/wasm/shared-memory-no-atomics.yaml [new file with mode: 0644]
lld/test/wasm/shared-memory.yaml [new file with mode: 0644]
lld/wasm/Writer.cpp

diff --git a/lld/test/wasm/shared-memory-no-atomics.yaml b/lld/test/wasm/shared-memory-no-atomics.yaml
new file mode 100644 (file)
index 0000000..e4c7b76
--- /dev/null
@@ -0,0 +1,60 @@
+# RUN: yaml2obj %s -o %t1.o
+
+# RUN: wasm-ld --no-entry %t1.o -o - | obj2yaml | FileCheck %s --check-prefix NO-SHARED
+
+# RUN: not wasm-ld --no-entry --shared-memory --max-memory=131072 %t1.o -o - 2>&1 | FileCheck %s --check-prefix SHARED
+
+--- !WASM
+FileHeader:
+  Version:         0x00000001
+Sections:
+  - Type:            IMPORT
+    Imports:
+      - Module:          env
+        Field:           __linear_memory
+        Kind:            MEMORY
+        Memory:
+          Initial:         0x00000001
+      - Module:          env
+        Field:           __indirect_function_table
+        Kind:            TABLE
+        Table:
+          ElemType:        FUNCREF
+          Limits:
+            Initial:         0x00000000
+  - Type:            DATA
+    Segments:
+      - SectionOffset:   6
+        InitFlags:       0
+        Offset:
+          Opcode:          I32_CONST
+          Value:           0
+        Content:         68656C6C6F0A00
+  - Type:            CUSTOM
+    Name:            linking
+    Version:         2
+    SymbolTable:
+      - Index:           0
+        Kind:            DATA
+        Name:            hello_str
+        Flags:           [  ]
+        Segment:         0
+        Size:            7
+    SegmentInfo:
+      - Index:           0
+        Name:            .rodata.hello_str
+        Alignment:       0
+        Flags:           [  ]
+  - Type:            CUSTOM
+    Name:            target_features
+    Features:
+      - Prefix:        DISALLOWED
+        Name:          "atomics"
+...
+
+# NO-SHARED:      - Type:            MEMORY
+# NO-SHARED-NEXT:   Memories:
+# NO-SHARED-NEXT:     - Initial:         0x00000002
+# NO-SHARED-NOT:        Maximum:
+
+# SHARED: 'atomics' feature is disallowed, so --shared-memory must not be used{{$}}
diff --git a/lld/test/wasm/shared-memory.yaml b/lld/test/wasm/shared-memory.yaml
new file mode 100644 (file)
index 0000000..3538f34
--- /dev/null
@@ -0,0 +1,75 @@
+# RUN: yaml2obj %s -o %t1.o
+
+# 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 --max-memory=100000 %t1.o -o - 2>&1 | FileCheck %s --check-prefix SHARED-UNALIGNED
+
+# RUN: wasm-ld --no-entry --shared-memory --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: not wasm-ld --no-entry --features=atomics --shared-memory %t1.o -o - 2>&1 | FileCheck %s --check-prefix ATOMICS-NO-MAX
+
+# RUN: not wasm-ld --no-entry --features=atomics --shared-memory --max-memory=100000 %t1.o -o - 2>&1 | FileCheck %s --check-prefix ATOMICS-UNALIGNED
+
+# RUN: wasm-ld --no-entry --features=atomics --shared-memory --max-memory=131072 %t1.o -o - | obj2yaml | FileCheck %s --check-prefix SHARED
+
+
+--- !WASM
+FileHeader:
+  Version:         0x00000001
+Sections:
+  - Type:            IMPORT
+    Imports:
+      - Module:          env
+        Field:           __linear_memory
+        Kind:            MEMORY
+        Memory:
+          Initial:         0x00000001
+      - Module:          env
+        Field:           __indirect_function_table
+        Kind:            TABLE
+        Table:
+          ElemType:        FUNCREF
+          Limits:
+            Initial:         0x00000000
+  - Type:            DATA
+    Segments:
+      - SectionOffset:   6
+        InitFlags:       0
+        Offset:
+          Opcode:          I32_CONST
+          Value:           0
+        Content:         68656C6C6F0A00
+  - Type:            CUSTOM
+    Name:            linking
+    Version:         2
+    SymbolTable:
+      - Index:           0
+        Kind:            DATA
+        Name:            hello_str
+        Flags:           [  ]
+        Segment:         0
+        Size:            7
+    SegmentInfo:
+      - Index:           0
+        Name:            .rodata.hello_str
+        Alignment:       0
+        Flags:           [  ]
+...
+
+# SHARED-NO-MAX: maximum memory too small, 66560 bytes needed{{$}}
+
+# SHARED-UNALIGNED: maximum memory must be 65536-byte aligned{{$}}
+
+# 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{{$}}
index 63e33d6..50dc76f 100644 (file)
@@ -169,7 +169,7 @@ void Writer::createImportSection() {
     Import.Kind = WASM_EXTERNAL_MEMORY;
     Import.Memory.Flags = 0;
     Import.Memory.Initial = NumMemoryPages;
-    if (MaxMemoryPages != 0) {
+    if (MaxMemoryPages != 0 || Config->SharedMemory) {
       Import.Memory.Flags |= WASM_LIMITS_FLAG_HAS_MAX;
       Import.Memory.Maximum = MaxMemoryPages;
     }
@@ -257,7 +257,7 @@ void Writer::createMemorySection() {
   SyntheticSection *Section = createSyntheticSection(WASM_SEC_MEMORY);
   raw_ostream &OS = Section->getStream();
 
-  bool HasMax = MaxMemoryPages != 0;
+  bool HasMax = MaxMemoryPages != 0 || Config->SharedMemory;
   writeUleb128(OS, 1, "memory count");
   unsigned Flags = 0;
   if (HasMax)
@@ -831,7 +831,8 @@ void Writer::layoutMemory() {
   NumMemoryPages = alignTo(MemoryPtr, WasmPageSize) / WasmPageSize;
   log("mem: total pages = " + Twine(NumMemoryPages));
 
-  if (Config->MaxMemory != 0) {
+  // Check max if explicitly supplied or required by shared memory
+  if (Config->MaxMemory != 0 || Config->SharedMemory) {
     if (Config->MaxMemory != alignTo(Config->MaxMemory, WasmPageSize))
       error("maximum memory must be " + Twine(WasmPageSize) + "-byte aligned");
     if (MemoryPtr > Config->MaxMemory)
@@ -927,9 +928,16 @@ void Writer::calculateTargetFeatures() {
   if (InferFeatures)
     TargetFeatures.insert(Used.begin(), Used.end());
 
+  if (TargetFeatures.count("atomics") && !Config->SharedMemory)
+    error("'atomics' feature is used, so --shared-memory must be used");
+
   if (!Config->CheckFeatures)
     return;
 
+  if (Disallowed.count("atomics") && Config->SharedMemory)
+    error(
+        "'atomics' feature is disallowed, so --shared-memory must not be used");
+
   // Validate that used features are allowed in output
   if (!InferFeatures) {
     for (auto &Feature : Used) {