mirror of
https://github.com/irmen/prog8.git
synced 2025-02-13 18:31:04 +00:00
ir: enforce single reg type
This commit is contained in:
parent
f42e12bc13
commit
ee521793f8
@ -56,6 +56,7 @@ Future Things and Ideas
|
||||
|
||||
IR/VM
|
||||
-----
|
||||
- fix the syscall interface. It should not use r0 as return reg, but something in the 65000 range. Also, separete input regs for byte or word types.
|
||||
- getting it in shape for code generation...: the IR file should be able to encode every detail about a prog8 program (the VM doesn't have to actually be able to run all of it though!)
|
||||
- add BZ and BNZ instructions? To replace CMPI #0 + Branch?
|
||||
- fix TODO("IR rol/ror on split words array")
|
||||
|
@ -139,14 +139,8 @@ class IRFileWriter(private val irProgram: IRProgram, outfileOverride: Path?) {
|
||||
if (usedRegs.writeRegs.any())
|
||||
regs.append(" write: ${usedRegs.writeRegs.toSortedMap().map { (reg, amount) -> "r$reg=${amount}" }}\n")
|
||||
regs.append(" types:\n")
|
||||
for ((regnum, types) in usedRegs.regsTypes.toSortedMap()) {
|
||||
regs.append(" r$regnum -> $types")
|
||||
if (types.size > 1) {
|
||||
regs.append(" !!!! more than one type !!!!\n")
|
||||
println("IR: Detected multi-type register usage: $regnum->$types in ${chunk.label} at perhaps ${chunk.sourceLinesPositions.firstOrNull()}")
|
||||
}
|
||||
else
|
||||
regs.append("\n")
|
||||
for ((regnum, type) in usedRegs.regsTypes.toSortedMap()) {
|
||||
regs.append(" r$regnum -> $type\n")
|
||||
}
|
||||
}
|
||||
if(usedRegs.readFpRegs.any() || usedRegs.writeFpRegs.any()) {
|
||||
|
@ -83,7 +83,8 @@ call label(argument register list) [: resultreg.type]
|
||||
syscall number (argument register list) [: resultreg.type]
|
||||
- do a systemcall identified by number, result value(s) are pushed on value stack by the syscall code so
|
||||
will be POPped off into the given resultregister if any.
|
||||
Always preceded by parameter setup and preparecall instructions
|
||||
Always preceded by parameter setup and preparecall instructions.
|
||||
All register types (arguments + result register) are ALWAYS WORDS.
|
||||
return - restore last saved instruction location and continue at that instruction. No return value.
|
||||
returnr reg1 - like return, but also returns the value in reg1 to the caller
|
||||
returni number - like return, but also returns the immediate value to the caller
|
||||
@ -862,7 +863,7 @@ data class IRInstruction(
|
||||
writeRegsCounts: MutableMap<Int, Int>,
|
||||
readFpRegsCounts: MutableMap<Int, Int>,
|
||||
writeFpRegsCounts: MutableMap<Int, Int>,
|
||||
regsTypes: MutableMap<Int, MutableSet<IRDataType>>
|
||||
regsTypes: MutableMap<Int, IRDataType>
|
||||
) {
|
||||
when (this.reg1direction) {
|
||||
OperandDirection.UNUSED -> {}
|
||||
@ -870,20 +871,25 @@ data class IRInstruction(
|
||||
readRegsCounts[this.reg1!!] = readRegsCounts.getValue(this.reg1)+1
|
||||
val actualtype = determineReg1Type()
|
||||
if(actualtype!=null) {
|
||||
var types = regsTypes[this.reg1]
|
||||
if(types==null) types = mutableSetOf()
|
||||
types += actualtype
|
||||
regsTypes[this.reg1] = types
|
||||
val existingType = regsTypes[reg1]
|
||||
if (existingType!=null) {
|
||||
if (existingType != actualtype)
|
||||
throw IllegalArgumentException("register $reg1 assigned multiple types! $existingType and $actualtype")
|
||||
} else
|
||||
regsTypes[reg1] = actualtype
|
||||
}
|
||||
}
|
||||
OperandDirection.WRITE -> {
|
||||
writeRegsCounts[this.reg1!!] = writeRegsCounts.getValue(this.reg1)+1
|
||||
val actualtype = determineReg1Type()
|
||||
if(actualtype!=null) {
|
||||
var types = regsTypes[this.reg1]
|
||||
if(types==null) types = mutableSetOf()
|
||||
types += actualtype
|
||||
regsTypes[this.reg1] = types
|
||||
val existingType = regsTypes[reg1]
|
||||
if (existingType!=null) {
|
||||
if (existingType != actualtype)
|
||||
throw IllegalArgumentException("register $reg1 assigned multiple types! $existingType and $actualtype")
|
||||
} else
|
||||
regsTypes[reg1] = actualtype
|
||||
|
||||
}
|
||||
}
|
||||
OperandDirection.READWRITE -> {
|
||||
@ -891,10 +897,13 @@ data class IRInstruction(
|
||||
writeRegsCounts[this.reg1] = writeRegsCounts.getValue(this.reg1)+1
|
||||
val actualtype = determineReg1Type()
|
||||
if(actualtype!=null) {
|
||||
var types = regsTypes[this.reg1]
|
||||
if(types==null) types = mutableSetOf()
|
||||
types += actualtype
|
||||
regsTypes[this.reg1] = types
|
||||
val existingType = regsTypes[reg1]
|
||||
if (existingType!=null) {
|
||||
if (existingType != actualtype)
|
||||
throw IllegalArgumentException("register $reg1 assigned multiple types! $existingType and $actualtype")
|
||||
} else
|
||||
regsTypes[reg1] = actualtype
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -904,10 +913,12 @@ data class IRInstruction(
|
||||
writeRegsCounts[this.reg2!!] = writeRegsCounts.getValue(this.reg2)+1
|
||||
val actualtype = determineReg2Type()
|
||||
if(actualtype!=null) {
|
||||
var types = regsTypes[this.reg2]
|
||||
if(types==null) types = mutableSetOf()
|
||||
types += actualtype
|
||||
regsTypes[this.reg2] = types
|
||||
val existingType = regsTypes[reg2]
|
||||
if (existingType!=null) {
|
||||
if (existingType != actualtype)
|
||||
throw IllegalArgumentException("register $reg2 assigned multiple types! $existingType and $actualtype")
|
||||
} else
|
||||
regsTypes[reg2] = actualtype
|
||||
}
|
||||
}
|
||||
else -> throw IllegalArgumentException("reg2 can only be read")
|
||||
@ -918,10 +929,12 @@ data class IRInstruction(
|
||||
writeRegsCounts[this.reg3!!] = writeRegsCounts.getValue(this.reg3)+1
|
||||
val actualtype = determineReg3Type()
|
||||
if(actualtype!=null) {
|
||||
var types = regsTypes[this.reg3]
|
||||
if(types==null) types = mutableSetOf()
|
||||
types += actualtype
|
||||
regsTypes[this.reg3] = types
|
||||
val existingType = regsTypes[reg3]
|
||||
if (existingType!=null) {
|
||||
if (existingType != actualtype)
|
||||
throw IllegalArgumentException("register $reg3 assigned multiple types! $existingType and $actualtype")
|
||||
} else
|
||||
regsTypes[reg3] = actualtype
|
||||
}
|
||||
}
|
||||
else -> throw IllegalArgumentException("reg3 can only be read")
|
||||
@ -949,13 +962,12 @@ data class IRInstruction(
|
||||
writeFpRegsCounts[it.registerNum] = writeFpRegsCounts.getValue(it.registerNum) + 1
|
||||
else {
|
||||
writeRegsCounts[it.registerNum] = writeRegsCounts.getValue(it.registerNum) + 1
|
||||
val types = regsTypes[it.registerNum]
|
||||
if (types == null) {
|
||||
regsTypes[it.registerNum] = mutableSetOf(it.dt)
|
||||
} else {
|
||||
types += it.dt
|
||||
regsTypes[it.registerNum] = types
|
||||
}
|
||||
val existingType = regsTypes[it.registerNum]
|
||||
if (existingType!=null) {
|
||||
if (existingType != it.dt)
|
||||
throw IllegalArgumentException("register ${it.registerNum} assigned multiple types! $existingType and ${it.dt}")
|
||||
} else
|
||||
regsTypes[it.registerNum] = it.dt
|
||||
}
|
||||
}
|
||||
fcallArgs.arguments.forEach {
|
||||
@ -963,13 +975,12 @@ data class IRInstruction(
|
||||
readFpRegsCounts[it.reg.registerNum] = readFpRegsCounts.getValue(it.reg.registerNum)+1
|
||||
else {
|
||||
readRegsCounts[it.reg.registerNum] = readRegsCounts.getValue(it.reg.registerNum) + 1
|
||||
val types = regsTypes[it.reg.registerNum]
|
||||
if(types==null) {
|
||||
regsTypes[it.reg.registerNum] = mutableSetOf(it.reg.dt)
|
||||
} else {
|
||||
types += it.reg.dt
|
||||
regsTypes[it.reg.registerNum] = types
|
||||
}
|
||||
val existingType = regsTypes[it.reg.registerNum]
|
||||
if (existingType!=null) {
|
||||
if (existingType != it.reg.dt)
|
||||
throw IllegalArgumentException("register ${it.reg.registerNum} assigned multiple types! $existingType and ${it.reg.dt}")
|
||||
} else
|
||||
regsTypes[it.reg.registerNum] = it.reg.dt
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -265,21 +265,23 @@ class IRProgram(val name: String,
|
||||
|
||||
fun registersUsed(): RegistersUsed {
|
||||
val readRegsCounts = mutableMapOf<Int, Int>().withDefault { 0 }
|
||||
val regsTypes = mutableMapOf<Int, MutableSet<IRDataType>>()
|
||||
val regsTypes = mutableMapOf<Int, IRDataType>()
|
||||
val readFpRegsCounts = mutableMapOf<Int, Int>().withDefault { 0 }
|
||||
val writeRegsCounts = mutableMapOf<Int, Int>().withDefault { 0 }
|
||||
val writeFpRegsCounts = mutableMapOf<Int, Int>().withDefault { 0 }
|
||||
|
||||
fun addUsed(usedRegisters: RegistersUsed) {
|
||||
fun addUsed(usedRegisters: RegistersUsed, child: IIRBlockElement) {
|
||||
usedRegisters.readRegs.forEach{ (reg, count) -> readRegsCounts[reg] = readRegsCounts.getValue(reg) + count }
|
||||
usedRegisters.writeRegs.forEach{ (reg, count) -> writeRegsCounts[reg] = writeRegsCounts.getValue(reg) + count }
|
||||
usedRegisters.readFpRegs.forEach{ (reg, count) -> readFpRegsCounts[reg] = readFpRegsCounts.getValue(reg) + count }
|
||||
usedRegisters.writeFpRegs.forEach{ (reg, count) -> writeFpRegsCounts[reg] = writeFpRegsCounts.getValue(reg) + count }
|
||||
usedRegisters.regsTypes.forEach{ (reg, types) ->
|
||||
var t = regsTypes[reg]
|
||||
if(t==null) t = mutableSetOf()
|
||||
t += types
|
||||
regsTypes[reg] = t
|
||||
usedRegisters.regsTypes.forEach{ (reg, type) ->
|
||||
val existingType = regsTypes[reg]
|
||||
if (existingType!=null) {
|
||||
if (existingType != type)
|
||||
throw IllegalArgumentException("register $reg assigned multiple types! $existingType and $type ${this.name}<--${child.label ?: child}")
|
||||
} else
|
||||
regsTypes[reg] = type
|
||||
}
|
||||
}
|
||||
|
||||
@ -290,11 +292,11 @@ class IRProgram(val name: String,
|
||||
blocks.forEach {block ->
|
||||
block.children.forEach { child ->
|
||||
when(child) {
|
||||
is IRAsmSubroutine -> addUsed(child.usedRegisters())
|
||||
is IRCodeChunk -> addUsed(child.usedRegisters())
|
||||
is IRInlineAsmChunk -> addUsed(child.usedRegisters())
|
||||
is IRInlineBinaryChunk -> addUsed(child.usedRegisters())
|
||||
is IRSubroutine -> child.chunks.forEach { chunk -> addUsed(chunk.usedRegisters()) }
|
||||
is IRAsmSubroutine -> addUsed(child.usedRegisters(), child)
|
||||
is IRCodeChunk -> addUsed(child.usedRegisters(), child)
|
||||
is IRInlineAsmChunk -> addUsed(child.usedRegisters(), child)
|
||||
is IRInlineBinaryChunk -> addUsed(child.usedRegisters(), child)
|
||||
is IRSubroutine -> child.chunks.forEach { chunk -> addUsed(chunk.usedRegisters(), child) }
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -468,7 +470,7 @@ class IRCodeChunk(label: String?, next: IRCodeChunkBase?): IRCodeChunkBase(label
|
||||
override fun isNotEmpty() = instructions.isNotEmpty()
|
||||
override fun usedRegisters(): RegistersUsed {
|
||||
val readRegsCounts = mutableMapOf<Int, Int>().withDefault { 0 }
|
||||
val regsTypes = mutableMapOf<Int, MutableSet<IRDataType>>()
|
||||
val regsTypes = mutableMapOf<Int, IRDataType>()
|
||||
val readFpRegsCounts = mutableMapOf<Int, Int>().withDefault { 0 }
|
||||
val writeRegsCounts = mutableMapOf<Int, Int>().withDefault { 0 }
|
||||
val writeFpRegsCounts = mutableMapOf<Int, Int>().withDefault { 0 }
|
||||
@ -530,7 +532,7 @@ class RegistersUsed(
|
||||
val writeRegs: Map<Int, Int>,
|
||||
val readFpRegs: Map<Int, Int>,
|
||||
val writeFpRegs: Map<Int, Int>,
|
||||
val regsTypes: Map<Int, Set<IRDataType>>
|
||||
val regsTypes: Map<Int, IRDataType>
|
||||
) {
|
||||
|
||||
override fun toString(): String {
|
||||
@ -546,7 +548,7 @@ class RegistersUsed(
|
||||
|
||||
private fun registersUsedInAssembly(isIR: Boolean, assembly: String): RegistersUsed {
|
||||
val readRegsCounts = mutableMapOf<Int, Int>().withDefault { 0 }
|
||||
val regsTypes = mutableMapOf<Int, MutableSet<IRDataType>>()
|
||||
val regsTypes = mutableMapOf<Int, IRDataType>()
|
||||
val readFpRegsCounts = mutableMapOf<Int, Int>().withDefault { 0 }
|
||||
val writeRegsCounts = mutableMapOf<Int, Int>().withDefault { 0 }
|
||||
val writeFpRegsCounts = mutableMapOf<Int, Int>().withDefault { 0 }
|
||||
|
Loading…
x
Reference in New Issue
Block a user