Skip to content

Commit c12cc3f

Browse files
authored
[EH] Update C and binaryen.js API for delegate (#3565)
This updates C and binaryen.js API to match the new `Try` structure to support `delegate`, added in #3561. Now `try` can take a name (which can be null) like a block, and also has an additional `delegateTarget` field argument which should only be used for try-delegate and otherwise null. This also adds several more variant of `makeTry` methods in wasm-builder. Some are for making try-delegate and some are for try-catch(_all).
1 parent ac3188f commit c12cc3f

11 files changed

+250
-33
lines changed

src/binaryen-c.cpp

Lines changed: 43 additions & 9 deletions
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

Lines changed: 18 additions & 2 deletions
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

Lines changed: 23 additions & 3 deletions
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']),
2903-
'hasCatchAll': Module['_BinaryenTryHasCatchAll'](expr)
2904+
'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

Lines changed: 49 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -637,26 +637,66 @@ class Builder {
637637
ret->finalize();
638638
return ret;
639639
}
640-
Try* makeTry(Expression* body,
640+
641+
private:
642+
Try* makeTry(Name name,
643+
Expression* body,
641644
const std::vector<Name>& catchEvents,
642-
const std::vector<Expression*>& catchBodies) {
645+
const std::vector<Expression*>& catchBodies,
646+
Name delegateTarget,
647+
Type type,
648+
bool hasType) { // differentiate whether a type was passed in
643649
auto* ret = wasm.allocator.alloc<Try>();
650+
ret->name = name;
644651
ret->body = body;
645652
ret->catchEvents.set(catchEvents);
646653
ret->catchBodies.set(catchBodies);
647-
ret->finalize();
654+
if (hasType) {
655+
ret->finalize(type);
656+
} else {
657+
ret->finalize();
658+
}
648659
return ret;
649660
}
661+
662+
public:
663+
Try* makeTry(Expression* body,
664+
const std::vector<Name>& catchEvents,
665+
const std::vector<Expression*>& catchBodies) {
666+
return makeTry(
667+
Name(), body, catchEvents, catchBodies, Name(), Type::none, false);
668+
}
650669
Try* makeTry(Expression* body,
651670
const std::vector<Name>& catchEvents,
652671
const std::vector<Expression*>& catchBodies,
653672
Type type) {
654-
auto* ret = wasm.allocator.alloc<Try>();
655-
ret->body = body;
656-
ret->catchEvents.set(catchEvents);
657-
ret->catchBodies.set(catchBodies);
658-
ret->finalize(type);
659-
return ret;
673+
return makeTry(Name(), body, catchEvents, catchBodies, Name(), type, true);
674+
}
675+
Try* makeTry(Name name,
676+
Expression* body,
677+
const std::vector<Name>& catchEvents,
678+
const std::vector<Expression*>& catchBodies) {
679+
return makeTry(
680+
name, body, catchEvents, catchBodies, Name(), Type::none, false);
681+
}
682+
Try* makeTry(Name name,
683+
Expression* body,
684+
const std::vector<Name>& catchEvents,
685+
const std::vector<Expression*>& catchBodies,
686+
Type type) {
687+
return makeTry(name, body, catchEvents, catchBodies, Name(), type, true);
688+
}
689+
Try* makeTry(Expression* body, Name delegateTarget) {
690+
return makeTry(Name(), body, {}, {}, delegateTarget, Type::none, false);
691+
}
692+
Try* makeTry(Expression* body, Name delegateTarget, Type type) {
693+
return makeTry(Name(), body, {}, {}, delegateTarget, type, true);
694+
}
695+
Try* makeTry(Name name, Expression* body, Name delegateTarget) {
696+
return makeTry(name, body, {}, {}, delegateTarget, Type::none, false);
697+
}
698+
Try* makeTry(Name name, Expression* body, Name delegateTarget, Type type) {
699+
return makeTry(name, body, {}, {}, delegateTarget, type, true);
660700
}
661701
Throw* makeThrow(Event* event, const std::vector<Expression*>& args) {
662702
return makeThrow(event->name, args);

test/binaryen.js/exception-handling.js

Lines changed: 35 additions & 5 deletions
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,42 @@ 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+
[module.nop()],
73+
''
74+
);
75+
76+
var body = module.block('', [try_catch, try_delegate])
77+
var func = module.addFunction("test", binaryen.none, binaryen.none, [], body);
4978

5079
console.log(module.emitText());
5180
assert(module.validate());
5281

5382
console.log("getExpressionInfo(throw) = " + stringify(throw_));
5483
console.log("getExpressionInfo(rethrow) = " + stringify(rethrow));
55-
console.log("getExpressionInfo(try) = " + stringify(try_));
84+
console.log("getExpressionInfo(try_catch) = " + stringify(try_catch));
85+
console.log("getExpressionInfo(try_delegate) = " + stringify(try_delegate));

test/binaryen.js/exception-handling.js.txt

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,25 @@
1616
(rethrow 0)
1717
)
1818
)
19+
(try $try_outer
20+
(do
21+
(try
22+
(do
23+
(throw $e
24+
(i32.const 0)
25+
)
26+
)
27+
(delegate $try_outer)
28+
)
29+
)
30+
(catch_all
31+
(nop)
32+
)
33+
)
1934
)
2035
)
2136

2237
getExpressionInfo(throw) = {"id":48,"type":1,"event":"e"}
2338
getExpressionInfo(rethrow) = {"id":49,"type":1,"depth":0}
24-
getExpressionInfo(try) = {"id":47,"type":1,"hasCatchAll":0}
39+
getExpressionInfo(try_catch) = {"id":47,"type":1,"name":"","hasCatchAll":0,"delegateTarget":"","isDelegate":0}
40+
getExpressionInfo(try_delegate) = {"id":47,"type":0,"name":"try_outer","hasCatchAll":1,"delegateTarget":"","isDelegate":0}

test/binaryen.js/expressions.js

Lines changed: 9 additions & 1 deletion
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/binaryen.js/expressions.js.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,13 @@
283283
)
284284
)
285285

286+
(try (result i32)
287+
(do
288+
(i32.const 4)
289+
)
290+
(delegate $try_outer)
291+
)
292+
286293
# Throw
287294
(throw $bar
288295
(i32.const 6)

0 commit comments

Comments
 (0)