Skip to content

Commit af575d3

Browse files
committed
C/JS accessors for function table segments
module.getNumFunctionTableSegments() gives the number of segments. module.getFunctionTableSegmentInfoByIndex() yields: ``` { offset, functions: ["func1", "func2"] } ``` Another piece for WebAssembly#2370
1 parent bcc7614 commit af575d3

File tree

5 files changed

+129
-0
lines changed

5 files changed

+129
-0
lines changed

src/binaryen-c.cpp

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3561,6 +3561,89 @@ void BinaryenSetFunctionTable(BinaryenModuleRef module,
35613561
wasm->table.segments.push_back(segment);
35623562
}
35633563

3564+
// Function table segments. Query utilities.
3565+
3566+
uint32_t BinaryenGetNumFunctionTableSegments(BinaryenModuleRef module) {
3567+
if (tracing) {
3568+
std::cout << " BinaryenGetNumFunctionTableSegments(the_module);\n";
3569+
}
3570+
3571+
auto* wasm = (Module*)module;
3572+
return wasm->table.segments.size();
3573+
}
3574+
3575+
uint32_t BinaryenGetFunctionTableSegmentOffset(BinaryenModuleRef module,
3576+
BinaryenIndex id) {
3577+
if (tracing) {
3578+
std::cout << " BinaryenGetFunctionTableSegmentOffset(the_module, " << id
3579+
<< ");\n";
3580+
}
3581+
3582+
auto* wasm = (Module*)module;
3583+
if (wasm->table.segments.size() <= id) {
3584+
Fatal() << "invalid segment id.";
3585+
}
3586+
3587+
auto globalOffset = [&](const Expression* const& expr,
3588+
int64_t& result) -> bool {
3589+
if (auto* c = expr->dynCast<Const>()) {
3590+
result = c->value.getInteger();
3591+
return true;
3592+
}
3593+
return false;
3594+
};
3595+
3596+
const Table::Segment& segment = wasm->table.segments[id];
3597+
3598+
int64_t ret;
3599+
if (globalOffset(segment.offset, ret)) {
3600+
return ret;
3601+
}
3602+
if (auto* get = segment.offset->dynCast<GlobalGet>()) {
3603+
Global* global = wasm->getGlobal(get->name);
3604+
if (globalOffset(global->init, ret)) {
3605+
return ret;
3606+
}
3607+
}
3608+
3609+
Fatal() << "non-constant offsets aren't supported yet";
3610+
return 0;
3611+
}
3612+
3613+
size_t BinaryenGetFunctionTableSegmentLength(BinaryenModuleRef module,
3614+
BinaryenIndex id) {
3615+
if (tracing) {
3616+
std::cout << " BinaryenGetFunctionTableSegmentLength(the_module, " << id
3617+
<< ");\n";
3618+
}
3619+
3620+
auto* wasm = (Module*)module;
3621+
if (wasm->table.segments.size() <= id) {
3622+
Fatal() << "invalid segment id.";
3623+
}
3624+
const Table::Segment& segment = wasm->table.segments[id];
3625+
return segment.data.size();
3626+
}
3627+
3628+
const char *BinaryenGetFunctionTableSegmentEntry(BinaryenModuleRef module,
3629+
BinaryenIndex id,
3630+
size_t entry) {
3631+
if (tracing) {
3632+
std::cout << " BinaryenGetFunctionTableSegmentEntry(the_module, " << id << ", "
3633+
<< entry << ");\n";
3634+
}
3635+
3636+
auto* wasm = (Module*)module;
3637+
if (wasm->memory.segments.size() <= id) {
3638+
Fatal() << "invalid segment id.";
3639+
}
3640+
const Table::Segment& segment = wasm->table.segments[id];
3641+
if (segment.data.size() <= entry) {
3642+
Fatal() << "invalid segment entry index.";
3643+
}
3644+
return segment.data[entry].c_str();
3645+
}
3646+
35643647
// Memory. One per module
35653648

