Skip to content

Commit 5a41bce

Browse files
committed
[EH] Update C and binaryen.js API for delegate
This updates C and binaryen.js API to match the new `Try` structure to support `delegate`, added in WebAssembly#3561.
1 parent f826df6 commit 5a41bce

8 files changed

+227
-21
lines changed

src/binaryen-c.cpp

+43-9
Original file line numberDiff line numberDiff line change
@@ -1210,21 +1210,29 @@ BinaryenExpressionRef BinaryenRefEq(BinaryenModuleRef module,
12101210
}
12111211

12121212
BinaryenExpressionRef BinaryenTry(BinaryenModuleRef module,
1213+
const char* name,
12131214
BinaryenExpressionRef body,
1214-
const char** catchEvents_,
1215+
const char** catchEvents,
12151216
BinaryenIndex numCatchEvents,
1216-
BinaryenExpressionRef* catchBodies_,
1217-
BinaryenIndex numCatchBodies) {
1218-
std::vector<Name> catchEvents;
1219-
std::vector<Expression*> catchBodies;
1217+
BinaryenExpressionRef* catchBodies,
1218+
BinaryenIndex numCatchBodies,
1219+
const char* delegateTarget) {
1220+
auto* ret = ((Module*)module)->allocator.alloc<Try>();
1221+
if (name) {
1222+
ret->name = name;
1223+
}
1224+
ret->body = (Expression*)body;
12201225
for (BinaryenIndex i = 0; i < numCatchEvents; i++) {
1221-
catchEvents.push_back(catchEvents_[i]);
1226+
ret->catchEvents.push_back(catchEvents[i]);
12221227
}
12231228
for (BinaryenIndex i = 0; i < numCatchBodies; i++) {
1224-
catchBodies.push_back((Expression*)catchBodies_[i]);
1229+
ret->catchBodies.push_back((Expression*)catchBodies[i]);
12251230
}
1226-
return static_cast<Expression*>(
1227-
Builder(*(Module*)module).makeTry(body, catchEvents, catchBodies));
1231+
if (delegateTarget) {
1232+
ret->delegateTarget = delegateTarget;
1233+
}
1234+
ret->finalize();
1235+
return static_cast<Expression*>(ret);
12281236
}
12291237

