summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/binary-reader-ir.cc10
-rw-r--r--src/binary-reader-logging.cc1
-rw-r--r--src/binary-reader-logging.h3
-rw-r--r--src/binary-reader-nop.h5
-rw-r--r--src/binary-reader.cc11
-rw-r--r--src/binary-reader.h3
-rw-r--r--src/binary-writer.cc3
-rw-r--r--src/expr-visitor.cc4
-rw-r--r--src/expr-visitor.h2
-rw-r--r--src/interp/binary-reader-interp.cc11
-rw-r--r--src/interp/interp.cc17
-rw-r--r--src/interp/interp.h2
-rw-r--r--src/interp/istream.cc2
-rw-r--r--src/ir-util.cc1
-rw-r--r--src/ir.cc1
-rw-r--r--src/ir.h2
-rw-r--r--src/lexer-keywords.txt2
-rw-r--r--src/opcode.def2
-rw-r--r--src/prebuilt/lexer-keywords.cc111
-rw-r--r--src/shared-validator.cc12
-rw-r--r--src/shared-validator.h1
-rw-r--r--src/validator.cc7
-rw-r--r--src/wat-writer.cc6
23 files changed, 165 insertions, 54 deletions
diff --git a/src/binary-reader-ir.cc b/src/binary-reader-ir.cc
index cdda3311..71bc3f9a 100644
--- a/src/binary-reader-ir.cc
+++ b/src/binary-reader-ir.cc
@@ -206,6 +206,9 @@ class BinaryReaderIR : public BinaryReaderNop {
Result OnLoadSplatExpr(Opcode opcode,
Address alignment_log2,
Address offset) override;
+ Result OnLoadZeroExpr(Opcode opcode,
+ Address alignment_log2,
+ Address offset) override;
Result OnElemSegmentCount(Index count) override;
Result BeginElemSegment(Index index,
@@ -1089,6 +1092,13 @@ Result BinaryReaderIR::OnLoadSplatExpr(Opcode opcode,
MakeUnique<LoadSplatExpr>(opcode, 1 << alignment_log2, offset));
}
+Result BinaryReaderIR::OnLoadZeroExpr(Opcode opcode,
+ Address alignment_log2,
+ Address offset) {
+ return AppendExpr(
+ MakeUnique<LoadZeroExpr>(opcode, 1 << alignment_log2, offset));
+}
+
Result BinaryReaderIR::OnElemSegmentCount(Index count) {
WABT_TRY
module_->elem_segments.reserve(count);
diff --git a/src/binary-reader-logging.cc b/src/binary-reader-logging.cc
index 5cebbe92..c0a05fe6 100644
--- a/src/binary-reader-logging.cc
+++ b/src/binary-reader-logging.cc
@@ -831,6 +831,7 @@ DEFINE_INDEX_DESC(OnReturnCallExpr, "func_index")
DEFINE_INDEX_INDEX(OnReturnCallIndirectExpr, "sig_index", "table_index")
DEFINE0(OnReturnExpr)
DEFINE_LOAD_STORE_OPCODE(OnLoadSplatExpr);
+DEFINE_LOAD_STORE_OPCODE(OnLoadZeroExpr);
DEFINE_LOAD_STORE_OPCODE(OnStoreExpr);
DEFINE_INDEX_DESC(OnThrowExpr, "event_index")
DEFINE0(OnUnreachableExpr)
diff --git a/src/binary-reader-logging.h b/src/binary-reader-logging.h
index 70dcbae6..e585ff27 100644
--- a/src/binary-reader-logging.h
+++ b/src/binary-reader-logging.h
@@ -234,6 +234,9 @@ class BinaryReaderLogging : public BinaryReaderDelegate {
Result OnLoadSplatExpr(Opcode opcode,
Address alignment_log2,
Address offset) override;
+ Result OnLoadZeroExpr(Opcode opcode,
+ Address alignment_log2,
+ Address offset) override;
Result BeginElemSection(Offset size) override;
Result OnElemSegmentCount(Index count) override;
diff --git a/src/binary-reader-nop.h b/src/binary-reader-nop.h
index f72dbf10..aedd4486 100644
--- a/src/binary-reader-nop.h
+++ b/src/binary-reader-nop.h
@@ -312,6 +312,11 @@ class BinaryReaderNop : public BinaryReaderDelegate {
Address offset) override {
return Result::Ok;
}
+ Result OnLoadZeroExpr(Opcode opcode,
+ Address alignment_log2,
+ Address offset) override {
+ return Result::Ok;
+ }
/* Elem section */
Result BeginElemSection(Offset size) override { return Result::Ok; }
diff --git a/src/binary-reader.cc b/src/binary-reader.cc
index 0ada95ba..289e7ba2 100644
--- a/src/binary-reader.cc
+++ b/src/binary-reader.cc
@@ -1318,6 +1318,17 @@ Result BinaryReader::ReadFunctionBody(Offset end_offset) {
CALLBACK(OnOpcodeUint32Uint32, alignment_log2, offset);
break;
}
+ case Opcode::V128Load32Zero:
+ case Opcode::V128Load64Zero: {
+ Address alignment_log2;
+ CHECK_RESULT(ReadAlignment(&alignment_log2, "load alignment"));
+ Address offset;
+ CHECK_RESULT(ReadAddress(&offset, 0, "load offset"));
+
+ CALLBACK(OnLoadZeroExpr, opcode, alignment_log2, offset);
+ CALLBACK(OnOpcodeUint32Uint32, alignment_log2, offset);
+ break;
+ }
case Opcode::I32TruncF32S:
case Opcode::I32TruncF64S:
case Opcode::I32TruncF32U:
diff --git a/src/binary-reader.h b/src/binary-reader.h
index 19643aa8..1a7ef0bd 100644
--- a/src/binary-reader.h
+++ b/src/binary-reader.h
@@ -298,6 +298,9 @@ class BinaryReaderDelegate {
virtual Result OnLoadSplatExpr(Opcode opcode,
Address alignment_log2,
Address offset) = 0;
+ virtual Result OnLoadZeroExpr(Opcode opcode,
+ Address alignment_log2,
+ Address offset) = 0;
/* Elem section */
virtual Result BeginElemSection(Offset size) = 0;
diff --git a/src/binary-writer.cc b/src/binary-writer.cc
index c744aca4..2f97354e 100644
--- a/src/binary-writer.cc
+++ b/src/binary-writer.cc
@@ -1026,6 +1026,9 @@ void BinaryWriter::WriteExpr(const Func* func, const Expr* expr) {
case ExprType::LoadSplat:
WriteLoadStoreExpr<LoadSplatExpr>(func, expr, "load offset");
break;
+ case ExprType::LoadZero:
+ WriteLoadStoreExpr<LoadZeroExpr>(func, expr, "load offset");
+ break;
case ExprType::Unreachable:
WriteOpcode(stream_, Opcode::Unreachable);
break;
diff --git a/src/expr-visitor.cc b/src/expr-visitor.cc
index af80e705..78b4a52c 100644
--- a/src/expr-visitor.cc
+++ b/src/expr-visitor.cc
@@ -270,6 +270,10 @@ Result ExprVisitor::HandleDefaultState(Expr* expr) {
CHECK_RESULT(delegate_->OnLoadSplatExpr(cast<LoadSplatExpr>(expr)));
break;
+ case ExprType::LoadZero:
+ CHECK_RESULT(delegate_->OnLoadZeroExpr(cast<LoadZeroExpr>(expr)));
+ break;
+
case ExprType::LocalGet:
CHECK_RESULT(delegate_->OnLocalGetExpr(cast<LocalGetExpr>(expr)));
break;
diff --git a/src/expr-visitor.h b/src/expr-visitor.h
index f30607ce..0412048e 100644
--- a/src/expr-visitor.h
+++ b/src/expr-visitor.h
@@ -134,6 +134,7 @@ class ExprVisitor::Delegate {
virtual Result OnSimdLaneOpExpr(SimdLaneOpExpr*) = 0;
virtual Result OnSimdShuffleOpExpr(SimdShuffleOpExpr*) = 0;
virtual Result OnLoadSplatExpr(LoadSplatExpr*) = 0;
+ virtual Result OnLoadZeroExpr(LoadZeroExpr*) = 0;
};
class ExprVisitor::DelegateNop : public ExprVisitor::Delegate {
@@ -208,6 +209,7 @@ class ExprVisitor::DelegateNop : public ExprVisitor::Delegate {
Result OnSimdLaneOpExpr(SimdLaneOpExpr*) override { return Result::Ok; }
Result OnSimdShuffleOpExpr(SimdShuffleOpExpr*) override { return Result::Ok; }
Result OnLoadSplatExpr(LoadSplatExpr*) override { return Result::Ok; }
+ Result OnLoadZeroExpr(LoadZeroExpr*) override { return Result::Ok; }
};
} // namespace wabt
diff --git a/src/interp/binary-reader-interp.cc b/src/interp/binary-reader-interp.cc
index 0cd9c523..0da318ae 100644
--- a/src/interp/binary-reader-interp.cc
+++ b/src/interp/binary-reader-interp.cc
@@ -216,6 +216,9 @@ class BinaryReaderInterp : public BinaryReaderNop {
Result OnLoadSplatExpr(Opcode opcode,
Address alignment_log2,
Address offset) override;
+ Result OnLoadZeroExpr(Opcode opcode,
+ Address alignment_log2,
+ Address offset) override;
Result OnElemSegmentCount(Index count) override;
Result BeginElemSegment(Index index,
@@ -906,6 +909,14 @@ Result BinaryReaderInterp::OnLoadSplatExpr(Opcode opcode,
return Result::Ok;
}
+Result BinaryReaderInterp::OnLoadZeroExpr(Opcode opcode,
+ Address align_log2,
+ Address offset) {
+ CHECK_RESULT(validator_.OnLoadZero(loc, opcode, GetAlignment(align_log2)));
+ istream_.Emit(opcode, kMemoryIndex0, offset);
+ return Result::Ok;
+}
+
Result BinaryReaderInterp::OnAtomicLoadExpr(Opcode opcode,
Address align_log2,
Address offset) {
diff --git a/src/interp/interp.cc b/src/interp/interp.cc
index a8730880..6538a341 100644
--- a/src/interp/interp.cc
+++ b/src/interp/interp.cc
@@ -1636,6 +1636,9 @@ RunResult Thread::StepInternal(Trap::Ptr* out_trap) {
case O::V128Load32Splat: return DoSimdLoadSplat<u32x4, u32>(instr, out_trap);
case O::V128Load64Splat: return DoSimdLoadSplat<u64x2, u64>(instr, out_trap);
+ case O::V128Load32Zero: return DoSimdLoadZero<u32x4, u32>(instr, out_trap);
+ case O::V128Load64Zero: return DoSimdLoadZero<u64x2, u64>(instr, out_trap);
+
case O::I8X16NarrowI16X8S: return DoSimdNarrow<s8x16, s16x8>();
case O::I8X16NarrowI16X8U: return DoSimdNarrow<u8x16, s16x8>();
case O::I16X8NarrowI32X4S: return DoSimdNarrow<s16x8, s32x4>();
@@ -2162,6 +2165,20 @@ RunResult Thread::DoSimdLoadSplat(Instr instr, Trap::Ptr* out_trap) {
return RunResult::Ok;
}
+template <typename S, typename T>
+RunResult Thread::DoSimdLoadZero(Instr instr, Trap::Ptr* out_trap) {
+ using L = typename S::LaneType;
+ L val;
+ if (Load<L>(instr, &val, out_trap) != RunResult::Ok) {
+ return RunResult::Trap;
+ }
+ S result;
+ std::fill(std::begin(result.v), std::end(result.v), 0);
+ result[0] = val;
+ Push(result);
+ return RunResult::Ok;
+}
+
RunResult Thread::DoSimdSwizzle() {
using S = u8x16;
auto rhs = Pop<S>();
diff --git a/src/interp/interp.h b/src/interp/interp.h
index e0acd1bb..2b7f1652 100644
--- a/src/interp/interp.h
+++ b/src/interp/interp.h
@@ -1152,6 +1152,8 @@ class Thread : public Object {
RunResult DoSimdShift(BinopFunc<R, T>);
template <typename S, typename T>
RunResult DoSimdLoadSplat(Instr, Trap::Ptr* out_trap);
+ template <typename S, typename T>
+ RunResult DoSimdLoadZero(Instr, Trap::Ptr* out_trap);
RunResult DoSimdSwizzle();
RunResult DoSimdShuffle(Instr);
template <typename S, typename T>
diff --git a/src/interp/istream.cc b/src/interp/istream.cc
index ab052545..67025c85 100644
--- a/src/interp/istream.cc
+++ b/src/interp/istream.cc
@@ -571,6 +571,8 @@ Instr Istream::Read(Offset* offset) const {
case Opcode::V128Load64Splat:
case Opcode::V128Load8Splat:
case Opcode::V128Load:
+ case Opcode::V128Load32Zero:
+ case Opcode::V128Load64Zero:
// Index + memory offset immediates, 1 operand.
instr.kind = InstrKind::Imm_Index_Offset_Op_1;
instr.imm_u32x2.fst = ReadAt<u32>(offset);
diff --git a/src/ir-util.cc b/src/ir-util.cc
index ef1c9a20..f5f0a5db 100644
--- a/src/ir-util.cc
+++ b/src/ir-util.cc
@@ -180,6 +180,7 @@ ModuleContext::Arities ModuleContext::GetExprArity(const Expr& expr) const {
case ExprType::TableGet:
case ExprType::RefIsNull:
case ExprType::LoadSplat:
+ case ExprType::LoadZero:
return { 1, 1 };
case ExprType::Drop:
diff --git a/src/ir.cc b/src/ir.cc
index c74b98e5..11878ca3 100644
--- a/src/ir.cc
+++ b/src/ir.cc
@@ -69,6 +69,7 @@ const char* ExprTypeName[] = {
"SimdLaneOp",
"SimdShuffleOp",
"LoadSplat",
+ "LoadZero",
"Store",
"TableCopy",
"ElemDrop",
diff --git a/src/ir.h b/src/ir.h
index 6742aee1..387f95b4 100644
--- a/src/ir.h
+++ b/src/ir.h
@@ -325,6 +325,7 @@ enum class ExprType {
SimdLaneOp,
SimdShuffleOp,
LoadSplat,
+ LoadZero,
Store,
TableCopy,
ElemDrop,
@@ -620,6 +621,7 @@ typedef LoadStoreExpr<ExprType::AtomicRmwCmpxchg> AtomicRmwCmpxchgExpr;
typedef LoadStoreExpr<ExprType::AtomicWait> AtomicWaitExpr;
typedef LoadStoreExpr<ExprType::AtomicNotify> AtomicNotifyExpr;
typedef LoadStoreExpr<ExprType::LoadSplat> LoadSplatExpr;
+typedef LoadStoreExpr<ExprType::LoadZero> LoadZeroExpr;
class AtomicFenceExpr : public ExprMixin<ExprType::AtomicFence> {
public:
diff --git a/src/lexer-keywords.txt b/src/lexer-keywords.txt
index 44b9beec..b9cea8c7 100644
--- a/src/lexer-keywords.txt
+++ b/src/lexer-keywords.txt
@@ -566,6 +566,8 @@ v128.load, TokenType::Load, Opcode::V128Load
v128.not, TokenType::Unary, Opcode::V128Not
v128.or, TokenType::Binary, Opcode::V128Or
v128.any_true, TokenType::Unary, Opcode::V128AnyTrue
+v128.load32_zero, TokenType::Load, Opcode::V128Load32Zero
+v128.load64_zero, TokenType::Load, Opcode::V128Load64Zero
v128.store, TokenType::Store, Opcode::V128Store
v128, Type::V128
v128.xor, TokenType::Binary, Opcode::V128Xor
diff --git a/src/opcode.def b/src/opcode.def
index da3015ab..1625cc31 100644
--- a/src/opcode.def
+++ b/src/opcode.def
@@ -346,6 +346,8 @@ WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x50, V128Or, "v128.or", "")
WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x51, V128Xor, "v128.xor", "")
WABT_OPCODE(V128, V128, V128, V128, 0, 0xfd, 0x52, V128BitSelect, "v128.bitselect", "")
WABT_OPCODE(I32, V128, ___, ___, 0, 0xfd, 0x53, V128AnyTrue, "v128.any_true", "")
+WABT_OPCODE(V128, I32, ___, ___, 4, 0xfd, 0x5c, V128Load32Zero, "v128.load32_zero", "")
+WABT_OPCODE(V128, I32, ___, ___, 8, 0xfd, 0x5d, V128Load64Zero, "v128.load64_zero", "")
WABT_OPCODE(V128, V128, ___, ___, 0, 0xfd, 0x5e, F32X4DemoteF64X2Zero, "f32x4.demote_f64x2_zero", "")
WABT_OPCODE(V128, V128, ___, ___, 0, 0xfd, 0x5f, F64X2PromoteLowF32X4, "f64x2.promote_low_f32x4", "")
WABT_OPCODE(V128, V128, ___, ___, 0, 0xfd, 0x60, I8X16Abs, "i8x16.abs", "")
diff --git a/src/prebuilt/lexer-keywords.cc b/src/prebuilt/lexer-keywords.cc
index 3a15fe5c..996daa9d 100644
--- a/src/prebuilt/lexer-keywords.cc
+++ b/src/prebuilt/lexer-keywords.cc
@@ -158,7 +158,7 @@ Perfect_Hash::InWordSet (const char *str, size_t len)
{
enum
{
- TOTAL_KEYWORDS = 601,
+ TOTAL_KEYWORDS = 603,
MIN_WORD_LENGTH = 2,
MAX_WORD_LENGTH = 29,
MIN_HASH_VALUE = 27,
@@ -470,10 +470,10 @@ Perfect_Hash::InWordSet (const char *str, size_t len)
#line 288 "src/lexer-keywords.txt"
{"i32.store16", TokenType::Store, Opcode::I32Store16},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
-#line 570 "src/lexer-keywords.txt"
+#line 572 "src/lexer-keywords.txt"
{"v128", Type::V128},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
-#line 587 "src/lexer-keywords.txt"
+#line 589 "src/lexer-keywords.txt"
{"f32.demote/f64", TokenType::Convert, Opcode::F32DemoteF64},
{""}, {""}, {""}, {""}, {""},
#line 385 "src/lexer-keywords.txt"
@@ -533,7 +533,7 @@ Perfect_Hash::InWordSet (const char *str, size_t len)
{"i64.atomic.store16", TokenType::AtomicStore, Opcode::I64AtomicStore16},
#line 251 "src/lexer-keywords.txt"
{"i32.atomic.store16", TokenType::AtomicStore, Opcode::I32AtomicStore16},
-#line 621 "src/lexer-keywords.txt"
+#line 623 "src/lexer-keywords.txt"
{"unwind", TokenType::Unwind, Opcode::Unwind},
#line 406 "src/lexer-keywords.txt"
{"i64.load32_s", TokenType::Load, Opcode::I64Load32S},
@@ -552,7 +552,7 @@ Perfect_Hash::InWordSet (const char *str, size_t len)
#line 295 "src/lexer-keywords.txt"
{"i32.trunc_f64_u", TokenType::Convert, Opcode::I32TruncF64U},
{""},
-#line 619 "src/lexer-keywords.txt"
+#line 621 "src/lexer-keywords.txt"
{"set_local", TokenType::LocalSet, Opcode::LocalSet},
#line 453 "src/lexer-keywords.txt"
{"i64x2.bitmask", TokenType::Unary, Opcode::I64X2Bitmask},
@@ -562,7 +562,7 @@ Perfect_Hash::InWordSet (const char *str, size_t len)
#line 109 "src/lexer-keywords.txt"
{"f32x4", TokenType::F32X4},
{""},
-#line 620 "src/lexer-keywords.txt"
+#line 622 "src/lexer-keywords.txt"
{"tee_local", TokenType::LocalTee, Opcode::LocalTee},
#line 338 "src/lexer-keywords.txt"
{"i32x4", TokenType::I32X4},
@@ -592,7 +592,7 @@ Perfect_Hash::InWordSet (const char *str, size_t len)
#line 542 "src/lexer-keywords.txt"
{"return_call", TokenType::ReturnCall, Opcode::ReturnCall},
{""}, {""}, {""}, {""},
-#line 569 "src/lexer-keywords.txt"
+#line 571 "src/lexer-keywords.txt"
{"v128.store", TokenType::Store, Opcode::V128Store},
#line 116 "src/lexer-keywords.txt"
{"f64.convert_i64_s", TokenType::Convert, Opcode::F64ConvertI64S},
@@ -607,13 +607,13 @@ Perfect_Hash::InWordSet (const char *str, size_t len)
#line 80 "src/lexer-keywords.txt"
{"f32.trunc", TokenType::Unary, Opcode::F32Trunc},
{""}, {""}, {""}, {""},
-#line 611 "src/lexer-keywords.txt"
+#line 613 "src/lexer-keywords.txt"
{"i64.trunc_s/f64", TokenType::Convert, Opcode::I64TruncF64S},
-#line 599 "src/lexer-keywords.txt"
+#line 601 "src/lexer-keywords.txt"
{"i32.trunc_s/f64", TokenType::Convert, Opcode::I32TruncF64S},
-#line 615 "src/lexer-keywords.txt"
+#line 617 "src/lexer-keywords.txt"
{"i64.trunc_u/f64", TokenType::Convert, Opcode::I64TruncF64U},
-#line 603 "src/lexer-keywords.txt"
+#line 605 "src/lexer-keywords.txt"
{"i32.trunc_u/f64", TokenType::Convert, Opcode::I32TruncF64U},
{""}, {""},
#line 430 "src/lexer-keywords.txt"
@@ -689,18 +689,18 @@ Perfect_Hash::InWordSet (const char *str, size_t len)
#line 33 "src/lexer-keywords.txt"
{"call_indirect", TokenType::CallIndirect, Opcode::CallIndirect},
{""},
-#line 581 "src/lexer-keywords.txt"
+#line 583 "src/lexer-keywords.txt"
{"i64.atomic.wait", TokenType::AtomicWait, Opcode::MemoryAtomicWait64},
-#line 580 "src/lexer-keywords.txt"
+#line 582 "src/lexer-keywords.txt"
{"i32.atomic.wait", TokenType::AtomicWait, Opcode::MemoryAtomicWait32},
{""}, {""}, {""}, {""}, {""},
-#line 610 "src/lexer-keywords.txt"
+#line 612 "src/lexer-keywords.txt"
{"i64.trunc_s/f32", TokenType::Convert, Opcode::I64TruncF32S},
-#line 598 "src/lexer-keywords.txt"
+#line 600 "src/lexer-keywords.txt"
{"i32.trunc_s/f32", TokenType::Convert, Opcode::I32TruncF32S},
-#line 614 "src/lexer-keywords.txt"
+#line 616 "src/lexer-keywords.txt"
{"i64.trunc_u/f32", TokenType::Convert, Opcode::I64TruncF32U},
-#line 602 "src/lexer-keywords.txt"
+#line 604 "src/lexer-keywords.txt"
{"i32.trunc_u/f32", TokenType::Convert, Opcode::I32TruncF32U},
{""}, {""},
#line 393 "src/lexer-keywords.txt"
@@ -715,11 +715,11 @@ Perfect_Hash::InWordSet (const char *str, size_t len)
{"i32x4.abs", TokenType::Unary, Opcode::I32X4Abs},
#line 171 "src/lexer-keywords.txt"
{"get", TokenType::Get},
-#line 607 "src/lexer-keywords.txt"
+#line 609 "src/lexer-keywords.txt"
{"i64.extend_s/i32", TokenType::Convert, Opcode::I64ExtendI32S},
#line 534 "src/lexer-keywords.txt"
{"ref.extern", TokenType::RefExtern},
-#line 608 "src/lexer-keywords.txt"
+#line 610 "src/lexer-keywords.txt"
{"i64.extend_u/i32", TokenType::Convert, Opcode::I64ExtendI32U},
{""}, {""},
#line 528 "src/lexer-keywords.txt"
@@ -824,13 +824,13 @@ Perfect_Hash::InWordSet (const char *str, size_t len)
{""}, {""}, {""}, {""},
#line 532 "src/lexer-keywords.txt"
{"param", TokenType::Param},
-#line 589 "src/lexer-keywords.txt"
+#line 591 "src/lexer-keywords.txt"
{"f64.convert_s/i32", TokenType::Convert, Opcode::F64ConvertI32S},
-#line 583 "src/lexer-keywords.txt"
+#line 585 "src/lexer-keywords.txt"
{"f32.convert_s/i32", TokenType::Convert, Opcode::F32ConvertI32S},
-#line 591 "src/lexer-keywords.txt"
+#line 593 "src/lexer-keywords.txt"
{"f64.convert_u/i32", TokenType::Convert, Opcode::F64ConvertI32U},
-#line 585 "src/lexer-keywords.txt"
+#line 587 "src/lexer-keywords.txt"
{"f32.convert_u/i32", TokenType::Convert, Opcode::F32ConvertI32U},
{""}, {""},
#line 541 "src/lexer-keywords.txt"
@@ -891,7 +891,10 @@ Perfect_Hash::InWordSet (const char *str, size_t len)
{""}, {""},
#line 147 "src/lexer-keywords.txt"
{"f64x2.ge", TokenType::Compare, Opcode::F64X2Ge},
- {""}, {""},
+#line 570 "src/lexer-keywords.txt"
+ {"v128.load64_zero", TokenType::Load, Opcode::V128Load64Zero},
+#line 569 "src/lexer-keywords.txt"
+ {"v128.load32_zero", TokenType::Load, Opcode::V128Load32Zero},
#line 362 "src/lexer-keywords.txt"
{"i64.atomic.rmw32.and_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw32AndU},
#line 447 "src/lexer-keywords.txt"
@@ -949,7 +952,7 @@ Perfect_Hash::InWordSet (const char *str, size_t len)
#line 66 "src/lexer-keywords.txt"
{"f32.gt", TokenType::Compare, Opcode::F32Gt},
{""},
-#line 571 "src/lexer-keywords.txt"
+#line 573 "src/lexer-keywords.txt"
{"v128.xor", TokenType::Binary, Opcode::V128Xor},
{""}, {""}, {""}, {""},
#line 357 "src/lexer-keywords.txt"
@@ -1014,13 +1017,13 @@ Perfect_Hash::InWordSet (const char *str, size_t len)
#line 315 "src/lexer-keywords.txt"
{"v128.load16x4_u", TokenType::Load, Opcode::V128Load16X4U},
{""}, {""},
-#line 590 "src/lexer-keywords.txt"
+#line 592 "src/lexer-keywords.txt"
{"f64.convert_s/i64", TokenType::Convert, Opcode::F64ConvertI64S},
-#line 584 "src/lexer-keywords.txt"
+#line 586 "src/lexer-keywords.txt"
{"f32.convert_s/i64", TokenType::Convert, Opcode::F32ConvertI64S},
-#line 592 "src/lexer-keywords.txt"
+#line 594 "src/lexer-keywords.txt"
{"f64.convert_u/i64", TokenType::Convert, Opcode::F64ConvertI64U},
-#line 586 "src/lexer-keywords.txt"
+#line 588 "src/lexer-keywords.txt"
{"f32.convert_u/i64", TokenType::Convert, Opcode::F32ConvertI64U},
{""}, {""}, {""}, {""}, {""}, {""},
#line 318 "src/lexer-keywords.txt"
@@ -1071,13 +1074,13 @@ Perfect_Hash::InWordSet (const char *str, size_t len)
{""}, {""},
#line 205 "src/lexer-keywords.txt"
{"i16x8.ne", TokenType::Compare, Opcode::I16X8Ne},
-#line 593 "src/lexer-keywords.txt"
+#line 595 "src/lexer-keywords.txt"
{"f64.promote/f32", TokenType::Convert, Opcode::F64PromoteF32},
{""}, {""},
#line 213 "src/lexer-keywords.txt"
{"i16x8.sub", TokenType::Binary, Opcode::I16X8Sub},
{""}, {""}, {""},
-#line 596 "src/lexer-keywords.txt"
+#line 598 "src/lexer-keywords.txt"
{"get_local", TokenType::LocalGet, Opcode::LocalGet},
{""},
#line 194 "src/lexer-keywords.txt"
@@ -1138,7 +1141,7 @@ Perfect_Hash::InWordSet (const char *str, size_t len)
{""}, {""}, {""}, {""}, {""}, {""},
#line 176 "src/lexer-keywords.txt"
{"i16x8.abs", TokenType::Unary, Opcode::I16X8Abs},
-#line 618 "src/lexer-keywords.txt"
+#line 620 "src/lexer-keywords.txt"
{"set_global", TokenType::GlobalSet, Opcode::GlobalSet},
{""}, {""},
#line 91 "src/lexer-keywords.txt"
@@ -1150,7 +1153,7 @@ Perfect_Hash::InWordSet (const char *str, size_t len)
#line 311 "src/lexer-keywords.txt"
{"i32x4.gt_u", TokenType::Compare, Opcode::I32X4GtU},
{""}, {""},
-#line 594 "src/lexer-keywords.txt"
+#line 596 "src/lexer-keywords.txt"
{"f64.reinterpret/i64", TokenType::Convert, Opcode::F64ReinterpretI64},
#line 308 "src/lexer-keywords.txt"
{"i32x4.ge_s", TokenType::Compare, Opcode::I32X4GeS},
@@ -1221,7 +1224,7 @@ Perfect_Hash::InWordSet (const char *str, size_t len)
{"v128.any_true", TokenType::Unary, Opcode::V128AnyTrue},
#line 484 "src/lexer-keywords.txt"
{"i8x16.le_s", TokenType::Compare, Opcode::I8X16LeS},
-#line 588 "src/lexer-keywords.txt"
+#line 590 "src/lexer-keywords.txt"
{"f32.reinterpret/i32", TokenType::Convert, Opcode::F32ReinterpretI32},
#line 485 "src/lexer-keywords.txt"
{"i8x16.le_u", TokenType::Compare, Opcode::I8X16LeU},
@@ -1232,7 +1235,7 @@ Perfect_Hash::InWordSet (const char *str, size_t len)
#line 491 "src/lexer-keywords.txt"
{"i8x16.min_u", TokenType::Binary, Opcode::I8X16MinU},
{""}, {""}, {""}, {""}, {""}, {""},
-#line 575 "src/lexer-keywords.txt"
+#line 577 "src/lexer-keywords.txt"
{"v128.load8_splat", TokenType::Load, Opcode::V128Load8Splat},
{""}, {""}, {""}, {""}, {""}, {""}, {""},
#line 366 "src/lexer-keywords.txt"
@@ -1243,13 +1246,13 @@ Perfect_Hash::InWordSet (const char *str, size_t len)
#line 182 "src/lexer-keywords.txt"
{"i16x8.bitmask", TokenType::Unary, Opcode::I16X8Bitmask},
{""},
-#line 613 "src/lexer-keywords.txt"
+#line 615 "src/lexer-keywords.txt"
{"i64.trunc_s:sat/f64", TokenType::Convert, Opcode::I64TruncSatF64S},
-#line 601 "src/lexer-keywords.txt"
+#line 603 "src/lexer-keywords.txt"
{"i32.trunc_s:sat/f64", TokenType::Convert, Opcode::I32TruncSatF64S},
-#line 617 "src/lexer-keywords.txt"
+#line 619 "src/lexer-keywords.txt"
{"i64.trunc_u:sat/f64", TokenType::Convert, Opcode::I64TruncSatF64U},
-#line 605 "src/lexer-keywords.txt"
+#line 607 "src/lexer-keywords.txt"
{"i32.trunc_u:sat/f64", TokenType::Convert, Opcode::I32TruncSatF64U},
#line 157 "src/lexer-keywords.txt"
{"f64x2.pmax", TokenType::Binary, Opcode::F64X2PMax},
@@ -1259,7 +1262,7 @@ Perfect_Hash::InWordSet (const char *str, size_t len)
#line 235 "src/lexer-keywords.txt"
{"i32.atomic.rmw16.xchg_u", TokenType::AtomicRmw, Opcode::I32AtomicRmw16XchgU},
{""}, {""}, {""}, {""}, {""},
-#line 582 "src/lexer-keywords.txt"
+#line 584 "src/lexer-keywords.txt"
{"anyfunc", Type::FuncRef},
#line 350 "src/lexer-keywords.txt"
{"i64.atomic.load16_u", TokenType::AtomicLoad, Opcode::I64AtomicLoad16U},
@@ -1285,9 +1288,9 @@ Perfect_Hash::InWordSet (const char *str, size_t len)
#line 558 "src/lexer-keywords.txt"
{"try", TokenType::Try, Opcode::Try},
{""}, {""},
-#line 574 "src/lexer-keywords.txt"
+#line 576 "src/lexer-keywords.txt"
{"v128.load64_splat", TokenType::Load, Opcode::V128Load64Splat},
-#line 573 "src/lexer-keywords.txt"
+#line 575 "src/lexer-keywords.txt"
{"v128.load32_splat", TokenType::Load, Opcode::V128Load32Splat},
{""}, {""}, {""},
#line 177 "src/lexer-keywords.txt"
@@ -1301,15 +1304,15 @@ Perfect_Hash::InWordSet (const char *str, size_t len)
#line 74 "src/lexer-keywords.txt"
{"f32.neg", TokenType::Unary, Opcode::F32Neg},
{""},
-#line 612 "src/lexer-keywords.txt"
+#line 614 "src/lexer-keywords.txt"
{"i64.trunc_s:sat/f32", TokenType::Convert, Opcode::I64TruncSatF32S},
-#line 600 "src/lexer-keywords.txt"
+#line 602 "src/lexer-keywords.txt"
{"i32.trunc_s:sat/f32", TokenType::Convert, Opcode::I32TruncSatF32S},
-#line 616 "src/lexer-keywords.txt"
+#line 618 "src/lexer-keywords.txt"
{"i64.trunc_u:sat/f32", TokenType::Convert, Opcode::I64TruncSatF32U},
-#line 604 "src/lexer-keywords.txt"
+#line 606 "src/lexer-keywords.txt"
{"i32.trunc_u:sat/f32", TokenType::Convert, Opcode::I32TruncSatF32U},
-#line 572 "src/lexer-keywords.txt"
+#line 574 "src/lexer-keywords.txt"
{"v128.load16_splat", TokenType::Load, Opcode::V128Load16Splat},
#line 502 "src/lexer-keywords.txt"
{"i8x16.sub_sat_s", TokenType::Binary, Opcode::I8X16SubSatS},
@@ -1321,7 +1324,7 @@ Perfect_Hash::InWordSet (const char *str, size_t len)
{"i64.atomic.rmw8.or_u", TokenType::AtomicRmw, Opcode::I64AtomicRmw8OrU},
#line 240 "src/lexer-keywords.txt"
{"i32.atomic.rmw8.or_u", TokenType::AtomicRmw, Opcode::I32AtomicRmw8OrU},
-#line 606 "src/lexer-keywords.txt"
+#line 608 "src/lexer-keywords.txt"
{"i32.wrap/i64", TokenType::Convert, Opcode::I32WrapI64},
{""}, {""},
#line 28 "src/lexer-keywords.txt"
@@ -1435,7 +1438,7 @@ Perfect_Hash::InWordSet (const char *str, size_t len)
#line 101 "src/lexer-keywords.txt"
{"f32x4.pmax", TokenType::Binary, Opcode::F32X4PMax},
{""}, {""}, {""}, {""}, {""}, {""},
-#line 577 "src/lexer-keywords.txt"
+#line 579 "src/lexer-keywords.txt"
{"i8x16.swizzle", TokenType::Binary, Opcode::I8X16Swizzle},
{""}, {""}, {""}, {""}, {""}, {""},
#line 44 "src/lexer-keywords.txt"
@@ -1487,10 +1490,10 @@ Perfect_Hash::InWordSet (const char *str, size_t len)
#line 340 "src/lexer-keywords.txt"
{"i32x4.trunc_sat_f32x4_u", TokenType::Unary, Opcode::I32X4TruncSatF32X4U},
{""}, {""}, {""}, {""}, {""}, {""},
-#line 595 "src/lexer-keywords.txt"
+#line 597 "src/lexer-keywords.txt"
{"get_global", TokenType::GlobalGet, Opcode::GlobalGet},
{""}, {""}, {""},
-#line 609 "src/lexer-keywords.txt"
+#line 611 "src/lexer-keywords.txt"
{"i64.reinterpret/f64", TokenType::Convert, Opcode::I64ReinterpretF64},
{""}, {""}, {""}, {""}, {""}, {""}, {""},
#line 280 "src/lexer-keywords.txt"
@@ -1532,7 +1535,7 @@ Perfect_Hash::InWordSet (const char *str, size_t len)
#line 481 "src/lexer-keywords.txt"
{"i8x16.ge_u", TokenType::Compare, Opcode::I8X16GeU},
{""}, {""}, {""},
-#line 597 "src/lexer-keywords.txt"
+#line 599 "src/lexer-keywords.txt"
{"i32.reinterpret/f32", TokenType::Convert, Opcode::I32ReinterpretF32},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
@@ -1541,7 +1544,7 @@ Perfect_Hash::InWordSet (const char *str, size_t len)
{"i8x16.splat", TokenType::Unary, Opcode::I8X16Splat},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
{""}, {""}, {""}, {""},
-#line 579 "src/lexer-keywords.txt"
+#line 581 "src/lexer-keywords.txt"
{"atomic.notify", TokenType::AtomicNotify, Opcode::MemoryAtomicNotify},
{""}, {""}, {""}, {""}, {""},
#line 37 "src/lexer-keywords.txt"
@@ -1621,7 +1624,7 @@ Perfect_Hash::InWordSet (const char *str, size_t len)
#line 60 "src/lexer-keywords.txt"
{"f32.copysign", TokenType::Binary, Opcode::F32Copysign},
{""}, {""}, {""},
-#line 576 "src/lexer-keywords.txt"
+#line 578 "src/lexer-keywords.txt"
{"i8x16.shuffle", TokenType::SimdShuffleOp, Opcode::I8X16Shuffle},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
{""}, {""},
diff --git a/src/shared-validator.cc b/src/shared-validator.cc
index 5d3b8acf..3f970276 100644
--- a/src/shared-validator.cc
+++ b/src/shared-validator.cc
@@ -895,6 +895,18 @@ Result SharedValidator::OnLoadSplat(const Location& loc,
return result;
}
+Result SharedValidator::OnLoadZero(const Location& loc,
+ Opcode opcode,
+ Address alignment) {
+ Result result = Result::Ok;
+ MemoryType mt;
+ expr_loc_ = &loc;
+ result |= CheckMemoryIndex(Var(0, loc), &mt);
+ result |= CheckAlign(loc, alignment, opcode.GetMemorySize());
+ result |= typechecker_.OnLoad(opcode, mt.limits);
+ return result;
+}
+
Result SharedValidator::OnLocalGet(const Location& loc, Var local_var) {
Result result = Result::Ok;
Type type = Type::Any;
diff --git a/src/shared-validator.h b/src/shared-validator.h
index 456693bf..34f48d72 100644
--- a/src/shared-validator.h
+++ b/src/shared-validator.h
@@ -139,6 +139,7 @@ class SharedValidator {
Result OnIf(const Location&, Type sig_type);
Result OnLoad(const Location&, Opcode, Address align);
Result OnLoadSplat(const Location&, Opcode, Address align);
+ Result OnLoadZero(const Location&, Opcode, Address align);
Result OnLocalGet(const Location&, Var);
Result OnLocalSet(const Location&, Var);
Result OnLocalTee(const Location&, Var);
diff --git a/src/validator.cc b/src/validator.cc
index 4733954f..fed3a950 100644
--- a/src/validator.cc
+++ b/src/validator.cc
@@ -151,6 +151,7 @@ class Validator : public ExprVisitor::Delegate {
Result OnSimdLaneOpExpr(SimdLaneOpExpr*) override;
Result OnSimdShuffleOpExpr(SimdShuffleOpExpr*) override;
Result OnLoadSplatExpr(LoadSplatExpr*) override;
+ Result OnLoadZeroExpr(LoadZeroExpr*) override;
private:
Type GetDeclarationType(const FuncDeclaration&);
@@ -583,6 +584,12 @@ Result Validator::OnLoadSplatExpr(LoadSplatExpr* expr) {
return Result::Ok;
}
+Result Validator::OnLoadZeroExpr(LoadZeroExpr* expr) {
+ result_ |= validator_.OnLoadZero(expr->loc, expr->opcode,
+ expr->opcode.GetAlignment(expr->align));
+ return Result::Ok;
+}
+
Validator::Validator(Errors* errors,
const Module* module,
const ValidateOptions& options)
diff --git a/src/wat-writer.cc b/src/wat-writer.cc
index 0c051f83..d6daa584 100644
--- a/src/wat-writer.cc
+++ b/src/wat-writer.cc
@@ -574,6 +574,7 @@ class WatWriter::ExprVisitorDelegate : public ExprVisitor::Delegate {
Result OnSimdLaneOpExpr(SimdLaneOpExpr*) override;
Result OnSimdShuffleOpExpr(SimdShuffleOpExpr*) override;
Result OnLoadSplatExpr(LoadSplatExpr*) override;
+ Result OnLoadZeroExpr(LoadZeroExpr*) override;
private:
WatWriter* writer_;
@@ -995,6 +996,11 @@ Result WatWriter::ExprVisitorDelegate::OnLoadSplatExpr(LoadSplatExpr* expr) {
return Result::Ok;
}
+Result WatWriter::ExprVisitorDelegate::OnLoadZeroExpr(LoadZeroExpr* expr) {
+ writer_->WriteLoadStoreExpr<LoadZeroExpr>(expr);
+ return Result::Ok;
+}
+
void WatWriter::WriteExpr(const Expr* expr) {
WABT_TRACE(WriteExprList);
ExprVisitorDelegate delegate(this);