1 /*
2  * Copyright 2019 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 #ifndef wasm_features_h
18 #define wasm_features_h
19 
20 #include <stdint.h>
21 #include <string>
22 
23 #include "compiler-support.h"
24 #include "support/utilities.h"
25 
26 struct FeatureSet {
27   enum Feature : uint32_t {
28     MVP = 0,
29     Atomics = 1 << 0,
30     MutableGlobals = 1 << 1,
31     TruncSat = 1 << 2,
32     SIMD = 1 << 3,
33     BulkMemory = 1 << 4,
34     SignExt = 1 << 5,
35     ExceptionHandling = 1 << 6,
36     TailCall = 1 << 7,
37     ReferenceTypes = 1 << 8,
38     Multivalue = 1 << 9,
39     GC = 1 << 10,
40     Memory64 = 1 << 11,
41     All = (1 << 12) - 1
42   };
43 
toStringFeatureSet44   static std::string toString(Feature f) {
45     switch (f) {
46       case Atomics:
47         return "threads";
48       case MutableGlobals:
49         return "mutable-globals";
50       case TruncSat:
51         return "nontrapping-float-to-int";
52       case SIMD:
53         return "simd";
54       case BulkMemory:
55         return "bulk-memory";
56       case SignExt:
57         return "sign-ext";
58       case ExceptionHandling:
59         return "exception-handling";
60       case TailCall:
61         return "tail-call";
62       case ReferenceTypes:
63         return "reference-types";
64       case Multivalue:
65         return "multivalue";
66       case GC:
67         return "gc";
68       case Memory64:
69         return "memory64";
70       default:
71         WASM_UNREACHABLE("unexpected feature");
72     }
73   }
74 
FeatureSetFeatureSet75   FeatureSet() : features(MVP) {}
FeatureSetFeatureSet76   FeatureSet(uint32_t features) : features(features) {}
uint32_tFeatureSet77   operator uint32_t() const { return features; }
78 
isMVPFeatureSet79   bool isMVP() const { return features == MVP; }
hasFeatureSet80   bool has(FeatureSet f) { return (features & f) == f; }
hasAtomicsFeatureSet81   bool hasAtomics() const { return (features & Atomics) != 0; }
hasMutableGlobalsFeatureSet82   bool hasMutableGlobals() const { return (features & MutableGlobals) != 0; }
hasTruncSatFeatureSet83   bool hasTruncSat() const { return (features & TruncSat) != 0; }
hasSIMDFeatureSet84   bool hasSIMD() const { return (features & SIMD) != 0; }
hasBulkMemoryFeatureSet85   bool hasBulkMemory() const { return (features & BulkMemory) != 0; }
hasSignExtFeatureSet86   bool hasSignExt() const { return (features & SignExt) != 0; }
hasExceptionHandlingFeatureSet87   bool hasExceptionHandling() const {
88     return (features & ExceptionHandling) != 0;
89   }
hasTailCallFeatureSet90   bool hasTailCall() const { return (features & TailCall) != 0; }
hasReferenceTypesFeatureSet91   bool hasReferenceTypes() const { return (features & ReferenceTypes) != 0; }
hasMultivalueFeatureSet92   bool hasMultivalue() const { return (features & Multivalue) != 0; }
hasGCFeatureSet93   bool hasGC() const { return (features & GC) != 0; }
hasMemory64FeatureSet94   bool hasMemory64() const { return (features & Memory64) != 0; }
hasAllFeatureSet95   bool hasAll() const { return (features & All) != 0; }
96 
makeMVPFeatureSet97   void makeMVP() { features = MVP; }
98   void set(FeatureSet f, bool v = true) {
99     features = v ? (features | f) : (features & ~f);
100   }
101   void setAtomics(bool v = true) { set(Atomics, v); }
102   void setMutableGlobals(bool v = true) { set(MutableGlobals, v); }
103   void setTruncSat(bool v = true) { set(TruncSat, v); }
104   void setSIMD(bool v = true) { set(SIMD, v); }
105   void setBulkMemory(bool v = true) { set(BulkMemory, v); }
106   void setSignExt(bool v = true) { set(SignExt, v); }
107   void setExceptionHandling(bool v = true) { set(ExceptionHandling, v); }
108   void setTailCall(bool v = true) { set(TailCall, v); }
109   void setReferenceTypes(bool v = true) { set(ReferenceTypes, v); }
110   void setMultivalue(bool v = true) { set(Multivalue, v); }
111   void setGC(bool v = true) { set(GC, v); }
112   void setMemory64(bool v = true) { set(Memory64, v); }
113   void setAll(bool v = true) { features = v ? All : MVP; }
114 
enableFeatureSet115   void enable(const FeatureSet& other) { features |= other.features; }
disableFeatureSet116   void disable(const FeatureSet& other) {
117     features = features & ~other.features & All;
118   }
119 
iterFeaturesFeatureSet120   template<typename F> void iterFeatures(F f) {
121     for (uint32_t feature = MVP + 1; feature < All; feature <<= 1) {
122       if (has(feature)) {
123         f(static_cast<Feature>(feature));
124       }
125     }
126   }
127 
128   bool operator<=(const FeatureSet& other) const {
129     return !(features & ~other.features);
130   }
131 
132   bool operator==(const FeatureSet& other) const {
133     return *this <= other && other <= *this;
134   }
135 
136   bool operator!=(const FeatureSet& other) const { return !(*this == other); }
137 
138   FeatureSet& operator|=(const FeatureSet& other) {
139     features |= other.features;
140     return *this;
141   }
142 
143   uint32_t features;
144 };
145 
146 #endif // wasm_features_h
147