(step *Step, instr *ssa.BinaryOp)
| 8 | "git.urbach.dev/cli/q/src/ssa" |
| 9 | "git.urbach.dev/cli/q/src/token" |
| 10 | "git.urbach.dev/cli/q/src/types" |
| 11 | ) |
| 12 | |
| 13 | func (f *Function) executeBinaryOp(step *Step, instr *ssa.BinaryOp) { |
| 14 | if step.Register == -1 && !instr.Op.IsComparison() { |
| 15 | return |
| 16 | } |
| 17 | |
| 18 | left := f.ValueToStep[instr.Left] |
| 19 | right := f.ValueToStep[instr.Right] |
| 20 | live := slices.Concat(step.Live, []*Step{left, right}) |
| 21 | source := f.resolveOperand(left, live) |
| 22 | avoid := []cpu.Register{source} |
| 23 | |
| 24 | if instr.Op == token.Div || instr.Op == token.Mod { |
| 25 | avoid = append(avoid, f.CPU.DivisorRestricted...) |
| 26 | } |
| 27 | |
| 28 | operand := f.resolveOperand(right, live, avoid...) |
| 29 | destination := step.Register |
| 30 | isSpilled := f.isSpilled(destination) |
| 31 | |
| 32 | if isSpilled { |
| 33 | avoid = append(avoid, operand) |
| 34 | |
| 35 | if instr.Op == token.Shl || instr.Op == token.Shr { |
| 36 | avoid = append(avoid, f.CPU.ShiftRestricted...) |
| 37 | } |
| 38 | |
| 39 | destination = f.findTempRegister(live, avoid...) |
| 40 | } |
| 41 | |
| 42 | if instr.Op.IsComparison() { |
| 43 | f.emitComparison(step, left, right, source, operand, destination, instr.Op) |
| 44 | } else if isImmediate(right) { |
| 45 | f.emitArithmeticImmediate(left, source, destination, right.Value.(*ssa.Int).Int, instr.Op) |
| 46 | } else { |
| 47 | f.emitArithmeticRegister(left, source, operand, destination, instr.Op) |
| 48 | } |
| 49 | |
| 50 | if isSpilled { |
| 51 | f.storeSpill(step, destination) |
| 52 | } |
| 53 | } |
| 54 | |
| 55 | // emitComparison emits a compare followed by a conditional set when the result register is needed. |
| 56 | func (f *Function) emitComparison(step *Step, left *Step, right *Step, source cpu.Register, operand cpu.Register, destination cpu.Register, op token.Kind) { |
| 57 | if isImmediate(right) { |
| 58 | f.Assembler.Append(&asm.CompareNumber{Destination: source, Number: right.Value.(*ssa.Int).Int}) |
| 59 | } else { |
| 60 | f.Assembler.Append(&asm.Compare{Destination: source, Source: operand}) |
| 61 | } |
| 62 | |
| 63 | if step.Register != -1 { |
| 64 | unsigned := types.IsUnsigned(left.Value.Type()) || types.IsUnsigned(right.Value.Type()) |
| 65 | f.conditionalSet(destination, op, unsigned) |
| 66 | } |
| 67 | } |
no test coverage detected