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 += IRCodeChunk(null, null).also {
if(targetArray.splitWords) {
it += IRInstruction(Opcode.STOREZX, IRDataType.BYTE, reg1 = indexReg, immediate = arrayLength, 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+"_lsb")
it += IRInstruction(Opcode.STOREZX, IRDataType.BYTE, reg1 = indexReg, labelSymbol = variable+"_msb")
}
else
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)
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)
}
@@ -1317,13 +1317,18 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express
IRInstruction(opc, vmDt, labelSymbol = symbol)
addInstr(result, ins, null)
} else {
val tr = expressionEval.translateExpression(operand)
addToResult(result, tr, tr.resultReg, -1)
val shiftTr = expressionEval.translateExpression(operand)
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 ins = if(constAddress!=null)
IRInstruction(opc, vmDt, reg1 = tr.resultReg, address = constAddress)
IRInstruction(opc, vmDt, reg1 = shiftReg, address = constAddress)
else
IRInstruction(opc, vmDt, reg1 = tr.resultReg, labelSymbol = symbol)
IRInstruction(opc, vmDt, reg1 = shiftReg, labelSymbol = symbol)
addInstr(result, ins, null)
}
return result
@@ -1376,12 +1381,17 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express
IRInstruction(Opcode.LSLM, vmDt, labelSymbol = symbol)
, null)
} else {
val tr = expressionEval.translateExpression(operand)
addToResult(result, tr, tr.resultReg, -1)
val shiftTr = expressionEval.translateExpression(operand)
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)
IRInstruction(Opcode.LSLNM, vmDt, reg1=tr.resultReg, address = constAddress)
IRInstruction(Opcode.LSLNM, vmDt, reg1=shiftReg, address = constAddress)
else
IRInstruction(Opcode.LSLNM, vmDt, reg1=tr.resultReg, labelSymbol = symbol)
IRInstruction(Opcode.LSLNM, vmDt, reg1=shiftReg, labelSymbol = symbol)
,null)
}
return result

View File

@@ -409,5 +409,68 @@ main {
errors.errors.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(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 textio
%zeropage basicsafe
main {
bool[10] barray
uword[10] @nosplit warrayns
uword[10] warray
float[10] farray
sub start() {
simpleptrindexing()
dump()
struct List {
float f
^^uword s
^^float fp
uword n
}
^^List l = List()
l.s = 2000
l.fp = 3000
; ALL OK
barray[2] = true
warrayns[2] = 1234
warray[2] = 5678
farray[2] = 3.1415
dump()
pokew(2000, 1)
pokew(2002, 2)
pokew(2004, 3)
pokew(2006, 4)
pokew(2008, 5)
pokef(3000, 1.111)
pokef(3008, 2.222)
pokef(3016, 3.333)
pokef(3024, 4.444)
pokef(3032, 5.555)
; ALL OK
cx16.r0L=2
barray[cx16.r0L] = false
warrayns[cx16.r0L] = 0
warray[cx16.r0L] = 0
farray[cx16.r0L] = 0
dump()
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()
lvref2()
lvref1f()
lvref2f()
; ALL OK
barray[2] = false
warrayns[2] = 0
warray[2] = 0
farray[2] = 0.0
dump()
ref1()
ref2()
ref1f()
ref2f()
sub lvref1() {
l.s[2] = 3333
}
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])
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()
}
}
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? {
if(type==IRDataType.FLOAT) {
// some float instructions have an integer register as well.
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))
// 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.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
else
IRDataType.WORD