Skip to content

Commit

Permalink
Update exception handling support to current proposal (#1596)
Browse files Browse the repository at this point in the history
This PR updates the support of exception handling to the latest proposal (that is compatible with future 2-phase exception handling) described in WebAssembly/exception-handling#137 and WebAssembly/exception-handling#143.

* Adds back tagged `catch $e`, `catch_all`, and `rethrow N` from a previous version of wabt, but with updates to match the current spec (e.g., `catch_all` shares an opcode with `else`, `rethrow`'s depth indexes only catch blocks, etc).
* Adds `unwind` and `delegate` instructions.
* Removes `exnref` and `br_on_exn`.
* Updates relevant tests.

There are some details that could still change (e.g., maybe how `delegate`'s depth is validated), but I'd be happy to submit further PRs if the spec details change.
  • Loading branch information
takikawa committed Feb 9, 2021
1 parent 09ac53e commit 036a632
Show file tree
Hide file tree
Showing 77 changed files with 2,542 additions and 1,784 deletions.
30 changes: 22 additions & 8 deletions src/apply-names.cc
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ class NameApplier : public ExprVisitor::DelegateNop {
Result EndBlockExpr(BlockExpr*) override;
Result OnBrExpr(BrExpr*) override;
Result OnBrIfExpr(BrIfExpr*) override;
Result OnBrOnExnExpr(BrOnExnExpr*) override;
Result OnBrTableExpr(BrTableExpr*) override;
Result OnCallExpr(CallExpr*) override;
Result OnRefFuncExpr(RefFuncExpr*) override;
Expand Down Expand Up @@ -67,7 +66,10 @@ class NameApplier : public ExprVisitor::DelegateNop {
Result OnTableFillExpr(TableFillExpr*) override;
Result BeginTryExpr(TryExpr*) override;
Result EndTryExpr(TryExpr*) override;
Result OnCatchExpr(TryExpr*, Catch*) override;
Result OnDelegateExpr(TryExpr*) override;
Result OnThrowExpr(ThrowExpr*) override;
Result OnRethrowExpr(RethrowExpr*) override;

private:
void PushLabel(const std::string& label);
Expand Down Expand Up @@ -310,13 +312,6 @@ Result NameApplier::OnBrIfExpr(BrIfExpr* expr) {
return Result::Ok;
}

Result NameApplier::OnBrOnExnExpr(BrOnExnExpr* expr) {
string_view label = FindLabelByVar(&expr->label_var);
UseNameForVar(label, &expr->label_var);
CHECK_RESULT(UseNameForEventVar(&expr->event_var));
return Result::Ok;
}

Result NameApplier::OnBrTableExpr(BrTableExpr* expr) {
for (Var& target : expr->targets) {
string_view label = FindLabelByVar(&target);
Expand All @@ -338,11 +333,30 @@ Result NameApplier::EndTryExpr(TryExpr*) {
return Result::Ok;
}

Result NameApplier::OnCatchExpr(TryExpr*, Catch* expr) {
if (!expr->IsCatchAll()) {
CHECK_RESULT(UseNameForEventVar(&expr->var));
}
return Result::Ok;
}

Result NameApplier::OnDelegateExpr(TryExpr* expr) {
string_view label = FindLabelByVar(&expr->delegate_target);
UseNameForVar(label, &expr->delegate_target);
return Result::Ok;
}

Result NameApplier::OnThrowExpr(ThrowExpr* expr) {
CHECK_RESULT(UseNameForEventVar(&expr->var));
return Result::Ok;
}

Result NameApplier::OnRethrowExpr(RethrowExpr* expr) {
string_view label = FindLabelByVar(&expr->var);
UseNameForVar(label, &expr->var);
return Result::Ok;
}

Result NameApplier::OnCallExpr(CallExpr* expr) {
CHECK_RESULT(UseNameForFuncVar(&expr->var));
return Result::Ok;
Expand Down
98 changes: 79 additions & 19 deletions src/binary-reader-ir.cc
Original file line number Diff line number Diff line change
Expand Up @@ -140,17 +140,17 @@ class BinaryReaderIR : public BinaryReaderNop {
Result OnBlockExpr(Type sig_type) override;
Result OnBrExpr(Index depth) override;
Result OnBrIfExpr(Index depth) override;
Result OnBrOnExnExpr(Index depth, Index event_index) override;
Result OnBrTableExpr(Index num_targets,
Index* target_depths,
Index default_target_depth) override;
Result OnCallExpr(Index func_index) override;
Result OnCatchExpr() override;
Result OnCatchExpr(Index event_index) override;
Result OnCallIndirectExpr(Index sig_index, Index table_index) override;
Result OnReturnCallExpr(Index func_index) override;
Result OnReturnCallIndirectExpr(Index sig_index, Index table_index) override;
Result OnCompareExpr(Opcode opcode) override;
Result OnConvertExpr(Opcode opcode) override;
Result OnDelegateExpr(Index depth) override;
Result OnDropExpr() override;
Result OnElseExpr() override;
Result OnEndExpr() override;
Expand Down Expand Up @@ -187,7 +187,7 @@ class BinaryReaderIR : public BinaryReaderNop {
Result OnRefNullExpr(Type type) override;
Result OnRefIsNullExpr() override;
Result OnNopExpr() override;
Result OnRethrowExpr() override;
Result OnRethrowExpr(Index depth) override;
Result OnReturnExpr() override;
Result OnSelectExpr(Index result_count, Type* result_types) override;
Result OnStoreExpr(Opcode opcode,
Expand All @@ -198,6 +198,7 @@ class BinaryReaderIR : public BinaryReaderNop {
Result OnUnaryExpr(Opcode opcode) override;
Result OnTernaryExpr(Opcode opcode) override;
Result OnUnreachableExpr() override;
Result OnUnwindExpr() override;
Result EndFunctionBody(Index index) override;
Result OnSimdLaneOpExpr(Opcode opcode, uint64_t value) override;
Result OnSimdShuffleOpExpr(Opcode opcode, v128 value) override;
Expand Down Expand Up @@ -274,6 +275,7 @@ class BinaryReaderIR : public BinaryReaderNop {
Result TopLabel(LabelNode** label);
Result TopLabelExpr(LabelNode** label, Expr** expr);
Result AppendExpr(std::unique_ptr<Expr> expr);
Result AppendCatch(Catch&& catch_);
void SetFuncDeclaration(FuncDeclaration* decl, Var var);
void SetBlockDeclaration(BlockDeclaration* decl, Type sig_type);

Expand Down Expand Up @@ -701,13 +703,6 @@ Result BinaryReaderIR::OnBrIfExpr(Index depth) {
return AppendExpr(MakeUnique<BrIfExpr>(Var(depth)));
}

Result BinaryReaderIR::OnBrOnExnExpr(Index depth, Index event_index) {
auto expr = MakeUnique<BrOnExnExpr>();
expr->label_var = Var(depth);
expr->event_var = Var(event_index);
return AppendExpr(std::move(expr));
}

Result BinaryReaderIR::OnBrTableExpr(Index num_targets,
Index* target_depths,
Index default_target_depth) {
Expand Down Expand Up @@ -764,6 +759,8 @@ Result BinaryReaderIR::OnElseExpr() {
if_expr->true_.end_loc = GetLocation();
label->exprs = &if_expr->false_;
label->label_type = LabelType::Else;
} else if (label->label_type == LabelType::Try) {
return AppendCatch(Catch(GetLocation()));
} else {
PrintError("else expression without matching if");
return Result::Error;
Expand Down Expand Up @@ -795,6 +792,7 @@ Result BinaryReaderIR::OnEndExpr() {

case LabelType::Func:
case LabelType::Catch:
case LabelType::Unwind:
break;
}

Expand Down Expand Up @@ -929,8 +927,8 @@ Result BinaryReaderIR::OnNopExpr() {
return AppendExpr(MakeUnique<NopExpr>());
}

Result BinaryReaderIR::OnRethrowExpr() {
return AppendExpr(MakeUnique<RethrowExpr>());
Result BinaryReaderIR::OnRethrowExpr(Index depth) {
return AppendExpr(MakeUnique<RethrowExpr>(Var(depth, GetLocation())));
}

Result BinaryReaderIR::OnReturnExpr() {
Expand Down Expand Up @@ -977,19 +975,81 @@ Result BinaryReaderIR::OnTryExpr(Type sig_type) {
return Result::Ok;
}

Result BinaryReaderIR::OnCatchExpr() {
LabelNode* label;
Result BinaryReaderIR::AppendCatch(Catch&& catch_) {
LabelNode* label = nullptr;
CHECK_RESULT(TopLabel(&label));

if (label->label_type != LabelType::Try) {
PrintError("catch expression without matching try");
PrintError("catch not inside try block");
return Result::Error;
}

LabelNode* parent_label;
CHECK_RESULT(GetLabelAt(&parent_label, 1));
auto* try_ = cast<TryExpr>(label->context);

if (catch_.IsCatchAll() && !try_->catches.empty() && try_->catches.back().IsCatchAll()) {
PrintError("only one catch_all allowed in try block");
return Result::Error;
}

if (try_->kind == TryKind::Invalid) {
try_->kind = TryKind::Catch;
} else if (try_->kind != TryKind::Catch) {
PrintError("catch not allowed in try-unwind or try-delegate");
return Result::Error;
}

try_->catches.push_back(std::move(catch_));
label->exprs = &try_->catches.back().exprs;
return Result::Ok;
}

Result BinaryReaderIR::OnCatchExpr(Index except_index) {
return AppendCatch(Catch(Var(except_index, GetLocation())));
}

Result BinaryReaderIR::OnUnwindExpr() {
LabelNode* label = nullptr;
CHECK_RESULT(TopLabel(&label));

if (label->label_type != LabelType::Try) {
PrintError("unwind not inside try block");
return Result::Error;
}

auto* try_ = cast<TryExpr>(label->context);

if (try_->kind == TryKind::Invalid) {
try_->kind = TryKind::Unwind;
} else if (try_->kind != TryKind::Unwind) {
PrintError("unwind not allowed in try-catch or try-delegate");
return Result::Error;
}

label->exprs = &try_->unwind;
return Result::Ok;
}

Result BinaryReaderIR::OnDelegateExpr(Index depth) {
LabelNode* label = nullptr;
CHECK_RESULT(TopLabel(&label));

if (label->label_type != LabelType::Try) {
PrintError("delegate not inside try block");
return Result::Error;
}

auto* try_ = cast<TryExpr>(label->context);

if (try_->kind == TryKind::Invalid) {
try_->kind = TryKind::Delegate;
} else if (try_->kind != TryKind::Delegate) {
PrintError("delegate not allowed in try-catch or try-unwind");
return Result::Error;
}

try_->delegate_target = Var(depth, GetLocation());

label->label_type = LabelType::Catch;
label->exprs = &cast<TryExpr>(&parent_label->exprs->back())->catch_;
PopLabel();
return Result::Ok;
}

Expand Down
7 changes: 4 additions & 3 deletions src/binary-reader-logging.cc
Original file line number Diff line number Diff line change
Expand Up @@ -790,13 +790,13 @@ DEFINE_LOAD_STORE_OPCODE(OnAtomicStoreExpr);
DEFINE_LOAD_STORE_OPCODE(OnAtomicWaitExpr);
DEFINE_INDEX_DESC(OnAtomicFenceExpr, "consistency_model");
DEFINE_LOAD_STORE_OPCODE(OnAtomicNotifyExpr);
DEFINE_INDEX_INDEX(OnBrOnExnExpr, "depth", "event_index");
DEFINE_OPCODE(OnBinaryExpr)
DEFINE_INDEX_DESC(OnCallExpr, "func_index")
DEFINE_INDEX_INDEX(OnCallIndirectExpr, "sig_index", "table_index")
DEFINE0(OnCatchExpr);
DEFINE_INDEX_DESC(OnCatchExpr, "event_index");
DEFINE_OPCODE(OnCompareExpr)
DEFINE_OPCODE(OnConvertExpr)
DEFINE_INDEX_DESC(OnDelegateExpr, "depth");
DEFINE0(OnDropExpr)
DEFINE0(OnElseExpr)
DEFINE0(OnEndExpr)
Expand Down Expand Up @@ -824,7 +824,7 @@ DEFINE_INDEX(OnRefFuncExpr)
DEFINE_TYPE(OnRefNullExpr)
DEFINE0(OnRefIsNullExpr)
DEFINE0(OnNopExpr)
DEFINE0(OnRethrowExpr);
DEFINE_INDEX_DESC(OnRethrowExpr, "depth");
DEFINE_INDEX_DESC(OnReturnCallExpr, "func_index")

DEFINE_INDEX_INDEX(OnReturnCallIndirectExpr, "sig_index", "table_index")
Expand All @@ -833,6 +833,7 @@ DEFINE_LOAD_STORE_OPCODE(OnLoadSplatExpr);
DEFINE_LOAD_STORE_OPCODE(OnStoreExpr);
DEFINE_INDEX_DESC(OnThrowExpr, "event_index")
DEFINE0(OnUnreachableExpr)
DEFINE0(OnUnwindExpr)
DEFINE_OPCODE(OnUnaryExpr)
DEFINE_OPCODE(OnTernaryExpr)
DEFINE_END(EndCodeSection)
Expand Down
7 changes: 4 additions & 3 deletions src/binary-reader-logging.h
Original file line number Diff line number Diff line change
Expand Up @@ -159,15 +159,15 @@ class BinaryReaderLogging : public BinaryReaderDelegate {
Result OnBlockExpr(Type sig_type) override;
Result OnBrExpr(Index depth) override;
Result OnBrIfExpr(Index depth) override;
Result OnBrOnExnExpr(Index depth, Index event_index) override;
Result OnBrTableExpr(Index num_targets,
Index* target_depths,
Index default_target_depth) override;
Result OnCallExpr(Index func_index) override;
Result OnCatchExpr() override;
Result OnCatchExpr(Index event_index) override;
Result OnCallIndirectExpr(Index sig_index, Index table_index) override;
Result OnCompareExpr(Opcode opcode) override;
Result OnConvertExpr(Opcode opcode) override;
Result OnDelegateExpr(Index depth) override;
Result OnDropExpr() override;
Result OnElseExpr() override;
Result OnEndExpr() override;
Expand Down Expand Up @@ -205,7 +205,7 @@ class BinaryReaderLogging : public BinaryReaderDelegate {
Result OnRefNullExpr(Type type) override;
Result OnRefIsNullExpr() override;
Result OnNopExpr() override;
Result OnRethrowExpr() override;
Result OnRethrowExpr(Index depth) override;
Result OnReturnCallExpr(Index func_index) override;
Result OnReturnCallIndirectExpr(Index sig_index, Index table_index) override;
Result OnReturnExpr() override;
Expand All @@ -218,6 +218,7 @@ class BinaryReaderLogging : public BinaryReaderDelegate {
Result OnUnaryExpr(Opcode opcode) override;
Result OnTernaryExpr(Opcode opcode) override;
Result OnUnreachableExpr() override;
Result OnUnwindExpr() override;
Result OnAtomicWaitExpr(Opcode opcode,
Address alignment_log2,
Address offset) override;
Expand Down
9 changes: 4 additions & 5 deletions src/binary-reader-nop.h
Original file line number Diff line number Diff line change
Expand Up @@ -226,19 +226,17 @@ class BinaryReaderNop : public BinaryReaderDelegate {
Result OnBlockExpr(Type sig_type) override { return Result::Ok; }
Result OnBrExpr(Index depth) override { return Result::Ok; }
Result OnBrIfExpr(Index depth) override { return Result::Ok; }
Result OnBrOnExnExpr(Index depth, Index event_index) override {
return Result::Ok;
}
Result OnBrTableExpr(Index num_targets,
Index* target_depths,
Index default_target_depth) override {
return Result::Ok;
}
Result OnCallExpr(Index func_index) override { return Result::Ok; }
Result OnCallIndirectExpr(Index sig_index, Index table_index) override { return Result::Ok; }
Result OnCatchExpr() override { return Result::Ok; }
Result OnCatchExpr(Index event_index) override { return Result::Ok; }
Result OnCompareExpr(Opcode opcode) override { return Result::Ok; }
Result OnConvertExpr(Opcode opcode) override { return Result::Ok; }
Result OnDelegateExpr(Index depth) override { return Result::Ok; }
Result OnDropExpr() override { return Result::Ok; }
Result OnElseExpr() override { return Result::Ok; }
Result OnEndExpr() override { return Result::Ok; }
Expand Down Expand Up @@ -282,7 +280,7 @@ class BinaryReaderNop : public BinaryReaderDelegate {
Result OnRefNullExpr(Type type) override { return Result::Ok; }
Result OnRefIsNullExpr() override { return Result::Ok; }
Result OnNopExpr() override { return Result::Ok; }
Result OnRethrowExpr() override { return Result::Ok; }
Result OnRethrowExpr(Index depth) override { return Result::Ok; }
Result OnReturnCallExpr(Index sig_index) override { return Result::Ok; }
Result OnReturnCallIndirectExpr(Index sig_index, Index table_index) override { return Result::Ok; }
Result OnReturnExpr() override { return Result::Ok; }
Expand All @@ -299,6 +297,7 @@ class BinaryReaderNop : public BinaryReaderDelegate {
Result OnUnaryExpr(Opcode opcode) override { return Result::Ok; }
Result OnTernaryExpr(Opcode opcode) override { return Result::Ok; }
Result OnUnreachableExpr() override { return Result::Ok; }
Result OnUnwindExpr() override { return Result::Ok; }
Result EndFunctionBody(Index index) override { return Result::Ok; }
Result EndCodeSection() override { return Result::Ok; }
Result OnSimdLaneOpExpr(Opcode opcode, uint64_t value) override {
Expand Down
11 changes: 11 additions & 0 deletions src/binary-reader-objdump.cc
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,7 @@ class BinaryReaderObjdumpDisassemble : public BinaryReaderObjdumpBase {
Result OnBrTableExpr(Index num_targets,
Index* target_depths,
Index default_target_depth) override;
Result OnDelegateExpr(Index) override;
Result OnEndExpr() override;
Result OnEndFunc() override;

Expand Down Expand Up @@ -595,6 +596,7 @@ void BinaryReaderObjdumpDisassemble::LogOpcode(size_t data_size,
switch (current_opcode) {
case Opcode::Else:
case Opcode::Catch:
case Opcode::Unwind:
indent_level--;
default:
break;
Expand Down Expand Up @@ -741,6 +743,15 @@ Result BinaryReaderObjdumpDisassemble::OnBrTableExpr(
return Result::Ok;
}

Result BinaryReaderObjdumpDisassemble::OnDelegateExpr(Index depth) {
// Because `delegate` ends the block we need to dedent here, and
// we don't need to dedent it in LogOpcode.
if (indent_level > 0) {
indent_level--;
}
return Result::Ok;
}

Result BinaryReaderObjdumpDisassemble::OnEndFunc() {
LogOpcode(0, nullptr);
return Result::Ok;
Expand Down
Loading

0 comments on commit 036a632

Please sign in to comment.