diff --git a/codeGenIntermediate/src/prog8/codegen/intermediate/ExpressionGen.kt b/codeGenIntermediate/src/prog8/codegen/intermediate/ExpressionGen.kt index 3d3c84e6d..06c5e11e1 100644 --- a/codeGenIntermediate/src/prog8/codegen/intermediate/ExpressionGen.kt +++ b/codeGenIntermediate/src/prog8/codegen/intermediate/ExpressionGen.kt @@ -17,8 +17,6 @@ internal class ExpressionCodeResult(val chunks: IRCodeChunks, val dt: IRDataType if(resultReg!=-1) require(resultFpReg==-1) if(resultFpReg!=-1) require(resultReg==-1) } - - fun lastInstruction() = chunks.last().instructions.last() } internal class ExpressionGen(private val codeGen: IRCodeGen) { diff --git a/codeGenIntermediate/src/prog8/codegen/intermediate/IRCodeGen.kt b/codeGenIntermediate/src/prog8/codegen/intermediate/IRCodeGen.kt index 3291ea945..01956dbfa 100644 --- a/codeGenIntermediate/src/prog8/codegen/intermediate/IRCodeGen.kt +++ b/codeGenIntermediate/src/prog8/codegen/intermediate/IRCodeGen.kt @@ -1026,7 +1026,8 @@ class IRCodeGen( val condition = ifElse.condition as PtBinaryExpression val leftTr = expressionEval.translateExpression(condition.left) addToResult(result, leftTr, leftTr.resultReg, -1) - val requireCompareZero = leftTr.lastInstruction().opcode !in OpcodesThatSetStatusbits + val lastInstruction = leftTr.chunks.last().instructions.lastOrNull() + val requireCompareZero = lastInstruction?.opcode !in OpcodesThatSetStatusbits when(condition.operator) { "==" -> { if(requireCompareZero) diff --git a/compiler/test/vm/TestCompilerVirtual.kt b/compiler/test/vm/TestCompilerVirtual.kt index 439e88407..876ece978 100644 --- a/compiler/test/vm/TestCompilerVirtual.kt +++ b/compiler/test/vm/TestCompilerVirtual.kt @@ -473,4 +473,17 @@ instructions { compileText(VMTarget(), false, src, writeAssembly = true) shouldNotBe null } + test("IR codegen for while loop with shortcircuit") { + val src=""" +main { + sub start() { + cx16.r0L=1 + while cx16.r0L < 10 and cx16.r0L>0 { + cx16.r0L++ + } + } +}""" + compileText(VMTarget(), true, src, writeAssembly = true) shouldNotBe null + } + }) \ No newline at end of file diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 80354a59c..a0487b82d 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -9,6 +9,8 @@ Future Things and Ideas ^^^^^^^^^^^^^^^^^^^^^^^ Compiler: +- get rid of the noshortcircuit fallback option and code. +- What happens when we make all subs return a boolean not as ubyte in A, but in the cpu's Carry flag? - Multidimensional arrays and chained indexing, purely as syntactic sugar over regular arrays. - make a form of "manual generics" possible like: varsub routine(T arg)->T where T is expanded to a specific type (this is already done hardcoded for several of the builtin functions) @@ -24,6 +26,7 @@ Compiler: - (need separate step in codegen and IR to write the "golden" variables) - do we need (array)variable alignment tag instead of block alignment tag? You want to align the data, not the code in the block? +- ir: proper code gen for the CALLI instruction and that it (optionally) returns a word value that needs to be assigned to a reg - ir: getting it in shape for code generation - ir: related to the one above: block alignment doesn't translate well to variables in the block (the actual stuff that needs to be aligned in memory) but: need variable alignment tag instead of block alignment tag, really - ir: idea: (but LLVM IR simply keeps the variables, so not a good idea then?...): replace all scalar variables by an allocated register. Keep a table of the variable to register mapping (including the datatype) @@ -44,7 +47,7 @@ Compiler: Libraries: -- once a VAL_1 implementation is merged into the X16 kernal properly, remove all the workarounds in cx16 floats.parse_f() +- once a VAL_1 implementation is merged into the X16 kernal properly, remove all the workarounds in cx16 floats.parse_f() . Prototype parse routine in examples/cx16/floatparse.p8 - fix the problems in atari target, and flesh out its libraries. - c128 target: make syslib more complete (missing kernal routines)? - pet32 target: make syslib more complete (missing kernal routines)? @@ -52,8 +55,6 @@ Libraries: Optimizations: -- give a warning for variables that could be a const - or even make them a const (if not @shared)? -- treat every scalar variable decl with initialization value, as const by default, unless the variable gets assigned to somewhere (or has its address taken, or is @shared) - VariableAllocator: can we think of a smarter strategy for allocating variables into zeropage, rather than first-come-first-served? for instance, vars used inside loops first, then loopvars, then uwords used as pointers, then the rest - various optimizers skip stuff if compTarget.name==VMTarget.NAME. Once 6502-codegen is done from IR code, @@ -76,9 +77,6 @@ What if we were to re-introduce Structs in prog8? Some thoughts: Other language/syntax features to think about --------------------------------------------- -- module directive to set the text encoding for that whole file (iso, petscii, etc.) -- chained assignments `x=y=z=99` -- declare multiple variables `ubyte x,y,z` (if init value present, all get that init value) -- chained comparisons `10 ubyte { - cx16.r0++ - txt.print("value(): ") - txt.print_ub(v) - txt.nl() - return v + cx16.r0L=1 + while cx16.r0L < 10 and cx16.r0L>0 { + cx16.r0L++ } - - bigtest() - } - - ubyte @shared a1 = 10 - ubyte @shared a2 = 20 - ubyte @shared x1 = 30 - ubyte @shared x2 = 40 - ubyte @shared zero = 0 - - sub bigtest () { - txt.print("1a:\n") - if calc_a1()calc_x2() - txt.print("* 1b and fail\n") - - txt.print("\n1c:\n") - if calc_a1()>calc_x1() and calc_a2()<=calc_x2() - txt.print("* 1c and fail\n") - - txt.print("\n2a:\n") - if calc_a1()calc_x2() - txt.print("* 2b or ok\n") - - txt.print("\n3a:\n") - if calc_a1()>calc_x1() or calc_a2()<=calc_x2() - txt.print("* 3a or ok\n") - - txt.print("\n3b:\n") - if calc_a1()>calc_x1() or calc_a2()>calc_x2() - txt.print("* 3b or fail\n") - - txt.print("\n4a:\n") - bool result = calc_a1()calc_x2() - txt.print_ub(result) - txt.nl() - txt.print("\n4b:\n") - result = calc_a1()>=calc_x1() and calc_a2()>calc_x2() - txt.print_ub(result) - txt.nl() - @($4000) &= 22 - - txt.print("\n5a:\n") - result = bool_true() or bool_false() - txt.print("\n5b:\n") - result = bool_true() and bool_false() - txt.print("\n5c:\n") - result = bool_false() and bool_true() - txt.print("\n5d:\n") - result = bool_false() xor bool_true() - - txt.print("augmented and shortcut:\n") - bool @shared b1 = false - cx16.r0++ - b1 = b1 and bool_true() - txt.print("augmented and no shortcut:\n") - b1 = true - cx16.r0++ - b1 = b1 and bool_true() - - txt.print("augmented or shortcut:\n") - b1 = true - cx16.r0++ - b1 = b1 or bool_true() - txt.print("augmented or no shortcut:\n") - b1 = false - cx16.r0++ - b1 = b1 or bool_true() - } - - sub bool_true() -> bool { - txt.print("bool_true\n") - return true - } - sub bool_false() -> bool { - txt.print("bool_false\n") - return false - } - sub calc_a1() -> ubyte { - txt.print("calc_a1\n") - return a1+zero - } - sub calc_a2() -> ubyte { - txt.print("calc_a2\n") - return a2+zero - } - sub calc_x1() -> ubyte { - txt.print("calc_x1\n") - return x1+zero - } - sub calc_x2() -> ubyte { - txt.print("calc_x2\n") - return x2+zero } }