diff options
Diffstat (limited to 'src/wasm')
-rw-r--r-- | src/wasm/wasm-binary.cpp | 61 | ||||
-rw-r--r-- | src/wasm/wasm-s-parser.cpp | 28 | ||||
-rw-r--r-- | src/wasm/wasm-stack.cpp | 20 | ||||
-rw-r--r-- | src/wasm/wasm-validator.cpp | 15 | ||||
-rw-r--r-- | src/wasm/wasm.cpp | 24 |
5 files changed, 128 insertions, 20 deletions
diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index 7b9d9c624..136301500 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -2340,9 +2340,6 @@ BinaryConsts::ASTNodes WasmBinaryBuilder::readExpression(Expression*& curr) { if (maybeVisitSIMDConst(curr, opcode)) { break; } - if (maybeVisitSIMDLoad(curr, opcode)) { - break; - } if (maybeVisitSIMDStore(curr, opcode)) { break; } @@ -2361,6 +2358,9 @@ BinaryConsts::ASTNodes WasmBinaryBuilder::readExpression(Expression*& curr) { if (maybeVisitSIMDShift(curr, opcode)) { break; } + if (maybeVisitSIMDLoad(curr, opcode)) { + break; + } throwError("invalid code after SIMD prefix: " + std::to_string(opcode)); break; } @@ -4158,21 +4158,6 @@ bool WasmBinaryBuilder::maybeVisitSIMDConst(Expression*& out, uint32_t code) { return true; } -bool WasmBinaryBuilder::maybeVisitSIMDLoad(Expression*& out, uint32_t code) { - if (code != BinaryConsts::V128Load) { - return false; - } - auto* curr = allocator.alloc<Load>(); - curr->type = v128; - curr->bytes = 16; - readMemoryAccess(curr->align, curr->offset); - curr->isAtomic = false; - curr->ptr = popNonVoidExpression(); - curr->finalize(); - out = curr; - return true; -} - bool WasmBinaryBuilder::maybeVisitSIMDStore(Expression*& out, uint32_t code) { if (code != BinaryConsts::V128Store) { return false; @@ -4394,6 +4379,46 @@ bool WasmBinaryBuilder::maybeVisitSIMDShift(Expression*& out, uint32_t code) { return true; } +bool WasmBinaryBuilder::maybeVisitSIMDLoad(Expression*& out, uint32_t code) { + if (code == BinaryConsts::V128Load) { + auto* curr = allocator.alloc<Load>(); + curr->type = v128; + curr->bytes = 16; + readMemoryAccess(curr->align, curr->offset); + curr->isAtomic = false; + curr->ptr = popNonVoidExpression(); + curr->finalize(); + out = curr; + return true; + } + SIMDLoad* curr; + switch (code) { + case BinaryConsts::V8x16LoadSplat: + curr = allocator.alloc<SIMDLoad>(); + curr->op = LoadSplatVec8x16; + break; + case BinaryConsts::V16x8LoadSplat: + curr = allocator.alloc<SIMDLoad>(); + curr->op = LoadSplatVec16x8; + break; + case BinaryConsts::V32x4LoadSplat: + curr = allocator.alloc<SIMDLoad>(); + curr->op = LoadSplatVec32x4; + break; + case BinaryConsts::V64x2LoadSplat: + curr = allocator.alloc<SIMDLoad>(); + curr->op = LoadSplatVec64x2; + break; + default: + return false; + } + readMemoryAccess(curr->align, curr->offset); + curr->ptr = popNonVoidExpression(); + curr->finalize(); + out = curr; + return true; +} + void WasmBinaryBuilder::visitSelect(Select* curr) { if (debug) { std::cerr << "zz node: Select" << std::endl; diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp index 322c36c45..9f1fe0044 100644 --- a/src/wasm/wasm-s-parser.cpp +++ b/src/wasm/wasm-s-parser.cpp @@ -1251,10 +1251,10 @@ static uint8_t parseMemBytes(const char*& s, uint8_t fallback) { static size_t parseMemAttributes(Element& s, Address* offset, Address* align, - Address fallback) { + Address fallbackAlign) { size_t i = 1; *offset = 0; - *align = fallback; + *align = fallbackAlign; while (!s[i]->isList()) { const char* str = s[i]->c_str(); const char* eq = strchr(str, '='); @@ -1493,6 +1493,30 @@ Expression* SExpressionWasmBuilder::makeSIMDShift(Element& s, SIMDShiftOp op) { return ret; } +Expression* SExpressionWasmBuilder::makeSIMDLoad(Element& s, SIMDLoadOp op) { + auto ret = allocator.alloc<SIMDLoad>(); + ret->op = op; + Address defaultAlign; + switch (op) { + case LoadSplatVec8x16: + defaultAlign = 1; + break; + case LoadSplatVec16x8: + defaultAlign = 2; + break; + case LoadSplatVec32x4: + defaultAlign = 4; + break; + case LoadSplatVec64x2: + defaultAlign = 8; + break; + } + size_t i = parseMemAttributes(s, &ret->offset, &ret->align, defaultAlign); + ret->ptr = parseExpression(s[i]); + ret->finalize(); + return ret; +} + Expression* SExpressionWasmBuilder::makeMemoryInit(Element& s) { auto ret = allocator.alloc<MemoryInit>(); ret->segment = atoi(s[1]->str().c_str()); diff --git a/src/wasm/wasm-stack.cpp b/src/wasm/wasm-stack.cpp index 1da6e9015..c673a3fb0 100644 --- a/src/wasm/wasm-stack.cpp +++ b/src/wasm/wasm-stack.cpp @@ -554,6 +554,26 @@ void BinaryInstWriter::visitSIMDShift(SIMDShift* curr) { } } +void BinaryInstWriter::visitSIMDLoad(SIMDLoad* curr) { + o << int8_t(BinaryConsts::SIMDPrefix); + switch (curr->op) { + case LoadSplatVec8x16: + o << U32LEB(BinaryConsts::V8x16LoadSplat); + break; + case LoadSplatVec16x8: + o << U32LEB(BinaryConsts::V16x8LoadSplat); + break; + case LoadSplatVec32x4: + o << U32LEB(BinaryConsts::V32x4LoadSplat); + break; + case LoadSplatVec64x2: + o << U32LEB(BinaryConsts::V64x2LoadSplat); + break; + } + assert(curr->align); + emitMemoryAccess(curr->align, /*(unused) bytes=*/0, curr->offset); +} + void BinaryInstWriter::visitMemoryInit(MemoryInit* curr) { o << int8_t(BinaryConsts::MiscPrefix); o << U32LEB(BinaryConsts::MemoryInit); diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp index e64e2ef73..68002e4d2 100644 --- a/src/wasm/wasm-validator.cpp +++ b/src/wasm/wasm-validator.cpp @@ -276,6 +276,7 @@ public: void visitSIMDShuffle(SIMDShuffle* curr); void visitSIMDTernary(SIMDTernary* curr); void visitSIMDShift(SIMDShift* curr); + void visitSIMDLoad(SIMDLoad* curr); void visitMemoryInit(MemoryInit* curr); void visitDataDrop(DataDrop* curr); void visitMemoryCopy(MemoryCopy* curr); @@ -1054,6 +1055,20 @@ void FunctionValidator::visitSIMDShift(SIMDShift* curr) { curr->shift->type, i32, curr, "expected shift amount to have type i32"); } +void FunctionValidator::visitSIMDLoad(SIMDLoad* curr) { + shouldBeTrue( + getModule()->memory.exists, curr, "Memory operations require a memory"); + shouldBeTrue( + getModule()->features.hasSIMD(), curr, "SIMD operation (SIMD is disabled)"); + shouldBeEqualOrFirstIsUnreachable( + curr->type, v128, curr, "load_splat must have type v128"); + shouldBeEqualOrFirstIsUnreachable( + curr->ptr->type, i32, curr, "load_splat address must have type i32"); + Type lane_t = curr->op == LoadSplatVec64x2 ? i64 : i32; + Index bytes = curr->getMemBytes(); + validateAlignment(curr->align, lane_t, bytes, /*isAtomic=*/false, curr); +} + void FunctionValidator::visitMemoryInit(MemoryInit* curr) { shouldBeTrue(getModule()->features.hasBulkMemory(), curr, diff --git a/src/wasm/wasm.cpp b/src/wasm/wasm.cpp index f8439ea96..58510cc8f 100644 --- a/src/wasm/wasm.cpp +++ b/src/wasm/wasm.cpp @@ -159,6 +159,8 @@ const char* getExpressionName(Expression* curr) { return "simd_ternary"; case Expression::Id::SIMDShiftId: return "simd_shift"; + case Expression::Id::SIMDLoadId: + return "simd_load"; case Expression::Id::MemoryInitId: return "memory_init"; case Expression::Id::DataDropId: @@ -626,6 +628,28 @@ void SIMDShift::finalize() { } } +void SIMDLoad::finalize() { + assert(ptr); + type = v128; + if (ptr->type == unreachable) { + type = unreachable; + } +} + +Index SIMDLoad::getMemBytes() { + switch (op) { + case LoadSplatVec8x16: + return 1; + case LoadSplatVec16x8: + return 2; + case LoadSplatVec32x4: + return 4; + case LoadSplatVec64x2: + return 8; + } + WASM_UNREACHABLE(); +} + Const* Const::set(Literal value_) { value = value_; type = value.type; |