github.com/taubyte/vm-wasm-utils@v1.0.2/features.go (about)

     1  package wasm
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  )
     7  
     8  // Features are the currently enabled features.
     9  //
    10  // Note: This is a bit flag until we have too many (>63). Flags are simpler to manage in multiple places than a map.
    11  type Features uint64
    12  
    13  // Features20191205 include those finished in WebAssembly 1.0 (20191205).
    14  //
    15  // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205
    16  const Features20191205 = FeatureMutableGlobal
    17  
    18  // Features20220419 include those finished in WebAssembly 2.0 (20220419).
    19  //
    20  // See https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/appendix/changes.html#release-1-1
    21  const Features20220419 = Features20191205 |
    22  	FeatureBulkMemoryOperations |
    23  	FeatureMultiValue |
    24  	FeatureNonTrappingFloatToIntConversion |
    25  	FeatureReferenceTypes |
    26  	FeatureSignExtensionOps |
    27  	FeatureSIMD
    28  
    29  const (
    30  	// FeatureBulkMemoryOperations decides if parsing should succeed on the following instructions:
    31  	//
    32  	// * [ OpcodeMiscPrefix, OpcodeMiscMemoryInit]
    33  	// * [ OpcodeMiscPrefix, OpcodeMiscDataDrop]
    34  	// * [ OpcodeMiscPrefix, OpcodeMiscMemoryCopy]
    35  	// * [ OpcodeMiscPrefix, OpcodeMiscMemoryFill]
    36  	// * [ OpcodeMiscPrefix, OpcodeMiscTableInit]
    37  	// * [ OpcodeMiscPrefix, OpcodeMiscElemDrop]
    38  	// * [ OpcodeMiscPrefix, OpcodeMiscTableCopy]
    39  	//
    40  	// Also, if the parsing should succeed with the presence of SectionIDDataCount.
    41  	//
    42  	// See https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/appendix/changes.html#bulk-memory-and-table-instructions
    43  	FeatureBulkMemoryOperations Features = 1 << iota
    44  
    45  	// FeatureMultiValue decides if parsing should succeed on the following:
    46  	//
    47  	// * FunctionType.Results length greater than one.
    48  	// * `block`, `loop` and `if` can be arbitrary function types.
    49  	//
    50  	// See https://github.com/WebAssembly/spec/blob/main/proposals/multi-value/Overview.md
    51  	FeatureMultiValue
    52  
    53  	// FeatureMutableGlobal decides if global vars are allowed to be imported or exported (ExternTypeGlobal)
    54  	// See https://github.com/WebAssembly/mutable-global
    55  	FeatureMutableGlobal
    56  
    57  	// FeatureNonTrappingFloatToIntConversion decides if parsing should succeed on the following instructions:
    58  	//
    59  	// * [ OpcodeMiscPrefix, OpcodeMiscI32TruncSatF32S]
    60  	// * [ OpcodeMiscPrefix, OpcodeMiscI32TruncSatF32U]
    61  	// * [ OpcodeMiscPrefix, OpcodeMiscI64TruncSatF32S]
    62  	// * [ OpcodeMiscPrefix, OpcodeMiscI64TruncSatF32U]
    63  	// * [ OpcodeMiscPrefix, OpcodeMiscI32TruncSatF64S]
    64  	// * [ OpcodeMiscPrefix, OpcodeMiscI32TruncSatF64U]
    65  	// * [ OpcodeMiscPrefix, OpcodeMiscI64TruncSatF64S]
    66  	// * [ OpcodeMiscPrefix, OpcodeMiscI64TruncSatF64U]
    67  	//
    68  	// See https://github.com/WebAssembly/spec/blob/main/proposals/nontrapping-float-to-int-conversion/Overview.md
    69  	FeatureNonTrappingFloatToIntConversion
    70  
    71  	// FeatureReferenceTypes enables various features related to reference types and tables.
    72  	// * Introduction of new values types: RefTypeFuncref and RefTypeExternref
    73  	// * Support for the following opcodes:
    74  	//  * OpcodeRefNull
    75  	//  * OpcodeRefIsNull
    76  	//  * OpcodeRefFunc
    77  	// 	* OpcodeTableGet
    78  	// 	* OpcodeTableSet
    79  	// 	* [ OpcodeMiscPrefix, OpcodeMiscTableFill]
    80  	// 	* [ OpcodeMiscPrefix, OpcodeMiscTableGrow]
    81  	// 	* [ OpcodeMiscPrefix, OpcodeMiscTableSize]
    82  	// * Support for multiple tables per module:
    83  	// 	* OpcodeCallIndirect, OpcodeTableInit, and OpcodeElemDrop can take non-zero table indexes.
    84  	// 	* Element segments can take non-zero table index.
    85  	//
    86  	// See https://github.com/WebAssembly/spec/blob/main/proposals/reference-types/Overview.md
    87  	FeatureReferenceTypes
    88  
    89  	// FeatureSignExtensionOps decides if parsing should succeed on the following instructions:
    90  	//
    91  	// * OpcodeI32Extend8S
    92  	// * OpcodeI32Extend16S
    93  	// * OpcodeI64Extend8S
    94  	// * OpcodeI64Extend16S
    95  	// * OpcodeI64Extend32S
    96  	//
    97  	// See https://github.com/WebAssembly/spec/blob/main/proposals/sign-extension-ops/Overview.md
    98  	FeatureSignExtensionOps
    99  
   100  	// FeatureSIMD enables the vector value type and vector instructions.
   101  	//
   102  	// See https://github.com/WebAssembly/spec/blob/main/proposals/simd/SIMD.md
   103  	FeatureSIMD
   104  )
   105  
   106  // Set assigns the value for the given feature.
   107  func (f Features) Set(feature Features, val bool) Features {
   108  	if val {
   109  		return f | feature
   110  	}
   111  	return f &^ feature
   112  }
   113  
   114  // Get returns the value of the given feature.
   115  func (f Features) Get(feature Features) bool {
   116  	return f&feature != 0
   117  }
   118  
   119  // Require fails with a configuration error if the given feature is not enabled
   120  func (f Features) Require(feature Features) error {
   121  	if f&feature == 0 {
   122  		return fmt.Errorf("feature %q is disabled", feature)
   123  	}
   124  	return nil
   125  }
   126  
   127  // String implements fmt.Stringer by returning each enabled feature.
   128  func (f Features) String() string {
   129  	var builder strings.Builder
   130  	for i := 0; i <= 63; i++ { // cycle through all bits to reduce code and maintenance
   131  		target := Features(1 << i)
   132  		if f.Get(target) {
   133  			if name := featureName(target); name != "" {
   134  				if builder.Len() > 0 {
   135  					builder.WriteByte('|')
   136  				}
   137  				builder.WriteString(name)
   138  			}
   139  		}
   140  	}
   141  	return builder.String()
   142  }
   143  
   144  func featureName(f Features) string {
   145  	switch f {
   146  	case FeatureMutableGlobal:
   147  		// match https://github.com/WebAssembly/mutable-global
   148  		return "mutable-global"
   149  	case FeatureSignExtensionOps:
   150  		// match https://github.com/WebAssembly/spec/blob/main/proposals/sign-extension-ops/Overview.md
   151  		return "sign-extension-ops"
   152  	case FeatureMultiValue:
   153  		// match https://github.com/WebAssembly/spec/blob/main/proposals/multi-value/Overview.md
   154  		return "multi-value"
   155  	case FeatureNonTrappingFloatToIntConversion:
   156  		// match https://github.com/WebAssembly/spec/blob/main/proposals/nontrapping-float-to-int-conversion/Overview.md
   157  		return "nontrapping-float-to-int-conversion"
   158  	case FeatureBulkMemoryOperations:
   159  		// match https://github.com/WebAssembly/spec/blob/main/proposals/bulk-memory-operations/Overview.md
   160  		return "bulk-memory-operations"
   161  	case FeatureReferenceTypes:
   162  		// match https://github.com/WebAssembly/spec/blob/main/proposals/reference-types/Overview.md
   163  		return "reference-types"
   164  	case FeatureSIMD:
   165  		// match https://github.com/WebAssembly/spec/blob/main/proposals/simd/SIMD.md
   166  		return "simd"
   167  	}
   168  	return ""
   169  }