summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/binaryen-c.cpp2
-rw-r--r--src/pass.h2
-rw-r--r--src/passes/Print.cpp2
-rw-r--r--src/tools/asm2wasm.cpp5
-rw-r--r--src/tools/feature-options.h81
-rw-r--r--src/tools/fuzzing.h18
-rw-r--r--src/tools/optimization-options.h10
-rw-r--r--src/tools/wasm-as.cpp2
-rw-r--r--src/tools/wasm-opt.cpp19
-rw-r--r--src/tools/wasm-reduce.cpp2
-rw-r--r--src/tools/wasm-shell.cpp10
-rw-r--r--src/wasm-validator.h2
-rw-r--r--src/wasm.h40
-rw-r--r--src/wasm/wasm-validator.cpp18
14 files changed, 154 insertions, 59 deletions
diff --git a/src/binaryen-c.cpp b/src/binaryen-c.cpp
index ebb8bb694..d098810e2 100644
--- a/src/binaryen-c.cpp
+++ b/src/binaryen-c.cpp
@@ -1936,7 +1936,7 @@ int BinaryenModuleValidate(BinaryenModuleRef module) {
Module* wasm = (Module*)module;
// TODO add feature selection support to C API
- FeatureSet features = Feature::Atomics;
+ FeatureSet features = FeatureSet::All;
return WasmValidator().validate(*wasm, features) ? 1 : 0;
}
diff --git a/src/pass.h b/src/pass.h
index 8064edc32..0a3d85e02 100644
--- a/src/pass.h
+++ b/src/pass.h
@@ -63,7 +63,7 @@ struct PassOptions {
int shrinkLevel = 0; // 0, 1, 2 correspond to -O0, -Os, -Oz
bool ignoreImplicitTraps = false; // optimize assuming things like div by 0, bad load/store, will not trap
bool debugInfo = false; // whether to try to preserve debug info through, which are special calls
- FeatureSet features = Feature::MVP; // Which wasm features to accept, and be allowed to use
+ FeatureSet features = FeatureSet::All; // Which wasm features to accept, and be allowed to use
void setDefaultOptimizationOptions() {
// -Os is our default
diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp
index 02fc2a83b..e874321cd 100644
--- a/src/passes/Print.cpp
+++ b/src/passes/Print.cpp
@@ -1184,7 +1184,7 @@ Pass* createPrintStackIRPass() {
std::ostream& WasmPrinter::printModule(Module* module, std::ostream& o) {
PassRunner passRunner(module);
- passRunner.setFeatures(Feature::All);
+ passRunner.setFeatures(FeatureSet::All);
passRunner.setIsNested(true);
passRunner.add<Printer>(&o);
passRunner.run();
diff --git a/src/tools/asm2wasm.cpp b/src/tools/asm2wasm.cpp
index d5e5827c5..a001c08a6 100644
--- a/src/tools/asm2wasm.cpp
+++ b/src/tools/asm2wasm.cpp
@@ -115,9 +115,6 @@ int main(int argc, const char *argv[]) {
.add("--emit-text", "-S", "Emit text instead of binary for the output file",
Options::Arguments::Zero,
[&](Options *o, const std::string& argument) { emitBinary = false; })
- .add("--enable-threads", "-a", "Enable the Atomics wasm feature",
- Options::Arguments::Zero,
- [&](Options *o, const std::string& argument) { options.passOptions.features |= Feature::Atomics; })
.add_positional("INFILE", Options::Arguments::One,
[](Options *o, const std::string& argument) {
o->extra["infile"] = argument;
@@ -188,7 +185,7 @@ int main(int argc, const char *argv[]) {
if (memInit != options.extra.end()) {
if (options.runningDefaultOptimizationPasses()) {
PassRunner runner(&wasm);
- runner.setFeatures(options.features);
+ runner.setFeatures(options.getFeatures());
runner.add("memory-packing");
runner.run();
}
diff --git a/src/tools/feature-options.h b/src/tools/feature-options.h
new file mode 100644
index 000000000..3b35656fc
--- /dev/null
+++ b/src/tools/feature-options.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2018 WebAssembly Community Group participants
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "support/command-line.h"
+#include "pass.h"
+
+//
+// Shared optimization options for commandline tools
+//
+
+namespace wasm {
+
+struct FeatureOptions : public Options {
+ PassOptions passOptions;
+
+ FeatureOptions(const std::string& command, const std::string& description)
+ : Options(command, description) {
+ (*this)
+ .add("--mvp-features", "-mvp", "Disable all non-MVP features (default)",
+ Options::Arguments::Zero,
+ [this](Options *o, const std::string& arguments) {
+ passOptions.features = FeatureSet::MVP;
+ })
+ .add("--all-features", "-all", "Enable all features",
+ Options::Arguments::Zero,
+ [this](Options *o, const std::string& arguments) {
+ passOptions.features = FeatureSet::All;
+ })
+ .add("--enable-threads", "", "Enable atomic operations",
+ Options::Arguments::Zero,
+ [this](Options *o, const std::string& arguments) {
+ passOptions.features.setAtomics();
+ })
+ .add("--disable-threads", "", "Disable atomic operations",
+ Options::Arguments::Zero,
+ [this](Options *o, const std::string& arguments) {
+ passOptions.features.setAtomics(false);
+ })
+ .add("--enable-mutable-globals", "", "Enable mutable globals",
+ Options::Arguments::Zero,
+ [this](Options *o, const std::string& arguments) {
+ passOptions.features.setMutableGlobals();
+ })
+ .add("--disable-mutable-globals", "", "Disable mutable globals",
+ Options::Arguments::Zero,
+ [this](Options *o, const std::string& arguments) {
+ passOptions.features.setMutableGlobals(false);
+ })
+ .add("--enable-nontrapping-float-to-int", "",
+ "Enable nontrapping float-to-int operations",
+ Options::Arguments::Zero,
+ [this](Options *o, const std::string& arguments) {
+ passOptions.features.setTruncSat();
+ })
+ .add("--disable-nontrapping-float-to-int", "",
+ "Disable nontrapping float-to-int operations",
+ Options::Arguments::Zero,
+ [this](Options *o, const std::string& arguments) {
+ passOptions.features.setTruncSat(false);
+ });
+ }
+
+ FeatureSet getFeatures() const {
+ return passOptions.features;
+ }
+};
+
+} // namespace wasm
diff --git a/src/tools/fuzzing.h b/src/tools/fuzzing.h
index 7954229c7..8f7123a78 100644
--- a/src/tools/fuzzing.h
+++ b/src/tools/fuzzing.h
@@ -123,8 +123,8 @@ public:
std::cout << "shrink level: " << options.passOptions.shrinkLevel << '\n';
}
- void build(bool initEmitAtomics = true) {
- emitAtomics = initEmitAtomics;
+ void build(FeatureSet features_) {
+ features = features_;
setupMemory();
setupTable();
setupGlobals();
@@ -179,8 +179,8 @@ private:
// cross-VM comparisons harder)
static const bool DE_NAN = true;
- // Whether to emit atomics
- bool emitAtomics = true;
+ // Features allowed to be emitted
+ FeatureSet features = FeatureSet::All;
// Whether to emit atomic waits (which in single-threaded mode, may hang...)
static const bool ATOMIC_WAITS = false;
@@ -1118,7 +1118,7 @@ private:
Expression* makeLoad(Type type) {
auto* ret = makeNonAtomicLoad(type);
if (type != i32 && type != i64) return ret;
- if (!emitAtomics || oneIn(2)) return ret;
+ if (!features.hasAtomics() || oneIn(2)) return ret;
// make it atomic
wasm.memory.shared = true;
ret->isAtomic = true;
@@ -1181,7 +1181,7 @@ private:
Store* makeStore(Type type) {
auto* ret = makeNonAtomicStore(type);
if (ret->value->type != i32 && ret->value->type != i64) return ret;
- if (!emitAtomics || oneIn(2)) return ret;
+ if (!features.hasAtomics() || oneIn(2)) return ret;
// make it atomic
wasm.memory.shared = true;
ret->isAtomic = true;
@@ -1314,7 +1314,7 @@ private:
case i32: {
switch (upTo(4)) {
case 0: {
- if (emitAtomics) {
+ if (features.hasAtomics()) {
return makeUnary({ pick(EqZInt32, ClzInt32, CtzInt32, PopcntInt32, ExtendS8Int32, ExtendS16Int32), make(i32) });
} else {
return makeUnary({ pick(EqZInt32, ClzInt32, CtzInt32, PopcntInt32), make(i32) });
@@ -1330,7 +1330,7 @@ private:
case i64: {
switch (upTo(4)) {
case 0: {
- if (emitAtomics) {
+ if (features.hasAtomics()) {
return makeUnary({ pick(ClzInt64, CtzInt64, PopcntInt64, ExtendS8Int64, ExtendS16Int64, ExtendS32Int64), make(i64) });
} else {
return makeUnary({ pick(ClzInt64, CtzInt64, PopcntInt64), make(i64) });
@@ -1465,7 +1465,7 @@ private:
}
Expression* makeAtomic(Type type) {
- if (!emitAtomics || (type != i32 && type != i64)) return makeTrivial(type);
+ if (!features.hasAtomics() || (type != i32 && type != i64)) return makeTrivial(type);
wasm.memory.shared = true;
if (type == i32 && oneIn(2)) {
if (ATOMIC_WAITS && oneIn(2)) {
diff --git a/src/tools/optimization-options.h b/src/tools/optimization-options.h
index abe3bcd6d..7849be375 100644
--- a/src/tools/optimization-options.h
+++ b/src/tools/optimization-options.h
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "support/command-line.h"
+#include "feature-options.h"
//
// Shared optimization options for commandline tools
@@ -22,14 +22,12 @@
namespace wasm {
-struct OptimizationOptions : public Options {
+struct OptimizationOptions : public FeatureOptions {
static constexpr const char* DEFAULT_OPT_PASSES = "O";
std::vector<std::string> passes;
- PassOptions passOptions;
- FeatureSet features = Feature::Atomics;
- OptimizationOptions(const std::string& command, const std::string& description) : Options(command, description) {
+ OptimizationOptions(const std::string& command, const std::string& description) : FeatureOptions(command, description) {
(*this).add("", "-O", "execute default optimization passes",
Options::Arguments::Zero,
[this](Options*, const std::string&) {
@@ -132,7 +130,7 @@ struct OptimizationOptions : public Options {
void runPasses(Module& wasm) {
PassRunner passRunner(&wasm, passOptions);
if (debug) passRunner.setDebug(true);
- passRunner.setFeatures(features);
+ passRunner.setFeatures(passOptions.features);
for (auto& pass : passes) {
if (pass == DEFAULT_OPT_PASSES) {
passRunner.addDefaultOptimizationPasses();
diff --git a/src/tools/wasm-as.cpp b/src/tools/wasm-as.cpp
index 46885dec0..c504c2a81 100644
--- a/src/tools/wasm-as.cpp
+++ b/src/tools/wasm-as.cpp
@@ -93,7 +93,7 @@ int main(int argc, const char *argv[]) {
if (options.extra["validate"] != "none") {
if (options.debug) std::cerr << "Validating..." << std::endl;
- if (!wasm::WasmValidator().validate(wasm, Feature::All,
+ if (!wasm::WasmValidator().validate(wasm, FeatureSet::All,
WasmValidator::Globally | (options.extra["validate"] == "web" ? WasmValidator::Web : 0))) {
WasmPrinter::printModule(&wasm);
Fatal() << "Error: input module is not valid.\n";
diff --git a/src/tools/wasm-opt.cpp b/src/tools/wasm-opt.cpp
index 421bcca59..3e04fc644 100644
--- a/src/tools/wasm-opt.cpp
+++ b/src/tools/wasm-opt.cpp
@@ -69,7 +69,6 @@ int main(int argc, const char* argv[]) {
bool fuzzBinary = false;
std::string extraFuzzCommand;
bool translateToFuzz = false;
- bool fuzzAtomics = true;
bool fuzzPasses = false;
std::string emitJSWrapper;
std::string emitSpecWrapper;
@@ -106,9 +105,6 @@ int main(int argc, const char* argv[]) {
.add("--translate-to-fuzz", "-ttf", "Translate the input into a valid wasm module *somehow*, useful for fuzzing",
Options::Arguments::Zero,
[&](Options *o, const std::string& arguments) { translateToFuzz = true; })
- .add("--no-fuzz-atomics", "-nfa", "Disable generation of atomic opcodes with translate-to-fuzz (on by default)",
- Options::Arguments::Zero,
- [&](Options *o, const std::string& arguments) { fuzzAtomics = false; })
.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)",
Options::Arguments::Zero,
[&](Options *o, const std::string& arguments) { fuzzPasses = true; })
@@ -134,11 +130,6 @@ int main(int argc, const char* argv[]) {
options.parse(argc, argv);
Module wasm;
- // It should be safe to just always enable atomics in wasm-opt, because we
- // don't expect any passes to accidentally generate atomic ops
- FeatureSet features = Feature::Atomics;
- // Same for MutableGlobals
- features |= Feature::MutableGlobals;
if (options.debug) std::cerr << "reading...\n";
@@ -160,7 +151,7 @@ int main(int argc, const char* argv[]) {
}
if (options.passOptions.validate) {
- if (!WasmValidator().validate(wasm, features)) {
+ if (!WasmValidator().validate(wasm, options.getFeatures())) {
WasmPrinter::printModule(&wasm);
Fatal() << "error in validating input";
}
@@ -171,9 +162,9 @@ int main(int argc, const char* argv[]) {
if (fuzzPasses) {
reader.pickPasses(options);
}
- reader.build(fuzzAtomics);
+ reader.build(options.getFeatures());
if (options.passOptions.validate) {
- if (!WasmValidator().validate(wasm, features)) {
+ if (!WasmValidator().validate(wasm, options.getFeatures())) {
WasmPrinter::printModule(&wasm);
std::cerr << "translate-to-fuzz must always generate a valid module";
abort();
@@ -226,7 +217,7 @@ int main(int argc, const char* argv[]) {
WasmBinaryBuilder parser(other, input, false);
parser.read();
if (options.passOptions.validate) {
- bool valid = WasmValidator().validate(other, features);
+ bool valid = WasmValidator().validate(other, options.getFeatures());
if (!valid) {
WasmPrinter::printModule(&other);
}
@@ -240,7 +231,7 @@ int main(int argc, const char* argv[]) {
auto runPasses = [&]() {
options.runPasses(*curr);
if (options.passOptions.validate) {
- bool valid = WasmValidator().validate(*curr, features);
+ bool valid = WasmValidator().validate(*curr, options.getFeatures());
if (!valid) {
WasmPrinter::printModule(&*curr);
}
diff --git a/src/tools/wasm-reduce.cpp b/src/tools/wasm-reduce.cpp
index 5c1f98d88..8c5df7a1b 100644
--- a/src/tools/wasm-reduce.cpp
+++ b/src/tools/wasm-reduce.cpp
@@ -797,7 +797,7 @@ struct Reducer : public WalkerPass<PostWalker<Reducer, UnifiedExpressionVisitor<
FunctionReferenceRemover referenceRemover(names);
referenceRemover.walkModule(module.get());
- if (WasmValidator().validate(*module, Feature::All, WasmValidator::Globally | WasmValidator::Quiet) &&
+ if (WasmValidator().validate(*module, FeatureSet::All, WasmValidator::Globally | WasmValidator::Quiet) &&
writeAndTestReduction()) {
std::cerr << "| removed " << names.size() << " functions\n";
return true;
diff --git a/src/tools/wasm-shell.cpp b/src/tools/wasm-shell.cpp
index 9ad1fa799..d8cd11f41 100644
--- a/src/tools/wasm-shell.cpp
+++ b/src/tools/wasm-shell.cpp
@@ -23,9 +23,9 @@
#include <memory>
#include "execution-results.h"
+#include "feature-options.h"
#include "pass.h"
#include "shell-interface.h"
-#include "support/command-line.h"
#include "support/file.h"
#include "wasm-interpreter.h"
#include "wasm-printing.h"
@@ -233,14 +233,14 @@ int main(int argc, const char* argv[]) {
Name entry;
std::set<size_t> skipped;
- Options options("wasm-shell", "Execute .wast files");
+ FeatureOptions options("wasm-shell", "Execute .wast files");
options
.add(
- "--entry", "-e", "call the entry point after parsing the module",
+ "--entry", "-e", "Call the entry point after parsing the module",
Options::Arguments::One,
[&entry](Options*, const std::string& argument) { entry = argument; })
.add(
- "--skip", "-s", "skip input on certain lines (comma-separated-list)",
+ "--skip", "-s", "Skip input on certain lines (comma-separated-list)",
Options::Arguments::One,
[&skipped](Options*, const std::string& argument) {
size_t i = 0;
@@ -292,7 +292,7 @@ int main(int argc, const char* argv[]) {
builders[moduleName].swap(builder);
modules[moduleName].swap(module);
i++;
- bool valid = WasmValidator().validate(*modules[moduleName]);
+ bool valid = WasmValidator().validate(*modules[moduleName], options.getFeatures());
if (!valid) {
WasmPrinter::printModule(modules[moduleName].get());
}
diff --git a/src/wasm-validator.h b/src/wasm-validator.h
index 81d65a6bd..3c0b6018b 100644
--- a/src/wasm-validator.h
+++ b/src/wasm-validator.h
@@ -57,7 +57,7 @@ struct WasmValidator {
};
typedef uint32_t Flags;
- bool validate(Module& module, FeatureSet features = MVP, Flags flags = Globally);
+ bool validate(Module& module, FeatureSet features = FeatureSet::MVP, Flags flags = Globally);
};
} // namespace wasm
diff --git a/src/wasm.h b/src/wasm.h
index 424f89d0b..1d5677134 100644
--- a/src/wasm.h
+++ b/src/wasm.h
@@ -37,13 +37,41 @@
namespace wasm {
-enum Feature : uint32_t {
- MVP = 0,
- Atomics = 1 << 0,
- MutableGlobals = 1 << 1,
- All = 0xffffffff,
+struct FeatureSet {
+ enum Feature : uint32_t {
+ MVP = 0,
+ Atomics = 1 << 0,
+ MutableGlobals = 1 << 1,
+ TruncSat = 1 << 2,
+ All = Atomics | MutableGlobals | TruncSat
+ };
+
+ FeatureSet() : features(MVP) {}
+ FeatureSet(uint32_t features) : features(features) {}
+
+ bool isMVP() const { return features == MVP; }
+ bool hasAtomics() const { return features & Atomics; }
+ bool hasMutableGlobals() const { return features & MutableGlobals; }
+ bool hasTruncSat() const { return features & TruncSat; }
+ bool hasAll() const { return features & (Atomics | MutableGlobals | TruncSat); }
+
+ void makeMVP() { features = MVP; }
+ void setAtomics(bool v = true) {
+ features = v ? (features | Atomics) : (features & ~Atomics);
+ }
+ void setMutableGlobals(bool v = true) {
+ features = v ? (features | MutableGlobals) : (features & ~MutableGlobals);
+ }
+ void setTruncSat(bool v = true) {
+ features = v ? (features | TruncSat) : (features & ~TruncSat);
+ }
+ void setAll(bool v = true) {
+ features = v ? All : MVP;
+ }
+
+ private:
+ uint32_t features;
};
-typedef uint32_t FeatureSet;
// An index in a wasm module
typedef uint32_t Index;
diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp
index b88a94e6d..fa239688f 100644
--- a/src/wasm/wasm-validator.cpp
+++ b/src/wasm/wasm-validator.cpp
@@ -497,7 +497,7 @@ void FunctionValidator::visitSetGlobal(SetGlobal* curr) {
}
void FunctionValidator::visitLoad(Load* curr) {
- if (curr->isAtomic) shouldBeTrue(info.features & Feature::Atomics, curr, "Atomic operation (atomics are disabled)");
+ if (curr->isAtomic) shouldBeTrue(info.features.hasAtomics(), curr, "Atomic operation (atomics are disabled)");
shouldBeFalse(curr->isAtomic && !getModule()->memory.shared, curr, "Atomic operation with non-shared memory");
validateMemBytes(curr->bytes, curr->type, curr);
validateAlignment(curr->align, curr->type, curr->bytes, curr->isAtomic, curr);
@@ -509,7 +509,7 @@ void FunctionValidator::visitLoad(Load* curr) {
}
void FunctionValidator::visitStore(Store* curr) {
- if (curr->isAtomic) shouldBeTrue(info.features & Feature::Atomics, curr, "Atomic operation (atomics are disabled)");
+ if (curr->isAtomic) shouldBeTrue(info.features.hasAtomics(), curr, "Atomic operation (atomics are disabled)");
shouldBeFalse(curr->isAtomic && !getModule()->memory.shared, curr, "Atomic operation with non-shared memory");
validateMemBytes(curr->bytes, curr->valueType, curr);
validateAlignment(curr->align, curr->type, curr->bytes, curr->isAtomic, curr);
@@ -522,7 +522,7 @@ void FunctionValidator::visitStore(Store* curr) {
}
void FunctionValidator::visitAtomicRMW(AtomicRMW* curr) {
- shouldBeTrue(info.features & Feature::Atomics, curr, "Atomic operation (atomics are disabled)");
+ shouldBeTrue(info.features.hasAtomics(), curr, "Atomic operation (atomics are disabled)");
shouldBeFalse(!getModule()->memory.shared, curr, "Atomic operation with non-shared memory");
validateMemBytes(curr->bytes, curr->type, curr);
shouldBeEqualOrFirstIsUnreachable(curr->ptr->type, i32, curr, "AtomicRMW pointer type must be i32");
@@ -531,7 +531,7 @@ void FunctionValidator::visitAtomicRMW(AtomicRMW* curr) {
}
void FunctionValidator::visitAtomicCmpxchg(AtomicCmpxchg* curr) {
- shouldBeTrue(info.features & Feature::Atomics, curr, "Atomic operation (atomics are disabled)");
+ shouldBeTrue(info.features.hasAtomics(), curr, "Atomic operation (atomics are disabled)");
shouldBeFalse(!getModule()->memory.shared, curr, "Atomic operation with non-shared memory");
validateMemBytes(curr->bytes, curr->type, curr);
shouldBeEqualOrFirstIsUnreachable(curr->ptr->type, i32, curr, "cmpxchg pointer type must be i32");
@@ -544,7 +544,7 @@ void FunctionValidator::visitAtomicCmpxchg(AtomicCmpxchg* curr) {
}
void FunctionValidator::visitAtomicWait(AtomicWait* curr) {
- shouldBeTrue(info.features & Feature::Atomics, curr, "Atomic operation (atomics are disabled)");
+ shouldBeTrue(info.features.hasAtomics(), curr, "Atomic operation (atomics are disabled)");
shouldBeFalse(!getModule()->memory.shared, curr, "Atomic operation with non-shared memory");
shouldBeEqualOrFirstIsUnreachable(curr->type, i32, curr, "AtomicWait must have type i32");
shouldBeEqualOrFirstIsUnreachable(curr->ptr->type, i32, curr, "AtomicWait pointer type must be i32");
@@ -554,7 +554,7 @@ void FunctionValidator::visitAtomicWait(AtomicWait* curr) {
}
void FunctionValidator::visitAtomicWake(AtomicWake* curr) {
- shouldBeTrue(info.features & Feature::Atomics, curr, "Atomic operation (atomics are disabled)");
+ shouldBeTrue(info.features.hasAtomics(), curr, "Atomic operation (atomics are disabled)");
shouldBeFalse(!getModule()->memory.shared, curr, "Atomic operation with non-shared memory");
shouldBeEqualOrFirstIsUnreachable(curr->type, i32, curr, "AtomicWake must have type i32");
shouldBeEqualOrFirstIsUnreachable(curr->ptr->type, i32, curr, "AtomicWake pointer type must be i32");
@@ -923,7 +923,7 @@ static void validateImports(Module& module, ValidationInfo& info) {
}
}
});
- if (!(info.features & Feature::MutableGlobals)) {
+ if (!info.features.hasMutableGlobals()) {
ModuleUtils::iterImportedGlobals(module, [&](Global* curr) {
info.shouldBeFalse(curr->mutable_, curr->name, "Imported global cannot be mutable");
});
@@ -940,7 +940,7 @@ static void validateExports(Module& module, ValidationInfo& info) {
info.shouldBeUnequal(param, i64, f->name, "Exported function must not have i64 parameters");
}
}
- } else if (curr->kind == ExternalKind::Global && !(info.features & Feature::MutableGlobals)) {
+ } else if (curr->kind == ExternalKind::Global && !info.features.hasMutableGlobals()) {
if (Global* g = module.getGlobalOrNull(curr->value)) {
info.shouldBeFalse(g->mutable_, g->name, "Exported global cannot be mutable");
}
@@ -981,7 +981,7 @@ static void validateMemory(Module& module, ValidationInfo& info) {
info.shouldBeFalse(curr.initial > curr.max, "memory", "memory max >= initial");
info.shouldBeTrue(!curr.hasMax() || curr.max <= Memory::kMaxSize, "memory", "max memory must be <= 4GB, or unlimited");
info.shouldBeTrue(!curr.shared || curr.hasMax(), "memory", "shared memory must have max size");
- if (curr.shared) info.shouldBeTrue(info.features & Feature::Atomics, "memory", "memory is shared, but atomics are disabled");
+ if (curr.shared) info.shouldBeTrue(info.features.hasAtomics(), "memory", "memory is shared, but atomics are disabled");
for (auto& segment : curr.segments) {
if (!info.shouldBeEqual(segment.offset->type, i32, segment.offset, "segment offset should be i32")) continue;
info.shouldBeTrue(checkOffset(segment.offset, segment.data.size(), curr.initial * Memory::kPageSize), segment.offset, "segment offset should be reasonable");