Skip to content

Commit

Permalink
Compiler: Add [f32|f64].convert_[i32|i64]_[s|u] opcodes
Browse files Browse the repository at this point in the history
This uses conv.r4 and conv.r8 in the signed cases, and conv.r.un +
conv.r4/conv.r8 in the unsigned cases. It might not be strictly needed
to do the extra conversion in the unsigned case, but conv.r.un can
seemingly return either single or double precision values depending on
its input, while the WASM opcodes expect a specific type.
  • Loading branch information
paulirwin committed Oct 28, 2023
1 parent c6727ec commit ef13d60
Show file tree
Hide file tree
Showing 11 changed files with 130 additions and 0 deletions.
42 changes: 42 additions & 0 deletions WasmNet.Core/WasmCompiler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,18 @@ private void CompileInstruction(WasmInstruction instruction)
case WasmOpcode.F64Load:
MemoryLoad(instruction, typeof(double));
break;
case WasmOpcode.F32ConvertI32S or WasmOpcode.F32ConvertI64S:
ConvR4();
break;
case WasmOpcode.F32ConvertI32U or WasmOpcode.F32ConvertI64U:
ConvR4Un();
break;
case WasmOpcode.F64ConvertI32S or WasmOpcode.F64ConvertI64S:
ConvR8();
break;
case WasmOpcode.F64ConvertI32U or WasmOpcode.F64ConvertI64U:
ConvR8Un();
break;
case WasmOpcode.I32ReinterpretF32:
I32ReinterpretF32();
break;
Expand Down Expand Up @@ -422,6 +434,36 @@ private void CompileInstruction(WasmInstruction instruction)
}
}

private void ConvR8()
{
_il.Emit(OpCodes.Conv_R8);
_stack.Pop();
_stack.Push(typeof(double));
}

private void ConvR4Un()
{
_il.Emit(OpCodes.Conv_R_Un);
_il.Emit(OpCodes.Conv_R4); // cast to float in case of double
_stack.Pop();
_stack.Push(typeof(float));
}

private void ConvR8Un()
{
_il.Emit(OpCodes.Conv_R_Un);
_il.Emit(OpCodes.Conv_R8); // cast to double in case of float
_stack.Pop();
_stack.Push(typeof(double));
}

private void ConvR4()
{
_il.Emit(OpCodes.Conv_R4);
_stack.Pop();
_stack.Push(typeof(float));
}

private void Truncate(Type source, Type dest, bool signed)
{
var type = _stack.Pop();
Expand Down
8 changes: 8 additions & 0 deletions WasmNet.Core/WasmOpcode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,14 @@ public enum WasmOpcode
I64TruncF32U = 0xAF,
I64TruncF64S = 0xB0,
I64TruncF64U = 0xB1,
F32ConvertI32S = 0xB2,
F32ConvertI32U = 0xB3,
F32ConvertI64S = 0xB4,
F32ConvertI64U = 0xB5,
F64ConvertI32S = 0xB7,
F64ConvertI32U = 0xB8,
F64ConvertI64S = 0xB9,
F64ConvertI64U = 0xBA,
I32ReinterpretF32 = 0xBC,
I64ReinterpretF64 = 0xBD,
F32ReinterpretI32 = 0xBE,
Expand Down
8 changes: 8 additions & 0 deletions WasmNet.Core/WasmReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -593,6 +593,14 @@ or WasmOpcode.F32Load
case WasmOpcode.I64TruncF32U:
case WasmOpcode.I64TruncF64S:
case WasmOpcode.I64TruncF64U:
case WasmOpcode.F32ConvertI32S:
case WasmOpcode.F32ConvertI32U:
case WasmOpcode.F32ConvertI64S:
case WasmOpcode.F32ConvertI64U:
case WasmOpcode.F64ConvertI32S:
case WasmOpcode.F64ConvertI32U:
case WasmOpcode.F64ConvertI64S:
case WasmOpcode.F64ConvertI64U:
case WasmOpcode.I32ReinterpretF32:
case WasmOpcode.I64ReinterpretF64:
case WasmOpcode.F32ReinterpretI32:
Expand Down
9 changes: 9 additions & 0 deletions WasmNet.Tests/IntegrationTests/0142-F32ConvertI32S.wat
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
;; invoke: convert
;; expect: (f32:-42)

(module
(func (export "convert") (result f32)
i32.const -42
f32.convert_i32_s
)
)
9 changes: 9 additions & 0 deletions WasmNet.Tests/IntegrationTests/0143-F32ConvertI32U.wat
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
;; invoke: convert
;; expect: (f32:42)

(module
(func (export "convert") (result f32)
i32.const 42
f32.convert_i32_u
)
)
9 changes: 9 additions & 0 deletions WasmNet.Tests/IntegrationTests/0144-F32ConvertI64S.wat
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
;; invoke: convert
;; expect: (f32:-42000000000)

(module
(func (export "convert") (result f32)
i64.const -42000000000
f32.convert_i64_s
)
)
9 changes: 9 additions & 0 deletions WasmNet.Tests/IntegrationTests/0145-F32ConvertI64U.wat
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
;; invoke: convert
;; expect: (f32:42000000000)

(module
(func (export "convert") (result f32)
i64.const 42000000000
f32.convert_i64_u
)
)
9 changes: 9 additions & 0 deletions WasmNet.Tests/IntegrationTests/0146-F64ConvertI32S.wat
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
;; invoke: convert
;; expect: (f64:-42)

(module
(func (export "convert") (result f64)
i32.const -42
f64.convert_i32_s
)
)
9 changes: 9 additions & 0 deletions WasmNet.Tests/IntegrationTests/0147-F64ConvertI32U.wat
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
;; invoke: convert
;; expect: (f64:42)

(module
(func (export "convert") (result f64)
i32.const 42
f64.convert_i32_u
)
)
9 changes: 9 additions & 0 deletions WasmNet.Tests/IntegrationTests/0148-F64ConvertI64S.wat
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
;; invoke: convert
;; expect: (f64:-42000000000)

(module
(func (export "convert") (result f64)
i64.const -42000000000
f64.convert_i64_s
)
)
9 changes: 9 additions & 0 deletions WasmNet.Tests/IntegrationTests/0149-F64ConvertI64U.wat
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
;; invoke: convert
;; expect: (f64:42000000000)

(module
(func (export "convert") (result f64)
i64.const 42000000000
f64.convert_i64_u
)
)

0 comments on commit ef13d60

Please sign in to comment.