mirror of
https://github.com/irmen/prog8.git
synced 2024-12-23 09:32:43 +00:00
fix expericodegen crash related to shortcircuiting
This commit is contained in:
parent
1e1f444cab
commit
75fd263e85
@ -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) {
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
})
|
@ -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<x<20` , `x==y==z` (desugars to `10<x and x<20`, `x==y and y==z`)
|
||||
- postincrdecr as expression, preincrdecr expression (`y = x++`, `y = ++x`) .... is this even possible, expression with side effects like this?
|
||||
- negative array index to refer to an element from the end of the array. Python `[-1]` or Raku syntax `[\*-1]` , `[\*/2]` .... \*=size of the array
|
||||
- add (rom/ram)bank support to romsub. A call will then automatically switch banks, use callfar and something else when in banked ram.
|
||||
challenges: how to not make this too X16 specific? How does the compiler know what bank to switch (ram/rom)?
|
||||
How to make it performant when we want to (i.e. NOT have it use callfar/auto bank switching) ?
|
||||
|
117
examples/test.p8
117
examples/test.p8
@ -1,118 +1,13 @@
|
||||
%import textio
|
||||
%zeropage dontuse
|
||||
%zeropage basicsafe
|
||||
|
||||
; Note: this program can be compiled for multiple target systems.
|
||||
|
||||
main {
|
||||
sub start() {
|
||||
ubyte @shared x = 10
|
||||
if value(12) < x < value(100)
|
||||
txt.print("gottem")
|
||||
|
||||
sub value(ubyte v) -> 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_x1() and calc_a2()<=calc_x2()
|
||||
txt.print("* 1a and ok\n")
|
||||
|
||||
txt.print("\n1b:\n")
|
||||
if calc_a1()<calc_x1() and calc_a2()>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_x1() or calc_a2()<=calc_x2()
|
||||
txt.print("* 2a or ok\n")
|
||||
|
||||
txt.print("\n2b:\n")
|
||||
if calc_a1()<calc_x1() or calc_a2()>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_x1() or calc_a2()>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
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user