| /* | |
| * Copyright 2019 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. | |
| */ | |
| #ifndef wasm_features_h | |
| #define wasm_features_h | |
| #include <stdint.h> | |
| #include <string> | |
| #include "compiler-support.h" | |
| #include "support/utilities.h" | |
| namespace wasm { | |
| struct FeatureSet { | |
| enum Feature : uint32_t { | |
| None = 0, | |
| Atomics = 1 << 0, | |
| MutableGlobals = 1 << 1, | |
| TruncSat = 1 << 2, | |
| SIMD = 1 << 3, | |
| BulkMemory = 1 << 4, | |
| SignExt = 1 << 5, | |
| ExceptionHandling = 1 << 6, | |
| TailCall = 1 << 7, | |
| ReferenceTypes = 1 << 8, | |
| Multivalue = 1 << 9, | |
| GC = 1 << 10, | |
| Memory64 = 1 << 11, | |
| RelaxedSIMD = 1 << 12, | |
| ExtendedConst = 1 << 13, | |
| Strings = 1 << 14, | |
| MultiMemory = 1 << 15, | |
| TypedContinuations = 1 << 16, | |
| SharedEverything = 1 << 17, | |
| FP16 = 1 << 18, | |
| MVP = None, | |
| // Keep in sync with llvm default features: | |
| // https://github.com/llvm/llvm-project/blob/c7576cb89d6c95f03968076e902d3adfd1996577/clang/lib/Basic/Targets/WebAssembly.cpp#L150-L153 | |
| Default = SignExt | MutableGlobals, | |
| All = (1 << 19) - 1, | |
| }; | |
| static std::string toString(Feature f) { | |
| switch (f) { | |
| case Atomics: | |
| return "threads"; | |
| case MutableGlobals: | |
| return "mutable-globals"; | |
| case TruncSat: | |
| return "nontrapping-float-to-int"; | |
| case SIMD: | |
| return "simd"; | |
| case BulkMemory: | |
| return "bulk-memory"; | |
| case SignExt: | |
| return "sign-ext"; | |
| case ExceptionHandling: | |
| return "exception-handling"; | |
| case TailCall: | |
| return "tail-call"; | |
| case ReferenceTypes: | |
| return "reference-types"; | |
| case Multivalue: | |
| return "multivalue"; | |
| case GC: | |
| return "gc"; | |
| case Memory64: | |
| return "memory64"; | |
| case RelaxedSIMD: | |
| return "relaxed-simd"; | |
| case ExtendedConst: | |
| return "extended-const"; | |
| case Strings: | |
| return "strings"; | |
| case MultiMemory: | |
| return "multimemory"; | |
| case TypedContinuations: | |
| return "typed-continuations"; | |
| case SharedEverything: | |
| return "shared-everything"; | |
| case FP16: | |
| return "fp16"; | |
| default: | |
| WASM_UNREACHABLE("unexpected feature"); | |
| } | |
| } | |
| std::string toString() const { | |
| std::string ret; | |
| uint32_t x = 1; | |
| while (x & Feature::All) { | |
| if (features & x) { | |
| if (!ret.empty()) { | |
| ret += ", "; | |
| } | |
| ret += toString(Feature(x)); | |
| } | |
| x <<= 1; | |
| } | |
| return ret; | |
| } | |
| FeatureSet() : features(None) {} | |
| FeatureSet(uint32_t features) : features(features) {} | |
| operator uint32_t() const { return features; } | |
| bool isMVP() const { return features == MVP; } | |
| bool has(FeatureSet f) const { return (features & f) == f.features; } | |
| bool hasAtomics() const { return (features & Atomics) != 0; } | |
| bool hasMutableGlobals() const { return (features & MutableGlobals) != 0; } | |
| bool hasTruncSat() const { return (features & TruncSat) != 0; } | |
| bool hasSIMD() const { return (features & SIMD) != 0; } | |
| bool hasBulkMemory() const { return (features & BulkMemory) != 0; } | |
| bool hasSignExt() const { return (features & SignExt) != 0; } | |
| bool hasExceptionHandling() const { | |
| return (features & ExceptionHandling) != 0; | |
| } | |
| bool hasTailCall() const { return (features & TailCall) != 0; } | |
| bool hasReferenceTypes() const { return (features & ReferenceTypes) != 0; } | |
| bool hasMultivalue() const { return (features & Multivalue) != 0; } | |
| bool hasGC() const { return (features & GC) != 0; } | |
| bool hasMemory64() const { return (features & Memory64) != 0; } | |
| bool hasRelaxedSIMD() const { return (features & RelaxedSIMD) != 0; } | |
| bool hasExtendedConst() const { return (features & ExtendedConst) != 0; } | |
| bool hasStrings() const { return (features & Strings) != 0; } | |
| bool hasMultiMemory() const { return (features & MultiMemory) != 0; } | |
| bool hasTypedContinuations() const { | |
| return (features & TypedContinuations) != 0; | |
| } | |
| bool hasSharedEverything() const { | |
| return (features & SharedEverything) != 0; | |
| } | |
| bool hasFP16() const { return (features & FP16) != 0; } | |
| bool hasAll() const { return (features & All) != 0; } | |
| void set(FeatureSet f, bool v = true) { | |
| features = v ? (features | f) : (features & ~f); | |
| } | |
| void setAtomics(bool v = true) { set(Atomics, v); } | |
| void setMutableGlobals(bool v = true) { set(MutableGlobals, v); } | |
| void setTruncSat(bool v = true) { set(TruncSat, v); } | |
| void setSIMD(bool v = true) { set(SIMD, v); } | |
| void setBulkMemory(bool v = true) { set(BulkMemory, v); } | |
| void setSignExt(bool v = true) { set(SignExt, v); } | |
| void setExceptionHandling(bool v = true) { set(ExceptionHandling, v); } | |
| void setTailCall(bool v = true) { set(TailCall, v); } | |
| void setReferenceTypes(bool v = true) { set(ReferenceTypes, v); } | |
| void setMultivalue(bool v = true) { set(Multivalue, v); } | |
| void setGC(bool v = true) { set(GC, v); } | |
| void setMemory64(bool v = true) { set(Memory64, v); } | |
| void setRelaxedSIMD(bool v = true) { set(RelaxedSIMD, v); } | |
| void setExtendedConst(bool v = true) { set(ExtendedConst, v); } | |
| void setStrings(bool v = true) { set(Strings, v); } | |
| void setMultiMemory(bool v = true) { set(MultiMemory, v); } | |
| void setTypedContinuations(bool v = true) { set(TypedContinuations, v); } | |
| void setSharedEverything(bool v = true) { set(SharedEverything, v); } | |
| void setFP16(bool v = true) { set(FP16, v); } | |
| void setMVP() { features = MVP; } | |
| void setAll() { features = All; } | |
| void enable(const FeatureSet& other) { features |= other.features; } | |
| void disable(const FeatureSet& other) { features &= ~other.features; } | |
| template<typename F> void iterFeatures(F f) const { | |
| for (uint32_t feature = MVP + 1; feature < All; feature <<= 1) { | |
| if (has(feature)) { | |
| f(static_cast<Feature>(feature)); | |
| } | |
| } | |
| } | |
| bool operator<=(const FeatureSet& other) const { | |
| return !(features & ~other.features); | |
| } | |
| bool operator==(const FeatureSet& other) const { | |
| return *this <= other && other <= *this; | |
| } | |
| bool operator!=(const FeatureSet& other) const { return !(*this == other); } | |
| FeatureSet& operator|=(const FeatureSet& other) { | |
| features |= other.features; | |
| return *this; | |
| } | |
| FeatureSet operator-(const FeatureSet& other) const { | |
| return features & ~other.features; | |
| } | |
| FeatureSet operator-(Feature other) const { | |
| return *this - FeatureSet(other); | |
| } | |
| uint32_t features; | |
| }; | |
| } // namespace wasm | |
| #endif // wasm_features_h |