IR: fix various register type mismatches

This commit is contained in:
Irmen de Jong
2025-05-28 22:15:07 +02:00
parent 86da9d3c7e
commit 08b314c37d
5 changed files with 149 additions and 101 deletions

View File

@@ -627,8 +627,8 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express
result += code result += code
result += IRCodeChunk(null, null).also { result += IRCodeChunk(null, null).also {
if(targetArray.splitWords) { if(targetArray.splitWords) {
it += IRInstruction(Opcode.STOREZX, IRDataType.BYTE, reg1 = indexReg, immediate = arrayLength, labelSymbol = variable+"_lsb") it += IRInstruction(Opcode.STOREZX, IRDataType.BYTE, reg1 = indexReg, labelSymbol = variable+"_lsb")
it += IRInstruction(Opcode.STOREZX, IRDataType.BYTE, reg1 = indexReg, immediate = arrayLength, labelSymbol = variable+"_msb") it += IRInstruction(Opcode.STOREZX, IRDataType.BYTE, reg1 = indexReg, labelSymbol = variable+"_msb")
} }
else else
it += IRInstruction(Opcode.STOREZX, targetDt, reg1=indexReg, labelSymbol = variable) it += IRInstruction(Opcode.STOREZX, targetDt, reg1=indexReg, labelSymbol = variable)
@@ -753,7 +753,7 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express
if(itemsize==1 || array.splitWords) if(itemsize==1 || array.splitWords)
return Pair(result, byteIndexTr.resultReg) return Pair(result, byteIndexTr.resultReg)
result += codeGen.multiplyByConst(DataType.UWORD, byteIndexTr.resultReg, itemsize) result += codeGen.multiplyByConst(DataType.UBYTE, byteIndexTr.resultReg, itemsize)
return Pair(result, byteIndexTr.resultReg) return Pair(result, byteIndexTr.resultReg)
} }
@@ -1317,13 +1317,18 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express
IRInstruction(opc, vmDt, labelSymbol = symbol) IRInstruction(opc, vmDt, labelSymbol = symbol)
addInstr(result, ins, null) addInstr(result, ins, null)
} else { } else {
val tr = expressionEval.translateExpression(operand) val shiftTr = expressionEval.translateExpression(operand)
addToResult(result, tr, tr.resultReg, -1) addToResult(result, shiftTr, shiftTr.resultReg, -1)
var shiftReg = shiftTr.resultReg
if(vmDt==IRDataType.WORD && shiftTr.dt==IRDataType.BYTE) {
shiftReg = codeGen.registers.next(IRDataType.WORD)
addInstr(result, IRInstruction(Opcode.EXT, IRDataType.BYTE, reg1=shiftReg, reg2=shiftTr.resultReg), null)
}
val opc = if (signed) Opcode.ASRNM else Opcode.LSRNM val opc = if (signed) Opcode.ASRNM else Opcode.LSRNM
val ins = if(constAddress!=null) val ins = if(constAddress!=null)
IRInstruction(opc, vmDt, reg1 = tr.resultReg, address = constAddress) IRInstruction(opc, vmDt, reg1 = shiftReg, address = constAddress)
else else
IRInstruction(opc, vmDt, reg1 = tr.resultReg, labelSymbol = symbol) IRInstruction(opc, vmDt, reg1 = shiftReg, labelSymbol = symbol)
addInstr(result, ins, null) addInstr(result, ins, null)
} }
return result return result
@@ -1376,12 +1381,17 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express
IRInstruction(Opcode.LSLM, vmDt, labelSymbol = symbol) IRInstruction(Opcode.LSLM, vmDt, labelSymbol = symbol)
, null) , null)
} else { } else {
val tr = expressionEval.translateExpression(operand) val shiftTr = expressionEval.translateExpression(operand)
addToResult(result, tr, tr.resultReg, -1) addToResult(result, shiftTr, shiftTr.resultReg, -1)
var shiftReg = shiftTr.resultReg
if(vmDt==IRDataType.WORD && shiftTr.dt==IRDataType.BYTE) {
shiftReg = codeGen.registers.next(IRDataType.WORD)
addInstr(result, IRInstruction(Opcode.EXT, IRDataType.BYTE, reg1=shiftReg, reg2=shiftTr.resultReg), null)
}
addInstr(result, if(constAddress!=null) addInstr(result, if(constAddress!=null)
IRInstruction(Opcode.LSLNM, vmDt, reg1=tr.resultReg, address = constAddress) IRInstruction(Opcode.LSLNM, vmDt, reg1=shiftReg, address = constAddress)
else else
IRInstruction(Opcode.LSLNM, vmDt, reg1=tr.resultReg, labelSymbol = symbol) IRInstruction(Opcode.LSLNM, vmDt, reg1=shiftReg, labelSymbol = symbol)
,null) ,null)
} }
return result return result

