From af17f903ee90c411e2f474bad8aa36d3809cb5ba Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Wed, 28 Feb 2024 01:27:03 +0100 Subject: [PATCH] fix that if not fcall() wasn't transformed to a conditional branch instruction --- .../src/prog8/codegen/cpu6502/AsmGen.kt | 2 +- .../src/prog8/codegen/cpu6502/IfElseAsmGen.kt | 19 +++++++++++++++++-- .../astprocessing/IntermediateAstMaker.kt | 12 ++++++++++++ docs/source/todo.rst | 7 +++++-- examples/test.p8 | 15 +++++++++------ 5 files changed, 44 insertions(+), 11 deletions(-) diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmGen.kt index d85ed9caa..4067d60b2 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmGen.kt @@ -235,7 +235,7 @@ class AsmGen6502Internal ( private val anyExprGen = AnyExprAsmGen(this) private val assignmentAsmGen = AssignmentAsmGen(program, this, anyExprGen, allocator) private val builtinFunctionsAsmGen = BuiltinFunctionsAsmGen(program, this, assignmentAsmGen) - private val ifElseAsmgen = IfElseAsmGen(program, this, allocator, assignmentAsmGen) + private val ifElseAsmgen = IfElseAsmGen(program, symbolTable, this, allocator, assignmentAsmGen) fun compileToAssembly(): IAssemblyProgram? { diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/IfElseAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/IfElseAsmGen.kt index 433955999..236b0f092 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/IfElseAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/IfElseAsmGen.kt @@ -1,24 +1,28 @@ package prog8.codegen.cpu6502 +import prog8.code.StRomSub +import prog8.code.SymbolTable import prog8.code.ast.* import prog8.code.core.* import prog8.codegen.cpu6502.assignment.AssignmentAsmGen internal class IfElseAsmGen(private val program: PtProgram, + private val st: SymbolTable, private val asmgen: AsmGen6502Internal, private val allocator: VariableAllocator, private val assignmentAsmGen: AssignmentAsmGen) { fun translate(stmt: PtIfElse) { require(stmt.condition.type== DataType.BOOL) + checkNotRomsubReturnsStatusReg(stmt.condition) val jumpAfterIf = stmt.ifScope.children.singleOrNull() as? PtJump if(stmt.condition is PtIdentifier || - stmt.condition is PtFunctionCall || - stmt.condition is PtBuiltinFunctionCall || stmt.condition is PtArrayIndexer || stmt.condition is PtTypeCast || + stmt.condition is PtBuiltinFunctionCall || + stmt.condition is PtFunctionCall || stmt.condition is PtMemoryByte || stmt.condition is PtContainmentCheck) return fallbackTranslate(stmt, false) // the fallback code for these is optimal, so no warning. @@ -35,6 +39,7 @@ internal class IfElseAsmGen(private val program: PtProgram, val prefixCond = stmt.condition as? PtPrefix if(prefixCond?.operator=="not") { + checkNotRomsubReturnsStatusReg(prefixCond.value) assignConditionValueToRegisterAndTest(prefixCond.value) return if(jumpAfterIf!=null) translateJumpElseBodies("beq", "bne", jumpAfterIf, stmt.elseScope) @@ -45,6 +50,16 @@ internal class IfElseAsmGen(private val program: PtProgram, fallbackTranslate(stmt, true) } + private fun checkNotRomsubReturnsStatusReg(condition: PtExpression) { + val fcall = condition as? PtFunctionCall + if(fcall!=null && fcall.type==DataType.BOOL) { + val romsub = st.lookup(fcall.name) as? StRomSub + if(romsub!=null && romsub.returns.any { it.register.statusflag!=null }) { + throw AssemblyError("if romsub() that returns a status register boolean should have been changed into a Conditional branch such as if_cc") + } + } + } + private fun assignConditionValueToRegisterAndTest(condition: PtExpression) { asmgen.assignExpressionToRegister(condition, RegisterOrPair.A, false) when(condition) { diff --git a/compiler/src/prog8/compiler/astprocessing/IntermediateAstMaker.kt b/compiler/src/prog8/compiler/astprocessing/IntermediateAstMaker.kt index be0e980ae..8b6cea82f 100644 --- a/compiler/src/prog8/compiler/astprocessing/IntermediateAstMaker.kt +++ b/compiler/src/prog8/compiler/astprocessing/IntermediateAstMaker.kt @@ -349,6 +349,7 @@ class IntermediateAstMaker(private val program: Program, private val errors: IEr } } + // if something_returning_Pc() -> if_cc val binexpr = srcIf.condition as? BinaryExpression if(binexpr!=null && binexpr.right.constValue(program)?.number==0.0) { if(binexpr.operator=="==" || binexpr.operator=="!=") { @@ -368,6 +369,17 @@ class IntermediateAstMaker(private val program: Program, private val errors: IEr return codeForStatusflag(fcall, returnRegs[0].statusflag!!, false) } } + + val prefix = srcIf.condition as? PrefixExpression + if(prefix!=null && prefix.operator=="not") { + val prefixedFcall = prefix.expression as? FunctionCallExpression + if (prefixedFcall != null) { + val returnRegs = prefixedFcall.target.targetSubroutine(program)?.asmReturnvaluesRegisters + if(returnRegs!=null && returnRegs.size==1 && returnRegs[0].statusflag!=null) { + return codeForStatusflag(prefixedFcall, returnRegs[0].statusflag!!, true) + } + } + } } val ifelse = PtIfElse(srcIf.position) diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 87a909004..fd016e7da 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -1,9 +1,12 @@ TODO ==== -floatparse is a lot larger (if string.isdigit() -> uses rols instead of just bcc) +test if any()... code size + + +floatparse is slightly larger snow is a lot larger -neofetch is larger +neofetch is sligthly larger diff --git a/examples/test.p8 b/examples/test.p8 index 0edf75521..70f4b74a6 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -1,14 +1,17 @@ -%import math +%import string %import textio -%zeropage dontuse %option no_sysinit +%zeropage basicsafe + main { sub start() { - if cx16.r0s > 0 - cx16.r1L++ - if cx16.r0s <= 0 - cx16.r1L++ + + if not string.isdigit(cx16.r0L) + goto done + + cx16.r0L++ +done: } }