diff options
-rw-r--r-- | src/binaryen-c.cpp | 6 | ||||
-rw-r--r-- | src/binaryen-c.h | 13 | ||||
-rw-r--r-- | test/example/c-api-kitchen-sink.c | 13 | ||||
-rw-r--r-- | test/example/c-api-kitchen-sink.txt | 93 |
4 files changed, 121 insertions, 4 deletions
diff --git a/src/binaryen-c.cpp b/src/binaryen-c.cpp index 39a6d0149..abc89c88e 100644 --- a/src/binaryen-c.cpp +++ b/src/binaryen-c.cpp @@ -383,7 +383,7 @@ void BinaryenExpressionPrint(BinaryenExpressionRef expr) { // Functions -BinaryenFunctionRef BinaryenAddFunction(BinaryenModuleRef module, const char* name, BinaryenFunctionTypeRef type, BinaryenType* localTypes, BinaryenIndex numLocalTypes, BinaryenExpressionRef body) { +BinaryenFunctionRef BinaryenAddFunction(BinaryenModuleRef module, const char* name, BinaryenFunctionTypeRef type, BinaryenType* varTypes, BinaryenIndex numVarTypes, BinaryenExpressionRef body) { auto* wasm = (Module*)module; auto* ret = new Function; ret->name = name; @@ -391,8 +391,8 @@ BinaryenFunctionRef BinaryenAddFunction(BinaryenModuleRef module, const char* na auto* functionType = wasm->getFunctionType(ret->type); ret->result = functionType->result; ret->params = functionType->params; - for (BinaryenIndex i = 0; i < numLocalTypes; i++) { - ret->vars.push_back(WasmType(localTypes[i])); + for (BinaryenIndex i = 0; i < numVarTypes; i++) { + ret->vars.push_back(WasmType(varTypes[i])); } ret->body = (Expression*)body; diff --git a/src/binaryen-c.h b/src/binaryen-c.h index 7f9a775d5..3f940c0cc 100644 --- a/src/binaryen-c.h +++ b/src/binaryen-c.h @@ -285,6 +285,10 @@ BinaryenExpressionRef BinaryenCallIndirect(BinaryenModuleRef module, BinaryenExp // type or their opcode, or failing that, their children. But // GetLocal has no children, it is where a "stream" of type info // begins.) +// Note also that the index of a local can refer to a param or +// a var, that is, either a parameter to the function or a variable +// declared when you call BinaryenAddFunction. See BinaryenAddFunction +// for more details. BinaryenExpressionRef BinaryenGetLocal(BinaryenModuleRef module, BinaryenIndex index, BinaryenType type); BinaryenExpressionRef BinaryenSetLocal(BinaryenModuleRef module, BinaryenIndex index, BinaryenExpressionRef value); // Load: align can be 0, in which case it will be the natural alignment (equal to bytes) @@ -310,7 +314,14 @@ void BinaryenExpressionPrint(BinaryenExpressionRef expr); typedef void* BinaryenFunctionRef; // Adds a function to the module. This is thread-safe. -BinaryenFunctionRef BinaryenAddFunction(BinaryenModuleRef module, const char* name, BinaryenFunctionTypeRef type, BinaryenType* localTypes, BinaryenIndex numLocalTypes, BinaryenExpressionRef body); +// @varTypes: the types of variables. In WebAssembly, vars share +// an index space with params. In other words, params come from +// the function type, and vars are provided in this call, and +// together they are all the locals. The order is first params +// and then vars, so if you have one param it will be at index +// 0 (and written $0), and if you also have 2 vars they will be +// at indexes 1 and 2, etc., that is, they share an index space. +BinaryenFunctionRef BinaryenAddFunction(BinaryenModuleRef module, const char* name, BinaryenFunctionTypeRef type, BinaryenType* varTypes, BinaryenIndex numVarTypes, BinaryenExpressionRef body); // Imports diff --git a/test/example/c-api-kitchen-sink.c b/test/example/c-api-kitchen-sink.c index ace95177a..6fb095d20 100644 --- a/test/example/c-api-kitchen-sink.c +++ b/test/example/c-api-kitchen-sink.c @@ -395,6 +395,19 @@ void test_relooper() { BinaryenExpressionRef body = RelooperRenderAndDispose(relooper, block0, 0, module); BinaryenFunctionRef sinker = BinaryenAddFunction(module, "switch", v, localTypes, 1, body); } + { // duff's device + RelooperRef relooper = RelooperCreate(); + RelooperBlockRef block0 = RelooperAddBlock(relooper, makeInt32(module, 0)); + RelooperBlockRef block1 = RelooperAddBlock(relooper, makeInt32(module, 1)); + RelooperBlockRef block2 = RelooperAddBlock(relooper, makeInt32(module, 2)); + RelooperAddBranch(block0, block1, makeInt32(module, 10), NULL); + RelooperAddBranch(block0, block2, NULL, NULL); + RelooperAddBranch(block1, block2, NULL, NULL); + RelooperAddBranch(block2, block1, NULL, NULL); + BinaryenExpressionRef body = RelooperRenderAndDispose(relooper, block0, 3, module); // use $3 as the helper var + BinaryenType localTypes[] = { BinaryenInt32(), BinaryenInt32(), BinaryenInt64(), BinaryenInt32(), BinaryenFloat32(), BinaryenFloat64(), BinaryenInt32() }; + BinaryenFunctionRef sinker = BinaryenAddFunction(module, "duffs-device", v, localTypes, sizeof(localTypes)/sizeof(BinaryenType), body); + } BinaryenFunctionTypeRef i = BinaryenAddFunctionType(module, "i", BinaryenInt32(), NULL, 0); diff --git a/test/example/c-api-kitchen-sink.txt b/test/example/c-api-kitchen-sink.txt index d4eb5e337..7076622c5 100644 --- a/test/example/c-api-kitchen-sink.txt +++ b/test/example/c-api-kitchen-sink.txt @@ -667,6 +667,67 @@ raw: ) ) ) + (func $duffs-device (type $v) + (local $0 i32) + (local $1 i32) + (local $2 i64) + (local $3 i32) + (local $4 f32) + (local $5 f64) + (local $6 i32) + (block + (i32.const 0) + (if + (i32.const 10) + (set_local $3 + (i32.const 2) + ) + (set_local $3 + (i32.const 3) + ) + ) + ) + (loop $shape$1$break $shape$1$continue + (block $shape$2$break + (if + (i32.eq + (get_local $3) + (i32.const 2) + ) + (block + (set_local $3 + (i32.const 0) + ) + (i32.const 1) + (block + (set_local $3 + (i32.const 3) + ) + (br $shape$1$continue) + ) + ) + (if + (i32.eq + (get_local $3) + (i32.const 3) + ) + (block + (set_local $3 + (i32.const 0) + ) + (i32.const 2) + (block + (set_local $3 + (i32.const 2) + ) + (br $shape$1$continue) + ) + ) + ) + ) + ) + ) + ) (func $return (type $i) (result i32) (local $0 i32) (block $the-list @@ -685,6 +746,38 @@ optimized: (func $just-one-block (type $v) (nop) ) + (func $duffs-device (type $v) + (local $0 i32) + (set_local $0 + (i32.const 2) + ) + (loop $shape$1$break $shape$1$continue + (if + (i32.eq + (get_local $0) + (i32.const 2) + ) + (block + (set_local $0 + (i32.const 3) + ) + (br $shape$1$continue) + ) + (if + (i32.eq + (get_local $0) + (i32.const 3) + ) + (block + (set_local $0 + (i32.const 2) + ) + (br $shape$1$continue) + ) + ) + ) + ) + ) (func $return (type $i) (result i32) (i32.const 1337) ) |