mirror of
https://github.com/irmen/prog8.git
synced 2026-10-22 05:02:58 +00:00
code cleanups
This commit is contained in:
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)
|
||||
}
|
||||
Reference in new issue
Block a user