summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt3
-rwxr-xr-xcheck.py10
-rw-r--r--src/binaryen-c.cpp19
-rw-r--r--src/binaryen-c.h11
-rw-r--r--src/wasm.h6
-rw-r--r--test/example/c-api-kitchen-sink.c213
-rw-r--r--test/example/c-api-kitchen-sink.txt318
7 files changed, 562 insertions, 18 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index f4e224ebe..c952df396 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -92,6 +92,9 @@ ADD_LIBRARY(support STATIC ${support_SOURCES})
SET(binaryen_c_SOURCES
src/binaryen-c.cpp
+ src/pass.cpp
+ src/passes/Print.cpp
+ src/wasm.cpp
)
ADD_LIBRARY(binaryen-c STATIC ${binaryen_c_SOURCES})
diff --git a/check.py b/check.py
index 4e8699b05..a21c1c03d 100755
--- a/check.py
+++ b/check.py
@@ -570,12 +570,12 @@ if has_vanilla_emcc and has_vanilla_llvm:
print '\n[ checking example testcases... ]\n'
for t in sorted(os.listdir(os.path.join('test', 'example'))):
- cmd = [os.path.join('src', 'pass.cpp'),
- os.path.join('src', 'wasm.cpp'),
- os.path.join('src', 'passes', 'Print.cpp'),
- '-Isrc', '-g', '-lasmjs', '-lsupport', '-Llib/.', '-pthread']
+ cmd = ['-Isrc', '-g', '-lasmjs', '-lsupport', '-Llib/.', '-pthread']
if t.endswith('.cpp'):
- cmd = [os.path.join('test', 'example', t)] + cmd
+ cmd = [os.path.join('test', 'example', t),
+ os.path.join('src', 'pass.cpp'),
+ os.path.join('src', 'wasm.cpp'),
+ os.path.join('src', 'passes', 'Print.cpp')] + cmd
elif t.endswith('.c'):
# build the C file separately
extra = [os.environ.get('CC') or 'gcc',
diff --git a/src/binaryen-c.cpp b/src/binaryen-c.cpp
index 3ee47e2a9..f80c2be50 100644
--- a/src/binaryen-c.cpp
+++ b/src/binaryen-c.cpp
@@ -31,6 +31,7 @@ static_assert(sizeof(BinaryenLiteral) == sizeof(Literal), "Binaryen C API litera
BinaryenLiteral toBinaryenLiteral(Literal x) {
BinaryenLiteral ret;
+ ret.type = x.type;
switch (x.type) {
case WasmType::i32: ret.i32 = x.geti32(); break;
case WasmType::i64: ret.i64 = x.geti64(); break;
@@ -103,7 +104,7 @@ BinaryenOp BinaryenFloor(void) { return Floor; }
BinaryenOp BinaryenTrunc(void) { return Trunc; }
BinaryenOp BinaryenNearest(void) { return Nearest; }
BinaryenOp BinaryenSqrt(void) { return Sqrt; }
-BinaryenOp BinaryenEqz(void) { return EqZ; }
+BinaryenOp BinaryenEqZ(void) { return EqZ; }
BinaryenOp BinaryenExtendSInt32(void) { return ExtendSInt32; }
BinaryenOp BinaryenExtentUInt32(void) { return ExtendUInt32; }
BinaryenOp BinaryenWrapInt64(void) { return WrapInt64; }
@@ -146,7 +147,7 @@ BinaryenOp BinaryenLeS(void) { return LeS; }
BinaryenOp BinaryenLeU(void) { return LeU; }
BinaryenOp BinaryenGtS(void) { return GtS; }
BinaryenOp BinaryenGtU(void) { return GtU; }
-BinaryenOp BinaryenGes(void) { return GeS; }
+BinaryenOp BinaryenGeS(void) { return GeS; }
BinaryenOp BinaryenGeU(void) { return GeU; }
BinaryenOp BinaryenLt(void) { return Lt; }
BinaryenOp BinaryenLe(void) { return Le; }
@@ -177,6 +178,7 @@ BinaryenExpressionRef BinaryenIf(BinaryenModuleRef module, BinaryenExpressionRef
return ret;
}
BinaryenExpressionRef BinaryenLoop(BinaryenModuleRef module, const char* out, const char* in, BinaryenExpressionRef body) {
+ if (out && !in) abort();
return Builder(*((Module*)module)).makeLoop(out ? Name(out) : Name(), in ? Name(in) : Name(), (Expression*)body);
}
BinaryenExpressionRef BinaryenBreak(BinaryenModuleRef module, const char* name, BinaryenExpressionRef value, BinaryenExpressionRef condition) {
@@ -235,12 +237,13 @@ BinaryenExpressionRef BinaryenSetLocal(BinaryenModuleRef module, BinaryenIndex i
ret->finalize();
return ret;
}
-BinaryenExpressionRef BinaryenLoad(BinaryenModuleRef module, uint32_t bytes, int8_t signed_, uint32_t offset, uint32_t align, BinaryenExpressionRef ptr) {
+BinaryenExpressionRef BinaryenLoad(BinaryenModuleRef module, uint32_t bytes, int8_t signed_, uint32_t offset, uint32_t align, BinaryenType type, BinaryenExpressionRef ptr) {
auto* ret = ((Module*)module)->allocator.alloc<Load>();
ret->bytes = bytes;
ret->signed_ = signed_;
ret->offset = offset;
- ret->align = align;
+ ret->align = align ? align : bytes;
+ ret->type = WasmType(type);
ret->ptr = (Expression*)ptr;
ret->finalize();
return ret;
@@ -249,7 +252,7 @@ BinaryenExpressionRef BinaryenStore(BinaryenModuleRef module, uint32_t bytes, ui
auto* ret = ((Module*)module)->allocator.alloc<Store>();
ret->bytes = bytes;
ret->offset = offset;
- ret->align = align;
+ ret->align = align ? align : bytes;
ret->ptr = (Expression*)ptr;
ret->value = (Expression*)value;
ret->finalize();
@@ -328,8 +331,8 @@ BinaryenImportRef BinaryenAddImport(BinaryenModuleRef module, const char* intern
BinaryenExportRef BinaryenAddExport(BinaryenModuleRef module, const char* internalName, const char* externalName) {
auto* wasm = (Module*)module;
auto* ret = new Export();
- ret->name = internalName;
- ret->value = externalName;
+ ret->value = internalName;
+ ret->name = externalName;
wasm->addExport(ret);
return ret;
}
@@ -349,7 +352,7 @@ void BinaryenSetMemory(BinaryenModuleRef module, BinaryenIndex initial, Binaryen
auto* wasm = (Module*)module;
wasm->memory.initial = initial;
wasm->memory.max = maximum;
- wasm->memory.exportName = exportName;
+ if (exportName) wasm->memory.exportName = exportName;
for (BinaryenIndex i = 0; i < numSegments; i++) {
wasm->memory.segments.emplace_back(segmentOffsets[i], segments[i], segmentSizes[i]);
}
diff --git a/src/binaryen-c.h b/src/binaryen-c.h
index 94523afcc..475c65613 100644
--- a/src/binaryen-c.h
+++ b/src/binaryen-c.h
@@ -117,7 +117,7 @@ BinaryenOp BinaryenFloor(void);
BinaryenOp BinaryenTrunc(void);
BinaryenOp BinaryenNearest(void);
BinaryenOp BinaryenSqrt(void);
-BinaryenOp BinaryenEqz(void);
+BinaryenOp BinaryenEqZ(void);
BinaryenOp BinaryenExtendSInt32(void);
BinaryenOp BinaryenExtentUInt32(void);
BinaryenOp BinaryenWrapInt64(void);
@@ -160,7 +160,7 @@ BinaryenOp BinaryenLeS(void);
BinaryenOp BinaryenLeU(void);
BinaryenOp BinaryenGtS(void);
BinaryenOp BinaryenGtU(void);
-BinaryenOp BinaryenGes(void);
+BinaryenOp BinaryenGeS(void);
BinaryenOp BinaryenGeU(void);
BinaryenOp BinaryenLt(void);
BinaryenOp BinaryenLe(void);
@@ -177,18 +177,18 @@ typedef void* BinaryenExpressionRef;
BinaryenExpressionRef BinaryenBlock(BinaryenModuleRef module, const char* name, BinaryenExpressionRef* children, BinaryenIndex numChildren);
// If: ifFalse can be NULL
BinaryenExpressionRef BinaryenIf(BinaryenModuleRef module, BinaryenExpressionRef condition, BinaryenExpressionRef ifTrue, BinaryenExpressionRef ifFalse);
-// Loop: out and in can be NULL
+// Loop: both out and in can be NULL, or just out can be NULL
BinaryenExpressionRef BinaryenLoop(BinaryenModuleRef module, const char* out, const char* in, BinaryenExpressionRef body);
// Break: value and condition can be NULL
BinaryenExpressionRef BinaryenBreak(BinaryenModuleRef module, const char* name, BinaryenExpressionRef value, BinaryenExpressionRef condition);
-// Switch: value and condition can be NULL
+// Switch: value can be NULL
BinaryenExpressionRef BinaryenSwitch(BinaryenModuleRef module, const char **names, BinaryenIndex numNames, const char* defaultName, BinaryenExpressionRef condition, BinaryenExpressionRef value);
BinaryenExpressionRef BinaryenCall(BinaryenModuleRef module, const char *target, BinaryenExpressionRef* operands, BinaryenIndex numOperands);
BinaryenExpressionRef BinaryenCallImport(BinaryenModuleRef module, const char *target, BinaryenExpressionRef* operands, BinaryenIndex numOperands);
BinaryenExpressionRef BinaryenCallIndirect(BinaryenModuleRef module, BinaryenExpressionRef target, BinaryenExpressionRef* operands, BinaryenIndex numOperands, BinaryenFunctionTypeRef type);
BinaryenExpressionRef BinaryenGetLocal(BinaryenModuleRef module, BinaryenIndex index, BinaryenType type);
BinaryenExpressionRef BinaryenSetLocal(BinaryenModuleRef module, BinaryenIndex index, BinaryenExpressionRef value);
-BinaryenExpressionRef BinaryenLoad(BinaryenModuleRef module, uint32_t bytes, int8_t signed_, uint32_t offset, uint32_t align, BinaryenExpressionRef ptr);
+BinaryenExpressionRef BinaryenLoad(BinaryenModuleRef module, uint32_t bytes, int8_t signed_, uint32_t offset, uint32_t align, BinaryenType type, BinaryenExpressionRef ptr);
BinaryenExpressionRef BinaryenStore(BinaryenModuleRef module, uint32_t bytes, uint32_t offset, uint32_t align, BinaryenExpressionRef ptr, BinaryenExpressionRef value);
BinaryenExpressionRef BinaryenConst(BinaryenModuleRef module, struct BinaryenLiteral value);
BinaryenExpressionRef BinaryenUnary(BinaryenModuleRef module, BinaryenOp op, BinaryenExpressionRef value, BinaryenType type);
@@ -226,6 +226,7 @@ void BinaryenSetFunctionTable(BinaryenModuleRef module, BinaryenFunctionRef* fun
// Memory. One per module
// Each segment has data in segments, a start offset in segmentOffsets, and a size in segmentSizes.
+// exportName can be NULL
void BinaryenSetMemory(BinaryenModuleRef module, BinaryenIndex initial, BinaryenIndex maximum, const char* exportName, const char **segments, BinaryenIndex* segmentOffsets, BinaryenIndex* segmentSizes, BinaryenIndex numSegments);
// Start function. One per module
diff --git a/src/wasm.h b/src/wasm.h
index c089d46b9..d61c8e564 100644
--- a/src/wasm.h
+++ b/src/wasm.h
@@ -975,6 +975,8 @@ public:
uint32_t offset;
uint32_t align;
Expression *ptr;
+
+ // type must be set during creation, cannot be inferred
};
class Store : public SpecificExpression<Expression::StoreId> {
@@ -986,6 +988,10 @@ public:
uint32_t offset;
unsigned align;
Expression *ptr, *value;
+
+ void finalize() {
+ type = value->type;
+ }
};
class Const : public SpecificExpression<Expression::ConstId> {
diff --git a/test/example/c-api-kitchen-sink.c b/test/example/c-api-kitchen-sink.c
new file mode 100644
index 000000000..f7dc5c341
--- /dev/null
+++ b/test/example/c-api-kitchen-sink.c
@@ -0,0 +1,213 @@
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <binaryen-c.h>
+
+
+// kitchen sink, tests the full API
+
+
+// helpers
+
+BinaryenExpressionRef makeUnary(BinaryenModuleRef module, BinaryenOp op, BinaryenType inputType, BinaryenType outputType) {
+ if (inputType == BinaryenInt32()) return BinaryenUnary(module, op, BinaryenConst(module, BinaryenLiteralInt32(-10)), outputType);
+ if (inputType == BinaryenInt64()) return BinaryenUnary(module, op, BinaryenConst(module, BinaryenLiteralInt64(-22)), outputType);
+ if (inputType == BinaryenFloat32()) return BinaryenUnary(module, op, BinaryenConst(module, BinaryenLiteralFloat32(-33.612)), outputType);
+ if (inputType == BinaryenFloat64()) return BinaryenUnary(module, op, BinaryenConst(module, BinaryenLiteralFloat64(-9005.841)), outputType);
+ abort();
+}
+
+BinaryenExpressionRef makeBinary(BinaryenModuleRef module, BinaryenOp op, BinaryenType type) {
+ if (type == BinaryenInt32()) return BinaryenBinary(module, op, BinaryenConst(module, BinaryenLiteralInt32(-10)), BinaryenConst(module, BinaryenLiteralInt32(-11)));
+ if (type == BinaryenInt64()) return BinaryenBinary(module, op, BinaryenConst(module, BinaryenLiteralInt64(-22)), BinaryenConst(module, BinaryenLiteralInt64(-23)));
+ if (type == BinaryenFloat32()) return BinaryenBinary(module, op, BinaryenConst(module, BinaryenLiteralFloat32(-33.612)), BinaryenConst(module, BinaryenLiteralFloat32(-62.5)));
+ if (type == BinaryenFloat64()) return BinaryenBinary(module, op, BinaryenConst(module, BinaryenLiteralFloat64(-9005.841)), BinaryenConst(module, BinaryenLiteralFloat64(-9007.333)));
+ abort();
+}
+
+BinaryenExpressionRef makeInt32(BinaryenModuleRef module, int x) {
+ return BinaryenConst(module, BinaryenLiteralInt32(x));
+}
+
+BinaryenExpressionRef makeFloat32(BinaryenModuleRef module, float x) {
+ return BinaryenConst(module, BinaryenLiteralFloat32(x));
+}
+
+BinaryenExpressionRef makeInt64(BinaryenModuleRef module, int64_t x) {
+ return BinaryenConst(module, BinaryenLiteralInt64(x));
+}
+
+BinaryenExpressionRef makeFloat64(BinaryenModuleRef module, double x) {
+ return BinaryenConst(module, BinaryenLiteralFloat64(x));
+}
+
+BinaryenExpressionRef makeSomething(BinaryenModuleRef module) {
+ return makeInt32(module, 1337);
+}
+
+// main
+
+int main() {
+
+ // Core types
+
+ printf("BinaryenNone: %d\n", BinaryenNone());
+ printf("BinaryenInt32: %d\n", BinaryenInt32());
+ printf("BinaryenInt64: %d\n", BinaryenInt64());
+ printf("BinaryenFloat32: %d\n", BinaryenFloat32());
+ printf("BinaryenFloat64: %d\n", BinaryenFloat64());
+
+ // Module creation
+
+ BinaryenModuleRef module = BinaryenModuleCreate();
+
+ // Literals and consts
+
+ BinaryenExpressionRef constI32 = BinaryenConst(module, BinaryenLiteralInt32(1)),
+ constI64 = BinaryenConst(module, BinaryenLiteralInt64(2)),
+ constF32 = BinaryenConst(module, BinaryenLiteralFloat32(3.14)),
+ constF64 = BinaryenConst(module, BinaryenLiteralFloat64(2.1828)),
+ constF32Bits = BinaryenConst(module, BinaryenLiteralFloat32Bits(0xffff1234)),
+ constF64Bits = BinaryenConst(module, BinaryenLiteralFloat64Bits(0xffff12345678abcdLL));
+
+ const char* switchNames[] = { "the-body" };
+
+ BinaryenExpressionRef callOperands2[] = { makeInt32(module, 13), makeFloat64(module, 3.7) };
+ BinaryenExpressionRef callOperands4[] = { makeInt32(module, 13), makeInt64(module, 37), makeFloat32(module, 1.3), makeFloat64(module, 3.7) };
+
+ BinaryenType params[4] = { BinaryenInt32(), BinaryenInt64(), BinaryenFloat32(), BinaryenFloat64() };
+ BinaryenFunctionTypeRef iiIfF = BinaryenAddFunctionType(module, "iiIfF", BinaryenInt32(), params, 4);
+
+ BinaryenExpressionRef bodyList[] = {
+ // Unary
+ makeUnary(module, BinaryenClz(), 1, 1),
+ makeUnary(module, BinaryenCtz(), 2, 2),
+ makeUnary(module, BinaryenPopcnt(), 1, 1),
+ makeUnary(module, BinaryenNeg(), 3, 3),
+ makeUnary(module, BinaryenAbs(), 4, 3),
+ makeUnary(module, BinaryenCeil(), 3, 3),
+ makeUnary(module, BinaryenFloor(), 4, 4),
+ makeUnary(module, BinaryenTrunc(), 3, 3),
+ makeUnary(module, BinaryenNearest(), 3, 3),
+ makeUnary(module, BinaryenSqrt(), 4, 4),
+ makeUnary(module, BinaryenEqZ(), 1, 1),
+ makeUnary(module, BinaryenExtendSInt32(), 1, 2),
+ makeUnary(module, BinaryenExtentUInt32(), 1, 2),
+ makeUnary(module, BinaryenWrapInt64(), 2, 1),
+ makeUnary(module, BinaryenTruncSFloat32(), 3, 1),
+ makeUnary(module, BinaryenTruncUFloat32(), 3, 2),
+ makeUnary(module, BinaryenTruncSFloat64(), 4, 2),
+ makeUnary(module, BinaryenTruncUFloat64(), 4, 1),
+ makeUnary(module, BinaryenReinterpretFloat(), 3, 1),
+ makeUnary(module, BinaryenConvertSInt32(), 1, 3),
+ makeUnary(module, BinaryenConvertUInt32(), 1, 4),
+ makeUnary(module, BinaryenConvertSInt64(), 2, 3),
+ makeUnary(module, BinaryenConvertUInt64(), 2, 4),
+ makeUnary(module, BinaryenPromoteFloat32(), 3, 4),
+ makeUnary(module, BinaryenDemoteFloat64(), 4, 3),
+ makeUnary(module, BinaryenReinterpretInt(), 1, 3),
+ // Binary
+ makeBinary(module, BinaryenAdd(), 1),
+ makeBinary(module, BinaryenSub(), 4),
+ makeBinary(module, BinaryenDivS(), 1),
+ makeBinary(module, BinaryenDivU(), 2),
+ makeBinary(module, BinaryenRemS(), 2),
+ makeBinary(module, BinaryenRemU(), 1),
+ makeBinary(module, BinaryenAnd(), 1),
+ makeBinary(module, BinaryenOr(), 2),
+ makeBinary(module, BinaryenXor(), 1),
+ makeBinary(module, BinaryenShl(), 2),
+ makeBinary(module, BinaryenShrU(), 2),
+ makeBinary(module, BinaryenShrS(), 1),
+ makeBinary(module, BinaryenRotL(), 1),
+ makeBinary(module, BinaryenRotR(), 2),
+ makeBinary(module, BinaryenDiv(), 3),
+ makeBinary(module, BinaryenCopySign(), 4),
+ makeBinary(module, BinaryenMin(), 3),
+ makeBinary(module, BinaryenMax(), 4),
+ makeBinary(module, BinaryenEq(), 1),
+ makeBinary(module, BinaryenNe(), 3),
+ makeBinary(module, BinaryenLtS(), 1),
+ makeBinary(module, BinaryenLtU(), 2),
+ makeBinary(module, BinaryenLeS(), 2),
+ makeBinary(module, BinaryenLeU(), 1),
+ makeBinary(module, BinaryenGtS(), 2),
+ makeBinary(module, BinaryenGtU(), 1),
+ makeBinary(module, BinaryenGeS(), 1),
+ makeBinary(module, BinaryenGeU(), 2),
+ makeBinary(module, BinaryenLt(), 3),
+ makeBinary(module, BinaryenLe(), 4),
+ makeBinary(module, BinaryenGt(), 4),
+ makeBinary(module, BinaryenGe(), 3),
+ // All the rest
+ BinaryenBlock(module, NULL, NULL, 0), // block with no name
+ BinaryenIf(module, makeInt32(module, 1), makeInt32(module, 2), makeInt32(module, 3)),
+ BinaryenIf(module, makeInt32(module, 4), makeInt32(module, 5), NULL),
+ BinaryenLoop(module, "out", "in", makeInt32(module, 0)),
+ BinaryenLoop(module, NULL, "in2", makeInt32(module, 0)),
+ BinaryenLoop(module, NULL, NULL, makeInt32(module, 0)),
+ BinaryenBreak(module, "the-body", makeInt32(module, 0), makeInt32(module, 1)),
+ BinaryenBreak(module, "the-body", makeInt32(module, 2), NULL),
+ BinaryenBreak(module, "the-body", NULL, makeInt32(module, 3)),
+ BinaryenBreak(module, "the-body", NULL, NULL),
+ BinaryenSwitch(module, switchNames, 1, "the-body", makeInt32(module, 0), makeInt32(module, 1)),
+ BinaryenSwitch(module, switchNames, 1, "the-body", makeInt32(module, 2), NULL),
+ BinaryenCall(module, "kitchen-sinker", callOperands4, 4),
+ BinaryenCallImport(module, "an-imported", callOperands2, 2),
+ BinaryenCallIndirect(module, makeInt32(module, 2449), callOperands4, 4, iiIfF),
+ BinaryenGetLocal(module, 0, BinaryenInt32()),
+ BinaryenSetLocal(module, 0, makeInt32(module, 101)),
+ BinaryenLoad(module, 4, 0, 0, 0, BinaryenInt32(), makeInt32(module, 1)),
+ BinaryenLoad(module, 1, 1, 2, 4, BinaryenInt64(), makeInt32(module, 8)),
+ BinaryenLoad(module, 4, 0, 0, 0, BinaryenFloat32(), makeInt32(module, 2)),
+ BinaryenLoad(module, 8, 0, 2, 8, BinaryenFloat64(), makeInt32(module, 9)),
+ BinaryenStore(module, 4, 0, 0, makeInt32(module, 10), makeInt32(module, 11)),
+ BinaryenStore(module, 8, 2, 4, makeInt32(module, 110), makeInt64(module, 111)),
+ BinaryenSelect(module, makeInt32(module, 1), makeInt32(module, 3), makeInt32(module, 5)),
+ BinaryenReturn(module, NULL),
+ BinaryenReturn(module, makeFloat32(module, 1)),
+ // TODO: Host
+ BinaryenNop(module),
+ BinaryenUnreachable(module),
+ };
+
+ // Make the main body of the function
+ BinaryenExpressionRef body = BinaryenBlock(module, "the-body", bodyList, sizeof(bodyList) / sizeof(BinaryenExpressionRef));
+
+ // Create the function
+ BinaryenType localTypes[] = { BinaryenInt32() };
+ BinaryenFunctionRef sinker = BinaryenAddFunction(module, "kitchen-sinker", iiIfF, localTypes, 1, body);
+
+ // Imports
+
+ BinaryenType iparams[2] = { BinaryenInt32(), BinaryenFloat64() };
+ BinaryenFunctionTypeRef viF = BinaryenAddFunctionType(module, "viF", BinaryenNone(), iparams, 2);
+ BinaryenAddImport(module, "an-imported", "module", "base", viF);
+
+ // Exports
+
+ BinaryenAddExport(module, "kitchen-sinker", "kitchen_sinker");
+
+ // Function table. One per module
+ BinaryenFunctionRef functions[] = { sinker };
+ BinaryenSetFunctionTable(module, functions, 1);
+
+ // Memory. One per module
+
+ const char *segments[] = { "hello, world" };
+ BinaryenIndex segmentOffsets[] = { 10 };
+ BinaryenIndex segmentSizes[] = { 12 };
+ BinaryenSetMemory(module, 1, 256, "mem", segments, segmentOffsets, segmentSizes, 1);
+
+ // Start function. One per module
+
+ BinaryenSetStart(module, "sinker");
+
+ // Print it out
+ BinaryenModulePrint(module);
+
+ // Clean up the module, which owns all the objects we created above
+ BinaryenModuleDispose(module);
+}
+
diff --git a/test/example/c-api-kitchen-sink.txt b/test/example/c-api-kitchen-sink.txt
new file mode 100644
index 000000000..2c80d8706
--- /dev/null
+++ b/test/example/c-api-kitchen-sink.txt
@@ -0,0 +1,318 @@
+BinaryenNone: 0
+BinaryenInt32: 1
+BinaryenInt64: 2
+BinaryenFloat32: 3
+BinaryenFloat64: 4
+(module
+ (memory 1 256
+ (segment 10 "hello, world")
+ )
+ (export "mem" memory)
+ (start $sinker)
+ (type $iiIfF (func (param i32 i64 f32 f64) (result i32)))
+ (type $viF (func (param i32 f64)))
+ (import $an-imported "module" "base" (param i32 f64))
+ (export "kitchen_sinker" $kitchen-sinker)
+ (table $kitchen-sinker)
+ (func $kitchen-sinker (type $iiIfF) (param $0 i32) (param $1 i64) (param $2 f32) (param $3 f64) (result i32)
+ (local $4 i32)
+ (block $the-body
+ (i32.clz
+ (i32.const -10)
+ )
+ (i64.ctz
+ (i64.const -22)
+ )
+ (i32.popcnt
+ (i32.const -10)
+ )
+ (f32.neg
+ (f32.const -33.61199951171875)
+ )
+ (f32.abs
+ (f64.const -9005.841)
+ )
+ (f32.ceil
+ (f32.const -33.61199951171875)
+ )
+ (f64.floor
+ (f64.const -9005.841)
+ )
+ (f32.trunc
+ (f32.const -33.61199951171875)
+ )
+ (f32.nearest
+ (f32.const -33.61199951171875)
+ )
+ (f64.sqrt
+ (f64.const -9005.841)
+ )
+ (i32.eqz
+ (i32.const -10)
+ )
+ (i64.extend_s/i32
+ (i32.const -10)
+ )
+ (i64.extend_u/i32
+ (i32.const -10)
+ )
+ (i32.wrap/i64
+ (i64.const -22)
+ )
+ (i32.trunc_s/f32
+ (f32.const -33.61199951171875)
+ )
+ (i64.trunc_u/f32
+ (f32.const -33.61199951171875)
+ )
+ (i64.trunc_s/f64
+ (f64.const -9005.841)
+ )
+ (i32.trunc_u/f64
+ (f64.const -9005.841)
+ )
+ (i32.reinterpret/f32
+ (f32.const -33.61199951171875)
+ )
+ (f32.convert_s/i32
+ (i32.const -10)
+ )
+ (f64.convert_u/i32
+ (i32.const -10)
+ )
+ (f32.convert_s/i64
+ (i64.const -22)
+ )
+ (f64.convert_u/i64
+ (i64.const -22)
+ )
+ (f64.promote/f32
+ (f32.const -33.61199951171875)
+ )
+ (f32.demote/f64
+ (f64.const -9005.841)
+ )
+ (f32.reinterpret/i32
+ (i32.const -10)
+ )
+ (i32.add
+ (i32.const -10)
+ (i32.const -11)
+ )
+ (f64.sub
+ (f64.const -9005.841)
+ (f64.const -9007.333)
+ )
+ (i32.div_s
+ (i32.const -10)
+ (i32.const -11)
+ )
+ (i64.div_u
+ (i64.const -22)
+ (i64.const -23)
+ )
+ (i64.rem_s
+ (i64.const -22)
+ (i64.const -23)
+ )
+ (i32.rem_u
+ (i32.const -10)
+ (i32.const -11)
+ )
+ (i32.and
+ (i32.const -10)
+ (i32.const -11)
+ )
+ (i64.or
+ (i64.const -22)
+ (i64.const -23)
+ )
+ (i32.xor
+ (i32.const -10)
+ (i32.const -11)
+ )
+ (i64.shl
+ (i64.const -22)
+ (i64.const -23)
+ )
+ (i64.shr_u
+ (i64.const -22)
+ (i64.const -23)
+ )
+ (i32.shr_s
+ (i32.const -10)
+ (i32.const -11)
+ )
+ (i32.rotl
+ (i32.const -10)
+ (i32.const -11)
+ )
+ (i64.rotr
+ (i64.const -22)
+ (i64.const -23)
+ )
+ (f32.div
+ (f32.const -33.61199951171875)
+ (f32.const -62.5)
+ )
+ (f64.copysign
+ (f64.const -9005.841)
+ (f64.const -9007.333)
+ )
+ (f32.min
+ (f32.const -33.61199951171875)
+ (f32.const -62.5)
+ )
+ (f64.max
+ (f64.const -9005.841)
+ (f64.const -9007.333)
+ )
+ (i32.eq
+ (i32.const -10)
+ (i32.const -11)
+ )
+ (f32.ne
+ (f32.const -33.61199951171875)
+ (f32.const -62.5)
+ )
+ (i32.lt_s
+ (i32.const -10)
+ (i32.const -11)
+ )
+ (i64.lt_u
+ (i64.const -22)
+ (i64.const -23)
+ )
+ (i64.le_s
+ (i64.const -22)
+ (i64.const -23)
+ )
+ (i32.le_u
+ (i32.const -10)
+ (i32.const -11)
+ )
+ (i64.gt_s
+ (i64.const -22)
+ (i64.const -23)
+ )
+ (i32.gt_u
+ (i32.const -10)
+ (i32.const -11)
+ )
+ (i32.ge_s
+ (i32.const -10)
+ (i32.const -11)
+ )
+ (i64.ge_u
+ (i64.const -22)
+ (i64.const -23)
+ )
+ (f32.lt
+ (f32.const -33.61199951171875)
+ (f32.const -62.5)
+ )
+ (f64.le
+ (f64.const -9005.841)
+ (f64.const -9007.333)
+ )
+ (f64.gt
+ (f64.const -9005.841)
+ (f64.const -9007.333)
+ )
+ (f32.ge
+ (f32.const -33.61199951171875)
+ (f32.const -62.5)
+ )
+ (block
+ )
+ (if
+ (i32.const 1)
+ (i32.const 2)
+ (i32.const 3)
+ )
+ (if
+ (i32.const 4)
+ (i32.const 5)
+ )
+ (loop $out $in
+ (i32.const 0)
+ )
+ (loop $in2
+ (i32.const 0)
+ )
+ (loop
+ (i32.const 0)
+ )
+ (br_if $the-body
+ (i32.const 0)
+ (i32.const 1)
+ )
+ (br $the-body
+ (i32.const 2)
+ )
+ (br_if $the-body
+ (i32.const 3)
+ )
+ (br $the-body)
+ (br_table $the-body $the-body
+ (i32.const 1)
+ (i32.const 0)
+ )
+ (br_table $the-body $the-body
+ (i32.const 2)
+ )
+ (call $kitchen-sinker
+ (i32.const 13)
+ (i64.const 37)
+ (f32.const 1.2999999523162842)
+ (f64.const 3.7)
+ )
+ (call_import $an-imported
+ (i32.const 13)
+ (f64.const 3.7)
+ )
+ (call_indirect $iiIfF
+ (i32.const 2449)
+ (i32.const 13)
+ (i64.const 37)
+ (f32.const 1.2999999523162842)
+ (f64.const 3.7)
+ )
+ (get_local $0)
+ (set_local $0
+ (i32.const 101)
+ )
+ (i32.load
+ (i32.const 1)
+ )
+ (i64.load8_s offset=2 align=4
+ (i32.const 8)
+ )
+ (f32.load
+ (i32.const 2)
+ )
+ (f64.load offset=2
+ (i32.const 9)
+ )
+ (i32.store
+ (i32.const 10)
+ (i32.const 11)
+ )
+ (i64.store offset=2 align=4
+ (i32.const 110)
+ (i64.const 111)
+ )
+ (select
+ (i32.const 3)
+ (i32.const 5)
+ (i32.const 1)
+ )
+ (return)
+ (return
+ (f32.const 1)
+ )
+ (nop)
+ (unreachable)
+ )
+ )
+)