summaryrefslogtreecommitdiff
path: root/test/example/c-api-kitchen-sink.c
diff options
context:
space:
mode:
authorHeejin Ahn <aheejin@gmail.com>2019-08-13 00:29:26 +0900
committerGitHub <noreply@github.com>2019-08-13 00:29:26 +0900
commite2f49d8227f2b71e4dede5cf4074bb9f65e3d77f (patch)
tree30b132b02824839d1d7718ed32c6b90cc0828151 /test/example/c-api-kitchen-sink.c
parent69ad1e8a8d2e1d395e30230433742f4f5668563b (diff)
downloadbinaryen-e2f49d8227f2b71e4dede5cf4074bb9f65e3d77f.tar.gz
binaryen-e2f49d8227f2b71e4dede5cf4074bb9f65e3d77f.tar.bz2
binaryen-e2f49d8227f2b71e4dede5cf4074bb9f65e3d77f.zip
Add basic exception handling support (#2282)
This adds basic support for exception handling instructions, according to the spec: https://github.com/WebAssembly/exception-handling/blob/master/proposals/Exceptions.md This PR includes support for: - Binary reading/writing - Wast reading/writing - Stack IR - Validation - binaryen.js + C API - Few IR routines: branch-utils, type-updating, etc - Few passes: just enough to make `wasm-opt -O` pass - Tests This PR does not include support for many optimization passes, fuzzer, or interpreter. They will be follow-up PRs. Try-catch construct is modeled in Binaryen IR in a similar manner to that of if-else: each of try body and catch body will contain a block, which can be omitted if there is only a single instruction. This block will not be emitted in wast or binary, as in if-else. As in if-else, `class Try` contains two expressions each for try body and catch body, and `catch` is not modeled as an instruction. `exnref` value pushed by `catch` is get by `pop` instruction. `br_on_exn` is special: it returns different types of values when taken and not taken. We make `exnref`, the type `br_on_exn` pushes if not taken, as `br_on_exn`'s type.
Diffstat (limited to 'test/example/c-api-kitchen-sink.c')
-rw-r--r--test/example/c-api-kitchen-sink.c57
1 files changed, 50 insertions, 7 deletions
diff --git a/test/example/c-api-kitchen-sink.c b/test/example/c-api-kitchen-sink.c
index 8b2d3ae8d..661d04ce2 100644
--- a/test/example/c-api-kitchen-sink.c
+++ b/test/example/c-api-kitchen-sink.c
@@ -206,6 +206,51 @@ void test_core() {
temp13 = makeInt32(module, 10), temp14 = makeInt32(module, 11),
temp15 = makeInt32(module, 110), temp16 = makeInt64(module, 111);
+ // Events
+ BinaryenType eparams[1] = {BinaryenTypeInt32()};
+ BinaryenFunctionTypeRef vi =
+ BinaryenAddFunctionType(module, "vi", BinaryenTypeNone(), eparams, 1);
+ BinaryenAddEvent(module, "a-event", 0, vi);
+
+ // Exception handling
+
+ // (try
+ // (throw $a-event (i32.const 0))
+ // (catch
+ // ;; We don't support multi-value yet. Use locals instead.
+ // (local.set 0 (exnref.pop))
+ // (drop
+ // (block $try-block (result i32)
+ // (rethrow
+ // (br_on_exn $try-block $a-event (local.get 5))
+ // )
+ // )
+ // )
+ // )
+ // )
+ BinaryenExpressionRef tryBody = BinaryenThrow(
+ module, "a-event", (BinaryenExpressionRef[]){makeInt32(module, 0)}, 1);
+ BinaryenExpressionRef catchBody = BinaryenBlock(
+ module,
+ NULL,
+ (BinaryenExpressionRef[]){
+ BinaryenLocalSet(module, 5, BinaryenPop(module, BinaryenTypeExnref())),
+ BinaryenDrop(
+ module,
+ BinaryenBlock(module,
+ "try-block",
+ (BinaryenExpressionRef[]){BinaryenRethrow(
+ module,
+ BinaryenBrOnExn(
+ module,
+ "try-block",
+ "a-event",
+ BinaryenLocalGet(module, 5, BinaryenTypeExnref())))},
+ 1,
+ BinaryenTypeInt32()))},
+ 2,
+ BinaryenTypeNone());
+
BinaryenExpressionRef valueList[] = {
// Unary
makeUnary(module, BinaryenClzInt32(), 1),
@@ -472,6 +517,8 @@ void test_core() {
module, "kitchen()sinker", callOperands4, 4, BinaryenTypeInt32()),
BinaryenReturnCallIndirect(
module, makeInt32(module, 2449), callOperands4b, 4, "iiIfF"),
+ // Exception handling
+ BinaryenTry(module, tryBody, catchBody),
// TODO: Host
BinaryenNop(module),
@@ -488,19 +535,15 @@ void test_core() {
BinaryenExpressionRef body = BinaryenBlock(module, "the-body", bodyList, 2, -1);
// Create the function
- BinaryenType localTypes[] = { BinaryenTypeInt32() };
- BinaryenFunctionRef sinker = BinaryenAddFunction(module, "kitchen()sinker", iiIfF, localTypes, 1, body);
+ BinaryenType localTypes[] = {BinaryenTypeInt32(), BinaryenTypeExnref()};
+ BinaryenFunctionRef sinker =
+ BinaryenAddFunction(module, "kitchen()sinker", iiIfF, localTypes, 2, body);
// Globals
BinaryenAddGlobal(module, "a-global", BinaryenTypeInt32(), 0, makeInt32(module, 7));
BinaryenAddGlobal(module, "a-mutable-global", BinaryenTypeFloat32(), 1, makeFloat32(module, 7.5));
- // Events
- BinaryenType eparams[1] = { BinaryenTypeInt32() };
- BinaryenFunctionTypeRef vi = BinaryenAddFunctionType(module, "vi", BinaryenTypeNone(), eparams, 1);
- BinaryenAddEvent(module, "a-event", 0, vi);
-
// Imports
BinaryenType iparams[2] = { BinaryenTypeInt32(), BinaryenTypeFloat64() };