mirror of
https://github.com/irmen/prog8.git
synced 2024-12-24 01:29:28 +00:00
ir: fix memory mapped var as for loop counter
This commit is contained in:
parent
67a36d8d31
commit
a5ef353484
@ -1,6 +1,7 @@
|
||||
package prog8.codegen.intermediate
|
||||
|
||||
import prog8.code.StMemVar
|
||||
import prog8.code.StNode
|
||||
import prog8.code.StStaticVariable
|
||||
import prog8.code.SymbolTable
|
||||
import prog8.code.ast.*
|
||||
@ -411,7 +412,7 @@ class IRCodeGen(
|
||||
}
|
||||
|
||||
private fun translate(forLoop: PtForLoop): IRCodeChunks {
|
||||
val loopvar = symbolTable.lookup(forLoop.variable.targetName) as StStaticVariable
|
||||
val loopvar = symbolTable.lookup(forLoop.variable.targetName)!!
|
||||
val iterable = forLoop.iterable
|
||||
val result = mutableListOf<IRCodeChunkBase>()
|
||||
when(iterable) {
|
||||
@ -480,7 +481,7 @@ class IRCodeGen(
|
||||
return result
|
||||
}
|
||||
|
||||
private fun translateForInNonConstantRange(forLoop: PtForLoop, loopvar: StStaticVariable): IRCodeChunks {
|
||||
private fun translateForInNonConstantRange(forLoop: PtForLoop, loopvar: StNode): IRCodeChunks {
|
||||
val iterable = forLoop.iterable as PtRange
|
||||
val step = iterable.step.number.toInt()
|
||||
if (step==0)
|
||||
@ -488,26 +489,36 @@ class IRCodeGen(
|
||||
val indexReg = registers.nextFree()
|
||||
val endvalueReg = registers.nextFree()
|
||||
val loopvarSymbol = loopvar.scopedName.joinToString(".")
|
||||
val loopvarDt = irType(loopvar.dt)
|
||||
val loopvarDt = when(loopvar) {
|
||||
is StMemVar -> loopvar.dt
|
||||
is StStaticVariable -> loopvar.dt
|
||||
else -> throw AssemblyError("invalid loopvar node type")
|
||||
}
|
||||
val loopvarDtIr = irType(loopvarDt)
|
||||
val loopLabel = createLabelName()
|
||||
val result = mutableListOf<IRCodeChunkBase>()
|
||||
|
||||
result += expressionEval.translateExpression(iterable.to, endvalueReg, -1)
|
||||
result += expressionEval.translateExpression(iterable.from, indexReg, -1)
|
||||
addInstr(result, IRInstruction(Opcode.STOREM, loopvarDt, reg1=indexReg, labelSymbol=loopvarSymbol), null, forLoop.position)
|
||||
addInstr(result, IRInstruction(Opcode.STOREM, loopvarDtIr, reg1=indexReg, labelSymbol=loopvarSymbol), null, forLoop.position)
|
||||
result += labelFirstChunk(translateNode(forLoop.statements), loopLabel)
|
||||
result += addConstMem(loopvarDt, null, loopvarSymbol, step, iterable.position)
|
||||
addInstr(result, IRInstruction(Opcode.LOADM, loopvarDt, reg1 = indexReg, labelSymbol = loopvarSymbol), null, forLoop.position)
|
||||
val branchOpcode = if(loopvar.dt in SignedDatatypes) Opcode.BLES else Opcode.BLE
|
||||
addInstr(result, IRInstruction(branchOpcode, loopvarDt, reg1=indexReg, reg2=endvalueReg, labelSymbol=loopLabel), null, forLoop.position)
|
||||
result += addConstMem(loopvarDtIr, null, loopvarSymbol, step, iterable.position)
|
||||
addInstr(result, IRInstruction(Opcode.LOADM, loopvarDtIr, reg1 = indexReg, labelSymbol = loopvarSymbol), null, forLoop.position)
|
||||
val branchOpcode = if(loopvarDt in SignedDatatypes) Opcode.BLES else Opcode.BLE
|
||||
addInstr(result, IRInstruction(branchOpcode, loopvarDtIr, reg1=indexReg, reg2=endvalueReg, labelSymbol=loopLabel), null, forLoop.position)
|
||||
return result
|
||||
}
|
||||
|
||||
private fun translateForInConstantRange(forLoop: PtForLoop, loopvar: StStaticVariable): IRCodeChunks {
|
||||
private fun translateForInConstantRange(forLoop: PtForLoop, loopvar: StNode): IRCodeChunks {
|
||||
val loopLabel = createLabelName()
|
||||
val loopvarSymbol = loopvar.scopedName.joinToString(".")
|
||||
val indexReg = registers.nextFree()
|
||||
val loopvarDt = irType(loopvar.dt)
|
||||
val loopvarDt = when(loopvar) {
|
||||
is StMemVar -> loopvar.dt
|
||||
is StStaticVariable -> loopvar.dt
|
||||
else -> throw AssemblyError("invalid loopvar node type")
|
||||
}
|
||||
val loopvarDtIr = irType(loopvarDt)
|
||||
val iterable = forLoop.iterable as PtRange
|
||||
val step = iterable.step.number.toInt()
|
||||
val rangeStart = (iterable.from as PtNumber).number.toInt()
|
||||
@ -516,27 +527,27 @@ class IRCodeGen(
|
||||
throw AssemblyError("step 0")
|
||||
if(step>0 && rangeEndUntyped<rangeStart || step<0 && rangeEndUntyped>rangeStart)
|
||||
throw AssemblyError("empty range")
|
||||
val rangeEndWrapped = if(loopvarDt==IRDataType.BYTE) rangeEndUntyped and 255 else rangeEndUntyped and 65535
|
||||
val rangeEndWrapped = if(loopvarDtIr==IRDataType.BYTE) rangeEndUntyped and 255 else rangeEndUntyped and 65535
|
||||
val endvalueReg: Int
|
||||
val result = mutableListOf<IRCodeChunkBase>()
|
||||
val chunk = IRCodeChunk(null, forLoop.position, null)
|
||||
if(rangeEndWrapped!=0) {
|
||||
endvalueReg = registers.nextFree()
|
||||
chunk += IRInstruction(Opcode.LOAD, loopvarDt, reg1 = endvalueReg, value = rangeEndWrapped)
|
||||
chunk += IRInstruction(Opcode.LOAD, loopvarDtIr, reg1 = endvalueReg, value = rangeEndWrapped)
|
||||
} else {
|
||||
endvalueReg = -1 // not used
|
||||
}
|
||||
chunk += IRInstruction(Opcode.LOAD, loopvarDt, reg1=indexReg, value=rangeStart)
|
||||
chunk += IRInstruction(Opcode.STOREM, loopvarDt, reg1=indexReg, labelSymbol=loopvarSymbol)
|
||||
chunk += IRInstruction(Opcode.LOAD, loopvarDtIr, reg1=indexReg, value=rangeStart)
|
||||
chunk += IRInstruction(Opcode.STOREM, loopvarDtIr, reg1=indexReg, labelSymbol=loopvarSymbol)
|
||||
result += chunk
|
||||
result += labelFirstChunk(translateNode(forLoop.statements), loopLabel)
|
||||
result += addConstMem(loopvarDt, null, loopvarSymbol, step, iterable.position)
|
||||
result += addConstMem(loopvarDtIr, null, loopvarSymbol, step, iterable.position)
|
||||
val chunk2 = IRCodeChunk(null, forLoop.position, null)
|
||||
chunk2 += IRInstruction(Opcode.LOADM, loopvarDt, reg1 = indexReg, labelSymbol = loopvarSymbol)
|
||||
chunk2 += IRInstruction(Opcode.LOADM, loopvarDtIr, reg1 = indexReg, labelSymbol = loopvarSymbol)
|
||||
chunk2 += if(rangeEndWrapped==0) {
|
||||
IRInstruction(Opcode.BNZ, loopvarDt, reg1 = indexReg, labelSymbol = loopLabel)
|
||||
IRInstruction(Opcode.BNZ, loopvarDtIr, reg1 = indexReg, labelSymbol = loopLabel)
|
||||
} else {
|
||||
IRInstruction(Opcode.BNE, loopvarDt, reg1 = indexReg, reg2 = endvalueReg, labelSymbol = loopLabel)
|
||||
IRInstruction(Opcode.BNE, loopvarDtIr, reg1 = indexReg, reg2 = endvalueReg, labelSymbol = loopLabel)
|
||||
}
|
||||
result += chunk2
|
||||
return result
|
||||
|
@ -186,7 +186,7 @@ main {
|
||||
val result = compileText(target, false, src, writeAssembly = true)!!
|
||||
val virtfile = result.compilationOptions.outputDir.resolve(result.program.name + ".p8ir")
|
||||
VmRunner().runAndTestProgram(virtfile.readText()) { vm ->
|
||||
vm.stepCount shouldBe 9999 // TODO FIX
|
||||
vm.stepCount shouldBe 49
|
||||
}
|
||||
}
|
||||
})
|
@ -393,6 +393,61 @@ val OpcodesForCpuRegisters = setOf(
|
||||
Opcode.STOREZCPU
|
||||
)
|
||||
|
||||
val OpcodesWithMemoryAddressAsValue = setOf(
|
||||
Opcode.LOADM,
|
||||
Opcode.LOADX,
|
||||
Opcode.LOADIX,
|
||||
Opcode.STOREM,
|
||||
Opcode.STOREX,
|
||||
Opcode.STOREIX,
|
||||
Opcode.STOREZM,
|
||||
Opcode.STOREZX,
|
||||
Opcode.JUMP,
|
||||
Opcode.JUMPA,
|
||||
Opcode.CALL,
|
||||
Opcode.BSTCC,
|
||||
Opcode.BSTCS,
|
||||
Opcode.BSTEQ,
|
||||
Opcode.BSTNE,
|
||||
Opcode.BSTNEG,
|
||||
Opcode.BSTPOS,
|
||||
Opcode.BSTVC,
|
||||
Opcode.BSTVS,
|
||||
Opcode.BZ,
|
||||
Opcode.BNZ,
|
||||
Opcode.BEQ,
|
||||
Opcode.BNE,
|
||||
Opcode.BLT,
|
||||
Opcode.BLTS,
|
||||
Opcode.BGT,
|
||||
Opcode.BGTS,
|
||||
Opcode.BLE,
|
||||
Opcode.BLES,
|
||||
Opcode.BGE,
|
||||
Opcode.BGES,
|
||||
Opcode.INCM,
|
||||
Opcode.DECM,
|
||||
Opcode.NEGM,
|
||||
Opcode.ADDM,
|
||||
Opcode.SUBM,
|
||||
Opcode.MULM,
|
||||
Opcode.DIVM,
|
||||
Opcode.DIVSM,
|
||||
Opcode.INVM,
|
||||
Opcode.ORM,
|
||||
Opcode.XORM,
|
||||
Opcode.ANDM,
|
||||
Opcode.ASRM,
|
||||
Opcode.LSRM,
|
||||
Opcode.LSLM,
|
||||
Opcode.LSLNM,
|
||||
Opcode.LSRNM,
|
||||
Opcode.ASRNM,
|
||||
Opcode.ROLM,
|
||||
Opcode.RORM,
|
||||
Opcode.ROXLM,
|
||||
Opcode.ROXRM
|
||||
)
|
||||
|
||||
enum class IRDataType {
|
||||
BYTE,
|
||||
@ -635,7 +690,7 @@ data class IRInstruction(
|
||||
require(reg2==null || reg2 in 0..65536) {"reg2 out of bounds"}
|
||||
require(fpReg1==null || fpReg1 in 0..65536) {"fpReg1 out of bounds"}
|
||||
require(fpReg2==null || fpReg2 in 0..65536) {"fpReg2 out of bounds"}
|
||||
if(value!=null && labelSymbol==null) {
|
||||
if(value!=null && opcode !in OpcodesWithMemoryAddressAsValue) {
|
||||
when (type) {
|
||||
IRDataType.BYTE -> require(value in -128..255) {"value out of range for byte: $value"}
|
||||
IRDataType.WORD -> require(value in -32768..65535) {"value out of range for word: $value"}
|
||||
|
@ -206,7 +206,7 @@ fun parseIRCodeLine(line: String, location: Pair<IRCodeChunk, Int>?, placeholder
|
||||
throw IRParseException("invalid reg1 for $line")
|
||||
if(format.reg2==OperandDirection.UNUSED && reg2!=null)
|
||||
throw IRParseException("invalid reg2 for $line")
|
||||
if(value!=null) {
|
||||
if(value!=null && opcode !in OpcodesWithMemoryAddressAsValue) {
|
||||
when (type) {
|
||||
IRDataType.BYTE -> {
|
||||
if (value < -128 || value > 255)
|
||||
|
Loading…
Reference in New Issue
Block a user