View File

@@ -409,5 +409,68 @@ main {
errors.errors.size shouldBe 0 errors.errors.size shouldBe 0
errors.warnings.size shouldBe 0 errors.warnings.size shouldBe 0
} }
test("various array indexed assignment scenarios") {
val src="""
%import floats
%import textio
%zeropage basicsafe
main {
bool[10] barray
uword[10] @nosplit warrayns
uword[10] warray
float[10] farray
sub start() {
dump()
; ALL OK
barray[2] = true
warrayns[2] = 1234
warray[2] = 5678
farray[2] = 3.1415
dump()
; ALL OK
cx16.r0L=2
barray[cx16.r0L] = false
warrayns[cx16.r0L] = 0
warray[cx16.r0L] = 0
farray[cx16.r0L] = 0
dump()
; ALL OK
cx16.r0L=2
barray[cx16.r0L] = true
warrayns[cx16.r0L] = 1234
warray[cx16.r0L] = 5678
farray[cx16.r0L] = 3.1415
dump()
; ALL OK
barray[2] = false
warrayns[2] = 0
warray[2] = 0
farray[2] = 0.0
dump()
sub dump() {
txt.print_bool(barray[2])
txt.spc()
txt.print_uw(warrayns[2])
txt.spc()
txt.print_uw(warray[2])
txt.spc()
txt.print_f(farray[2])
txt.nl()
}
}
}"""
compileText(C64Target(), optimize=true, src, outputDir) shouldNotBe null
compileText(VMTarget(), optimize=true, src, outputDir) shouldNotBe null
compileText(C64Target(), optimize=false, src, outputDir) shouldNotBe null
compileText(VMTarget(), optimize=false, src, outputDir) shouldNotBe null
}
}) })

View File

@@ -615,4 +615,19 @@ main {
compileText(C64Target(), false, src, outputDir, writeAssembly = true) shouldNotBe null compileText(C64Target(), false, src, outputDir, writeAssembly = true) shouldNotBe null
compileText(VMTarget(), false, src, outputDir, writeAssembly = true) shouldNotBe null compileText(VMTarget(), false, src, outputDir, writeAssembly = true) shouldNotBe null
} }
test("word bitshift with byte operand") {
val src="""
main{
sub start() {
cx16.r0 >>= 4
cx16.r1 <<= 4
}
}"""
compileText(C64Target(), false, src, outputDir) shouldNotBe null
compileText(VMTarget(), false, src, outputDir) shouldNotBe null
compileText(C64Target(), true, src, outputDir) shouldNotBe null
compileText(VMTarget(), true, src, outputDir) shouldNotBe null
}
}) })

View File

