[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
This commit is contained in:
Thomas Lively 2019-03-29 20:43:49 +00:00
parent 54f7118de5
commit 06391f34bd
3 changed files with 146 additions and 3 deletions

View File

@ -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{{$}}

View File

@ -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{{$}}

View 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) {