summaryrefslogtreecommitdiff
path: root/src/wasm
diff options
context:
space:
mode:
Diffstat (limited to 'src/wasm')
-rw-r--r--src/wasm/wasm-binary.cpp61
-rw-r--r--src/wasm/wasm-s-parser.cpp28
-rw-r--r--src/wasm/wasm-stack.cpp20
-rw-r--r--src/wasm/wasm-validator.cpp15
-rw-r--r--src/wasm/wasm.cpp24
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;