wazevo: shares more ABI related codes between archs (#1904)
Signed-off-by: Takeshi Yoneda <t.y.mathetake@gmail.com>
This commit is contained in:
@@ -7,15 +7,9 @@ import (
|
||||
"github.com/tetratelabs/wazero/internal/engine/wazevo/ssa"
|
||||
)
|
||||
|
||||
type FunctionABIRegInfo interface {
|
||||
// ArgsResultsRegs returns the registers used for passing parameters.
|
||||
ArgsResultsRegs() (argInts, argFloats, resultInt, resultFloats []regalloc.RealReg)
|
||||
}
|
||||
|
||||
type (
|
||||
// FunctionABI represents the ABI information for a function which corresponds to a ssa.Signature.
|
||||
FunctionABI[R FunctionABIRegInfo] struct {
|
||||
r R
|
||||
FunctionABI struct {
|
||||
Initialized bool
|
||||
|
||||
Args, Rets []ABIArg
|
||||
@@ -70,19 +64,17 @@ func (a ABIArgKind) String() string {
|
||||
}
|
||||
|
||||
// Init initializes the abiImpl for the given signature.
|
||||
func (a *FunctionABI[M]) Init(sig *ssa.Signature) {
|
||||
argInts, argFloats, resultInts, resultFloats := a.r.ArgsResultsRegs()
|
||||
|
||||
func (a *FunctionABI) Init(sig *ssa.Signature, argResultInts, argResultFloats []regalloc.RealReg) {
|
||||
if len(a.Rets) < len(sig.Results) {
|
||||
a.Rets = make([]ABIArg, len(sig.Results))
|
||||
}
|
||||
a.Rets = a.Rets[:len(sig.Results)]
|
||||
a.RetStackSize = a.setABIArgs(a.Rets, sig.Results, argInts, argFloats)
|
||||
a.RetStackSize = a.setABIArgs(a.Rets, sig.Results, argResultInts, argResultFloats)
|
||||
if argsNum := len(sig.Params); len(a.Args) < argsNum {
|
||||
a.Args = make([]ABIArg, argsNum)
|
||||
}
|
||||
a.Args = a.Args[:len(sig.Params)]
|
||||
a.ArgStackSize = a.setABIArgs(a.Args, sig.Params, resultInts, resultFloats)
|
||||
a.ArgStackSize = a.setABIArgs(a.Args, sig.Params, argResultInts, argResultFloats)
|
||||
|
||||
// Gather the real registers usages in arg/return.
|
||||
a.RetRealRegs = a.RetRealRegs[:0]
|
||||
@@ -106,7 +98,7 @@ func (a *FunctionABI[M]) Init(sig *ssa.Signature) {
|
||||
|
||||
// setABIArgs sets the ABI arguments in the given slice. This assumes that len(s) >= len(types)
|
||||
// where if len(s) > len(types), the last elements of s is for the multi-return slot.
|
||||
func (a *FunctionABI[M]) setABIArgs(s []ABIArg, types []ssa.Type, ints, floats []regalloc.RealReg) (stackSize int64) {
|
||||
func (a *FunctionABI) setABIArgs(s []ABIArg, types []ssa.Type, ints, floats []regalloc.RealReg) (stackSize int64) {
|
||||
il, fl := len(ints), len(floats)
|
||||
|
||||
var stackOffset int64
|
||||
@@ -145,7 +137,7 @@ func (a *FunctionABI[M]) setABIArgs(s []ABIArg, types []ssa.Type, ints, floats [
|
||||
return stackOffset
|
||||
}
|
||||
|
||||
func (a *FunctionABI[M]) AlignedArgResultStackSlotSize() int64 {
|
||||
func (a *FunctionABI) AlignedArgResultStackSlotSize() int64 {
|
||||
stackSlotSize := a.RetStackSize + a.ArgStackSize
|
||||
// Align stackSlotSize to 16 bytes.
|
||||
stackSlotSize = (stackSlotSize + 15) &^ 15
|
||||
|
||||
@@ -16,9 +16,12 @@ func NewCompiler(ctx context.Context, mach Machine, builder ssa.Builder) Compile
|
||||
}
|
||||
|
||||
func newCompiler(_ context.Context, mach Machine, builder ssa.Builder) *compiler {
|
||||
argResultInts, argResultFloats := mach.ArgsResultsRegs()
|
||||
c := &compiler{
|
||||
mach: mach, ssaBuilder: builder,
|
||||
nextVRegID: regalloc.VRegIDNonReservedBegin,
|
||||
nextVRegID: regalloc.VRegIDNonReservedBegin,
|
||||
argResultInts: argResultInts,
|
||||
argResultFloats: argResultFloats,
|
||||
}
|
||||
mach.SetCompiler(c)
|
||||
return c
|
||||
@@ -96,6 +99,9 @@ type Compiler interface {
|
||||
|
||||
// Emit4Bytes appends 4 bytes to the buffer. Used during the code emission.
|
||||
Emit4Bytes(b uint32)
|
||||
|
||||
// GetFunctionABI returns the ABI information for the given signature.
|
||||
GetFunctionABI(sig *ssa.Signature) *FunctionABI
|
||||
}
|
||||
|
||||
// RelocationInfo represents the relocation information for a call instruction.
|
||||
@@ -135,6 +141,9 @@ type compiler struct {
|
||||
buf []byte
|
||||
relocations []RelocationInfo
|
||||
sourceOffsets []SourceOffsetInfo
|
||||
// abis maps ssa.SignatureID to the ABI implementation.
|
||||
abis []FunctionABI
|
||||
argResultInts, argResultFloats []regalloc.RealReg
|
||||
}
|
||||
|
||||
// SourceOffsetInfo is a data to associate the source offset with the executable offset.
|
||||
@@ -380,3 +389,17 @@ func (c *compiler) Emit4Bytes(b uint32) {
|
||||
func (c *compiler) Buf() []byte {
|
||||
return c.buf
|
||||
}
|
||||
|
||||
func (c *compiler) GetFunctionABI(sig *ssa.Signature) *FunctionABI {
|
||||
if int(sig.ID) >= len(c.abis) {
|
||||
c.abis = append(c.abis, make([]FunctionABI, int(sig.ID)+1)...)
|
||||
}
|
||||
|
||||
abi := &c.abis[sig.ID]
|
||||
if abi.Initialized {
|
||||
return abi
|
||||
}
|
||||
|
||||
abi.Init(sig, c.argResultInts, c.argResultFloats)
|
||||
return abi
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
// Lower implements Compiler.Lower.
|
||||
func (c *compiler) Lower() {
|
||||
c.assignVirtualRegisters()
|
||||
c.mach.InitializeABI(c.ssaBuilder.Signature())
|
||||
c.mach.SetCurrentABI(c.GetFunctionABI(c.ssaBuilder.Signature()))
|
||||
c.mach.ExecutableContext().StartLoweringFunction(c.ssaBuilder.BlockIDMax())
|
||||
c.lowerBlocks()
|
||||
}
|
||||
|
||||
@@ -50,6 +50,10 @@ func TestCompiler_lowerBlockArguments(t *testing.T) {
|
||||
target regalloc.VReg
|
||||
}{instr: instr, target: vr})
|
||||
},
|
||||
argResultInts: []regalloc.RealReg{regalloc.RealReg(0), regalloc.RealReg(1)},
|
||||
argResultFloats: []regalloc.RealReg{
|
||||
regalloc.RealReg(2), regalloc.RealReg(3), regalloc.RealReg(4), regalloc.RealReg(5),
|
||||
},
|
||||
}
|
||||
|
||||
c := newCompiler(context.Background(), m, builder)
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package amd64
|
||||
|
||||
import (
|
||||
"github.com/tetratelabs/wazero/internal/engine/wazevo/backend"
|
||||
"github.com/tetratelabs/wazero/internal/engine/wazevo/backend/regalloc"
|
||||
"github.com/tetratelabs/wazero/internal/engine/wazevo/ssa"
|
||||
)
|
||||
@@ -47,28 +46,9 @@ var regInfo = ®alloc.RegisterInfo{
|
||||
},
|
||||
}
|
||||
|
||||
// functionABIRegInfo implements backend.FunctionABIRegInfo.
|
||||
type functionABIRegInfo struct{}
|
||||
|
||||
// ArgsResultsRegs implements backend.FunctionABIRegInfo.
|
||||
func (f functionABIRegInfo) ArgsResultsRegs() (argInts, argFloats, resultInt, resultFloats []regalloc.RealReg) {
|
||||
return intArgResultRegs, floatArgResultRegs, intArgResultRegs, floatArgResultRegs
|
||||
}
|
||||
|
||||
type abiImpl = backend.FunctionABI[functionABIRegInfo]
|
||||
|
||||
func (m *machine) getOrCreateFunctionABI(sig *ssa.Signature) *abiImpl {
|
||||
if int(sig.ID) >= len(m.abis) {
|
||||
m.abis = append(m.abis, make([]abiImpl, int(sig.ID)+1)...)
|
||||
}
|
||||
|
||||
abi := &m.abis[sig.ID]
|
||||
if abi.Initialized {
|
||||
return abi
|
||||
}
|
||||
|
||||
abi.Init(sig)
|
||||
return abi
|
||||
// ArgsResultsRegs implements backend.Machine.
|
||||
func (m *machine) ArgsResultsRegs() (argResultInts, argResultFloats []regalloc.RealReg) {
|
||||
return intArgResultRegs, floatArgResultRegs
|
||||
}
|
||||
|
||||
// LowerParams implements backend.Machine.
|
||||
|
||||
@@ -29,11 +29,8 @@ type machine struct {
|
||||
ectx *backend.ExecutableContextT[instruction]
|
||||
stackBoundsCheckDisabled bool
|
||||
|
||||
regAlloc regalloc.Allocator
|
||||
|
||||
// abis maps ssa.SignatureID to the ABI implementation.
|
||||
abis []abiImpl
|
||||
currentABI *abiImpl
|
||||
regAlloc regalloc.Allocator
|
||||
currentABI *backend.FunctionABI
|
||||
}
|
||||
|
||||
// Reset implements backend.Machine.
|
||||
@@ -51,9 +48,9 @@ func (m *machine) DisableStackCheck() { m.stackBoundsCheckDisabled = true }
|
||||
// SetCompiler implements backend.Machine.
|
||||
func (m *machine) SetCompiler(compiler backend.Compiler) { m.c = compiler }
|
||||
|
||||
// InitializeABI implements backend.Machine.
|
||||
func (m *machine) InitializeABI(sig *ssa.Signature) {
|
||||
m.currentABI = m.getOrCreateFunctionABI(sig)
|
||||
// SetCurrentABI implements backend.Machine.
|
||||
func (m *machine) SetCurrentABI(abi *backend.FunctionABI) {
|
||||
m.currentABI = abi
|
||||
}
|
||||
|
||||
// LowerSingleBranch implements backend.Machine.
|
||||
|
||||
@@ -56,28 +56,9 @@ var regInfo = ®alloc.RegisterInfo{
|
||||
},
|
||||
}
|
||||
|
||||
// functionABIRegInfo implements backend.FunctionABIRegInfo.
|
||||
type functionABIRegInfo struct{}
|
||||
|
||||
// ArgsResultsRegs implements backend.FunctionABIRegInfo.
|
||||
func (f functionABIRegInfo) ArgsResultsRegs() (argInts, argFloats, resultInt, resultFloats []regalloc.RealReg) {
|
||||
return intParamResultRegs, floatParamResultRegs, intParamResultRegs, floatParamResultRegs
|
||||
}
|
||||
|
||||
type functionABI = backend.FunctionABI[functionABIRegInfo]
|
||||
|
||||
func (m *machine) getOrCreateFunctionABI(sig *ssa.Signature) *functionABI {
|
||||
if int(sig.ID) >= len(m.abis) {
|
||||
m.abis = append(m.abis, make([]functionABI, int(sig.ID)+1)...)
|
||||
}
|
||||
|
||||
abi := &m.abis[sig.ID]
|
||||
if abi.Initialized {
|
||||
return abi
|
||||
}
|
||||
|
||||
abi.Init(sig)
|
||||
return abi
|
||||
// ArgsResultsRegs implements backend.Machine.
|
||||
func (m *machine) ArgsResultsRegs() (argResultInts, argResultFloats []regalloc.RealReg) {
|
||||
return intParamResultRegs, floatParamResultRegs
|
||||
}
|
||||
|
||||
// LowerParams implements backend.FunctionABI.
|
||||
@@ -198,7 +179,7 @@ func (m *machine) LowerReturns(rets []ssa.Value) {
|
||||
|
||||
// callerGenVRegToFunctionArg is the opposite of GenFunctionArgToVReg, which is used to generate the
|
||||
// caller side of the function call.
|
||||
func (m *machine) callerGenVRegToFunctionArg(a *functionABI, argIndex int, reg regalloc.VReg, def *backend.SSAValueDefinition, slotBegin int64) {
|
||||
func (m *machine) callerGenVRegToFunctionArg(a *backend.FunctionABI, argIndex int, reg regalloc.VReg, def *backend.SSAValueDefinition, slotBegin int64) {
|
||||
arg := &a.Args[argIndex]
|
||||
if def != nil && def.IsFromInstr() {
|
||||
// Constant instructions are inlined.
|
||||
@@ -220,7 +201,7 @@ func (m *machine) callerGenVRegToFunctionArg(a *functionABI, argIndex int, reg r
|
||||
}
|
||||
}
|
||||
|
||||
func (m *machine) callerGenFunctionReturnVReg(a *functionABI, retIndex int, reg regalloc.VReg, slotBegin int64) {
|
||||
func (m *machine) callerGenFunctionReturnVReg(a *backend.FunctionABI, retIndex int, reg regalloc.VReg, slotBegin int64) {
|
||||
r := &a.Rets[retIndex]
|
||||
if r.Kind == backend.ABIArgKindReg {
|
||||
m.InsertMove(reg, r.Reg, r.Type)
|
||||
@@ -284,7 +265,7 @@ func (m *machine) lowerCall(si *ssa.Instruction) {
|
||||
} else {
|
||||
indirectCalleePtr, sigID, args = si.CallIndirectData()
|
||||
}
|
||||
calleeABI := m.getOrCreateFunctionABI(m.compiler.SSABuilder().ResolveSignature(sigID))
|
||||
calleeABI := m.compiler.GetFunctionABI(m.compiler.SSABuilder().ResolveSignature(sigID))
|
||||
|
||||
stackSlotSize := calleeABI.AlignedArgResultStackSlotSize()
|
||||
if m.maxRequiredStackSizeForCalls < stackSlotSize+16 {
|
||||
|
||||
@@ -135,8 +135,9 @@ func (m *machine) goEntryPreamblePassResult(cur *instruction, resultSlicePtr reg
|
||||
}
|
||||
|
||||
func (m *machine) constructEntryPreamble(sig *ssa.Signature) (root *instruction) {
|
||||
abi := functionABI{}
|
||||
abi.Init(sig)
|
||||
abi := backend.FunctionABI{}
|
||||
m.ArgsResultsRegs()
|
||||
abi.Init(sig, intParamResultRegs, floatParamResultRegs)
|
||||
|
||||
root = m.allocateNop()
|
||||
|
||||
|
||||
@@ -20,8 +20,8 @@ func (m *machine) CompileGoFunctionTrampoline(exitCode wazevoapi.ExitCode, sig *
|
||||
argBegin++
|
||||
}
|
||||
|
||||
abi := &functionABI{}
|
||||
abi.Init(sig)
|
||||
abi := &backend.FunctionABI{}
|
||||
abi.Init(sig, intParamResultRegs, floatParamResultRegs)
|
||||
m.currentABI = abi
|
||||
|
||||
cur := m.allocateInstr()
|
||||
|
||||
@@ -623,7 +623,7 @@ func Test_goFunctionCallStoreStackResult(t *testing.T) {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
_, _, m := newSetupWithMockContext()
|
||||
m.currentABI = &functionABI{ArgStackSize: 8}
|
||||
m.currentABI = &backend.FunctionABI{ArgStackSize: 8}
|
||||
|
||||
nop := m.allocateNop()
|
||||
m.goFunctionCallStoreStackResult(nop, spVReg, tc.result, tc.resultReg)
|
||||
|
||||
@@ -13,12 +13,12 @@ func TestAbiImpl_init(t *testing.T) {
|
||||
for _, tc := range []struct {
|
||||
name string
|
||||
sig *ssa.Signature
|
||||
exp functionABI
|
||||
exp backend.FunctionABI
|
||||
}{
|
||||
{
|
||||
name: "empty sig",
|
||||
sig: &ssa.Signature{},
|
||||
exp: functionABI{},
|
||||
exp: backend.FunctionABI{},
|
||||
},
|
||||
{
|
||||
name: "small sig",
|
||||
@@ -26,7 +26,7 @@ func TestAbiImpl_init(t *testing.T) {
|
||||
Params: []ssa.Type{ssa.TypeI32, ssa.TypeF32, ssa.TypeI32},
|
||||
Results: []ssa.Type{ssa.TypeI64, ssa.TypeF64},
|
||||
},
|
||||
exp: functionABI{
|
||||
exp: backend.FunctionABI{
|
||||
Args: []backend.ABIArg{
|
||||
{Index: 0, Kind: backend.ABIArgKindReg, Reg: x0VReg, Type: ssa.TypeI32},
|
||||
{Index: 1, Kind: backend.ABIArgKindReg, Reg: v0VReg, Type: ssa.TypeF32},
|
||||
@@ -80,7 +80,7 @@ func TestAbiImpl_init(t *testing.T) {
|
||||
ssa.TypeI64, ssa.TypeF64,
|
||||
},
|
||||
},
|
||||
exp: functionABI{
|
||||
exp: backend.FunctionABI{
|
||||
ArgStackSize: 128, RetStackSize: 128,
|
||||
Args: []backend.ABIArg{
|
||||
{Index: 0, Kind: backend.ABIArgKindReg, Reg: x0VReg, Type: ssa.TypeI32},
|
||||
@@ -178,7 +178,7 @@ func TestAbiImpl_init(t *testing.T) {
|
||||
ssa.TypeI64, ssa.TypeF64,
|
||||
},
|
||||
},
|
||||
exp: functionABI{
|
||||
exp: backend.FunctionABI{
|
||||
Args: []backend.ABIArg{
|
||||
{Index: 0, Kind: backend.ABIArgKindReg, Reg: x0VReg, Type: ssa.TypeI32},
|
||||
{Index: 1, Kind: backend.ABIArgKindReg, Reg: v0VReg, Type: ssa.TypeF32},
|
||||
@@ -222,8 +222,8 @@ func TestAbiImpl_init(t *testing.T) {
|
||||
} {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
abi := functionABI{}
|
||||
abi.Init(tc.sig)
|
||||
abi := backend.FunctionABI{}
|
||||
abi.Init(tc.sig, intParamResultRegs, floatParamResultRegs)
|
||||
require.Equal(t, tc.exp.Args, abi.Args)
|
||||
require.Equal(t, tc.exp.Rets, abi.Rets)
|
||||
require.Equal(t, tc.exp.ArgStackSize, abi.ArgStackSize)
|
||||
@@ -264,7 +264,8 @@ func TestAbiImpl_callerGenVRegToFunctionArg_constant_inlining(t *testing.T) {
|
||||
|
||||
i64 := builder.AllocateInstruction().AsIconst64(10).Insert(builder)
|
||||
f64 := builder.AllocateInstruction().AsF64const(3.14).Insert(builder)
|
||||
abi := m.getOrCreateFunctionABI(&ssa.Signature{Params: []ssa.Type{ssa.TypeI64, ssa.TypeF64}})
|
||||
abi := &backend.FunctionABI{}
|
||||
abi.Init(&ssa.Signature{Params: []ssa.Type{ssa.TypeI64, ssa.TypeF64}}, intParamResultRegs, floatParamResultRegs)
|
||||
m.callerGenVRegToFunctionArg(abi, 0, regalloc.VReg(100).SetRegType(regalloc.RegTypeInt), &backend.SSAValueDefinition{Instr: i64, RefCount: 1}, 0)
|
||||
m.callerGenVRegToFunctionArg(abi, 1, regalloc.VReg(50).SetRegType(regalloc.RegTypeFloat), &backend.SSAValueDefinition{Instr: f64, RefCount: 1}, 0)
|
||||
require.Equal(t, `movz x100?, #0xa, lsl 0
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"math"
|
||||
"strings"
|
||||
|
||||
"github.com/tetratelabs/wazero/internal/engine/wazevo/backend"
|
||||
"github.com/tetratelabs/wazero/internal/engine/wazevo/backend/regalloc"
|
||||
"github.com/tetratelabs/wazero/internal/engine/wazevo/ssa"
|
||||
)
|
||||
@@ -26,7 +27,7 @@ type (
|
||||
u1, u2, u3 uint64
|
||||
rd, rm, rn, ra operand
|
||||
amode addressMode
|
||||
abi *functionABI
|
||||
abi *backend.FunctionABI
|
||||
targets []uint32
|
||||
addedBeforeRegAlloc bool
|
||||
}
|
||||
@@ -461,13 +462,13 @@ func (i *instruction) AssignUse(index int, reg regalloc.VReg) {
|
||||
}
|
||||
}
|
||||
|
||||
func (i *instruction) asCall(ref ssa.FuncRef, abi *functionABI) {
|
||||
func (i *instruction) asCall(ref ssa.FuncRef, abi *backend.FunctionABI) {
|
||||
i.kind = call
|
||||
i.u1 = uint64(ref)
|
||||
i.abi = abi
|
||||
}
|
||||
|
||||
func (i *instruction) asCallIndirect(ptr regalloc.VReg, abi *functionABI) {
|
||||
func (i *instruction) asCallIndirect(ptr regalloc.VReg, abi *backend.FunctionABI) {
|
||||
i.kind = callInd
|
||||
i.rn = operandNR(ptr)
|
||||
i.abi = abi
|
||||
@@ -524,7 +525,7 @@ func (i *instruction) nop0Label() label {
|
||||
return label(i.u1)
|
||||
}
|
||||
|
||||
func (i *instruction) asRet(abi *functionABI) {
|
||||
func (i *instruction) asRet(abi *backend.FunctionABI) {
|
||||
i.kind = ret
|
||||
i.abi = abi
|
||||
}
|
||||
|
||||
@@ -16,9 +16,7 @@ type (
|
||||
machine struct {
|
||||
compiler backend.Compiler
|
||||
executableContext *backend.ExecutableContextT[instruction]
|
||||
currentABI *functionABI
|
||||
// abis maps ssa.SignatureID to the ABI implementation.
|
||||
abis []functionABI
|
||||
currentABI *backend.FunctionABI
|
||||
|
||||
regAlloc regalloc.Allocator
|
||||
regAllocFn *backend.RegAllocFunction[*instruction, *machine]
|
||||
@@ -149,9 +147,9 @@ func (m *machine) Reset() {
|
||||
m.executableContext.Reset()
|
||||
}
|
||||
|
||||
// InitializeABI implements backend.Machine InitializeABI.
|
||||
func (m *machine) InitializeABI(sig *ssa.Signature) {
|
||||
m.currentABI = m.getOrCreateFunctionABI(sig)
|
||||
// SetCurrentABI implements backend.Machine SetCurrentABI.
|
||||
func (m *machine) SetCurrentABI(abi *backend.FunctionABI) {
|
||||
m.currentABI = abi
|
||||
}
|
||||
|
||||
// DisableStackCheck implements backend.Machine DisableStackCheck.
|
||||
|
||||
@@ -3,6 +3,7 @@ package arm64
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/tetratelabs/wazero/internal/engine/wazevo/backend"
|
||||
"github.com/tetratelabs/wazero/internal/engine/wazevo/backend/regalloc"
|
||||
"github.com/tetratelabs/wazero/internal/testing/require"
|
||||
)
|
||||
@@ -12,7 +13,7 @@ func TestMachine_SetupPrologue(t *testing.T) {
|
||||
spillSlotSize int64
|
||||
clobberedRegs []regalloc.VReg
|
||||
exp string
|
||||
abi functionABI
|
||||
abi backend.FunctionABI
|
||||
}{
|
||||
{
|
||||
spillSlotSize: 0,
|
||||
@@ -24,7 +25,7 @@ func TestMachine_SetupPrologue(t *testing.T) {
|
||||
},
|
||||
{
|
||||
spillSlotSize: 0,
|
||||
abi: functionABI{ArgStackSize: 16, RetStackSize: 16},
|
||||
abi: backend.FunctionABI{ArgStackSize: 16, RetStackSize: 16},
|
||||
exp: `
|
||||
orr x27, xzr, #0x20
|
||||
sub sp, sp, x27
|
||||
@@ -74,7 +75,7 @@ func TestMachine_SetupPrologue(t *testing.T) {
|
||||
},
|
||||
{
|
||||
spillSlotSize: 320,
|
||||
abi: functionABI{ArgStackSize: 320, RetStackSize: 160},
|
||||
abi: backend.FunctionABI{ArgStackSize: 320, RetStackSize: 160},
|
||||
clobberedRegs: []regalloc.VReg{v18VReg, v19VReg, x18VReg, x25VReg},
|
||||
exp: `
|
||||
orr x27, xzr, #0x1e0
|
||||
@@ -117,7 +118,7 @@ func TestMachine_SetupPrologue(t *testing.T) {
|
||||
func TestMachine_SetupEpilogue(t *testing.T) {
|
||||
for _, tc := range []struct {
|
||||
exp string
|
||||
abi functionABI
|
||||
abi backend.FunctionABI
|
||||
clobberedRegs []regalloc.VReg
|
||||
spillSlotSize int64
|
||||
}{
|
||||
@@ -148,7 +149,7 @@ func TestMachine_SetupEpilogue(t *testing.T) {
|
||||
add sp, sp, #0x20
|
||||
ret
|
||||
`,
|
||||
abi: functionABI{ArgStackSize: 16, RetStackSize: 16},
|
||||
abi: backend.FunctionABI{ArgStackSize: 16, RetStackSize: 16},
|
||||
spillSlotSize: 16 * 5,
|
||||
clobberedRegs: nil,
|
||||
},
|
||||
@@ -201,7 +202,7 @@ func TestMachine_SetupEpilogue(t *testing.T) {
|
||||
ret
|
||||
`,
|
||||
spillSlotSize: 16 * 10,
|
||||
abi: functionABI{ArgStackSize: 16, RetStackSize: 320},
|
||||
abi: backend.FunctionABI{ArgStackSize: 16, RetStackSize: 320},
|
||||
clobberedRegs: []regalloc.VReg{v18VReg, v27VReg, x18VReg, x25VReg},
|
||||
},
|
||||
} {
|
||||
|
||||
@@ -3,6 +3,7 @@ package arm64
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/tetratelabs/wazero/internal/engine/wazevo/backend"
|
||||
"github.com/tetratelabs/wazero/internal/engine/wazevo/backend/regalloc"
|
||||
"github.com/tetratelabs/wazero/internal/testing/require"
|
||||
)
|
||||
@@ -79,7 +80,7 @@ func TestMachine_arg0OffsetFromSP(t *testing.T) {
|
||||
func TestMachine_ret0OffsetFromSP(t *testing.T) {
|
||||
m := &machine{
|
||||
clobberedRegs: make([]regalloc.VReg, 10), spillSlotSize: 16 * 8,
|
||||
currentABI: &functionABI{ArgStackSize: 180},
|
||||
currentABI: &backend.FunctionABI{ArgStackSize: 180},
|
||||
}
|
||||
require.Equal(t, int64(16*18)+32+180, m.ret0OffsetFromSP())
|
||||
}
|
||||
|
||||
@@ -61,6 +61,11 @@ type mockCompiler struct {
|
||||
buf []byte
|
||||
}
|
||||
|
||||
func (m *mockCompiler) GetFunctionABI(sig *ssa.Signature) *backend.FunctionABI {
|
||||
// TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (m *mockCompiler) SSABuilder() ssa.Builder { return nil }
|
||||
|
||||
func (m *mockCompiler) LoopNestingForestRoots() []ssa.BasicBlock { panic("TODO") }
|
||||
|
||||
@@ -16,8 +16,8 @@ type (
|
||||
// DisableStackCheck disables the stack check for the current compilation for debugging/testing.
|
||||
DisableStackCheck()
|
||||
|
||||
// InitializeABI initializes the FunctionABI for the given signature.
|
||||
InitializeABI(sig *ssa.Signature)
|
||||
// SetCurrentABI initializes the FunctionABI for the given signature.
|
||||
SetCurrentABI(abi *FunctionABI)
|
||||
|
||||
// SetCompiler sets the compilation context used for the lifetime of Machine.
|
||||
// This is only called once per Machine, i.e. before the first compilation.
|
||||
@@ -88,5 +88,8 @@ type (
|
||||
|
||||
// LowerReturns lowers the given returns.
|
||||
LowerReturns(returns []ssa.Value)
|
||||
|
||||
// ArgsResultsRegs returns the registers used for arguments and return values.
|
||||
ArgsResultsRegs() (argResultInts, argResultFloats []regalloc.RealReg)
|
||||
}
|
||||
)
|
||||
|
||||
@@ -10,19 +10,24 @@ import (
|
||||
|
||||
// mockMachine implements Machine for testing.
|
||||
type mockMachine struct {
|
||||
startLoweringFunction func(id ssa.BasicBlockID)
|
||||
startBlock func(block ssa.BasicBlock)
|
||||
lowerSingleBranch func(b *ssa.Instruction)
|
||||
lowerConditionalBranch func(b *ssa.Instruction)
|
||||
lowerInstr func(instruction *ssa.Instruction)
|
||||
endBlock func()
|
||||
endLoweringFunction func()
|
||||
reset func()
|
||||
insertMove func(dst, src regalloc.VReg)
|
||||
insertLoadConstant func(instr *ssa.Instruction, vr regalloc.VReg)
|
||||
format func() string
|
||||
linkAdjacentBlocks func(prev, next ssa.BasicBlock)
|
||||
rinfo *regalloc.RegisterInfo
|
||||
argResultInts, argResultFloats []regalloc.RealReg
|
||||
startLoweringFunction func(id ssa.BasicBlockID)
|
||||
startBlock func(block ssa.BasicBlock)
|
||||
lowerSingleBranch func(b *ssa.Instruction)
|
||||
lowerConditionalBranch func(b *ssa.Instruction)
|
||||
lowerInstr func(instruction *ssa.Instruction)
|
||||
endBlock func()
|
||||
endLoweringFunction func()
|
||||
reset func()
|
||||
insertMove func(dst, src regalloc.VReg)
|
||||
insertLoadConstant func(instr *ssa.Instruction, vr regalloc.VReg)
|
||||
format func() string
|
||||
linkAdjacentBlocks func(prev, next ssa.BasicBlock)
|
||||
rinfo *regalloc.RegisterInfo
|
||||
}
|
||||
|
||||
func (m mockMachine) ArgsResultsRegs() (argResultInts, argResultFloats []regalloc.RealReg) {
|
||||
return m.argResultInts, m.argResultFloats
|
||||
}
|
||||
|
||||
func (m mockMachine) RegAlloc() { panic("implement me") }
|
||||
@@ -78,8 +83,8 @@ func (m mockMachine) InsertReturn() { panic("TODO") }
|
||||
// LinkAdjacentBlocks implements Machine.LinkAdjacentBlocks.
|
||||
func (m mockMachine) LinkAdjacentBlocks(prev, next ssa.BasicBlock) { m.linkAdjacentBlocks(prev, next) }
|
||||
|
||||
// InitializeABI implements Machine.InitializeABI.
|
||||
func (m mockMachine) InitializeABI(*ssa.Signature) {}
|
||||
// SetCurrentABI implements Machine.SetCurrentABI.
|
||||
func (m mockMachine) SetCurrentABI(*FunctionABI) {}
|
||||
|
||||
// SetCompiler implements Machine.SetCompiler.
|
||||
func (m mockMachine) SetCompiler(Compiler) {}
|
||||
|
||||
Reference in New Issue
Block a user