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 { irProgram.blocks.firstOrNull()?.let {
if(it.subroutines.any { it.name=="main.start" }) { if(it.subroutines.any { it.name=="main.start" }) {
// there is a "main.start" entrypoint, jump to it // 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") write("\n")
} }
is IRCodeLabel -> { is IRCodeLabel -> {
write("_" + line.name.joinToString(".") + ":\n") write("_${line.name}:\n")
} }
else -> throw AssemblyError("invalid IR code line") 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 align = (call.args[2] as PtNumber).number.toUInt()
val label = codeGen.addMemorySlab(name, size, align, call.position) val label = codeGen.addMemorySlab(name, size, align, call.position)
val code = IRCodeChunk(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 return code
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -9,6 +9,10 @@ import prog8.code.core.Position
import java.nio.file.Path import java.nio.file.Path
/* /*
note: all symbol names are flattened so that they're a single string that is globally unique.
PROGRAM: PROGRAM:
OPTIONS (from CompilationOptions) OPTIONS (from CompilationOptions)
VARIABLES (from Symboltable) VARIABLES (from Symboltable)
@ -116,9 +120,9 @@ class IRCodeInstruction(
fpReg2: Int?=null, // 0-$ffff fpReg2: Int?=null, // 0-$ffff
value: Int?=null, // 0-$ffff value: Int?=null, // 0-$ffff
fpValue: Float?=null, fpValue: Float?=null,
labelSymbol: List<String>?=null // alternative to value labelSymbol: String?=null // alternative to value
): IRCodeLine() { ): 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 { init {
if(reg1!=null && (reg1<0 || reg1>65536)) 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") 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() class IRCodeComment(val comment: String): IRCodeLine()