summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/binaryen-c.cpp6
-rw-r--r--src/binaryen-c.h13
-rw-r--r--test/example/c-api-kitchen-sink.c13
-rw-r--r--test/example/c-api-kitchen-sink.txt93
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)
)