features.go

  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}