From af21eba418ee0acdc7349679b557955362be5602 Mon Sep 17 00:00:00 2001 From: COFFEETALES Date: Tue, 15 Oct 2019 15:28:34 +0200 Subject: [PATCH 01/10] Ability to list each item from Exports/Data Segments/Functions --- build-js.sh | 12 +++- src/binaryen-c.cpp | 112 +++++++++++++++++++++++++++++++++++++ src/binaryen-c.h | 23 ++++++++ src/js/binaryen.js-post.js | 29 ++++++++++ 4 files changed, 175 insertions(+), 1 deletion(-) diff --git a/build-js.sh b/build-js.sh index 37bdc00ee9f..1e0127d1ce7 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 1cb0963a239..607100f9e49 100644 --- a/src/binaryen-c.cpp +++ b/src/binaryen-c.cpp @@ -3142,6 +3142,25 @@ 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 +3597,79 @@ 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."; + ::wasm::Memory::Segment segment = wasm->memory.segments[id]; + + int64_t ret; + auto globalOffset = [&](const ::wasm::Expression* const & expr, int64_t & result) -> bool { + if (auto* c = expr->template dynCast()) { + result = c->value.getInteger(); + return true; + } + return false; + }; + + if ( globalOffset(segment.offset, ret) ) { + return ret; + } + if (auto* get = segment.offset->template dynCast()) { + ::wasm::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."; + ::wasm::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(buffer) + << ");\n"; + } + + auto* wasm = (Module*)module; + if (wasm->memory.segments.size() <= id) + Fatal() << "invalid segment id."; + ::wasm::Memory::Segment segment = wasm->memory.segments[id]; + std::copy(segment.data.begin(), segment.data.end(), buffer); +} + + + // Start function. One per module void BinaryenSetStart(BinaryenModuleRef module, BinaryenFunctionRef start) { @@ -4305,6 +4397,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 ae0a068352e..ff713da92aa 100644 --- a/src/binaryen-c.h +++ b/src/binaryen-c.h @@ -1058,6 +1058,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 @@ -1162,6 +1168,18 @@ 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, @@ -1431,6 +1449,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 7c99ded15ef..1710a9adf68 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 = allocate(size, 'i8', ALLOC_NORMAL); + 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 = ''; From fb46c0335b58a490528d59ecb9b3dd8783a2d777 Mon Sep 17 00:00:00 2001 From: COFFEETALES Date: Thu, 17 Oct 2019 01:37:29 +0200 Subject: [PATCH 02/10] js-foreach-api: several fixes and test --- src/binaryen-c.cpp | 25 +++++++++------ src/js/binaryen.js-post.js | 2 +- test/binaryen.js/kitchen-sink.js | 50 ++++++++++++++++++++++++++++++ test/example/c-api-kitchen-sink.c | 51 +++++++++++++++++++++++++++++++ 4 files changed, 117 insertions(+), 11 deletions(-) diff --git a/src/binaryen-c.cpp b/src/binaryen-c.cpp index 607100f9e49..7f170bc51d4 100644 --- a/src/binaryen-c.cpp +++ b/src/binaryen-c.cpp @@ -3157,8 +3157,9 @@ BinaryenFunctionRef BinaryenGetFunctionByIndex(BinaryenModuleRef module, Binarye } auto* wasm = (Module*)module; - if (wasm->functions.size() <= id) + if (wasm->functions.size() <= id) { Fatal() << "invalid function id."; + } return wasm->functions[id].get(); } @@ -3614,12 +3615,13 @@ int64_t BinaryenGetMemorySegmentByteOffset(BinaryenModuleRef module, BinaryenInd } auto* wasm = (Module*)module; - if (wasm->memory.segments.size() <= id) + if (wasm->memory.segments.size() <= id) { Fatal() << "invalid segment id."; - ::wasm::Memory::Segment segment = wasm->memory.segments[id]; + } + Memory::Segment segment = wasm->memory.segments[id]; int64_t ret; - auto globalOffset = [&](const ::wasm::Expression* const & expr, int64_t & result) -> bool { + auto globalOffset = [&](const Expression* const & expr, int64_t & result) -> bool { if (auto* c = expr->template dynCast()) { result = c->value.getInteger(); return true; @@ -3631,7 +3633,7 @@ int64_t BinaryenGetMemorySegmentByteOffset(BinaryenModuleRef module, BinaryenInd return ret; } if (auto* get = segment.offset->template dynCast()) { - ::wasm::Global* global = wasm->getGlobal(get->name); + Global* global = wasm->getGlobal(get->name); if ( globalOffset(global->init, ret) ) { return ret; } @@ -3647,9 +3649,10 @@ size_t BinaryenGetMemorySegmentByteLength(BinaryenModuleRef module, BinaryenInde } auto* wasm = (Module*)module; - if (wasm->memory.segments.size() <= id) + if (wasm->memory.segments.size() <= id) { Fatal() << "invalid segment id."; - ::wasm::Memory::Segment segment = wasm->memory.segments[id]; + } + Memory::Segment segment = wasm->memory.segments[id]; return segment.data.size(); } void BinaryenCopyMemorySegmentData(BinaryenModuleRef module, @@ -3662,9 +3665,10 @@ void BinaryenCopyMemorySegmentData(BinaryenModuleRef module, } auto* wasm = (Module*)module; - if (wasm->memory.segments.size() <= id) + if (wasm->memory.segments.size() <= id) { Fatal() << "invalid segment id."; - ::wasm::Memory::Segment segment = wasm->memory.segments[id]; + } + Memory::Segment segment = wasm->memory.segments[id]; std::copy(segment.data.begin(), segment.data.end(), buffer); } @@ -4412,8 +4416,9 @@ BinaryenExportRef BinaryenGetExportByIndex(BinaryenModuleRef module, BinaryenInd } auto* wasm = (Module*)module; - if (wasm->exports.size() <= id) + if (wasm->exports.size() <= id) { Fatal() << "invalid export id."; + } return wasm->exports[id].get(); } diff --git a/src/js/binaryen.js-post.js b/src/js/binaryen.js-post.js index 1710a9adf68..0da3f2df48b 100644 --- a/src/js/binaryen.js-post.js +++ b/src/js/binaryen.js-post.js @@ -2104,7 +2104,7 @@ function wrapModule(module, self) { 'byteOffset': Module['_BinaryenGetMemorySegmentByteOffset'](module, id), 'data': (function(){ var size = Module['_BinaryenGetMemorySegmentByteLength'](module, id); - var ptr = allocate(size, 'i8', ALLOC_NORMAL); + var ptr = _malloc(size); Module['_BinaryenCopyMemorySegmentData'](module, id, ptr); var res = new Uint8Array(size); res.set(new Uint8Array(buffer, ptr, size)); diff --git a/test/binaryen.js/kitchen-sink.js b/test/binaryen.js/kitchen-sink.js index 1d955eb6f42..1b17f954333 100644 --- a/test/binaryen.js/kitchen-sink.js +++ b/test/binaryen.js/kitchen-sink.js @@ -887,6 +887,55 @@ 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 fn0 = module.addFunction("fn0", v, [], module.nop()); + var fn1 = module.addFunction("fn1", v, [], module.nop()); + var fn2 = module.addFunction("fn2", v, [], module.nop()); + + var i; + for (i = 0 ; i < module.getNumFunctions() ; i++) { + assert(module.getFunctionByIndex(i) === (0===i?fn0:(1===i?fn1:fn2))); + } + + var exp0 = module.addFunctionExport("fn0", "export0"); + var exp1 = module.addFunctionExport("fn1", "export1"); + var exp2 = module.addFunctionExport("fn1", "export2"); + for (i = 0 ; i < module.getNumExports() ; i++) { + assert(module.getExportByIndex(i) === (0===i?exp0:(1===i?exp1:exp2))); + } + + var global = module.addGlobal("a-global", Binaryen.i32, false, module.i32.const(125)) + module.setMemory(1, 256, "mem", [ + { + passive: false, + offset: module.i32.const(10), + data: "hello, world".split('').map(function(x) { return x.charCodeAt(0) }) + }, + { + passive: false, + offset: module.global.get("a-global"), + data: "segment data 2".split('').map(function(x) { return x.charCodeAt(0) }) + } + ], false); + for (i = 0 ; i < module.getNumMemorySegments() ; i++) { + var segment = module.getMemorySegmentInfoByIndex(i); + assert((0===i?10:125) === segment.byteOffset); + var data8 = new Uint8Array(segment.data); + var str = String.fromCharCode.apply(null, data8); + if (0 === i) { + assert("hello, world" === str); + continue; + } + assert("segment data 2" === str); + } + + console.log(module.emitText()); + module.dispose(); +} + function main() { test_types(); test_features(); @@ -899,6 +948,7 @@ function main() { test_tracing(); test_parsing(); test_internals(); + test_for_each(); } main(); diff --git a/test/example/c-api-kitchen-sink.c b/test/example/c-api-kitchen-sink.c index 32443a85064..9834c000227 100644 --- a/test/example/c-api-kitchen-sink.c +++ b/test/example/c-api-kitchen-sink.c @@ -994,6 +994,56 @@ void test_color_status() { BinaryenSetColorsEnabled(old_state); } +void test_for_each() { + int i; + + BinaryenModuleRef module = BinaryenModuleCreate(); + { + BinaryenFunctionTypeRef v = BinaryenAddFunctionType(module, "v", BinaryenTypeNone(), NULL, 0); + BinaryenFunctionRef fn0 = BinaryenAddFunction(module, "fn0", v, NULL, 0, BinaryenNop(module)); + BinaryenFunctionRef fn1 = BinaryenAddFunction(module, "fn1", v, NULL, 0, BinaryenNop(module)); + BinaryenFunctionRef fn2 = BinaryenAddFunction(module, "fn2", v, NULL, 0, BinaryenNop(module)); + + for (i = 0; i < BinaryenGetNumFunctions(module) ; i++) { + assert(BinaryenGetFunctionByIndex(module, i) == (0==i?fn0:(1==i?fn1:fn2))); + } + + BinaryenExportRef exp0 = BinaryenAddFunctionExport(module, "fn0", "export0"); + BinaryenExportRef exp1 = BinaryenAddFunctionExport(module, "fn1", "export1"); + BinaryenExportRef exp2 = BinaryenAddFunctionExport(module, "fn2", "export2"); + + for (i = 0; i < BinaryenGetNumExports(module) ; i++) { + assert(BinaryenGetExportByIndex(module, i) == (0==i?exp0:(1==i?exp1:exp2))); + } + + 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) == (0==i?12:14)); + 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 +1055,7 @@ int main() { test_nonvalid(); test_tracing(); test_color_status(); + test_for_each(); return 0; } From 8524c63a4c0792d121dbca7bb4590473a8806cc6 Mon Sep 17 00:00:00 2001 From: COFFEETALES Date: Thu, 17 Oct 2019 02:05:51 +0200 Subject: [PATCH 03/10] js-foreach-api: Tests are now more readable --- test/binaryen.js/kitchen-sink.js | 22 ++++++++++++++-------- test/example/c-api-kitchen-sink.c | 24 ++++++++++++++---------- 2 files changed, 28 insertions(+), 18 deletions(-) diff --git a/test/binaryen.js/kitchen-sink.js b/test/binaryen.js/kitchen-sink.js index 1b17f954333..070c7bd1c0a 100644 --- a/test/binaryen.js/kitchen-sink.js +++ b/test/binaryen.js/kitchen-sink.js @@ -891,20 +891,26 @@ function test_for_each() { module = new Binaryen.Module(); var v = module.addFunctionType("v", Binaryen.None, []); - var fn0 = module.addFunction("fn0", v, [], module.nop()); - var fn1 = module.addFunction("fn1", v, [], module.nop()); - var fn2 = module.addFunction("fn2", v, [], module.nop()); + + 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) === (0===i?fn0:(1===i?fn1:fn2))); + assert(module.getFunctionByIndex(i) === fns[i]); } - var exp0 = module.addFunctionExport("fn0", "export0"); - var exp1 = module.addFunctionExport("fn1", "export1"); - var exp2 = module.addFunctionExport("fn1", "export2"); + 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) === (0===i?exp0:(1===i?exp1:exp2))); + assert(module.getExportByIndex(i) === exps[i]); } var global = module.addGlobal("a-global", Binaryen.i32, false, module.i32.const(125)) diff --git a/test/example/c-api-kitchen-sink.c b/test/example/c-api-kitchen-sink.c index 9834c000227..6848ee805a6 100644 --- a/test/example/c-api-kitchen-sink.c +++ b/test/example/c-api-kitchen-sink.c @@ -6,6 +6,7 @@ #include #include #include +#include #include @@ -995,25 +996,28 @@ void test_color_status() { } void test_for_each() { - int i; + uint32_t i; BinaryenModuleRef module = BinaryenModuleCreate(); { BinaryenFunctionTypeRef v = BinaryenAddFunctionType(module, "v", BinaryenTypeNone(), NULL, 0); - BinaryenFunctionRef fn0 = BinaryenAddFunction(module, "fn0", v, NULL, 0, BinaryenNop(module)); - BinaryenFunctionRef fn1 = BinaryenAddFunction(module, "fn1", v, NULL, 0, BinaryenNop(module)); - BinaryenFunctionRef fn2 = BinaryenAddFunction(module, "fn2", v, NULL, 0, BinaryenNop(module)); + + 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) == (0==i?fn0:(1==i?fn1:fn2))); + assert(BinaryenGetFunctionByIndex(module, i) == fns[i]); } - BinaryenExportRef exp0 = BinaryenAddFunctionExport(module, "fn0", "export0"); - BinaryenExportRef exp1 = BinaryenAddFunctionExport(module, "fn1", "export1"); - BinaryenExportRef exp2 = BinaryenAddFunctionExport(module, "fn2", "export2"); + 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) == (0==i?exp0:(1==i?exp1:exp2))); + assert(BinaryenGetExportByIndex(module, i) == exps[i]); } BinaryenAddGlobal(module, "a-global", BinaryenTypeInt32(), 0, makeInt32(module, 125)); @@ -1030,7 +1034,7 @@ void test_for_each() { for (i = 0; i < BinaryenGetNumMemorySegments(module) ; i++) { char out[15] = {0}; assert(BinaryenGetMemorySegmentByteOffset(module, i) == (0==i?10:125)); - assert(BinaryenGetMemorySegmentByteLength(module, i) == (0==i?12:14)); + assert(BinaryenGetMemorySegmentByteLength(module, i) == segmentSizes[i]); BinaryenCopyMemorySegmentData(module, i, &out[0]); if (0 == i) { assert(0 == strcmp("hello, world", &out[0])); From 51a7fab70f3d64a7caffadfd538d243fd9065800 Mon Sep 17 00:00:00 2001 From: COFFEETALES Date: Thu, 17 Oct 2019 14:11:06 +0200 Subject: [PATCH 04/10] js-foreach-api: clang-format on binaryen-c.cpp --- src/binaryen-c.cpp | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/src/binaryen-c.cpp b/src/binaryen-c.cpp index 7f170bc51d4..76fa18fc081 100644 --- a/src/binaryen-c.cpp +++ b/src/binaryen-c.cpp @@ -3150,10 +3150,10 @@ uint32_t BinaryenGetNumFunctions(BinaryenModuleRef module) { auto* wasm = (Module*)module; return wasm->functions.size(); } -BinaryenFunctionRef BinaryenGetFunctionByIndex(BinaryenModuleRef module, BinaryenIndex id) { +BinaryenFunctionRef BinaryenGetFunctionByIndex(BinaryenModuleRef module, + BinaryenIndex id) { if (tracing) { - std::cout << " BinaryenGetFunctionByIndex(the_module, " << id - << ");\n"; + std::cout << " BinaryenGetFunctionByIndex(the_module, " << id << ");\n"; } auto* wasm = (Module*)module; @@ -3608,7 +3608,8 @@ uint32_t BinaryenGetNumMemorySegments(BinaryenModuleRef module) { auto* wasm = (Module*)module; return wasm->memory.segments.size(); } -int64_t BinaryenGetMemorySegmentByteOffset(BinaryenModuleRef module, BinaryenIndex id) { +int64_t BinaryenGetMemorySegmentByteOffset(BinaryenModuleRef module, + BinaryenIndex id) { if (tracing) { std::cout << " BinaryenGetMemorySegmentByteOffset(the_module, " << id << ");\n"; @@ -3621,7 +3622,8 @@ int64_t BinaryenGetMemorySegmentByteOffset(BinaryenModuleRef module, BinaryenInd Memory::Segment segment = wasm->memory.segments[id]; int64_t ret; - auto globalOffset = [&](const Expression* const & expr, int64_t & result) -> bool { + auto globalOffset = [&](const Expression* const& expr, + int64_t& result) -> bool { if (auto* c = expr->template dynCast()) { result = c->value.getInteger(); return true; @@ -3629,12 +3631,12 @@ int64_t BinaryenGetMemorySegmentByteOffset(BinaryenModuleRef module, BinaryenInd return false; }; - if ( globalOffset(segment.offset, ret) ) { + if (globalOffset(segment.offset, ret)) { return ret; } if (auto* get = segment.offset->template dynCast()) { Global* global = wasm->getGlobal(get->name); - if ( globalOffset(global->init, ret) ) { + if (globalOffset(global->init, ret)) { return ret; } } @@ -3642,7 +3644,8 @@ int64_t BinaryenGetMemorySegmentByteOffset(BinaryenModuleRef module, BinaryenInd Fatal() << "non-constant offsets aren't supported yet"; return 0; } -size_t BinaryenGetMemorySegmentByteLength(BinaryenModuleRef module, BinaryenIndex id) { +size_t BinaryenGetMemorySegmentByteLength(BinaryenModuleRef module, + BinaryenIndex id) { if (tracing) { std::cout << " BinaryenGetMemorySegmentByteLength(the_module, " << id << ");\n"; @@ -3659,9 +3662,8 @@ void BinaryenCopyMemorySegmentData(BinaryenModuleRef module, BinaryenIndex id, char* buffer) { if (tracing) { - std::cout << " BinaryenCopyMemorySegmentData(the_module, " << id - << ", " << static_cast(buffer) - << ");\n"; + std::cout << " BinaryenCopyMemorySegmentData(the_module, " << id << ", " + << static_cast(buffer) << ");\n"; } auto* wasm = (Module*)module; @@ -3672,8 +3674,6 @@ void BinaryenCopyMemorySegmentData(BinaryenModuleRef module, std::copy(segment.data.begin(), segment.data.end(), buffer); } - - // Start function. One per module void BinaryenSetStart(BinaryenModuleRef module, BinaryenFunctionRef start) { @@ -4409,10 +4409,10 @@ uint32_t BinaryenGetNumExports(BinaryenModuleRef module) { auto* wasm = (Module*)module; return wasm->exports.size(); } -BinaryenExportRef BinaryenGetExportByIndex(BinaryenModuleRef module, BinaryenIndex id) { +BinaryenExportRef BinaryenGetExportByIndex(BinaryenModuleRef module, + BinaryenIndex id) { if (tracing) { - std::cout << " BinaryenGetExportByIndex(the_module, " << id - << ");\n"; + std::cout << " BinaryenGetExportByIndex(the_module, " << id << ");\n"; } auto* wasm = (Module*)module; @@ -4422,7 +4422,6 @@ BinaryenExportRef BinaryenGetExportByIndex(BinaryenModuleRef module, BinaryenInd return wasm->exports[id].get(); } - // // ========= Custom sections ========= // From f33b40e372a494e10e91c7b324d76555911665dc Mon Sep 17 00:00:00 2001 From: COFFEETALES Date: Thu, 17 Oct 2019 15:44:39 +0200 Subject: [PATCH 05/10] js-foreach-api: build passes --- src/binaryen-c.h | 13 ++++++------- test/example/c-api-kitchen-sink.txt | 20 ++++++++++++++++++++ 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/src/binaryen-c.h b/src/binaryen-c.h index ff713da92aa..0488ececa48 100644 --- a/src/binaryen-c.h +++ b/src/binaryen-c.h @@ -1061,8 +1061,8 @@ BINARYEN_API void BinaryenRemoveFunction(BinaryenModuleRef module, // 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); +BINARYEN_API BinaryenFunctionRef +BinaryenGetFunctionByIndex(BinaryenModuleRef module, BinaryenIndex id); // Imports @@ -1171,15 +1171,14 @@ BINARYEN_API void BinaryenSetMemory(BinaryenModuleRef module, // Memory segments. Query utilities. BINARYEN_API uint32_t BinaryenGetNumMemorySegments(BinaryenModuleRef module); -BINARYEN_API int64_t BinaryenGetMemorySegmentByteOffset(BinaryenModuleRef module, - BinaryenIndex id); +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, @@ -1452,8 +1451,8 @@ 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); +BINARYEN_API BinaryenExportRef +BinaryenGetExportByIndex(BinaryenModuleRef module, BinaryenIndex id); // // ========= Custom sections ========= diff --git a/test/example/c-api-kitchen-sink.txt b/test/example/c-api-kitchen-sink.txt index 25338bc423c..6a8e50c91c5 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) + ) +) From 317e67cc0c9bf93191eda202731da0545a4af245 Mon Sep 17 00:00:00 2001 From: COFFEETALES Date: Thu, 17 Oct 2019 15:50:57 +0200 Subject: [PATCH 06/10] js-foreach-api: build passes 2 --- test/binaryen.js/kitchen-sink.js.txt | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/test/binaryen.js/kitchen-sink.js.txt b/test/binaryen.js/kitchen-sink.js.txt index 87a6bc97c80..ea2ff9d0ce0 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) + ) +) From 631260933fabe29f789a01f75987f91589ac432b Mon Sep 17 00:00:00 2001 From: COFFEETALES Date: Thu, 17 Oct 2019 20:12:44 +0200 Subject: [PATCH 07/10] js-foreach-api: improved readability on kitchen-sink.js --- test/binaryen.js/kitchen-sink.js | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/test/binaryen.js/kitchen-sink.js b/test/binaryen.js/kitchen-sink.js index 070c7bd1c0a..54fa9abd8db 100644 --- a/test/binaryen.js/kitchen-sink.js +++ b/test/binaryen.js/kitchen-sink.js @@ -913,29 +913,28 @@ function test_for_each() { assert(module.getExportByIndex(i) === exps[i]); } - var global = module.addGlobal("a-global", Binaryen.i32, false, module.i32.const(125)) + 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(10), - data: "hello, world".split('').map(function(x) { return x.charCodeAt(0) }) + 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: "segment data 2".split('').map(function(x) { return x.charCodeAt(0) }) + 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((0===i?10:125) === segment.byteOffset); + assert(expected_offsets[i] === segment.byteOffset); var data8 = new Uint8Array(segment.data); var str = String.fromCharCode.apply(null, data8); - if (0 === i) { - assert("hello, world" === str); - continue; - } - assert("segment data 2" === str); + assert(expected_data[i] === str); } console.log(module.emitText()); From 1733581dee3f3bc28216b81fb7504502a6b55221 Mon Sep 17 00:00:00 2001 From: COFFEETALES Date: Thu, 17 Oct 2019 22:23:14 +0200 Subject: [PATCH 08/10] js-foreach-api: cref instead of variable copy --- src/binaryen-c.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/binaryen-c.cpp b/src/binaryen-c.cpp index 76fa18fc081..4ffb2a58676 100644 --- a/src/binaryen-c.cpp +++ b/src/binaryen-c.cpp @@ -3619,22 +3619,22 @@ int64_t BinaryenGetMemorySegmentByteOffset(BinaryenModuleRef module, if (wasm->memory.segments.size() <= id) { Fatal() << "invalid segment id."; } - Memory::Segment segment = wasm->memory.segments[id]; int64_t ret; auto globalOffset = [&](const Expression* const& expr, int64_t& result) -> bool { - if (auto* c = expr->template dynCast()) { + if (auto* c = expr->dynCast()) { result = c->value.getInteger(); return true; } return false; }; + const Memory::Segment & segment = wasm->memory.segments[id]; if (globalOffset(segment.offset, ret)) { return ret; } - if (auto* get = segment.offset->template dynCast()) { + if (auto* get = segment.offset->dynCast()) { Global* global = wasm->getGlobal(get->name); if (globalOffset(global->init, ret)) { return ret; @@ -3655,7 +3655,7 @@ size_t BinaryenGetMemorySegmentByteLength(BinaryenModuleRef module, if (wasm->memory.segments.size() <= id) { Fatal() << "invalid segment id."; } - Memory::Segment segment = wasm->memory.segments[id]; + const Memory::Segment & segment = wasm->memory.segments[id]; return segment.data.size(); } void BinaryenCopyMemorySegmentData(BinaryenModuleRef module, @@ -3670,8 +3670,8 @@ void BinaryenCopyMemorySegmentData(BinaryenModuleRef module, if (wasm->memory.segments.size() <= id) { Fatal() << "invalid segment id."; } - Memory::Segment segment = wasm->memory.segments[id]; - std::copy(segment.data.begin(), segment.data.end(), buffer); + const Memory::Segment & segment = wasm->memory.segments[id]; + std::copy(segment.data.cbegin(), segment.data.cend(), buffer); } // Start function. One per module From 36bc95efa59f505fddacd33131a7375f0d0a85d0 Mon Sep 17 00:00:00 2001 From: COFFEETALES Date: Thu, 17 Oct 2019 23:19:55 +0200 Subject: [PATCH 09/10] js-foreach-api: cref instead of variable copy (fix) --- src/binaryen-c.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/binaryen-c.cpp b/src/binaryen-c.cpp index 4ffb2a58676..e10fa69ecda 100644 --- a/src/binaryen-c.cpp +++ b/src/binaryen-c.cpp @@ -3630,7 +3630,7 @@ int64_t BinaryenGetMemorySegmentByteOffset(BinaryenModuleRef module, return false; }; - const Memory::Segment & segment = wasm->memory.segments[id]; + const Memory::Segment& segment = wasm->memory.segments[id]; if (globalOffset(segment.offset, ret)) { return ret; } @@ -3655,7 +3655,7 @@ size_t BinaryenGetMemorySegmentByteLength(BinaryenModuleRef module, if (wasm->memory.segments.size() <= id) { Fatal() << "invalid segment id."; } - const Memory::Segment & segment = wasm->memory.segments[id]; + const Memory::Segment& segment = wasm->memory.segments[id]; return segment.data.size(); } void BinaryenCopyMemorySegmentData(BinaryenModuleRef module, @@ -3670,7 +3670,7 @@ void BinaryenCopyMemorySegmentData(BinaryenModuleRef module, if (wasm->memory.segments.size() <= id) { Fatal() << "invalid segment id."; } - const Memory::Segment & segment = wasm->memory.segments[id]; + const Memory::Segment& segment = wasm->memory.segments[id]; std::copy(segment.data.cbegin(), segment.data.cend(), buffer); } From 700c03c33b7fa3d82b743afe7f120f5ec7a942c8 Mon Sep 17 00:00:00 2001 From: COFFEETALES Date: Mon, 21 Oct 2019 22:40:25 +0200 Subject: [PATCH 10/10] js-foreach-api: variable ret moved --- src/binaryen-c.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/binaryen-c.cpp b/src/binaryen-c.cpp index e10fa69ecda..6bb6f6e1415 100644 --- a/src/binaryen-c.cpp +++ b/src/binaryen-c.cpp @@ -3620,7 +3620,6 @@ int64_t BinaryenGetMemorySegmentByteOffset(BinaryenModuleRef module, Fatal() << "invalid segment id."; } - int64_t ret; auto globalOffset = [&](const Expression* const& expr, int64_t& result) -> bool { if (auto* c = expr->dynCast()) { @@ -3631,6 +3630,8 @@ int64_t BinaryenGetMemorySegmentByteOffset(BinaryenModuleRef module, }; const Memory::Segment& segment = wasm->memory.segments[id]; + + int64_t ret; if (globalOffset(segment.offset, ret)) { return ret; }