improve detection of register re-use in parameters

This commit is contained in:
Irmen de Jong 2024-11-24 05:27:43 +01:00
parent cc53d698bf
commit 18e37accf9
2 changed files with 48 additions and 62 deletions

View File

@ -451,66 +451,49 @@ internal class AstChecker(private val program: Program,
}
}
val regCounts = mutableMapOf<CpuRegister, Int>().withDefault { 0 }
val statusflagCounts = mutableMapOf<Statusflag, Int>().withDefault { 0 }
val regsUsed = mutableListOf<RegisterOrPair>()
val statusflagUsed = mutableListOf<Statusflag>()
fun countRegisters(from: Iterable<RegisterOrStatusflag>) {
regCounts.clear()
statusflagCounts.clear()
regsUsed.clear()
statusflagUsed.clear()
for(p in from) {
when(p.registerOrPair) {
RegisterOrPair.A -> regCounts[CpuRegister.A]=regCounts.getValue(CpuRegister.A)+1
RegisterOrPair.X -> regCounts[CpuRegister.X]=regCounts.getValue(CpuRegister.X)+1
RegisterOrPair.Y -> regCounts[CpuRegister.Y]=regCounts.getValue(CpuRegister.Y)+1
null -> {
if (p.statusflag != null)
statusflagUsed += p.statusflag!!
}
RegisterOrPair.AX -> {
regCounts[CpuRegister.A]=regCounts.getValue(CpuRegister.A)+1
regCounts[CpuRegister.X]=regCounts.getValue(CpuRegister.X)+1
regsUsed += RegisterOrPair.A
regsUsed += RegisterOrPair.X
}
RegisterOrPair.AY -> {
regCounts[CpuRegister.A]=regCounts.getValue(CpuRegister.A)+1
regCounts[CpuRegister.Y]=regCounts.getValue(CpuRegister.Y)+1
regsUsed += RegisterOrPair.A
regsUsed += RegisterOrPair.Y
}
RegisterOrPair.XY -> {
regCounts[CpuRegister.X]=regCounts.getValue(CpuRegister.X)+1
regCounts[CpuRegister.Y]=regCounts.getValue(CpuRegister.Y)+1
}
RegisterOrPair.FAC1, RegisterOrPair.FAC2 -> { /* no sensible way to count this */ }
RegisterOrPair.R0,
RegisterOrPair.R1,
RegisterOrPair.R2,
RegisterOrPair.R3,
RegisterOrPair.R4,
RegisterOrPair.R5,
RegisterOrPair.R6,
RegisterOrPair.R7,
RegisterOrPair.R8,
RegisterOrPair.R9,
RegisterOrPair.R10,
RegisterOrPair.R11,
RegisterOrPair.R12,
RegisterOrPair.R13,
RegisterOrPair.R14,
RegisterOrPair.R15 -> { /* no sensible way to count this */ }
null -> {
val statusf = p.statusflag
if (statusf != null)
statusflagCounts[statusf] = statusflagCounts.getValue(statusf) + 1
regsUsed += RegisterOrPair.X
regsUsed += RegisterOrPair.Y
}
else -> regsUsed += p.registerOrPair!!
}
}
}
countRegisters(subroutine.asmParameterRegisters)
if(regCounts.any{it.value>1})
if(regsUsed.size != regsUsed.toSet().size)
err("a register is used multiple times in the parameters")
if(statusflagCounts.any{it.value>1})
if(statusflagUsed.size != statusflagUsed.toSet().size)
err("a status flag is used multiple times in the parameters")
countRegisters(subroutine.asmReturnvaluesRegisters)
if(regCounts.any{it.value>1})
if(regsUsed.size != regsUsed.toSet().size)
err("a register is used multiple times in the return values")
if(statusflagCounts.any{it.value>1})
if(statusflagUsed.size != statusflagUsed.toSet().size)
err("a status flag is used multiple times in the return values")
if(subroutine.asmClobbers.intersect(regCounts.keys).isNotEmpty())
err("a return register is also in the clobber list")
for(reg in subroutine.asmClobbers) {
if(regsUsed.contains(RegisterOrPair.fromCpuRegister(reg)))
err("a return register is also in the clobber list")
}
if(subroutine.statements.any{it !is InlineAssembly})
err("asmsub can only contain inline assembly (%asm)")

View File

@ -3,31 +3,34 @@
main {
sub start() {
const long foo2 = $123456
cx16.r0 = $ffff
cx16.r1 = $ea31
txt.print_uwbin(cx16.r1 << 7, true)
txt.nl()
txt.print_uwhex(cx16.r0 ^ cx16.r1, true)
txt.nl()
txt.print_ubhex(^cx16.r0, true)
txt.spc()
txt.print_uwhex(<<cx16.r0, false)
txt.nl()
txt.print_ubhex(^foo2, true)
txt.spc()
txt.print_uwhex(<<foo2, false)
txt.nl()
txt.print_ubhex(bankof(foo2), true)
txt.spc()
txt.print_uwhex(foo2 &$ffff, false)
foo(42)
bar(9999,55)
txt.nl()
test(1,2,3)
test2(1)
}
txt.print_ubhex(msw(foo2), true)
txt.spc()
txt.print_uwhex(lsw(foo2), false)
sub foo(ubyte arg) {
txt.print_ub(arg)
txt.nl()
}
sub bar(uword arg, ubyte arg2) {
txt.print_uw(arg)
txt.spc()
txt.print_ub(arg2)
txt.nl()
}
asmsub test(ubyte a1 @R1, ubyte a2 @R1, ubyte a3 @R2) { ; TODO should give register reuse error
%asm {{
rts
}}
}
asmsub test2(uword a1 @AY) clobbers(A, X) -> ubyte @X {
%asm {{
rts
}}
}
}