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 {
|
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")
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 =
|
||||||
|
@ -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.
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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()
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user