mirror of
https://github.com/irmen/prog8.git
synced 2025-01-11 13:29:45 +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
|
package prog8.codegen.intermediate
|
||||||
|
|
||||||
import prog8.code.StMemVar
|
import prog8.code.StMemVar
|
||||||
|
import prog8.code.StNode
|
||||||
import prog8.code.StStaticVariable
|
import prog8.code.StStaticVariable
|
||||||
import prog8.code.SymbolTable
|
import prog8.code.SymbolTable
|
||||||
import prog8.code.ast.*
|
import prog8.code.ast.*
|
||||||
@ -411,7 +412,7 @@ class IRCodeGen(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun translate(forLoop: PtForLoop): IRCodeChunks {
|
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 iterable = forLoop.iterable
|
||||||
val result = mutableListOf<IRCodeChunkBase>()
|
val result = mutableListOf<IRCodeChunkBase>()
|
||||||
when(iterable) {
|
when(iterable) {
|
||||||
@ -480,7 +481,7 @@ class IRCodeGen(
|
|||||||
return result
|
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 iterable = forLoop.iterable as PtRange
|
||||||
val step = iterable.step.number.toInt()
|
val step = iterable.step.number.toInt()
|
||||||
if (step==0)
|
if (step==0)
|
||||||
@ -488,26 +489,36 @@ class IRCodeGen(
|
|||||||
val indexReg = registers.nextFree()
|
val indexReg = registers.nextFree()
|
||||||
val endvalueReg = registers.nextFree()
|
val endvalueReg = registers.nextFree()
|
||||||
val loopvarSymbol = loopvar.scopedName.joinToString(".")
|
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 loopLabel = createLabelName()
|
||||||
val result = mutableListOf<IRCodeChunkBase>()
|
val result = mutableListOf<IRCodeChunkBase>()
|
||||||
|
|
||||||
result += expressionEval.translateExpression(iterable.to, endvalueReg, -1)
|
result += expressionEval.translateExpression(iterable.to, endvalueReg, -1)
|
||||||
result += expressionEval.translateExpression(iterable.from, indexReg, -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 += labelFirstChunk(translateNode(forLoop.statements), loopLabel)
|
||||||
result += addConstMem(loopvarDt, null, loopvarSymbol, step, iterable.position)
|
result += addConstMem(loopvarDtIr, null, loopvarSymbol, step, iterable.position)
|
||||||
addInstr(result, IRInstruction(Opcode.LOADM, loopvarDt, reg1 = indexReg, labelSymbol = loopvarSymbol), null, forLoop.position)
|
addInstr(result, IRInstruction(Opcode.LOADM, loopvarDtIr, reg1 = indexReg, labelSymbol = loopvarSymbol), null, forLoop.position)
|
||||||
val branchOpcode = if(loopvar.dt in SignedDatatypes) Opcode.BLES else Opcode.BLE
|
val branchOpcode = if(loopvarDt in SignedDatatypes) Opcode.BLES else Opcode.BLE
|
||||||
addInstr(result, IRInstruction(branchOpcode, loopvarDt, reg1=indexReg, reg2=endvalueReg, labelSymbol=loopLabel), null, forLoop.position)
|
addInstr(result, IRInstruction(branchOpcode, loopvarDtIr, reg1=indexReg, reg2=endvalueReg, labelSymbol=loopLabel), null, forLoop.position)
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun translateForInConstantRange(forLoop: PtForLoop, loopvar: StStaticVariable): IRCodeChunks {
|
private fun translateForInConstantRange(forLoop: PtForLoop, loopvar: StNode): IRCodeChunks {
|
||||||
val loopLabel = createLabelName()
|
val loopLabel = createLabelName()
|
||||||
val loopvarSymbol = loopvar.scopedName.joinToString(".")
|
val loopvarSymbol = loopvar.scopedName.joinToString(".")
|
||||||
val indexReg = registers.nextFree()
|
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 iterable = forLoop.iterable as PtRange
|
||||||
val step = iterable.step.number.toInt()
|
val step = iterable.step.number.toInt()
|
||||||
val rangeStart = (iterable.from as PtNumber).number.toInt()
|
val rangeStart = (iterable.from as PtNumber).number.toInt()
|
||||||
@ -516,27 +527,27 @@ class IRCodeGen(
|
|||||||
throw AssemblyError("step 0")
|
throw AssemblyError("step 0")
|
||||||
if(step>0 && rangeEndUntyped<rangeStart || step<0 && rangeEndUntyped>rangeStart)
|
if(step>0 && rangeEndUntyped<rangeStart || step<0 && rangeEndUntyped>rangeStart)
|
||||||
throw AssemblyError("empty range")
|
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 endvalueReg: Int
|
||||||
val result = mutableListOf<IRCodeChunkBase>()
|
val result = mutableListOf<IRCodeChunkBase>()
|
||||||
val chunk = IRCodeChunk(null, forLoop.position, null)
|
val chunk = IRCodeChunk(null, forLoop.position, null)
|
||||||
if(rangeEndWrapped!=0) {
|
if(rangeEndWrapped!=0) {
|
||||||
endvalueReg = registers.nextFree()
|
endvalueReg = registers.nextFree()
|
||||||
chunk += IRInstruction(Opcode.LOAD, loopvarDt, reg1 = endvalueReg, value = rangeEndWrapped)
|
chunk += IRInstruction(Opcode.LOAD, loopvarDtIr, reg1 = endvalueReg, value = rangeEndWrapped)
|
||||||
} else {
|
} else {
|
||||||
endvalueReg = -1 // not used
|
endvalueReg = -1 // not used
|
||||||
}
|
}
|
||||||
chunk += IRInstruction(Opcode.LOAD, loopvarDt, reg1=indexReg, value=rangeStart)
|
chunk += IRInstruction(Opcode.LOAD, loopvarDtIr, reg1=indexReg, value=rangeStart)
|
||||||
chunk += IRInstruction(Opcode.STOREM, loopvarDt, reg1=indexReg, labelSymbol=loopvarSymbol)
|
chunk += IRInstruction(Opcode.STOREM, loopvarDtIr, reg1=indexReg, labelSymbol=loopvarSymbol)
|
||||||
result += chunk
|
result += chunk
|
||||||
result += labelFirstChunk(translateNode(forLoop.statements), loopLabel)
|
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)
|
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) {
|
chunk2 += if(rangeEndWrapped==0) {
|
||||||
IRInstruction(Opcode.BNZ, loopvarDt, reg1 = indexReg, labelSymbol = loopLabel)
|
IRInstruction(Opcode.BNZ, loopvarDtIr, reg1 = indexReg, labelSymbol = loopLabel)
|
||||||
} else {
|
} else {
|
||||||
IRInstruction(Opcode.BNE, loopvarDt, reg1 = indexReg, reg2 = endvalueReg, labelSymbol = loopLabel)
|
IRInstruction(Opcode.BNE, loopvarDtIr, reg1 = indexReg, reg2 = endvalueReg, labelSymbol = loopLabel)
|
||||||
}
|
}
|
||||||
result += chunk2
|
result += chunk2
|
||||||
return result
|
return result
|
||||||
|
@ -186,7 +186,7 @@ main {
|
|||||||
val result = compileText(target, false, src, writeAssembly = true)!!
|
val result = compileText(target, false, src, writeAssembly = true)!!
|
||||||
val virtfile = result.compilationOptions.outputDir.resolve(result.program.name + ".p8ir")
|
val virtfile = result.compilationOptions.outputDir.resolve(result.program.name + ".p8ir")
|
||||||
VmRunner().runAndTestProgram(virtfile.readText()) { vm ->
|
VmRunner().runAndTestProgram(virtfile.readText()) { vm ->
|
||||||
vm.stepCount shouldBe 9999 // TODO FIX
|
vm.stepCount shouldBe 49
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
@ -393,6 +393,61 @@ val OpcodesForCpuRegisters = setOf(
|
|||||||
Opcode.STOREZCPU
|
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 {
|
enum class IRDataType {
|
||||||
BYTE,
|
BYTE,
|
||||||
@ -635,7 +690,7 @@ data class IRInstruction(
|
|||||||
require(reg2==null || reg2 in 0..65536) {"reg2 out of bounds"}
|
require(reg2==null || reg2 in 0..65536) {"reg2 out of bounds"}
|
||||||
require(fpReg1==null || fpReg1 in 0..65536) {"fpReg1 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"}
|
require(fpReg2==null || fpReg2 in 0..65536) {"fpReg2 out of bounds"}
|
||||||
if(value!=null && labelSymbol==null) {
|
if(value!=null && opcode !in OpcodesWithMemoryAddressAsValue) {
|
||||||
when (type) {
|
when (type) {
|
||||||
IRDataType.BYTE -> require(value in -128..255) {"value out of range for byte: $value"}
|
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"}
|
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")
|
throw IRParseException("invalid reg1 for $line")
|
||||||
if(format.reg2==OperandDirection.UNUSED && reg2!=null)
|
if(format.reg2==OperandDirection.UNUSED && reg2!=null)
|
||||||
throw IRParseException("invalid reg2 for $line")
|
throw IRParseException("invalid reg2 for $line")
|
||||||
if(value!=null) {
|
if(value!=null && opcode !in OpcodesWithMemoryAddressAsValue) {
|
||||||
when (type) {
|
when (type) {
|
||||||
IRDataType.BYTE -> {
|
IRDataType.BYTE -> {
|
||||||
if (value < -128 || value > 255)
|
if (value < -128 || value > 255)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user