welw | About_me Blog WebAssembly

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:

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:

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.