From c64bce3eb8a6f5e9d4873f3ce3b3e16ad5e614cb Mon Sep 17 00:00:00 2001 From: Eduard Urbach Date: Mon, 15 Jun 2026 18:46:51 +0200 Subject: [PATCH] Fixed missing register assignment when returning a comparison --- src/codegen/conditionalSet.go | 23 +++++++++++++++++++++++ src/codegen/executeBinaryOp.go | 4 ++++ src/codegen/executeUnaryOp.go | 19 ++++--------------- src/codegen/hintDestination.go | 2 ++ src/ssa/UnaryOp.go | 2 +- tests/return-bool.q | 32 ++++++++++++++++++++++++++++++++ tests/tests_test.go | 1 + 7 files changed, 67 insertions(+), 16 deletions(-) create mode 100644 src/codegen/conditionalSet.go create mode 100644 tests/return-bool.q diff --git a/src/codegen/conditionalSet.go b/src/codegen/conditionalSet.go new file mode 100644 index 0000000..69df801 --- /dev/null +++ b/src/codegen/conditionalSet.go @@ -0,0 +1,23 @@ +package codegen + +import ( + "git.urbach.dev/cli/q/src/asm" + "git.urbach.dev/cli/q/src/config" + "git.urbach.dev/cli/q/src/cpu" + "git.urbach.dev/cli/q/src/token" +) + +// conditionalSet sets the target register to 0 or 1 depending on the condition. +func (f *Function) conditionalSet(register cpu.Register, condition token.Kind) { + if f.build.Arch == config.X86 { + f.Assembler.Append(&asm.MoveNumber{ + Destination: register, + Number: 0, + }) + } + + f.Assembler.Append(&asm.ConditionalSet{ + Destination: register, + Condition: condition, + }) +} \ No newline at end of file diff --git a/src/codegen/executeBinaryOp.go b/src/codegen/executeBinaryOp.go index 297736a..a372698 100644 --- a/src/codegen/executeBinaryOp.go +++ b/src/codegen/executeBinaryOp.go @@ -20,6 +20,10 @@ func (f *Function) executeBinaryOp(step *Step, instr *ssa.BinaryOp) { f.Assembler.Append(&asm.Compare{Destination: left.Register, Source: right.Register}) } + if step.Register != -1 { + f.conditionalSet(step.Register, instr.Op) + } + return } diff --git a/src/codegen/executeUnaryOp.go b/src/codegen/executeUnaryOp.go index d15f3ef..c966e45 100644 --- a/src/codegen/executeUnaryOp.go +++ b/src/codegen/executeUnaryOp.go @@ -2,38 +2,27 @@ package codegen import ( "git.urbach.dev/cli/q/src/asm" - "git.urbach.dev/cli/q/src/config" "git.urbach.dev/cli/q/src/ssa" "git.urbach.dev/cli/q/src/token" ) func (f *Function) executeUnaryOp(step *Step, instr *ssa.UnaryOp) { - left := f.ValueToStep[instr.Operand] + operand := f.ValueToStep[instr.Operand] switch instr.Op { case token.Negate: f.Assembler.Append(&asm.Negate{ Destination: step.Register, - Source: left.Register, + Source: operand.Register, }) case token.Not: f.Assembler.Append(&asm.CompareNumber{ - Destination: left.Register, + Destination: operand.Register, Number: 0, }) - if f.build.Arch == config.X86 { - f.Assembler.Append(&asm.MoveNumber{ - Destination: step.Register, - Number: 0, - }) - } - - f.Assembler.Append(&asm.ConditionalSet{ - Destination: step.Register, - Condition: token.Equal, - }) + f.conditionalSet(step.Register, token.Equal) default: panic("not implemented: " + instr.String()) diff --git a/src/codegen/hintDestination.go b/src/codegen/hintDestination.go index 8020b59..443903d 100644 --- a/src/codegen/hintDestination.go +++ b/src/codegen/hintDestination.go @@ -27,5 +27,7 @@ func (f *Function) hintDestination(step *Step) { variant.Phis.Add(step) variant.hint(step.Register) } + case *ssa.UnaryOp: + f.ValueToStep[instr.Operand].hint(step.Register) } } \ No newline at end of file diff --git a/src/ssa/UnaryOp.go b/src/ssa/UnaryOp.go index 30c37f8..903a71c 100644 --- a/src/ssa/UnaryOp.go +++ b/src/ssa/UnaryOp.go @@ -45,7 +45,7 @@ func (u *UnaryOp) Replace(old Value, new Value) { // String returns a human-readable representation of the unary operation. func (u *UnaryOp) String() string { - return fmt.Sprintf("%s(%s)", u.Op, u.Operand) + return fmt.Sprintf("%s(%p)", u.Op, u.Operand) } // Type returns the type of the operand. diff --git a/tests/return-bool.q b/tests/return-bool.q new file mode 100644 index 0000000..e4cc417 --- /dev/null +++ b/tests/return-bool.q @@ -0,0 +1,32 @@ +main() { + assert no() == false + assert yes() == true + assert notNo() == true + assert notYes() == false + assert notNotNo() == false + assert notNotYes() == true +} + +no() -> bool { + return 1 < 0 +} + +yes() -> bool { + return 1 > 0 +} + +notNo() -> bool { + return !(1 < 0) +} + +notYes() -> bool { + return !(1 > 0) +} + +notNotNo() -> bool { + return !!(1 < 0) +} + +notNotYes() -> bool { + return !!(1 > 0) +} \ No newline at end of file diff --git a/tests/tests_test.go b/tests/tests_test.go index 061e652..3e0c729 100644 --- a/tests/tests_test.go +++ b/tests/tests_test.go @@ -104,6 +104,7 @@ var tests = []run{ {"return-2", nil, "", "", 0}, {"return-3", nil, "", "", 0}, {"return-4", nil, "", "", 0}, + {"return-bool", nil, "", "", 0}, {"return-string", nil, "", "Hello\n", 0}, {"return-tuple", nil, "", "", 0}, {"multi-define-assign", nil, "", "", 0}, -- 2.51.2