12301238
BinaryenExpressionRef BinaryenThrow(BinaryenModuleRef module,
@@ -2765,6 +2773,16 @@ void BinaryenRefEqSetRight(BinaryenExpressionRef expr,
27652773
static_cast<RefEq*>(expression)->right = (Expression*)right;
27662774
}
27672775
// Try
2776+
const char* BinaryenTryGetName(BinaryenExpressionRef expr) {
2777+
auto* expression = (Expression*)expr;
2778+
assert(expression->is<Try>());
2779+
return static_cast<Try*>(expression)->name.c_str();
2780+
}
2781+
void BinaryenTrySetName(BinaryenExpressionRef expr, const char* name) {
2782+
auto* expression = (Expression*)expr;
2783+
assert(expression->is<Try>());
2784+
static_cast<Try*>(expression)->name = name;
2785+
}
27682786
BinaryenExpressionRef BinaryenTryGetBody(BinaryenExpressionRef expr) {
27692787
auto* expression = (Expression*)expr;
27702788
assert(expression->is<Try>());
@@ -2873,6 +2891,22 @@ int BinaryenTryHasCatchAll(BinaryenExpressionRef expr) {
28732891
assert(expression->is<Try>());
28742892
return static_cast<Try*>(expression)->hasCatchAll();
28752893
}
2894+
const char* BinaryenTryGetDelegateTarget(BinaryenExpressionRef expr) {
2895+
auto* expression = (Expression*)expr;
2896+
assert(expression->is<Try>());
2897+
return static_cast<Try*>(expression)->delegateTarget.c_str();
2898+
}
2899+
void BinaryenTrySetDelegateTarget(BinaryenExpressionRef expr,
2900+
const char* delegateTarget) {
2901+
auto* expression = (Expression*)expr;
2902+
assert(expression->is<Try>());
2903+
static_cast<Try*>(expression)->delegateTarget = delegateTarget;
2904+
}
2905+
int BinaryenTryIsDelegate(BinaryenExpressionRef expr) {
2906+
auto* expression = (Expression*)expr;
2907+
assert(expression->is<Try>());
2908+
return static_cast<Try*>(expression)->isDelegate();
2909+
}
28762910
// Throw
28772911
const char* BinaryenThrowGetEvent(BinaryenExpressionRef expr) {
28782912
auto* expression = (Expression*)expr;

src/binaryen-c.h

+18-2
Original file line numberDiff line numberDiff line change
@@ -802,13 +802,16 @@ BINARYEN_API BinaryenExpressionRef BinaryenRefFunc(BinaryenModuleRef module,
802802
BINARYEN_API BinaryenExpressionRef BinaryenRefEq(BinaryenModuleRef module,
803803
BinaryenExpressionRef left,
804804
BinaryenExpressionRef right);
805+
// Try: name can be NULL. delegateTarget should be NULL in try-catch.
805806
BINARYEN_API BinaryenExpressionRef
806807
BinaryenTry(BinaryenModuleRef module,
808+
const char* name,
807809
BinaryenExpressionRef body,
808810
const char** catchEvents,
809811
BinaryenIndex numCatchEvents,
810812
BinaryenExpressionRef* catchBodies,
811-
BinaryenIndex numCatchBodies);
813+
BinaryenIndex numCatchBodies,
814+
const char* delegateTarget);
812815
BINARYEN_API BinaryenExpressionRef
813816
BinaryenThrow(BinaryenModuleRef module,
814817
const char* event,
@@ -1719,6 +1722,11 @@ BINARYEN_API void BinaryenRefEqSetRight(BinaryenExpressionRef expr,
17191722

17201723
// Try
17211724

1725+
// Gets the name (label) of a `try` expression.
1726+
BINARYEN_API const char* BinaryenTryGetName(BinaryenExpressionRef expr);
1727+
// Sets the name (label) of a `try` expression.
1728+
BINARYEN_API void BinaryenTrySetName(BinaryenExpressionRef expr,
1729+
const char* name);
17221730
// Gets the body expression of a `try` expression.
17231731
BINARYEN_API BinaryenExpressionRef
17241732
BinaryenTryGetBody(BinaryenExpressionRef expr);
@@ -1774,8 +1782,16 @@ BINARYEN_API void BinaryenTryInsertCatchBodyAt(BinaryenExpressionRef expr,
17741782
// expression.
17751783
BINARYEN_API BinaryenExpressionRef
17761784
BinaryenTryRemoveCatchBodyAt(BinaryenExpressionRef expr, BinaryenIndex index);
1777-
// Gets whether an `try` expression has a catch_all clause.
1785+
// Gets whether a `try` expression has a catch_all clause.
17781786
BINARYEN_API int BinaryenTryHasCatchAll(BinaryenExpressionRef expr);
1787+
// Gets the target label of a `delegate`.
1788+
BINARYEN_API const char*
1789+
BinaryenTryGetDelegateTarget(BinaryenExpressionRef expr);
1790+
// Sets the target label of a `delegate`.
1791+
BINARYEN_API void BinaryenTrySetDelegateTarget(BinaryenExpressionRef expr,
1792+
const char* delegateTarget);
1793+
// Gets whether a `try` expression is a try-delegate.
1794+
BINARYEN_API int BinaryenTryIsDelegate(BinaryenExpressionRef expr);
17791795

17801796
// Throw
17811797

src/js/binaryen.js-post.js

+22-2
Original file line numberDiff line numberDiff line change
@@ -2147,9 +2147,9 @@ function wrapModule(module, self = {}) {
21472147
}
21482148
};
21492149

2150-
self['try'] = function(body, catchEvents, catchBodies) {
2150+
self['try'] = function(name, body, catchEvents, catchBodies, delegateTarget) {
21512151
return preserveStack(() =>
2152-
Module['_BinaryenTry'](module, body, i32sToStack(catchEvents.map(strToStack)), catchEvents.length, i32sToStack(catchBodies), catchBodies.length));
2152+
Module['_BinaryenTry'](module, name ? strToStack(name) : 0, body, i32sToStack(catchEvents.map(strToStack)), catchEvents.length, i32sToStack(catchBodies), catchBodies.length, delegateTarget ? strToStack(delegateTarget) : 0));
21532153
};
21542154
self['throw'] = function(event_, operands) {
21552155
return preserveStack(() => Module['_BinaryenThrow'](module, strToStack(event_), i32sToStack(operands), operands.length));
@@ -2897,10 +2897,13 @@ Module['getExpressionInfo'] = function(expr) {
28972897
return {
28982898
'id': id,
28992899
'type': type,
2900+
'name': UTF8ToString(Module['_BinaryenTryGetName'](expr)),
29002901
'body': Module['_BinaryenTryGetBody'](expr),
29012902
'catchEvents': getAllNested(expr, Module['_BinaryenTryGetNumCatchEvents'], Module['_BinaryenTryGetCatchEventAt']),
29022903
'catchBodies': getAllNested(expr, Module['_BinaryenTryGetNumCatchBodies'], Module['_BinaryenTryGetCatchBodyAt']),
29032904
'hasCatchAll': Module['_BinaryenTryHasCatchAll'](expr)
2905+
'delegateTarget': UTF8ToString(Module['_BinaryenTryGetDelegateTarget'](expr)),
2906+
'isDelegate': Module['_BinaryenTryIsDelegate'](expr)
29042907
};
29052908
case Module['ThrowId']:
29062909
return {
@@ -4172,6 +4175,13 @@ Module['RefEq'] = makeExpressionWrapper({
41724175
});
41734176

41744177
Module['Try'] = makeExpressionWrapper({
4178+
'getName'(expr) {
4179+
const name = Module['_BinaryenTryGetName'](expr);
4180+
return name ? UTF8ToString(name) : null;
4181+
},
4182+
'setName'(expr, name) {
4183+
preserveStack(() => { Module['_BinaryenTrySetName'](expr, strToStack(name)) });
4184+
},
41754185
'getBody'(expr) {
41764186
return Module['_BinaryenTryGetBody'](expr);
41774187
},
@@ -4231,6 +4241,16 @@ Module['Try'] = makeExpressionWrapper({
42314241
'hasCatchAll'(expr) {
42324242
return Boolean(Module['_BinaryenTryHasCatchAll'](expr));
42334243
},
4244+
'getDelegateTarget'(expr) {
4245+
const name = Module['_BinaryenTryGetDelegateTarget'](expr);
4246+
return name ? UTF8ToString(name) : null;
4247+
},
4248+
'setDelegateTarget'(expr, name) {
4249+
preserveStack(() => { Module['_BinaryenTrySetDelegateTarget'](expr, strToStack(name)) });
4250+
},
4251+
'isDelegate'(expr) {
4252+
return Boolean(Module['_BinaryenTryIsDelegate'](expr));
4253+
}
42344254
});
42354255

42364256
Module['Throw'] = makeExpressionWrapper({

src/wasm-builder.h

+55
Original file line numberDiff line numberDiff line change
@@ -647,6 +647,18 @@ class Builder {
647647
ret->finalize();
648648
return ret;
649649
}
650+
Try* makeTry(Name name,
651+
Expression* body,
652+
const std::vector<Name>& catchEvents,
653+
const std::vector<Expression*>& catchBodies) {
654+
auto* ret = wasm.allocator.alloc<Try>();
655+
ret->name = name;
656+
ret->body = body;
657+
ret->catchEvents.set(catchEvents);
658+
ret->catchBodies.set(catchBodies);
659+
ret->finalize();
660+
return ret;
661+
}
650662
Try* makeTry(Expression* body,
651663
const std::vector<Name>& catchEvents,
652664
const std::vector<Expression*>& catchBodies,
@@ -658,6 +670,49 @@ class Builder {
658670
ret->finalize(type);
659671
return ret;
660672
}
673+
Try* makeTry(Name name,
674+
Expression* body,
675+
const std::vector<Name>& catchEvents,
676+
const std::vector<Expression*>& catchBodies,
677+
Type type) {
678+
auto* ret = wasm.allocator.alloc<Try>();
679+
ret->name = name;
680+
ret->body = body;
681+
ret->catchEvents.set(catchEvents);
682+
ret->catchBodies.set(catchBodies);
683+
ret->finalize(type);
684+
return ret;
685+
}
686+
Try* makeTry(Expression* body, Name delegateTarget) {
687+
auto* ret = wasm.allocator.alloc<Try>();
688+
ret->body = body;
689+
ret->delegateTarget = delegateTarget;
690+
ret->finalize();
691+
return ret;
692+
}
693+
Try* makeTry(Name name, Expression* body, Name delegateTarget) {
694+
auto* ret = wasm.allocator.alloc<Try>();
695+
ret->name = name;
696+
ret->body = body;
697+
ret->delegateTarget = delegateTarget;
698+
ret->finalize();
699+
return ret;
700+
}
701+
Try* makeTry(Expression* body, Name delegateTarget, Type type) {
702+
auto* ret = wasm.allocator.alloc<Try>();
703+
ret->body = body;
704+
ret->delegateTarget = delegateTarget;
705+
ret->finalize(type);
706+
return ret;
707+
}
708+
Try* makeTry(Name name, Expression* body, Name delegateTarget, Type type) {
709+
auto* ret = wasm.allocator.alloc<Try>();
710+
ret->name = name;
711+
ret->body = body;
712+
ret->delegateTarget = delegateTarget;
713+
ret->finalize(type);
714+
return ret;
715+
}
661716
Throw* makeThrow(Event* event, const std::vector<Expression*>& args) {
662717
return makeThrow(event->name, args);
663718
}

test/binaryen.js/exception-handling.js

+34-5
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ function cleanInfo(info) {
33
for (var x in info) {
44
// Filter out address pointers and only print meaningful info
55
if (x == 'id' || x == 'type' || x == 'name' || x == 'event' ||
6-
x == 'depth' || x == 'hasCatchAll') {
6+
x == 'depth' || x == 'hasCatchAll' || x == 'delegateTarget' ||
7+
x == 'isDelegate') {
78
ret[x] = info[x];
89
}
910
}
@@ -31,7 +32,8 @@ var event_ = module.addEvent("e", 0, binaryen.i32, binaryen.none);
3132
// )
3233
var throw_ = module.throw("e", [module.i32.const(0)]);
3334
var rethrow = module.rethrow(0);
34-
var try_ = module.try(
35+
var try_catch = module.try(
36+
'',
3537
throw_,
3638
["e"],
3739
[
@@ -42,14 +44,41 @@ var try_ = module.try(
4244
],
4345
binaryen.none
4446
)
45-
]
47+
],
48+
''
4649
);
4750

48-
var func = module.addFunction("test", binaryen.none, binaryen.none, [], try_);
51+
// (try $try_outer
52+
// (do
53+
// (try
54+
// (do
55+
// (throw $a-event (i32.const 0))
56+
// )
57+
// (delegate $try_outer)
58+
// )
59+
// )
60+
// (catch_all)
61+
// )
62+
var try_delegate = module.try(
63+
'try_outer',
64+
module.try(
65+
'',
66+
throw_,
67+
[],
68+
[],
69+
'try_outer'
70+
),
71+
[],
72+
[],
73+
''
74+
);
75+
76+
var func = module.addFunction("test", binaryen.none, binaryen.none, [], [try_catch, try_delegate]);
4977

5078
console.log(module.emitText());
5179
assert(module.validate());
5280

5381
console.log("getExpressionInfo(throw) = " + stringify(throw_));
5482
console.log("getExpressionInfo(rethrow) = " + stringify(rethrow));
55-
console.log("getExpressionInfo(try) = " + stringify(try_));
83+
console.log("getExpressionInfo(try_catch) = " + stringify(try_catch));
84+
console.log("getExpressionInfo(try_delegate) = " + stringify(try_delegate));

test/binaryen.js/expressions.js

+9-1
Original file line numberDiff line numberDiff line change
@@ -1469,7 +1469,7 @@ console.log("# Try");
14691469
module.i32.const(2),
14701470
module.i32.const(3)
14711471
];
1472-
const theTry = binaryen.Try(module.try(body, ["event1"], catchBodies));
1472+
const theTry = binaryen.Try(module.try('', body, ["event1"], catchBodies, ''));
14731473
assert(theTry instanceof binaryen.Try);
14741474
assert(theTry instanceof binaryen.Expression);
14751475
assert(theTry.body === body);
@@ -1523,6 +1523,14 @@ console.log("# Try");
15231523
assert(theTry.type === binaryen.i32);
15241524

15251525
console.log(theTry.toText());
1526+
1527+
const tryDelegate = binaryen.Try(module.try('', body, [], [], "try_blah"));
1528+
assert(tryDelegate.isDelegate() == 1);
1529+
assert(tryDelegate.getDelegateTarget() == "try_blah");
1530+
tryDelegate.setDelegateTarget("try_outer");
1531+
assert(tryDelegate.getDelegateTarget() == "try_outer");
1532+
console.log(tryDelegate.toText());
1533+
15261534
module.dispose();
15271535
})();
15281536

test/example/c-api-kitchen-sink.c

+31-2
Original file line numberDiff line numberDiff line change
@@ -336,8 +336,11 @@ void test_core() {
336336
BinaryenExpressionRef catchBody =
337337
BinaryenDrop(module, BinaryenPop(module, BinaryenTypeInt32()));
338338
BinaryenExpressionRef catchAllBody = BinaryenNop(module);
339-
BinaryenExpressionRef catchBodies[] = {catchBody, catchAllBody};
340339
const char* catchEvents[] = {"a-event"};
340+
BinaryenExpressionRef catchBodies[] = {catchBody, catchAllBody};
341+
const char* emptyCatchEvents[] = {};
342+
BinaryenExpressionRef emptyCatchBodies[] = {};
343+
BinaryenExpressionRef nopCatchBody[] = {BinaryenNop(module)};
341344

342345
BinaryenType i32 = BinaryenTypeInt32();
343346
BinaryenType i64 = BinaryenTypeInt64();
@@ -727,7 +730,33 @@ void test_core() {
727730
BinaryenRefNull(module, BinaryenTypeEqref()),
728731
BinaryenRefNull(module, BinaryenTypeEqref())),
729732
// Exception handling
730-
BinaryenTry(module, tryBody, catchEvents, 1, catchBodies, 2),
733+
BinaryenTry(module, NULL, tryBody, catchEvents, 1, catchBodies, 2, NULL),
734+
// (try $try_outer
735+
// (do
736+
// (try
737+
// (do
738+
// (throw $a-event (i32.const 0))
739+
// )
740+
// (delegate $try_outer)
741+
// )
742+
// )
743+
// (catch_all)
744+
// )
745+
BinaryenTry(module,
746+
"try_outer",
747+
BinaryenTry(module,
748+
NULL,
749+
tryBody,
750+
emptyCatchEvents,
751+
0,
752+
emptyCatchBodies,
753+
0,
754+
"try_outer"),
755+
emptyCatchEvents,
756+
0,
757+
nopCatchBody,
758+
1,
759+
NULL),
731760
// Atomics
732761
BinaryenAtomicStore(
733762
module,

0 commit comments

Comments
 (0)