Skip to content

Commit 2d5b3b7

Browse files
committed
feat(C & JS API): Implement BinaryenDataSegmentRef
1 parent 4e47c5e commit 2d5b3b7

6 files changed

Lines changed: 114 additions & 82 deletions

File tree

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

1824
- Add support for non-nullable table types and initialization expressions for
1925
tables. This comes with a breaking change to C API: `BinaryenAddTable` takes
@@ -77,8 +83,6 @@ v126
7783
`BinaryenMemoryOrder` param. The functions formerly implicitly used
7884
`BinaryenMemoryOrderSeqCst()`. In JS this param is optional and thus not
7985
breaking.
80-
- Add `BinaryenHasMemorySegment(<module>, <name>)` to the C API and
81-
`module.hasMemorySegment(name)` to the JS API. Allowing users to check if a segment exists.
8286

8387
v125
8488
----

src/binaryen-c.cpp

Lines changed: 25 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -5492,17 +5492,24 @@ void BinaryenSetMemory(BinaryenModuleRef module,
54925492
uint32_t BinaryenGetNumMemorySegments(BinaryenModuleRef module) {
54935493
return ((Module*)module)->dataSegments.size();
54945494
}
5495-
bool BinaryenHasMemorySegment(BinaryenModuleRef module,
5496-
const char* segmentName) {
5497-
return (Module*)module->getDataSegmentOrNull(Name(segmentName)) != NULL;
5495+
BinaryenDataSegmentRef BinaryenGetMemorySegment(BinaryenModuleRef module,
5496+
const char* segmentName) {
5497+
return ((Module*)module)->getDataSegmentOrNull(Name(segmentName));
5498+
}
5499+
BinaryenDataSegmentRef BinaryenGetMemorySegmentByIndex(BinaryenModuleRef module,
5500+
BinaryenIndex index) {
5501+
const auto& dataSegments = ((Module*)module)->dataSegments;
5502+
if (dataSegments.size() <= index) {
5503+
Fatal() << "invalid memory segment index.";
5504+
}
5505+
return dataSegments[index].get();
5506+
}
5507+
const char* BinaryenGetMemorySegmentName(BinaryenDataSegmentRef segment) {
5508+
return ((DataSegment*)segment)->name.str.data();
54985509
}
54995510
uint32_t BinaryenGetMemorySegmentByteOffset(BinaryenModuleRef module,
5500-
const char* segmentName) {
5511+
BinaryenDataSegmentRef segment) {
55015512
auto* wasm = (Module*)module;
5502-
const auto* segment = wasm->getDataSegmentOrNull(Name(segmentName));
5503-
if (segment == NULL) {
5504-
Fatal() << "invalid segment name.";
5505-
}
55065513

55075514
auto globalOffset = [&](const Expression* const& expr,
55085515
int64_t& result) -> bool {
@@ -5514,10 +5521,10 @@ uint32_t BinaryenGetMemorySegmentByteOffset(BinaryenModuleRef module,
55145521
};
55155522

55165523
int64_t ret;
5517-
if (globalOffset(segment->offset, ret)) {
5524+
if (globalOffset(((DataSegment*)segment)->offset, ret)) {
55185525
return ret;
55195526
}
5520-
if (auto* get = segment->offset->dynCast<GlobalGet>()) {
5527+
if (auto* get = ((DataSegment*)segment)->offset->dynCast<GlobalGet>()) {
55215528
Global* global = wasm->getGlobal(get->name);
55225529
if (globalOffset(global->init, ret)) {
55235530
return ret;
@@ -5618,33 +5625,17 @@ bool BinaryenMemoryIs64(BinaryenModuleRef module, const char* name) {
56185625
}
56195626
return memory->is64();
56205627
}
5621-
size_t BinaryenGetMemorySegmentByteLength(BinaryenModuleRef module,
5622-
const char* segmentName) {
5623-
auto* wasm = (Module*)module;
5624-
const auto* segment = wasm->getDataSegmentOrNull(Name(segmentName));
5625-
if (segment == NULL) {
5626-
Fatal() << "invalid segment name.";
5627-
}
5628-
return segment->data.size();
5628+
size_t BinaryenGetMemorySegmentByteLength(BinaryenDataSegmentRef segment) {
5629+
return ((DataSegment*)segment)->data.size();
56295630
}
5630-
bool BinaryenGetMemorySegmentPassive(BinaryenModuleRef module,
5631-
const char* segmentName) {
5632-
auto* wasm = (Module*)module;
5633-
const auto* segment = wasm->getDataSegmentOrNull(Name(segmentName));
5634-
if (segment == NULL) {
5635-
Fatal() << "invalid segment name.";
5636-
}
5637-
return segment->isPassive;
5631+
bool BinaryenGetMemorySegmentPassive(BinaryenDataSegmentRef segment) {
5632+
return ((DataSegment*)segment)->isPassive;
56385633
}
5639-
void BinaryenCopyMemorySegmentData(BinaryenModuleRef module,
5640-
const char* segmentName,
5634+
void BinaryenCopyMemorySegmentData(BinaryenDataSegmentRef segment,
56415635
char* buffer) {
5642-
auto* wasm = (Module*)module;
5643-
const auto* segment = wasm->getDataSegmentOrNull(Name(segmentName));
5644-
if (segment == NULL) {
5645-
Fatal() << "invalid segment name.";
5646-
}
5647-
std::copy(segment->data.cbegin(), segment->data.cend(), buffer);
5636+
std::copy(((DataSegment*)segment)->data.cbegin(),
5637+
((DataSegment*)segment)->data.cend(),
5638+
buffer);
56485639
}
56495640
void BinaryenAddDataSegment(BinaryenModuleRef module,
56505641
const char* segmentName,

src/binaryen-c.h

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

30063006
// Memory segments. Query utilities.
30073007

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

src/js/binaryen.js-post.js

Lines changed: 51 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2773,35 +2773,61 @@ 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))));
2782-
};
2783-
self['getMemorySegmentInfo'] = function(name) {
2781+
self['getMemorySegment'] = function(name) {
27842782
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-
};
2783+
const segment = Module['_BinaryenGetMemorySegment'](module, strToStack(name));
2784+
return segment === 0 ? null : segment;
28032785
});
28042786
};
2787+
/**
2788+
* Gets the memory segment at the given index.
2789+
*
2790+
* @param {number} index - The index of the memory segment to get.
2791+
* @returns {number} A MemorySegmentRef referring to the memory segment at the given index.
2792+
*
2793+
* @throws If no memory segment exists at the given index.
2794+
*/
2795+
self['getMemorySegmentByIndex'] = function(index) {
2796+
return Module['_BinaryenGetMemorySegmentByIndex'](module, index);
2797+
};
2798+
/**
2799+
* Queries information about a memory segment.
2800+
*
2801+
* @param {number} segment - A MemorySegmentRef referring to the memory segment to get information about.
2802+
* @returns {Object} An object containing the following fields:
2803+
* - `name`: The name of the segment.
2804+
* - `offset`: If the segment is active, the offset expression of the segment. Otherwise, `null`.
2805+
* - `data`: A buffer containing the data of the segment.
2806+
* - `passive`: A boolean indicating whether the segment is passive.
2807+
*
2808+
* @throws If the given segment reference is invalid.
2809+
*/
2810+
self['getMemorySegmentInfo'] = function(segment) {
2811+
const passive = Boolean(Module['_BinaryenGetMemorySegmentPassive'](segment));
2812+
let offset = null;
2813+
if (!passive) {
2814+
offset = Module['_BinaryenGetMemorySegmentByteOffset'](module, segment);
2815+
}
2816+
return {
2817+
'name': UTF8ToString(Module['_BinaryenGetMemorySegmentName'](segment)),
2818+
'offset': offset,
2819+
'data': (function(){
2820+
const size = Module['_BinaryenGetMemorySegmentByteLength'](segment);
2821+
const ptr = _malloc(size);
2822+
Module['_BinaryenCopyMemorySegmentData'](segment, ptr);
2823+
const res = new Uint8Array(size);
2824+
res.set(HEAP8.subarray(ptr, ptr + size));
2825+
_free(ptr);
2826+
return res.buffer;
2827+
})(),
2828+
'passive': passive
2829+
};
2830+
};
28052831
self['setStart'] = function(start) {
28062832
return Module['_BinaryenSetStart'](module, start);
28072833
};

test/binaryen.js/kitchen-sink.js

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1144,15 +1144,17 @@ function test_for_each() {
11441144
data: expected_data[2].split('').map(function(x) { return x.charCodeAt(0) })
11451145
}
11461146
], false);
1147-
assert(module.hasMemorySegment(expected_names[0]));
1148-
assert(!module.hasMemorySegment("NonExistantSegment"));
1147+
assert(module.getMemorySegment(expected_names[0]) !== null);
1148+
assert(module.getMemorySegment("NonExistantSegment") === null);
11491149
for (i = 0; i < module.getNumMemorySegments(); i++) {
1150-
var segment = module.getMemorySegmentInfo(expected_names[i]);
1151-
assert(expected_offsets[i] === segment.offset);
1152-
var data8 = new Uint8Array(segment.data);
1150+
var segment = module.getMemorySegmentByIndex(i);
1151+
var info = module.getMemorySegmentInfo(segment);
1152+
assert(expected_names[i] === info.name);
1153+
assert(expected_offsets[i] === info.offset);
1154+
var data8 = new Uint8Array(info.data);
11531155
var str = String.fromCharCode.apply(null, data8);
11541156
assert(expected_data[i] === str);
1155-
assert(expected_passive[i] === segment.passive);
1157+
assert(expected_passive[i] === info.passive);
11561158
}
11571159

11581160
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
@@ -2019,15 +2019,19 @@ void test_for_each() {
20192019
BinaryenTypeInt32(),
20202020
0,
20212021
makeInt32(module, expected_offsets[1]));
2022-
assert(BinaryenHasMemorySegment(module, segmentNames[0]));
2023-
assert(!BinaryenHasMemorySegment(module, "NonExistantSegment"));
2022+
assert(BinaryenGetMemorySegment(module, segmentNames[0]) != NULL);
2023+
assert(BinaryenGetMemorySegment(module, "NonExistantSegment") == NULL);
20242024
for (i = 0; i < BinaryenGetNumMemorySegments(module); i++) {
20252025
char out[15] = {};
2026-
assert(BinaryenGetMemorySegmentByteOffset(module, segmentNames[i]) ==
2026+
BinaryenDataSegmentRef segment =
2027+
BinaryenGetMemorySegmentByIndex(module, i);
2028+
assert(segment != NULL);
2029+
assert(BinaryenGetMemorySegmentName(segment) != NULL);
2030+
assert(BinaryenGetMemorySegmentByteOffset(module, segment) ==
20272031
expected_offsets[i]);
2028-
assert(BinaryenGetMemorySegmentByteLength(module, segmentNames[i]) ==
2029-
segmentSizes[i]);
2030-
BinaryenCopyMemorySegmentData(module, segmentNames[i], out);
2032+
assert(BinaryenGetMemorySegmentByteLength(segment) == segmentSizes[i]);
2033+
assert(BinaryenGetMemorySegmentPassive(segment) == segmentPassives[i]);
2034+
BinaryenCopyMemorySegmentData(segment, out);
20312035
assert(0 == strcmp(segmentDatas[i], out));
20322036
}
20332037
}

0 commit comments

Comments
 (0)