From 2e7e18a2d9affc31f5f8bc9b8e7fb2c5f69564ef Mon Sep 17 00:00:00 2001 From: Eduard Urbach Date: Wed, 15 Jul 2026 17:41:52 +0200 Subject: [PATCH] Fixed incorrect bool conversion of conditions --- lib/strings/fromInt.q | 8 +----- src/codegen/executeBranch.go | 52 +++++++++++++++++++++--------------- src/codegen/needsRegister.go | 10 ++++++- 3 files changed, 40 insertions(+), 30 deletions(-) diff --git a/lib/strings/fromInt.q b/lib/strings/fromInt.q index 7f0050f..4dde6c6 100644 --- a/lib/strings/fromInt.q +++ b/lib/strings/fromInt.q @@ -1,11 +1,5 @@ fromInt(x int, base int, buffer []byte) -> []byte { - // TODO: Fix the bug that prevents generating boolean values directly from a condition - negative := false - - if x < 0 { - negative = true - } - + negative := x < 0 end := buffer.ptr + buffer.len tmp := end diff --git a/src/codegen/executeBranch.go b/src/codegen/executeBranch.go index bf0473f..00d8d7c 100644 --- a/src/codegen/executeBranch.go +++ b/src/codegen/executeBranch.go @@ -10,34 +10,42 @@ import ( ) func (f *Function) executeBranch(step *Step, instr *ssa.Branch) { - var op token.Kind - binaryOp, isBinaryOp := instr.Condition.(*ssa.BinaryOp) - cas, isCas := instr.Condition.(*ssa.Cas) - unsigned := false + var ( + op token.Kind + unsigned bool + conditionStep = f.ValueToStep[instr.Condition] + ) - if isBinaryOp && binaryOp.Op.IsComparison() { - op = binaryOp.Op - unsigned = types.IsUnsigned(binaryOp.Left.Type()) || types.IsUnsigned(binaryOp.Right.Type()) - } else if isCas { - op = token.Equal - - dest := f.ValueToStep[cas.Arguments[1]].Register - - if f.build.Arch == config.X86 { - dest = x86.R0 - } - - f.Assembler.Append(&asm.CompareNumber{ - Destination: dest, - Number: cas.Arguments[1].(*ssa.Int).Int, - }) - } else { + if conditionStep.Register != -1 { op = token.NotEqual f.Assembler.Append(&asm.CompareNumber{ - Destination: f.ValueToStep[instr.Condition].Register, + Destination: conditionStep.Register, Number: 0, }) + } else { + switch condition := instr.Condition.(type) { + case *ssa.BinaryOp: + if condition.Op.IsComparison() { + op = condition.Op + unsigned = types.IsUnsigned(condition.Left.Type()) || types.IsUnsigned(condition.Right.Type()) + } else { + panic("condition using a binary operation not assigned to a register") + } + + case *ssa.Cas: + op = token.Equal + dest := f.ValueToStep[condition.Arguments[1]].Register + + if f.build.Arch == config.X86 { + dest = x86.R0 + } + + f.Assembler.Append(&asm.CompareNumber{ + Destination: dest, + Number: condition.Arguments[1].(*ssa.Int).Int, + }) + } } f.insertPhiMoves(step) diff --git a/src/codegen/needsRegister.go b/src/codegen/needsRegister.go index df66276..903654b 100644 --- a/src/codegen/needsRegister.go +++ b/src/codegen/needsRegister.go @@ -1,6 +1,8 @@ package codegen import ( + "slices" + "git.urbach.dev/cli/q/src/ssa" "git.urbach.dev/cli/q/src/types" ) @@ -39,7 +41,13 @@ func (f *Function) needsRegister(s *Step) bool { switch instr := s.Value.(type) { case *ssa.BinaryOp: - return !instr.Op.IsComparison() + if instr.Op.IsComparison() { + next := f.Steps[s.Index+1] + branch, isBranch := next.Value.(*ssa.Branch) + return !isBranch || !slices.Contains(branch.Inputs(), s.Value) + } + + return true case *ssa.Cas: return false case *ssa.Int: -- 2.51.2