Signed-off-by: Achille Roussel <achille.roussel@gmail.com> Co-authored-by: Crypt Keeper <64215+codefromthecrypt@users.noreply.github.com>
68 lines
2.6 KiB
Go
68 lines
2.6 KiB
Go
package compiler
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/tetratelabs/wazero/internal/asm"
|
|
"github.com/tetratelabs/wazero/internal/testing/require"
|
|
"github.com/tetratelabs/wazero/internal/wasm"
|
|
"github.com/tetratelabs/wazero/internal/wazeroir"
|
|
)
|
|
|
|
// TestCompiler_conditional_value_saving ensure that saving conditional register works correctly even if there's
|
|
// no free registers available.
|
|
func TestCompiler_conditional_value_saving(t *testing.T) {
|
|
env := newCompilerEnvironment()
|
|
compiler := env.requireNewCompiler(t, &wasm.FunctionType{}, newCompiler, nil)
|
|
err := compiler.compilePreamble()
|
|
require.NoError(t, err)
|
|
|
|
// Place the f32 local.
|
|
err = compiler.compileConstF32(operationPtr(wazeroir.NewOperationConstF32(1.0)))
|
|
require.NoError(t, err)
|
|
|
|
// Generate constants to occupy all the unreserved GP registers.
|
|
for i := 0; i < len(unreservedGeneralPurposeRegisters); i++ {
|
|
err = compiler.compileConstI32(operationPtr(wazeroir.NewOperationConstI32(100)))
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
// Pick the f32 floating point local (1.0) twice.
|
|
// Note that the f32 (function local variable in general) is placed above the call frame.
|
|
err = compiler.compilePick(operationPtr(wazeroir.NewOperationPick(int(compiler.runtimeValueLocationStack().sp-1-callFrameDataSizeInUint64), false)))
|
|
|
|
require.NoError(t, err)
|
|
err = compiler.compilePick(operationPtr(wazeroir.NewOperationPick(int(compiler.runtimeValueLocationStack().sp-1-callFrameDataSizeInUint64), false)))
|
|
|
|
require.NoError(t, err)
|
|
// Generate conditional flag via floating point comparisons.
|
|
err = compiler.compileLe(operationPtr(wazeroir.NewOperationLe(wazeroir.SignedTypeFloat32)))
|
|
require.NoError(t, err)
|
|
|
|
// Ensures that we have conditional value at top of stack.
|
|
l := compiler.runtimeValueLocationStack().peek()
|
|
require.True(t, l.onConditionalRegister())
|
|
|
|
// Ensures that no free registers are available.
|
|
_, ok := compiler.runtimeValueLocationStack().takeFreeRegister(registerTypeGeneralPurpose)
|
|
require.False(t, ok)
|
|
|
|
// We should be able to use the conditional value (an i32 value in Wasm) as an operand for, say, i32.add.
|
|
err = compiler.compileAdd(operationPtr(wazeroir.NewOperationAdd(wazeroir.UnsignedTypeI32)))
|
|
require.NoError(t, err)
|
|
|
|
err = compiler.compileReturnFunction()
|
|
require.NoError(t, err)
|
|
|
|
code := asm.CodeSegment{}
|
|
defer func() { require.NoError(t, code.Unmap()) }()
|
|
|
|
// Generate and run the code under test.
|
|
_, err = compiler.compile(code.NextCodeSection())
|
|
require.NoError(t, err)
|
|
env.exec(code.Bytes())
|
|
|
|
// expect 101 = 100(== the integer const) + 1 (== flag value == the result of (1.0 <= 1.0))
|
|
require.Equal(t, uint32(101), env.stackTopAsUint32())
|
|
}
|