summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSam Clegg <sbc@chromium.org>2021-12-02 17:30:09 -0800
committerGitHub <noreply@github.com>2021-12-02 17:30:09 -0800
commit0dfa83c1bc645eaa65d8e6ee51f42f8578931ecc (patch)
tree976045d56346480584f4c91eea47e7bd808db2a1
parent952560950f176913c1f54525f250e30d26c2b49a (diff)
downloadwabt-0dfa83c1bc645eaa65d8e6ee51f42f8578931ecc.tar.gz
wabt-0dfa83c1bc645eaa65d8e6ee51f42f8578931ecc.tar.bz2
wabt-0dfa83c1bc645eaa65d8e6ee51f42f8578931ecc.zip
Perform init expression validation outside of the binary reader. NFC (#1770)
Rather than spocial casing them in the reader we now use the same instruction callbacks for instruction that appear in init expressions as instructions that appear in normal functions. The result of this change is the validation of init expressions is pushed further up the stack. For example, objdump will now quite happily dump modules that use arbitrary instructions in thier init expressions even though they are not valid. To me, this makes sense since objdump does not do instruction validation elsewhere. The change is pre-cursor to allowing a wider variety of instruction to be present in init expressions. See https://github.com/WebAssembly/extended-const
-rw-r--r--src/binary-reader-ir.cc104
-rw-r--r--src/binary-reader-logging.cc46
-rw-r--r--src/binary-reader-logging.h9
-rw-r--r--src/binary-reader-nop.h27
-rw-r--r--src/binary-reader-objdump.cc175
-rw-r--r--src/binary-reader.cc123
-rw-r--r--src/binary-reader.h11
-rw-r--r--src/interp/binary-reader-interp.cc182
-rw-r--r--src/interp/interp.h1
-rw-r--r--test/opcodecnt/basic.txt10
-rw-r--r--test/spec/binary-leb128.txt24
-rw-r--r--test/spec/binary.txt56
-rw-r--r--test/spec/data.txt27
-rw-r--r--test/spec/elem.txt27
-rw-r--r--test/spec/func_ptrs.txt9
-rw-r--r--test/spec/global.txt27
-rw-r--r--test/spec/memory64/binary-leb128.txt24
-rw-r--r--test/spec/multi-memory/binary.txt56
-rw-r--r--test/spec/multi-memory/data.txt27
19 files changed, 461 insertions, 504 deletions
diff --git a/src/binary-reader-ir.cc b/src/binary-reader-ir.cc
index 6d3478c6..74d047af 100644
--- a/src/binary-reader-ir.cc
+++ b/src/binary-reader-ir.cc
@@ -259,15 +259,6 @@ class BinaryReaderIR : public BinaryReaderNop {
Result OnTagType(Index index, Index sig_index) override;
Result EndTagSection() override { return Result::Ok; }
- Result OnInitExprF32ConstExpr(Index index, uint32_t value) override;
- Result OnInitExprF64ConstExpr(Index index, uint64_t value) override;
- Result OnInitExprV128ConstExpr(Index index, v128 value) override;
- Result OnInitExprGlobalGetExpr(Index index, Index global_index) override;
- Result OnInitExprI32ConstExpr(Index index, uint32_t value) override;
- Result OnInitExprI64ConstExpr(Index index, uint64_t value) override;
- Result OnInitExprRefNull(Index index, Type type) override;
- Result OnInitExprRefFunc(Index index, Index func_index) override;
-
Result OnDataSymbol(Index index, uint32_t flags, string_view name,
Index segment, uint32_t offset, uint32_t size) override;
Result OnFunctionSymbol(Index index, uint32_t flags, string_view name,
@@ -289,6 +280,7 @@ class BinaryReaderIR : public BinaryReaderNop {
void PushLabel(LabelType label_type,
ExprList* first,
Expr* context = nullptr);
+ Result EndInitExpr();
Result PopLabel();
Result GetLabelAt(LabelNode** label, Index depth);
Result TopLabel(LabelNode** label);
@@ -313,6 +305,7 @@ class BinaryReaderIR : public BinaryReaderNop {
Func* current_func_ = nullptr;
std::vector<LabelNode> label_stack_;
ExprList* current_init_expr_ = nullptr;
+ bool current_init_expr_ended_ = false;
const char* filename_;
};
@@ -375,9 +368,13 @@ Result BinaryReaderIR::TopLabelExpr(LabelNode** label, Expr** expr) {
Result BinaryReaderIR::AppendExpr(std::unique_ptr<Expr> expr) {
expr->loc = GetLocation();
- LabelNode* label;
- CHECK_RESULT(TopLabel(&label));
- label->exprs->push_back(std::move(expr));
+ if (current_init_expr_) {
+ current_init_expr_->push_back(std::move(expr));
+ } else {
+ LabelNode* label;
+ CHECK_RESULT(TopLabel(&label));
+ label->exprs->push_back(std::move(expr));
+ }
return Result::Ok;
}
@@ -611,12 +608,12 @@ Result BinaryReaderIR::BeginGlobalInitExpr(Index index) {
assert(index == module_->globals.size() - 1);
Global* global = module_->globals[index];
current_init_expr_ = &global->init_expr;
+ current_init_expr_ended_ = false;
return Result::Ok;
}
Result BinaryReaderIR::EndGlobalInitExpr(Index index) {
- current_init_expr_ = nullptr;
- return Result::Ok;
+ return EndInitExpr();
}
Result BinaryReaderIR::OnExportCount(Index count) {
@@ -803,6 +800,11 @@ Result BinaryReaderIR::OnElseExpr() {
}
Result BinaryReaderIR::OnEndExpr() {
+ if (current_init_expr_) {
+ assert(!current_init_expr_ended_);
+ current_init_expr_ended_ = true;
+ return Result::Ok;
+ }
if (label_stack_.size() > 1) {
LabelNode* label;
Expr* expr;
@@ -1157,14 +1159,26 @@ Result BinaryReaderIR::BeginElemSegmentInitExpr(Index index) {
assert(index == module_->elem_segments.size() - 1);
ElemSegment* segment = module_->elem_segments[index];
current_init_expr_ = &segment->offset;
+ current_init_expr_ended_ = false;
return Result::Ok;
}
-Result BinaryReaderIR::EndElemSegmentInitExpr(Index index) {
+Result BinaryReaderIR::EndInitExpr() {
+ // This logic is currently duplicated in binary-reader-interp.cpp.
+ // TODO(sbc): Find a way to do this validation in SharedValidator instead.
+ if (!current_init_expr_ended_) {
+ PrintError("expected END opcode after initializer expression");
+ return Result::Error;
+ }
current_init_expr_ = nullptr;
+ current_init_expr_ended_ = false;
return Result::Ok;
}
+Result BinaryReaderIR::EndElemSegmentInitExpr(Index index) {
+ return EndInitExpr();
+}
+
Result BinaryReaderIR::OnElemSegmentElemType(Index index, Type elem_type) {
assert(index == module_->elem_segments.size() - 1);
ElemSegment* segment = module_->elem_segments[index];
@@ -1229,12 +1243,12 @@ Result BinaryReaderIR::BeginDataSegmentInitExpr(Index index) {
assert(index == module_->data_segments.size() - 1);
DataSegment* segment = module_->data_segments[index];
current_init_expr_ = &segment->offset;
+ current_init_expr_ended_ = false;
return Result::Ok;
}
Result BinaryReaderIR::EndDataSegmentInitExpr(Index index) {
- current_init_expr_ = nullptr;
- return Result::Ok;
+ return EndInitExpr();
}
Result BinaryReaderIR::OnDataSegmentData(Index index,
@@ -1416,62 +1430,6 @@ Result BinaryReaderIR::OnLocalNameLocalCount(Index index, Index count) {
return Result::Ok;
}
-Result BinaryReaderIR::OnInitExprF32ConstExpr(Index index, uint32_t value) {
- Location loc = GetLocation();
- current_init_expr_->push_back(
- MakeUnique<ConstExpr>(Const::F32(value, loc), loc));
- return Result::Ok;
-}
-
-Result BinaryReaderIR::OnInitExprF64ConstExpr(Index index, uint64_t value) {
- Location loc = GetLocation();
- current_init_expr_->push_back(
- MakeUnique<ConstExpr>(Const::F64(value, loc), loc));
- return Result::Ok;
-}
-
-Result BinaryReaderIR::OnInitExprV128ConstExpr(Index index, v128 value) {
- Location loc = GetLocation();
- current_init_expr_->push_back(
- MakeUnique<ConstExpr>(Const::V128(value, loc), loc));
- return Result::Ok;
-}
-
-Result BinaryReaderIR::OnInitExprGlobalGetExpr(Index index,
- Index global_index) {
- Location loc = GetLocation();
- current_init_expr_->push_back(
- MakeUnique<GlobalGetExpr>(Var(global_index, loc), loc));
- return Result::Ok;
-}
-
-Result BinaryReaderIR::OnInitExprI32ConstExpr(Index index, uint32_t value) {
- Location loc = GetLocation();
- current_init_expr_->push_back(
- MakeUnique<ConstExpr>(Const::I32(value, loc), loc));
- return Result::Ok;
-}
-
-Result BinaryReaderIR::OnInitExprI64ConstExpr(Index index, uint64_t value) {
- Location loc = GetLocation();
- current_init_expr_->push_back(
- MakeUnique<ConstExpr>(Const::I64(value, loc), loc));
- return Result::Ok;
-}
-
-Result BinaryReaderIR::OnInitExprRefNull(Index index, Type type) {
- Location loc = GetLocation();
- current_init_expr_->push_back(MakeUnique<RefNullExpr>(type, loc));
- return Result::Ok;
-}
-
-Result BinaryReaderIR::OnInitExprRefFunc(Index index, Index func_index) {
- Location loc = GetLocation();
- current_init_expr_->push_back(
- MakeUnique<RefFuncExpr>(Var(func_index, loc), loc));
- return Result::Ok;
-}
-
Result BinaryReaderIR::OnLocalName(Index func_index,
Index local_index,
string_view name) {
diff --git a/src/binary-reader-logging.cc b/src/binary-reader-logging.cc
index 6e0779a5..d9ae7dd7 100644
--- a/src/binary-reader-logging.cc
+++ b/src/binary-reader-logging.cc
@@ -491,48 +491,6 @@ Result BinaryReaderLogging::OnNameEntry(NameSectionSubsection type,
return reader_->OnNameEntry(type, index, name);
}
-Result BinaryReaderLogging::OnInitExprF32ConstExpr(Index index,
- uint32_t value_bits) {
- float value;
- memcpy(&value, &value_bits, sizeof(value));
- LOGF("OnInitExprF32ConstExpr(index: %" PRIindex ", value: %g (0x04%x))\n",
- index, value, value_bits);
- return reader_->OnInitExprF32ConstExpr(index, value_bits);
-}
-
-Result BinaryReaderLogging::OnInitExprF64ConstExpr(Index index,
- uint64_t value_bits) {
- double value;
- memcpy(&value, &value_bits, sizeof(value));
- LOGF("OnInitExprF64ConstExpr(index: %" PRIindex " value: %g (0x08%" PRIx64
- "))\n",
- index, value, value_bits);
- return reader_->OnInitExprF64ConstExpr(index, value_bits);
-}
-
-Result BinaryReaderLogging::OnInitExprV128ConstExpr(Index index,
- v128 value_bits) {
- LOGF("OnInitExprV128ConstExpr(index: %" PRIindex
- " value: ( 0x%08x 0x%08x 0x%08x 0x%08x))\n",
- index, value_bits.u32(0), value_bits.u32(1), value_bits.u32(2),
- value_bits.u32(3));
- return reader_->OnInitExprV128ConstExpr(index, value_bits);
-}
-
-Result BinaryReaderLogging::OnInitExprI32ConstExpr(Index index,
- uint32_t value) {
- LOGF("OnInitExprI32ConstExpr(index: %" PRIindex ", value: %u)\n", index,
- value);
- return reader_->OnInitExprI32ConstExpr(index, value);
-}
-
-Result BinaryReaderLogging::OnInitExprI64ConstExpr(Index index,
- uint64_t value) {
- LOGF("OnInitExprI64ConstExpr(index: %" PRIindex ", value: %" PRIu64 ")\n",
- index, value);
- return reader_->OnInitExprI64ConstExpr(index, value);
-}
-
Result BinaryReaderLogging::OnDylinkInfo(uint32_t mem_size,
uint32_t mem_align,
uint32_t table_size,
@@ -907,10 +865,6 @@ DEFINE_END(EndNamesSection)
DEFINE_BEGIN(BeginRelocSection)
DEFINE_END(EndRelocSection)
-DEFINE_INDEX_INDEX(OnInitExprGlobalGetExpr, "index", "global_index")
-DEFINE_INDEX_TYPE(OnInitExprRefNull)
-DEFINE_INDEX_INDEX(OnInitExprRefFunc, "index", "func_index")
-
DEFINE_BEGIN(BeginDylinkSection)
DEFINE_INDEX(OnDylinkNeededCount)
DEFINE_INDEX(OnDylinkExportCount)
diff --git a/src/binary-reader-logging.h b/src/binary-reader-logging.h
index d1531b35..c722181b 100644
--- a/src/binary-reader-logging.h
+++ b/src/binary-reader-logging.h
@@ -382,15 +382,6 @@ class BinaryReaderLogging : public BinaryReaderDelegate {
Result OnTagType(Index index, Index sig_index) override;
Result EndTagSection() override;
- Result OnInitExprF32ConstExpr(Index index, uint32_t value) override;
- Result OnInitExprF64ConstExpr(Index index, uint64_t value) override;
- Result OnInitExprV128ConstExpr(Index index, v128 value) override;
- Result OnInitExprGlobalGetExpr(Index index, Index global_index) override;
- Result OnInitExprI32ConstExpr(Index index, uint32_t value) override;
- Result OnInitExprI64ConstExpr(Index index, uint64_t value) override;
- Result OnInitExprRefNull(Index index, Type type) override;
- Result OnInitExprRefFunc(Index index, Index func_index) override;
-
private:
void Indent();
void Dedent();
diff --git a/src/binary-reader-nop.h b/src/binary-reader-nop.h
index 6bad926b..f3aae0e2 100644
--- a/src/binary-reader-nop.h
+++ b/src/binary-reader-nop.h
@@ -549,33 +549,6 @@ class BinaryReaderNop : public BinaryReaderDelegate {
return Result::Ok;
}
Result EndLinkingSection() override { return Result::Ok; }
-
- /* InitExpr - used by elem, data and global sections; these functions are
- * only called between calls to Begin*InitExpr and End*InitExpr */
- Result OnInitExprF32ConstExpr(Index index, uint32_t value) override {
- return Result::Ok;
- }
- Result OnInitExprF64ConstExpr(Index index, uint64_t value) override {
- return Result::Ok;
- }
- Result OnInitExprV128ConstExpr(Index index, v128 value) override {
- return Result::Ok;
- }
- Result OnInitExprGlobalGetExpr(Index index, Index global_index) override {
- return Result::Ok;
- }
- Result OnInitExprI32ConstExpr(Index index, uint32_t value) override {
- return Result::Ok;
- }
- Result OnInitExprI64ConstExpr(Index index, uint64_t value) override {
- return Result::Ok;
- }
- Result OnInitExprRefNull(Index index, Type type) override {
- return Result::Ok;
- }
- Result OnInitExprRefFunc(Index index, Index func_index) override {
- return Result::Ok;
- }
};
} // namespace wabt
diff --git a/src/binary-reader-objdump.cc b/src/binary-reader-objdump.cc
index 4689b1e5..51ad0694 100644
--- a/src/binary-reader-objdump.cc
+++ b/src/binary-reader-objdump.cc
@@ -462,6 +462,7 @@ class BinaryReaderObjdumpDisassemble : public BinaryReaderObjdumpBase {
std::string BlockSigToString(Type type) const;
Result BeginFunctionBody(Index index, Offset size) override;
+ Result EndFunctionBody(Index index) override;
Result OnLocalDeclCount(Index count) override;
Result OnLocalDecl(Index decl_index, Index count, Type type) override;
@@ -495,6 +496,7 @@ class BinaryReaderObjdumpDisassemble : public BinaryReaderObjdumpBase {
int indent_level = 0;
Index next_reloc = 0;
Index local_index_ = 0;
+ bool in_function_body = false;
};
std::string BinaryReaderObjdumpDisassemble::BlockSigToString(Type type) const {
@@ -508,6 +510,9 @@ std::string BinaryReaderObjdumpDisassemble::BlockSigToString(Type type) const {
}
Result BinaryReaderObjdumpDisassemble::OnOpcode(Opcode opcode) {
+ if (!in_function_body) {
+ return Result::Ok;
+ }
if (options_->debug) {
const char* opcode_name = opcode.GetName();
err_stream_->Writef("on_opcode: %#" PRIzx ": %s\n", state->offset,
@@ -535,6 +540,9 @@ Result BinaryReaderObjdumpDisassemble::OnOpcode(Opcode opcode) {
#define IMMEDIATE_OCTET_COUNT 9
Result BinaryReaderObjdumpDisassemble::OnLocalDeclCount(Index count) {
+ if (!in_function_body) {
+ return Result::Ok;
+ }
local_index_ = 0;
current_opcode_offset = state->offset;
return Result::Ok;
@@ -543,6 +551,9 @@ Result BinaryReaderObjdumpDisassemble::OnLocalDeclCount(Index count) {
Result BinaryReaderObjdumpDisassemble::OnLocalDecl(Index decl_index,
Index count,
Type type) {
+ if (!in_function_body) {
+ return Result::Ok;
+ }
Offset offset = current_opcode_offset;
size_t data_size = state->offset - offset;
@@ -572,6 +583,10 @@ Result BinaryReaderObjdumpDisassemble::OnLocalDecl(Index decl_index,
void BinaryReaderObjdumpDisassemble::LogOpcode(size_t data_size,
const char* fmt,
...) {
+ // BinaryReaderObjdumpDisassemble is only used to disassembly function bodies
+ // so this should never be called for instructions outside of function bodies
+ // (i.e. init expresions).
+ assert(in_function_body);
const Offset opcode_size = current_opcode.GetLength();
const Offset total_size = opcode_size + data_size;
// current_opcode_offset has already read past this opcode; rewind it by the
@@ -642,11 +657,17 @@ void BinaryReaderObjdumpDisassemble::LogOpcode(size_t data_size,
}
Result BinaryReaderObjdumpDisassemble::OnOpcodeBare() {
+ if (!in_function_body) {
+ return Result::Ok;
+ }
LogOpcode(0, nullptr);
return Result::Ok;
}
Result BinaryReaderObjdumpDisassemble::OnOpcodeIndex(Index value) {
+ if (!in_function_body) {
+ return Result::Ok;
+ }
Offset immediate_len = state->offset - current_opcode_offset;
string_view name;
if (current_opcode == Opcode::Call &&
@@ -666,12 +687,18 @@ Result BinaryReaderObjdumpDisassemble::OnOpcodeIndex(Index value) {
Result BinaryReaderObjdumpDisassemble::OnOpcodeIndexIndex(Index value,
Index value2) {
+ if (!in_function_body) {
+ return Result::Ok;
+ }
Offset immediate_len = state->offset - current_opcode_offset;
LogOpcode(immediate_len, "%" PRIindex " %" PRIindex, value, value2);
return Result::Ok;
}
Result BinaryReaderObjdumpDisassemble::OnOpcodeUint32(uint32_t value) {
+ if (!in_function_body) {
+ return Result::Ok;
+ }
Offset immediate_len = state->offset - current_opcode_offset;
string_view name;
if (current_opcode == Opcode::DataDrop &&
@@ -686,6 +713,8 @@ Result BinaryReaderObjdumpDisassemble::OnOpcodeUint32(uint32_t value) {
Result BinaryReaderObjdumpDisassemble::OnOpcodeUint32Uint32(uint32_t value,
uint32_t value2) {
+ if (!in_function_body)
+ return Result::Ok;
Offset immediate_len = state->offset - current_opcode_offset;
string_view name;
if (current_opcode == Opcode::MemoryInit &&
@@ -702,18 +731,27 @@ Result BinaryReaderObjdumpDisassemble::OnOpcodeUint32Uint32Uint32(
uint32_t value,
uint32_t value2,
uint32_t value3) {
+ if (!in_function_body) {
+ return Result::Ok;
+ }
Offset immediate_len = state->offset - current_opcode_offset;
LogOpcode(immediate_len, "%u %u %u", value, value2, value3);
return Result::Ok;
}
Result BinaryReaderObjdumpDisassemble::OnOpcodeUint64(uint64_t value) {
+ if (!in_function_body) {
+ return Result::Ok;
+ }
Offset immediate_len = state->offset - current_opcode_offset;
LogOpcode(immediate_len, "%" PRId64, value);
return Result::Ok;
}
Result BinaryReaderObjdumpDisassemble::OnOpcodeF32(uint32_t value) {
+ if (!in_function_body) {
+ return Result::Ok;
+ }
Offset immediate_len = state->offset - current_opcode_offset;
char buffer[WABT_MAX_FLOAT_HEX];
WriteFloatHex(buffer, sizeof(buffer), value);
@@ -722,6 +760,9 @@ Result BinaryReaderObjdumpDisassemble::OnOpcodeF32(uint32_t value) {
}
Result BinaryReaderObjdumpDisassemble::OnOpcodeF64(uint64_t value) {
+ if (!in_function_body) {
+ return Result::Ok;
+ }
Offset immediate_len = state->offset - current_opcode_offset;
char buffer[WABT_MAX_DOUBLE_HEX];
WriteDoubleHex(buffer, sizeof(buffer), value);
@@ -730,6 +771,9 @@ Result BinaryReaderObjdumpDisassemble::OnOpcodeF64(uint64_t value) {
}
Result BinaryReaderObjdumpDisassemble::OnOpcodeV128(v128 value) {
+ if (!in_function_body) {
+ return Result::Ok;
+ }
Offset immediate_len = state->offset - current_opcode_offset;
// v128 is always dumped as i32x4:
LogOpcode(immediate_len, "0x%08x 0x%08x 0x%08x 0x%08x", value.u32(0),
@@ -738,6 +782,9 @@ Result BinaryReaderObjdumpDisassemble::OnOpcodeV128(v128 value) {
}
Result BinaryReaderObjdumpDisassemble::OnOpcodeType(Type type) {
+ if (!in_function_body) {
+ return Result::Ok;
+ }
Offset immediate_len = state->offset - current_opcode_offset;
LogOpcode(immediate_len, type.GetRefKindName());
return Result::Ok;
@@ -747,6 +794,9 @@ Result BinaryReaderObjdumpDisassemble::OnBrTableExpr(
Index num_targets,
Index* target_depths,
Index default_target_depth) {
+ if (!in_function_body) {
+ return Result::Ok;
+ }
Offset immediate_len = state->offset - current_opcode_offset;
std::string buffer = std::string();
@@ -760,6 +810,9 @@ Result BinaryReaderObjdumpDisassemble::OnBrTableExpr(
}
Result BinaryReaderObjdumpDisassemble::OnDelegateExpr(Index depth) {
+ if (!in_function_body) {
+ return Result::Ok;
+ }
// Because `delegate` ends the block we need to dedent here, and
// we don't need to dedent it in LogOpcode.
if (indent_level > 0) {
@@ -769,6 +822,9 @@ Result BinaryReaderObjdumpDisassemble::OnDelegateExpr(Index depth) {
}
Result BinaryReaderObjdumpDisassemble::OnEndExpr() {
+ if (!in_function_body) {
+ return Result::Ok;
+ }
if (indent_level > 0) {
indent_level--;
}
@@ -787,10 +843,20 @@ Result BinaryReaderObjdumpDisassemble::BeginFunctionBody(Index index,
printf(":\n");
last_opcode_end = 0;
+ in_function_body = true;
+ return Result::Ok;
+}
+
+Result BinaryReaderObjdumpDisassemble::EndFunctionBody(Index index) {
+ assert(in_function_body);
+ in_function_body = false;
return Result::Ok;
}
Result BinaryReaderObjdumpDisassemble::OnOpcodeBlockSig(Type sig_type) {
+ if (!in_function_body) {
+ return Result::Ok;
+ }
Offset immediate_len = state->offset - current_opcode_offset;
if (sig_type != Type::Void) {
LogOpcode(immediate_len, "%s", BlockSigToString(sig_type).c_str());
@@ -964,15 +1030,6 @@ class BinaryReaderObjdump : public BinaryReaderObjdumpBase {
Index index,
string_view name) override;
- Result OnInitExprF32ConstExpr(Index index, uint32_t value) override;
- Result OnInitExprF64ConstExpr(Index index, uint64_t value) override;
- Result OnInitExprV128ConstExpr(Index index, v128 value) override;
- Result OnInitExprGlobalGetExpr(Index index, Index global_index) override;
- Result OnInitExprI32ConstExpr(Index index, uint32_t value) override;
- Result OnInitExprI64ConstExpr(Index index, uint64_t value) override;
- Result OnInitExprRefNull(Index index, Type type) override;
- Result OnInitExprRefFunc(Index index, Index func_index) override;
-
Result OnDylinkInfo(uint32_t mem_size,
uint32_t mem_align_log2,
uint32_t table_size,
@@ -1034,6 +1091,12 @@ class BinaryReaderObjdump : public BinaryReaderObjdumpBase {
Result OnTagCount(Index count) override;
Result OnTagType(Index index, Index sig_index) override;
+ Result OnI32ConstExpr(uint32_t value) override;
+ Result OnI64ConstExpr(uint64_t value) override;
+ Result OnF32ConstExpr(uint32_t value) override;
+ Result OnF64ConstExpr(uint64_t value) override;
+ Result OnGlobalGetExpr(Index global_index) override;
+
private:
Result InitExprToConstOffset(const InitExpr& expr, uint64_t* out_offset);
Result HandleInitExpr(const InitExpr& expr);
@@ -1058,6 +1121,11 @@ class BinaryReaderObjdump : public BinaryReaderObjdumpBase {
Index data_mem_index_ = 0;
uint64_t data_offset_ = 0;
uint64_t elem_offset_ = 0;
+
+ bool ReadingInitExpr() {
+ return reading_elem_init_expr_ || reading_data_init_expr_ ||
+ reading_global_init_expr_;
+ }
};
BinaryReaderObjdump::BinaryReaderObjdump(const uint8_t* data,
@@ -1609,63 +1677,54 @@ Result BinaryReaderObjdump::HandleInitExpr(const InitExpr& expr) {
}
}
-Result BinaryReaderObjdump::OnInitExprF32ConstExpr(Index index,
- uint32_t value) {
- InitExpr expr;
- expr.type = InitExprType::F32;
- expr.value.f32 = value;
- return HandleInitExpr(expr);
-}
-
-Result BinaryReaderObjdump::OnInitExprF64ConstExpr(Index index,
- uint64_t value) {
- InitExpr expr;
- expr.type = InitExprType::F64;
- expr.value.f64 = value;
- return HandleInitExpr(expr);
-}
-
-Result BinaryReaderObjdump::OnInitExprV128ConstExpr(Index index, v128 value) {
- InitExpr expr;
- expr.type = InitExprType::V128;
- expr.value.v128_v = value;
- return HandleInitExpr(expr);
-}
-
-Result BinaryReaderObjdump::OnInitExprGlobalGetExpr(Index index,
- Index global_index) {
- InitExpr expr;
- expr.type = InitExprType::Global;
- expr.value.index = global_index;
- return HandleInitExpr(expr);
+Result BinaryReaderObjdump::OnI32ConstExpr(uint32_t value) {
+ if (ReadingInitExpr()) {
+ InitExpr expr;
+ expr.type = InitExprType::I32;
+ expr.value.i32 = value;
+ return HandleInitExpr(expr);
+ }
+ return Result::Ok;
}
-Result BinaryReaderObjdump::OnInitExprI32ConstExpr(Index index,
- uint32_t value) {
- InitExpr expr;
- expr.type = InitExprType::I32;
- expr.value.i32 = value;
- return HandleInitExpr(expr);
+Result BinaryReaderObjdump::OnI64ConstExpr(uint64_t value) {
+ if (ReadingInitExpr()) {
+ InitExpr expr;
+ expr.type = InitExprType::I64;
+ expr.value.i64 = value;
+ return HandleInitExpr(expr);
+ }
+ return Result::Ok;
}
-Result BinaryReaderObjdump::OnInitExprI64ConstExpr(Index index,
- uint64_t value) {
- InitExpr expr;
- expr.type = InitExprType::I64;
- expr.value.i64 = value;
- return HandleInitExpr(expr);
+Result BinaryReaderObjdump::OnF32ConstExpr(uint32_t value) {
+ if (ReadingInitExpr()) {
+ InitExpr expr;
+ expr.type = InitExprType::F32;
+ expr.value.f32 = value;
+ return HandleInitExpr(expr);
+ }
+ return Result::Ok;
}
-Result BinaryReaderObjdump::OnInitExprRefNull(Index index, Type type) {
- InitExpr expr;
- expr.type = InitExprType::NullRef;
- expr.value.type = type;
- return HandleInitExpr(expr);
+Result BinaryReaderObjdump::OnF64ConstExpr(uint64_t value) {
+ if (ReadingInitExpr()) {
+ InitExpr expr;
+ expr.type = InitExprType::F64;
+ expr.value.f64 = value;
+ return HandleInitExpr(expr);
+ }
+ return Result::Ok;
}
-Result BinaryReaderObjdump::OnInitExprRefFunc(Index index, Index func_index) {
- InitExpr expr{InitExprType::FuncRef, {func_index}};
- return HandleInitExpr(expr);
+Result BinaryReaderObjdump::OnGlobalGetExpr(Index global_index) {
+ if (ReadingInitExpr()) {
+ InitExpr expr;
+ expr.type = InitExprType::Global;
+ expr.value.index = global_index;
+ return HandleInitExpr(expr);
+ }
+ return Result::Ok;
}
Result BinaryReaderObjdump::OnModuleName(string_view name) {
diff --git a/src/binary-reader.cc b/src/binary-reader.cc
index c146c7ec..e0775430 100644
--- a/src/binary-reader.cc
+++ b/src/binary-reader.cc
@@ -119,7 +119,7 @@ class BinaryReader {
Index NumTotalFuncs();
- Result ReadInitExpr(Index index, Type required = Type::Any) WABT_WARN_UNUSED;
+ Result ReadInitExpr(Index index) WABT_WARN_UNUSED;
Result ReadTable(Type* out_elem_type,
Limits* out_elem_limits) WABT_WARN_UNUSED;
Result ReadMemory(Limits* out_page_limits) WABT_WARN_UNUSED;
@@ -129,6 +129,11 @@ class BinaryReader {
Index memory,
const char* desc) WABT_WARN_UNUSED;
Result ReadFunctionBody(Offset end_offset) WABT_WARN_UNUSED;
+ // ReadInstructions either until and END instruction, or until
+ // the given end_offset.
+ Result ReadInstructions(bool stop_on_end,
+ Offset end_offset,
+ Opcode* final_opcode) WABT_WARN_UNUSED;
Result ReadNameSection(Offset section_size) WABT_WARN_UNUSED;
Result ReadRelocSection(Offset section_size) WABT_WARN_UNUSED;
Result ReadDylinkSection(Offset section_size) WABT_WARN_UNUSED;
@@ -487,91 +492,9 @@ Index BinaryReader::NumTotalFuncs() {
return num_func_imports_ + num_function_signatures_;
}
-Result BinaryReader::ReadInitExpr(Index index, Type required) {
- Opcode opcode;
- CHECK_RESULT(ReadOpcode(&opcode, "opcode"));
- ERROR_UNLESS_OPCODE_ENABLED(opcode);
-
- switch (opcode) {
- case Opcode::I32Const: {
- uint32_t value = 0;
- CHECK_RESULT(ReadS32Leb128(&value, "init_expr i32.const value"));
- CALLBACK(OnInitExprI32ConstExpr, index, value);
- break;
- }
-
- case Opcode::I64Const: {
- uint64_t value = 0;
- CHECK_RESULT(ReadS64Leb128(&value, "init_expr i64.const value"));
- CALLBACK(OnInitExprI64ConstExpr, index, value);
- break;
- }
-
- case Opcode::F32Const: {
- uint32_t value_bits = 0;
- CHECK_RESULT(ReadF32(&value_bits, "init_expr f32.const value"));
- CALLBACK(OnInitExprF32ConstExpr, index, value_bits);
- break;
- }
-
- case Opcode::F64Const: {
- uint64_t value_bits = 0;
- CHECK_RESULT(ReadF64(&value_bits, "init_expr f64.const value"));
- CALLBACK(OnInitExprF64ConstExpr, index, value_bits);
- break;
- }
-
- case Opcode::V128Const: {
- v128 value_bits;
- ZeroMemory(value_bits);
- CHECK_RESULT(ReadV128(&value_bits, "init_expr v128.const value"));
- CALLBACK(OnInitExprV128ConstExpr, index, value_bits);
- break;
- }
-
- case Opcode::GlobalGet: {
- Index global_index;
- CHECK_RESULT(ReadIndex(&global_index, "init_expr global.get index"));
- CALLBACK(OnInitExprGlobalGetExpr, index, global_index);
- break;
- }
-
- case Opcode::RefNull: {
- Type type;
- CHECK_RESULT(ReadRefType(&type, "ref.null type"));
- CALLBACK(OnInitExprRefNull, index, type);
- break;
- }
-
- case Opcode::RefFunc: {
- Index func_index;
- CHECK_RESULT(ReadIndex(&func_index, "init_expr ref.func index"));
- CALLBACK(OnInitExprRefFunc, index, func_index);
- break;
- }
-
- case Opcode::End:
- return Result::Ok;
-
- default:
- return ReportUnexpectedOpcode(opcode, "in initializer expression");
- }
-
- if (required == Type::I32 && opcode != Opcode::I32Const &&
- opcode != Opcode::GlobalGet) {
- PrintError("expected i32 init_expr");
- return Result::Error;
- }
- if (required == Type::I64 && opcode != Opcode::I64Const &&
- opcode != Opcode::GlobalGet) {
- PrintError("expected i64 init_expr");
- return Result::Error;
- }
-
- CHECK_RESULT(ReadOpcode(&opcode, "opcode"));
- ERROR_UNLESS(opcode == Opcode::End,
- "expected END opcode after initializer expression");
- return Result::Ok;
+Result BinaryReader::ReadInitExpr(Index index) {
+ // Read instructions until END opcode is reached.
+ return ReadInstructions(/*stop_on_end=*/true, read_end_, NULL);
}
Result BinaryReader::ReadTable(Type* out_elem_type, Limits* out_elem_limits) {
@@ -672,12 +595,27 @@ Result BinaryReader::ReadAddress(Address* out_value,
}
Result BinaryReader::ReadFunctionBody(Offset end_offset) {
- bool seen_end_opcode = false;
+ Opcode final_opcode(Opcode::Invalid);
+ CHECK_RESULT(
+ ReadInstructions(/*stop_on_end=*/false, end_offset, &final_opcode));
+ ERROR_UNLESS(state_.offset == end_offset,
+ "function body longer than given size");
+ ERROR_UNLESS(final_opcode == Opcode::End,
+ "function body must end with END opcode");
+ return Result::Ok;
+}
+
+Result BinaryReader::ReadInstructions(bool stop_on_end,
+ Offset end_offset,
+ Opcode* final_opcode) {
while (state_.offset < end_offset) {
Opcode opcode;
CHECK_RESULT(ReadOpcode(&opcode, "opcode"));
CALLBACK(OnOpcode, opcode);
ERROR_UNLESS_OPCODE_ENABLED(opcode);
+ if (final_opcode) {
+ *final_opcode = opcode;
+ }
switch (opcode) {
case Opcode::Unreachable:
@@ -801,8 +739,8 @@ Result BinaryReader::ReadFunctionBody(Offset end_offset) {
case Opcode::End:
CALLBACK0(OnEndExpr);
- if (state_.offset == end_offset) {
- seen_end_opcode = true;
+ if (stop_on_end) {
+ return Result::Ok;
}
break;
@@ -1823,9 +1761,6 @@ Result BinaryReader::ReadFunctionBody(Offset end_offset) {
return ReportUnexpectedOpcode(opcode);
}
}
- ERROR_UNLESS(state_.offset == end_offset,
- "function body longer than given size");
- ERROR_UNLESS(seen_end_opcode, "function body must end with END opcode");
return Result::Ok;
}
@@ -2616,7 +2551,7 @@ Result BinaryReader::ReadElemSection(Offset section_size) {
if (!(flags & SegPassive)) {
CALLBACK(BeginElemSegmentInitExpr, i);
- CHECK_RESULT(ReadInitExpr(i, Type::I32));
+ CHECK_RESULT(ReadInitExpr(i));
CALLBACK(EndElemSegmentInitExpr, i);
}
@@ -2733,7 +2668,7 @@ Result BinaryReader::ReadDataSection(Offset section_size) {
if (!(flags & SegPassive)) {
ERROR_UNLESS(memories.size() > 0, "no memory to copy data to");
CALLBACK(BeginDataSegmentInitExpr, i);
- CHECK_RESULT(ReadInitExpr(i, memories[0].IndexType()));
+ CHECK_RESULT(ReadInitExpr(i));
CALLBACK(EndDataSegmentInitExpr, i);
}
diff --git a/src/binary-reader.h b/src/binary-reader.h
index 65095791..d000dd9b 100644
--- a/src/binary-reader.h
+++ b/src/binary-reader.h
@@ -460,17 +460,6 @@ class BinaryReaderDelegate {
virtual Result OnTagType(Index index, Index sig_index) = 0;
virtual Result EndTagSection() = 0;
- /* InitExpr - used by elem, data and global sections; these functions are
- * only called between calls to Begin*InitExpr and End*InitExpr */
- virtual Result OnInitExprF32ConstExpr(Index index, uint32_t value) = 0;
- virtual Result OnInitExprF64ConstExpr(Index index, uint64_t value) = 0;
- virtual Result OnInitExprV128ConstExpr(Index index, v128 value) = 0;
- virtual Result OnInitExprGlobalGetExpr(Index index, Index global_index) = 0;
- virtual Result OnInitExprI32ConstExpr(Index index, uint32_t value) = 0;
- virtual Result OnInitExprI64ConstExpr(Index index, uint64_t value) = 0;
- virtual Result OnInitExprRefNull(Index index, Type type) = 0;
- virtual Result OnInitExprRefFunc(Index index, Index func_index) = 0;
-
const State* state = nullptr;
};
diff --git a/src/interp/binary-reader-interp.cc b/src/interp/binary-reader-interp.cc
index 659e14e3..40e85fd5 100644
--- a/src/interp/binary-reader-interp.cc
+++ b/src/interp/binary-reader-interp.cc
@@ -132,6 +132,7 @@ class BinaryReaderInterp : public BinaryReaderNop {
Result OnGlobalCount(Index count) override;
Result BeginGlobal(Index index, Type type, bool mutable_) override;
+ Result BeginGlobalInitExpr(Index index) override;
Result EndGlobalInitExpr(Index index) override;
Result OnTagCount(Index count) override;
@@ -255,6 +256,7 @@ class BinaryReaderInterp : public BinaryReaderNop {
Result BeginElemSegment(Index index,
Index table_index,
uint8_t flags) override;
+ Result BeginElemSegmentInitExpr(Index index) override;
Result EndElemSegmentInitExpr(Index index) override;
Result OnElemSegmentElemType(Index index, Type elem_type) override;
Result OnElemSegmentElemExprCount(Index index, Index count) override;
@@ -263,6 +265,7 @@ class BinaryReaderInterp : public BinaryReaderNop {
Index func_index) override;
Result OnDataCount(Index count) override;
+ Result BeginDataSegmentInitExpr(Index index) override;
Result EndDataSegmentInitExpr(Index index) override;
Result BeginDataSegment(Index index,
Index memory_index,
@@ -271,15 +274,6 @@ class BinaryReaderInterp : public BinaryReaderNop {
const void* data,
Address size) override;
- Result OnInitExprF32ConstExpr(Index index, uint32_t value) override;
- Result OnInitExprF64ConstExpr(Index index, uint64_t value) override;
- Result OnInitExprV128ConstExpr(Index index, v128 value) override;
- Result OnInitExprGlobalGetExpr(Index index, Index global_index) override;
- Result OnInitExprI32ConstExpr(Index index, uint32_t value) override;
- Result OnInitExprI64ConstExpr(Index index, uint64_t value) override;
- Result OnInitExprRefNull(Index index, Type type) override;
- Result OnInitExprRefFunc(Index index, Index func_index) override;
-
private:
Label* GetLabel(Index depth);
Label* GetNearestTryLabel(Index depth);
@@ -303,6 +297,11 @@ class BinaryReaderInterp : public BinaryReaderNop {
Index keep_extra,
Index* out_drop_count,
Index* out_keep_count);
+ Result BeginInitExpr();
+ Result EndInitExpr();
+ Result CheckEmptyInitExpr();
+ Result CheckNotInitExpr();
+
void EmitBr(Index depth,
Index drop_count,
Index keep_count,
@@ -325,6 +324,7 @@ class BinaryReaderInterp : public BinaryReaderNop {
FixupMap depth_fixups_;
FixupMap func_fixups_;
+ bool reading_init_expr_ = false;
InitExpr init_expr_;
u32 local_decl_count_;
u32 local_count_;
@@ -620,7 +620,47 @@ Result BinaryReaderInterp::BeginGlobal(Index index, Type type, bool mutable_) {
return Result::Ok;
}
+Result BinaryReaderInterp::BeginGlobalInitExpr(Index index) {
+ return BeginInitExpr();
+}
+
+Result BinaryReaderInterp::EndInitExpr() {
+ assert(reading_init_expr_);
+ reading_init_expr_ = false;
+ if (!init_expr_.ended) {
+ PrintError("expected END opcode after initializer expression");
+ return Result::Error;
+ }
+ return Result::Ok;
+}
+
+Result BinaryReaderInterp::BeginInitExpr() {
+ assert(!reading_init_expr_);
+ reading_init_expr_ = true;
+ init_expr_.kind = InitExprKind::None;
+ init_expr_.ended = false;
+ return Result::Ok;
+}
+
+Result BinaryReaderInterp::CheckEmptyInitExpr() {
+ assert(reading_init_expr_);
+ if (init_expr_.kind != InitExprKind::None) {
+ PrintError("expected END opcode after initializer expression");
+ return Result::Error;
+ }
+ return Result::Ok;
+}
+
+Result BinaryReaderInterp::CheckNotInitExpr() {
+ if (reading_init_expr_) {
+ PrintError("Unepxected opcode in init expr");
+ return Result::Error;
+ }
+ return Result::Ok;
+}
+
Result BinaryReaderInterp::EndGlobalInitExpr(Index index) {
+ CHECK_RESULT(EndInitExpr());
switch (init_expr_.kind) {
case InitExprKind::I32:
CHECK_RESULT(validator_.OnGlobalInitExpr_Const(loc, ValueType::I32));
@@ -666,58 +706,6 @@ Result BinaryReaderInterp::EndGlobalInitExpr(Index index) {
return Result::Ok;
}
-Result BinaryReaderInterp::OnInitExprF32ConstExpr(Index index,
- uint32_t value_bits) {
- init_expr_.kind = InitExprKind::F32;
- init_expr_.f32_ = Bitcast<f32>(value_bits);
- return Result::Ok;
-}
-
-Result BinaryReaderInterp::OnInitExprF64ConstExpr(Index index,
- uint64_t value_bits) {
- init_expr_.kind = InitExprKind::F64;
- init_expr_.f64_ = Bitcast<f64>(value_bits);
- return Result::Ok;
-}
-
-Result BinaryReaderInterp::OnInitExprV128ConstExpr(Index index,
- v128 value_bits) {
- init_expr_.kind = InitExprKind::V128;
- init_expr_.v128_ = Bitcast<v128>(value_bits);
- return Result::Ok;
-}
-
-Result BinaryReaderInterp::OnInitExprGlobalGetExpr(Index index,
- Index global_index) {
- init_expr_.kind = InitExprKind::GlobalGet;
- init_expr_.index_ = global_index;
- return Result::Ok;
-}
-
-Result BinaryReaderInterp::OnInitExprI32ConstExpr(Index index, uint32_t value) {
- init_expr_.kind = InitExprKind::I32;
- init_expr_.i32_ = value;
- return Result::Ok;
-}
-
-Result BinaryReaderInterp::OnInitExprI64ConstExpr(Index index, uint64_t value) {
- init_expr_.kind = InitExprKind::I64;
- init_expr_.i64_ = value;
- return Result::Ok;
-}
-
-Result BinaryReaderInterp::OnInitExprRefNull(Index index, Type type) {
- init_expr_.kind = InitExprKind::RefNull;
- init_expr_.type_ = type;
- return Result::Ok;
-}
-
-Result BinaryReaderInterp::OnInitExprRefFunc(Index index, Index func_index) {
- init_expr_.kind = InitExprKind::RefFunc;
- init_expr_.index_ = func_index;
- return Result::Ok;
-}
-
Result BinaryReaderInterp::OnTagCount(Index count) {
module_.tags.reserve(count);
return Result::Ok;
@@ -777,7 +765,12 @@ Result BinaryReaderInterp::BeginElemSegment(Index index,
return Result::Ok;
}
+Result BinaryReaderInterp::BeginElemSegmentInitExpr(Index index) {
+ return BeginInitExpr();
+}
+
Result BinaryReaderInterp::EndElemSegmentInitExpr(Index index) {
+ CHECK_RESULT(EndInitExpr());
switch (init_expr_.kind) {
case InitExprKind::I32:
CHECK_RESULT(validator_.OnElemSegmentInitExpr_Const(loc, ValueType::I32));
@@ -834,7 +827,12 @@ Result BinaryReaderInterp::OnDataCount(Index count) {
return Result::Ok;
}
+Result BinaryReaderInterp::BeginDataSegmentInitExpr(Index index) {
+ return BeginInitExpr();
+}
+
Result BinaryReaderInterp::EndDataSegmentInitExpr(Index index) {
+ CHECK_RESULT(EndInitExpr());
switch (init_expr_.kind) {
case InitExprKind::I32:
CHECK_RESULT(validator_.OnDataSegmentInitExpr_Const(loc, ValueType::I32));
@@ -960,7 +958,7 @@ Index BinaryReaderInterp::num_func_imports() const {
}
Result BinaryReaderInterp::OnOpcode(Opcode opcode) {
- if (func_ == nullptr || label_stack_.empty()) {
+ if ((func_ == nullptr || label_stack_.empty()) && !reading_init_expr_) {
PrintError("Unexpected instruction after end of function");
return Result::Error;
}
@@ -968,12 +966,14 @@ Result BinaryReaderInterp::OnOpcode(Opcode opcode) {
}
Result BinaryReaderInterp::OnUnaryExpr(Opcode opcode) {
+ CHECK_RESULT(CheckNotInitExpr());
CHECK_RESULT(validator_.OnUnary(loc, opcode));
istream_.Emit(opcode);
return Result::Ok;
}
Result BinaryReaderInterp::OnTernaryExpr(Opcode opcode) {
+ CHECK_RESULT(CheckNotInitExpr());
CHECK_RESULT(validator_.OnTernary(loc, opcode));
istream_.Emit(opcode);
return Result::Ok;
@@ -1100,6 +1100,14 @@ Result BinaryReaderInterp::OnElseExpr() {
}
Result BinaryReaderInterp::OnEndExpr() {
+ if (reading_init_expr_) {
+ if (init_expr_.ended) {
+ PrintError("duplicate END opcode init initializer expression");
+ return Result::Error;
+ }
+ init_expr_.ended = true;
+ return Result::Ok;
+ }
if (label_stack_.size() == 1) {
return Result::Ok;
}
@@ -1263,41 +1271,78 @@ Result BinaryReaderInterp::OnDropExpr() {
Result BinaryReaderInterp::OnI32ConstExpr(uint32_t value) {
CHECK_RESULT(validator_.OnConst(loc, Type::I32));
+ if (reading_init_expr_) {
+ CHECK_RESULT(CheckEmptyInitExpr());
+ init_expr_.kind = InitExprKind::I32;
+ init_expr_.i32_ = value;
+ return Result::Ok;
+ }
istream_.Emit(Opcode::I32Const, value);
return Result::Ok;
}
Result BinaryReaderInterp::OnI64ConstExpr(uint64_t value) {
CHECK_RESULT(validator_.OnConst(loc, Type::I64));
+ if (reading_init_expr_) {
+ CHECK_RESULT(CheckEmptyInitExpr());
+ init_expr_.kind = InitExprKind::I64;
+ init_expr_.i64_ = value;
+ return Result::Ok;
+ }
istream_.Emit(Opcode::I64Const, value);
return Result::Ok;
}
Result BinaryReaderInterp::OnF32ConstExpr(uint32_t value_bits) {
CHECK_RESULT(validator_.OnConst(loc, Type::F32));
+ if (reading_init_expr_) {
+ CHECK_RESULT(CheckEmptyInitExpr());
+ init_expr_.kind = InitExprKind::F32;
+ init_expr_.f32_ = Bitcast<f32>(value_bits);
+ return Result::Ok;
+ }
istream_.Emit(Opcode::F32Const, value_bits);
return Result::Ok;
}
Result BinaryReaderInterp::OnF64ConstExpr(uint64_t value_bits) {
CHECK_RESULT(validator_.OnConst(loc, Type::F64));
+ if (reading_init_expr_) {
+ CHECK_RESULT(CheckEmptyInitExpr());
+ init_expr_.kind = InitExprKind::F64;
+ init_expr_.f64_ = Bitcast<f64>(value_bits);
+ return Result::Ok;
+ }
istream_.Emit(Opcode::F64Const, value_bits);
return Result::Ok;
}
Result BinaryReaderInterp::OnV128ConstExpr(v128 value_bits) {
CHECK_RESULT(validator_.OnConst(loc, Type::V128));
+ if (reading_init_expr_) {
+ CHECK_RESULT(CheckEmptyInitExpr());
+ init_expr_.kind = InitExprKind::V128;
+ init_expr_.v128_ = Bitcast<v128>(value_bits);
+ return Result::Ok;
+ }
istream_.Emit(Opcode::V128Const, value_bits);
return Result::Ok;
}
Result BinaryReaderInterp::OnGlobalGetExpr(Index global_index) {
+ if (reading_init_expr_) {
+ CHECK_RESULT(CheckEmptyInitExpr());
+ init_expr_.kind = InitExprKind::GlobalGet;
+ init_expr_.index_ = global_index;
+ return Result::Ok;
+ }
CHECK_RESULT(validator_.OnGlobalGet(loc, Var(global_index)));
istream_.Emit(Opcode::GlobalGet, global_index);
return Result::Ok;
}
Result BinaryReaderInterp::OnGlobalSetExpr(Index global_index) {
+ CHECK_RESULT(CheckNotInitExpr());
CHECK_RESULT(validator_.OnGlobalSet(loc, Var(global_index)));
istream_.Emit(Opcode::GlobalSet, global_index);
return Result::Ok;
@@ -1383,6 +1428,12 @@ Result BinaryReaderInterp::OnTableFillExpr(Index table_index) {
}
Result BinaryReaderInterp::OnRefFuncExpr(Index func_index) {
+ if (reading_init_expr_) {
+ CHECK_RESULT(CheckEmptyInitExpr());
+ init_expr_.kind = InitExprKind::RefFunc;
+ init_expr_.index_ = func_index;
+ return Result::Ok;
+ }
CHECK_RESULT(validator_.OnRefFunc(loc, Var(func_index)));
istream_.Emit(Opcode::RefFunc, func_index);
return Result::Ok;
@@ -1390,6 +1441,12 @@ Result BinaryReaderInterp::OnRefFuncExpr(Index func_index) {
Result BinaryReaderInterp::OnRefNullExpr(Type type) {
CHECK_RESULT(validator_.OnRefNull(loc, type));
+ if (reading_init_expr_) {
+ CHECK_RESULT(CheckEmptyInitExpr());
+ init_expr_.kind = InitExprKind::RefNull;
+ init_expr_.type_ = type;
+ return Result::Ok;
+ }
istream_.Emit(Opcode::RefNull);
return Result::Ok;
}
@@ -1401,6 +1458,7 @@ Result BinaryReaderInterp::OnRefIsNullExpr() {
}
Result BinaryReaderInterp::OnNopExpr() {
+ CHECK_RESULT(CheckNotInitExpr());
CHECK_RESULT(validator_.OnNop(loc));
return Result::Ok;
}
diff --git a/src/interp/interp.h b/src/interp/interp.h
index 34a220c7..0247d48a 100644
--- a/src/interp/interp.h
+++ b/src/interp/interp.h
@@ -109,6 +109,7 @@ enum class InitExprKind {
struct InitExpr {
InitExprKind kind;
+ bool ended = false;
union {
u32 i32_;
u64 i64_;
diff --git a/test/opcodecnt/basic.txt b/test/opcodecnt/basic.txt
index 39ddb85e..79696d57 100644
--- a/test/opcodecnt/basic.txt
+++ b/test/opcodecnt/basic.txt
@@ -20,24 +20,24 @@
f32.add
br 0))
(;; STDOUT ;;;
-Total opcodes: 16
+Total opcodes: 18
Opcode counts:
local.get: 5
-i32.const: 3
-end: 2
+i32.const: 4
+end: 3
br: 2
f32.const: 2
i32.load: 1
f32.add: 1
Opcode counts with immediates:
+end: 3
local.get 0: 3
-end: 2
br 0: 2
local.get 1: 2
+i32.const 0 (0x0): 2
i32.load 2, 0: 1
-i32.const 0 (0x0): 1
i32.const 1 (0x1): 1
i32.const 2 (0x2): 1
f32.const 2 (0x1p+1): 1
diff --git a/test/spec/binary-leb128.txt b/test/spec/binary-leb128.txt
index 26e3bf71..8e316f2d 100644
--- a/test/spec/binary-leb128.txt
+++ b/test/spec/binary-leb128.txt
@@ -40,13 +40,13 @@ out/test/spec/binary-leb128.wast:443: assert_malformed passed:
out/test/spec/binary-leb128.wast:462: assert_malformed passed:
0000024: error: unable to read u32 leb128: store offset
out/test/spec/binary-leb128.wast:483: assert_malformed passed:
- 000000e: error: unable to read i32 leb128: init_expr i32.const value
+ 000000e: error: unable to read i32 leb128: i32.const value
out/test/spec/binary-leb128.wast:493: assert_malformed passed:
- 000000e: error: unable to read i32 leb128: init_expr i32.const value
+ 000000e: error: unable to read i32 leb128: i32.const value
out/test/spec/binary-leb128.wast:504: assert_malformed passed:
- 000000e: error: unable to read i64 leb128: init_expr i64.const value
+ 000000e: error: unable to read i64 leb128: i64.const value
out/test/spec/binary-leb128.wast:514: assert_malformed passed:
- 000000e: error: unable to read i64 leb128: init_expr i64.const value
+ 000000e: error: unable to read i64 leb128: i64.const value
out/test/spec/binary-leb128.wast:526: assert_malformed passed:
000000c: error: unable to read u32 leb128: memory initial page count
out/test/spec/binary-leb128.wast:534: assert_malformed passed:
@@ -98,21 +98,21 @@ out/test/spec/binary-leb128.wast:844: assert_malformed passed:
out/test/spec/binary-leb128.wast:863: assert_malformed passed:
0000024: error: unable to read u32 leb128: store offset
out/test/spec/binary-leb128.wast:885: assert_malformed passed:
- 000000e: error: unable to read i32 leb128: init_expr i32.const value
+ 000000e: error: unable to read i32 leb128: i32.const value
out/test/spec/binary-leb128.wast:895: assert_malformed passed:
- 000000e: error: unable to read i32 leb128: init_expr i32.const value
+ 000000e: error: unable to read i32 leb128: i32.const value
out/test/spec/binary-leb128.wast:905: assert_malformed passed:
- 000000e: error: unable to read i32 leb128: init_expr i32.const value
+ 000000e: error: unable to read i32 leb128: i32.const value
out/test/spec/binary-leb128.wast:915: assert_malformed passed:
- 000000e: error: unable to read i32 leb128: init_expr i32.const value
+ 000000e: error: unable to read i32 leb128: i32.const value
out/test/spec/binary-leb128.wast:926: assert_malformed passed:
- 000000e: error: unable to read i64 leb128: init_expr i64.const value
+ 000000e: error: unable to read i64 leb128: i64.const value
out/test/spec/binary-leb128.wast:936: assert_malformed passed:
- 000000e: error: unable to read i64 leb128: init_expr i64.const value
+ 000000e: error: unable to read i64 leb128: i64.const value
out/test/spec/binary-leb128.wast:946: assert_malformed passed:
- 000000e: error: unable to read i64 leb128: init_expr i64.const value
+ 000000e: error: unable to read i64 leb128: i64.const value
out/test/spec/binary-leb128.wast:956: assert_malformed passed:
- 000000e: error: unable to read i64 leb128: init_expr i64.const value
+ 000000e: error: unable to read i64 leb128: i64.const value
out/test/spec/binary-leb128.wast:988: assert_malformed passed:
0000019: error: unable to read u32 leb128: opcode
57/57 tests passed.
diff --git a/test/spec/binary.txt b/test/spec/binary.txt
index 0c901ca6..2bcc503a 100644
--- a/test/spec/binary.txt
+++ b/test/spec/binary.txt
@@ -72,41 +72,41 @@ out/test/spec/binary.wast:165: assert_malformed passed:
out/test/spec/binary.wast:178: assert_malformed passed:
000000c: error: unable to read u32 leb128: memory initial page count
out/test/spec/binary.wast:188: assert_malformed passed:
- 000000e: error: unable to read i32 leb128: init_expr i32.const value
+ 000000e: error: unable to read i32 leb128: i32.const value
out/test/spec/binary.wast:198: assert_malformed passed:
- 000000e: error: unable to read i32 leb128: init_expr i32.const value
+ 000000e: error: unable to read i32 leb128: i32.const value
out/test/spec/binary.wast:209: assert_malformed passed:
- 000000e: error: unable to read i64 leb128: init_expr i64.const value
+ 000000e: error: unable to read i64 leb128: i64.const value
out/test/spec/binary.wast:219: assert_malformed passed:
- 000000e: error: unable to read i64 leb128: init_expr i64.const value
+ 000000e: error: unable to read i64 leb128: i64.const value
out/test/spec/binary.wast:231: assert_malformed passed:
000000c: error: unable to read u32 leb128: memory initial page count
out/test/spec/binary.wast:239: assert_malformed passed:
000000c: error: unable to read u32 leb128: memory initial page count
out/test/spec/binary.wast:249: assert_malformed passed:
- 000000e: error: unable to read i32 leb128: init_expr i32.const value
+ 000000e: error: unable to read i32 leb128: i32.const value
out/test/spec/binary.wast:259: assert_malformed passed:
- 000000e: error: unable to read i32 leb128: init_expr i32.const value
+ 000000e: error: unable to read i32 leb128: i32.const value
out/test/spec/binary.wast:269: assert_malformed passed:
- 000000e: error: unable to read i32 leb128: init_expr i32.const value
+ 000000e: error: unable to read i32 leb128: i32.const value
out/test/spec/binary.wast:279: assert_malformed passed:
- 000000e: error: unable to read i32 leb128: init_expr i32.const value
+ 000000e: error: unable to read i32 leb128: i32.const value
out/test/spec/binary.wast:290: assert_malformed passed:
- 000000e: error: unable to read i64 leb128: init_expr i64.const value
+ 000000e: error: unable to read i64 leb128: i64.const value
out/test/spec/binary.wast:300: assert_malformed passed:
- 000000e: error: unable to read i64 leb128: init_expr i64.const value
+ 000000e: error: unable to read i64 leb128: i64.const value
out/test/spec/binary.wast:310: assert_malformed passed:
- 000000e: error: unable to read i64 leb128: init_expr i64.const value
+ 000000e: error: unable to read i64 leb128: i64.const value
out/test/spec/binary.wast:320: assert_malformed passed:
- 000000e: error: unable to read i64 leb128: init_expr i64.const value
+ 000000e: error: unable to read i64 leb128: i64.const value
out/test/spec/binary.wast:331: assert_malformed passed:
- 000000e: error: unable to read i64 leb128: init_expr i64.const value
+ 000000e: error: unable to read i64 leb128: i64.const value
out/test/spec/binary.wast:341: assert_malformed passed:
- 000000e: error: unable to read i64 leb128: init_expr i64.const value
+ 000000e: error: unable to read i64 leb128: i64.const value
out/test/spec/binary.wast:351: assert_malformed passed:
- 000000e: error: unable to read i64 leb128: init_expr i64.const value
+ 000000e: error: unable to read i64 leb128: i64.const value
out/test/spec/binary.wast:361: assert_malformed passed:
- 000000e: error: unable to read i64 leb128: init_expr i64.const value
+ 000000e: error: unable to read i64 leb128: i64.const value
out/test/spec/binary.wast:374: assert_malformed passed:
000000c: error: unable to read u32 leb128: memory initial page count
out/test/spec/binary.wast:382: assert_malformed passed:
@@ -118,13 +118,13 @@ out/test/spec/binary.wast:420: assert_malformed passed:
out/test/spec/binary.wast:439: assert_malformed passed:
0000024: error: unable to read u32 leb128: store offset
out/test/spec/binary.wast:460: assert_malformed passed:
- 000000e: error: unable to read i32 leb128: init_expr i32.const value
+ 000000e: error: unable to read i32 leb128: i32.const value
out/test/spec/binary.wast:470: assert_malformed passed:
- 000000e: error: unable to read i32 leb128: init_expr i32.const value
+ 000000e: error: unable to read i32 leb128: i32.const value
out/test/spec/binary.wast:481: assert_malformed passed:
- 000000e: error: unable to read i64 leb128: init_expr i64.const value
+ 000000e: error: unable to read i64 leb128: i64.const value
out/test/spec/binary.wast:491: assert_malformed passed:
- 000000e: error: unable to read i64 leb128: init_expr i64.const value
+ 000000e: error: unable to read i64 leb128: i64.const value
out/test/spec/binary.wast:503: assert_malformed passed:
000000c: error: unable to read u32 leb128: memory initial page count
out/test/spec/binary.wast:511: assert_malformed passed:
@@ -146,21 +146,21 @@ out/test/spec/binary.wast:632: assert_malformed passed:
out/test/spec/binary.wast:651: assert_malformed passed:
0000024: error: unable to read u32 leb128: store offset
out/test/spec/binary.wast:673: assert_malformed passed:
- 000000e: error: unable to read i32 leb128: init_expr i32.const value
+ 000000e: error: unable to read i32 leb128: i32.const value
out/test/spec/binary.wast:683: assert_malformed passed:
- 000000e: error: unable to read i32 leb128: init_expr i32.const value
+ 000000e: error: unable to read i32 leb128: i32.const value
out/test/spec/binary.wast:693: assert_malformed passed:
- 000000e: error: unable to read i32 leb128: init_expr i32.const value
+ 000000e: error: unable to read i32 leb128: i32.const value
out/test/spec/binary.wast:703: assert_malformed passed:
- 000000e: error: unable to read i32 leb128: init_expr i32.const value
+ 000000e: error: unable to read i32 leb128: i32.const value
out/test/spec/binary.wast:714: assert_malformed passed:
- 000000e: error: unable to read i64 leb128: init_expr i64.const value
+ 000000e: error: unable to read i64 leb128: i64.const value
out/test/spec/binary.wast:724: assert_malformed passed:
- 000000e: error: unable to read i64 leb128: init_expr i64.const value
+ 000000e: error: unable to read i64 leb128: i64.const value
out/test/spec/binary.wast:734: assert_malformed passed:
- 000000e: error: unable to read i64 leb128: init_expr i64.const value
+ 000000e: error: unable to read i64 leb128: i64.const value
out/test/spec/binary.wast:744: assert_malformed passed:
- 000000e: error: unable to read i64 leb128: init_expr i64.const value
+ 000000e: error: unable to read i64 leb128: i64.const value
out/test/spec/binary.wast:756: assert_malformed passed:
0000020: error: memory.grow reserved value must be 0
out/test/spec/binary.wast:776: assert_malformed passed:
diff --git a/test/spec/data.txt b/test/spec/data.txt
index 5b99dd1e..b8645eb8 100644
--- a/test/spec/data.txt
+++ b/test/spec/data.txt
@@ -20,26 +20,35 @@ out/test/spec/data.wast:359: assert_invalid passed:
0000000: error: memory variable out of range: 1 (max 0)
000000d: error: BeginDataSegment callback failed
out/test/spec/data.wast:378: assert_invalid passed:
- 0000013: error: expected i32 init_expr
+ error: type mismatch at data segment offset. got i64, expected i32
+ 0000014: error: EndDataSegmentInitExpr callback failed
out/test/spec/data.wast:386: assert_invalid passed:
- 0000013: error: expected i32 init_expr
+ error: invalid data segment offset, must be a constant expression; either iXX.const or global.get.
+ 0000014: error: EndDataSegmentInitExpr callback failed
out/test/spec/data.wast:394: assert_invalid passed:
error: invalid data segment offset, must be a constant expression; either iXX.const or global.get.
0000012: error: EndDataSegmentInitExpr callback failed
out/test/spec/data.wast:402: assert_invalid passed:
- 0000014: error: expected END opcode after initializer expression
+ error: expected END opcode after initializer expression
+ 0000015: error: OnI32ConstExpr callback failed
out/test/spec/data.wast:410: assert_invalid passed:
- 000002a: error: expected END opcode after initializer expression
+ error: expected END opcode after initializer expression
+ 000002b: error: OnGlobalGetExpr callback failed
out/test/spec/data.wast:419: assert_invalid passed:
- 000002a: error: expected END opcode after initializer expression
+ error: expected END opcode after initializer expression
+ 000002b: error: OnI32ConstExpr callback failed
out/test/spec/data.wast:428: assert_invalid passed:
- 0000014: error: expected END opcode after initializer expression
+ error: Unepxected opcode in init expr
+ 0000014: error: OnUnaryExpr callback failed
out/test/spec/data.wast:436: assert_invalid passed:
- 0000012: error: unexpected opcode in initializer expression: 0x1
+ error: Unepxected opcode in init expr
+ 0000012: error: OnNopExpr callback failed
out/test/spec/data.wast:444: assert_invalid passed:
- 0000012: error: unexpected opcode in initializer expression: 0x1
+ error: Unepxected opcode in init expr
+ 0000012: error: OnNopExpr callback failed
out/test/spec/data.wast:452: assert_invalid passed:
- 0000014: error: expected END opcode after initializer expression
+ error: Unepxected opcode in init expr
+ 0000014: error: OnNopExpr callback failed
out/test/spec/data.wast:466: assert_invalid passed:
0000000: error: global variable out of range: 0 (max 0)
error: initializer expression cannot reference a mutable global
diff --git a/test/spec/elem.txt b/test/spec/elem.txt
index 25bfc27d..a2872f9d 100644
--- a/test/spec/elem.txt
+++ b/test/spec/elem.txt
@@ -7,26 +7,35 @@ out/test/spec/elem.wast:336: assert_invalid passed:
0000000: error: table variable out of range: 0 (max 0)
0000016: error: BeginElemSegment callback failed
out/test/spec/elem.wast:346: assert_invalid passed:
- 0000014: error: expected i32 init_expr
+ error: invalid elem segment offset, must be a constant expression; either i32.const or global.get.
+ 0000015: error: EndElemSegmentInitExpr callback failed
out/test/spec/elem.wast:354: assert_invalid passed:
- 0000014: error: expected i32 init_expr
+ error: invalid elem segment offset, must be a constant expression; either i32.const or global.get.
+ 0000015: error: EndElemSegmentInitExpr callback failed
out/test/spec/elem.wast:362: assert_invalid passed:
error: invalid elem segment offset, must be a constant expression; either i32.const or global.get.
0000013: error: EndElemSegmentInitExpr callback failed
out/test/spec/elem.wast:370: assert_invalid passed:
- 0000015: error: expected END opcode after initializer expression
+ error: expected END opcode after initializer expression
+ 0000016: error: OnI32ConstExpr callback failed
out/test/spec/elem.wast:378: assert_invalid passed:
- 000002b: error: expected END opcode after initializer expression
+ error: expected END opcode after initializer expression
+ 000002c: error: OnGlobalGetExpr callback failed
out/test/spec/elem.wast:387: assert_invalid passed:
- 000002b: error: expected END opcode after initializer expression
+ error: expected END opcode after initializer expression
+ 000002c: error: OnI32ConstExpr callback failed
out/test/spec/elem.wast:397: assert_invalid passed:
- 0000015: error: expected END opcode after initializer expression
+ error: Unepxected opcode in init expr
+ 0000015: error: OnUnaryExpr callback failed
out/test/spec/elem.wast:405: assert_invalid passed:
- 0000013: error: unexpected opcode in initializer expression: 0x1
+ error: Unepxected opcode in init expr
+ 0000013: error: OnNopExpr callback failed
out/test/spec/elem.wast:413: assert_invalid passed:
- 0000013: error: unexpected opcode in initializer expression: 0x1
+ error: Unepxected opcode in init expr
+ 0000013: error: OnNopExpr callback failed
out/test/spec/elem.wast:421: assert_invalid passed:
- 0000015: error: expected END opcode after initializer expression
+ error: Unepxected opcode in init expr
+ 0000015: error: OnNopExpr callback failed
out/test/spec/elem.wast:435: assert_invalid passed:
0000000: error: global variable out of range: 0 (max 0)
error: initializer expression cannot reference a mutable global
diff --git a/test/spec/func_ptrs.txt b/test/spec/func_ptrs.txt
index a49c5f9f..b29e8b80 100644
--- a/test/spec/func_ptrs.txt
+++ b/test/spec/func_ptrs.txt
@@ -10,11 +10,14 @@ out/test/spec/func_ptrs.wast:33: assert_invalid passed:
0000000: error: table variable out of range: 0 (max 0)
0000016: error: BeginElemSegment callback failed
out/test/spec/func_ptrs.wast:36: assert_invalid passed:
- 0000014: error: expected i32 init_expr
+ error: invalid elem segment offset, must be a constant expression; either i32.const or global.get.
+ 0000015: error: EndElemSegmentInitExpr callback failed
out/test/spec/func_ptrs.wast:40: assert_invalid passed:
- 0000015: error: expected END opcode after initializer expression
+ error: Unepxected opcode in init expr
+ 0000015: error: OnUnaryExpr callback failed
out/test/spec/func_ptrs.wast:44: assert_invalid passed:
- 0000013: error: unexpected opcode in initializer expression: 0x1
+ error: Unepxected opcode in init expr
+ 0000013: error: OnNopExpr callback failed
out/test/spec/func_ptrs.wast:48: assert_invalid passed:
0000000: error: function type variable out of range: 42 (max 0)
000000c: error: OnFunction callback failed
diff --git a/test/spec/global.txt b/test/spec/global.txt
index 71885889..436aecfc 100644
--- a/test/spec/global.txt
+++ b/test/spec/global.txt
@@ -9,22 +9,29 @@ out/test/spec/global.wast:278: assert_invalid passed:
error: can't global.set on immutable global at index 0.
0000035: error: OnGlobalSetExpr callback failed
out/test/spec/global.wast:287: assert_invalid passed:
- 0000013: error: expected END opcode after initializer expression
+ error: Unepxected opcode in init expr
+ 0000013: error: OnUnaryExpr callback failed
out/test/spec/global.wast:292: assert_invalid passed:
- 000000e: error: unexpected opcode in initializer expression: 0x20
+ 0000000: error: local variable out of range (max 0)
+ 000000f: error: OnLocalGetExpr callback failed
out/test/spec/global.wast:297: assert_invalid passed:
- 0000013: error: expected END opcode after initializer expression
+ error: Unepxected opcode in init expr
+ 0000013: error: OnUnaryExpr callback failed
out/test/spec/global.wast:302: assert_invalid passed:
- 0000010: error: expected END opcode after initializer expression
+ error: Unepxected opcode in init expr
+ 0000010: error: OnNopExpr callback failed
out/test/spec/global.wast:307: assert_invalid passed:
- 0000010: error: expected END opcode after initializer expression
+ error: Unepxected opcode in init expr
+ 0000010: error: OnUnaryExpr callback failed
out/test/spec/global.wast:312: assert_invalid passed:
- 000000e: error: unexpected opcode in initializer expression: 0x1
+ error: Unepxected opcode in init expr
+ 000000e: error: OnNopExpr callback failed
out/test/spec/global.wast:317: assert_invalid passed:
error: type mismatch at global initializer expression. got f32, expected i32
0000013: error: EndGlobalInitExpr callback failed
out/test/spec/global.wast:322: assert_invalid passed:
- 0000010: error: expected END opcode after initializer expression
+ error: expected END opcode after initializer expression
+ 0000011: error: OnI32ConstExpr callback failed
out/test/spec/global.wast:327: assert_invalid passed:
error: invalid global initializer expression, must be a constant expression
000000e: error: EndGlobalInitExpr callback failed
@@ -32,9 +39,11 @@ out/test/spec/global.wast:332: assert_invalid passed:
error: type mismatch at global initializer expression. got externref, expected funcref
0000018: error: EndGlobalInitExpr callback failed
out/test/spec/global.wast:337: assert_invalid passed:
- 0000026: error: expected END opcode after initializer expression
+ error: expected END opcode after initializer expression
+ 0000027: error: OnGlobalGetExpr callback failed
out/test/spec/global.wast:342: assert_invalid passed:
- 0000026: error: expected END opcode after initializer expression
+ error: expected END opcode after initializer expression
+ 0000027: error: OnGlobalGetExpr callback failed
out/test/spec/global.wast:347: assert_invalid passed:
0000000: error: initializer expression can only reference an imported global
0000010: error: EndGlobalInitExpr callback failed
diff --git a/test/spec/memory64/binary-leb128.txt b/test/spec/memory64/binary-leb128.txt
index 56a8e030..70d479dd 100644
--- a/test/spec/memory64/binary-leb128.txt
+++ b/test/spec/memory64/binary-leb128.txt
@@ -41,13 +41,13 @@ out/test/spec/memory64/binary-leb128.wast:442: assert_malformed passed:
out/test/spec/memory64/binary-leb128.wast:461: assert_malformed passed:
0000024: error: unable to read u32 leb128: store offset
out/test/spec/memory64/binary-leb128.wast:482: assert_malformed passed:
- 000000e: error: unable to read i32 leb128: init_expr i32.const value
+ 000000e: error: unable to read i32 leb128: i32.const value
out/test/spec/memory64/binary-leb128.wast:492: assert_malformed passed:
- 000000e: error: unable to read i32 leb128: init_expr i32.const value
+ 000000e: error: unable to read i32 leb128: i32.const value
out/test/spec/memory64/binary-leb128.wast:503: assert_malformed passed:
- 000000e: error: unable to read i64 leb128: init_expr i64.const value
+ 000000e: error: unable to read i64 leb128: i64.const value
out/test/spec/memory64/binary-leb128.wast:513: assert_malformed passed:
- 000000e: error: unable to read i64 leb128: init_expr i64.const value
+ 000000e: error: unable to read i64 leb128: i64.const value
out/test/spec/memory64/binary-leb128.wast:525: assert_malformed passed:
000000c: error: unable to read u32 leb128: memory initial page count
out/test/spec/memory64/binary-leb128.wast:533: assert_malformed passed:
@@ -99,21 +99,21 @@ out/test/spec/memory64/binary-leb128.wast:843: assert_malformed passed:
out/test/spec/memory64/binary-leb128.wast:862: assert_malformed passed:
0000024: error: unable to read u32 leb128: store offset
out/test/spec/memory64/binary-leb128.wast:884: assert_malformed passed:
- 000000e: error: unable to read i32 leb128: init_expr i32.const value
+ 000000e: error: unable to read i32 leb128: i32.const value
out/test/spec/memory64/binary-leb128.wast:894: assert_malformed passed:
- 000000e: error: unable to read i32 leb128: init_expr i32.const value
+ 000000e: error: unable to read i32 leb128: i32.const value
out/test/spec/memory64/binary-leb128.wast:904: assert_malformed passed:
- 000000e: error: unable to read i32 leb128: init_expr i32.const value
+ 000000e: error: unable to read i32 leb128: i32.const value
out/test/spec/memory64/binary-leb128.wast:914: assert_malformed passed:
- 000000e: error: unable to read i32 leb128: init_expr i32.const value
+ 000000e: error: unable to read i32 leb128: i32.const value
out/test/spec/memory64/binary-leb128.wast:925: assert_malformed passed:
- 000000e: error: unable to read i64 leb128: init_expr i64.const value
+ 000000e: error: unable to read i64 leb128: i64.const value
out/test/spec/memory64/binary-leb128.wast:935: assert_malformed passed:
- 000000e: error: unable to read i64 leb128: init_expr i64.const value
+ 000000e: error: unable to read i64 leb128: i64.const value
out/test/spec/memory64/binary-leb128.wast:945: assert_malformed passed:
- 000000e: error: unable to read i64 leb128: init_expr i64.const value
+ 000000e: error: unable to read i64 leb128: i64.const value
out/test/spec/memory64/binary-leb128.wast:955: assert_malformed passed:
- 000000e: error: unable to read i64 leb128: init_expr i64.const value
+ 000000e: error: unable to read i64 leb128: i64.const value
out/test/spec/memory64/binary-leb128.wast:987: assert_malformed passed:
0000019: error: unable to read u32 leb128: opcode
57/57 tests passed.
diff --git a/test/spec/multi-memory/binary.txt b/test/spec/multi-memory/binary.txt
index 4ab0a28e..4a3fbba3 100644
--- a/test/spec/multi-memory/binary.txt
+++ b/test/spec/multi-memory/binary.txt
@@ -73,41 +73,41 @@ out/test/spec/multi-memory/binary.wast:165: assert_malformed passed:
out/test/spec/multi-memory/binary.wast:178: assert_malformed passed:
000000c: error: unable to read u32 leb128: memory initial page count
out/test/spec/multi-memory/binary.wast:188: assert_malformed passed:
- 000000e: error: unable to read i32 leb128: init_expr i32.const value
+ 000000e: error: unable to read i32 leb128: i32.const value
out/test/spec/multi-memory/binary.wast:198: assert_malformed passed:
- 000000e: error: unable to read i32 leb128: init_expr i32.const value
+ 000000e: error: unable to read i32 leb128: i32.const value
out/test/spec/multi-memory/binary.wast:209: assert_malformed passed:
- 000000e: error: unable to read i64 leb128: init_expr i64.const value
+ 000000e: error: unable to read i64 leb128: i64.const value
out/test/spec/multi-memory/binary.wast:219: assert_malformed passed:
- 000000e: error: unable to read i64 leb128: init_expr i64.const value
+ 000000e: error: unable to read i64 leb128: i64.const value
out/test/spec/multi-memory/binary.wast:231: assert_malformed passed:
000000c: error: unable to read u32 leb128: memory initial page count
out/test/spec/multi-memory/binary.wast:239: assert_malformed passed:
000000c: error: unable to read u32 leb128: memory initial page count
out/test/spec/multi-memory/binary.wast:249: assert_malformed passed:
- 000000e: error: unable to read i32 leb128: init_expr i32.const value
+ 000000e: error: unable to read i32 leb128: i32.const value
out/test/spec/multi-memory/binary.wast:259: assert_malformed passed:
- 000000e: error: unable to read i32 leb128: init_expr i32.const value
+ 000000e: error: unable to read i32 leb128: i32.const value
out/test/spec/multi-memory/binary.wast:269: assert_malformed passed:
- 000000e: error: unable to read i32 leb128: init_expr i32.const value
+ 000000e: error: unable to read i32 leb128: i32.const value
out/test/spec/multi-memory/binary.wast:279: assert_malformed passed:
- 000000e: error: unable to read i32 leb128: init_expr i32.const value
+ 000000e: error: unable to read i32 leb128: i32.const value
out/test/spec/multi-memory/binary.wast:290: assert_malformed passed:
- 000000e: error: unable to read i64 leb128: init_expr i64.const value
+ 000000e: error: unable to read i64 leb128: i64.const value
out/test/spec/multi-memory/binary.wast:300: assert_malformed passed:
- 000000e: error: unable to read i64 leb128: init_expr i64.const value
+ 000000e: error: unable to read i64 leb128: i64.const value
out/test/spec/multi-memory/binary.wast:310: assert_malformed passed:
- 000000e: error: unable to read i64 leb128: init_expr i64.const value
+ 000000e: error: unable to read i64 leb128: i64.const value
out/test/spec/multi-memory/binary.wast:320: assert_malformed passed:
- 000000e: error: unable to read i64 leb128: init_expr i64.const value
+ 000000e: error: unable to read i64 leb128: i64.const value
out/test/spec/multi-memory/binary.wast:331: assert_malformed passed:
- 000000e: error: unable to read i64 leb128: init_expr i64.const value
+ 000000e: error: unable to read i64 leb128: i64.const value
out/test/spec/multi-memory/binary.wast:341: assert_malformed passed:
- 000000e: error: unable to read i64 leb128: init_expr i64.const value
+ 000000e: error: unable to read i64 leb128: i64.const value
out/test/spec/multi-memory/binary.wast:351: assert_malformed passed:
- 000000e: error: unable to read i64 leb128: init_expr i64.const value
+ 000000e: error: unable to read i64 leb128: i64.const value
out/test/spec/multi-memory/binary.wast:361: assert_malformed passed:
- 000000e: error: unable to read i64 leb128: init_expr i64.const value
+ 000000e: error: unable to read i64 leb128: i64.const value
out/test/spec/multi-memory/binary.wast:374: assert_malformed passed:
000000c: error: unable to read u32 leb128: memory initial page count
out/test/spec/multi-memory/binary.wast:382: assert_malformed passed:
@@ -119,13 +119,13 @@ out/test/spec/multi-memory/binary.wast:420: assert_malformed passed:
out/test/spec/multi-memory/binary.wast:439: assert_malformed passed:
0000024: error: unable to read u32 leb128: store offset
out/test/spec/multi-memory/binary.wast:460: assert_malformed passed:
- 000000e: error: unable to read i32 leb128: init_expr i32.const value
+ 000000e: error: unable to read i32 leb128: i32.const value
out/test/spec/multi-memory/binary.wast:470: assert_malformed passed:
- 000000e: error: unable to read i32 leb128: init_expr i32.const value
+ 000000e: error: unable to read i32 leb128: i32.const value
out/test/spec/multi-memory/binary.wast:481: assert_malformed passed:
- 000000e: error: unable to read i64 leb128: init_expr i64.const value
+ 000000e: error: unable to read i64 leb128: i64.const value
out/test/spec/multi-memory/binary.wast:491: assert_malformed passed:
- 000000e: error: unable to read i64 leb128: init_expr i64.const value
+ 000000e: error: unable to read i64 leb128: i64.const value
out/test/spec/multi-memory/binary.wast:503: assert_malformed passed:
000000c: error: unable to read u32 leb128: memory initial page count
out/test/spec/multi-memory/binary.wast:511: assert_malformed passed:
@@ -147,21 +147,21 @@ out/test/spec/multi-memory/binary.wast:632: assert_malformed passed:
out/test/spec/multi-memory/binary.wast:651: assert_malformed passed:
0000024: error: unable to read u32 leb128: store offset
out/test/spec/multi-memory/binary.wast:673: assert_malformed passed:
- 000000e: error: unable to read i32 leb128: init_expr i32.const value
+ 000000e: error: unable to read i32 leb128: i32.const value
out/test/spec/multi-memory/binary.wast:683: assert_malformed passed:
- 000000e: error: unable to read i32 leb128: init_expr i32.const value
+ 000000e: error: unable to read i32 leb128: i32.const value
out/test/spec/multi-memory/binary.wast:693: assert_malformed passed:
- 000000e: error: unable to read i32 leb128: init_expr i32.const value
+ 000000e: error: unable to read i32 leb128: i32.const value
out/test/spec/multi-memory/binary.wast:703: assert_malformed passed:
- 000000e: error: unable to read i32 leb128: init_expr i32.const value
+ 000000e: error: unable to read i32 leb128: i32.const value
out/test/spec/multi-memory/binary.wast:714: assert_malformed passed:
- 000000e: error: unable to read i64 leb128: init_expr i64.const value
+ 000000e: error: unable to read i64 leb128: i64.const value
out/test/spec/multi-memory/binary.wast:724: assert_malformed passed:
- 000000e: error: unable to read i64 leb128: init_expr i64.const value
+ 000000e: error: unable to read i64 leb128: i64.const value
out/test/spec/multi-memory/binary.wast:734: assert_malformed passed:
- 000000e: error: unable to read i64 leb128: init_expr i64.const value
+ 000000e: error: unable to read i64 leb128: i64.const value
out/test/spec/multi-memory/binary.wast:744: assert_malformed passed:
- 000000e: error: unable to read i64 leb128: init_expr i64.const value
+ 000000e: error: unable to read i64 leb128: i64.const value
out/test/spec/multi-memory/binary.wast:756: assert_malformed passed:
0000017: error: unable to read u32 leb128: local type count
out/test/spec/multi-memory/binary.wast:773: assert_malformed passed:
diff --git a/test/spec/multi-memory/data.txt b/test/spec/multi-memory/data.txt
index 8e3973aa..9a793340 100644
--- a/test/spec/multi-memory/data.txt
+++ b/test/spec/multi-memory/data.txt
@@ -21,26 +21,35 @@ out/test/spec/multi-memory/data.wast:360: assert_invalid passed:
0000000: error: memory variable out of range: 1 (max 0)
000000d: error: BeginDataSegment callback failed
out/test/spec/multi-memory/data.wast:379: assert_invalid passed:
- 0000013: error: expected i32 init_expr
+ error: type mismatch at data segment offset. got i64, expected i32
+ 0000014: error: EndDataSegmentInitExpr callback failed
out/test/spec/multi-memory/data.wast:387: assert_invalid passed:
- 0000013: error: expected i32 init_expr
+ error: invalid data segment offset, must be a constant expression; either iXX.const or global.get.
+ 0000014: error: EndDataSegmentInitExpr callback failed
out/test/spec/multi-memory/data.wast:395: assert_invalid passed:
error: invalid data segment offset, must be a constant expression; either iXX.const or global.get.
0000012: error: EndDataSegmentInitExpr callback failed
out/test/spec/multi-memory/data.wast:403: assert_invalid passed:
- 0000014: error: expected END opcode after initializer expression
+ error: expected END opcode after initializer expression
+ 0000015: error: OnI32ConstExpr callback failed
out/test/spec/multi-memory/data.wast:411: assert_invalid passed:
- 000002a: error: expected END opcode after initializer expression
+ error: expected END opcode after initializer expression
+ 000002b: error: OnGlobalGetExpr callback failed
out/test/spec/multi-memory/data.wast:420: assert_invalid passed:
- 000002a: error: expected END opcode after initializer expression
+ error: expected END opcode after initializer expression
+ 000002b: error: OnI32ConstExpr callback failed
out/test/spec/multi-memory/data.wast:429: assert_invalid passed:
- 0000014: error: expected END opcode after initializer expression
+ error: Unepxected opcode in init expr
+ 0000014: error: OnUnaryExpr callback failed
out/test/spec/multi-memory/data.wast:437: assert_invalid passed:
- 0000012: error: unexpected opcode in initializer expression: 0x1
+ error: Unepxected opcode in init expr
+ 0000012: error: OnNopExpr callback failed
out/test/spec/multi-memory/data.wast:445: assert_invalid passed:
- 0000012: error: unexpected opcode in initializer expression: 0x1
+ error: Unepxected opcode in init expr
+ 0000012: error: OnNopExpr callback failed
out/test/spec/multi-memory/data.wast:453: assert_invalid passed:
- 0000014: error: expected END opcode after initializer expression
+ error: Unepxected opcode in init expr
+ 0000014: error: OnNopExpr callback failed
out/test/spec/multi-memory/data.wast:467: assert_invalid passed:
0000000: error: global variable out of range: 0 (max 0)
error: initializer expression cannot reference a mutable global