Skip to content

Commit beccdf7

Browse files
authored
Basic EH instrucion support for the new spec (#3487)
This updates `try`-`catch`-`catch_all` and `rethrow` instructions to match the new spec. `delegate` is not included. Now `Try` contains not a single `catchBody` expression but a vector of catch bodies and events. This updates most existing routines, optimizations, and tests modulo the interpreter and the CFG traversal. Because the interpreter has not been updated yet, the EH spec test is temporarily disabled in check.py. Also, because the CFG traversal for EH is not yet updated, several EH tests in `rse_all-features.wast`, which uses CFG traversal, are temporarily commented out. Also added a few more tests in existing EH test functions in test/passes. In the previous spec, `catch` was catching all exceptions so it was assumed that anything `try` body throws is caught by its `catch`, but now we can assume the same only if there is a `catch_all`. Newly added tests test cases when there is a `catch_all` and cases there are only `catch`es separately.
1 parent f18c18e commit beccdf7

File tree

73 files changed

+1621
-961
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

73 files changed

+1621
-961
lines changed

check.py

+3
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,9 @@ def run_spec_tests():
189189
# windows has some failures that need to be investigated
190190
if base == 'names.wast' and shared.skip_if_on_windows('spec: ' + base):
191191
continue
192+
# FIXME Reenable this after updating interpreter for EH
193+
if base == 'exception-handling.wast':
194+
continue
192195

193196
def run_spec_test(wast):
194197
cmd = shared.WASM_SHELL + [wast]

src/binaryen-c.cpp

+109-18
Original file line numberDiff line numberDiff line change
@@ -1200,10 +1200,20 @@ BinaryenExpressionRef BinaryenRefEq(BinaryenModuleRef module,
12001200

12011201
BinaryenExpressionRef BinaryenTry(BinaryenModuleRef module,
12021202
BinaryenExpressionRef body,
1203-
BinaryenExpressionRef catchBody) {
1203+
const char** catchEvents_,
1204+
BinaryenIndex numCatchEvents,
1205+
BinaryenExpressionRef* catchBodies_,
1206+
BinaryenIndex numCatchBodies) {
1207+
std::vector<Name> catchEvents;
1208+
std::vector<Expression*> catchBodies;
1209+
for (BinaryenIndex i = 0; i < numCatchEvents; i++) {
1210+
catchEvents.push_back(catchEvents_[i]);
1211+
}
1212+
for (BinaryenIndex i = 0; i < numCatchBodies; i++) {
1213+
catchBodies.push_back((Expression*)catchBodies_[i]);
1214+
}
12041215
return static_cast<Expression*>(
1205-
Builder(*(Module*)module)
1206-
.makeTry((Expression*)body, (Expression*)catchBody));
1216+
Builder(*(Module*)module).makeTry(body, catchEvents, catchBodies));
12071217
}
12081218

12091219
BinaryenExpressionRef BinaryenThrow(BinaryenModuleRef module,
@@ -1219,9 +1229,8 @@ BinaryenExpressionRef BinaryenThrow(BinaryenModuleRef module,
12191229
}
12201230

12211231
BinaryenExpressionRef BinaryenRethrow(BinaryenModuleRef module,
1222-
BinaryenExpressionRef exnref) {
1223-
return static_cast<Expression*>(
1224-
Builder(*(Module*)module).makeRethrow((Expression*)exnref));
1232+
BinaryenIndex depth) {
1233+
return static_cast<Expression*>(Builder(*(Module*)module).makeRethrow(depth));
12251234
}
12261235

12271236
BinaryenExpressionRef BinaryenBrOnExn(BinaryenModuleRef module,
@@ -2755,17 +2764,101 @@ void BinaryenTrySetBody(BinaryenExpressionRef expr,
27552764
assert(bodyExpr);
27562765
static_cast<Try*>(expression)->body = (Expression*)bodyExpr;
27572766
}
2758-
BinaryenExpressionRef BinaryenTryGetCatchBody(BinaryenExpressionRef expr) {
2767+
BinaryenIndex BinaryenTryGetNumCatchEvents(BinaryenExpressionRef expr) {
2768+
auto* expression = (Expression*)expr;
2769+
assert(expression->is<Try>());
2770+
return static_cast<Try*>(expression)->catchEvents.size();
2771+
}
2772+
BinaryenIndex BinaryenTryGetNumCatchBodies(BinaryenExpressionRef expr) {
2773+
auto* expression = (Expression*)expr;
2774+
assert(expression->is<Try>());
2775+
return static_cast<Try*>(expression)->catchBodies.size();
2776+
}
2777+
const char* BinaryenTryGetCatchEventAt(BinaryenExpressionRef expr,
2778+
BinaryenIndex index) {
2779+
auto* expression = (Expression*)expr;
2780+
assert(expression->is<Try>());
2781+
assert(index < static_cast<Try*>(expression)->catchEvents.size());
2782+
return static_cast<Try*>(expression)->catchEvents[index].c_str();
2783+
}
2784+
void BinaryenTrySetCatchEventAt(BinaryenExpressionRef expr,
2785+
BinaryenIndex index,
2786+
const char* catchEvent) {
27592787
auto* expression = (Expression*)expr;
27602788
assert(expression->is<Try>());
2761-
return static_cast<Try*>(expression)->catchBody;
2789+
assert(index < static_cast<Try*>(expression)->catchEvents.size());
2790+
assert(catchEvent);
2791+
static_cast<Try*>(expression)->catchEvents[index] = catchEvent;
27622792
}
2763-
void BinaryenTrySetCatchBody(BinaryenExpressionRef expr,
2764-
BinaryenExpressionRef catchBodyExpr) {
2793+
BinaryenIndex BinaryenTryAppendCatchEvent(BinaryenExpressionRef expr,
2794+
const char* catchEvent) {
27652795
auto* expression = (Expression*)expr;
27662796
assert(expression->is<Try>());
2767-
assert(catchBodyExpr);
2768-
static_cast<Try*>(expression)->catchBody = (Expression*)catchBodyExpr;
2797+
assert(catchEvent);
2798+
auto& list = static_cast<Try*>(expression)->catchEvents;
2799+
auto index = list.size();
2800+
list.push_back(catchEvent);
2801+
return index;
2802+
}
2803+
void BinaryenTryInsertCatchEventAt(BinaryenExpressionRef expr,
2804+
BinaryenIndex index,
2805+
const char* catchEvent) {
2806+
auto* expression = (Expression*)expr;
2807+
assert(expression->is<Try>());
2808+
assert(catchEvent);
2809+
static_cast<Try*>(expression)->catchEvents.insertAt(index, catchEvent);
2810+
}
2811+
const char* BinaryenTryRemoveCatchEventAt(BinaryenExpressionRef expr,
2812+
BinaryenIndex index) {
2813+
auto* expression = (Expression*)expr;
2814+
assert(expression->is<Try>());
2815+
return static_cast<Try*>(expression)->catchEvents.removeAt(index).c_str();
2816+
}
2817+
BinaryenExpressionRef BinaryenTryGetCatchBodyAt(BinaryenExpressionRef expr,
2818+
BinaryenIndex index) {
2819+
auto* expression = (Expression*)expr;
2820+
assert(expression->is<Try>());
2821+
assert(index < static_cast<Try*>(expression)->catchBodies.size());
2822+
return static_cast<Try*>(expression)->catchBodies[index];
2823+
}
2824+
void BinaryenTrySetCatchBodyAt(BinaryenExpressionRef expr,
2825+
BinaryenIndex index,
2826+
BinaryenExpressionRef catchExpr) {
2827+
auto* expression = (Expression*)expr;
2828+
assert(expression->is<Try>());
2829+
assert(index < static_cast<Try*>(expression)->catchBodies.size());
2830+
assert(catchExpr);
2831+
static_cast<Try*>(expression)->catchBodies[index] = (Expression*)catchExpr;
2832+
}
2833+
BinaryenIndex BinaryenTryAppendCatchBody(BinaryenExpressionRef expr,
2834+
BinaryenExpressionRef catchExpr) {
2835+
auto* expression = (Expression*)expr;
2836+
assert(expression->is<Try>());
2837+
assert(catchExpr);
2838+
auto& list = static_cast<Try*>(expression)->catchBodies;
2839+
auto index = list.size();
2840+
list.push_back((Expression*)catchExpr);
2841+
return index;
2842+
}
2843+
void BinaryenTryInsertCatchBodyAt(BinaryenExpressionRef expr,
2844+
BinaryenIndex index,
2845+
BinaryenExpressionRef catchExpr) {
2846+
auto* expression = (Expression*)expr;
2847+
assert(expression->is<Try>());
2848+
assert(catchExpr);
2849+
static_cast<Try*>(expression)
2850+
->catchBodies.insertAt(index, (Expression*)catchExpr);
2851+
}
2852+
BinaryenExpressionRef BinaryenTryRemoveCatchBodyAt(BinaryenExpressionRef expr,
2853+
BinaryenIndex index) {
2854+
auto* expression = (Expression*)expr;
2855+
assert(expression->is<Try>());
2856+
return static_cast<Try*>(expression)->catchBodies.removeAt(index);
2857+
}
2858+
int BinaryenTryHasCatchAll(BinaryenExpressionRef expr) {
2859+
auto* expression = (Expression*)expr;
2860+
assert(expression->is<Try>());
2861+
return static_cast<Try*>(expression)->hasCatchAll();
27692862
}
27702863
// Throw
27712864
const char* BinaryenThrowGetEvent(BinaryenExpressionRef expr) {
@@ -2825,17 +2918,15 @@ BinaryenExpressionRef BinaryenThrowRemoveOperandAt(BinaryenExpressionRef expr,
28252918
return static_cast<Throw*>(expression)->operands.removeAt(index);
28262919
}
28272920
// Rethrow
2828-
BinaryenExpressionRef BinaryenRethrowGetExnref(BinaryenExpressionRef expr) {
2921+
BinaryenIndex BinaryenRethrowGetDepth(BinaryenExpressionRef expr) {
28292922
auto* expression = (Expression*)expr;
28302923
assert(expression->is<Rethrow>());
2831-
return static_cast<Rethrow*>(expression)->exnref;
2924+
return static_cast<Rethrow*>(expression)->depth;
28322925
}
2833-
void BinaryenRethrowSetExnref(BinaryenExpressionRef expr,
2834-
BinaryenExpressionRef exnrefExpr) {
2926+
void BinaryenRethrowSetDepth(BinaryenExpressionRef expr, BinaryenIndex depth) {
28352927
auto* expression = (Expression*)expr;
28362928
assert(expression->is<Rethrow>());
2837-
assert(exnrefExpr);
2838-
static_cast<Rethrow*>(expression)->exnref = (Expression*)exnrefExpr;
2929+
static_cast<Rethrow*>(expression)->depth = depth;
28392930
}
28402931
// BrOnExn
28412932
const char* BinaryenBrOnExnGetEvent(BinaryenExpressionRef expr) {

src/binaryen-c.h

+63-15
Original file line numberDiff line numberDiff line change
@@ -796,16 +796,20 @@ BINARYEN_API BinaryenExpressionRef BinaryenRefFunc(BinaryenModuleRef module,
796796
BINARYEN_API BinaryenExpressionRef BinaryenRefEq(BinaryenModuleRef module,
797797
BinaryenExpressionRef left,
798798
BinaryenExpressionRef right);
799-
BINARYEN_API BinaryenExpressionRef BinaryenTry(BinaryenModuleRef module,
800-
BinaryenExpressionRef body,
801-
BinaryenExpressionRef catchBody);
799+
BINARYEN_API BinaryenExpressionRef
800+
BinaryenTry(BinaryenModuleRef module,
801+
BinaryenExpressionRef body,
802+
const char** catchEvents,
803+
BinaryenIndex numCatchEvents,
804+
BinaryenExpressionRef* catchBodies,
805+
BinaryenIndex numCatchBodies);
802806
BINARYEN_API BinaryenExpressionRef
803807
BinaryenThrow(BinaryenModuleRef module,
804808
const char* event,
805809
BinaryenExpressionRef* operands,
806810
BinaryenIndex numOperands);
807-
BINARYEN_API BinaryenExpressionRef
808-
BinaryenRethrow(BinaryenModuleRef module, BinaryenExpressionRef exnref);
811+
BINARYEN_API BinaryenExpressionRef BinaryenRethrow(BinaryenModuleRef module,
812+
BinaryenIndex depth);
809813
BINARYEN_API BinaryenExpressionRef
810814
BinaryenBrOnExn(BinaryenModuleRef module,
811815
const char* name,
@@ -1714,12 +1718,57 @@ BinaryenTryGetBody(BinaryenExpressionRef expr);
17141718
// Sets the body expression of a `try` expression.
17151719
BINARYEN_API void BinaryenTrySetBody(BinaryenExpressionRef expr,
17161720
BinaryenExpressionRef bodyExpr);
1717-
// Gets the catch body expression of a `try` expression.
1721+
// Gets the number of catch blocks (= the number of catch events) of a `try`
1722+
// expression.
1723+
BINARYEN_API BinaryenIndex
1724+
BinaryenTryGetNumCatchEvents(BinaryenExpressionRef expr);
1725+
// Gets the number of catch/catch_all blocks of a `try` expression.
1726+
BINARYEN_API BinaryenIndex
1727+
BinaryenTryGetNumCatchBodies(BinaryenExpressionRef expr);
1728+
// Gets the catch event at the specified index of a `try` expression.
1729+
BINARYEN_API const char* BinaryenTryGetCatchEventAt(BinaryenExpressionRef expr,
1730+
BinaryenIndex index);
1731+
// Sets the catch event at the specified index of a `try` expression.
1732+
BINARYEN_API void BinaryenTrySetCatchEventAt(BinaryenExpressionRef expr,
1733+
BinaryenIndex index,
1734+
const char* catchEvent);
1735+
// Appends a catch event to a `try` expression, returning its insertion index.
1736+
BINARYEN_API BinaryenIndex
1737+
BinaryenTryAppendCatchEvent(BinaryenExpressionRef expr, const char* catchEvent);
1738+
// Inserts a catch event at the specified index of a `try` expression, moving
1739+
// existing catch events including the one previously at that index one index
1740+
// up.
1741+
BINARYEN_API void BinaryenTryInsertCatchEventAt(BinaryenExpressionRef expr,
1742+
BinaryenIndex index,
1743+
const char* catchEvent);
1744+
// Removes the catch event at the specified index of a `try` expression, moving
1745+
// all subsequent catch events one index down. Returns the event.
1746+
BINARYEN_API const char*
1747+
BinaryenTryRemoveCatchEventAt(BinaryenExpressionRef expr, BinaryenIndex index);
1748+
// Gets the catch body expression at the specified index of a `try` expression.
1749+
BINARYEN_API BinaryenExpressionRef
1750+
BinaryenTryGetCatchBodyAt(BinaryenExpressionRef expr, BinaryenIndex index);
1751+
// Sets the catch body expression at the specified index of a `try` expression.
1752+
BINARYEN_API void BinaryenTrySetCatchBodyAt(BinaryenExpressionRef expr,
1753+
BinaryenIndex index,
1754+
BinaryenExpressionRef catchExpr);
1755+
// Appends a catch expression to a `try` expression, returning its insertion
1756+
// index.
1757+
BINARYEN_API BinaryenIndex BinaryenTryAppendCatchBody(
1758+
BinaryenExpressionRef expr, BinaryenExpressionRef catchExpr);
1759+
// Inserts a catch expression at the specified index of a `try` expression,
1760+
// moving existing catch bodies including the one previously at that index one
1761+
// index up.
1762+
BINARYEN_API void BinaryenTryInsertCatchBodyAt(BinaryenExpressionRef expr,
1763+
BinaryenIndex index,
1764+
BinaryenExpressionRef catchExpr);
1765+
// Removes the catch expression at the specified index of a `try` expression,
1766+
// moving all subsequent catch bodies one index down. Returns the catch
1767+
// expression.
17181768
BINARYEN_API BinaryenExpressionRef
1719-
BinaryenTryGetCatchBody(BinaryenExpressionRef expr);
1720-
// Sets the catch body expression of a `try` expression.
1721-
BINARYEN_API void BinaryenTrySetCatchBody(BinaryenExpressionRef expr,
1722-
BinaryenExpressionRef catchBodyExpr);
1769+
BinaryenTryRemoveCatchBodyAt(BinaryenExpressionRef expr, BinaryenIndex index);
1770+
// Gets whether an `try` expression has a catch_all clause.
1771+
BINARYEN_API int BinaryenTryHasCatchAll(BinaryenExpressionRef expr);
17231772

17241773
// Throw
17251774

@@ -1757,12 +1806,11 @@ BinaryenThrowRemoveOperandAt(BinaryenExpressionRef expr, BinaryenIndex index);
17571806

17581807
// Rethrow
17591808

1760-
// Gets the exception reference expression of a `rethrow` expression.
1761-
BINARYEN_API BinaryenExpressionRef
1762-
BinaryenRethrowGetExnref(BinaryenExpressionRef expr);
1809+
// Gets the depth of a `rethrow` expression.
1810+
BINARYEN_API BinaryenIndex BinaryenRethrowGetDepth(BinaryenExpressionRef expr);
17631811
// Sets the exception reference expression of a `rethrow` expression.
1764-
BINARYEN_API void BinaryenRethrowSetExnref(BinaryenExpressionRef expr,
1765-
BinaryenExpressionRef exnrefExpr);
1812+
BINARYEN_API void BinaryenRethrowSetDepth(BinaryenExpressionRef expr,
1813+
BinaryenIndex depth);
17661814

17671815
// BrOnExn
17681816

src/cfg/cfg-traversal.h

+4
Original file line numberDiff line numberDiff line change
@@ -304,12 +304,16 @@ struct CFGWalker : public ControlFlowWalker<SubType, VisitorType> {
304304
break;
305305
}
306306
case Expression::Id::TryId: {
307+
// FIXME Update the implementation to match the new spec
308+
WASM_UNREACHABLE("unimp");
309+
/*
307310
self->pushTask(SubType::doEndTry, currp);
308311
self->pushTask(SubType::scan, &curr->cast<Try>()->catchBody);
309312
self->pushTask(SubType::doStartCatch, currp);
310313
self->pushTask(SubType::scan, &curr->cast<Try>()->body);
311314
self->pushTask(SubType::doStartTry, currp);
312315
return; // don't do anything else
316+
*/
313317
}
314318
case Expression::Id::ThrowId:
315319
case Expression::Id::RethrowId: {

src/ir/ExpressionAnalyzer.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,7 @@ bool ExpressionAnalyzer::flexibleEqual(Expression* left,
206206
}
207207

208208
#define DELEGATE_FIELD_INT_ARRAY(id, name) COMPARE_LIST(name)
209+
#define DELEGATE_FIELD_NAME_VECTOR(id, name) COMPARE_LIST(name)
209210

210211
#define DELEGATE_FIELD_SCOPE_NAME_DEF(id, name) \
211212
if (castLeft->name.is() != castRight->name.is()) { \

src/ir/ExpressionManipulator.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ flexibleCopy(Expression* original, Module& wasm, CustomCopier custom) {
9797
COPY_FIELD_LIST(name)
9898

9999
#define DELEGATE_FIELD_SCOPE_NAME_USE_VECTOR(id, name) COPY_VECTOR(name)
100+
#define DELEGATE_FIELD_NAME_VECTOR(id, name) COPY_VECTOR(name)
100101

101102
#define DELEGATE_FIELD_INT_ARRAY(id, name) COPY_ARRAY(name)
102103

src/ir/branch-utils.h

+2
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ template<typename T> void operateOnScopeNameUses(Expression* expr, T func) {
5858
#define DELEGATE_FIELD_INT(id, name)
5959
#define DELEGATE_FIELD_LITERAL(id, name)
6060
#define DELEGATE_FIELD_NAME(id, name)
61+
#define DELEGATE_FIELD_NAME_VECTOR(id, name)
6162
#define DELEGATE_FIELD_SCOPE_NAME_DEF(id, name)
6263
#define DELEGATE_FIELD_SIGNATURE(id, name)
6364
#define DELEGATE_FIELD_TYPE(id, name)
@@ -104,6 +105,7 @@ template<typename T> void operateOnScopeNameDefs(Expression* expr, T func) {
104105
#define DELEGATE_FIELD_INT(id, name)
105106
#define DELEGATE_FIELD_LITERAL(id, name)
106107
#define DELEGATE_FIELD_NAME(id, name)
108+
#define DELEGATE_FIELD_NAME_VECTOR(id, name)
107109
#define DELEGATE_FIELD_SIGNATURE(id, name)
108110
#define DELEGATE_FIELD_TYPE(id, name)
109111
#define DELEGATE_FIELD_ADDRESS(id, name)

src/ir/cost.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -546,7 +546,7 @@ struct CostAnalyzer : public OverriddenVisitor<CostAnalyzer, Index> {
546546
}
547547
Index visitTry(Try* curr) {
548548
// We assume no exception will be thrown in most cases
549-
return visit(curr->body) + maybeVisit(curr->catchBody);
549+
return visit(curr->body);
550550
}
551551
Index visitThrow(Throw* curr) {
552552
Index ret = 100;
@@ -555,7 +555,7 @@ struct CostAnalyzer : public OverriddenVisitor<CostAnalyzer, Index> {
555555
}
556556
return ret;
557557
}
558-
Index visitRethrow(Rethrow* curr) { return 100 + visit(curr->exnref); }
558+
Index visitRethrow(Rethrow* curr) { return 100; }
559559
Index visitBrOnExn(BrOnExn* curr) {
560560
return 1 + visit(curr->exnref) + curr->sent.size();
561561
}

0 commit comments

Comments
 (0)