IR/VM: testing the boolean changes, added in-place and/or.

This commit is contained in:
Irmen de Jong 2024-02-05 21:33:07 +01:00
parent cd9119655c
commit 10d12f73d6
4 changed files with 331 additions and 44 deletions

View File

@ -1092,7 +1092,30 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
internal fun operatorLogicalAndInplace(symbol: String?, array: PtArrayIndexer?, constAddress: Int?, memory: PtMemoryByte?, vmDt: IRDataType, operand: PtExpression): Result<IRCodeChunks, NotImplementedError> { internal fun operatorLogicalAndInplace(symbol: String?, array: PtArrayIndexer?, constAddress: Int?, memory: PtMemoryByte?, vmDt: IRDataType, operand: PtExpression): Result<IRCodeChunks, NotImplementedError> {
if(array!=null) { if(array!=null) {
TODO("and") val result = mutableListOf<IRCodeChunkBase>()
val constIndex = array.index.asConstInteger()
val constValue = operand.asConstInteger()
val eltSize = codeGen.program.memsizer.memorySize(array.type)
if(constIndex!=null && constValue!=null) {
if(array.splitWords) {
val valueRegLsb = codeGen.registers.nextFree()
val valueRegMsb = codeGen.registers.nextFree()
result += IRCodeChunk(null, null).also {
it += IRInstruction(Opcode.LOAD, vmDt, reg1=valueRegLsb, immediate=constValue and 255)
it += IRInstruction(Opcode.LOAD, vmDt, reg1=valueRegMsb, immediate=constValue shr 8)
it += IRInstruction(Opcode.ANDM, vmDt, reg1=valueRegLsb, labelSymbol = array.variable.name+"_lsb", symbolOffset = constIndex)
it += IRInstruction(Opcode.ANDM, vmDt, reg1=valueRegMsb, labelSymbol = array.variable.name+"_msb", symbolOffset = constIndex)
}
} else {
val valueReg = codeGen.registers.nextFree()
result += IRCodeChunk(null, null).also {
it += IRInstruction(Opcode.LOAD, vmDt, reg1=valueReg, immediate=constValue)
it += IRInstruction(Opcode.ANDM, vmDt, reg1=valueReg, labelSymbol = array.variable.name, symbolOffset = constIndex*eltSize)
}
}
return Ok(result)
}
return Err(NotImplementedError("inplace word array and")) // TODO?
} }
if(constAddress==null && memory!=null) if(constAddress==null && memory!=null)
return Err(NotImplementedError("optimized memory in-place and")) // TODO return Err(NotImplementedError("optimized memory in-place and")) // TODO
@ -1169,7 +1192,30 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
internal fun operatorLogicalOrInplace(symbol: String?, array: PtArrayIndexer?, constAddress: Int?, memory: PtMemoryByte?, vmDt: IRDataType, operand: PtExpression): Result<IRCodeChunks, NotImplementedError> { internal fun operatorLogicalOrInplace(symbol: String?, array: PtArrayIndexer?, constAddress: Int?, memory: PtMemoryByte?, vmDt: IRDataType, operand: PtExpression): Result<IRCodeChunks, NotImplementedError> {
if(array!=null) { if(array!=null) {
TODO("or") val result = mutableListOf<IRCodeChunkBase>()
val constIndex = array.index.asConstInteger()
val constValue = operand.asConstInteger()
val eltSize = codeGen.program.memsizer.memorySize(array.type)
if(constIndex!=null && constValue!=null) {
if(array.splitWords) {
val valueRegLsb = codeGen.registers.nextFree()
val valueRegMsb = codeGen.registers.nextFree()
result += IRCodeChunk(null, null).also {
it += IRInstruction(Opcode.LOAD, vmDt, reg1=valueRegLsb, immediate=constValue and 255)
it += IRInstruction(Opcode.LOAD, vmDt, reg1=valueRegMsb, immediate=constValue shr 8)
it += IRInstruction(Opcode.ORM, vmDt, reg1=valueRegLsb, labelSymbol = array.variable.name+"_lsb", symbolOffset = constIndex)
it += IRInstruction(Opcode.ORM, vmDt, reg1=valueRegMsb, labelSymbol = array.variable.name+"_msb", symbolOffset = constIndex)
}
} else {
val valueReg = codeGen.registers.nextFree()
result += IRCodeChunk(null, null).also {
it += IRInstruction(Opcode.LOAD, vmDt, reg1=valueReg, immediate=constValue)
it += IRInstruction(Opcode.ORM, vmDt, reg1=valueReg, labelSymbol = array.variable.name, symbolOffset = constIndex*eltSize)
}
}
return Ok(result)
}
return Err(NotImplementedError("inplace word array or")) // TODO?
} }
if(constAddress==null && memory!=null) if(constAddress==null && memory!=null)
return Err(NotImplementedError("optimized memory in-place or")) // TODO return Err(NotImplementedError("optimized memory in-place or")) // TODO
@ -1206,7 +1252,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
internal fun operatorDivideInplace(symbol: String?, array: PtArrayIndexer?, constAddress: Int?, memory: PtMemoryByte?, vmDt: IRDataType, operand: PtExpression, signed: Boolean): Result<IRCodeChunks, NotImplementedError> { internal fun operatorDivideInplace(symbol: String?, array: PtArrayIndexer?, constAddress: Int?, memory: PtMemoryByte?, vmDt: IRDataType, operand: PtExpression, signed: Boolean): Result<IRCodeChunks, NotImplementedError> {
if(array!=null) { if(array!=null) {
TODO("/") TODO("/ in array")
} }
if(constAddress==null && memory!=null) if(constAddress==null && memory!=null)
return Err(NotImplementedError("optimized memory in-place /")) // TODO return Err(NotImplementedError("optimized memory in-place /")) // TODO
@ -1261,7 +1307,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
internal fun operatorMultiplyInplace(symbol: String?, array: PtArrayIndexer?, constAddress: Int?, memory: PtMemoryByte?, vmDt: IRDataType, operand: PtExpression): Result<IRCodeChunks, NotImplementedError> { internal fun operatorMultiplyInplace(symbol: String?, array: PtArrayIndexer?, constAddress: Int?, memory: PtMemoryByte?, vmDt: IRDataType, operand: PtExpression): Result<IRCodeChunks, NotImplementedError> {
if(array!=null) { if(array!=null) {
TODO("*") TODO("* in array")
} }
if(constAddress==null && memory!=null) if(constAddress==null && memory!=null)
return Err(NotImplementedError("optimized memory in-place *")) // TODO return Err(NotImplementedError("optimized memory in-place *")) // TODO
@ -1475,7 +1521,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
internal fun operatorShiftRightInplace(symbol: String?, array: PtArrayIndexer?, constAddress: Int?, memory: PtMemoryByte?, vmDt: IRDataType, operand: PtExpression, signed: Boolean): Result<IRCodeChunks, NotImplementedError> { internal fun operatorShiftRightInplace(symbol: String?, array: PtArrayIndexer?, constAddress: Int?, memory: PtMemoryByte?, vmDt: IRDataType, operand: PtExpression, signed: Boolean): Result<IRCodeChunks, NotImplementedError> {
if(array!=null) { if(array!=null) {
TODO(">>") TODO(">> in array")
} }
if(constAddress==null && memory!=null) if(constAddress==null && memory!=null)
return Err(NotImplementedError("optimized memory in-place >>")) // TODO return Err(NotImplementedError("optimized memory in-place >>")) // TODO
@ -1503,7 +1549,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
internal fun operatorShiftLeftInplace(symbol: String?, array: PtArrayIndexer?, constAddress: Int?, memory: PtMemoryByte?, vmDt: IRDataType, operand: PtExpression): Result<IRCodeChunks, NotImplementedError> { internal fun operatorShiftLeftInplace(symbol: String?, array: PtArrayIndexer?, constAddress: Int?, memory: PtMemoryByte?, vmDt: IRDataType, operand: PtExpression): Result<IRCodeChunks, NotImplementedError> {
if(array!=null) { if(array!=null) {
TODO("<<") TODO("<< in array")
} }
if(constAddress==null && memory!=null) if(constAddress==null && memory!=null)
return Err(NotImplementedError("optimized memory in-place <<")) // TODO return Err(NotImplementedError("optimized memory in-place <<")) // TODO
@ -1552,7 +1598,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
} }
return Ok(result) return Ok(result)
} }
return Err(NotImplementedError("inplace word array ^")) // TODO? return Err(NotImplementedError("inplace word array xor")) // TODO?
} }
if(constAddress==null && memory!=null) if(constAddress==null && memory!=null)
return Err(NotImplementedError("optimized memory in-place xor")) // TODO return Err(NotImplementedError("optimized memory in-place xor")) // TODO
@ -1570,7 +1616,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
internal fun operatorModuloInplace(symbol: String?, array: PtArrayIndexer?, constAddress: Int?, memory: PtMemoryByte?, vmDt: IRDataType, operand: PtExpression): Result<IRCodeChunks, NotImplementedError> { internal fun operatorModuloInplace(symbol: String?, array: PtArrayIndexer?, constAddress: Int?, memory: PtMemoryByte?, vmDt: IRDataType, operand: PtExpression): Result<IRCodeChunks, NotImplementedError> {
if(array!=null) { if(array!=null) {
TODO("%") TODO("% in array")
} }
if(constAddress==null && memory!=null) if(constAddress==null && memory!=null)
return Err(NotImplementedError("optimized memory in-place %")) // TODO return Err(NotImplementedError("optimized memory in-place %")) // TODO

View File

@ -128,7 +128,6 @@ if not CONDITION
if(!whileLoop.condition.inferType(program).isBool) if(!whileLoop.condition.inferType(program).isBool)
errors.err("condition should be a boolean", whileLoop.condition.position) errors.err("condition should be a boolean", whileLoop.condition.position)
/* /*
while true -> repeat while true -> repeat
while false -> discard while false -> discard

View File

@ -13,30 +13,27 @@ ConstantFoldingOptimizer (after merging master):
===== ====== ======= ===== ====== =======
VM 6502 what VM 6502 what
===== ====== ======= ===== ====== =======
ok ok boolean const ok . boolean const
ok ok boolean variables value ok . boolean variables value, boolean subroutine param
ok ok static bool var (block scope) with initializer value (staticVariable2asm) ok . static bool var (block scope) with initializer value (staticVariable2asm)
ok ok boolean arrays value, list and single value ok . boolean arrays value, list and single value
ok ok type error for bool[3] derp = 99 and also for init value [1,0,1] and also for [true, false, 1, 0, 222] ok . return boolean value from sub
ok ok return boolean value from sub ok . logical not, and, or, xor work correctly, also inplace
ok . make sure that and,or,xor,not aren't getting replaced by the bitwise versions ok . make sure that and,or,xor,not aren't getting replaced by the bitwise versions in the Ast
ok . and, or, xor, not work in expressions: print_ub((bb and true) as ubyte) ok . and, or, xor, not should work in expressions: print_ub((bb and true) as ubyte)
ok . logical not works, also inplace ok . bitwise logical ops on bools give type error, including invert
ok . logical xor works, also inplace ok . arithmetic ops on bools give type error
- . efficient code for manipulating bools in an array (normal and agumented assigns) ok . logical ops on ints give type error
ok ok bitwise logical ops on bools give type error, including invert ok . boolean values in ubyte array should give type error
ok ok arithmetic ops on bools give type error ok . type error for bool[3] derp = 99 and also for init value [1,0,1] and also for [true, false, 1, 0, 222]
ok ok boolean values in ubyte array should give type error ok . while booleanvar==42 and do..until booleanvar==42 should give type error
ok ok while booleanvar==42 should give type error ok . while not <integervar> should give type error
ok ok do..until booleanvar==42 should give type error ok . while not <integer functioncall> should give type error
ok ok while not <integervar> should give type error
FAIL . while not <integer functioncall> should give type error
ok . while boolean should produce identical code as while integer!=0 ok . while boolean should produce identical code as while integer!=0
ok . while not guessed -> can we get rid of the cmp? ok . while not boolvar -> can we get rid of the cmp? (6502 only?)
ok . if someint==0 / ==1 should stil produce good asm same as what it used to be with if not someint/if someint ok . if someint==0 / ==1 should stil produce good asm same as what it used to be with if not someint/if someint
ok . if not X -> test all variations with and without else ok . efficient code for manipulating bools in an array (normal and agumented assigns)
yes . is this De Morgan's optimization still useful in this branch? : not a1 or not a2 -> not(a1 and a2) likewise for and. ok . testmonogfx works
yes . is it beneficial to somehow have DeMorgan's law also work on integer types if b1==0 and b2==0 -> if (b1 & b2)==0
ok . check program sizes vs. master branch ok . check program sizes vs. master branch
===== ====== ======= ===== ====== =======

View File

@ -3,22 +3,267 @@
%option no_sysinit %option no_sysinit
main { main {
bool @shared staticbool1 = true
bool @shared staticbool2
sub start() { sub start() {
bool[3] barr boolean_const_and_var(true)
staticbool1 = boolean_arrays_and_return()
txt.print_ub(staticbool1 as ubyte)
txt.nl()
and_or_xor_not()
; bitwise_on_bools_errors()
; arith_on_bools_errors()
; logical_on_ints_errors()
; bools_in_intarray_errors()
; ints_in_boolarray_errors()
; while_until_int_errors()
while_equiv()
bools_in_array_assigns()
bools_in_array_assigns_inplace()
if_code()
; bool[3] barr
; bool @shared bb
;
; barr[1] = barr[0] and barr[2]
; barr[1] = barr[0] or barr[2]
; barr[1] = barr[0] xor barr[2]
; barr[1] = not barr[0]
; barr[1] = not barr[1]
; barr[1] = barr[1] and bb
; barr[1] = barr[1] or bb
; barr[1] = barr[1] xor bb
;
; bb = bb and barr[1]
; bb = bb or barr[1]
; bb = bb xor barr[1]
; bb = not bb
}
sub boolean_const_and_var(bool barg) {
const bool bconst1 = true
const bool bconst2 = false
bool @shared bvar1 = bconst1 or bconst2
bool @shared bvar2
bool @shared bvar3 = true
; should print: 101101
txt.print_ub(staticbool1 as ubyte)
txt.print_ub(staticbool2 as ubyte)
txt.print_ub(barg as ubyte)
txt.print_ub(bvar1 as ubyte)
txt.print_ub(bvar2 as ubyte)
txt.print_ub(bvar3 as ubyte)
txt.nl()
}
sub boolean_arrays_and_return() -> bool {
bool[] barr1 = [ true, false, true ]
bool[3] barr2 = true
bool zz
; should print: 101, 111
for zz in barr1
txt.print_ub(zz as ubyte)
txt.nl()
for zz in barr2
txt.print_ub(zz as ubyte)
txt.nl()
return false
}
sub and_or_xor_not() {
bool @shared btrue1 = true
bool @shared bfalse1 = false
bool @shared btrue2 = true
bool @shared bfalse2 = false
bool @shared bb
staticbool2 = staticbool1 and bb
staticbool1 = staticbool2 or bb
staticbool2 = staticbool1 xor bb
staticbool1 = staticbool1 and bb
staticbool2 = staticbool2 or bb
staticbool1 = staticbool1 xor bb
txt.print_ub((bb and true) as ubyte)
txt.print_ub((bb or true) as ubyte)
txt.print_ub((bb xor true) as ubyte)
txt.nl()
if not(btrue1 and btrue2)
txt.print("fail1\n")
if btrue1 and bfalse2
txt.print("fail2\n")
if bfalse1 or bfalse2
txt.print("fail3\n")
if not(btrue1 or btrue2)
txt.print("fail4\n")
if btrue1 xor btrue2
txt.print("fail5\n")
if not(bfalse1 xor btrue1)
txt.print("fail6\n")
bb = false
bb = bb or btrue1
if not bb
txt.print("fail7\n")
bb = bb and bfalse1
if bb
txt.print("fail8\n")
bb = bb xor btrue1
if not bb
txt.print("fail9\n")
}
; sub bitwise_on_bools_errors() {
; bool bb1
; bool bb2
; bb2 = bb1 | staticbool1
; bb1 = bb2 & staticbool1
; bb2 = bb1 ^ staticbool1
; bb1 = bb1 | staticbool1
; bb2 = bb2 & staticbool1
; bb1 = bb1 ^ staticbool1
; bb2 = ~ staticbool1
; voidfuncub(bb1 | staticbool1)
; }
;
; sub arith_on_bools_errors() {
; bool @shared bb1
; bool @shared bb2
; bb2 = bb1 + staticbool1
; bb1 = bb2 * staticbool1
; bb2 = staticbool1 * staticbool1
; voidfuncub(bb1 + staticbool1)
; }
;
; sub logical_on_ints_errors() {
; ubyte @shared ub1
; ubyte @shared ub2
; staticbool1 = ub1 and ub2
; voidfuncub(ub1 xor ub2)
; }
;
; sub bools_in_intarray_errors() {
; ubyte[3] arr1 = true
; ubyte[3] arr2 = [1, true, 2]
; }
;
; sub ints_in_boolarray_errors() {
; ;; bool[3] arr1 = 42
; bool[3] arr2 = [1, true, 2]
; }
;
; sub while_until_int_errors() {
;; while staticbool1==42 {
;; cx16.r0++
;; }
;;
;; do {
;; cx16.r0++
;; } until staticbool1==42
;
; ubyte @shared ub1
;
; while not ub1 {
; cx16.r0++
; }
;
; while intfunc() {
; cx16.r0++
; }
;
; while not intfunc() {
; cx16.r0++
; }
;
;; while not cx16.mouse_pos() {
;; cx16.r0++
;; }
; }
sub while_equiv() {
ubyte @shared ub
bool @shared bb bool @shared bb
barr[1] = barr[0] and barr[2] while bb {
barr[1] = barr[0] or barr[2] cx16.r0++
barr[1] = barr[0] xor barr[2] }
barr[1] = not barr[0] while ub!=0 {
barr[1] = not barr[1] cx16.r0++
barr[1] = barr[1] and bb }
barr[1] = barr[1] or bb while not bb {
barr[1] = barr[1] xor bb cx16.r0++
}
while ub==0 {
cx16.r0++
}
}
bb = bb and barr[1] sub bools_in_array_assigns() {
bb = bb or barr[1] bool[] ba = [true, false, true]
bb = bb xor barr[1] ba[1] = ba[0] xor staticbool2
bb = not bb ba[2] = staticbool2 xor ba[0]
ba[1] = ba[0] and staticbool2
ba[2] = staticbool2 and ba[0]
ba[1] = ba[0] or staticbool2
ba[2] = staticbool2 or ba[0]
ba[1] = not staticbool2
ba[1] = ba[0] xor ba[2]
ba[2] = ba[0] and ba[1]
ba[1] = ba[0] or ba[2]
ba[1] = not ba[2]
}
sub bools_in_array_assigns_inplace() {
bool[] ba = [true, false, true]
cx16.r0++
ba[1] = ba[1] xor staticbool2
ba[2] = staticbool2 xor ba[2]
ba[1] = ba[1] and staticbool2
ba[2] = staticbool2 and ba[2]
ba[1] = ba[1] or staticbool2
ba[2] = staticbool2 or ba[2]
ba[2] = ba[2] xor ba[1]
ba[1] = ba[1] and ba[2]
ba[2] = ba[2] or ba[1]
ba[2] = not ba[2]
}
sub if_code() {
ubyte @shared ub
bool @shared bb
if ub==0
cx16.r0++
if ub!=0
cx16.r0++
if bb
cx16.r0++
if not bb
cx16.r0++
if ub==0
cx16.r0++
else
cx16.r0--
if ub!=0
cx16.r0++
else
cx16.r0--
if bb
cx16.r0++
else
cx16.r0--
if not bb
cx16.r0++
else
cx16.r0--
}
sub intfunc() -> ubyte {
return cx16.r0L
}
sub voidfuncub(ubyte arg) {
cx16.r0++
} }
} }