diff options
author | Heejin Ahn <aheejin@gmail.com> | 2019-08-13 00:29:26 +0900 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-08-13 00:29:26 +0900 |
commit | e2f49d8227f2b71e4dede5cf4074bb9f65e3d77f (patch) | |
tree | 30b132b02824839d1d7718ed32c6b90cc0828151 /test/example/c-api-kitchen-sink.c | |
parent | 69ad1e8a8d2e1d395e30230433742f4f5668563b (diff) | |
download | binaryen-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.c | 57 |
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() }; |