Something went wrong. Try again.
🌱 A minimal programming language and compiler. git.urbach.dev/cli/q
high-performance programming-language compiler
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384package codegen
import ( "slices"
"git.urbach.dev/cli/q/src/ssa" "git.urbach.dev/cli/q/src/token")
// fixRegisterConflicts checks for conflicts where 2 values that are live at the same time use the same register.// It then assigns a new register to the value that was defined earlier.func (f *Function) fixRegisterConflicts() { for _, step := range f.Steps { switch instr := step.Value.(type) { case *ssa.BinaryOp: if instr.Op == token.Shl || instr.Op == token.Shr { if slices.Contains(f.CPU.ShiftRestricted, step.Register) { f.assignFreeRegister(step) } }
if step.Register != -1 { right := f.ValueToStep[instr.Right]
if step.Register == right.Register { f.assignFreeRegister(right) }
left := f.ValueToStep[instr.Left]
if instr.Op == token.Mod && step.Register == left.Register { f.assignFreeRegister(left) } } case *ssa.Register: if f.arch.conflictsWithStackPointer(step.Register) { f.assignFreeRegister(step) } }
clobbered := f.clobberedRegisters(step)
for i, live := range step.Live { if live.Register == -1 { continue }
if live.Value != step.Value { if slices.Contains(clobbered, live.Register) { f.assignFreeRegister(live) continue }
field, isField := live.Value.(*ssa.Field)
if isField { _, isFieldFromCall := field.Tuple.(*ssa.Call)
if isFieldFromCall && live.Index > step.Index && step.Register == f.CPU.Call.Out[field.Index] { f.assignFreeRegister(step) break } } }
for _, previous := range step.Live[:i] { if previous.Register == -1 { continue }
if previous.Register != live.Register { continue }
if previous.Index < live.Index { f.assignFreeRegister(previous) } else { f.assignFreeRegister(live) break } } } }}