summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/binaryen-c.cpp59
-rw-r--r--src/binaryen-c.h10
-rw-r--r--src/js/binaryen.js-post.js21
-rw-r--r--test/binaryen.js/kitchen-sink.js32
-rw-r--r--test/binaryen.js/kitchen-sink.js.txt2
-rw-r--r--test/example/c-api-kitchen-sink.c65
-rw-r--r--test/example/c-api-kitchen-sink.txt2
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))