diff options
-rw-r--r-- | src/binaryen-c.cpp | 59 | ||||
-rw-r--r-- | src/binaryen-c.h | 10 | ||||
-rw-r--r-- | src/js/binaryen.js-post.js | 21 | ||||
-rw-r--r-- | test/binaryen.js/kitchen-sink.js | 32 | ||||
-rw-r--r-- | test/binaryen.js/kitchen-sink.js.txt | 2 | ||||
-rw-r--r-- | test/example/c-api-kitchen-sink.c | 65 | ||||
-rw-r--r-- | test/example/c-api-kitchen-sink.txt | 2 |
7 files changed, 156 insertions, 35 deletions
diff --git a/src/binaryen-c.cpp b/src/binaryen-c.cpp index fc16eee42..b9ac3abf9 100644 --- a/src/binaryen-c.cpp +++ b/src/binaryen-c.cpp @@ -3561,6 +3561,65 @@ void BinaryenSetFunctionTable(BinaryenModuleRef module, wasm->table.segments.push_back(segment); } +int BinaryenIsFunctionTableImported(BinaryenModuleRef module) { + if (tracing) { + std::cout << " BinaryenIsFunctionTableImported(the_module);\n"; + } + + auto* wasm = (Module*)module; + return wasm->table.imported(); +} +BinaryenIndex BinaryenGetNumFunctionTableSegments(BinaryenModuleRef module) { + if (tracing) { + std::cout << " BinaryenGetNumFunctionTableSegments(the_module);\n"; + } + + auto* wasm = (Module*)module; + return wasm->table.segments.size(); +} +BinaryenExpressionRef +BinaryenGetFunctionTableSegmentOffset(BinaryenModuleRef module, + BinaryenIndex segmentId) { + if (tracing) { + std::cout << " BinaryenGetFunctionTableSegmentOffset(the_module, " + << segmentId << ");\n"; + } + + auto* wasm = (Module*)module; + if (wasm->table.segments.size() <= segmentId) { + Fatal() << "invalid function table segment id."; + } + return wasm->table.segments[segmentId].offset; +} +BinaryenIndex BinaryenGetFunctionTableSegmentLength(BinaryenModuleRef module, + BinaryenIndex segmentId) { + if (tracing) { + std::cout << " BinaryenGetFunctionTableSegmentLength(the_module, " + << segmentId << ");\n"; + } + + auto* wasm = (Module*)module; + if (wasm->table.segments.size() <= segmentId) { + Fatal() << "invalid function table segment id."; + } + return wasm->table.segments[segmentId].data.size(); +} +const char* BinaryenGetFunctionTableSegmentData(BinaryenModuleRef module, + BinaryenIndex segmentId, + BinaryenIndex dataId) { + if (tracing) { + std::cout << " BinaryenGetFunctionTableSegmentData(the_module, " + << segmentId << ", " << dataId << ");\n"; + } + + auto* wasm = (Module*)module; + if (wasm->table.segments.size() <= segmentId || + wasm->table.segments[segmentId].data.size() <= dataId) { + Fatal() << "invalid function table segment or data id."; + } + return wasm->table.segments[segmentId].data[dataId].c_str(); +} + // Memory. One per module void BinaryenSetMemory(BinaryenModuleRef module, diff --git a/src/binaryen-c.h b/src/binaryen-c.h index 39e0aca33..fa6398fea 100644 --- a/src/binaryen-c.h +++ b/src/binaryen-c.h @@ -1191,12 +1191,22 @@ BINARYEN_API void BinaryenRemoveEvent(BinaryenModuleRef module, // Function table. One per module +// TODO: Add support for multiple segments in BinaryenSetFunctionTable. BINARYEN_API void BinaryenSetFunctionTable(BinaryenModuleRef module, BinaryenIndex initial, BinaryenIndex maximum, const char** funcNames, BinaryenIndex numFuncNames, BinaryenExpressionRef offset); +BINARYEN_API int BinaryenIsFunctionTableImported(BinaryenModuleRef module); +BINARYEN_API BinaryenIndex +BinaryenGetNumFunctionTableSegments(BinaryenModuleRef module); +BINARYEN_API BinaryenExpressionRef BinaryenGetFunctionTableSegmentOffset( + BinaryenModuleRef module, BinaryenIndex segmentId); +BINARYEN_API BinaryenIndex BinaryenGetFunctionTableSegmentLength( + BinaryenModuleRef module, BinaryenIndex segmentId); +BINARYEN_API const char* BinaryenGetFunctionTableSegmentData( + BinaryenModuleRef module, BinaryenIndex segmentId, BinaryenIndex dataId); // Memory. One per module diff --git a/src/js/binaryen.js-post.js b/src/js/binaryen.js-post.js index 3ef19fd7d..33f94939e 100644 --- a/src/js/binaryen.js-post.js +++ b/src/js/binaryen.js-post.js @@ -2177,6 +2177,23 @@ function wrapModule(module, self) { ); }); }; + self['getFunctionTable'] = function() { + return { + 'imported': Boolean(Module['_BinaryenIsFunctionTableImported'](module)), + 'segments': (function() { + var arr = []; + for (var i = 0, numSegments = Module['_BinaryenGetNumFunctionTableSegments'](module); i !== numSegments; ++i) { + var seg = {'offset': Module['_BinaryenGetFunctionTableSegmentOffset'](module, i), 'names': []}; + for (var j = 0, segmentLength = Module['_BinaryenGetFunctionTableSegmentLength'](module, i); j !== segmentLength; ++j) { + var ptr = Module['_BinaryenGetFunctionTableSegmentData'](module, i, j); + seg['names'].push(UTF8ToString(ptr)); + } + arr.push(seg); + } + return arr; + })() + }; + }; self['setMemory'] = function(initial, maximum, exportName, segments, shared) { // segments are assumed to be { passive: bool, offset: expression ref, data: array of 8-bit data } if (!segments) segments = []; @@ -2511,7 +2528,7 @@ Module['getExpressionInfo'] = function(expr) { var tempBuffer = stackAlloc(16); Module['_BinaryenConstGetValueV128'](expr, tempBuffer); value = new Array(16); - for (var i = 0 ; i < 16; i++) { + for (var i = 0; i < 16; i++) { value[i] = HEAPU8[tempBuffer + i]; } }); @@ -2639,7 +2656,7 @@ Module['getExpressionInfo'] = function(expr) { var tempBuffer = stackAlloc(16); Module['_BinaryenSIMDShuffleGetMask'](expr, tempBuffer); var mask = new Array(16); - for (var i = 0 ; i < 16; i++) { + for (var i = 0; i < 16; i++) { mask[i] = HEAPU8[tempBuffer + i]; } return { diff --git a/test/binaryen.js/kitchen-sink.js b/test/binaryen.js/kitchen-sink.js index fd951814c..95865566a 100644 --- a/test/binaryen.js/kitchen-sink.js +++ b/test/binaryen.js/kitchen-sink.js @@ -917,24 +917,26 @@ function test_internals() { function test_for_each() { module = new binaryen.Module(); + var funcNames = [ "fn0", "fn1", "fn2" ]; + var fns = [ - module.addFunction("fn0", binaryen.none, binaryen.none, [], module.nop()), - module.addFunction("fn1", binaryen.none, binaryen.none, [], module.nop()), - module.addFunction("fn2", binaryen.none, binaryen.none, [], module.nop()) + module.addFunction(funcNames[0], binaryen.none, binaryen.none, [], module.nop()), + module.addFunction(funcNames[1], binaryen.none, binaryen.none, [], module.nop()), + module.addFunction(funcNames[2], binaryen.none, binaryen.none, [], module.nop()) ]; var i; - for (i = 0 ; i < module.getNumFunctions() ; 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") + module.addFunctionExport(funcNames[0], "export0"), + module.addFunctionExport(funcNames[1], "export1"), + module.addFunctionExport(funcNames[2], "export2") ]; - for (i = 0 ; i < module.getNumExports() ; i++) { + for (i = 0; i < module.getNumExports(); i++) { assert(module.getExportByIndex(i) === exps[i]); } @@ -955,7 +957,7 @@ function test_for_each() { data: expected_data[1].split('').map(function(x) { return x.charCodeAt(0) }) } ], false); - for (i = 0 ; i < module.getNumMemorySegments() ; i++) { + for (i = 0; i < module.getNumMemorySegments(); i++) { var segment = module.getMemorySegmentInfoByIndex(i); assert(expected_offsets[i] === segment.offset); var data8 = new Uint8Array(segment.data); @@ -964,6 +966,18 @@ function test_for_each() { assert(expected_passive[i] === segment.passive); } + var constExprRef = module.i32.const(0); + module.setFunctionTable(1, 0xffffffff, funcNames, constExprRef); + + var ftable = module.getFunctionTable(); + assert(false === ftable.imported); + assert(1 === ftable.segments.length); + assert(constExprRef === ftable.segments[0].offset); + assert(3 === ftable.segments[0].names.length); + for (i = 0; i < ftable.segments[0].names.length; i++) { + assert(funcNames[i] === ftable.segments[0].names[i]); + } + console.log(module.emitText()); module.dispose(); } diff --git a/test/binaryen.js/kitchen-sink.js.txt b/test/binaryen.js/kitchen-sink.js.txt index c86b276d5..00e5710a9 100644 --- a/test/binaryen.js/kitchen-sink.js.txt +++ b/test/binaryen.js/kitchen-sink.js.txt @@ -10317,6 +10317,8 @@ sizeof Literal: 24 (memory $0 1 256) (data (i32.const 10) "hello, world") (data (global.get $a-global) "segment data 2") + (table $0 1 funcref) + (elem (i32.const 0) $fn0 $fn1 $fn2) (global $a-global i32 (i32.const 125)) (export "export0" (func $fn0)) (export "export1" (func $fn1)) diff --git a/test/example/c-api-kitchen-sink.c b/test/example/c-api-kitchen-sink.c index 6d56ccf44..67f7e0642 100644 --- a/test/example/c-api-kitchen-sink.c +++ b/test/example/c-api-kitchen-sink.c @@ -1225,33 +1225,32 @@ void test_color_status() { } void test_for_each() { - uint32_t i; + BinaryenIndex i; BinaryenModuleRef module = BinaryenModuleCreate(); + BinaryenFunctionRef fns[3] = {}; + fns[0] = BinaryenAddFunction(module, + "fn0", + BinaryenTypeNone(), + BinaryenTypeNone(), + NULL, + 0, + BinaryenNop(module)); + fns[1] = BinaryenAddFunction(module, + "fn1", + BinaryenTypeNone(), + BinaryenTypeNone(), + NULL, + 0, + BinaryenNop(module)); + fns[2] = BinaryenAddFunction(module, + "fn2", + BinaryenTypeNone(), + BinaryenTypeNone(), + NULL, + 0, + BinaryenNop(module)); { - BinaryenFunctionRef fns[3] = {0}; - fns[0] = BinaryenAddFunction(module, - "fn0", - BinaryenTypeNone(), - BinaryenTypeNone(), - NULL, - 0, - BinaryenNop(module)); - fns[1] = BinaryenAddFunction(module, - "fn1", - BinaryenTypeNone(), - BinaryenTypeNone(), - NULL, - 0, - BinaryenNop(module)); - fns[2] = BinaryenAddFunction(module, - "fn2", - BinaryenTypeNone(), - BinaryenTypeNone(), - NULL, - 0, - BinaryenNop(module)); - for (i = 0; i < BinaryenGetNumFunctions(module) ; i++) { assert(BinaryenGetFunctionByIndex(module, i) == fns[i]); } @@ -1285,6 +1284,24 @@ void test_for_each() { assert(0 == strcmp(segments[i], out)); } } + { + const char* funcNames[] = { + BinaryenFunctionGetName(fns[0]), + BinaryenFunctionGetName(fns[1]), + BinaryenFunctionGetName(fns[2]) + }; + BinaryenExpressionRef constExprRef = BinaryenConst(module, BinaryenLiteralInt32(0)); + BinaryenSetFunctionTable(module, 1, 1, funcNames, 3, constExprRef); + assert(0 == BinaryenIsFunctionTableImported(module)); + assert(1 == BinaryenGetNumFunctionTableSegments(module)); + assert(constExprRef == BinaryenGetFunctionTableSegmentOffset(module, 0)); + assert(3 == BinaryenGetFunctionTableSegmentLength(module, 0)); + for (i = 0; i != BinaryenGetFunctionTableSegmentLength(module, 0); ++i) + { + const char * str = BinaryenGetFunctionTableSegmentData(module, 0, i); + assert(0 == strcmp(funcNames[i], str)); + } + } BinaryenModulePrint(module); BinaryenModuleDispose(module); } diff --git a/test/example/c-api-kitchen-sink.txt b/test/example/c-api-kitchen-sink.txt index b64aeefc7..1d3ee1dc2 100644 --- a/test/example/c-api-kitchen-sink.txt +++ b/test/example/c-api-kitchen-sink.txt @@ -6749,6 +6749,8 @@ validation: 0 (memory $0 1 256) (data (i32.const 10) "hello, world") (data (global.get $a-global) "segment data 2") + (table $0 1 1 funcref) + (elem (i32.const 0) $fn0 $fn1 $fn2) (global $a-global i32 (i32.const 125)) (export "export0" (func $fn0)) (export "export1" (func $fn1)) |