mirror of
https://github.com/superseriousbusiness/gotosocial.git
synced 2024-11-01 15:00:00 +00:00
215 lines
8.2 KiB
Go
215 lines
8.2 KiB
Go
|
package api
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"strings"
|
||
|
)
|
||
|
|
||
|
// CoreFeatures is a bit flag of WebAssembly Core specification features. See
|
||
|
// https://github.com/WebAssembly/proposals for proposals and their status.
|
||
|
//
|
||
|
// Constants define individual features, such as CoreFeatureMultiValue, or
|
||
|
// groups of "finished" features, assigned to a WebAssembly Core Specification
|
||
|
// version, e.g. CoreFeaturesV1 or CoreFeaturesV2.
|
||
|
//
|
||
|
// Note: Numeric values are not intended to be interpreted except as bit flags.
|
||
|
type CoreFeatures uint64
|
||
|
|
||
|
// CoreFeaturesV1 are features included in the WebAssembly Core Specification
|
||
|
// 1.0. As of late 2022, this is the only version that is a Web Standard (W3C
|
||
|
// Recommendation).
|
||
|
//
|
||
|
// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/
|
||
|
const CoreFeaturesV1 = CoreFeatureMutableGlobal
|
||
|
|
||
|
// CoreFeaturesV2 are features included in the WebAssembly Core Specification
|
||
|
// 2.0 (20220419). As of late 2022, version 2.0 is a W3C working draft, not yet
|
||
|
// a Web Standard (W3C Recommendation).
|
||
|
//
|
||
|
// See https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/appendix/changes.html#release-1-1
|
||
|
const CoreFeaturesV2 = CoreFeaturesV1 |
|
||
|
CoreFeatureBulkMemoryOperations |
|
||
|
CoreFeatureMultiValue |
|
||
|
CoreFeatureNonTrappingFloatToIntConversion |
|
||
|
CoreFeatureReferenceTypes |
|
||
|
CoreFeatureSignExtensionOps |
|
||
|
CoreFeatureSIMD
|
||
|
|
||
|
const (
|
||
|
// CoreFeatureBulkMemoryOperations adds instructions modify ranges of
|
||
|
// memory or table entries ("bulk-memory-operations"). This is included in
|
||
|
// CoreFeaturesV2, but not CoreFeaturesV1.
|
||
|
//
|
||
|
// Here are the notable effects:
|
||
|
// - Adds `memory.fill`, `memory.init`, `memory.copy` and `data.drop`
|
||
|
// instructions.
|
||
|
// - Adds `table.init`, `table.copy` and `elem.drop` instructions.
|
||
|
// - Introduces a "passive" form of element and data segments.
|
||
|
// - Stops checking "active" element and data segment boundaries at
|
||
|
// compile-time, meaning they can error at runtime.
|
||
|
//
|
||
|
// Note: "bulk-memory-operations" is mixed with the "reference-types"
|
||
|
// proposal due to the WebAssembly Working Group merging them
|
||
|
// "mutually dependent". Therefore, enabling this feature requires enabling
|
||
|
// CoreFeatureReferenceTypes, and vice-versa.
|
||
|
//
|
||
|
// See https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/bulk-memory-operations/Overview.md
|
||
|
// https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/reference-types/Overview.md and
|
||
|
// https://github.com/WebAssembly/spec/pull/1287
|
||
|
CoreFeatureBulkMemoryOperations CoreFeatures = 1 << iota
|
||
|
|
||
|
// CoreFeatureMultiValue enables multiple values ("multi-value"). This is
|
||
|
// included in CoreFeaturesV2, but not CoreFeaturesV1.
|
||
|
//
|
||
|
// Here are the notable effects:
|
||
|
// - Function (`func`) types allow more than one result.
|
||
|
// - Block types (`block`, `loop` and `if`) can be arbitrary function
|
||
|
// types.
|
||
|
//
|
||
|
// See https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/multi-value/Overview.md
|
||
|
CoreFeatureMultiValue
|
||
|
|
||
|
// CoreFeatureMutableGlobal allows globals to be mutable. This is included
|
||
|
// in both CoreFeaturesV1 and CoreFeaturesV2.
|
||
|
//
|
||
|
// When false, an api.Global can never be cast to an api.MutableGlobal, and
|
||
|
// any wasm that includes global vars will fail to parse.
|
||
|
CoreFeatureMutableGlobal
|
||
|
|
||
|
// CoreFeatureNonTrappingFloatToIntConversion enables non-trapping
|
||
|
// float-to-int conversions ("nontrapping-float-to-int-conversion"). This
|
||
|
// is included in CoreFeaturesV2, but not CoreFeaturesV1.
|
||
|
//
|
||
|
// The only effect of enabling is allowing the following instructions,
|
||
|
// which return 0 on NaN instead of panicking.
|
||
|
// - `i32.trunc_sat_f32_s`
|
||
|
// - `i32.trunc_sat_f32_u`
|
||
|
// - `i32.trunc_sat_f64_s`
|
||
|
// - `i32.trunc_sat_f64_u`
|
||
|
// - `i64.trunc_sat_f32_s`
|
||
|
// - `i64.trunc_sat_f32_u`
|
||
|
// - `i64.trunc_sat_f64_s`
|
||
|
// - `i64.trunc_sat_f64_u`
|
||
|
//
|
||
|
// See https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/nontrapping-float-to-int-conversion/Overview.md
|
||
|
CoreFeatureNonTrappingFloatToIntConversion
|
||
|
|
||
|
// CoreFeatureReferenceTypes enables various instructions and features
|
||
|
// related to table and new reference types. This is included in
|
||
|
// CoreFeaturesV2, but not CoreFeaturesV1.
|
||
|
//
|
||
|
// - Introduction of new value types: `funcref` and `externref`.
|
||
|
// - Support for the following new instructions:
|
||
|
// - `ref.null`
|
||
|
// - `ref.func`
|
||
|
// - `ref.is_null`
|
||
|
// - `table.fill`
|
||
|
// - `table.get`
|
||
|
// - `table.grow`
|
||
|
// - `table.set`
|
||
|
// - `table.size`
|
||
|
// - Support for multiple tables per module:
|
||
|
// - `call_indirect`, `table.init`, `table.copy` and `elem.drop`
|
||
|
// - Support for instructions can take non-zero table index.
|
||
|
// - Element segments can take non-zero table index.
|
||
|
//
|
||
|
// Note: "reference-types" is mixed with the "bulk-memory-operations"
|
||
|
// proposal due to the WebAssembly Working Group merging them
|
||
|
// "mutually dependent". Therefore, enabling this feature requires enabling
|
||
|
// CoreFeatureBulkMemoryOperations, and vice-versa.
|
||
|
//
|
||
|
// See https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/bulk-memory-operations/Overview.md
|
||
|
// https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/reference-types/Overview.md and
|
||
|
// https://github.com/WebAssembly/spec/pull/1287
|
||
|
CoreFeatureReferenceTypes
|
||
|
|
||
|
// CoreFeatureSignExtensionOps enables sign extension instructions
|
||
|
// ("sign-extension-ops"). This is included in CoreFeaturesV2, but not
|
||
|
// CoreFeaturesV1.
|
||
|
//
|
||
|
// Adds instructions:
|
||
|
// - `i32.extend8_s`
|
||
|
// - `i32.extend16_s`
|
||
|
// - `i64.extend8_s`
|
||
|
// - `i64.extend16_s`
|
||
|
// - `i64.extend32_s`
|
||
|
//
|
||
|
// See https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/sign-extension-ops/Overview.md
|
||
|
CoreFeatureSignExtensionOps
|
||
|
|
||
|
// CoreFeatureSIMD enables the vector value type and vector instructions
|
||
|
// (aka SIMD). This is included in CoreFeaturesV2, but not CoreFeaturesV1.
|
||
|
//
|
||
|
// Note: The instruction list is too long to enumerate in godoc.
|
||
|
// See https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/simd/SIMD.md
|
||
|
CoreFeatureSIMD
|
||
|
|
||
|
// Update experimental/features.go when adding elements here.
|
||
|
)
|
||
|
|
||
|
// SetEnabled enables or disables the feature or group of features.
|
||
|
func (f CoreFeatures) SetEnabled(feature CoreFeatures, val bool) CoreFeatures {
|
||
|
if val {
|
||
|
return f | feature
|
||
|
}
|
||
|
return f &^ feature
|
||
|
}
|
||
|
|
||
|
// IsEnabled returns true if the feature (or group of features) is enabled.
|
||
|
func (f CoreFeatures) IsEnabled(feature CoreFeatures) bool {
|
||
|
return f&feature != 0
|
||
|
}
|
||
|
|
||
|
// RequireEnabled returns an error if the feature (or group of features) is not
|
||
|
// enabled.
|
||
|
func (f CoreFeatures) RequireEnabled(feature CoreFeatures) error {
|
||
|
if f&feature == 0 {
|
||
|
return fmt.Errorf("feature %q is disabled", feature)
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// String implements fmt.Stringer by returning each enabled feature.
|
||
|
func (f CoreFeatures) String() string {
|
||
|
var builder strings.Builder
|
||
|
for i := 0; i <= 63; i++ { // cycle through all bits to reduce code and maintenance
|
||
|
target := CoreFeatures(1 << i)
|
||
|
if f.IsEnabled(target) {
|
||
|
if name := featureName(target); name != "" {
|
||
|
if builder.Len() > 0 {
|
||
|
builder.WriteByte('|')
|
||
|
}
|
||
|
builder.WriteString(name)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return builder.String()
|
||
|
}
|
||
|
|
||
|
func featureName(f CoreFeatures) string {
|
||
|
switch f {
|
||
|
case CoreFeatureMutableGlobal:
|
||
|
// match https://github.com/WebAssembly/mutable-global
|
||
|
return "mutable-global"
|
||
|
case CoreFeatureSignExtensionOps:
|
||
|
// match https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/sign-extension-ops/Overview.md
|
||
|
return "sign-extension-ops"
|
||
|
case CoreFeatureMultiValue:
|
||
|
// match https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/multi-value/Overview.md
|
||
|
return "multi-value"
|
||
|
case CoreFeatureNonTrappingFloatToIntConversion:
|
||
|
// match https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/nontrapping-float-to-int-conversion/Overview.md
|
||
|
return "nontrapping-float-to-int-conversion"
|
||
|
case CoreFeatureBulkMemoryOperations:
|
||
|
// match https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/bulk-memory-operations/Overview.md
|
||
|
return "bulk-memory-operations"
|
||
|
case CoreFeatureReferenceTypes:
|
||
|
// match https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/reference-types/Overview.md
|
||
|
return "reference-types"
|
||
|
case CoreFeatureSIMD:
|
||
|
// match https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/simd/SIMD.md
|
||
|
return "simd"
|
||
|
}
|
||
|
return ""
|
||
|
}
|