Skip to content

Commit 2994ff6

Browse files
committed
feat(C & JS API): Implement BinaryenDataSegmentRef
1 parent 8f96cbd commit 2994ff6

File tree

6 files changed

+112
-83
lines changed

6 files changed

+112
-83
lines changed

CHANGELOG.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,12 @@ full changeset diff at the end of each section.
1414

1515
Current Trunk
1616
-------------
17+
- Add a `BinaryenDataSegmentRef` type to the C API. (#8286)
18+
- Add `BinaryenGetMemorySegment` and `BinaryenGetMemorySegmentByIndex` to the C API, which allow looking up a memory segment by name or index.
19+
- Add `BinaryenGetMemorySegmentName` to the C API, which allows looking up a memory segment's name.
20+
- Convert `BinaryenGetMemorySegmentByteOffset`, `BinaryenGetMemorySegmentByteLength`, `BinaryenGetMemorySegmentPassive` and `BinaryenCopyMemorySegmentData` to take a `BinaryenDataSegmentRef` instead of a name.
21+
- Add `module.getMemorySegment`, `module.getMemorySegmentByIndex` to the JS API, which allows looking up a memory segment by name or index.
22+
- Convert `module.getMemorySegmentInfo` to take a memory segment reference instead of a name, and return the name as part of the info.
1723
- The emscripten build of binaryen no longer targets pure JS (via wasm2js) by
1824
default. This allows us to enable WASM_BIGINT and other features that
1925
wasm2js does not support. There is now just a single binaryen_js target. It
@@ -59,8 +65,6 @@ v126
5965
`BinaryenMemoryOrder` param. The functions formerly implicitly used
6066
`BinaryenMemoryOrderSeqCst()`. In JS this param is optional and thus not
6167
breaking.
62-
- Add `BinaryenHasMemorySegment(<module>, <name>)` to the C API and
63-
`module.hasMemorySegment(name)` to the JS API. Allowing users to check if a segment exists.
6468

6569
v125
6670
----

src/binaryen-c.cpp

Lines changed: 25 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -5487,17 +5487,24 @@ void BinaryenSetMemory(BinaryenModuleRef module,
54875487
uint32_t BinaryenGetNumMemorySegments(BinaryenModuleRef module) {
54885488
return ((Module*)module)->dataSegments.size();
54895489
}
5490-
bool BinaryenHasMemorySegment(BinaryenModuleRef module,
5491-
const char* segmentName) {
5492-
return (Module*)module->getDataSegmentOrNull(Name(segmentName)) != NULL;
5490+
BinaryenDataSegmentRef BinaryenGetMemorySegment(BinaryenModuleRef module,
5491+
const char* segmentName) {
5492+
return ((Module*)module)->getDataSegmentOrNull(Name(segmentName));
5493+
}
5494+
BinaryenDataSegmentRef BinaryenGetMemorySegmentByIndex(BinaryenModuleRef module,
5495+
BinaryenIndex index) {
5496+
const auto& dataSegments = ((Module*)module)->dataSegments;
5497+
if (dataSegments.size() <= index) {
5498+
Fatal() << "invalid memory segment index.";
5499+
}
5500+
return dataSegments[index].get();
5501+
}
5502+
const char* BinaryenGetMemorySegmentName(BinaryenDataSegmentRef segment) {
5503+
return ((DataSegment*)segment)->name.str.data();
54935504
}
54945505
uint32_t BinaryenGetMemorySegmentByteOffset(BinaryenModuleRef module,
5495-
const char* segmentName) {
5506+
BinaryenDataSegmentRef segment) {
54965507
auto* wasm = (Module*)module;
5497-
const auto* segment = wasm->getDataSegmentOrNull(Name(segmentName));
5498-
if (segment == NULL) {
5499-
Fatal() << "invalid segment name.";
5500-
}
55015508

55025509
auto globalOffset = [&](const Expression* const& expr,
55035510
int64_t& result) -> bool {
@@ -5509,10 +5516,10 @@ uint32_t BinaryenGetMemorySegmentByteOffset(BinaryenModuleRef module,
55095516
};
55105517

55115518
int64_t ret;
5512-
if (globalOffset(segment->offset, ret)) {
5519+
if (globalOffset(((DataSegment*)segment)->offset, ret)) {
55135520
return ret;
55145521
}
5515-
if (auto* get = segment->offset->dynCast<GlobalGet>()) {
5522+
if (auto* get = ((DataSegment*)segment)->offset->dynCast<GlobalGet>()) {
55165523
Global* global = wasm->getGlobal(get->name);
55175524
if (globalOffset(global->init, ret)) {
55185525
return ret;
@@ -5613,33 +5620,17 @@ bool BinaryenMemoryIs64(BinaryenModuleRef module, const char* name) {
56135620
}
56145621
return memory->is64();
56155622
}
5616-
size_t BinaryenGetMemorySegmentByteLength(BinaryenModuleRef module,
5617-
const char* segmentName) {
5618-
auto* wasm = (Module*)module;
5619-
const auto* segment = wasm->getDataSegmentOrNull(Name(segmentName));
5620-
if (segment == NULL) {
5621-
Fatal() << "invalid segment name.";
5622-
}
5623-
return segment->data.size();
5623+
size_t BinaryenGetMemorySegmentByteLength(BinaryenDataSegmentRef segment) {
5624+
return ((DataSegment*)segment)->data.size();
56245625
}
5625-
bool BinaryenGetMemorySegmentPassive(BinaryenModuleRef module,
5626-
const char* segmentName) {
5627-
auto* wasm = (Module*)module;
5628-
const auto* segment = wasm->getDataSegmentOrNull(Name(segmentName));
5629-
if (segment == NULL) {
5630-
Fatal() << "invalid segment name.";
5631-
}
5632-
return segment->isPassive;
5626+
bool BinaryenGetMemorySegmentPassive(BinaryenDataSegmentRef segment) {
5627+
return ((DataSegment*)segment)->isPassive;
56335628
}
5634-
void BinaryenCopyMemorySegmentData(BinaryenModuleRef module,
5635-
const char* segmentName,
5629+
void BinaryenCopyMemorySegmentData(BinaryenDataSegmentRef segment,
56365630
char* buffer) {
5637-
auto* wasm = (Module*)module;
5638-
const auto* segment = wasm->getDataSegmentOrNull(Name(segmentName));
5639-
if (segment == NULL) {
5640-
Fatal() << "invalid segment name.";
5641-
}
5642-
std::copy(segment->data.cbegin(), segment->data.cend(), buffer);
5631+
std::copy(((DataSegment*)segment)->data.cbegin(),
5632+
((DataSegment*)segment)->data.cend(),
5633+
buffer);
56435634
}
56445635
void BinaryenAddDataSegment(BinaryenModuleRef module,
56455636
const char* segmentName,

src/binaryen-c.h

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3003,17 +3003,22 @@ BINARYEN_API bool BinaryenMemoryIs64(BinaryenModuleRef module,
30033003

30043004
// Memory segments. Query utilities.
30053005

3006+
BINARYEN_REF(DataSegment);
3007+
30063008
BINARYEN_API uint32_t BinaryenGetNumMemorySegments(BinaryenModuleRef module);
3007-
BINARYEN_API bool BinaryenHasMemorySegment(BinaryenModuleRef module,
3008-
const char* segmentName);
3009+
BINARYEN_API BinaryenDataSegmentRef
3010+
BinaryenGetMemorySegment(BinaryenModuleRef module, const char* segmentName);
3011+
BINARYEN_API BinaryenDataSegmentRef
3012+
BinaryenGetMemorySegmentByIndex(BinaryenModuleRef module, BinaryenIndex index);
3013+
BINARYEN_API const char*
3014+
BinaryenGetMemorySegmentName(BinaryenDataSegmentRef segment);
30093015
BINARYEN_API uint32_t BinaryenGetMemorySegmentByteOffset(
3010-
BinaryenModuleRef module, const char* segmentName);
3011-
BINARYEN_API size_t BinaryenGetMemorySegmentByteLength(BinaryenModuleRef module,
3012-
const char* segmentName);
3013-
BINARYEN_API bool BinaryenGetMemorySegmentPassive(BinaryenModuleRef module,
3014-
const char* segmentName);
3015-
BINARYEN_API void BinaryenCopyMemorySegmentData(BinaryenModuleRef module,
3016-
const char* segmentName,
3016+
BinaryenModuleRef module, BinaryenDataSegmentRef segment);
3017+
BINARYEN_API size_t
3018+
BinaryenGetMemorySegmentByteLength(BinaryenDataSegmentRef segment);
3019+
BINARYEN_API bool
3020+
BinaryenGetMemorySegmentPassive(BinaryenDataSegmentRef segment);
3021+
BINARYEN_API void BinaryenCopyMemorySegmentData(BinaryenDataSegmentRef segment,
30173022
char* buffer);
30183023
BINARYEN_API void BinaryenAddDataSegment(BinaryenModuleRef module,
30193024
const char* segmentName,

src/js/binaryen.js-post.js

Lines changed: 49 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2773,34 +2773,57 @@ function wrapModule(module, self = {}) {
27732773
return Module['_BinaryenGetNumMemorySegments'](module);
27742774
};
27752775
/**
2776-
* Determines wether a memory segment with the given name exists within the given module.
2777-
* @param {string} name - The name of the memory segment to check exists.
2778-
* @returns `true` if the memory segment exists, `false` otherwise
2776+
* Gets the memory segment with the given name.
2777+
*
2778+
* @param {string} name - The name of the memory segment to get.
2779+
* @returns {number} A MemorySegmentRef referring to the memory segment with the given name, or `null` if no such segment exists.
27792780
*/
2780-
self['hasMemorySegment'] = function(name) {
2781-
return preserveStack(() => Boolean(Module['_BinaryenHasMemorySegment'](module, strToStack(name))));
2781+
self['getMemorySegment'] = function(name) {
2782+
return preserveStack(() => Module['_BinaryenGetMemorySegment'](module, strToStack(name)));
27822783
};
2783-
self['getMemorySegmentInfo'] = function(name) {
2784-
return preserveStack(() => {
2785-
const passive = Boolean(Module['_BinaryenGetMemorySegmentPassive'](module, strToStack(name)));
2786-
let offset = null;
2787-
if (!passive) {
2788-
offset = Module['_BinaryenGetMemorySegmentByteOffset'](module, strToStack(name));
2789-
}
2790-
return {
2791-
'offset': offset,
2792-
'data': (function(){
2793-
const size = Module['_BinaryenGetMemorySegmentByteLength'](module, strToStack(name));
2794-
const ptr = _malloc(size);
2795-
Module['_BinaryenCopyMemorySegmentData'](module, strToStack(name), ptr);
2796-
const res = new Uint8Array(size);
2797-
res.set(HEAP8.subarray(ptr, ptr + size));
2798-
_free(ptr);
2799-
return res.buffer;
2800-
})(),
2801-
'passive': passive
2802-
};
2803-
});
2784+
/**
2785+
* Gets the memory segment at the given index.
2786+
*
2787+
* @param {number} index - The index of the memory segment to get.
2788+
* @returns {number} A MemorySegmentRef referring to the memory segment at the given index.
2789+
*
2790+
* @throws If no memory segment exists at the given index.
2791+
*/
2792+
self['getMemorySegmentByIndex'] = function(index) {
2793+
return Module['_BinaryenGetMemorySegmentByIndex'](module, index);
2794+
};
2795+
/**
2796+
* Queries information about a memory segment.
2797+
*
2798+
* @param {number} segment - A MemorySegmentRef referring to the memory segment to get information about.
2799+
* @returns {Object} An object containing the following fields:
2800+
* - `name`: The name of the segment.
2801+
* - `offset`: If the segment is active, the offset expression of the segment. Otherwise, `null`.
2802+
* - `data`: A buffer containing the data of the segment.
2803+
* - `passive`: A boolean indicating whether the segment is passive.
2804+
*
2805+
* @throws If the given segment reference is invalid.
2806+
*/
2807+
self['getMemorySegmentInfo'] = function(segment) {
2808+
const passive = Boolean(Module['_BinaryenGetMemorySegmentPassive'](segment));
2809+
let offset = null;
2810+
if (!passive) {
2811+
offset = Module['_BinaryenGetMemorySegmentByteOffset'](module, segment);
2812+
}
2813+
return {
2814+
'name': UTF8ToString(Module['_BinaryenGetMemorySegmentName'](segment)),
2815+
'offset': offset,
2816+
'data': (function(){
2817+
const size = Module['_BinaryenGetMemorySegmentByteLength'](segment);
2818+
const ptr = _malloc(size);
2819+
Module['_BinaryenCopyMemorySegmentData'](segment, ptr);
2820+
const res = new Uint8Array(size);
2821+
res.set(HEAP8.subarray(ptr, ptr + size));
2822+
_free(ptr);
2823+
return res.buffer;
2824+
})(),
2825+
'passive': passive
2826+
};
28042827
};
28052828
self['setStart'] = function(start) {
28062829
return Module['_BinaryenSetStart'](module, start);

test/binaryen.js/kitchen-sink.js

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1142,15 +1142,17 @@ function test_for_each() {
11421142
data: expected_data[2].split('').map(function(x) { return x.charCodeAt(0) })
11431143
}
11441144
], false);
1145-
assert(module.hasMemorySegment(expected_names[0]));
1146-
assert(!module.hasMemorySegment("NonExistantSegment"));
1145+
assert(module.getMemorySegment(expected_names[0]) !== null);
1146+
assert(module.getMemorySegment("NonExistantSegment") === null);
11471147
for (i = 0; i < module.getNumMemorySegments(); i++) {
1148-
var segment = module.getMemorySegmentInfo(expected_names[i]);
1149-
assert(expected_offsets[i] === segment.offset);
1150-
var data8 = new Uint8Array(segment.data);
1148+
var segment = module.getMemorySegmentByIndex(i);
1149+
var info = module.getMemorySegmentInfo(segment);
1150+
assert(expected_names[i] === info.name);
1151+
assert(expected_offsets[i] === info.offset);
1152+
var data8 = new Uint8Array(info.data);
11511153
var str = String.fromCharCode.apply(null, data8);
11521154
assert(expected_data[i] === str);
1153-
assert(expected_passive[i] === segment.passive);
1155+
assert(expected_passive[i] === info.passive);
11541156
}
11551157

11561158
module.addTable("t0", 1, 0xffffffff);

test/example/c-api-kitchen-sink.c

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2006,15 +2006,19 @@ void test_for_each() {
20062006
BinaryenTypeInt32(),
20072007
0,
20082008
makeInt32(module, expected_offsets[1]));
2009-
assert(BinaryenHasMemorySegment(module, segmentNames[0]));
2010-
assert(!BinaryenHasMemorySegment(module, "NonExistantSegment"));
2009+
assert(BinaryenGetMemorySegment(module, segmentNames[0]) != NULL);
2010+
assert(BinaryenGetMemorySegment(module, "NonExistantSegment") == NULL);
20112011
for (i = 0; i < BinaryenGetNumMemorySegments(module); i++) {
20122012
char out[15] = {};
2013-
assert(BinaryenGetMemorySegmentByteOffset(module, segmentNames[i]) ==
2013+
BinaryenDataSegmentRef segment =
2014+
BinaryenGetMemorySegmentByIndex(module, i);
2015+
assert(segment != NULL);
2016+
assert(BinaryenGetMemorySegmentName(segment) != NULL);
2017+
assert(BinaryenGetMemorySegmentByteOffset(module, segment) ==
20142018
expected_offsets[i]);
2015-
assert(BinaryenGetMemorySegmentByteLength(module, segmentNames[i]) ==
2016-
segmentSizes[i]);
2017-
BinaryenCopyMemorySegmentData(module, segmentNames[i], out);
2019+
assert(BinaryenGetMemorySegmentByteLength(segment) == segmentSizes[i]);
2020+
assert(BinaryenGetMemorySegmentPassive(segment) == segmentPassives[i]);
2021+
BinaryenCopyMemorySegmentData(segment, out);
20182022
assert(0 == strcmp(segmentDatas[i], out));
20192023
}
20202024
}

0 commit comments

Comments
 (0)