diff --git a/codeGenExperimental/src/prog8/codegen/experimental/AssemblyProgram.kt b/codeGenExperimental/src/prog8/codegen/experimental/AssemblyProgram.kt index dd399e267..a0df8dae9 100644 --- a/codeGenExperimental/src/prog8/codegen/experimental/AssemblyProgram.kt +++ b/codeGenExperimental/src/prog8/codegen/experimental/AssemblyProgram.kt @@ -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") } diff --git a/codeGenExperimental/src/prog8/codegen/experimental/BuiltinFuncGen.kt b/codeGenExperimental/src/prog8/codegen/experimental/BuiltinFuncGen.kt index 841765f9e..7437299cd 100644 --- a/codeGenExperimental/src/prog8/codegen/experimental/BuiltinFuncGen.kt +++ b/codeGenExperimental/src/prog8/codegen/experimental/BuiltinFuncGen.kt @@ -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 } diff --git a/codeGenExperimental/src/prog8/codegen/experimental/CodeGen.kt b/codeGenExperimental/src/prog8/codegen/experimental/CodeGen.kt index 0e78ea342..7a6639787 100644 --- a/codeGenExperimental/src/prog8/codegen/experimental/CodeGen.kt +++ b/codeGenExperimental/src/prog8/codegen/experimental/CodeGen.kt @@ -90,6 +90,7 @@ class CodeGen(internal val program: PtProgram, val removalsAsmSubs = mutableListOf>() val renameSubs = mutableListOf>() val renameAsmSubs = mutableListOf>() + val renameLabels = mutableListOf>() 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().forEach { subsub->flattenNested(block, it, subsub)} it.children.filterIsInstance().forEach { asmsubsub->flattenNestedAsm(block, it, asmsubsub)} + it.children.filterIsInstance().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 { + internal fun createLabelName(): String { labelSequenceNumber++ - return listOf("prog8_label_gen_$labelSequenceNumber") + return "prog8_label_gen_$labelSequenceNumber" } internal fun translateBuiltinFunc(call: PtBuiltinFunctionCall, resultRegister: Int): IRCodeChunk = diff --git a/codeGenExperimental/src/prog8/codegen/experimental/ExpressionGen.kt b/codeGenExperimental/src/prog8/codegen/experimental/ExpressionGen.kt index 83f4e5a09..a3171f6a8 100644 --- a/codeGenExperimental/src/prog8/codegen/experimental/ExpressionGen.kt +++ b/codeGenExperimental/src/prog8/codegen/experimental/ExpressionGen.kt @@ -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. diff --git a/examples/test.p8 b/examples/test.p8 index 5130067d8..41f20e669 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -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 diff --git a/intermediate/src/prog8/intermediate/IRFileReader.kt b/intermediate/src/prog8/intermediate/IRFileReader.kt index ee6a9919b..da8414bc5 100644 --- a/intermediate/src/prog8/intermediate/IRFileReader.kt +++ b/intermediate/src/prog8/intermediate/IRFileReader.kt @@ -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? = 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) diff --git a/intermediate/src/prog8/intermediate/IRFileWriter.kt b/intermediate/src/prog8/intermediate/IRFileWriter.kt index 037223ae2..3fee3ca10 100644 --- a/intermediate/src/prog8/intermediate/IRFileWriter.kt +++ b/intermediate/src/prog8/intermediate/IRFileWriter.kt @@ -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) diff --git a/intermediate/src/prog8/intermediate/IRPeepholeOptimizer.kt b/intermediate/src/prog8/intermediate/IRPeepholeOptimizer.kt index f3cb6dbde..08c9cd120 100644 --- a/intermediate/src/prog8/intermediate/IRPeepholeOptimizer.kt +++ b/intermediate/src/prog8/intermediate/IRPeepholeOptimizer.kt @@ -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 } diff --git a/intermediate/src/prog8/intermediate/IRProgram.kt b/intermediate/src/prog8/intermediate/IRProgram.kt index 1a4e3132e..1786a387d 100644 --- a/intermediate/src/prog8/intermediate/IRProgram.kt +++ b/intermediate/src/prog8/intermediate/IRProgram.kt @@ -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?=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): IRCodeLine() +class IRCodeLabel(val name: String): IRCodeLine() class IRCodeComment(val comment: String): IRCodeLine()