summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/binary-reader-ir.cc113
-rw-r--r--src/binary-reader-logging.cc41
-rw-r--r--src/binary-reader-logging.h16
-rw-r--r--src/binary-reader-nop.h22
-rw-r--r--src/binary-reader.cc126
-rw-r--r--src/binary-reader.h18
-rw-r--r--src/binary.h1
-rw-r--r--src/ir.cc25
-rw-r--r--src/ir.h13
-rw-r--r--src/tools/wasm2wast.cc4
-rw-r--r--src/wast-parser.y4
-rw-r--r--src/wat-writer.cc3
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(&section_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) \
diff --git a/src/ir.cc b/src/ir.cc
index c3196a33..cd6e4d90 100644
--- a/src/ir.cc
+++ b/src/ir.cc
@@ -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_;
diff --git a/src/ir.h b/src/ir.h
index 2d450781..b77f28b3 100644
--- a/src/ir.h
+++ b/src/ir.h
@@ -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);
}