properly flatten label names for the IR code

This commit is contained in:
Irmen de Jong 2022-09-08 21:52:26 +02:00
parent 502a665ffc
commit 0744c9fa29
9 changed files with 40 additions and 24 deletions

View File

@ -48,7 +48,7 @@ class AssemblyProgram(override val name: String, val irProgram: IRProgram): IAss
irProgram.blocks.firstOrNull()?.let {
if(it.subroutines.any { it.name=="main.start" }) {
// there is a "main.start" entrypoint, jump to it
out.writeLine(IRCodeInstruction(Opcode.JUMP, labelSymbol = listOf("main.start")))
out.writeLine(IRCodeInstruction(Opcode.JUMP, labelSymbol = "main.start"))
}
}
@ -96,7 +96,7 @@ private fun BufferedWriter.writeLine(line: IRCodeLine) {
write("\n")
}
is IRCodeLabel -> {
write("_" + line.name.joinToString(".") + ":\n")
write("_${line.name}:\n")
}
else -> throw AssemblyError("invalid IR code line")
}

View File

@ -328,7 +328,7 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
val align = (call.args[2] as PtNumber).number.toUInt()
val label = codeGen.addMemorySlab(name, size, align, call.position)
val code = IRCodeChunk(call.position)
code += IRCodeInstruction(Opcode.LOAD, VmDataType.WORD, reg1=resultRegister, labelSymbol = listOf(label))
code += IRCodeInstruction(Opcode.LOAD, VmDataType.WORD, reg1=resultRegister, labelSymbol = label)
return code
}

View File

