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
26namespace wasm {
27
28struct FeatureSet {
29 enum Feature : uint32_t {
30 None = 0,
31 Atomics = 1 << 0,
32 MutableGlobals = 1 << 1,
33 TruncSat = 1 << 2,
34 SIMD = 1 << 3,
35 BulkMemory = 1 << 4,
36 SignExt = 1 << 5,
37 ExceptionHandling = 1 << 6,
38 TailCall = 1 << 7,
39 ReferenceTypes = 1 << 8,
40 Multivalue = 1 << 9,
41 GC = 1 << 10,
42 Memory64 = 1 << 11,
43 // TODO: Remove this feature when the wasm spec stabilizes.
44 GCNNLocals = 1 << 12,
45 RelaxedSIMD = 1 << 13,
46 ExtendedConst = 1 << 14,
47 Strings = 1 << 15,
48 MultiMemories = 1 << 16,
49 MVP = None,
50 // Keep in sync with llvm default features:
51 // https://github.com/llvm/llvm-project/blob/c7576cb89d6c95f03968076e902d3adfd1996577/clang/lib/Basic/Targets/WebAssembly.cpp#L150-L153
52 Default = SignExt | MutableGlobals,
53 // GCNNLocals are opt-in: merely asking for "All" does not apply them. To
54 // get all possible values use AllPossible. See setAll() below for more
55 // details.
56 All = ((1 << 17) - 1) & ~GCNNLocals,
57 AllPossible = (1 << 17) - 1,
58 };
59
60 static std::string toString(Feature f) {
61 switch (f) {
62 case Atomics:
63 return "threads";
64 case MutableGlobals:
65 return "mutable-globals";
66 case TruncSat:
67 return "nontrapping-float-to-int";
68 case SIMD:
69 return "simd";
70 case BulkMemory:
71 return "bulk-memory";
72 case SignExt:
73 return "sign-ext";
74 case ExceptionHandling:
75 return "exception-handling";
76 case TailCall:
77 return "tail-call";
78 case ReferenceTypes:
79 return "reference-types";
80 case Multivalue:
81 return "multivalue";
82 case GC:
83 return "gc";
84 case Memory64:
85 return "memory64";
86 case GCNNLocals:
87 return "gc-nn-locals";
88 case RelaxedSIMD:
89 return "relaxed-simd";
90 case ExtendedConst:
91 return "extended-const";
92 case Strings:
93 return "strings";
94 case MultiMemories:
95 return "multi-memories";
96 default:
97 WASM_UNREACHABLE("unexpected feature");
98 }
99 }
100
101 std::string toString() const {
102 std::string ret;
103 uint32_t x = 1;
104 while (x & Feature::AllPossible) {
105 if (features & x) {
106 if (!ret.empty()) {
107 ret += ", ";
108 }
109 ret += toString(Feature(x));
110 }
111 x <<= 1;
112 }
113 return ret;
114 }
115
116 FeatureSet() : features(None) {}
117 FeatureSet(uint32_t features) : features(features) {}
118 operator uint32_t() const { return features; }
119
120 bool isMVP() const { return features == MVP; }
121 bool has(FeatureSet f) const { return (features & f) == f.features; }
122 bool hasAtomics() const { return (features & Atomics) != 0; }
123 bool hasMutableGlobals() const { return (features & MutableGlobals) != 0; }
124 bool hasTruncSat() const { return (features & TruncSat) != 0; }
125 bool hasSIMD() const { return (features & SIMD) != 0; }
126 bool hasBulkMemory() const { return (features & BulkMemory) != 0; }
127 bool hasSignExt() const { return (features & SignExt) != 0; }
128 bool hasExceptionHandling() const {
129 return (features & ExceptionHandling) != 0;
130 }
131 bool hasTailCall() const { return (features & TailCall) != 0; }
132 bool hasReferenceTypes() const { return (features & ReferenceTypes) != 0; }
133 bool hasMultivalue() const { return (features & Multivalue) != 0; }
134 bool hasGC() const { return (features & GC) != 0; }
135 bool hasMemory64() const { return (features & Memory64) != 0; }
136 bool hasGCNNLocals() const { return (features & GCNNLocals) != 0; }
137 bool hasRelaxedSIMD() const { return (features & RelaxedSIMD) != 0; }
138 bool hasExtendedConst() const { return (features & ExtendedConst) != 0; }
139 bool hasStrings() const { return (features & Strings) != 0; }
140 bool hasMultiMemories() const { return (features & MultiMemories) != 0; }
141 bool hasAll() const { return (features & AllPossible) != 0; }
142
143 void set(FeatureSet f, bool v = true) {
144 features = v ? (features | f) : (features & ~f);
145 }
146 void setAtomics(bool v = true) { set(f: Atomics, v); }
147 void setMutableGlobals(bool v = true) { set(f: MutableGlobals, v); }
148 void setTruncSat(bool v = true) { set(f: TruncSat, v); }
149 void setSIMD(bool v = true) { set(f: SIMD, v); }
150 void setBulkMemory(bool v = true) { set(f: BulkMemory, v); }
151 void setSignExt(bool v = true) { set(f: SignExt, v); }
152 void setExceptionHandling(bool v = true) { set(f: ExceptionHandling, v); }
153 void setTailCall(bool v = true) { set(f: TailCall, v); }
154 void setReferenceTypes(bool v = true) { set(f: ReferenceTypes, v); }
155 void setMultivalue(bool v = true) { set(f: Multivalue, v); }
156 void setGC(bool v = true) { set(f: GC, v); }
157 void setMemory64(bool v = true) { set(f: Memory64, v); }
158 void setGCNNLocals(bool v = true) { set(f: GCNNLocals, v); }
159 void setRelaxedSIMD(bool v = true) { set(f: RelaxedSIMD, v); }
160 void setExtendedConst(bool v = true) { set(f: ExtendedConst, v); }
161 void setStrings(bool v = true) { set(f: Strings, v); }
162 void setMultiMemories(bool v = true) { set(f: MultiMemories, v); }
163 void setMVP() { features = MVP; }
164 void setAll() {
165 // Do not set GCNNLocals, which forces the user to opt in to that feature
166 // explicitly. That is, wasm-opt -all will enable GC but *not* enable
167 // non-nullable locals. To get them, do wasm-opt -all --enable-gc-nn-locals
168 // FIXME: When the wasm spec stabilizes, this feature will go away, as the
169 // non-nullable locals experiment will either become the standard,
170 // or it will go away.
171 // Leave the old GCNNLocals value unmodified. This makes things like
172 // --enable-gc-nn-locals -all work (that is, if we enable the feature,
173 // then -all does not disable it; it simply does not enable it by itself).
174 auto oldGCNNLocals = hasGCNNLocals();
175 features = AllPossible;
176 setGCNNLocals(oldGCNNLocals);
177 }
178
179 void enable(const FeatureSet& other) { features |= other.features; }
180 void disable(const FeatureSet& other) {
181 features = features & ~other.features & AllPossible;
182 }
183
184 template<typename F> void iterFeatures(F f) const {
185 for (uint32_t feature = MVP + 1; feature < AllPossible; feature <<= 1) {
186 if (has(f: feature)) {
187 f(static_cast<Feature>(feature));
188 }
189 }
190 }
191
192 bool operator<=(const FeatureSet& other) const {
193 return !(features & ~other.features);
194 }
195
196 bool operator==(const FeatureSet& other) const {
197 return *this <= other && other <= *this;
198 }
199
200 bool operator!=(const FeatureSet& other) const { return !(*this == other); }
201
202 FeatureSet& operator|=(const FeatureSet& other) {
203 features |= other.features;
204 return *this;
205 }
206
207 uint32_t features;
208};
209
210} // namespace wasm
211
212#endif // wasm_features_h
213

source code of dart_sdk/third_party/binaryen/src/src/wasm-features.h