Skip to content

Commit 6b6e89d

Browse files
authored
Feature options (#1797)
Add feature flags and struct interface. Default feature set has all feature enabled.
1 parent 99cad87 commit 6b6e89d

15 files changed

+155
-60
lines changed

auto_update_tests.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ def update_asm_js_tests():
3434
if asm.endswith('.asm.js'):
3535
for precise in [0, 1, 2]:
3636
for opts in [1, 0]:
37-
cmd = ASM2WASM + [os.path.join('test', asm), '--enable-threads']
37+
cmd = ASM2WASM + [os.path.join('test', asm)]
3838
wasm = asm.replace('.asm.js', '.fromasm')
3939
if not precise:
4040
cmd += ['--trap-mode=allow', '--ignore-implicit-traps']

src/binaryen-c.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1936,7 +1936,7 @@ int BinaryenModuleValidate(BinaryenModuleRef module) {
19361936

19371937
Module* wasm = (Module*)module;
19381938
// TODO add feature selection support to C API
1939-
FeatureSet features = Feature::Atomics;
1939+
FeatureSet features = FeatureSet::All;
19401940
return WasmValidator().validate(*wasm, features) ? 1 : 0;
19411941
}
19421942

src/pass.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ struct PassOptions {
6363
int shrinkLevel = 0; // 0, 1, 2 correspond to -O0, -Os, -Oz
6464
bool ignoreImplicitTraps = false; // optimize assuming things like div by 0, bad load/store, will not trap
6565
bool debugInfo = false; // whether to try to preserve debug info through, which are special calls
66-
FeatureSet features = Feature::MVP; // Which wasm features to accept, and be allowed to use
66+
FeatureSet features = FeatureSet::All; // Which wasm features to accept, and be allowed to use
6767

6868
void setDefaultOptimizationOptions() {
6969
// -Os is our default

src/passes/Print.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1184,7 +1184,7 @@ Pass* createPrintStackIRPass() {
11841184

11851185
std::ostream& WasmPrinter::printModule(Module* module, std::ostream& o) {
11861186
PassRunner passRunner(module);
1187-
passRunner.setFeatures(Feature::All);
1187+
passRunner.setFeatures(FeatureSet::All);
11881188
passRunner.setIsNested(true);
11891189
passRunner.add<Printer>(&o);
11901190
passRunner.run();

src/tools/asm2wasm.cpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -115,9 +115,6 @@ int main(int argc, const char *argv[]) {
115115
.add("--emit-text", "-S", "Emit text instead of binary for the output file",
116116
Options::Arguments::Zero,
117117
[&](Options *o, const std::string& argument) { emitBinary = false; })
118-
.add("--enable-threads", "-a", "Enable the Atomics wasm feature",
119-
Options::Arguments::Zero,
120-
[&](Options *o, const std::string& argument) { options.passOptions.features |= Feature::Atomics; })
121118
.add_positional("INFILE", Options::Arguments::One,
122119
[](Options *o, const std::string& argument) {
123120
o->extra["infile"] = argument;
@@ -188,7 +185,7 @@ int main(int argc, const char *argv[]) {
188185
if (memInit != options.extra.end()) {
189186
if (options.runningDefaultOptimizationPasses()) {
190187
PassRunner runner(&wasm);
191-
runner.setFeatures(options.features);
188+
runner.setFeatures(options.getFeatures());
192189
runner.add("memory-packing");
193190
runner.run();
194191
}

src/tools/feature-options.h

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
/*
2+
* Copyright 2018 WebAssembly Community Group participants
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#include "support/command-line.h"
18+
#include "pass.h"
19+
20+
//
21+
// Shared optimization options for commandline tools
22+
//
23+
24+
namespace wasm {
25+
26+
struct FeatureOptions : public Options {
27+
PassOptions passOptions;
28+
29+
FeatureOptions(const std::string& command, const std::string& description)
30+
: Options(command, description) {
31+
(*this)
32+
.add("--mvp-features", "-mvp", "Disable all non-MVP features (default)",
33+
Options::Arguments::Zero,
34+
[this](Options *o, const std::string& arguments) {
35+
passOptions.features = FeatureSet::MVP;
36+
})
37+
.add("--all-features", "-all", "Enable all features",
38+
Options::Arguments::Zero,
39+
[this](Options *o, const std::string& arguments) {
40+
passOptions.features = FeatureSet::All;
41+
})
42+
.add("--enable-threads", "", "Enable atomic operations",
43+
Options::Arguments::Zero,
44+
[this](Options *o, const std::string& arguments) {
45+
passOptions.features.setAtomics();
46+
})
47+
.add("--disable-threads", "", "Disable atomic operations",
48+
Options::Arguments::Zero,
49+
[this](Options *o, const std::string& arguments) {
50+
passOptions.features.setAtomics(false);
51+
})
52+
.add("--enable-mutable-globals", "", "Enable mutable globals",
53+
Options::Arguments::Zero,
54+
[this](Options *o, const std::string& arguments) {
55+
passOptions.features.setMutableGlobals();
56+
})
57+
.add("--disable-mutable-globals", "", "Disable mutable globals",
58+
Options::Arguments::Zero,
59+
[this](Options *o, const std::string& arguments) {
60+
passOptions.features.setMutableGlobals(false);
61+
})
62+
.add("--enable-nontrapping-float-to-int", "",
63+
"Enable nontrapping float-to-int operations",
64+
Options::Arguments::Zero,
65+
[this](Options *o, const std::string& arguments) {
66+
passOptions.features.setTruncSat();
67+
})
68+
.add("--disable-nontrapping-float-to-int", "",
69+
"Disable nontrapping float-to-int operations",
70+
Options::Arguments::Zero,
71+
[this](Options *o, const std::string& arguments) {
72+
passOptions.features.setTruncSat(false);
73+
});
74+
}
75+
76+
FeatureSet getFeatures() const {
77+
return passOptions.features;
78+
}
79+
};
80+
81+
} // namespace wasm

src/tools/fuzzing.h

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -123,8 +123,8 @@ class TranslateToFuzzReader {
123123
std::cout << "shrink level: " << options.passOptions.shrinkLevel << '\n';
124124
}
125125

126-
void build(bool initEmitAtomics = true) {
127-
emitAtomics = initEmitAtomics;
126+
void build(FeatureSet features_) {
127+
features = features_;
128128
setupMemory();
129129
setupTable();
130130
setupGlobals();
@@ -179,8 +179,8 @@ class TranslateToFuzzReader {
179179
// cross-VM comparisons harder)
180180
static const bool DE_NAN = true;
181181

182-
// Whether to emit atomics
183-
bool emitAtomics = true;
182+
// Features allowed to be emitted
183+
FeatureSet features = FeatureSet::All;
184184

185185
// Whether to emit atomic waits (which in single-threaded mode, may hang...)
186186
static const bool ATOMIC_WAITS = false;
@@ -1118,7 +1118,7 @@ class TranslateToFuzzReader {
11181118
Expression* makeLoad(Type type) {
11191119
auto* ret = makeNonAtomicLoad(type);
11201120
if (type != i32 && type != i64) return ret;
1121-
if (!emitAtomics || oneIn(2)) return ret;
1121+
if (!features.hasAtomics() || oneIn(2)) return ret;
11221122
// make it atomic
11231123
wasm.memory.shared = true;
11241124
ret->isAtomic = true;
@@ -1181,7 +1181,7 @@ class TranslateToFuzzReader {
11811181
Store* makeStore(Type type) {
11821182
auto* ret = makeNonAtomicStore(type);
11831183
if (ret->value->type != i32 && ret->value->type != i64) return ret;
1184-
if (!emitAtomics || oneIn(2)) return ret;
1184+
if (!features.hasAtomics() || oneIn(2)) return ret;
11851185
// make it atomic
11861186
wasm.memory.shared = true;
11871187
ret->isAtomic = true;
@@ -1314,7 +1314,7 @@ class TranslateToFuzzReader {
13141314
case i32: {
13151315
switch (upTo(4)) {
13161316
case 0: {
1317-
if (emitAtomics) {
1317+
if (features.hasAtomics()) {
13181318
return makeUnary({ pick(EqZInt32, ClzInt32, CtzInt32, PopcntInt32, ExtendS8Int32, ExtendS16Int32), make(i32) });
13191319
} else {
13201320
return makeUnary({ pick(EqZInt32, ClzInt32, CtzInt32, PopcntInt32), make(i32) });
@@ -1330,7 +1330,7 @@ class TranslateToFuzzReader {
13301330
case i64: {
13311331
switch (upTo(4)) {
13321332
case 0: {
1333-
if (emitAtomics) {
1333+
if (features.hasAtomics()) {
13341334
return makeUnary({ pick(ClzInt64, CtzInt64, PopcntInt64, ExtendS8Int64, ExtendS16Int64, ExtendS32Int64), make(i64) });
13351335
} else {
13361336
return makeUnary({ pick(ClzInt64, CtzInt64, PopcntInt64), make(i64) });
@@ -1465,7 +1465,7 @@ class TranslateToFuzzReader {
14651465
}
14661466

14671467
Expression* makeAtomic(Type type) {
1468-
if (!emitAtomics || (type != i32 && type != i64)) return makeTrivial(type);
1468+
if (!features.hasAtomics() || (type != i32 && type != i64)) return makeTrivial(type);
14691469
wasm.memory.shared = true;
14701470
if (type == i32 && oneIn(2)) {
14711471
if (ATOMIC_WAITS && oneIn(2)) {

src/tools/optimization-options.h

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,22 +14,20 @@
1414
* limitations under the License.
1515
*/
1616

17-
#include "support/command-line.h"
17+
#include "feature-options.h"
1818

1919
//
2020
// Shared optimization options for commandline tools
2121
//
2222

2323
namespace wasm {
2424

25-
struct OptimizationOptions : public Options {
25+
struct OptimizationOptions : public FeatureOptions {
2626
static constexpr const char* DEFAULT_OPT_PASSES = "O";
2727

2828
std::vector<std::string> passes;
29-
PassOptions passOptions;
30-
FeatureSet features = Feature::Atomics;
3129

32-
OptimizationOptions(const std::string& command, const std::string& description) : Options(command, description) {
30+
OptimizationOptions(const std::string& command, const std::string& description) : FeatureOptions(command, description) {
3331
(*this).add("", "-O", "execute default optimization passes",
3432
Options::Arguments::Zero,
3533
[this](Options*, const std::string&) {
@@ -132,7 +130,7 @@ struct OptimizationOptions : public Options {
132130
void runPasses(Module& wasm) {
133131
PassRunner passRunner(&wasm, passOptions);
134132
if (debug) passRunner.setDebug(true);
135-
passRunner.setFeatures(features);
133+
passRunner.setFeatures(passOptions.features);
136134
for (auto& pass : passes) {
137135
if (pass == DEFAULT_OPT_PASSES) {
138136
passRunner.addDefaultOptimizationPasses();

src/tools/wasm-as.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ int main(int argc, const char *argv[]) {
9393

9494
if (options.extra["validate"] != "none") {
9595
if (options.debug) std::cerr << "Validating..." << std::endl;
96-
if (!wasm::WasmValidator().validate(wasm, Feature::All,
96+
if (!wasm::WasmValidator().validate(wasm, FeatureSet::All,
9797
WasmValidator::Globally | (options.extra["validate"] == "web" ? WasmValidator::Web : 0))) {
9898
WasmPrinter::printModule(&wasm);
9999
Fatal() << "Error: input module is not valid.\n";

src/tools/wasm-opt.cpp

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,6 @@ int main(int argc, const char* argv[]) {
6969
bool fuzzBinary = false;
7070
std::string extraFuzzCommand;
7171
bool translateToFuzz = false;
72-
bool fuzzAtomics = true;
7372
bool fuzzPasses = false;
7473
std::string emitJSWrapper;
7574
std::string emitSpecWrapper;
@@ -106,9 +105,6 @@ int main(int argc, const char* argv[]) {
106105
.add("--translate-to-fuzz", "-ttf", "Translate the input into a valid wasm module *somehow*, useful for fuzzing",
107106
Options::Arguments::Zero,
108107
[&](Options *o, const std::string& arguments) { translateToFuzz = true; })
109-
.add("--no-fuzz-atomics", "-nfa", "Disable generation of atomic opcodes with translate-to-fuzz (on by default)",
110-
Options::Arguments::Zero,
111-
[&](Options *o, const std::string& arguments) { fuzzAtomics = false; })
112108
.add("--fuzz-passes", "-fp", "Pick a random set of passes to run, useful for fuzzing. this depends on translate-to-fuzz (it picks the passes from the input)",
113109
Options::Arguments::Zero,
114110
[&](Options *o, const std::string& arguments) { fuzzPasses = true; })
@@ -134,11 +130,6 @@ int main(int argc, const char* argv[]) {
134130
options.parse(argc, argv);
135131

136132
Module wasm;
137-
// It should be safe to just always enable atomics in wasm-opt, because we
138-
// don't expect any passes to accidentally generate atomic ops
139-
FeatureSet features = Feature::Atomics;
140-
// Same for MutableGlobals
141-
features |= Feature::MutableGlobals;
142133

143134
if (options.debug) std::cerr << "reading...\n";
144135

@@ -160,7 +151,7 @@ int main(int argc, const char* argv[]) {
160151
}
161152

162153
if (options.passOptions.validate) {
163-
if (!WasmValidator().validate(wasm, features)) {
154+
if (!WasmValidator().validate(wasm, options.getFeatures())) {
164155
WasmPrinter::printModule(&wasm);
165156
Fatal() << "error in validating input";
166157
}
@@ -171,9 +162,9 @@ int main(int argc, const char* argv[]) {
171162
if (fuzzPasses) {
172163
reader.pickPasses(options);
173164
}
174-
reader.build(fuzzAtomics);
165+
reader.build(options.getFeatures());
175166
if (options.passOptions.validate) {
176-
if (!WasmValidator().validate(wasm, features)) {
167+
if (!WasmValidator().validate(wasm, options.getFeatures())) {
177168
WasmPrinter::printModule(&wasm);
178169
std::cerr << "translate-to-fuzz must always generate a valid module";
179170
abort();
@@ -226,7 +217,7 @@ int main(int argc, const char* argv[]) {
226217
WasmBinaryBuilder parser(other, input, false);
227218
parser.read();
228219
if (options.passOptions.validate) {
229-
bool valid = WasmValidator().validate(other, features);
220+
bool valid = WasmValidator().validate(other, options.getFeatures());
230221
if (!valid) {
231222
WasmPrinter::printModule(&other);
232223
}
@@ -240,7 +231,7 @@ int main(int argc, const char* argv[]) {
240231
auto runPasses = [&]() {
241232
options.runPasses(*curr);
242233
if (options.passOptions.validate) {
243-
bool valid = WasmValidator().validate(*curr, features);
234+
bool valid = WasmValidator().validate(*curr, options.getFeatures());
244235
if (!valid) {
245236
WasmPrinter::printModule(&*curr);
246237
}

0 commit comments

Comments
 (0)