summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-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
9 files changed, 298 insertions, 380 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_;