@@ -1,103 +1,56 @@
%import floats %import floats
%import textio %import textio
%zeropage basicsafe
main { main {
bool[10] barray
uword[10] @nosplit warrayns
uword[10] warray
float[10] farray
sub start() { sub start() {
simpleptrindexing() dump()
struct List { ; ALL OK
float f barray[2] = true
^^uword s warrayns[2] = 1234
^^float fp warray[2] = 5678
uword n farray[2] = 3.1415
} dump()
^^List l = List()
l.s = 2000
l.fp = 3000
pokew(2000, 1) ; ALL OK
pokew(2002, 2) cx16.r0L=2
pokew(2004, 3) barray[cx16.r0L] = false
pokew(2006, 4) warrayns[cx16.r0L] = 0
pokew(2008, 5) warray[cx16.r0L] = 0
pokef(3000, 1.111) farray[cx16.r0L] = 0
pokef(3008, 2.222) dump()
pokef(3016, 3.333)
pokef(3024, 4.444)
pokef(3032, 5.555)
cx16.r9L = 2 ; ALL OK
cx16.r0L=2
barray[cx16.r0L] = true
warrayns[cx16.r0L] = 1234
warray[cx16.r0L] = 5678
farray[cx16.r0L] = 3.1415
dump()
lvref1() ; ALL OK
lvref2() barray[2] = false
lvref1f() warrayns[2] = 0
lvref2f() warray[2] = 0
farray[2] = 0.0
dump()
ref1() sub dump() {
ref2() txt.print_bool(barray[2])
ref1f() txt.spc()
ref2f() txt.print_uw(warrayns[2])
txt.spc()
sub lvref1() { txt.print_uw(warray[2])
l.s[2] = 3333 txt.spc()
} txt.print_f(farray[2])
sub lvref2() {
l.s[cx16.r9L+1] = 4444
}
sub lvref1f() {
l.fp[2] = 3333.3
}
sub lvref2f() {
l.fp[cx16.r9L+1] = 4444.4
}
sub ref1() {
cx16.r0 = l.s[2]
txt.print_uw(l.s[2])
txt.nl()
}
sub ref2() {
cx16.r1 = l.s[cx16.r9L+1]
txt.print_uw(l.s[cx16.r9L+1])
txt.nl()
}
sub ref1f() {
txt.print_f(l.fp[2])
txt.nl()
}
sub ref2f() {
txt.print_f(l.fp[cx16.r9L+1])
txt.nl() txt.nl()
} }
} }
sub simpleptrindexing() {
^^float flptr = 2000
^^bool bptr = 3000
; flptr[0] = 0.0
; flptr[1] = 1.1
cx16.r9L = 2
flptr[cx16.r9L] = 2.2
bptr[cx16.r9L] = true
; txt.print_f(flptr[0])
; txt.nl()
; txt.print_f(flptr[1])
; txt.nl()
txt.print_f(peekf(2000+8*2))
txt.nl()
txt.print_f(flptr[2])
txt.nl()
pokef(2000+8*2, 9.9999)
txt.print_f(peekf(2000+8*2))
txt.nl()
txt.print_f(flptr[2])
txt.nl()
}
} }

View File

@@ -1019,8 +1019,15 @@ data class IRInstruction(
private fun determineReg1Type(): IRDataType? { private fun determineReg1Type(): IRDataType? {
if(type==IRDataType.FLOAT) { if(type==IRDataType.FLOAT) {
// some float instructions have an integer register as well. // some float instructions have an integer (byte or word) register as well in reg1
return if(opcode in arrayOf(Opcode.FFROMUB, Opcode.FFROMSB, Opcode.FTOUB, Opcode.FTOSB, Opcode.FCOMP, Opcode.LOADIX, Opcode.LOADX, Opcode.STOREIX, Opcode.STOREX, Opcode.STOREZX)) return if(opcode in arrayOf(Opcode.FFROMUB, Opcode.FFROMSB, Opcode.FTOUB, Opcode.FTOSB, Opcode.FCOMP, Opcode.LOADIX, Opcode.LOADX, Opcode.STOREX, Opcode.STOREIX, Opcode.STOREZX))
IRDataType.BYTE
else
IRDataType.WORD
}
if(type==IRDataType.WORD) {
// some word instructions have byte reg1
return if(opcode in arrayOf(Opcode.STOREZX))
IRDataType.BYTE IRDataType.BYTE
else else
IRDataType.WORD IRDataType.WORD