1package api
2
3import (
4 "fmt"
5 "strings"
6)
7
8// CoreFeatures is a bit flag of WebAssembly Core specification features. See
9// https://github.com/WebAssembly/proposals for proposals and their status.
10//
11// Constants define individual features, such as CoreFeatureMultiValue, or
12// groups of "finished" features, assigned to a WebAssembly Core Specification
13// version, e.g. CoreFeaturesV1 or CoreFeaturesV2.
14//
15// Note: Numeric values are not intended to be interpreted except as bit flags.
16type CoreFeatures uint64
17
18// CoreFeaturesV1 are features included in the WebAssembly Core Specification
19// 1.0. As of late 2022, this is the only version that is a Web Standard (W3C
20// Recommendation).
21//
22// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/
23const CoreFeaturesV1 = CoreFeatureMutableGlobal
24
25// CoreFeaturesV2 are features included in the WebAssembly Core Specification
26// 2.0 (20220419). As of late 2022, version 2.0 is a W3C working draft, not yet
27// a Web Standard (W3C Recommendation).
28//
29// See https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/appendix/changes.html#release-1-1
30const CoreFeaturesV2 = CoreFeaturesV1 |
31 CoreFeatureBulkMemoryOperations |
32 CoreFeatureMultiValue |
33 CoreFeatureNonTrappingFloatToIntConversion |
34 CoreFeatureReferenceTypes |
35 CoreFeatureSignExtensionOps |
36 CoreFeatureSIMD
37
38const (
39 // CoreFeatureBulkMemoryOperations adds instructions modify ranges of
40 // memory or table entries ("bulk-memory-operations"). This is included in
41 // CoreFeaturesV2, but not CoreFeaturesV1.
42 //
43 // Here are the notable effects:
44 // - Adds `memory.fill`, `memory.init`, `memory.copy` and `data.drop`
45 // instructions.
46 // - Adds `table.init`, `table.copy` and `elem.drop` instructions.
47 // - Introduces a "passive" form of element and data segments.
48 // - Stops checking "active" element and data segment boundaries at
49 // compile-time, meaning they can error at runtime.
50 //
51 // Note: "bulk-memory-operations" is mixed with the "reference-types"
52 // proposal due to the WebAssembly Working Group merging them
53 // "mutually dependent". Therefore, enabling this feature requires enabling
54 // CoreFeatureReferenceTypes, and vice-versa.
55 //
56 // See https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/bulk-memory-operations/Overview.md
57 // https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/reference-types/Overview.md and
58 // https://github.com/WebAssembly/spec/pull/1287
59 CoreFeatureBulkMemoryOperations CoreFeatures = 1 << iota
60
61 // CoreFeatureMultiValue enables multiple values ("multi-value"). This is
62 // included in CoreFeaturesV2, but not CoreFeaturesV1.
63 //
64 // Here are the notable effects:
65 // - Function (`func`) types allow more than one result.
66 // - Block types (`block`, `loop` and `if`) can be arbitrary function
67 // types.
68 //
69 // See https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/multi-value/Overview.md
70 CoreFeatureMultiValue
71
72 // CoreFeatureMutableGlobal allows globals to be mutable. This is included
73 // in both CoreFeaturesV1 and CoreFeaturesV2.
74 //
75 // When false, an api.Global can never be cast to an api.MutableGlobal, and
76 // any wasm that includes global vars will fail to parse.
77 CoreFeatureMutableGlobal
78
79 // CoreFeatureNonTrappingFloatToIntConversion enables non-trapping
80 // float-to-int conversions ("nontrapping-float-to-int-conversion"). This
81 // is included in CoreFeaturesV2, but not CoreFeaturesV1.
82 //
83 // The only effect of enabling is allowing the following instructions,
84 // which return 0 on NaN instead of panicking.
85 // - `i32.trunc_sat_f32_s`
86 // - `i32.trunc_sat_f32_u`
87 // - `i32.trunc_sat_f64_s`
88 // - `i32.trunc_sat_f64_u`
89 // - `i64.trunc_sat_f32_s`
90 // - `i64.trunc_sat_f32_u`
91 // - `i64.trunc_sat_f64_s`
92 // - `i64.trunc_sat_f64_u`
93 //
94 // See https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/nontrapping-float-to-int-conversion/Overview.md
95 CoreFeatureNonTrappingFloatToIntConversion
96
97 // CoreFeatureReferenceTypes enables various instructions and features
98 // related to table and new reference types. This is included in
99 // CoreFeaturesV2, but not CoreFeaturesV1.
100 //
101 // - Introduction of new value types: `funcref` and `externref`.
102 // - Support for the following new instructions:
103 // - `ref.null`
104 // - `ref.func`
105 // - `ref.is_null`
106 // - `table.fill`
107 // - `table.get`
108 // - `table.grow`
109 // - `table.set`
110 // - `table.size`
111 // - Support for multiple tables per module:
112 // - `call_indirect`, `table.init`, `table.copy` and `elem.drop`
113 // - Support for instructions can take non-zero table index.
114 // - Element segments can take non-zero table index.
115 //
116 // Note: "reference-types" is mixed with the "bulk-memory-operations"
117 // proposal due to the WebAssembly Working Group merging them
118 // "mutually dependent". Therefore, enabling this feature requires enabling
119 // CoreFeatureBulkMemoryOperations, and vice-versa.
120 //
121 // See https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/bulk-memory-operations/Overview.md
122 // https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/reference-types/Overview.md and
123 // https://github.com/WebAssembly/spec/pull/1287
124 CoreFeatureReferenceTypes
125
126 // CoreFeatureSignExtensionOps enables sign extension instructions
127 // ("sign-extension-ops"). This is included in CoreFeaturesV2, but not
128 // CoreFeaturesV1.
129 //
130 // Adds instructions:
131 // - `i32.extend8_s`
132 // - `i32.extend16_s`
133 // - `i64.extend8_s`
134 // - `i64.extend16_s`
135 // - `i64.extend32_s`
136 //
137 // See https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/sign-extension-ops/Overview.md
138 CoreFeatureSignExtensionOps
139
140 // CoreFeatureSIMD enables the vector value type and vector instructions
141 // (aka SIMD). This is included in CoreFeaturesV2, but not CoreFeaturesV1.
142 //
143 // Note: The instruction list is too long to enumerate in godoc.
144 // See https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/simd/SIMD.md
145 CoreFeatureSIMD
146
147 // Update experimental/features.go when adding elements here.
148)
149
150// SetEnabled enables or disables the feature or group of features.
151func (f CoreFeatures) SetEnabled(feature CoreFeatures, val bool) CoreFeatures {
152 if val {
153 return f | feature
154 }
155 return f &^ feature
156}
157
158// IsEnabled returns true if the feature (or group of features) is enabled.
159func (f CoreFeatures) IsEnabled(feature CoreFeatures) bool {
160 return f&feature != 0
161}
162
163// RequireEnabled returns an error if the feature (or group of features) is not
164// enabled.
165func (f CoreFeatures) RequireEnabled(feature CoreFeatures) error {
166 if f&feature == 0 {
167 return fmt.Errorf("feature %q is disabled", feature)
168 }
169 return nil
170}
171
172// String implements fmt.Stringer by returning each enabled feature.
173func (f CoreFeatures) String() string {
174 var builder strings.Builder
175 for i := 0; i <= 63; i++ { // cycle through all bits to reduce code and maintenance
176 target := CoreFeatures(1 << i)
177 if f.IsEnabled(target) {
178 if name := featureName(target); name != "" {
179 if builder.Len() > 0 {
180 builder.WriteByte('|')
181 }
182 builder.WriteString(name)
183 }
184 }
185 }
186 return builder.String()
187}
188
189func featureName(f CoreFeatures) string {
190 switch f {
191 case CoreFeatureMutableGlobal:
192 // match https://github.com/WebAssembly/mutable-global
193 return "mutable-global"
194 case CoreFeatureSignExtensionOps:
195 // match https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/sign-extension-ops/Overview.md
196 return "sign-extension-ops"
197 case CoreFeatureMultiValue:
198 // match https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/multi-value/Overview.md
199 return "multi-value"
200 case CoreFeatureNonTrappingFloatToIntConversion:
201 // match https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/nontrapping-float-to-int-conversion/Overview.md
202 return "nontrapping-float-to-int-conversion"
203 case CoreFeatureBulkMemoryOperations:
204 // match https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/bulk-memory-operations/Overview.md
205 return "bulk-memory-operations"
206 case CoreFeatureReferenceTypes:
207 // match https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/reference-types/Overview.md
208 return "reference-types"
209 case CoreFeatureSIMD:
210 // match https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/simd/SIMD.md
211 return "simd"
212 }
213 return ""
214}