package amd64
import (
"github.com/tetratelabs/wazero/internal/engine/wazevo/backend"
"github.com/tetratelabs/wazero/internal/engine/wazevo/backend/regalloc"
)
func (m *machine ) PostRegAlloc () {
m .setupPrologue ()
m .postRegAlloc ()
}
func (m *machine ) setupPrologue () {
cur := m .rootInstr
prevInitInst := cur .next
cur = m .setupRBPRSP (cur )
if !m .stackBoundsCheckDisabled {
cur = m .insertStackBoundsCheck (m .requiredStackSize (), cur )
}
if regs := m .clobberedRegs ; len (regs ) > 0 {
for i := range regs {
r := regs [len (regs )-1 -i ]
if r .RegType () == regalloc .RegTypeInt {
cur = linkInstr (cur , m .allocateInstr ().asPush64 (newOperandReg (r )))
} else {
cur = m .addRSP (-16 , cur )
push := m .allocateInstr ().asXmmMovRM (
sseOpcodeMovdqu , r , newOperandMem (m .newAmodeImmReg (0 , rspVReg )),
)
cur = linkInstr (cur , push )
}
}
}
if size := m .spillSlotSize ; size > 0 {
cur = linkInstr (cur , m .allocateInstr ().asAluRmiR (aluRmiROpcodeSub , newOperandImm32 (uint32 (size )), rspVReg , true ))
}
linkInstr (cur , prevInitInst )
}
func (m *machine ) postRegAlloc () {
for cur := m .rootInstr ; cur != nil ; cur = cur .next {
switch k := cur .kind ; k {
case ret :
m .setupEpilogueAfter (cur .prev )
continue
case fcvtToSintSequence , fcvtToUintSequence :
m .pendingInstructions = m .pendingInstructions [:0 ]
if k == fcvtToSintSequence {
m .lowerFcvtToSintSequenceAfterRegalloc (cur )
} else {
m .lowerFcvtToUintSequenceAfterRegalloc (cur )
}
prev := cur .prev
next := cur .next
cur := prev
for _ , instr := range m .pendingInstructions {
cur = linkInstr (cur , instr )
}
linkInstr (cur , next )
continue
case xmmCMov :
m .pendingInstructions = m .pendingInstructions [:0 ]
m .lowerXmmCmovAfterRegAlloc (cur )
prev := cur .prev
next := cur .next
cur := prev
for _ , instr := range m .pendingInstructions {
cur = linkInstr (cur , instr )
}
linkInstr (cur , next )
continue
case idivRemSequence :
m .pendingInstructions = m .pendingInstructions [:0 ]
m .lowerIDivRemSequenceAfterRegAlloc (cur )
prev := cur .prev
next := cur .next
cur := prev
for _ , instr := range m .pendingInstructions {
cur = linkInstr (cur , instr )
}
linkInstr (cur , next )
continue
case call , callIndirect :
call := cur
next := call .next
_ , _ , _ , _ , size := backend .ABIInfoFromUint64 (call .u2 )
if size > 0 {
dec := m .allocateInstr ().asAluRmiR (aluRmiROpcodeSub , newOperandImm32 (size ), rspVReg , true )
linkInstr (call .prev , dec )
linkInstr (dec , call )
inc := m .allocateInstr ().asAluRmiR (aluRmiROpcodeAdd , newOperandImm32 (size ), rspVReg , true )
linkInstr (call , inc )
linkInstr (inc , next )
}
continue
case tailCall , tailCallIndirect :
tailCall := cur
_ , _ , _ , _ , size := backend .ABIInfoFromUint64 (tailCall .u2 )
if size > 0 {
dec := m .allocateInstr ().asAluRmiR (aluRmiROpcodeSub , newOperandImm32 (size ), rspVReg , true )
linkInstr (tailCall .prev , dec )
linkInstr (dec , tailCall )
}
m .setupEpilogueAfter (tailCall .prev )
m .removeUntilRet (cur .next )
continue
}
if cur .IsCopy () && cur .op1 .reg ().RealReg () == cur .op2 .reg ().RealReg () {
prev , next := cur .prev , cur .next
prev .next = next
if next != nil {
next .prev = prev
}
}
}
}
func (m *machine ) setupEpilogueAfter (cur *instruction ) {
prevNext := cur .next
if size := m .spillSlotSize ; size > 0 {
cur = linkInstr (cur , m .allocateInstr ().asAluRmiR (aluRmiROpcodeAdd , newOperandImm32 (uint32 (size )), rspVReg , true ))
}
if regs := m .clobberedRegs ; len (regs ) > 0 {
for _ , r := range regs {
if r .RegType () == regalloc .RegTypeInt {
cur = linkInstr (cur , m .allocateInstr ().asPop64 (r ))
} else {
pop := m .allocateInstr ().asXmmUnaryRmR (
sseOpcodeMovdqu , newOperandMem (m .newAmodeImmReg (0 , rspVReg )), r ,
)
cur = linkInstr (cur , pop )
cur = m .addRSP (16 , cur )
}
}
}
cur = m .revertRBPRSP (cur )
linkInstr (cur , prevNext )
}
func (m *machine ) removeUntilRet (cur *instruction ) {
for ; cur != nil ; cur = cur .next {
prev , next := cur .prev , cur .next
prev .next = next
if next != nil {
next .prev = prev
}
if cur .kind == ret {
return
}
}
}
func (m *machine ) addRSP (offset int32 , cur *instruction ) *instruction {
if offset == 0 {
return cur
}
opcode := aluRmiROpcodeAdd
if offset < 0 {
opcode = aluRmiROpcodeSub
offset = -offset
}
return linkInstr (cur , m .allocateInstr ().asAluRmiR (opcode , newOperandImm32 (uint32 (offset )), rspVReg , true ))
}
func (m *machine ) setupRBPRSP (cur *instruction ) *instruction {
cur = linkInstr (cur , m .allocateInstr ().asPush64 (newOperandReg (rbpVReg )))
cur = linkInstr (cur , m .allocateInstr ().asMovRR (rspVReg , rbpVReg , true ))
return cur
}
func (m *machine ) revertRBPRSP (cur *instruction ) *instruction {
cur = linkInstr (cur , m .allocateInstr ().asMovRR (rbpVReg , rspVReg , true ))
cur = linkInstr (cur , m .allocateInstr ().asPop64 (rbpVReg ))
return cur
}
The pages are generated with Golds v0.8.2 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds .