summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSurma <surma@surma.dev>2024-03-07 17:39:29 +0000
committerGitHub <noreply@github.com>2024-03-07 17:39:29 +0000
commitab9e3f75fcaae429e236bd50641e0d69e63cfdc2 (patch)
tree7ba8f348a612e4cf629b5b5e51486d5eee751fb7
parent920cbc32603fdb8eff8f50283a1788812863f0d3 (diff)
downloadbinaryen-ab9e3f75fcaae429e236bd50641e0d69e63cfdc2.tar.gz
binaryen-ab9e3f75fcaae429e236bd50641e0d69e63cfdc2.tar.bz2
binaryen-ab9e3f75fcaae429e236bd50641e0d69e63cfdc2.zip
Expose features option in C API binary reading (#6380)
This allows reading a module that requires a particular feature set. The old API assumed only MVP features.
-rw-r--r--CHANGELOG.md2
-rw-r--r--src/binaryen-c.cpp11
-rw-r--r--src/binaryen-c.h6
-rw-r--r--test/example/c-api-kitchen-sink.c26
4 files changed, 41 insertions, 4 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index fc03cf492..b42efef38 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -18,6 +18,8 @@ Current Trunk
- (If new wat parser is enabled) Source map comments on `else` branches must
now be placed above the instruction inside the `else` branch rather than on
the `else` branch itself.
+ - Add a new `BinaryenModuleReadWithFeatures` function to the C API that allows
+ to configure which features to enable in the parser.
v117
----
diff --git a/src/binaryen-c.cpp b/src/binaryen-c.cpp
index f9a778a68..29e0597d7 100644
--- a/src/binaryen-c.cpp
+++ b/src/binaryen-c.cpp
@@ -5851,14 +5851,15 @@ char* BinaryenModuleAllocateAndWriteStackIR(BinaryenModuleRef module,
return output;
}
-BinaryenModuleRef BinaryenModuleRead(char* input, size_t inputSize) {
+BinaryenModuleRef BinaryenModuleReadWithFeatures(char* input,
+ size_t inputSize,
+ BinaryenFeatures features) {
auto* wasm = new Module;
std::vector<char> buffer(false);
buffer.resize(inputSize);
std::copy_n(input, inputSize, buffer.begin());
try {
- // TODO: allow providing features in the C API
- WasmBinaryReader parser(*wasm, FeatureSet::MVP, buffer);
+ WasmBinaryReader parser(*wasm, features, buffer);
parser.read();
} catch (ParseException& p) {
p.dump(std::cerr);
@@ -5867,6 +5868,10 @@ BinaryenModuleRef BinaryenModuleRead(char* input, size_t inputSize) {
return wasm;
}
+BinaryenModuleRef BinaryenModuleRead(char* input, size_t inputSize) {
+ return BinaryenModuleReadWithFeatures(input, inputSize, BinaryenFeatureMVP());
+}
+
void BinaryenModuleInterpret(BinaryenModuleRef module) {
ShellExternalInterface interface;
ModuleRunner instance(*(Module*)module, &interface, {});
diff --git a/src/binaryen-c.h b/src/binaryen-c.h
index 4ead70ea4..42bd45915 100644
--- a/src/binaryen-c.h
+++ b/src/binaryen-c.h
@@ -3175,10 +3175,14 @@ BINARYEN_API char* BinaryenModuleAllocateAndWriteText(BinaryenModuleRef module);
BINARYEN_API char*
BinaryenModuleAllocateAndWriteStackIR(BinaryenModuleRef module, bool optimize);
-// Deserialize a module from binary form.
+// Deserialize a module from binary form, assuming the MVP feature set.
BINARYEN_API BinaryenModuleRef BinaryenModuleRead(char* input,
size_t inputSize);
+// Deserialize a module from binary form, enabling the given feature set.
+BINARYEN_API BinaryenModuleRef BinaryenModuleReadWithFeatures(
+ char* input, size_t inputSize, BinaryenFeatures featureSet);
+
// Execute a module in the Binaryen interpreter. This will create an instance of
// the module, run it in the interpreter - which means running the start method
// - and then destroying the instance.
diff --git a/test/example/c-api-kitchen-sink.c b/test/example/c-api-kitchen-sink.c
index bf80833a0..e5b614bec 100644
--- a/test/example/c-api-kitchen-sink.c
+++ b/test/example/c-api-kitchen-sink.c
@@ -401,6 +401,32 @@ void test_features() {
printf("BinaryenFeatureAll: %d\n", BinaryenFeatureAll());
}
+void test_read_with_feature() {
+ BinaryenModuleRef module = BinaryenModuleCreate();
+ // Having multiple tables makes this module inherently not MVP compatible
+ // and requires the externref feature enabled to parse successfully.
+ BinaryenAddTable(module, "tab", 0, 100, BinaryenTypeFuncref());
+ BinaryenAddTable(module, "tab2", 0, 100, BinaryenTypeFuncref());
+
+ BinaryenFeatures features =
+ BinaryenFeatureMVP() | BinaryenFeatureReferenceTypes();
+ BinaryenModuleSetFeatures(module, features);
+
+ size_t bufferSize = 1024;
+ char* buffer = malloc(bufferSize);
+ size_t written = BinaryenModuleWrite(module, buffer, bufferSize);
+ BinaryenModuleDispose(module);
+
+ // See we can read the bytes and get a valid module from there.
+ BinaryenModuleRef readModule =
+ BinaryenModuleReadWithFeatures(buffer, written, features);
+ int valid = BinaryenModuleValidate(readModule);
+ assert(valid);
+ BinaryenModuleDispose(readModule);
+
+ free(buffer);
+}
+
void test_core() {
// Module creation