mirror of
https://github.com/irmen/prog8.git
synced 2025-01-03 06:29:54 +00:00
properly flatten label names for the IR code
This commit is contained in:
parent
502a665ffc
commit
0744c9fa29
@ -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")
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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 =
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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()
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user