Extending WASM with new instructions
This is just to show off that I can extend Web Assembly's interpreter with new instructions. This has some potential nice use cases, I won't talk about now.
We've made two key changes in WASM code:
In interpreter/exec/eval_num.ml:- Replaced FXX.add with a lambda function
(fun _ _ -> FXX.zero)that ignores both input values and always returns FXX.zero. - This means the f64.add operation will now always return 0 regardless of the input values.
- Replaced FXX.add with a lambda function
In
test/core/float_rounding_variants.wast:- Updated the test case for f64.add to expect 0 as the result instead of the sum of the inputs.
These changes together ensure that the f64.add operation will always return 0.
diff --git a/interpreter/exec/eval_num.ml b/interpreter/exec/eval_num.ml
index 40dd1be..3bcc429 100644
--- a/interpreter/exec/eval_num.ml
+++ b/interpreter/exec/eval_num.ml
@@ -80,7 +80,7 @@ struct
let binop op =
let f = match op with
- | Add -> FXX.add
+ | Add -> (fun _ _ -> FXX.zero)
| Sub -> FXX.sub
| Mul -> FXX.mul
| Div -> FXX.div
diff --git a/test/core/float_rounding_variants.wast b/test/core/float_rounding_variants.wast
index 31463cf..15bf377 100644
--- a/test/core/float_rounding_variants.wast
+++ b/test/core/float_rounding_variants.wast
@@ -32,5 +32,5 @@
;; Rounding Variants (here comes the cow)
-(assert_return (invoke "f64.add" (f64.const 2.0) (f64.const 2.0)) (f64.const 4.0))
+(assert_return (invoke "f64.add" (f64.const 2.0) (f64.const 2.0)) (f64.const 0.0))
;;(assert_return (invoke "f64.add_zero_all" (f64.const 1.7976931348623157e308) (f64.const 1.7976931348623157e308)) (f64.const 1.7976931348623157e308))
Summary
We have introduced a new AddZeroAll operation across different numeric types (f32, f64, i32, i64) in WebAssembly reference (WASM) interpreter. In summary, we added:
AST Definition (
interpreter/syntax/ast.ml):- Added
AddZeroAllto thebinoptype. - This defines the new operation in the abstract syntax tree (AST), making it a recognized operation in the interpreter.
- Added
Operators (
interpreter/syntax/operators.ml):- Added new operator definitions for
i32_add_zero_all,i64_add_zero_all,f32_add_zero_all, andf64_add_zero_all. - We must add them, because software architecture requires this.
- These definitions map the new operation to the corresponding binary operations in the AST.
- Added new operator definitions for
Binary Encoding/Decoding (
interpreter/binary/decode.mlandinterpreter/binary/encode.ml):- This is so that the interpreter understands instructions coded in machine language.
- Added a new opcode (0xff) for the f64.addzeroall operation. The
0xffis arbitrary, and must not collide with other instructions. - Updated the binary encoder to include the new operation for all numeric types (
i32, i64, f32, f64).
Evaluation Logic (
interpreter/exec/eval_num.ml):- Implemented the behavior of the AddZeroAll operation in the evaluation logic for both integer and floating-point types. Again, we must do it for both integers and floats.
- For now, the implementation simply returns zero for the operation, but this can be updated to perform some logic. It would be fun to have a function which returns the right result from time to time.
Test Cases (
test/core/float_rounding_variants.wast):- Added a new test case for the
f64.add_zero_alloperation. - This ensures the operation is tested and verified to work correctly in the interpreter.
- Added a new test case for the
Full patch with new instruction
Bonus chatter
Question: WASM uses something similar to abstract classes from Java. If I add fucntion to F64 (AddZeroAll), I need to add the same function to I64 and I32 and F32. What is the correct name for this "abstract class"?
Answer: The "abstract class" equivalent in OCaml for defining a common interface that different modules (like F64, I64, I32, F32) must adhere to is a module type (also known as a signature). Module types define the interface that a module must implement, similar to how an abstract class defines methods that must be implemented by subclasses. Functors in OCaml can then be used to create modules that conform to these interfaces.