35663649
void BinaryenSetMemory(BinaryenModuleRef module,

src/binaryen-c.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1198,6 +1198,19 @@ BINARYEN_API void BinaryenSetFunctionTable(BinaryenModuleRef module,
11981198
BinaryenIndex numFuncNames,
11991199
BinaryenExpressionRef offset);
12001200

1201+
// Function table segments. Query utilities.
1202+
1203+
BINARYEN_API uint32_t
1204+
BinaryenGetNumFunctionTableSegments(BinaryenModuleRef module);
1205+
BINARYEN_API uint32_t BinaryenGetFunctionTableSegmentOffset(
1206+
BinaryenModuleRef module, BinaryenIndex id);
1207+
BINARYEN_API size_t BinaryenGetFunctionTableSegmentLength(
1208+
BinaryenModuleRef module, BinaryenIndex id);
1209+
BINARYEN_API
1210+
const char* BinaryenGetFunctionTableSegmentEntry(BinaryenModuleRef module,
1211+
BinaryenIndex id,
1212+
size_t entry);
1213+
12011214
// Memory. One per module
12021215

12031216
// Each segment has data in segments, a start offset in segmentOffsets, and a

src/js/binaryen.js-post.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2158,6 +2158,22 @@ function wrapModule(module, self) {
21582158
);
21592159
});
21602160
};
2161+
self['getNumFunctionTableSegments'] = function() {
2162+
return Module['_BinaryenGetNumFunctionTableSegments'](module);
2163+
};
2164+
self['getFunctionTableSegmentInfoByIndex'] = function(id) {
2165+
return {
2166+
'offset': Module['_BinaryenGetFunctionTableSegmentOffset'](module, id),
2167+
'functions': (function(){
2168+
var size = Module['_BinaryenGetFunctionTableSegmentLength'](module, id);
2169+
var res = new Array(size);
2170+
for (var i = 0; i < size; i++) {
2171+
res[i] = UTF8ToString(Module['_BinaryenGetFunctionTableSegmentEntry'](module, id, i));
2172+
}
2173+
return res;
2174+
})()
2175+
};
2176+
};
21612177
self['setMemory'] = function(initial, maximum, exportName, segments, shared) {
21622178
// segments are assumed to be { passive: bool, offset: expression ref, data: array of 8-bit data }
21632179
if (!segments) segments = [];

test/binaryen.js/kitchen-sink.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -966,6 +966,21 @@ function test_for_each() {
966966
assert(expected_data[i] === str);
967967
}
968968

969+
var expected_table_offsets = [0];
970+
var expected_table_functions = [
971+
['fn0', 'fn1', 'fn2']
972+
];
973+
module.setFunctionTable(3, 3, ['fn0', 'fn1', 'fn2'])
974+
assert(expected_table_offsets.length === module.getNumFunctionTableSegments());
975+
for (i = 0 ; i < module.getNumFunctionTableSegments() ; i++) {
976+
var segment = module.getFunctionTableSegmentInfoByIndex(i);
977+
assert(expected_table_offsets[i] === segment.offset);
978+
assert(expected_table_functions[i].length === segment.functions.length);
979+
for (var j = 0; j < segment.functions.length; j++) {
980+
assert(expected_table_functions[i][j] === segment.functions[j]);
981+
}
982+
}
983+
969984
console.log(module.emitText());
970985
module.dispose();
971986
}

test/binaryen.js/kitchen-sink.js.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10317,6 +10317,8 @@ sizeof Literal: 24
1031710317
(memory $0 1 256)
1031810318
(data (i32.const 10) "hello, world")
1031910319
(data (global.get $a-global) "segment data 2")
10320+
(table $0 3 3 funcref)
10321+
(elem (i32.const 0) $fn0 $fn1 $fn2)
1032010322
(global $a-global i32 (i32.const 125))
1032110323
(export "export0" (func $fn0))
1032210324
(export "export1" (func $fn1))

0 commit comments

Comments
 (0)