Skip to content

Commit 9c63728

Browse files
authored
Features C/JS API (#2049)
Add feature handling to the C/JS APIs. No features are enabled by default, so all used features will have to be explicitly enabled in order for modules to validate.
1 parent 1184678 commit 9c63728

File tree

11 files changed

+152
-3
lines changed

11 files changed

+152
-3
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ full changeset diff at the end of each section.
1515
Current Trunk
1616
-------------
1717

18+
- Add feature handling to the C/JS API with no feature enabled by default.
19+
1820
v84
1921
---
2022

build-js.sh

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,15 @@ export_function "_BinaryenExternalTable"
230230
export_function "_BinaryenExternalMemory"
231231
export_function "_BinaryenExternalGlobal"
232232

233+
# Features
234+
export_function "_BinaryenFeatureAtomics"
235+
export_function "_BinaryenFeatureBulkMemory"
236+
export_function "_BinaryenFeatureMutableGlobals"
237+
export_function "_BinaryenFeatureNontrappingFPToInt"
238+
export_function "_BinaryenFeatureSignExt"
239+
export_function "_BinaryenFeatureSIMD128"
240+
export_function "_BinaryenFeatureExceptionHandling"
241+
233242
# Literals
234243
export_function "_BinaryenLiteralInt32"
235244
export_function "_BinaryenLiteralInt64"
@@ -758,6 +767,8 @@ export_function "_BinaryenRemoveExport"
758767
export_function "_BinaryenSetFunctionTable"
759768
export_function "_BinaryenSetMemory"
760769
export_function "_BinaryenSetStart"
770+
export_function "_BinaryenGetFeatures"
771+
export_function "_BinaryenSetFeatures"
761772
export_function "_BinaryenModuleParse"
762773
export_function "_BinaryenModulePrint"
763774
export_function "_BinaryenModulePrintAsmjs"

src/binaryen-c.cpp

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,30 @@ BinaryenExternalKind BinaryenExternalGlobal(void) {
367367
return static_cast<BinaryenExternalKind>(ExternalKind::Global);
368368
}
369369

370+
// Features
371+
372+
BinaryenFeatures BinaryenFeatureAtomics(void) {
373+
return static_cast<BinaryenFeatures>(FeatureSet::Feature::Atomics);
374+
}
375+
BinaryenFeatures BinaryenFeatureBulkMemory(void) {
376+
return static_cast<BinaryenFeatures>(FeatureSet::Feature::BulkMemory);
377+
}
378+
BinaryenFeatures BinaryenFeatureMutableGlobals(void) {
379+
return static_cast<BinaryenFeatures>(FeatureSet::Feature::MutableGlobals);
380+
}
381+
BinaryenFeatures BinaryenFeatureNontrappingFPToInt(void) {
382+
return static_cast<BinaryenFeatures>(FeatureSet::Feature::TruncSat);
383+
}
384+
BinaryenFeatures BinaryenFeatureSignExt(void) {
385+
return static_cast<BinaryenFeatures>(FeatureSet::Feature::SignExt);
386+
}
387+
BinaryenFeatures BinaryenFeatureSIMD128(void) {
388+
return static_cast<BinaryenFeatures>(FeatureSet::Feature::SIMD);
389+
}
390+
BinaryenFeatures BinaryenFeatureExceptionHandling(void) {
391+
return static_cast<BinaryenFeatures>(FeatureSet::Feature::ExceptionHandling);
392+
}
393+
370394
// Modules
371395

372396
BinaryenModuleRef BinaryenModuleCreate(void) {
@@ -3053,6 +3077,24 @@ void BinaryenSetStart(BinaryenModuleRef module, BinaryenFunctionRef start) {
30533077
wasm->addStart(((Function*)start)->name);
30543078
}
30553079

3080+
// Features
3081+
3082+
BinaryenFeatures BinaryenGetFeatures(BinaryenModuleRef module) {
3083+
if (tracing) {
3084+
std::cout << " BinaryenGetFeatures(the_module);\n";
3085+
}
3086+
auto* wasm = static_cast<Module*>(module);
3087+
return wasm->features.features;
3088+
}
3089+
3090+
void BinaryenSetFeatures(BinaryenModuleRef module, BinaryenFeatures features) {
3091+
if (tracing) {
3092+
std::cout << " BinaryenSetFeatures(the_module, " << features << ");\n";
3093+
}
3094+
auto* wasm = static_cast<Module*>(module);
3095+
wasm->features.features = features;
3096+
}
3097+
30563098
//
30573099
// ========== Module Operations ==========
30583100
//
@@ -3106,8 +3148,6 @@ int BinaryenModuleValidate(BinaryenModuleRef module) {
31063148
}
31073149

31083150
Module* wasm = (Module*)module;
3109-
// TODO(tlively): Add C API for managing features
3110-
wasm->features = FeatureSet::All;
31113151
return WasmValidator().validate(*wasm) ? 1 : 0;
31123152
}
31133153

src/binaryen-c.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,19 @@ BinaryenExternalKind BinaryenExternalTable(void);
137137
BinaryenExternalKind BinaryenExternalMemory(void);
138138
BinaryenExternalKind BinaryenExternalGlobal(void);
139139

140+
// Features. Call to get the value of each; you can cache them. Use bitwise
141+
// operators to combine and test particular features.
142+
143+
typedef uint32_t BinaryenFeatures;
144+
145+
BinaryenFeatures BinaryenFeatureAtomics(void);
146+
BinaryenFeatures BinaryenFeatureBulkMemory(void);
147+
BinaryenFeatures BinaryenFeatureMutableGlobals(void);
148+
BinaryenFeatures BinaryenFeatureNontrappingFPToInt(void);
149+
BinaryenFeatures BinaryenFeatureSignExt(void);
150+
BinaryenFeatures BinaryenFeatureSIMD128(void);
151+
BinaryenFeatures BinaryenFeatureExceptionHandling(void);
152+
140153
// Modules
141154
//
142155
// Modules contain lists of functions, imports, exports, function types. The
@@ -929,6 +942,12 @@ void BinaryenSetMemory(BinaryenModuleRef module,
929942

930943
void BinaryenSetStart(BinaryenModuleRef module, BinaryenFunctionRef start);
931944

945+
// Features
946+
947+
// These control what features are allowed when validation and in passes.
948+
BinaryenFeatures BinaryenGetFeatures(BinaryenModuleRef module);
949+
void BinaryenSetFeatures(BinaryenModuleRef module, BinaryenFeatures features);
950+
932951
//
933952
// ========== Module Operations ==========
934953
//

src/js/binaryen.js-post.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,17 @@ Module['ExternalTable'] = Module['_BinaryenExternalTable']();
8585
Module['ExternalMemory'] = Module['_BinaryenExternalMemory']();
8686
Module['ExternalGlobal'] = Module['_BinaryenExternalGlobal']();
8787

88+
// Features
89+
Module['Features'] = {
90+
'Atomics': Module['_BinaryenFeatureAtomics'](),
91+
'BulkMemory': Module['_BinaryenFeatureBulkMemory'](),
92+
'MutableGlobals': Module['_BinaryenFeatureMutableGlobals'](),
93+
'NontrappingFPToInt': Module['_BinaryenFeatureNontrappingFPToInt'](),
94+
'SignExt': Module['_BinaryenFeatureSignExt'](),
95+
'SIMD128': Module['_BinaryenFeatureSIMD128'](),
96+
'ExceptionHandling': Module['_BinaryenFeatureExceptionHandling'](),
97+
};
98+
8899
// Operations
89100
Module['ClzInt32'] = Module['_BinaryenClzInt32']();
90101
Module['CtzInt32'] = Module['_BinaryenCtzInt32']();
@@ -1866,6 +1877,12 @@ function wrapModule(module, self) {
18661877
self['setStart'] = function(start) {
18671878
return Module['_BinaryenSetStart'](module, start);
18681879
};
1880+
self['getFeatures'] = function() {
1881+
return Module['_BinaryenGetFeatures'](module);
1882+
};
1883+
self['setFeatures'] = function(features) {
1884+
Module['_BinaryenSetFeatures'](module, features);
1885+
};
18691886
self['emitText'] = function() {
18701887
var old = out;
18711888
var ret = '';

src/wasm-features.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,6 @@ struct FeatureSet {
128128
return *this;
129129
}
130130

131-
private:
132131
uint32_t features;
133132
};
134133

test/binaryen.js/atomics.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,5 +59,6 @@ module.addFunction("main", signature, [], module.block("", [
5959
)
6060
]));
6161

62+
module.setFeatures(Binaryen.Features.Atomics);
6263
module.validate();
6364
console.log(module.emitText());

test/binaryen.js/kitchen-sink.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,16 @@ function test_types() {
6262
console.log("BinaryenTypeAuto: " + Binaryen.auto);
6363
}
6464

65+
function test_features() {
66+
console.log("Binaryen.Features.Atomics: " + Binaryen.Features.Atomics);
67+
console.log("Binaryen.Features.BulkMemory: " + Binaryen.Features.BulkMemory);
68+
console.log("Binaryen.Features.MutableGlobals: " + Binaryen.Features.MutableGlobals);
69+
console.log("Binaryen.Features.NontrappingFPToInt: " + Binaryen.Features.NontrappingFPToInt);
70+
console.log("Binaryen.Features.SignExt: " + Binaryen.Features.SignExt);
71+
console.log("Binaryen.Features.SIMD128: " + Binaryen.Features.SIMD128);
72+
console.log("Binaryen.Features.ExceptionHandling: " + Binaryen.Features.ExceptionHandling);
73+
}
74+
6575
function test_ids() {
6676
console.log("BinaryenInvalidId: " + Binaryen.InvalidId);
6777
console.log("BinaryenBlockId: " + Binaryen.BlockId);
@@ -454,6 +464,16 @@ function test_core() {
454464
// A bunch of our code needs drop, auto-add it
455465
module.autoDrop();
456466

467+
var features =
468+
Binaryen.Features.Atomics |
469+
Binaryen.Features.BulkMemory |
470+
Binaryen.Features.NontrappingFPToInt |
471+
Binaryen.Features.SignExt |
472+
Binaryen.Features.SIMD128;
473+
474+
module.setFeatures(features);
475+
assert(module.getFeatures() == features);
476+
457477
// Verify it validates
458478
assert(module.validate());
459479

@@ -766,6 +786,7 @@ function test_internals() {
766786

767787
function main() {
768788
test_types();
789+
test_features();
769790
test_ids();
770791
test_core();
771792
test_relooper();

test/binaryen.js/kitchen-sink.js.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,13 @@ BinaryenTypeVec128: 5
77
BinaryenTypeExceptRef: 6
88
BinaryenTypeUnreachable: 7
99
BinaryenTypeAuto: -1
10+
Binaryen.Features.Atomics: 1
11+
Binaryen.Features.BulkMemory: 16
12+
Binaryen.Features.MutableGlobals: 2
13+
Binaryen.Features.NontrappingFPToInt: 4
14+
Binaryen.Features.SignExt: 32
15+
Binaryen.Features.SIMD128: 8
16+
Binaryen.Features.ExceptionHandling: 64
1017
BinaryenInvalidId: 0
1118
BinaryenBlockId: 1
1219
BinaryenIfId: 2
@@ -3383,6 +3390,8 @@ getExpressionInfo(f64.const)={"id":14,"type":4,"value":9.5}
33833390
functionTypes[3] = BinaryenAddFunctionType(the_module, NULL, 0, paramTypes, 0);
33843391
}
33853392
BinaryenModuleAutoDrop(the_module);
3393+
BinaryenSetFeatures(the_module, 61);
3394+
BinaryenGetFeatures(the_module);
33863395
BinaryenModuleValidate(the_module);
33873396
BinaryenModulePrint(the_module);
33883397
(module

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

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,16 @@ void test_types() {
160160
printf("BinaryenTypeAuto: %d\n", BinaryenTypeAuto());
161161
}
162162

163+
void test_features() {
164+
printf("BinaryenFeatureAtomics: %d\n", BinaryenFeatureAtomics());
165+
printf("BinaryenFeatureBulkMemory: %d\n", BinaryenFeatureBulkMemory());
166+
printf("BinaryenFeatureMutableGlobals: %d\n", BinaryenFeatureMutableGlobals());
167+
printf("BinaryenFeatureNontrappingFPToInt: %d\n", BinaryenFeatureNontrappingFPToInt());
168+
printf("BinaryenFeatureSignExt: %d\n", BinaryenFeatureSignExt());
169+
printf("BinaryenFeatureSIMD128: %d\n", BinaryenFeatureSIMD128());
170+
printf("BinaryenFeatureExceptionHandling: %d\n", BinaryenFeatureExceptionHandling());
171+
}
172+
163173
void test_core() {
164174

165175
// Module creation
@@ -511,6 +521,16 @@ void test_core() {
511521
// A bunch of our code needs drop(), auto-add it
512522
BinaryenModuleAutoDrop(module);
513523

524+
BinaryenFeatures features =
525+
BinaryenFeatureAtomics() |
526+
BinaryenFeatureBulkMemory() |
527+
BinaryenFeatureNontrappingFPToInt() |
528+
BinaryenFeatureSignExt() |
529+
BinaryenFeatureSIMD128();
530+
531+
BinaryenSetFeatures(module, features);
532+
assert(BinaryenGetFeatures(module) == features);
533+
514534
// Verify it validates
515535
assert(BinaryenModuleValidate(module));
516536

@@ -830,6 +850,7 @@ void test_color_status() {
830850

831851
int main() {
832852
test_types();
853+
test_features();
833854
test_core();
834855
test_unreachable();
835856
test_relooper();

0 commit comments

Comments
 (0)