code cleanups

This commit is contained in:
Irmen de Jong committed 2026-10-13 22:40:19 +02:00
1 parent dea43c99bb
commit 6cac707fd1
72 files changed
+665 -788

No files matched your search

@@ -655,10 +655,10 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val exprGen
else -> throw AssemblyError("assignment value and target dt mismatch: $valueDt -> $targetDt")
}
}
fun extOpcode(src: IRDataType, dest: IRDataType, signed: Boolean): Opcode = when {
src==IRDataType.BYTE && dest==IRDataType.WORD -> if(signed) Opcode.EXTS else Opcode.EXT
src==IRDataType.WORD && dest==IRDataType.LONG -> if(signed) Opcode.EXTS else Opcode.EXT
src==IRDataType.BYTE && dest==IRDataType.LONG -> if(signed) Opcode.EXTLS else Opcode.EXTL
fun extOpcode(src: IRDataType, dest: IRDataType, signed: Boolean): Opcode = when (src) {
IRDataType.BYTE if dest==IRDataType.WORD -> if(signed) Opcode.EXTS else Opcode.EXT
IRDataType.WORD if dest==IRDataType.LONG -> if(signed) Opcode.EXTS else Opcode.EXT
IRDataType.BYTE if dest==IRDataType.LONG -> if(signed) Opcode.EXTLS else Opcode.EXTL
else -> throw AssemblyError("unsupported extension $src -> $dest")
}
if (assignment.value is PtIrRegister) {
@@ -1537,10 +1537,10 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val exprGen
if(valueTr!=null)
addToResult(result, valueTr, -1, valueTr.resultFpReg)
result += IRCodeChunk(null, null).also {
if(constFloat!=null)
it += IRInstructions.binaryImmediateFloat(divROpcode, loadReg, constFloat)
it += if(constFloat!=null)
IRInstructions.binaryImmediateFloat(divROpcode, loadReg, constFloat)
else
it += IRInstructions.binary(divROpcode, IRDataType.FLOAT, loadReg, valueTr!!.resultFpReg)
IRInstructions.binary(divROpcode, IRDataType.FLOAT, loadReg, valueTr!!.resultFpReg)
it += IRInstructions.storeMemory(Opcode.STOREX, IRDataType.FLOAT, loadReg, IRMemory.indexed(arrayVariableName, indexReg, codeGen.options.compTarget.indexRegType))
}
return result
@@ -3066,14 +3066,14 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val exprGen
result += idxCode
if(zero) {
result += IRCodeChunk(null, null).also {
if(info.fieldOffset==0) it += IRInstructions.storeZero(Opcode.STOREZX, targetDt, IRMemory.indexed(info.arrayName, indexReg, codeGen.options.compTarget.indexRegType, scale=info.structSize))
else it += IRInstructions.storeZero(Opcode.STOREZX, targetDt, IRMemory.indexed(info.arrayName, indexReg, codeGen.options.compTarget.indexRegType, scale=info.structSize, displacement=info.fieldOffset))
it += if(info.fieldOffset==0) IRInstructions.storeZero(Opcode.STOREZX, targetDt, IRMemory.indexed(info.arrayName, indexReg, codeGen.options.compTarget.indexRegType, scale=info.structSize))
else IRInstructions.storeZero(Opcode.STOREZX, targetDt, IRMemory.indexed(info.arrayName, indexReg, codeGen.options.compTarget.indexRegType, scale=info.structSize, displacement=info.fieldOffset))
}
} else {
if(valueReg<0) return false
result += IRCodeChunk(null, null).also {
if(info.fieldOffset==0) it += IRInstructions.storeMemory(Opcode.STOREX, targetDt, valueReg, IRMemory.indexed(info.arrayName, indexReg, codeGen.options.compTarget.indexRegType, scale=info.structSize))
else it += IRInstructions.storeMemory(Opcode.STOREX, targetDt, valueReg, IRMemory.indexed(info.arrayName, indexReg, codeGen.options.compTarget.indexRegType, scale=info.structSize, displacement=info.fieldOffset))
it += if(info.fieldOffset==0) IRInstructions.storeMemory(Opcode.STOREX, targetDt, valueReg, IRMemory.indexed(info.arrayName, indexReg, codeGen.options.compTarget.indexRegType, scale=info.structSize))
else IRInstructions.storeMemory(Opcode.STOREX, targetDt, valueReg, IRMemory.indexed(info.arrayName, indexReg, codeGen.options.compTarget.indexRegType, scale=info.structSize, displacement=info.fieldOffset))
}
}
return true
@@ -261,31 +261,39 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
// Route to the return value locations expected by the caller (via returnsWhatWhere).
if(codeGen.options.compTarget.cpu.usesM68kConvention) {
// m68k: first return value in D0 (slot 10), second in D1 (slot 11)
if(type==IRDataType.BYTE) {
result += IRCodeChunk(null, null).also {
it += IRInstructions.hardwareStore(IRDataType.BYTE, remainderReg, CallingConventionSlot(11))
it += IRInstructions.hardwareStore(IRDataType.BYTE, divisionReg, CallingConventionSlot(10))
when (type) {
IRDataType.BYTE -> {
result += IRCodeChunk(null, null).also {
it += IRInstructions.hardwareStore(IRDataType.BYTE, remainderReg, CallingConventionSlot(11))
it += IRInstructions.hardwareStore(IRDataType.BYTE, divisionReg, CallingConventionSlot(10))
}
}
} else if(type==IRDataType.WORD) {
result += IRCodeChunk(null, null).also {
it += IRInstructions.hardwareStore(IRDataType.WORD, remainderReg, CallingConventionSlot(11))
it += IRInstructions.hardwareStore(IRDataType.WORD, divisionReg, CallingConventionSlot(10))
IRDataType.WORD -> {
result += IRCodeChunk(null, null).also {
it += IRInstructions.hardwareStore(IRDataType.WORD, remainderReg, CallingConventionSlot(11))
it += IRInstructions.hardwareStore(IRDataType.WORD, divisionReg, CallingConventionSlot(10))
}
}
} else throw AssemblyError("invalid type for DIVMOD")
else -> throw AssemblyError("invalid type for DIVMOD")
}
} else {
// 6502/cx16: quotient to A (slot 0) or AY (slot 4), remainder to cx16.r15
// Note: STOREM must come before STOREHR, otherwise STOREM clobbers A before LOADHR reads it.
if(type==IRDataType.BYTE) {
result += IRCodeChunk(null, null).also {
it += IRInstructions.storeMemory(Opcode.STOREM, IRDataType.BYTE, remainderReg, IRMemory.direct("cx16.r15"))
it += IRInstructions.hardwareStore(IRDataType.BYTE, divisionReg, CallingConventionSlot(0))
when (type) {
IRDataType.BYTE -> {
result += IRCodeChunk(null, null).also {
it += IRInstructions.storeMemory(Opcode.STOREM, IRDataType.BYTE, remainderReg, IRMemory.direct("cx16.r15"))
it += IRInstructions.hardwareStore(IRDataType.BYTE, divisionReg, CallingConventionSlot(0))
}
}
} else if(type==IRDataType.WORD) {
result += IRCodeChunk(null, null).also {
it += IRInstructions.storeMemory(Opcode.STOREM, IRDataType.WORD, remainderReg, IRMemory.direct("cx16.r15"))
it += IRInstructions.hardwareStore(IRDataType.WORD, divisionReg, CallingConventionSlot(4))
IRDataType.WORD -> {
result += IRCodeChunk(null, null).also {
it += IRInstructions.storeMemory(Opcode.STOREM, IRDataType.WORD, remainderReg, IRMemory.direct("cx16.r15"))
it += IRInstructions.hardwareStore(IRDataType.WORD, divisionReg, CallingConventionSlot(4))
}
}
} else throw AssemblyError("invalid type for DIVMOD")
else -> throw AssemblyError("invalid type for DIVMOD")
}
}
return ExpressionCodeResult(result, type, -1, -1)
}
@@ -996,10 +1004,10 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
val valueTr = exprGen.translateExpression(call.args[1])
addToResult(result, valueTr, valueTr.resultReg, valueTr.resultFpReg)
result += IRCodeChunk(null, null).also {
if(dt==IRDataType.FLOAT) {
it += IRInstructions.storeMemory(Opcode.STOREX, dt, valueTr.resultFpReg, IRMemory.indexed(info.arrayName, indexReg, codeGen.options.compTarget.indexRegType, scale=info.structSize, displacement=info.fieldOffset))
it += if(dt==IRDataType.FLOAT) {
IRInstructions.storeMemory(Opcode.STOREX, dt, valueTr.resultFpReg, IRMemory.indexed(info.arrayName, indexReg, codeGen.options.compTarget.indexRegType, scale=info.structSize, displacement=info.fieldOffset))
} else {
it += IRInstructions.storeMemory(Opcode.STOREX, dt, valueTr.resultReg, IRMemory.indexed(info.arrayName, indexReg, codeGen.options.compTarget.indexRegType, scale=info.structSize, displacement=info.fieldOffset))
IRInstructions.storeMemory(Opcode.STOREX, dt, valueTr.resultReg, IRMemory.indexed(info.arrayName, indexReg, codeGen.options.compTarget.indexRegType, scale=info.structSize, displacement=info.fieldOffset))
}
}
ExpressionCodeResult(result, IRDataType.BYTE, -1, -1)
@@ -62,19 +62,19 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
val vmDt = codeGen.irType(expr.type)
if(vmDt==IRDataType.FLOAT) {
val resultFpRegister = codeGen.registers.next(IRDataType.FLOAT)
if (isConstant) {
code += IRInstructions.loadAddress(IRDataType.FLOAT, resultFpRegister, expr.name)
code += if (isConstant) {
IRInstructions.loadAddress(IRDataType.FLOAT, resultFpRegister, expr.name)
} else {
code += IRInstructions.loadMemory(Opcode.LOADM, IRDataType.FLOAT, resultFpRegister, IRMemory.direct(expr.name))
IRInstructions.loadMemory(Opcode.LOADM, IRDataType.FLOAT, resultFpRegister, IRMemory.direct(expr.name))
}
ExpressionCodeResult(code, vmDt, -1, resultFpRegister)
}
else {
val resultRegister = codeGen.registers.next(vmDt)
if (isConstant) {
code += IRInstructions.loadAddress(vmDt, resultRegister, expr.name)
code += if (isConstant) {
IRInstructions.loadAddress(vmDt, resultRegister, expr.name)
} else {
code += IRInstructions.loadMemory(Opcode.LOADM, vmDt, resultRegister, IRMemory.direct(expr.name))
IRInstructions.loadMemory(Opcode.LOADM, vmDt, resultRegister, IRMemory.direct(expr.name))
}
ExpressionCodeResult(code, vmDt, resultRegister, -1)
}
@@ -395,7 +395,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
if(ptr.value != null)
IRInstructions.load(vmDt, resultRegister, ptr.value!!.toInt())
else
TODO("LOAD memory() address? ${ptr}")
TODO("LOAD memory() address? $ptr")
}
else
IRInstructions.loadMemory(Opcode.LOADM, vmDt, resultRegister, IRMemory.direct(identifier.name))
@@ -958,9 +958,9 @@ class IRCodeGen(
addToResult(result, toTr, toTr.resultReg, -1)
val stepTr = expressionEval.translateExpression(iterable.step)
addToResult(result, stepTr, stepTr.resultReg, -1)
val stepReg = when {
stepTr.dt == loopvarDtIr -> stepTr.resultReg
stepTr.dt == IRDataType.WORD && loopvarDtIr == IRDataType.LONG && !iterable.step.type.isSigned -> {
val stepReg = when (stepTr.dt) {
loopvarDtIr -> stepTr.resultReg
IRDataType.WORD if loopvarDtIr == IRDataType.LONG && !iterable.step.type.isSigned -> {
val widenedReg = registers.next(IRDataType.LONG)
addInstr(result, IRInstructions.binary(Opcode.EXT, IRDataType.WORD, widenedReg, stepTr.resultReg), null)
widenedReg
@@ -1194,11 +1194,10 @@ class IRCodeGen(
code += IRInstructions.memoryOp(Opcode.SUBM, dt, mem(), valueReg)
}
} else {
if(value>0) {
code += IRInstructions.memoryOpImmediate(Opcode.ADDIM, dt, mem(), value)
} else {
code += IRInstructions.memoryOpImmediate(Opcode.SUBIM, dt, mem(), -value)
}
code += if(value>0)
IRInstructions.memoryOpImmediate(Opcode.ADDIM, dt, mem(), value)
else
IRInstructions.memoryOpImmediate(Opcode.SUBIM, dt, mem(), -value)
}
}
}
@@ -1237,15 +1236,14 @@ class IRCodeGen(
if(factor==1)
return code
val pow2 = powersOfTwoInt.indexOf(factor)
if(pow2==1) {
code += if(pow2==1) {
// just shift 1 bit
code += IRInstructions.unary(Opcode.LSL, irdt, reg)
}
else if(pow2>=1) {
IRInstructions.unary(Opcode.LSL, irdt, reg)
} else if(pow2>=1) {
// just shift multiple bits
code += IRInstructions.binaryImmediate(Opcode.LSLI, irdt, reg, pow2)
IRInstructions.binaryImmediate(Opcode.LSLI, irdt, reg, pow2)
} else {
code += if (factor == 0) {
if (factor == 0) {
IRInstructions.load(irdt, reg, 0)
} else {
val opcode = if(dt.isSigned) Opcode.MULS else Opcode.MUL
@@ -1318,13 +1316,13 @@ class IRCodeGen(
val pow2 = powersOfTwoInt.indexOf(factor)
if(pow2>=0 && !signed) {
// unsigned division by a power of two: logical shift right (correct)
if(pow2==1) {
code += IRInstructions.unary(Opcode.LSR, dt, reg)
code += if(pow2==1) {
IRInstructions.unary(Opcode.LSR, dt, reg)
} else if(dt == IRDataType.LONG && pow2 == 16) {
// x / 65536 for unsigned long == x >> 16 == MSIGW(x)
code += IRInstructions.binary(Opcode.MSIGW, dt, reg, reg)
IRInstructions.binary(Opcode.MSIGW, dt, reg, reg)
} else {
code += IRInstructions.binaryImmediate(Opcode.LSRI, dt, reg, pow2)
IRInstructions.binaryImmediate(Opcode.LSRI, dt, reg, pow2)
}
return code
}
@@ -1829,8 +1827,7 @@ class IRCodeGen(
result += callResult.chunks
// Get the return register specs for the called function
val calledSub = symbolTable.lookup(fcall.name)
val calledReturnRegs = when(calledSub) {
val calledReturnRegs = when(val calledSub = symbolTable.lookup(fcall.name)) {
is StSub -> (calledSub.astNode!! as IPtSubroutine).returnsWhatWhere(options.compTarget)
is StExtSub -> calledSub.returns.map { it.register to it.type }
else -> throw AssemblyError("unexpected subroutine type for multi-value return ${ret.position}")
@@ -1848,12 +1845,12 @@ class IRCodeGen(
when(fromReg.registerOrPair) {
RegisterOrPair.FAC1 -> addInstr(result, IRInstructions.unary(Opcode.LOADHFACZERO, IRDataType.FLOAT, tempFpReg), null)
RegisterOrPair.FAC2 -> addInstr(result, IRInstructions.unary(Opcode.LOADHFACONE, IRDataType.FLOAT, tempFpReg), null)
else -> throw AssemblyError("unexpected FP return register ${fromReg}")
else -> throw AssemblyError("unexpected FP return register $fromReg")
}
when(toReg.registerOrPair) {
RegisterOrPair.FAC1 -> addInstr(result, storeHwFac(Opcode.STOREHFACZERO, tempFpReg), null)
RegisterOrPair.FAC2 -> addInstr(result, storeHwFac(Opcode.STOREHFACONE, tempFpReg), null)
else -> throw AssemblyError("unexpected FP return register ${toReg}")
else -> throw AssemblyError("unexpected FP return register $toReg")
}
} else {
// For non-float returns, load from source to temp IR register, then store to destination
@@ -2177,7 +2174,7 @@ class IRCodeGen(
}
else -> throw AssemblyError("unsupported statusflag ${registerOrFlag.statusflag}")
}
else -> throw AssemblyError("weird CPU register ${registerOrFlag}")
else -> throw AssemblyError("weird CPU register $registerOrFlag")
}
return chunk
}
@@ -2258,15 +2255,19 @@ class IRCodeGen(
val indexDt = byteIndexTr.dt
if(indexDt != indexRegType) {
val newReg = registers.next(indexRegType)
when {
indexRegType == IRDataType.WORD && indexDt == IRDataType.BYTE ->
when (indexRegType) {
IRDataType.WORD if indexDt == IRDataType.BYTE ->
addInstr(result, IRInstructions.binary(Opcode.EXT, IRDataType.BYTE, newReg, byteIndexTr.resultReg), null)
indexRegType == IRDataType.WORD && indexDt == IRDataType.LONG ->
IRDataType.WORD if indexDt == IRDataType.LONG ->
addInstr(result, IRInstructions.binary(Opcode.LSIGW, IRDataType.LONG, newReg, byteIndexTr.resultReg), null)
indexRegType == IRDataType.BYTE && indexDt == IRDataType.WORD ->
IRDataType.BYTE if indexDt == IRDataType.WORD ->
addInstr(result, IRInstructions.binary(Opcode.LSIGB, IRDataType.WORD, newReg, byteIndexTr.resultReg), null)
indexRegType == IRDataType.BYTE && indexDt == IRDataType.LONG ->
IRDataType.BYTE if indexDt == IRDataType.LONG ->
addInstr(result, IRInstructions.binary(Opcode.LSIGB, IRDataType.LONG, newReg, byteIndexTr.resultReg), null)
else -> throw IllegalArgumentException("unexpected index conversion $indexDt -> $indexRegType")
}
indexReg = newReg
@@ -2284,24 +2285,30 @@ class IRCodeGen(
if(effectiveDt == indexRegType)
return indexTr.resultReg
val newReg = registers.next(indexRegType)
when {
indexRegType==IRDataType.WORD && indexTr.dt==IRDataType.BYTE ->
when (indexRegType) {
IRDataType.WORD if indexTr.dt==IRDataType.BYTE ->
addInstr(result, IRInstructions.binary(Opcode.EXT, IRDataType.BYTE, newReg, indexTr.resultReg), null)
indexRegType==IRDataType.WORD && indexTr.dt==IRDataType.LONG ->
IRDataType.WORD if indexTr.dt==IRDataType.LONG ->
addInstr(result, IRInstructions.binary(Opcode.LSIGW, IRDataType.LONG, newReg, indexTr.resultReg), null)
indexRegType==IRDataType.WORD && indexTr.dt==IRDataType.POINTER ->
IRDataType.WORD if indexTr.dt==IRDataType.POINTER ->
addInstr(result, IRInstructions.binary(Opcode.LSIGW, IRDataType.LONG, newReg, indexTr.resultReg), null)
indexRegType==IRDataType.BYTE && indexTr.dt==IRDataType.WORD ->
IRDataType.BYTE if indexTr.dt==IRDataType.WORD ->
addInstr(result, IRInstructions.binary(Opcode.LSIGB, IRDataType.WORD, newReg, indexTr.resultReg), null)
indexRegType==IRDataType.BYTE && indexTr.dt==IRDataType.LONG ->
IRDataType.BYTE if indexTr.dt==IRDataType.LONG ->
addInstr(result, IRInstructions.binary(Opcode.LSIGB, IRDataType.LONG, newReg, indexTr.resultReg), null)
indexRegType==IRDataType.BYTE && indexTr.dt==IRDataType.POINTER -> {
IRDataType.BYTE if indexTr.dt==IRDataType.POINTER -> {
val ptrType = options.compTarget.pointerIRType
if(ptrType==IRDataType.WORD)
addInstr(result, IRInstructions.binary(Opcode.LSIGB, IRDataType.WORD, newReg, indexTr.resultReg), null)
else
addInstr(result, IRInstructions.binary(Opcode.LSIGB, IRDataType.LONG, newReg, indexTr.resultReg), null)
}
else -> throw IllegalArgumentException("unexpected index conversion ${indexTr.dt} -> $indexRegType")
}
return newReg
@@ -481,8 +481,7 @@ jump p8_label_gen_2
val delta = arithmeticDelta(ins)
val nextDelta = arithmeticDelta(nextInstr)
if(delta != null && nextDelta != null) {
val newDelta = delta + nextDelta
when(newDelta) {
when(val newDelta = delta + nextDelta) {
0 -> {
chunk.instructions[idx] = IRInstructions.simple(Opcode.NOP)
chunk.instructions[idx+1] = IRInstructions.simple(Opcode.NOP)
@@ -624,8 +623,7 @@ jump p8_label_gen_2
}
}
Opcode.OR -> {
val imm = ins.immediate?.integerValue
if (imm == null) return@forEach
val imm = ins.immediate?.integerValue ?: return@forEach
if (imm == 0) {
chunk.instructions.removeAt(idx)
changed = true
@@ -643,8 +641,7 @@ jump p8_label_gen_2
}
}
Opcode.XOR -> {
val imm = ins.immediate?.integerValue
if (imm == null) return@forEach
val imm = ins.immediate?.integerValue ?: return@forEach
if (imm == 0) {
chunk.instructions.removeAt(idx)
changed = true
@@ -866,7 +863,7 @@ jump p8_label_gen_2
var foundIdx: Int? = null
var foundIns: IRInstruction? = null
for((midIdx, midIns) in indexedInstructions) {
if(midIdx <= loadmIdx || midIdx >= incIdx) continue
if(midIdx !in (loadmIdx + 1)..<incIdx) continue
if(midIdx in toRemove || midIdx in toReplace) continue
if(midIns.type == IRDataType.FLOAT) continue
val indirect = midIns.memory as? MemoryReference.Indirect ?: continue
@@ -1220,8 +1217,7 @@ jump p8_label_gen_2
}
fun writesMem(ins: IRInstruction, key: MemKey): Boolean {
if(memKey(ins) != key) return false
return ins.memoryEffect == MemoryEffect.WRITE || ins.memoryEffect == MemoryEffect.READ_WRITE
return memKey(ins) == key && (ins.memoryEffect == MemoryEffect.WRITE || ins.memoryEffect == MemoryEffect.READ_WRITE)
}
val groups = mutableListOf<AddrGroup>()
@@ -1372,7 +1368,6 @@ jump p8_label_gen_2
if (stInstr.opcode != Opcode.STOREM || stInstr.srcA == null) { idx++; continue }
val loopvarSymbol = stInstr.memory?.symbolName
if (loopvarSymbol == null) { idx++; continue }
val loopvar = loopvarSymbol
val loopReg = stInstr.requireSrcA().register
val loopType = stInstr.type ?: IRDataType.WORD
// next chunk should be the loop body start with a label
@@ -1388,7 +1383,7 @@ jump p8_label_gen_2
for (k in idx + 1 until sub.chunks.size) {
val c = sub.chunks[k]
if (c !is IRCodeChunk) continue
val hasIncDec = c.instructions.any { it.opcode in setOf(Opcode.INCM, Opcode.DECM) && it.memory?.symbolName == loopvar }
val hasIncDec = c.instructions.any { it.opcode in setOf(Opcode.INCM, Opcode.DECM) && it.memory?.symbolName == loopvarSymbol }
if (!hasIncDec) continue
// old shape: INCM then (same chunk or next chunk) JUMP loopLabel
@@ -1408,7 +1403,7 @@ jump p8_label_gen_2
val i1 = nxt.instructions[0]
val i2 = nxt.instructions[1]
val i3 = nxt.instructions[2]
if (i1.opcode == Opcode.LOADM && i1.memory?.symbolName == loopvar && i1.dest != null &&
if (i1.opcode == Opcode.LOADM && i1.memory?.symbolName == loopvarSymbol && i1.dest != null &&
i2.opcode == Opcode.CMP && (i2.srcA?.register == i1.dest?.register || i2.srcB?.register == i1.dest?.register) &&
i3.opcode == Opcode.BSTNE && i3.labelTarget == loopLabel) {
tail = Tail(k, k + 1, false)
@@ -1429,7 +1424,7 @@ jump p8_label_gen_2
if (ch !is IRCodeChunk) continue
for (ins in ch.instructions) {
// any store/inc/dec that writes to loopvar memory
if (ins.memory?.symbolName == loopvar && ins.opcode in setOf(Opcode.STOREM, Opcode.STOREIM, Opcode.STOREZM, Opcode.STOREX, Opcode.STOREZX, Opcode.INCM, Opcode.DECM, Opcode.ADDIM, Opcode.SUBIM)) {
if (ins.memory?.symbolName == loopvarSymbol && ins.opcode in setOf(Opcode.STOREM, Opcode.STOREIM, Opcode.STOREZM, Opcode.STOREX, Opcode.STOREZX, Opcode.INCM, Opcode.DECM, Opcode.ADDIM, Opcode.SUBIM)) {
// exclude the initial STOREM itself (not in body) and the inc chunk (not in body)
bodyWrites = true; break
}
@@ -1449,7 +1444,7 @@ jump p8_label_gen_2
for (k in tailEnd + 1 until sub.chunks.size) {
val ch = sub.chunks[k] as? IRCodeChunk ?: continue
for (ins in ch.instructions) {
if (ins.opcode == Opcode.LOADM && ins.memory?.symbolName == loopvar) { liveOut = true; break }
if (ins.opcode == Opcode.LOADM && ins.memory?.symbolName == loopvarSymbol) { liveOut = true; break }
}
if (liveOut) break
}
@@ -1466,7 +1461,7 @@ jump p8_label_gen_2
val ch = sub.chunks[b] as? IRCodeChunk ?: continue
for (i in ch.instructions.indices) {
val ins = ch.instructions[i]
if (ins.opcode == Opcode.LOADM && ins.memory?.symbolName == loopvar) {
if (ins.opcode == Opcode.LOADM && ins.memory?.symbolName == loopvarSymbol) {
val dest = ins.requireDest().register
if (dest == loopReg) {
// Already holds the correct value; remove the reload
@@ -1482,7 +1477,7 @@ jump p8_label_gen_2
val incChunk = sub.chunks[incIdx] as IRCodeChunk
for (i in incChunk.instructions.indices) {
val ins = incChunk.instructions[i]
if (ins.memory?.symbolName == loopvar && ins.opcode in setOf(Opcode.INCM, Opcode.DECM)) {
if (ins.memory?.symbolName == loopvarSymbol && ins.opcode in setOf(Opcode.INCM, Opcode.DECM)) {
val newOpcode = if (ins.opcode == Opcode.INCM) Opcode.INC else Opcode.DEC
incChunk.instructions[i] = IRInstructions.unary(newOpcode, loopType, loopReg.num)
break
@@ -1493,7 +1488,7 @@ jump p8_label_gen_2
val cmpChunk = sub.chunks[newCmpIdx] as IRCodeChunk
for (i in cmpChunk.instructions.indices) {
val ins = cmpChunk.instructions[i]
if (ins.opcode == Opcode.LOADM && ins.memory?.symbolName == loopvar) {
if (ins.opcode == Opcode.LOADM && ins.memory?.symbolName == loopvarSymbol) {
val dest = ins.requireDest().register
if (dest == loopReg) {
cmpChunk.instructions[i] = IRInstructions.simple(Opcode.NOP)
@@ -428,9 +428,8 @@ object RegisterPacker {
}
private fun typesCompatible(t1: IRDataType, t2: IRDataType): Boolean {
if (t1 == t2) return true
return (t1 == IRDataType.POINTER && t2 in setOf(IRDataType.WORD, IRDataType.LONG)) ||
(t2 == IRDataType.POINTER && t1 in setOf(IRDataType.WORD, IRDataType.LONG))
return t1 == t2 || (t1 == IRDataType.POINTER && t2 in setOf(IRDataType.WORD, IRDataType.LONG)) ||
(t2 == IRDataType.POINTER && t1 in setOf(IRDataType.WORD, IRDataType.LONG))
}
private fun conflictsWithRegister(
@@ -340,8 +340,8 @@ class StackFrameLayout(private val program: IRProgram, private val errors: IErro
val (node, children) = work.last()
if (children.hasNext()) {
val next = children.next()
when {
next !in index -> {
when (next) {
!in index -> {
index[next] = counter
lowLink[next] = counter
counter++
@@ -349,7 +349,7 @@ class StackFrameLayout(private val program: IRProgram, private val errors: IErro
onStack += next
work.addLast(next to edges.getValue(next).iterator())
}
next in onStack -> {
in onStack -> {
lowLink[node] = minOf(lowLink.getValue(node), index.getValue(next))
}
}
@@ -388,7 +388,7 @@ class StackFrameLayout(private val program: IRProgram, private val errors: IErro
/** outcome of the frameability decision for one subroutine */
private sealed interface Frameability {
class Frameable(val layout: FrameLayoutResult) : Frameability
class NotFrameable() : Frameability
data object NotFrameable : Frameability
}
private fun frameableSubroutine(
@@ -403,7 +403,7 @@ class StackFrameLayout(private val program: IRProgram, private val errors: IErro
reachesFramePointerClobber: Set<String>,
framePointerClobberers: Set<String>
): Frameability {
val static = { Frameability.NotFrameable() }
val static = { Frameability.NotFrameable }
// a %option noframe subroutine requires the legacy static convention (it manipulates
// the machine stack itself), so it never gets a frame
if (sub.noframe) return static()
@@ -450,7 +450,6 @@ class StackFrameLayout(private val program: IRProgram, private val errors: IErro
// each slot takes its own width (2 or 4 bytes), accumulated from the last parameter backwards
var incomingSize = 0
for (name in scopedParamNames.reversed()) {
val irType = slotIrTypes.getValue(name)
val slotSize = slotSizes.getValue(name)
paramSlots[name] = INCOMING_BASE + incomingSize
// single-instruction byte pushes land at the slot base, so all parameters
@@ -506,7 +505,7 @@ class StackFrameLayout(private val program: IRProgram, private val errors: IErro
val elemDt = isFrameableVariable(v, name, addressTaken, asmTexts) ?: continue
val count = v.length?.toInt() ?: 1
val size = target.memorySize(v.dt, v.length?.toInt())
if (size <= 0 || size >= MAX_FRAME_SIZE) continue
if (size !in 1..<MAX_FRAME_SIZE) continue
val alignment = when {
size >= 4 -> 4
size >= 2 -> 2
@@ -642,10 +641,10 @@ class StackFrameLayout(private val program: IRProgram, private val errors: IErro
// a static-initialized local gets its initializer stored into the frame slot;
// this replaces the zero-clear for it
val irType = irTypeFor(fv.elemDt) ?: continue
if (irType == IRDataType.FLOAT)
prologueInstrs += IRInstructions.storeImmediateFloat(init.value, IRMemory.frameDirect(fv.slot))
prologueInstrs += if (irType == IRDataType.FLOAT)
IRInstructions.storeImmediateFloat(init.value, IRMemory.frameDirect(fv.slot))
else
prologueInstrs += IRInstructions.storeImmediate(irType, init.value.toInt(), IRMemory.frameDirect(fv.slot))
IRInstructions.storeImmediate(irType, init.value.toInt(), IRMemory.frameDirect(fv.slot))
continue
}
if (fv.dirty) continue
@@ -24,17 +24,19 @@ internal fun extractStructArrayIndexInfo(
val baseAddrOf: PtAddressOf
val fieldOffset: Int
val unwrapped = unwrapCast(addressExpr)
when {
unwrapped is PtAddressOf -> {
when (unwrapped) {
is PtAddressOf -> {
baseAddrOf = unwrapped
fieldOffset = 0
}
unwrapped is PtBinaryExpression && unwrapped.operator == "+" -> {
is PtBinaryExpression if unwrapped.operator == "+" -> {
val leftAddr = asAddressOf(unwrapped.left) ?: return null
val rightNum = (unwrapCast(unwrapped.right) as? PtNumber)?.number?.toInt() ?: return null
baseAddrOf = leftAddr
fieldOffset = rightNum
}
else -> return null
}
if(!baseAddrOf.isFromArrayElement) return null
@@ -46,7 +48,7 @@ internal fun extractStructArrayIndexInfo(
val elemType = arrayType.elementType()
if(!elemType.isStructInstance) return null
val structSize = codeGen.program.memsizer.memorySize(elemType, null)
if(structSize <= 0 || structSize > 65535) return null
if(fieldOffset < 0 || fieldOffset > 65535) return null
if(structSize !in 1..65535) return null
if(fieldOffset !in 0..65535) return null
return StructArrayIndexInfo(arrayIdent.name, idxExpr, structSize, fieldOffset)
}