Skip to content

Commit 2609e6c

Browse files
authored
[C & JS API] Add more DataSegment APIs (#8286)
- Add a `BinaryenDataSegmentRef` type to the C API - Add `BinaryenGetDataSegment` and `BinaryenGetDataSegmentByIndex` to the C API, which allow looking up a data segment by name or index. - Add `BinaryenDataSegmentGetName` to the C API, which allows looking up a data segment's name. - Convert `BinaryenGetMemorySegmentByteOffset`, `BinaryenGetMemorySegmentByteLength`, `BinaryenGetMemorySegmentPassive` and `BinaryenCopyMemorySegmentData` to take a `BinaryenDataSegmentRef` instead of a name. - Add `module.getDataSegment`, `module.getDataSegmentByIndex` to the JS API, which allows looking up a data segment by name or index. - Convert `module.getMemorySegmentInfo` to take a data segment reference instead of a name, and return the name as part of the info.
1 parent 8d9af32 commit 2609e6c

File tree

6 files changed

+115
-66
lines changed

6 files changed

+115
-66
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 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 `BinaryenGetDataSegment` and `BinaryenGetDataSegmentByIndex` to the C API, which allow looking up a data segment by name or index.
19+
- Add `BinaryenDataSegmentGetName` to the C API, which allows looking up a data segment's name.
20+
- Convert `BinaryenGetMemorySegmentByteOffset`, `BinaryenGetMemorySegmentByteLength`, `BinaryenGetMemorySegmentPassive` and `BinaryenCopyMemorySegmentData` to take a `BinaryenDataSegmentRef` instead of a name.
21+
- Add `module.getDataSegment`, `module.getDataSegmentByIndex` to the JS API, which allows looking up a data segment by name or index.
22+
- Convert `module.getMemorySegmentInfo` to take a data 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

src/binaryen-c.cpp

Lines changed: 26 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -5492,13 +5492,24 @@ void BinaryenSetMemory(BinaryenModuleRef module,
54925492
uint32_t BinaryenGetNumMemorySegments(BinaryenModuleRef module) {
54935493
return ((Module*)module)->dataSegments.size();
54945494
}
5495+
BinaryenDataSegmentRef BinaryenGetDataSegment(BinaryenModuleRef module,
5496+
const char* segmentName) {
5497+
return ((Module*)module)->getDataSegmentOrNull(Name(segmentName));
5498+
}
5499+
BinaryenDataSegmentRef BinaryenGetDataSegmentByIndex(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* BinaryenDataSegmentGetName(BinaryenDataSegmentRef segment) {
5508+
return ((DataSegment*)segment)->name.str.data();
5509+
}
54955510
uint32_t BinaryenGetMemorySegmentByteOffset(BinaryenModuleRef module,
5496-
const char* segmentName) {
5511+
BinaryenDataSegmentRef segment) {
54975512
auto* wasm = (Module*)module;
5498-
const auto* segment = wasm->getDataSegmentOrNull(Name(segmentName));
5499-
if (segment == NULL) {
5500-
Fatal() << "invalid segment name.";
5501-
}
55025513

55035514
auto globalOffset = [&](const Expression* const& expr,
55045515
int64_t& result) -> bool {
@@ -5510,10 +5521,10 @@ uint32_t BinaryenGetMemorySegmentByteOffset(BinaryenModuleRef module,
55105521
};
55115522

55125523
int64_t ret;
5513-
if (globalOffset(segment->offset, ret)) {
5524+
if (globalOffset(((DataSegment*)segment)->offset, ret)) {
55145525
return ret;
55155526
}
5516-
if (auto* get = segment->offset->dynCast<GlobalGet>()) {
5527+
if (auto* get = ((DataSegment*)segment)->offset->dynCast<GlobalGet>()) {
55175528
Global* global = wasm->getGlobal(get->name);
55185529
if (globalOffset(global->init, ret)) {
55195530
return ret;
@@ -5614,33 +5625,17 @@ bool BinaryenMemoryIs64(BinaryenModuleRef module, const char* name) {
56145625
}
56155626
return memory->is64();
56165627
}
5617-
size_t BinaryenGetMemorySegmentByteLength(BinaryenModuleRef module,
5618-
const char* segmentName) {
5619-
auto* wasm = (Module*)module;
5620-
const auto* segment = wasm->getDataSegmentOrNull(Name(segmentName));
5621-
if (segment == NULL) {
5622-
Fatal() << "invalid segment name.";
5623-
}
5624-
return segment->data.size();
5628+
size_t BinaryenGetMemorySegmentByteLength(BinaryenDataSegmentRef segment) {
5629+
return ((DataSegment*)segment)->data.size();
56255630
}
5626-
bool BinaryenGetMemorySegmentPassive(BinaryenModuleRef module,
5627-
const char* segmentName) {
5628-
auto* wasm = (Module*)module;
5629-
const auto* segment = wasm->getDataSegmentOrNull(Name(segmentName));
5630-
if (segment == NULL) {
5631-
Fatal() << "invalid segment name.";
5632-
}
5633-
return segment->isPassive;
5631+
bool BinaryenGetMemorySegmentPassive(BinaryenDataSegmentRef segment) {
5632+
return ((DataSegment*)segment)->isPassive;
56345633
}
5635-
void BinaryenCopyMemorySegmentData(BinaryenModuleRef module,
5636-
const char* segmentName,
5634+
void BinaryenCopyMemorySegmentData(BinaryenDataSegmentRef segment,
56375635
char* buffer) {
5638-
auto* wasm = (Module*)module;
5639-
const auto* segment = wasm->getDataSegmentOrNull(Name(segmentName));
5640-
if (segment == NULL) {
5641-
Fatal() << "invalid segment name.";
5642-
}
5643-
std::copy(segment->data.cbegin(), segment->data.cend(), buffer);
5636+
std::copy(((DataSegment*)segment)->data.cbegin(),
5637+
((DataSegment*)segment)->data.cend(),
5638+
buffer);
56445639
}
56455640
void BinaryenAddDataSegment(BinaryenModuleRef module,
56465641
const char* segmentName,

src/binaryen-c.h

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3005,15 +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);
3011+
BINARYEN_API BinaryenDataSegmentRef
3012+
BinaryenGetDataSegment(BinaryenModuleRef module, const char* segmentName);
3013+
BINARYEN_API BinaryenDataSegmentRef
3014+
BinaryenGetDataSegmentByIndex(BinaryenModuleRef module, BinaryenIndex index);
3015+
BINARYEN_API const char*
3016+
BinaryenDataSegmentGetName(BinaryenDataSegmentRef segment);
30093017
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,
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,
30173024
char* buffer);
30183025
BINARYEN_API void BinaryenAddDataSegment(BinaryenModuleRef module,
30193026
const char* segmentName,

src/js/binaryen.js-post.js

Lines changed: 52 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2772,28 +2772,61 @@ function wrapModule(module, self = {}) {
27722772
self['getNumMemorySegments'] = function() {
27732773
return Module['_BinaryenGetNumMemorySegments'](module);
27742774
};
2775-
self['getMemorySegmentInfo'] = function(name) {
2775+
/**
2776+
* Gets the data segment with the given name.
2777+
*
2778+
* @param {string} name - The name of the data segment to get.
2779+
* @returns {number} A DataSegmentRef referring to the data segment with the given name, or `0` if no such segment exists.
2780+
*/
2781+
self['getDataSegment'] = function(name) {
27762782
return preserveStack(() => {
2777-
const passive = Boolean(Module['_BinaryenGetMemorySegmentPassive'](module, strToStack(name)));
2778-
let offset = null;
2779-
if (!passive) {
2780-
offset = Module['_BinaryenGetMemorySegmentByteOffset'](module, strToStack(name));
2781-
}
2782-
return {
2783-
'offset': offset,
2784-
'data': (function(){
2785-
const size = Module['_BinaryenGetMemorySegmentByteLength'](module, strToStack(name));
2786-
const ptr = _malloc(size);
2787-
Module['_BinaryenCopyMemorySegmentData'](module, strToStack(name), ptr);
2788-
const res = new Uint8Array(size);
2789-
res.set(HEAP8.subarray(ptr, ptr + size));
2790-
_free(ptr);
2791-
return res.buffer;
2792-
})(),
2793-
'passive': passive
2794-
};
2783+
return Module['_BinaryenGetDataSegment'](module, strToStack(name));
27952784
});
27962785
};
2786+
/**
2787+
* Gets the data segment at the given index.
2788+
*
2789+
* @param {number} index - The index of the data segment to get.
2790+
* @returns {number} A DataSegmentRef referring to the data segment at the given index.
2791+
*
2792+
* @throws If no data segment exists at the given index.
2793+
*/
2794+
self['getDataSegmentByIndex'] = function(index) {
2795+
return Module['_BinaryenGetDataSegmentByIndex'](module, index);
2796+
};
2797+
/**
2798+
* Queries information about a memory segment.
2799+
*
2800+
* @param {number} segment - A MemorySegmentRef referring to the memory segment to get information about.
2801+
* @returns {Object} An object containing the following fields:
2802+
* - `name`: The name of the segment.
2803+
* - `offset`: If the segment is active, the offset expression of the segment. Otherwise, `null`.
2804+
* - `data`: A buffer containing the data of the segment.
2805+
* - `passive`: A boolean indicating whether the segment is passive.
2806+
*
2807+
* @throws If the given segment reference is invalid.
2808+
*/
2809+
self['getMemorySegmentInfo'] = function(segment) {
2810+
const passive = Boolean(Module['_BinaryenGetMemorySegmentPassive'](segment));
2811+
let offset = null;
2812+
if (!passive) {
2813+
offset = Module['_BinaryenGetMemorySegmentByteOffset'](module, segment);
2814+
}
2815+
return {
2816+
'name': UTF8ToString(Module['_BinaryenDataSegmentGetName'](segment)),
2817+
'offset': offset,
2818+
'data': (function(){
2819+
const size = Module['_BinaryenGetMemorySegmentByteLength'](segment);
2820+
const ptr = _malloc(size);
2821+
Module['_BinaryenCopyMemorySegmentData'](segment, ptr);
2822+
const res = new Uint8Array(size);
2823+
res.set(HEAP8.subarray(ptr, ptr + size));
2824+
_free(ptr);
2825+
return res.buffer;
2826+
})(),
2827+
'passive': passive
2828+
};
2829+
};
27972830
self['setStart'] = function(start) {
27982831
return Module['_BinaryenSetStart'](module, start);
27992832
};

test/binaryen.js/kitchen-sink.js

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1193,13 +1193,17 @@ function test_for_each() {
11931193
data: expected_data[2].split('').map(function(x) { return x.charCodeAt(0) })
11941194
}
11951195
], false);
1196+
assert(module.getDataSegment(expected_names[0]) !== 0);
1197+
assert(module.getDataSegment("NonExistantSegment") === 0);
11961198
for (i = 0; i < module.getNumMemorySegments(); i++) {
1197-
var segment = module.getMemorySegmentInfo(expected_names[i]);
1198-
assert(expected_offsets[i] === segment.offset);
1199-
var data8 = new Uint8Array(segment.data);
1199+
var segment = module.getDataSegmentByIndex(i);
1200+
var info = module.getMemorySegmentInfo(segment);
1201+
assert(expected_names[i] === info.name);
1202+
assert(expected_offsets[i] === info.offset);
1203+
var data8 = new Uint8Array(info.data);
12001204
var str = String.fromCharCode.apply(null, data8);
12011205
assert(expected_data[i] === str);
1202-
assert(expected_passive[i] === segment.passive);
1206+
assert(expected_passive[i] === info.passive);
12031207
}
12041208

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

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

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2019,14 +2019,18 @@ void test_for_each() {
20192019
BinaryenTypeInt32(),
20202020
0,
20212021
makeInt32(module, expected_offsets[1]));
2022-
2022+
assert(BinaryenGetDataSegment(module, segmentNames[0]) != NULL);
2023+
assert(BinaryenGetDataSegment(module, "NonExistentSegment") == NULL);
20232024
for (i = 0; i < BinaryenGetNumMemorySegments(module); i++) {
20242025
char out[15] = {};
2025-
assert(BinaryenGetMemorySegmentByteOffset(module, segmentNames[i]) ==
2026+
BinaryenDataSegmentRef segment = BinaryenGetDataSegmentByIndex(module, i);
2027+
assert(segment != NULL);
2028+
assert(BinaryenDataSegmentGetName(segment) != NULL);
2029+
assert(BinaryenGetMemorySegmentByteOffset(module, segment) ==
20262030
expected_offsets[i]);
2027-
assert(BinaryenGetMemorySegmentByteLength(module, segmentNames[i]) ==
2028-
segmentSizes[i]);
2029-
BinaryenCopyMemorySegmentData(module, segmentNames[i], out);
2031+
assert(BinaryenGetMemorySegmentByteLength(segment) == segmentSizes[i]);
2032+
assert(BinaryenGetMemorySegmentPassive(segment) == segmentPassives[i]);
2033+
BinaryenCopyMemorySegmentData(segment, out);
20302034
assert(0 == strcmp(segmentDatas[i], out));
20312035
}
20322036
}

0 commit comments

Comments
 (0)