@ -90,6 +90,7 @@ class CodeGen(internal val program: PtProgram,
val removalsAsmSubs = mutableListOf<Pair<PtSub, PtAsmSub>>()
val renameSubs = mutableListOf<Pair<PtBlock, PtSub>>()
val renameAsmSubs = mutableListOf<Pair<PtBlock, PtAsmSub>>()
val renameLabels = mutableListOf<Pair<PtNode, PtLabel>>()
val entrypoint = program.entrypoint()
fun flattenNestedAsm(block: PtBlock, parentSub: PtSub, asmsub: PtAsmSub) {
@ -125,13 +126,22 @@ class CodeGen(internal val program: PtProgram,
// Only regular subroutines can have nested subroutines.
it.children.filterIsInstance<PtSub>().forEach { subsub->flattenNested(block, it, subsub)}
it.children.filterIsInstance<PtAsmSub>().forEach { asmsubsub->flattenNestedAsm(block, it, asmsubsub)}
it.children.filterIsInstance<PtLabel>().forEach { label->renameLabels.add(Pair(it, label))}
renameSubs += Pair(block, it)
}
if(it is PtAsmSub)
renameAsmSubs += Pair(block, it)
if(it is PtLabel)
renameLabels += Pair(block, it)
}
}
renameLabels.forEach { (parent, label) ->
val renamedLabel = PtLabel(label.scopedName.joinToString("."), label.position)
val idx = parent.children.indexOf(label)
parent.children.removeAt(idx)
parent.children.add(idx, renamedLabel)
}
removalsSubs.forEach { (parent, sub) -> parent.children.remove(sub) }
removalsAsmSubs.forEach { (parent, asmsub) -> parent.children.remove(asmsub) }
flattenedSubs.forEach { (block, sub) -> block.add(sub) }
@ -182,7 +192,7 @@ class CodeGen(internal val program: PtProgram,
is PtRepeatLoop -> translate(node)
is PtLabel -> {
val chunk = IRCodeChunk(node.position)
chunk += IRCodeLabel(node.scopedName)
chunk += IRCodeLabel(node.name)
return chunk
}
is PtBreakpoint -> {
@ -302,7 +312,7 @@ class CodeGen(internal val program: PtProgram,
is PtIdentifier -> {
val arrayAddress = addressOf(iterable.targetName)
val iterableVar = symbolTable.lookup(iterable.targetName) as StStaticVariable
val loopvarAddress = addressOf(loopvar.scopedName)
val loopvarAddress = addressOf(loopvar.scopedName) // TODO name?
val indexReg = vmRegisters.nextFree()
val tmpReg = vmRegisters.nextFree()
val loopLabel = createLabelName()
@ -363,7 +373,7 @@ class CodeGen(internal val program: PtProgram,
throw AssemblyError("step 0")
val indexReg = vmRegisters.nextFree()
val endvalueReg = vmRegisters.nextFree()
val loopvarAddress = addressOf(loopvar.scopedName)
val loopvarAddress = addressOf(loopvar.scopedName) // TODO name?
val loopvarDt = vmType(loopvar.dt)
val loopLabel = createLabelName()
val code = IRCodeChunk(forLoop.position)
@ -382,7 +392,7 @@ class CodeGen(internal val program: PtProgram,
private fun translateForInConstantRange(forLoop: PtForLoop, loopvar: StStaticVariable): IRCodeChunk {
val loopLabel = createLabelName()
val loopvarAddress = addressOf(loopvar.scopedName)
val loopvarAddress = addressOf(loopvar.scopedName) // TODO name?
val indexReg = vmRegisters.nextFree()
val loopvarDt = vmType(loopvar.dt)
val iterable = forLoop.iterable as PtRange
@ -820,9 +830,9 @@ class CodeGen(internal val program: PtProgram,
if(jump.address!=null)
throw AssemblyError("cannot jump to memory location in the vm target")
code += if(jump.generatedLabel!=null)
IRCodeInstruction(Opcode.JUMP, labelSymbol = listOf(jump.generatedLabel!!))
IRCodeInstruction(Opcode.JUMP, labelSymbol = jump.generatedLabel!!)
else if(jump.identifier!=null)
IRCodeInstruction(Opcode.JUMP, labelSymbol = jump.identifier!!.targetName)
IRCodeInstruction(Opcode.JUMP, labelSymbol = jump.identifier!!.targetName.joinToString("."))
else
throw AssemblyError("weird jump")
return code
@ -892,9 +902,9 @@ class CodeGen(internal val program: PtProgram,
}
private var labelSequenceNumber = 0
internal fun createLabelName(): List<String> {
internal fun createLabelName(): String {
labelSequenceNumber++
return listOf("prog8_label_gen_$labelSequenceNumber")
return "prog8_label_gen_$labelSequenceNumber"
}
internal fun translateBuiltinFunc(call: PtBuiltinFunctionCall, resultRegister: Int): IRCodeChunk =

View File

@ -839,7 +839,7 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
}
}
}
code += IRCodeInstruction(Opcode.CALL, labelSymbol=fcall.functionName)
code += IRCodeInstruction(Opcode.CALL, labelSymbol=fcall.functionName.joinToString("."))
if(fcall.type==DataType.FLOAT) {
if (!fcall.void && resultFpRegister != 0) {
// Call convention: result value is in fr0, so put it in the required register instead.

View File

@ -21,8 +21,10 @@ main {
sub start() {
sys.wait(1)
a_label:
%asm {{
nop
jump a_label
}}
; TODO add proper memory SLAB support to IR+VM

View File

@ -335,7 +335,7 @@ class IRFileReader(outputDir: Path, programName: String) {
if(match==null) {
// it's a label.
val labelmatch = labelPattern.matchEntire(line.trim()) ?: throw IRParseException("invalid label")
return IRCodeLabel(labelmatch.groupValues[1].split('.'))
return IRCodeLabel(labelmatch.groupValues[1])
}
// it's an instruction.
@ -370,7 +370,7 @@ class IRFileReader(outputDir: Path, programName: String) {
var fpReg3: Int? = null
var value: Float? = null
var operand: String?
var labelSymbol: List<String>? = null
var labelSymbol: String? = null
if(operands.isNotEmpty() && operands[0].isNotEmpty()) {
operand = operands.removeFirst().trim()
if(operand[0]=='r')
@ -380,7 +380,7 @@ class IRFileReader(outputDir: Path, programName: String) {
else {
if(operand.startsWith('_')) {
// it's a label.
labelSymbol = rest.split(",")[0].trim().substring(1).split('.') // keep the original case
labelSymbol = rest.split(",")[0].trim().substring(1) // keep the original case
value = null
} else {
value = parseValue(operand)
@ -396,7 +396,7 @@ class IRFileReader(outputDir: Path, programName: String) {
else {
if(operand.startsWith('_')) {
// it's a label.
labelSymbol = rest.split(",")[1].trim().substring(1).split('.') // keep the original case
labelSymbol = rest.split(",")[1].trim().substring(1) // keep the original case
value = null
} else {
value = parseValue(operand)
@ -412,7 +412,7 @@ class IRFileReader(outputDir: Path, programName: String) {
else {
if(operand.startsWith('_')) {
// it's a label.
labelSymbol = rest.split(",")[2].trim().substring(1).split('.') // keep the original case
labelSymbol = rest.split(",")[2].trim().substring(1) // keep the original case
value = null
} else {
value = parseValue(operand)
@ -423,7 +423,7 @@ class IRFileReader(outputDir: Path, programName: String) {
operand = operands.removeFirst().trim()
if(operand.startsWith('_')) {
// it's a label.
labelSymbol = rest.split(",")[3].trim().substring(1).split('.') // keep the original case
labelSymbol = rest.split(",")[3].trim().substring(1) // keep the original case
value = null
} else {
value = parseValue(operand)

View File

@ -169,7 +169,7 @@ class IRFileWriter(private val irProgram: IRProgram) {
is IRCodeInstruction -> {
write(line.ins.toString() + "\n")
}
is IRCodeLabel -> write("_" + line.name.joinToString(".") + ":\n")
is IRCodeLabel -> write("_${line.name}:\n")
is IRCodeInlineBinary -> {
write("incbin \"${line.file}\"")
if(line.offset!=null)

View File

@ -81,7 +81,7 @@ class IRPeepholeOptimizer(private val vmprog: IRProgram) {
// if jumping to label immediately following this
if(idx < chunk.lines.size-1) {
val label = chunk.lines[idx+1] as? IRCodeLabel
if(label?.name == ins.labelSymbol) {
if(ins.labelSymbol.size==1 && label?.name == ins.labelSymbol[0]) {
chunk.lines.removeAt(idx)
changed = true
}

View File

@ -9,6 +9,10 @@ import prog8.code.core.Position
import java.nio.file.Path
/*
note: all symbol names are flattened so that they're a single string that is globally unique.
PROGRAM:
OPTIONS (from CompilationOptions)
VARIABLES (from Symboltable)
@ -116,9 +120,9 @@ class IRCodeInstruction(
fpReg2: Int?=null, // 0-$ffff
value: Int?=null, // 0-$ffff
fpValue: Float?=null,
labelSymbol: List<String>?=null // alternative to value
labelSymbol: String?=null // alternative to value
): IRCodeLine() {
val ins = Instruction(opcode, type, reg1, reg2, fpReg1, fpReg2, value, fpValue, labelSymbol)
val ins = Instruction(opcode, type, reg1, reg2, fpReg1, fpReg2, value, fpValue, if(labelSymbol==null) null else listOf(labelSymbol))
init {
if(reg1!=null && (reg1<0 || reg1>65536))
@ -144,13 +148,13 @@ class IRCodeInstruction(
}
}
if(labelSymbol?.first()?.startsWith('_')==true) {
if(labelSymbol?.startsWith('_')==true) {
throw IllegalArgumentException("label/symbol should not start with underscore $labelSymbol")
}
}
}
class IRCodeLabel(val name: List<String>): IRCodeLine()
class IRCodeLabel(val name: String): IRCodeLine()
class IRCodeComment(val comment: String): IRCodeLine()