Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Basic EH instrucion support for the new spec #3487

Merged
merged 11 commits into from
Jan 15, 2021
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions check.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,9 @@ def run_spec_tests():
# windows has some failures that need to be investigated
if base == 'names.wast' and shared.skip_if_on_windows('spec: ' + base):
continue
# FIXME Reenable this after updating interpreter for EH
if base == 'exception-handling.wast':
continue

def run_spec_test(wast):
cmd = shared.WASM_SHELL + [wast]
Expand Down
129 changes: 110 additions & 19 deletions src/binaryen-c.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1200,10 +1200,20 @@ BinaryenExpressionRef BinaryenRefEq(BinaryenModuleRef module,

BinaryenExpressionRef BinaryenTry(BinaryenModuleRef module,
BinaryenExpressionRef body,
BinaryenExpressionRef catchBody) {
return static_cast<Expression*>(
Builder(*(Module*)module)
.makeTry((Expression*)body, (Expression*)catchBody));
const char** catchEvents,
BinaryenIndex numCatchEvents,
BinaryenExpressionRef* catchBodies,
BinaryenIndex numCatchBodies) {
auto* ret = ((Module*)module)->allocator.alloc<Try>();
ret->body = (Expression*)body;
for (BinaryenIndex i = 0; i < numCatchEvents; i++) {
ret->catchEvents.push_back(catchEvents[i]);
}
for (BinaryenIndex i = 0; i < numCatchBodies; i++) {
ret->catchBodies.push_back((Expression*)catchBodies[i]);
}
ret->finalize();
aheejin marked this conversation as resolved.
Show resolved Hide resolved
return ret;
}

BinaryenExpressionRef BinaryenThrow(BinaryenModuleRef module,
Expand All @@ -1219,9 +1229,8 @@ BinaryenExpressionRef BinaryenThrow(BinaryenModuleRef module,
}

BinaryenExpressionRef BinaryenRethrow(BinaryenModuleRef module,
BinaryenExpressionRef exnref) {
return static_cast<Expression*>(
Builder(*(Module*)module).makeRethrow((Expression*)exnref));
BinaryenIndex depth) {
return static_cast<Expression*>(Builder(*(Module*)module).makeRethrow(depth));
}

BinaryenExpressionRef BinaryenBrOnExn(BinaryenModuleRef module,
Expand Down Expand Up @@ -2755,17 +2764,101 @@ void BinaryenTrySetBody(BinaryenExpressionRef expr,
assert(bodyExpr);
static_cast<Try*>(expression)->body = (Expression*)bodyExpr;
}
BinaryenExpressionRef BinaryenTryGetCatchBody(BinaryenExpressionRef expr) {
BinaryenIndex BinaryenTryGetNumCatchEvents(BinaryenExpressionRef expr) {
auto* expression = (Expression*)expr;
assert(expression->is<Try>());
return static_cast<Try*>(expression)->catchEvents.size();
}
BinaryenIndex BinaryenTryGetNumCatchBodies(BinaryenExpressionRef expr) {
auto* expression = (Expression*)expr;
assert(expression->is<Try>());
return static_cast<Try*>(expression)->catchBodies.size();
}
const char* BinaryenTryGetCatchEventAt(BinaryenExpressionRef expr,
BinaryenIndex index) {
auto* expression = (Expression*)expr;
assert(expression->is<Try>());
assert(index < static_cast<Try*>(expression)->catchEvents.size());
return static_cast<Try*>(expression)->catchEvents[index].c_str();
}
void BinaryenTrySetCatchEventAt(BinaryenExpressionRef expr,
BinaryenIndex index,
const char* catchEvent) {
auto* expression = (Expression*)expr;
assert(expression->is<Try>());
assert(index < static_cast<Try*>(expression)->catchEvents.size());
assert(catchEvent);
static_cast<Try*>(expression)->catchEvents[index] = catchEvent;
}
BinaryenIndex BinaryenTryAppendCatchEvent(BinaryenExpressionRef expr,
const char* catchEvent) {
auto* expression = (Expression*)expr;
assert(expression->is<Try>());
return static_cast<Try*>(expression)->catchBody;
assert(catchEvent);
auto& list = static_cast<Try*>(expression)->catchEvents;
auto index = list.size();
list.push_back(catchEvent);
return index;
}
void BinaryenTrySetCatchBody(BinaryenExpressionRef expr,
BinaryenExpressionRef catchBodyExpr) {
void BinaryenTryInsertCatchEventAt(BinaryenExpressionRef expr,
BinaryenIndex index,
const char* catchEvent) {
auto* expression = (Expression*)expr;
assert(expression->is<Try>());
assert(catchBodyExpr);
static_cast<Try*>(expression)->catchBody = (Expression*)catchBodyExpr;
assert(catchEvent);
static_cast<Try*>(expression)->catchEvents.insertAt(index, catchEvent);
}
const char* BinaryenTryRemoveCatchEventAt(BinaryenExpressionRef expr,
BinaryenIndex index) {
auto* expression = (Expression*)expr;
assert(expression->is<Try>());
return static_cast<Try*>(expression)->catchEvents.removeAt(index).c_str();
}
BinaryenExpressionRef BinaryenTryGetCatchBodyAt(BinaryenExpressionRef expr,
BinaryenIndex index) {
auto* expression = (Expression*)expr;
assert(expression->is<Try>());
assert(index < static_cast<Try*>(expression)->catchBodies.size());
return static_cast<Try*>(expression)->catchBodies[index];
}
void BinaryenTrySetCatchBodyAt(BinaryenExpressionRef expr,
BinaryenIndex index,
BinaryenExpressionRef catchExpr) {
auto* expression = (Expression*)expr;
assert(expression->is<Try>());
assert(index < static_cast<Try*>(expression)->catchBodies.size());
assert(catchExpr);
static_cast<Try*>(expression)->catchBodies[index] = (Expression*)catchExpr;
}
BinaryenIndex BinaryenTryAppendCatchBody(BinaryenExpressionRef expr,
BinaryenExpressionRef catchExpr) {
auto* expression = (Expression*)expr;
assert(expression->is<Try>());
assert(catchExpr);
auto& list = static_cast<Try*>(expression)->catchBodies;
auto index = list.size();
list.push_back((Expression*)catchExpr);
return index;
}
void BinaryenTryInsertCatchBodyAt(BinaryenExpressionRef expr,
BinaryenIndex index,
BinaryenExpressionRef catchExpr) {
auto* expression = (Expression*)expr;
assert(expression->is<Try>());
assert(catchExpr);
static_cast<Try*>(expression)
->catchBodies.insertAt(index, (Expression*)catchExpr);
}
BinaryenExpressionRef BinaryenTryRemoveCatchBodyAt(BinaryenExpressionRef expr,
BinaryenIndex index) {
auto* expression = (Expression*)expr;
assert(expression->is<Try>());
return static_cast<Try*>(expression)->catchBodies.removeAt(index);
}
int BinaryenTryHasCatchAll(BinaryenExpressionRef expr) {
auto* expression = (Expression*)expr;
assert(expression->is<Try>());
return static_cast<Try*>(expression)->hasCatchAll();
}
// Throw
const char* BinaryenThrowGetEvent(BinaryenExpressionRef expr) {
Expand Down Expand Up @@ -2825,17 +2918,15 @@ BinaryenExpressionRef BinaryenThrowRemoveOperandAt(BinaryenExpressionRef expr,
return static_cast<Throw*>(expression)->operands.removeAt(index);
}
// Rethrow
BinaryenExpressionRef BinaryenRethrowGetExnref(BinaryenExpressionRef expr) {
BinaryenIndex BinaryenRethrowGetDepth(BinaryenExpressionRef expr) {
auto* expression = (Expression*)expr;
assert(expression->is<Rethrow>());
return static_cast<Rethrow*>(expression)->exnref;
return static_cast<Rethrow*>(expression)->depth;
}
void BinaryenRethrowSetExnref(BinaryenExpressionRef expr,
BinaryenExpressionRef exnrefExpr) {
void BinaryenRethrowSetDepth(BinaryenExpressionRef expr, BinaryenIndex depth) {
auto* expression = (Expression*)expr;
assert(expression->is<Rethrow>());
assert(exnrefExpr);
static_cast<Rethrow*>(expression)->exnref = (Expression*)exnrefExpr;
static_cast<Rethrow*>(expression)->depth = depth;
}
// BrOnExn
const char* BinaryenBrOnExnGetEvent(BinaryenExpressionRef expr) {
Expand Down
78 changes: 63 additions & 15 deletions src/binaryen-c.h
Original file line number Diff line number Diff line change
Expand Up @@ -796,16 +796,20 @@ BINARYEN_API BinaryenExpressionRef BinaryenRefFunc(BinaryenModuleRef module,
BINARYEN_API BinaryenExpressionRef BinaryenRefEq(BinaryenModuleRef module,
BinaryenExpressionRef left,
BinaryenExpressionRef right);
BINARYEN_API BinaryenExpressionRef BinaryenTry(BinaryenModuleRef module,
BinaryenExpressionRef body,
BinaryenExpressionRef catchBody);
BINARYEN_API BinaryenExpressionRef
BinaryenTry(BinaryenModuleRef module,
BinaryenExpressionRef body,
const char** catchEvents,
BinaryenIndex numCatchEvents,
BinaryenExpressionRef* catchBodies,
BinaryenIndex numCatchBodies);
BINARYEN_API BinaryenExpressionRef
BinaryenThrow(BinaryenModuleRef module,
const char* event,
BinaryenExpressionRef* operands,
BinaryenIndex numOperands);
BINARYEN_API BinaryenExpressionRef
BinaryenRethrow(BinaryenModuleRef module, BinaryenExpressionRef exnref);
BINARYEN_API BinaryenExpressionRef BinaryenRethrow(BinaryenModuleRef module,
BinaryenIndex depth);
BINARYEN_API BinaryenExpressionRef
BinaryenBrOnExn(BinaryenModuleRef module,
const char* name,
Expand Down Expand Up @@ -1714,12 +1718,57 @@ BinaryenTryGetBody(BinaryenExpressionRef expr);
// Sets the body expression of a `try` expression.
BINARYEN_API void BinaryenTrySetBody(BinaryenExpressionRef expr,
BinaryenExpressionRef bodyExpr);
// Gets the catch body expression of a `try` expression.
// Gets the number of catch blocks (= the number of catch events) of a `try`
// expression.
BINARYEN_API BinaryenIndex
BinaryenTryGetNumCatchEvents(BinaryenExpressionRef expr);
// Gets the number of catch/catch_all blocks of a `try` expression.
BINARYEN_API BinaryenIndex
BinaryenTryGetNumCatchBodies(BinaryenExpressionRef expr);
// Gets the catch event at the specified index of a `try` expression.
BINARYEN_API const char* BinaryenTryGetCatchEventAt(BinaryenExpressionRef expr,
BinaryenIndex index);
// Sets the catch event at the specified index of a `try` expression.
BINARYEN_API void BinaryenTrySetCatchEventAt(BinaryenExpressionRef expr,
BinaryenIndex index,
const char* catchEvent);
// Appends a catch event to a `try` expression, returning its insertion index.
BINARYEN_API BinaryenIndex
BinaryenTryAppendCatchEvent(BinaryenExpressionRef expr, const char* catchEvent);
// Inserts a catch event at the specified index of a `try` expression, moving
// existing catch events including the one previously at that index one index
// up.
BINARYEN_API void BinaryenTryInsertCatchEventAt(BinaryenExpressionRef expr,
BinaryenIndex index,
const char* catchEvent);
// Removes the catch event at the specified index of a `try` expression, moving
// all subsequent catch events one index down. Returns the event.
BINARYEN_API const char*
BinaryenTryRemoveCatchEventAt(BinaryenExpressionRef expr, BinaryenIndex index);
// Gets the catch body expression at the specified index of a `try` expression.
BINARYEN_API BinaryenExpressionRef
BinaryenTryGetCatchBodyAt(BinaryenExpressionRef expr, BinaryenIndex index);
// Sets the catch body expression at the specified index of a `try` expression.
BINARYEN_API void BinaryenTrySetCatchBodyAt(BinaryenExpressionRef expr,
BinaryenIndex index,
BinaryenExpressionRef catchExpr);
// Appends a catch expression to a `try` expression, returning its insertion
// index.
BINARYEN_API BinaryenIndex BinaryenTryAppendCatchBody(
BinaryenExpressionRef expr, BinaryenExpressionRef catchExpr);
// Inserts a catch expression at the specified index of a `try` expression,
// moving existing catch bodies including the one previously at that index one
// index up.
BINARYEN_API void BinaryenTryInsertCatchBodyAt(BinaryenExpressionRef expr,
BinaryenIndex index,
BinaryenExpressionRef catchExpr);
// Removes the catch expression at the specified index of a `try` expression,
// moving all subsequent catch bodies one index down. Returns the catch
// expression.
BINARYEN_API BinaryenExpressionRef
BinaryenTryGetCatchBody(BinaryenExpressionRef expr);
// Sets the catch body expression of a `try` expression.
BINARYEN_API void BinaryenTrySetCatchBody(BinaryenExpressionRef expr,
BinaryenExpressionRef catchBodyExpr);
BinaryenTryRemoveCatchBodyAt(BinaryenExpressionRef expr, BinaryenIndex index);
// Gets whether an `try` expression has a catch_all clause.
BINARYEN_API int BinaryenTryHasCatchAll(BinaryenExpressionRef expr);

aheejin marked this conversation as resolved.
Show resolved Hide resolved
// Throw

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

// Rethrow

// Gets the exception reference expression of a `rethrow` expression.
BINARYEN_API BinaryenExpressionRef
BinaryenRethrowGetExnref(BinaryenExpressionRef expr);
// Gets the depth of a `rethrow` expression.
BINARYEN_API BinaryenIndex BinaryenRethrowGetDepth(BinaryenExpressionRef expr);
// Sets the exception reference expression of a `rethrow` expression.
BINARYEN_API void BinaryenRethrowSetExnref(BinaryenExpressionRef expr,
BinaryenExpressionRef exnrefExpr);
BINARYEN_API void BinaryenRethrowSetDepth(BinaryenExpressionRef expr,
BinaryenIndex depth);

// BrOnExn

Expand Down
3 changes: 3 additions & 0 deletions src/cfg/cfg-traversal.h
Original file line number Diff line number Diff line change
Expand Up @@ -304,11 +304,14 @@ struct CFGWalker : public ControlFlowWalker<SubType, VisitorType> {
break;
}
case Expression::Id::TryId: {
// FIXME Update the implementation to match the new spec
/*
self->pushTask(SubType::doEndTry, currp);
self->pushTask(SubType::scan, &curr->cast<Try>()->catchBody);
self->pushTask(SubType::doStartCatch, currp);
self->pushTask(SubType::scan, &curr->cast<Try>()->body);
self->pushTask(SubType::doStartTry, currp);
*/
aheejin marked this conversation as resolved.
Show resolved Hide resolved
return; // don't do anything else
}
case Expression::Id::ThrowId:
Expand Down
5 changes: 5 additions & 0 deletions src/ir/ExpressionAnalyzer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ bool ExpressionAnalyzer::flexibleEqual(Expression* left,
}

#define DELEGATE_FIELD_INT_ARRAY(id, name) COMPARE_LIST(name)
#define DELEGATE_FIELD_NAME_VECTOR(id, name) COMPARE_LIST(name)

#define DELEGATE_FIELD_SCOPE_NAME_DEF(id, name) \
if (castLeft->name.is() != castRight->name.is()) { \
Expand Down Expand Up @@ -306,6 +307,10 @@ size_t ExpressionAnalyzer::hash(Expression* curr) {
#define DELEGATE_FIELD_SIGNATURE(id, name) HASH_FIELD(name)

#define DELEGATE_FIELD_NAME(id, name) visitNonScopeName(cast->name)
#define DELEGATE_FIELD_NAME_VECTOR(id, name) \
for (auto n : cast->name) { \
visitNonScopeName(n); \
}
aheejin marked this conversation as resolved.
Show resolved Hide resolved
#define DELEGATE_FIELD_TYPE(id, name) visitType(cast->name);
#define DELEGATE_FIELD_ADDRESS(id, name) visitAddress(cast->name);

Expand Down
1 change: 1 addition & 0 deletions src/ir/ExpressionManipulator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ flexibleCopy(Expression* original, Module& wasm, CustomCopier custom) {
COPY_FIELD_LIST(name)

#define DELEGATE_FIELD_SCOPE_NAME_USE_VECTOR(id, name) COPY_VECTOR(name)
#define DELEGATE_FIELD_NAME_VECTOR(id, name) COPY_VECTOR(name)

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

Expand Down
2 changes: 2 additions & 0 deletions src/ir/branch-utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ template<typename T> void operateOnScopeNameUses(Expression* expr, T func) {
#define DELEGATE_FIELD_INT(id, name)
#define DELEGATE_FIELD_LITERAL(id, name)
#define DELEGATE_FIELD_NAME(id, name)
#define DELEGATE_FIELD_NAME_VECTOR(id, name)
#define DELEGATE_FIELD_SCOPE_NAME_DEF(id, name)
#define DELEGATE_FIELD_SIGNATURE(id, name)
#define DELEGATE_FIELD_TYPE(id, name)
Expand Down Expand Up @@ -104,6 +105,7 @@ template<typename T> void operateOnScopeNameDefs(Expression* expr, T func) {
#define DELEGATE_FIELD_INT(id, name)
#define DELEGATE_FIELD_LITERAL(id, name)
#define DELEGATE_FIELD_NAME(id, name)
#define DELEGATE_FIELD_NAME_VECTOR(id, name)
#define DELEGATE_FIELD_SIGNATURE(id, name)
#define DELEGATE_FIELD_TYPE(id, name)
#define DELEGATE_FIELD_ADDRESS(id, name)
Expand Down
2 changes: 1 addition & 1 deletion src/ir/cost.h
Original file line number Diff line number Diff line change
Expand Up @@ -546,7 +546,7 @@ struct CostAnalyzer : public OverriddenVisitor<CostAnalyzer, Index> {
}
Index visitTry(Try* curr) {
// We assume no exception will be thrown in most cases
return visit(curr->body) + maybeVisit(curr->catchBody);
aheejin marked this conversation as resolved.
Show resolved Hide resolved
return visit(curr->body);
}
Index visitThrow(Throw* curr) {
Index ret = 100;
Expand Down
Loading