diff --git a/src/binaryen-c.cpp b/src/binaryen-c.cpp index 27da01616c1..e3780ce15c5 100644 --- a/src/binaryen-c.cpp +++ b/src/binaryen-c.cpp @@ -712,6 +712,10 @@ BinaryenOp BinaryenRefIsNull(void) { return RefIsNull; } BinaryenOp BinaryenRefIsFunc(void) { return RefIsFunc; } BinaryenOp BinaryenRefIsData(void) { return RefIsData; } BinaryenOp BinaryenRefIsI31(void) { return RefIsI31; } +BinaryenOp BinaryenRefAsNonNull(void) { return RefAsNonNull; }; +BinaryenOp BinaryenRefAsFunc(void) { return RefAsFunc; } +BinaryenOp BinaryenRefAsData(void) { return RefAsData; }; +BinaryenOp BinaryenRefAsI31(void) { return RefAsI31; }; BinaryenExpressionRef BinaryenBlock(BinaryenModuleRef module, const char* name, @@ -1198,6 +1202,13 @@ BinaryenExpressionRef BinaryenRefIs(BinaryenModuleRef module, Builder(*(Module*)module).makeRefIs(RefIsOp(op), (Expression*)value)); } +BinaryenExpressionRef BinaryenRefAs(BinaryenModuleRef module, + BinaryenOp op, + BinaryenExpressionRef value) { + return static_cast( + Builder(*(Module*)module).makeRefAs(RefAsOp(op), (Expression*)value)); +} + BinaryenExpressionRef BinaryenRefFunc(BinaryenModuleRef module, const char* func, BinaryenType type) { Type type_(type); @@ -2752,6 +2763,29 @@ void BinaryenRefIsSetValue(BinaryenExpressionRef expr, assert(valueExpr); static_cast(expression)->value = (Expression*)valueExpr; } +// RefAs +BinaryenOp BinaryenRefAsGetOp(BinaryenExpressionRef expr) { + auto* expression = (Expression*)expr; + assert(expression->is()); + return static_cast(expression)->op; +} +void BinaryenRefAsSetOp(BinaryenExpressionRef expr, BinaryenOp op) { + auto* expression = (Expression*)expr; + assert(expression->is()); + static_cast(expression)->op = RefAsOp(op); +} +BinaryenExpressionRef BinaryenRefAsGetValue(BinaryenExpressionRef expr) { + auto* expression = (Expression*)expr; + assert(expression->is()); + return static_cast(expression)->value; +} +void BinaryenRefAsSetValue(BinaryenExpressionRef expr, + BinaryenExpressionRef valueExpr) { + auto* expression = (Expression*)expr; + assert(expression->is()); + assert(valueExpr); + static_cast(expression)->value = (Expression*)valueExpr; +} // RefFunc const char* BinaryenRefFuncGetFunc(BinaryenExpressionRef expr) { auto* expression = (Expression*)expr; diff --git a/src/binaryen-c.h b/src/binaryen-c.h index 099b50c9c41..24018e4d863 100644 --- a/src/binaryen-c.h +++ b/src/binaryen-c.h @@ -563,6 +563,10 @@ BINARYEN_API BinaryenOp BinaryenRefIsNull(void); BINARYEN_API BinaryenOp BinaryenRefIsFunc(void); BINARYEN_API BinaryenOp BinaryenRefIsData(void); BINARYEN_API BinaryenOp BinaryenRefIsI31(void); +BINARYEN_API BinaryenOp BinaryenRefAsNonNull(void); +BINARYEN_API BinaryenOp BinaryenRefAsFunc(void); +BINARYEN_API BinaryenOp BinaryenRefAsData(void); +BINARYEN_API BinaryenOp BinaryenRefAsI31(void); BINARYEN_REF(Expression); @@ -797,6 +801,9 @@ BINARYEN_API BinaryenExpressionRef BinaryenRefNull(BinaryenModuleRef module, BINARYEN_API BinaryenExpressionRef BinaryenRefIs(BinaryenModuleRef module, BinaryenOp op, BinaryenExpressionRef value); +BINARYEN_API BinaryenExpressionRef BinaryenRefAs(BinaryenModuleRef module, + BinaryenOp op, + BinaryenExpressionRef value); BINARYEN_API BinaryenExpressionRef BinaryenRefFunc(BinaryenModuleRef module, const char* func, BinaryenType type); @@ -1702,6 +1709,19 @@ BinaryenRefIsGetValue(BinaryenExpressionRef expr); BINARYEN_API void BinaryenRefIsSetValue(BinaryenExpressionRef expr, BinaryenExpressionRef valueExpr); +// RefAs + +// Gets the operation performed by a `ref.as_*` expression. +BINARYEN_API BinaryenOp BinaryenRefAsGetOp(BinaryenExpressionRef expr); +// Sets the operation performed by a `ref.as_*` expression. +BINARYEN_API void BinaryenRefAsSetOp(BinaryenExpressionRef expr, BinaryenOp op); +// Gets the value expression tested by a `ref.as_*` expression. +BINARYEN_API BinaryenExpressionRef +BinaryenRefAsGetValue(BinaryenExpressionRef expr); +// Sets the value expression tested by a `ref.as_*` expression. +BINARYEN_API void BinaryenRefAsSetValue(BinaryenExpressionRef expr, + BinaryenExpressionRef valueExpr); + // RefFunc // Gets the name of the function being wrapped by a `ref.func` expression. diff --git a/src/js/binaryen.js-post.js b/src/js/binaryen.js-post.js index 4416e4d1043..785c5610641 100644 --- a/src/js/binaryen.js-post.js +++ b/src/js/binaryen.js-post.js @@ -491,6 +491,10 @@ function initializeConstants() { 'RefIsFunc', 'RefIsData', 'RefIsI31', + 'RefAsNonNull', + 'RefAsFunc', + 'RefAsData', + 'RefAsI31', ].forEach(name => { Module['Operations'][name] = Module[name] = Module['_Binaryen' + name](); }); @@ -2118,6 +2122,18 @@ function wrapModule(module, self = {}) { 'is_i31'(value) { return Module['_BinaryenRefIs'](module, Module['RefIsI31'], value); }, + 'as_non_null'(value) { + return Module['_BinaryenRefAs'](module, Module['RefAsNonNull'], value); + }, + 'as_func'(value) { + return Module['_BinaryenRefAs'](module, Module['RefAsFunc'], value); + }, + 'as_data'(value) { + return Module['_BinaryenRefAs'](module, Module['RefAsData'], value); + }, + 'as_i31'(value) { + return Module['_BinaryenRefAs'](module, Module['RefAsI31'], value); + }, 'func'(func, type) { return preserveStack(() => Module['_BinaryenRefFunc'](module, strToStack(func), type)); }, @@ -2879,8 +2895,16 @@ Module['getExpressionInfo'] = function(expr) { return { 'id': id, 'type': type, + 'op': Module['_BinaryenRefIsGetOp'](expr), 'value': Module['_BinaryenRefIsGetValue'](expr) }; + case Module['RefAsId']: + return { + 'id': id, + 'type': type, + 'op': Module['_BinaryenRefAsGetOp'](expr), + 'value': Module['_BinaryenRefAsGetValue'](expr) + }; case Module['RefFuncId']: return { 'id': id, @@ -4157,6 +4181,21 @@ Module['RefIs'] = makeExpressionWrapper({ } }); +Module['RefAs'] = makeExpressionWrapper({ + 'getOp'(expr) { + return Module['_BinaryenRefAsGetOp'](expr); + }, + 'setOp'(expr, op) { + Module['_BinaryenRefAsSetOp'](expr, op); + }, + 'getValue'(expr) { + return Module['_BinaryenRefAsGetValue'](expr); + }, + 'setValue'(expr, valueExpr) { + Module['_BinaryenRefAsSetValue'](expr, valueExpr); + } +}); + Module['RefFunc'] = makeExpressionWrapper({ 'getFunc'(expr) { return UTF8ToString(Module['_BinaryenRefFuncGetFunc'](expr)); diff --git a/test/binaryen.js/expressions.js b/test/binaryen.js/expressions.js index 69081f0e6ee..d6256cec167 100644 --- a/test/binaryen.js/expressions.js +++ b/test/binaryen.js/expressions.js @@ -1403,6 +1403,54 @@ console.log("# RefIs"); module.dispose(); })(); +console.log("# RefAs"); +(function testRefAs() { + const module = new binaryen.Module(); + + var op = binaryen.Operations.RefAsNonNull; + var value = module.local.get(1, binaryen.anyref); + const theRefAs = binaryen.RefAs(module.ref.as_non_null(value)); + assert(theRefAs instanceof binaryen.RefAs); + assert(theRefAs instanceof binaryen.Expression); + assert(theRefAs.op === op); + assert(theRefAs.value === value); + assert(theRefAs.type !== binaryen.i32); // TODO: === (ref any) + + theRefAs.op = op = binaryen.Operations.RefAsFunc; + assert(theRefAs.op === op); + theRefAs.op = op = binaryen.Operations.RefAsNull; + theRefAs.value = value = module.local.get(2, binaryen.anyref); + assert(theRefAs.value === value); + theRefAs.type = binaryen.f64; + theRefAs.finalize(); + assert(theRefAs.type !== binaryen.f64); // TODO: === (ref any) + + console.log(theRefAs.toText()); + assert( + theRefAs.toText() + == + "(ref.as_non_null\n (local.get $2)\n)\n" + ); + + assert( + binaryen.RefAs(module.ref.as_func(value)).toText() + == + "(ref.as_func\n (local.get $2)\n)\n" + ); + assert( + binaryen.RefAs(module.ref.as_data(value)).toText() + == + "(ref.as_data\n (local.get $2)\n)\n" + ); + assert( + binaryen.RefAs(module.ref.as_i31(value)).toText() + == + "(ref.as_i31\n (local.get $2)\n)\n" + ); + + module.dispose(); +})(); + console.log("# RefFunc"); (function testRefFunc() { const module = new binaryen.Module(); diff --git a/test/binaryen.js/expressions.js.txt b/test/binaryen.js/expressions.js.txt index 1efbd9e1397..0467e9332e9 100644 --- a/test/binaryen.js/expressions.js.txt +++ b/test/binaryen.js/expressions.js.txt @@ -207,6 +207,11 @@ (local.get $2) ) +# RefAs +(ref.as_non_null + (local.get $2) +) + # RefFunc (ref.func $b) diff --git a/test/example/c-api-kitchen-sink.c b/test/example/c-api-kitchen-sink.c index cbf795e5c05..4faf7aa5e51 100644 --- a/test/example/c-api-kitchen-sink.c +++ b/test/example/c-api-kitchen-sink.c @@ -731,6 +731,13 @@ void test_core() { BinaryenRefEq(module, BinaryenRefNull(module, BinaryenTypeEqref()), BinaryenRefNull(module, BinaryenTypeEqref())), + BinaryenRefIs(module, BinaryenRefIsFunc(), BinaryenRefNull(module, BinaryenTypeAnyref())), + BinaryenRefIs(module, BinaryenRefIsData(), BinaryenRefNull(module, BinaryenTypeAnyref())), + BinaryenRefIs(module, BinaryenRefIsI31(), BinaryenRefNull(module, BinaryenTypeAnyref())), + BinaryenRefAs(module, BinaryenRefAsNonNull(), BinaryenRefNull(module, BinaryenTypeAnyref())), + BinaryenRefAs(module, BinaryenRefAsFunc(), BinaryenRefNull(module, BinaryenTypeAnyref())), + BinaryenRefAs(module, BinaryenRefAsData(), BinaryenRefNull(module, BinaryenTypeAnyref())), + BinaryenRefAs(module, BinaryenRefAsI31(), BinaryenRefNull(module, BinaryenTypeAnyref())), // Exception handling BinaryenTry(module, NULL, tryBody, catchEvents, 1, catchBodies, 2, NULL), // (try $try_outer diff --git a/test/example/c-api-kitchen-sink.txt b/test/example/c-api-kitchen-sink.txt index 66b9ab50792..40b7da26e7d 100644 --- a/test/example/c-api-kitchen-sink.txt +++ b/test/example/c-api-kitchen-sink.txt @@ -1761,6 +1761,41 @@ BinaryenFeatureAll: 8191 (ref.null eq) ) ) + (drop + (ref.is_func + (ref.null any) + ) + ) + (drop + (ref.is_data + (ref.null any) + ) + ) + (drop + (ref.is_i31 + (ref.null any) + ) + ) + (drop + (ref.as_non_null + (ref.null any) + ) + ) + (drop + (ref.as_func + (ref.null any) + ) + ) + (drop + (ref.as_data + (ref.null any) + ) + ) + (drop + (ref.as_i31 + (ref.null any) + ) + ) (try (do (throw $a-event