summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xbuild-js.sh12
-rw-r--r--src/binaryen-c.cpp117
-rw-r--r--src/binaryen-c.h22
-rw-r--r--src/js/binaryen.js-post.js29
-rw-r--r--test/binaryen.js/kitchen-sink.js55
-rw-r--r--test/binaryen.js/kitchen-sink.js.txt20
-rw-r--r--test/example/c-api-kitchen-sink.c55
-rw-r--r--test/example/c-api-kitchen-sink.txt20
8 files changed, 329 insertions, 1 deletions
diff --git a/build-js.sh b/build-js.sh
index 37bdc00ee..1e0127d1c 100755
--- a/build-js.sh
+++ b/build-js.sh
@@ -18,7 +18,7 @@ if [ "$1" == "-h" ] || [ "$1" == "--help" ] || [ "$1" == "-help" ]; then
echo "usage: $0 [-g]" >&2
echo " -g produce debug build" >&2
echo ""
- echo "If EMSCRIPTEN is set in the envionment, emscripten will be loaded"
+ echo "If EMSCRIPTEN is set in the environment, emscripten will be loaded"
echo "from that directory. Otherwise the location of emscripten is resolved"
echo "through PATH."
exit 1
@@ -811,6 +811,12 @@ export_function "_BinaryenMemoryFillGetDest"
export_function "_BinaryenMemoryFillGetValue"
export_function "_BinaryenMemoryFillGetSize"
+# 'Segments' query operations.
+export_function "_BinaryenGetNumMemorySegments"
+export_function "_BinaryenGetMemorySegmentByteOffset"
+export_function "_BinaryenGetMemorySegmentByteLength"
+export_function "_BinaryenCopyMemorySegmentData"
+
# 'Try' expression operations
export_function "_BinaryenTryGetBody"
export_function "_BinaryenTryGetCatchBody"
@@ -840,12 +846,16 @@ export_function "_BinaryenGetFunctionTypeBySignature"
export_function "_BinaryenAddFunction"
export_function "_BinaryenGetFunction"
export_function "_BinaryenRemoveFunction"
+export_function "_BinaryenGetNumFunctions"
+export_function "_BinaryenGetFunctionByIndex"
export_function "_BinaryenAddGlobal"
export_function "_BinaryenGetGlobal"
export_function "_BinaryenRemoveGlobal"
export_function "_BinaryenAddEvent"
export_function "_BinaryenGetEvent"
export_function "_BinaryenRemoveEvent"
+export_function "_BinaryenGetNumExports"
+export_function "_BinaryenGetExportByIndex"
export_function "_BinaryenAddFunctionImport"
export_function "_BinaryenAddTableImport"
export_function "_BinaryenAddMemoryImport"
diff --git a/src/binaryen-c.cpp b/src/binaryen-c.cpp
index 1cb0963a2..6bb6f6e14 100644
--- a/src/binaryen-c.cpp
+++ b/src/binaryen-c.cpp
@@ -3142,6 +3142,26 @@ void BinaryenRemoveFunction(BinaryenModuleRef module, const char* name) {
auto* wasm = (Module*)module;
wasm->removeFunction(name);
}
+uint32_t BinaryenGetNumFunctions(BinaryenModuleRef module) {
+ if (tracing) {
+ std::cout << " BinaryenGetNumFunctions(the_module);\n";
+ }
+
+ auto* wasm = (Module*)module;
+ return wasm->functions.size();
+}
+BinaryenFunctionRef BinaryenGetFunctionByIndex(BinaryenModuleRef module,
+ BinaryenIndex id) {
+ if (tracing) {
+ std::cout << " BinaryenGetFunctionByIndex(the_module, " << id << ");\n";
+ }
+
+ auto* wasm = (Module*)module;
+ if (wasm->functions.size() <= id) {
+ Fatal() << "invalid function id.";
+ }
+ return wasm->functions[id].get();
+}
// Globals
@@ -3578,6 +3598,83 @@ void BinaryenSetMemory(BinaryenModuleRef module,
}
}
+// Memory segments
+
+uint32_t BinaryenGetNumMemorySegments(BinaryenModuleRef module) {
+ if (tracing) {
+ std::cout << " BinaryenGetNumMemorySegments(the_module);\n";
+ }
+
+ auto* wasm = (Module*)module;
+ return wasm->memory.segments.size();
+}
+int64_t BinaryenGetMemorySegmentByteOffset(BinaryenModuleRef module,
+ BinaryenIndex id) {
+ if (tracing) {
+ std::cout << " BinaryenGetMemorySegmentByteOffset(the_module, " << id
+ << ");\n";
+ }
+
+ auto* wasm = (Module*)module;
+ if (wasm->memory.segments.size() <= id) {
+ Fatal() << "invalid segment id.";
+ }
+
+ auto globalOffset = [&](const Expression* const& expr,
+ int64_t& result) -> bool {
+ if (auto* c = expr->dynCast<Const>()) {
+ result = c->value.getInteger();
+ return true;
+ }
+ return false;
+ };
+
+ const Memory::Segment& segment = wasm->memory.segments[id];
+
+ int64_t ret;
+ if (globalOffset(segment.offset, ret)) {
+ return ret;
+ }
+ if (auto* get = segment.offset->dynCast<GlobalGet>()) {
+ Global* global = wasm->getGlobal(get->name);
+ if (globalOffset(global->init, ret)) {
+ return ret;
+ }
+ }
+
+ Fatal() << "non-constant offsets aren't supported yet";
+ return 0;
+}
+size_t BinaryenGetMemorySegmentByteLength(BinaryenModuleRef module,
+ BinaryenIndex id) {
+ if (tracing) {
+ std::cout << " BinaryenGetMemorySegmentByteLength(the_module, " << id
+ << ");\n";
+ }
+
+ auto* wasm = (Module*)module;
+ if (wasm->memory.segments.size() <= id) {
+ Fatal() << "invalid segment id.";
+ }
+ const Memory::Segment& segment = wasm->memory.segments[id];
+ return segment.data.size();
+}
+void BinaryenCopyMemorySegmentData(BinaryenModuleRef module,
+ BinaryenIndex id,
+ char* buffer) {
+ if (tracing) {
+ std::cout << " BinaryenCopyMemorySegmentData(the_module, " << id << ", "
+ << static_cast<void*>(buffer) << ");\n";
+ }
+
+ auto* wasm = (Module*)module;
+ if (wasm->memory.segments.size() <= id) {
+ Fatal() << "invalid segment id.";
+ }
+ const Memory::Segment& segment = wasm->memory.segments[id];
+ std::copy(segment.data.cbegin(), segment.data.cend(), buffer);
+}
+
// Start function. One per module
void BinaryenSetStart(BinaryenModuleRef module, BinaryenFunctionRef start) {
@@ -4305,6 +4402,26 @@ const char* BinaryenExportGetValue(BinaryenExportRef export_) {
return ((Export*)export_)->value.c_str();
}
+uint32_t BinaryenGetNumExports(BinaryenModuleRef module) {
+ if (tracing) {
+ std::cout << " BinaryenGetNumExports(the_module);\n";
+ }
+
+ auto* wasm = (Module*)module;
+ return wasm->exports.size();
+}
+BinaryenExportRef BinaryenGetExportByIndex(BinaryenModuleRef module,
+ BinaryenIndex id) {
+ if (tracing) {
+ std::cout << " BinaryenGetExportByIndex(the_module, " << id << ");\n";
+ }
+
+ auto* wasm = (Module*)module;
+ if (wasm->exports.size() <= id) {
+ Fatal() << "invalid export id.";
+ }
+ return wasm->exports[id].get();
+}
//
// ========= Custom sections =========
diff --git a/src/binaryen-c.h b/src/binaryen-c.h
index 1015c65de..9dddc9ce6 100644
--- a/src/binaryen-c.h
+++ b/src/binaryen-c.h
@@ -1064,6 +1064,12 @@ BINARYEN_API BinaryenFunctionRef BinaryenGetFunction(BinaryenModuleRef module,
BINARYEN_API void BinaryenRemoveFunction(BinaryenModuleRef module,
const char* name);
+// Gets the number of functions in the module.
+BINARYEN_API uint32_t BinaryenGetNumFunctions(BinaryenModuleRef module);
+// Get function pointer from its index.
+BINARYEN_API BinaryenFunctionRef
+BinaryenGetFunctionByIndex(BinaryenModuleRef module, BinaryenIndex id);
+
// Imports
BINARYEN_API void
@@ -1168,6 +1174,17 @@ BINARYEN_API void BinaryenSetMemory(BinaryenModuleRef module,
BinaryenIndex numSegments,
uint8_t shared);
+// Memory segments. Query utilities.
+
+BINARYEN_API uint32_t BinaryenGetNumMemorySegments(BinaryenModuleRef module);
+BINARYEN_API int64_t
+BinaryenGetMemorySegmentByteOffset(BinaryenModuleRef module, BinaryenIndex id);
+BINARYEN_API size_t BinaryenGetMemorySegmentByteLength(BinaryenModuleRef module,
+ BinaryenIndex id);
+BINARYEN_API void BinaryenCopyMemorySegmentData(BinaryenModuleRef module,
+ BinaryenIndex id,
+ char* buffer);
+
// Start function. One per module
BINARYEN_API void BinaryenSetStart(BinaryenModuleRef module,
@@ -1437,6 +1454,11 @@ BinaryenExportGetKind(BinaryenExportRef export_);
BINARYEN_API const char* BinaryenExportGetName(BinaryenExportRef export_);
// Gets the internal name of the specified export.
BINARYEN_API const char* BinaryenExportGetValue(BinaryenExportRef export_);
+// Gets the number of exports in the module.
+BINARYEN_API uint32_t BinaryenGetNumExports(BinaryenModuleRef module);
+// Get export pointer from its index.
+BINARYEN_API BinaryenExportRef
+BinaryenGetExportByIndex(BinaryenModuleRef module, BinaryenIndex id);
//
// ========= Custom sections =========
diff --git a/src/js/binaryen.js-post.js b/src/js/binaryen.js-post.js
index 7c99ded15..0da3f2df4 100644
--- a/src/js/binaryen.js-post.js
+++ b/src/js/binaryen.js-post.js
@@ -2096,6 +2096,23 @@ function wrapModule(module, self) {
);
});
};
+ self['getNumMemorySegments'] = function() {
+ return Module['_BinaryenGetNumMemorySegments'](module);
+ }
+ self['getMemorySegmentInfoByIndex'] = function(id) {
+ return {
+ 'byteOffset': Module['_BinaryenGetMemorySegmentByteOffset'](module, id),
+ 'data': (function(){
+ var size = Module['_BinaryenGetMemorySegmentByteLength'](module, id);
+ var ptr = _malloc(size);
+ Module['_BinaryenCopyMemorySegmentData'](module, id, ptr);
+ var res = new Uint8Array(size);
+ res.set(new Uint8Array(buffer, ptr, size));
+ _free(ptr);
+ return res.buffer;
+ })()
+ };
+ }
self['setStart'] = function(start) {
return Module['_BinaryenSetStart'](module, start);
};
@@ -2110,6 +2127,18 @@ function wrapModule(module, self) {
return Module['_BinaryenAddCustomSection'](module, strToStack(name), i8sToStack(contents), contents.length);
});
};
+ self['getNumExports'] = function() {
+ return Module['_BinaryenGetNumExports'](module);
+ }
+ self['getExportByIndex'] = function(id) {
+ return Module['_BinaryenGetExportByIndex'](module, id);
+ }
+ self['getNumFunctions'] = function() {
+ return Module['_BinaryenGetNumFunctions'](module);
+ }
+ self['getFunctionByIndex'] = function(id) {
+ return Module['_BinaryenGetFunctionByIndex'](module, id);
+ }
self['emitText'] = function() {
var old = out;
var ret = '';
diff --git a/test/binaryen.js/kitchen-sink.js b/test/binaryen.js/kitchen-sink.js
index 1d955eb6f..54fa9abd8 100644
--- a/test/binaryen.js/kitchen-sink.js
+++ b/test/binaryen.js/kitchen-sink.js
@@ -887,6 +887,60 @@ function test_internals() {
console.log('sizeof Literal: ' + Binaryen['_BinaryenSizeofLiteral']());
}
+function test_for_each() {
+ module = new Binaryen.Module();
+
+ var v = module.addFunctionType("v", Binaryen.None, []);
+
+ var fns = [
+ module.addFunction("fn0", v, [], module.nop()),
+ module.addFunction("fn1", v, [], module.nop()),
+ module.addFunction("fn2", v, [], module.nop())
+ ];
+
+ var i;
+ for (i = 0 ; i < module.getNumFunctions() ; i++) {
+ assert(module.getFunctionByIndex(i) === fns[i]);
+ }
+
+ var exps = [
+ module.addFunctionExport("fn0", "export0"),
+ module.addFunctionExport("fn1", "export1"),
+ module.addFunctionExport("fn2", "export2")
+ ];
+
+ for (i = 0 ; i < module.getNumExports() ; i++) {
+ assert(module.getExportByIndex(i) === exps[i]);
+ }
+
+ var expected_offsets = [10, 125];
+ var expected_data = ["hello, world", "segment data 2"];
+
+ var global = module.addGlobal("a-global", Binaryen.i32, false, module.i32.const(expected_offsets[1]))
+ module.setMemory(1, 256, "mem", [
+ {
+ passive: false,
+ offset: module.i32.const(expected_offsets[0]),
+ data: expected_data[0].split('').map(function(x) { return x.charCodeAt(0) })
+ },
+ {
+ passive: false,
+ offset: module.global.get("a-global"),
+ data: expected_data[1].split('').map(function(x) { return x.charCodeAt(0) })
+ }
+ ], false);
+ for (i = 0 ; i < module.getNumMemorySegments() ; i++) {
+ var segment = module.getMemorySegmentInfoByIndex(i);
+ assert(expected_offsets[i] === segment.byteOffset);
+ var data8 = new Uint8Array(segment.data);
+ var str = String.fromCharCode.apply(null, data8);
+ assert(expected_data[i] === str);
+ }
+
+ console.log(module.emitText());
+ module.dispose();
+}
+
function main() {
test_types();
test_features();
@@ -899,6 +953,7 @@ function main() {
test_tracing();
test_parsing();
test_internals();
+ test_for_each();
}
main();
diff --git a/test/binaryen.js/kitchen-sink.js.txt b/test/binaryen.js/kitchen-sink.js.txt
index 87a6bc97c..ea2ff9d0c 100644
--- a/test/binaryen.js/kitchen-sink.js.txt
+++ b/test/binaryen.js/kitchen-sink.js.txt
@@ -9699,3 +9699,23 @@ module loaded from text form:
)
sizeof Literal: 24
+(module
+ (type $v (func))
+ (memory $0 1 256)
+ (data (i32.const 10) "hello, world")
+ (data (global.get $a-global) "segment data 2")
+ (global $a-global i32 (i32.const 125))
+ (export "export0" (func $fn0))
+ (export "export1" (func $fn1))
+ (export "export2" (func $fn2))
+ (export "mem" (memory $0))
+ (func $fn0 (; 0 ;) (type $v)
+ (nop)
+ )
+ (func $fn1 (; 1 ;) (type $v)
+ (nop)
+ )
+ (func $fn2 (; 2 ;) (type $v)
+ (nop)
+ )
+)
diff --git a/test/example/c-api-kitchen-sink.c b/test/example/c-api-kitchen-sink.c
index 32443a850..6848ee805 100644
--- a/test/example/c-api-kitchen-sink.c
+++ b/test/example/c-api-kitchen-sink.c
@@ -6,6 +6,7 @@
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <binaryen-c.h>
@@ -994,6 +995,59 @@ void test_color_status() {
BinaryenSetColorsEnabled(old_state);
}
+void test_for_each() {
+ uint32_t i;
+
+ BinaryenModuleRef module = BinaryenModuleCreate();
+ {
+ BinaryenFunctionTypeRef v = BinaryenAddFunctionType(module, "v", BinaryenTypeNone(), NULL, 0);
+
+ BinaryenFunctionRef fns[3] = {0};
+ fns[0] = BinaryenAddFunction(module, "fn0", v, NULL, 0, BinaryenNop(module));
+ fns[1] = BinaryenAddFunction(module, "fn1", v, NULL, 0, BinaryenNop(module));
+ fns[2] = BinaryenAddFunction(module, "fn2", v, NULL, 0, BinaryenNop(module));
+
+ for (i = 0; i < BinaryenGetNumFunctions(module) ; i++) {
+ assert(BinaryenGetFunctionByIndex(module, i) == fns[i]);
+ }
+
+ BinaryenExportRef exps[3] = {0};
+ exps[0] = BinaryenAddFunctionExport(module, "fn0", "export0");
+ exps[1] = BinaryenAddFunctionExport(module, "fn1", "export1");
+ exps[2] = BinaryenAddFunctionExport(module, "fn2", "export2");
+
+ for (i = 0; i < BinaryenGetNumExports(module) ; i++) {
+ assert(BinaryenGetExportByIndex(module, i) == exps[i]);
+ }
+
+ BinaryenAddGlobal(module, "a-global", BinaryenTypeInt32(), 0, makeInt32(module, 125));
+
+ const char* segments[] = { "hello, world", "segment data 2" };
+ int8_t segmentPassive[] = { 0, 0 };
+ BinaryenExpressionRef segmentOffsets[] = {
+ BinaryenConst(module, BinaryenLiteralInt32(10)),
+ BinaryenGlobalGet(module, "a-global", BinaryenTypeInt32())
+ };
+ BinaryenIndex segmentSizes[] = { 12, 14 };
+ BinaryenSetMemory(module, 1, 256, "mem", segments, segmentPassive, segmentOffsets, segmentSizes, 2, 0);
+
+ for (i = 0; i < BinaryenGetNumMemorySegments(module) ; i++) {
+ char out[15] = {0};
+ assert(BinaryenGetMemorySegmentByteOffset(module, i) == (0==i?10:125));
+ assert(BinaryenGetMemorySegmentByteLength(module, i) == segmentSizes[i]);
+ BinaryenCopyMemorySegmentData(module, i, &out[0]);
+ if (0 == i) {
+ assert(0 == strcmp("hello, world", &out[0]));
+ }
+ else {
+ assert(0 == strcmp("segment data 2", &out[0]));
+ }
+ }
+ }
+ BinaryenModulePrint(module);
+ BinaryenModuleDispose(module);
+}
+
int main() {
test_types();
test_features();
@@ -1005,6 +1059,7 @@ int main() {
test_nonvalid();
test_tracing();
test_color_status();
+ test_for_each();
return 0;
}
diff --git a/test/example/c-api-kitchen-sink.txt b/test/example/c-api-kitchen-sink.txt
index 25338bc42..6a8e50c91 100644
--- a/test/example/c-api-kitchen-sink.txt
+++ b/test/example/c-api-kitchen-sink.txt
@@ -6348,3 +6348,23 @@ optimized:
relooperBlocks.clear();
return 0;
}
+(module
+ (type $v (func))
+ (memory $0 1 256)
+ (data (i32.const 10) "hello, world")
+ (data (global.get $a-global) "segment data 2")
+ (global $a-global i32 (i32.const 125))
+ (export "export0" (func $fn0))
+ (export "export1" (func $fn1))
+ (export "export2" (func $fn2))
+ (export "mem" (memory $0))
+ (func $fn0 (; 0 ;) (type $v)
+ (nop)
+ )
+ (func $fn1 (; 1 ;) (type $v)
+ (nop)
+ )
+ (func $fn2 (; 2 ;) (type $v)
+ (nop)
+ )
+)