From 06391f34bd4ec04a2f0e9376b99d7821185eabb2 Mon Sep 17 00:00:00 2001 From: Thomas Lively Date: Fri, 29 Mar 2019 20:43:49 +0000 Subject: [PATCH] [WebAssembly] "atomics" feature requires shared memory 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 | 60 +++++++++++++++++++++++ lld/test/wasm/shared-memory.yaml | 75 +++++++++++++++++++++++++++++ lld/wasm/Writer.cpp | 14 ++++-- 3 files changed, 146 insertions(+), 3 deletions(-) create mode 100644 lld/test/wasm/shared-memory-no-atomics.yaml create mode 100644 lld/test/wasm/shared-memory.yaml diff --git a/lld/test/wasm/shared-memory-no-atomics.yaml b/lld/test/wasm/shared-memory-no-atomics.yaml new file mode 100644 index 0000000..e4c7b76 --- /dev/null +++ b/lld/test/wasm/shared-memory-no-atomics.yaml @@ -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 index 0000000..3538f34 --- /dev/null +++ b/lld/test/wasm/shared-memory.yaml @@ -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{{$}} diff --git a/lld/wasm/Writer.cpp b/lld/wasm/Writer.cpp index 63e33d6..50dc76f 100644 --- a/lld/wasm/Writer.cpp +++ b/lld/wasm/Writer.cpp @@ -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) { -- 2.7.4