github.com/wasilibs/wazerox@v0.0.0-20240124024944-4923be63ab5f/api/features.go (about)

     1  package api
     2  
     3  import (
     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.
    16  type 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/
    23  const 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
    30  const CoreFeaturesV2 = CoreFeaturesV1 |
    31  	CoreFeatureBulkMemoryOperations |
    32  	CoreFeatureMultiValue |
    33  	CoreFeatureNonTrappingFloatToIntConversion |
    34  	CoreFeatureReferenceTypes |
    35  	CoreFeatureSignExtensionOps |
    36  	CoreFeatureSIMD
    37  
    38  const (
    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.
   151  func (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.
   159  func (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.
   165  func (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.
   173  func (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  
   189  func 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  	case CoreFeatureSIMD << 1: // Defined in experimental/features.go
   213  		// match https://github.com/WebAssembly/threads/blob/main/proposals/threads/Overview.md
   214  		return "threads"
   215  	}
   216  	return ""
   217  }