Skip to content

Ability to list each item on Exports/Data Segments/Functions #2386

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Oct 21, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion build-js.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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"
Expand Down Expand Up @@ -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"
Expand Down
117 changes: 117 additions & 0 deletions src/binaryen-c.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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 =========
Expand Down
22 changes: 22 additions & 0 deletions src/binaryen-c.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -1162,6 +1168,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,
Expand Down Expand Up @@ -1431,6 +1448,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 =========
Expand Down
29 changes: 29 additions & 0 deletions src/js/binaryen.js-post.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
};
Expand All @@ -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 = '';
Expand Down
55 changes: 55 additions & 0 deletions test/binaryen.js/kitchen-sink.js
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -899,6 +953,7 @@ function main() {
test_tracing();
test_parsing();
test_internals();
test_for_each();
}

main();
20 changes: 20 additions & 0 deletions test/binaryen.js/kitchen-sink.js.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
)
)
Loading