diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/binary-reader-ir.cc | 113 | ||||
-rw-r--r-- | src/binary-reader-logging.cc | 41 | ||||
-rw-r--r-- | src/binary-reader-logging.h | 16 | ||||
-rw-r--r-- | src/binary-reader-nop.h | 22 | ||||
-rw-r--r-- | src/binary-reader.cc | 126 | ||||
-rw-r--r-- | src/binary-reader.h | 18 | ||||
-rw-r--r-- | src/binary.h | 1 | ||||
-rw-r--r-- | src/ir.cc | 25 | ||||
-rw-r--r-- | src/ir.h | 13 | ||||
-rw-r--r-- | src/tools/wasm2wast.cc | 4 | ||||
-rw-r--r-- | src/wast-parser.y | 4 | ||||
-rw-r--r-- | src/wat-writer.cc | 3 |
12 files changed, 359 insertions, 27 deletions
diff --git a/src/binary-reader-ir.cc b/src/binary-reader-ir.cc index 4f685bfa..93bae4b9 100644 --- a/src/binary-reader-ir.cc +++ b/src/binary-reader-ir.cc @@ -44,10 +44,12 @@ struct LabelNode { LabelType label_type; ExprList* exprs; + Expr* context; }; LabelNode::LabelNode(LabelType label_type, ExprList* exprs) - : label_type(label_type), exprs(exprs) {} + : label_type(label_type), exprs(exprs), context(nullptr) {} + class BinaryReaderIR : public BinaryReaderNop { public: @@ -90,6 +92,11 @@ class BinaryReaderIR : public BinaryReaderNop { Index global_index, Type type, bool mutable_) override; + Result OnImportException(Index import_index, + StringSlice module_name, + StringSlice field_name, + Index except_index, + TypeVector& sig) override; Result OnFunctionCount(Index count) override; Result OnFunction(Index index, Index sig_index) override; @@ -127,6 +134,8 @@ class BinaryReaderIR : public BinaryReaderNop { Index* target_depths, Index default_target_depth) override; Result OnCallExpr(Index func_index) override; + Result OnCatchExpr(Index except_index) override; + Result OnCatchAllExpr() override; Result OnCallIndirectExpr(Index sig_index) override; Result OnCompareExpr(Opcode opcode) override; Result OnConvertExpr(Opcode opcode) override; @@ -147,6 +156,7 @@ class BinaryReaderIR : public BinaryReaderNop { Result OnLoopExpr(Index num_types, Type* sig_types) override; Result OnCurrentMemoryExpr() override; Result OnNopExpr() override; + Result OnRethrowExpr(Index depth) override; Result OnReturnExpr() override; Result OnSelectExpr() override; Result OnSetGlobalExpr(Index global_index) override; @@ -154,7 +164,9 @@ class BinaryReaderIR : public BinaryReaderNop { Result OnStoreExpr(Opcode opcode, uint32_t alignment_log2, Address offset) override; + Result OnThrowExpr(Index except_index) override; Result OnTeeLocalExpr(Index local_index) override; + Result OnTryExpr(Index num_types, Type* sig_types) override; Result OnUnaryExpr(Opcode opcode) override; Result OnUnreachableExpr() override; Result EndFunctionBody(Index index) override; @@ -185,6 +197,11 @@ class BinaryReaderIR : public BinaryReaderNop { Index local_index, StringSlice local_name) override; + Result BeginExceptionSection(Offset size) override { return Result::Ok; } + Result OnExceptionCount(Index count) override { return Result::Ok; } + Result OnExceptionType(Index index, TypeVector& types) override; + Result EndExceptionSection() override { return Result::Ok; } + Result OnInitExprF32ConstExpr(Index index, uint32_t value) override; Result OnInitExprF64ConstExpr(Index index, uint64_t value) override; Result OnInitExprGetGlobalExpr(Index index, Index global_index) override; @@ -200,6 +217,7 @@ class BinaryReaderIR : public BinaryReaderNop { Result GetLabelAt(LabelNode** label, Index depth); Result TopLabel(LabelNode** label); Result AppendExpr(Expr* expr); + Result AppendCatch(Catch* catch_); BinaryErrorHandler* error_handler = nullptr; Module* module = nullptr; @@ -379,6 +397,18 @@ Result BinaryReaderIR::OnImportGlobal(Index import_index, return Result::Ok; } +Result BinaryReaderIR::OnImportException(Index import_index, + StringSlice module_name, + StringSlice field_name, + Index except_index, + TypeVector& sig) { + assert(import_index == module->imports.size() - 1); + Import* import = module->imports[import_index]; + import->kind = ExternalKind::Except; + import->except = new Exception(sig); + return Result::Ok; +} + Result BinaryReaderIR::OnFunctionCount(Index count) { module->funcs.reserve(module->num_func_imports + count); return Result::Ok; @@ -474,7 +504,7 @@ Result BinaryReaderIR::OnExport(Index index, assert(item_index < module->globals.size()); break; case ExternalKind::Except: - WABT_FATAL("OnExport(except) not implemented\n"); + // Note: Can't check if index valid, exceptions section comes later. break; } export_->var = Var(item_index, GetLocation()); @@ -518,18 +548,19 @@ Result BinaryReaderIR::OnBinaryExpr(Opcode opcode) { Result BinaryReaderIR::OnBlockExpr(Index num_types, Type* sig_types) { auto expr = new BlockExpr(new Block()); expr->block->sig.assign(sig_types, sig_types + num_types); - AppendExpr(expr); + if (Failed(AppendExpr(expr))) + return Result::Error; PushLabel(LabelType::Block, &expr->block->exprs); return Result::Ok; } Result BinaryReaderIR::OnBrExpr(Index depth) { - auto expr = new BrExpr(Var(depth)); + auto expr = new BrExpr(Var(depth, GetLocation())); return AppendExpr(expr); } Result BinaryReaderIR::OnBrIfExpr(Index depth) { - auto expr = new BrIfExpr(Var(depth)); + auto expr = new BrIfExpr(Var(depth, GetLocation())); return AppendExpr(expr); } @@ -541,19 +572,20 @@ Result BinaryReaderIR::OnBrTableExpr(Index num_targets, for (Index i = 0; i < num_targets; ++i) { (*targets)[i] = Var(target_depths[i]); } - auto expr = new BrTableExpr(targets, Var(default_target_depth)); + auto expr = new BrTableExpr(targets, + Var(default_target_depth, GetLocation())); return AppendExpr(expr); } Result BinaryReaderIR::OnCallExpr(Index func_index) { assert(func_index < module->funcs.size()); - auto expr = new CallExpr(Var(func_index)); + auto expr = new CallExpr(Var(func_index, GetLocation())); return AppendExpr(expr); } Result BinaryReaderIR::OnCallIndirectExpr(Index sig_index) { assert(sig_index < module->func_types.size()); - auto expr = new CallIndirectExpr(Var(sig_index)); + auto expr = new CallIndirectExpr(Var(sig_index, GetLocation())); return AppendExpr(expr); } @@ -635,7 +667,8 @@ Result BinaryReaderIR::OnI64ConstExpr(uint64_t value) { Result BinaryReaderIR::OnIfExpr(Index num_types, Type* sig_types) { auto expr = new IfExpr(new Block()); expr->true_->sig.assign(sig_types, sig_types + num_types); - AppendExpr(expr); + if (Failed(AppendExpr(expr))) + return Result::Error; PushLabel(LabelType::If, &expr->true_->exprs); return Result::Ok; } @@ -650,7 +683,8 @@ Result BinaryReaderIR::OnLoadExpr(Opcode opcode, Result BinaryReaderIR::OnLoopExpr(Index num_types, Type* sig_types) { auto expr = new LoopExpr(new Block()); expr->block->sig.assign(sig_types, sig_types + num_types); - AppendExpr(expr); + if (Failed(AppendExpr(expr))) + return Result::Error; PushLabel(LabelType::Loop, &expr->block->exprs); return Result::Ok; } @@ -660,6 +694,10 @@ Result BinaryReaderIR::OnNopExpr() { return AppendExpr(expr); } +Result BinaryReaderIR::OnRethrowExpr(Index depth) { + return AppendExpr(new RethrowExpr(Var(depth, GetLocation()))); +} + Result BinaryReaderIR::OnReturnExpr() { auto expr = new ReturnExpr(); return AppendExpr(expr); @@ -687,11 +725,59 @@ Result BinaryReaderIR::OnStoreExpr(Opcode opcode, return AppendExpr(expr); } +Result BinaryReaderIR::OnThrowExpr(Index except_index) { + return AppendExpr(new ThrowExpr(Var(except_index, GetLocation()))); +} + Result BinaryReaderIR::OnTeeLocalExpr(Index local_index) { auto expr = new TeeLocalExpr(Var(local_index, GetLocation())); return AppendExpr(expr); } +Result BinaryReaderIR::OnTryExpr(Index num_types, Type* sig_types) { + auto expr = new TryExpr(); + expr->block = new Block(); + expr->block->sig.assign(sig_types, sig_types + num_types); + if (Failed(AppendExpr(expr))) + return Result::Error; + PushLabel(LabelType::Try, &expr->block->exprs); + LabelNode* label = nullptr; + { Result result = TopLabel(&label); + (void) result; + assert(Succeeded(result)); + } + label->context = expr; + return Result::Ok; +} + +Result BinaryReaderIR::AppendCatch(Catch* catch_) { + LabelNode* label = nullptr; + if (Succeeded(TopLabel(&label)) && label->label_type == LabelType::Try) { + if (auto try_ = dyn_cast<TryExpr>(label->context)) { + // TODO(karlschimpf) Probably should be set in the Catch constructor. + catch_->loc = GetLocation(); + try_->catches.push_back(catch_); + label->exprs = &catch_->exprs; + return Result::Ok; + } + } + if (label != nullptr) + PrintError("catch not inside try block"); + delete catch_; + return Result::Error; +} + +Result BinaryReaderIR::OnCatchExpr(Index except_index) { + ExprList empty; + return AppendCatch(new Catch(Var(except_index, GetLocation()))); + return Result::Error; +} + +Result BinaryReaderIR::OnCatchAllExpr() { + ExprList empty; + return AppendCatch(new Catch()); +} + Result BinaryReaderIR::OnUnaryExpr(Opcode opcode) { auto expr = new UnaryExpr(opcode); return AppendExpr(expr); @@ -886,6 +972,13 @@ Result BinaryReaderIR::OnLocalName(Index func_index, return Result::Ok; } +Result BinaryReaderIR::OnExceptionType(Index index, TypeVector& sig) { + auto except = new Exception(sig); + module->excepts.push_back(except); + module->AppendField(new ExceptionModuleField(except)); + return Result::Ok; +} + } // end anonymous namespace Result read_binary_ir(const char* filename, diff --git a/src/binary-reader-logging.cc b/src/binary-reader-logging.cc index da115165..eb7d266b 100644 --- a/src/binary-reader-logging.cc +++ b/src/binary-reader-logging.cc @@ -86,6 +86,10 @@ void BinaryReaderLogging::LogTypes(Index type_count, Type* types) { LOGF_NOINDENT("]"); } +void BinaryReaderLogging::LogTypes(TypeVector& types) { + LogTypes(types.size(), types.data()); +} + bool BinaryReaderLogging::OnError(const char* message) { return reader->OnError(message); } @@ -194,6 +198,20 @@ Result BinaryReaderLogging::OnImportGlobal(Index import_index, global_index, type, mutable_); } +Result BinaryReaderLogging::OnImportException(Index import_index, + StringSlice module_name, + StringSlice field_name, + Index except_index, + TypeVector& sig) { + LOGF("OnImportException(import_index: %" PRIindex ", except_index: %" PRIindex + ", sig: ", import_index, except_index); + LogTypes(sig); + LOGF_NOINDENT(")\n"); + return reader->OnImportException(import_index, module_name,field_name, + except_index, sig); +} + + Result BinaryReaderLogging::OnTable(Index index, Type elem_type, const Limits* elem_limits) { @@ -270,6 +288,13 @@ Result BinaryReaderLogging::OnBrTableExpr(Index num_targets, default_target_depth); } +Result BinaryReaderLogging::OnExceptionType(Index index, TypeVector& sig) { + LOGF("OnType(index: %" PRIindex ", values: ", index); + LogTypes(sig); + LOGF_NOINDENT(")\n"); + return reader->OnExceptionType(index, sig); +} + Result BinaryReaderLogging::OnF32ConstExpr(uint32_t value_bits) { float value; memcpy(&value, &value_bits, sizeof(value)); @@ -326,6 +351,13 @@ Result BinaryReaderLogging::OnStoreExpr(Opcode opcode, return reader->OnStoreExpr(opcode, alignment_log2, offset); } +Result BinaryReaderLogging::OnTryExpr(Index num_types, Type* sig_types) { + LOGF("OnTryExpr(sig: "); + LogTypes(num_types, sig_types); + LOGF_NOINDENT(")\n"); + return reader->OnTryExpr(num_types, sig_types); +} + Result BinaryReaderLogging::OnDataSegmentData(Index index, const void* data, Address size) { @@ -522,6 +554,8 @@ DEFINE_INDEX(OnLocalDeclCount) DEFINE_OPCODE(OnBinaryExpr) DEFINE_INDEX_DESC(OnCallExpr, "func_index") DEFINE_INDEX_DESC(OnCallIndirectExpr, "sig_index") +DEFINE_INDEX_DESC(OnCatchExpr, "except_index"); +DEFINE0(OnCatchAllExpr) DEFINE_OPCODE(OnCompareExpr) DEFINE_OPCODE(OnConvertExpr) DEFINE0(OnCurrentMemoryExpr) @@ -532,11 +566,13 @@ DEFINE_INDEX_DESC(OnGetGlobalExpr, "index") DEFINE_INDEX_DESC(OnGetLocalExpr, "index") DEFINE0(OnGrowMemoryExpr) DEFINE0(OnNopExpr) +DEFINE_INDEX_DESC(OnRethrowExpr, "depth"); DEFINE0(OnReturnExpr) DEFINE0(OnSelectExpr) DEFINE_INDEX_DESC(OnSetGlobalExpr, "index") DEFINE_INDEX_DESC(OnSetLocalExpr, "index") DEFINE_INDEX_DESC(OnTeeLocalExpr, "index") +DEFINE_INDEX_DESC(OnThrowExpr, "except_index") DEFINE0(OnUnreachableExpr) DEFINE_OPCODE(OnUnaryExpr) DEFINE_END(EndCodeSection) @@ -574,6 +610,11 @@ DEFINE_INDEX(OnSymbolInfoCount) DEFINE_INDEX(OnStackGlobal) DEFINE_END(EndLinkingSection) +DEFINE_BEGIN(BeginExceptionSection); +DEFINE_INDEX(OnExceptionCount); + +DEFINE_END(EndExceptionSection); + // We don't need to log these (the individual opcodes are logged instead), but // we still need to forward the calls. Result BinaryReaderLogging::OnOpcode(Opcode opcode) { diff --git a/src/binary-reader-logging.h b/src/binary-reader-logging.h index 1bc89acb..57be35d3 100644 --- a/src/binary-reader-logging.h +++ b/src/binary-reader-logging.h @@ -74,6 +74,11 @@ class BinaryReaderLogging : public BinaryReaderDelegate { Index global_index, Type type, bool mutable_) override; + Result OnImportException(Index import_index, + StringSlice module_name, + StringSlice field_name, + Index except_index, + TypeVector& sig) override; Result EndImportSection() override; Result BeginFunctionSection(Offset size) override; @@ -136,6 +141,8 @@ class BinaryReaderLogging : public BinaryReaderDelegate { Index* target_depths, Index default_target_depth) override; Result OnCallExpr(Index func_index) override; + Result OnCatchExpr(Index except_index) override; + Result OnCatchAllExpr() override; Result OnCallIndirectExpr(Index sig_index) override; Result OnCompareExpr(Opcode opcode) override; Result OnConvertExpr(Opcode opcode) override; @@ -157,6 +164,7 @@ class BinaryReaderLogging : public BinaryReaderDelegate { Address offset) override; Result OnLoopExpr(Index num_types, Type* sig_types) override; Result OnNopExpr() override; + Result OnRethrowExpr(Index depth) override; Result OnReturnExpr() override; Result OnSelectExpr() override; Result OnSetGlobalExpr(Index global_index) override; @@ -165,6 +173,8 @@ class BinaryReaderLogging : public BinaryReaderDelegate { uint32_t alignment_log2, Address offset) override; Result OnTeeLocalExpr(Index local_index) override; + Result OnThrowExpr(Index except_index) override; + Result OnTryExpr(Index num_types, Type* sig_types) override; Result OnUnaryExpr(Opcode opcode) override; Result OnUnreachableExpr() override; Result EndFunctionBody(Index index) override; @@ -227,6 +237,11 @@ class BinaryReaderLogging : public BinaryReaderDelegate { Result OnSymbolInfoCount(Index count) override; Result EndLinkingSection() override; + Result BeginExceptionSection(Offset size) override; + Result OnExceptionCount(Index count) override; + Result OnExceptionType(Index index, TypeVector& sig) override; + Result EndExceptionSection() override; + Result OnInitExprF32ConstExpr(Index index, uint32_t value) override; Result OnInitExprF64ConstExpr(Index index, uint64_t value) override; Result OnInitExprGetGlobalExpr(Index index, @@ -239,6 +254,7 @@ class BinaryReaderLogging : public BinaryReaderDelegate { void Dedent(); void WriteIndent(); void LogTypes(Index type_count, Type* types); + void LogTypes(TypeVector& types); Stream* stream; BinaryReaderDelegate* reader; diff --git a/src/binary-reader-nop.h b/src/binary-reader-nop.h index ff2bd515..9223c623 100644 --- a/src/binary-reader-nop.h +++ b/src/binary-reader-nop.h @@ -89,6 +89,13 @@ class BinaryReaderNop : public BinaryReaderDelegate { bool mutable_) override { return Result::Ok; } + Result OnImportException(Index import_index, + StringSlice module_name, + StringSlice field_name, + Index except_index, + TypeVector& sig) override { + return Result::Error; + } Result EndImportSection() override { return Result::Ok; } /* Function section */ @@ -181,6 +188,8 @@ class BinaryReaderNop : public BinaryReaderDelegate { } Result OnCallExpr(Index func_index) override { return Result::Ok; } Result OnCallIndirectExpr(Index sig_index) override { return Result::Ok; } + Result OnCatchExpr(Index except_index) override { return Result::Error; } + Result OnCatchAllExpr() override { return Result::Error; } Result OnCompareExpr(Opcode opcode) override { return Result::Ok; } Result OnConvertExpr(Opcode opcode) override { return Result::Ok; } Result OnCurrentMemoryExpr() override { return Result::Ok; } @@ -207,6 +216,7 @@ class BinaryReaderNop : public BinaryReaderDelegate { return Result::Ok; } Result OnNopExpr() override { return Result::Ok; } + Result OnRethrowExpr(Index depth) override { return Result::Error; } Result OnReturnExpr() override { return Result::Ok; } Result OnSelectExpr() override { return Result::Ok; } Result OnSetGlobalExpr(Index global_index) override { return Result::Ok; } @@ -217,6 +227,10 @@ class BinaryReaderNop : public BinaryReaderDelegate { return Result::Ok; } Result OnTeeLocalExpr(Index local_index) override { return Result::Ok; } + Result OnThrowExpr(Index depth) override { return Result::Error; } + Result OnTryExpr(Index num_types, Type* sig_types) override { + return Result::Error; + } Result OnUnaryExpr(Opcode opcode) override { return Result::Ok; } Result OnUnreachableExpr() override { return Result::Ok; } Result EndFunctionBody(Index index) override { return Result::Ok; } @@ -303,6 +317,14 @@ class BinaryReaderNop : public BinaryReaderDelegate { } Result EndRelocSection() override { return Result::Ok; } + /* Exception section */ + Result BeginExceptionSection(Offset size) override { return Result::Error; } + Result OnExceptionCount(Index count) override { return Result::Error; } + Result OnExceptionType(Index index, TypeVector& sig) override { + return Result::Error; + } + Result EndExceptionSection() override { return Result::Error; } + /* Linking section */ Result BeginLinkingSection(Offset size) override { return Result::Ok; } Result OnStackGlobal(Index stack_global) override { return Result::Ok; } diff --git a/src/binary-reader.cc b/src/binary-reader.cc index beb807ff..1c162210 100644 --- a/src/binary-reader.cc +++ b/src/binary-reader.cc @@ -48,6 +48,12 @@ } \ } while (0) +#define ERROR_UNLESS_FUTURE_EXCEPTIONS_OPCODE(opcode) \ + do { \ + if (!options_->allow_future_exceptions) \ + return ReportUnexpectedOpcode(opcode); \ + } while (0) + #define CALLBACK0(member) \ ERROR_UNLESS(Succeeded(delegate_->member()), #member \ " callback failed") @@ -180,6 +186,7 @@ class BinaryReader { Limits* out_elem_limits) WABT_WARN_UNUSED; Result ReadMemory(Limits* out_page_limits) WABT_WARN_UNUSED; Result ReadGlobalHeader(Type* out_type, bool* out_mutable) WABT_WARN_UNUSED; + Result ReadExceptionType(TypeVector& sig) WABT_WARN_UNUSED; Result ReadFunctionBody(Offset end_offset) WABT_WARN_UNUSED; Result ReadNamesSection(Offset section_size) WABT_WARN_UNUSED; Result ReadRelocSection(Offset section_size) WABT_WARN_UNUSED; @@ -196,7 +203,9 @@ class BinaryReader { Result ReadElemSection(Offset section_size) WABT_WARN_UNUSED; Result ReadCodeSection(Offset section_size) WABT_WARN_UNUSED; Result ReadDataSection(Offset section_size) WABT_WARN_UNUSED; + Result ReadExceptionSection(Offset section_size) WABT_WARN_UNUSED; Result ReadSections() WABT_WARN_UNUSED; + Result ReportUnexpectedOpcode(Opcode opcode, const char* message = nullptr); size_t read_end_ = 0; /* Either the section end or data_size. */ BinaryReaderDelegate::State state_; @@ -212,12 +221,14 @@ class BinaryReader { Index num_table_imports_ = 0; Index num_memory_imports_ = 0; Index num_global_imports_ = 0; + Index num_exception_imports_ = 0; Index num_function_signatures_ = 0; Index num_tables_ = 0; Index num_memories_ = 0; Index num_globals_ = 0; Index num_exports_ = 0; Index num_function_bodies_ = 0; + Index num_exceptions_ = 0; }; BinaryReader::BinaryReader(const void* data, @@ -253,6 +264,16 @@ void WABT_PRINTF_FORMAT(2, 3) BinaryReader::PrintError(const char* format, state_.offset += sizeof(type); \ return Result::Ok +Result BinaryReader::ReportUnexpectedOpcode(Opcode opcode, + const char* message) { + const char* maybe_space = " "; + if (!message) + message = maybe_space = ""; + PrintError("unexpected opcode%s%s: %d (0x%x)", + maybe_space, message, opcode.GetCode(), opcode.GetCode()); + return Result::Error; +} + Result BinaryReader::ReadOpcode(Opcode* out_value, const char* desc) { uint8_t value = 0; if (Failed(ReadU8(&value, desc))) { @@ -508,9 +529,7 @@ Result BinaryReader::ReadInitExpr(Index index) { return Result::Ok; default: - PrintError("unexpected opcode in initializer expression: %d (0x%x)", - opcode.GetCode(), opcode.GetCode()); - return Result::Error; + return ReportUnexpectedOpcode(opcode, "in initializer expression"); } CHECK_RESULT(ReadOpcode(&opcode, "opcode")); @@ -989,10 +1008,54 @@ Result BinaryReader::ReadFunctionBody(Offset end_offset) { CALLBACK0(OnOpcodeBare); break; + case Opcode::Try: { + ERROR_UNLESS_FUTURE_EXCEPTIONS_OPCODE(opcode); + Type sig_type; + CHECK_RESULT(ReadType(&sig_type, "try signature type")); + ERROR_UNLESS(is_inline_sig_type(sig_type), + "expected valid block signature type"); + Index num_types = sig_type == Type::Void ? 0 : 1; + CALLBACK(OnTryExpr, num_types, &sig_type); + CALLBACK(OnOpcodeBlockSig, num_types, &sig_type); + break; + } + + case Opcode::Catch: { + ERROR_UNLESS_FUTURE_EXCEPTIONS_OPCODE(opcode); + Index index; + CHECK_RESULT(ReadIndex(&index, "exception index")); + CALLBACK(OnCatchExpr, index); + CALLBACK(OnOpcodeIndex, index); + break; + } + + case Opcode::CatchAll: { + ERROR_UNLESS_FUTURE_EXCEPTIONS_OPCODE(opcode); + CALLBACK(OnCatchAllExpr); + CALLBACK0(OnOpcodeBare); + break; + } + + case Opcode::Rethrow: { + ERROR_UNLESS_FUTURE_EXCEPTIONS_OPCODE(opcode); + Index depth; + CHECK_RESULT(ReadIndex(&depth, "catch depth")); + CALLBACK(OnRethrowExpr, depth); + CALLBACK(OnOpcodeIndex, depth); + break; + } + + case Opcode::Throw: { + ERROR_UNLESS_FUTURE_EXCEPTIONS_OPCODE(opcode); + Index index; + CHECK_RESULT(ReadIndex(&index, "exception index")); + CALLBACK(OnThrowExpr, index); + CALLBACK(OnOpcodeIndex, index); + break; + } + default: - PrintError("unexpected opcode: %d (0x%x)", static_cast<int>(opcode), - static_cast<unsigned>(opcode)); - return Result::Error; + return ReportUnexpectedOpcode(opcode); } } ERROR_UNLESS(state_.offset == end_offset, @@ -1185,6 +1248,36 @@ Result BinaryReader::ReadLinkingSection(Offset section_size) { return Result::Ok; } +Result BinaryReader::ReadExceptionType(TypeVector& sig) { + Index num_values; + CHECK_RESULT(ReadIndex(&num_values, "exception type count")); + sig.resize(num_values); + for (Index j = 0; j < num_values; ++j) { + Type value_type; + CHECK_RESULT(ReadType(&value_type, "exception value type")); + ERROR_UNLESS(is_concrete_type(value_type), + "excepted valid exception value type (got %d)", + static_cast<int>(value_type)); + sig[j] = value_type; + } + return Result::Ok; +} + +Result BinaryReader::ReadExceptionSection(Offset section_size) { + CALLBACK(BeginExceptionSection, section_size); + CHECK_RESULT(ReadIndex(&num_exceptions_, "exception count")); + CALLBACK(OnExceptionCount, num_exceptions_); + + for (Index i = 0; i < num_exceptions_; ++i) { + TypeVector sig; + CHECK_RESULT(ReadExceptionType(sig)); + CALLBACK(OnExceptionType, i, sig); + } + + CALLBACK(EndExceptionSection); + return Result::Ok; +} + Result BinaryReader::ReadCustomSection(Offset section_size) { StringSlice section_name; CHECK_RESULT(ReadStr(§ion_name, "section name")); @@ -1201,6 +1294,10 @@ Result BinaryReader::ReadCustomSection(Offset section_size) { } else if (strncmp(section_name.start, WABT_BINARY_SECTION_LINKING, strlen(WABT_BINARY_SECTION_LINKING)) == 0) { CHECK_RESULT(ReadLinkingSection(section_size)); + } else if (options_->allow_future_exceptions && + strncmp(section_name.start, WABT_BINARY_SECTION_EXCEPTION, + strlen(WABT_BINARY_SECTION_EXCEPTION)) == 0) { + CHECK_RESULT(ReadExceptionSection(section_size)); } else { /* This is an unknown custom section, skip it. */ state_.offset = read_end_; @@ -1311,6 +1408,18 @@ Result BinaryReader::ReadImportSection(Offset section_size) { break; } + case ExternalKind::Except: { + if (!options_->allow_future_exceptions) + PrintError("invalid import exception kind: exceptions not allowed"); + TypeVector sig; + CHECK_RESULT(ReadExceptionType(sig)); + CALLBACK(OnImport, i, module_name, field_name); + CALLBACK(OnImportException, i, module_name, field_name, + num_exception_imports_, sig); + num_exception_imports_++; + break; + } + default: PrintError("invalid import kind: %d", kind); return Result::Error; @@ -1421,8 +1530,9 @@ Result BinaryReader::ReadExportSection(Offset section_size) { "invalid export global index: %" PRIindex, item_index); break; case ExternalKind::Except: - // TODO(karlschimpf) Define. - WABT_FATAL("read export except not implemented"); + // Note: Can't check if index valid, exceptions section comes later. + if (!options_->allow_future_exceptions) + PrintError("invalid export exception kind: exceptions not allowed"); break; } diff --git a/src/binary-reader.h b/src/binary-reader.h index 95220a5f..742b60f9 100644 --- a/src/binary-reader.h +++ b/src/binary-reader.h @@ -35,6 +35,7 @@ struct ReadBinaryOptions { Stream* log_stream = nullptr; bool read_debug_names = false; + bool allow_future_exceptions = false; }; class BinaryReaderDelegate { @@ -101,6 +102,11 @@ class BinaryReaderDelegate { Index global_index, Type type, bool mutable_) = 0; + virtual Result OnImportException(Index import_index, + StringSlice module_name, + StringSlice field_name, + Index except_index, + TypeVector& sig) = 0; virtual Result EndImportSection() = 0; /* Function section */ @@ -173,6 +179,8 @@ class BinaryReaderDelegate { Index default_target_depth) = 0; virtual Result OnCallExpr(Index func_index) = 0; virtual Result OnCallIndirectExpr(Index sig_index) = 0; + virtual Result OnCatchExpr(Index except_index) = 0; + virtual Result OnCatchAllExpr() = 0; virtual Result OnCompareExpr(Opcode opcode) = 0; virtual Result OnConvertExpr(Opcode opcode) = 0; virtual Result OnCurrentMemoryExpr() = 0; @@ -193,6 +201,7 @@ class BinaryReaderDelegate { Address offset) = 0; virtual Result OnLoopExpr(Index num_types, Type* sig_types) = 0; virtual Result OnNopExpr() = 0; + virtual Result OnRethrowExpr(Index depth) = 0; virtual Result OnReturnExpr() = 0; virtual Result OnSelectExpr() = 0; virtual Result OnSetGlobalExpr(Index global_index) = 0; @@ -201,6 +210,9 @@ class BinaryReaderDelegate { uint32_t alignment_log2, Address offset) = 0; virtual Result OnTeeLocalExpr(Index local_index) = 0; + virtual Result OnThrowExpr(Index except_index) = 0; + virtual Result OnTryExpr(Index num_types, Type* sig_types) = 0; + virtual Result OnUnaryExpr(Opcode opcode) = 0; virtual Result OnUnreachableExpr() = 0; virtual Result EndFunctionBody(Index index) = 0; @@ -267,6 +279,12 @@ class BinaryReaderDelegate { virtual Result OnSymbolInfo(StringSlice name, uint32_t flags) = 0; virtual Result EndLinkingSection() = 0; + /* Exception section */ + virtual Result BeginExceptionSection(Offset size) = 0; + virtual Result OnExceptionCount(Index count) = 0; + virtual Result OnExceptionType(Index index, TypeVector& sig) = 0; + virtual Result EndExceptionSection() = 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; diff --git a/src/binary.h b/src/binary.h index a866ec14..84b9447a 100644 --- a/src/binary.h +++ b/src/binary.h @@ -26,6 +26,7 @@ #define WABT_BINARY_SECTION_NAME "name" #define WABT_BINARY_SECTION_RELOC "reloc" #define WABT_BINARY_SECTION_LINKING "linking" +#define WABT_BINARY_SECTION_EXCEPTION "exception" #define WABT_FOREACH_BINARY_SECTION(V) \ V(Custom, custom, 0) \ @@ -328,9 +328,32 @@ Block::~Block() { destroy_string_slice(&label); } +Exception::Exception() { + ZeroMemory(name); +} + +Exception::Exception(const TypeVector& sig) + : sig(sig) { + ZeroMemory(name); +} + +Exception::Exception(StringSlice name, const TypeVector& sig) + : name(name), sig(sig) {} + +Exception& Exception::operator =(const Exception& except) { + name = dup_string_slice(except.name); + sig = except.sig; + return *this; +} + +Catch::Catch() {} + +Catch::Catch(const Var& var) : var(var) {} + Catch::Catch(ExprList exprs) : exprs(std::move(exprs)) {} -Catch::Catch(Var var, ExprList exprs) : var(var), exprs(std::move(exprs)) {} +Catch::Catch(const Var& var, ExprList exprs) + : var(var), exprs(std::move(exprs)) {} IfExpr::~IfExpr() { delete true_; @@ -139,9 +139,10 @@ struct Block { struct Catch { WABT_DISALLOW_COPY_AND_ASSIGN(Catch); - Catch() = delete; + Catch(); + explicit Catch(const Var& var); explicit Catch(ExprList exprs); - Catch(Var var, ExprList exprs); + Catch(const Var& var, ExprList exprs); Location loc; Var var; ExprList exprs; @@ -281,6 +282,10 @@ typedef LoadStoreExpr<ExprType::Store> StoreExpr; struct Exception { StringSlice name; TypeVector sig; + Exception(); + Exception(const TypeVector& sig); + Exception(StringSlice name, const TypeVector& sig); + Exception& operator =(const Exception& except); ~Exception() { destroy_string_slice(&name); } }; @@ -838,8 +843,8 @@ struct Script { }; void MakeTypeBindingReverseMapping( - const TypeVector&, - const BindingHash&, + const TypeVector& types, + const BindingHash& bindings, std::vector<std::string>* out_reverse_mapping); } // namespace wabt diff --git a/src/tools/wasm2wast.cc b/src/tools/wasm2wast.cc index 840d6e15..e84d779c 100644 --- a/src/tools/wasm2wast.cc +++ b/src/tools/wasm2wast.cc @@ -74,6 +74,10 @@ static void parse_options(int argc, char** argv) { }); parser.AddOption('f', "fold-exprs", "Write folded expressions where possible", []() { s_write_wat_options.fold_exprs = true; }); + parser.AddOption("future-exceptions", + "Test future extension for exception handling", + []() { s_read_binary_options.allow_future_exceptions = true; + }); parser.AddOption("inline-exports", "Write all exports inline", []() { s_write_wat_options.inline_export = true; }); parser.AddOption("no-debug-names", "Ignore debug names in the binary file", diff --git a/src/wast-parser.y b/src/wast-parser.y index e0b624e0..c85fa7b6 100644 --- a/src/wast-parser.y +++ b/src/wast-parser.y @@ -834,9 +834,7 @@ const_expr : /* Exceptions */ exception : LPAR EXCEPT bind_var_opt value_type_list RPAR { - $$ = new Exception(); - $$->name = $3; - $$->sig = std::move(*$4); + $$ = new Exception($3, *$4); delete $4; } ; diff --git a/src/wat-writer.cc b/src/wat-writer.cc index 044e8d77..5a9d536e 100644 --- a/src/wat-writer.cc +++ b/src/wat-writer.cc @@ -193,6 +193,7 @@ class WatWriter { Index table_index_ = 0; Index memory_index_ = 0; Index func_type_index_ = 0; + Index except_index_ = 0; }; void WatWriter::Indent() { @@ -1028,7 +1029,7 @@ void WatWriter::WriteGlobal(const Global* global) { void WatWriter::WriteBeginException(const Exception* except) { WriteOpenSpace("except"); - WriteName(&except->name, NextChar::Space); + WriteNameOrIndex(&except->name, except_index_++, NextChar::Space); WriteTypes(except->sig, nullptr); } |