fixing label names

This commit is contained in:
Irmen de Jong 2019-03-29 02:13:28 +01:00
parent 5502a3e3ee
commit 25e3b599e7
4 changed files with 80 additions and 57 deletions

View File

@ -326,8 +326,10 @@ inline fun <reified T> findParentNode(node: Node): T? {
interface IStatement : Node { interface IStatement : Node {
fun process(processor: IAstProcessor) : IStatement fun process(processor: IAstProcessor) : IStatement
fun makeScopedName(name: String): String { fun makeScopedName(name: String): String {
// TODO eventually get rid of this scopedName // easy way out is to always return the full scoped name.
// this is usually cached in a lazy property on the statement object itself (label, subroutine, vardecl) // it would be nicer to find only the minimal prefixed scoped name, but that's too much hassle for now.
// and like this, we can cache the name even,
// like in a lazy property on the statement object itself (label, subroutine, vardecl)
val scope = mutableListOf<String>() val scope = mutableListOf<String>()
var statementScope = this.parent var statementScope = this.parent
while(statementScope !is ParentSentinel && statementScope !is Module) { while(statementScope !is ParentSentinel && statementScope !is Module) {
@ -336,7 +338,8 @@ interface IStatement : Node {
} }
statementScope = statementScope.parent statementScope = statementScope.parent
} }
scope.add(name) if(name.isNotEmpty())
scope.add(name)
return scope.joinToString(".") return scope.joinToString(".")
} }
} }
@ -547,7 +550,6 @@ data class DirectiveArg(val str: String?, val name: String?, val int: Int?, over
data class Label(val name: String, override val position: Position) : IStatement { data class Label(val name: String, override val position: Position) : IStatement {
override lateinit var parent: Node override lateinit var parent: Node
val scopedname: String by lazy { makeScopedName(name) }
override fun linkParents(parent: Node) { override fun linkParents(parent: Node) {
this.parent = parent this.parent = parent
@ -558,6 +560,8 @@ data class Label(val name: String, override val position: Position) : IStatement
override fun toString(): String { override fun toString(): String {
return "Label(name=$name, pos=$position)" return "Label(name=$name, pos=$position)"
} }
val scopedname: String by lazy { makeScopedName(name) }
} }

View File

@ -159,7 +159,6 @@ internal class Compiler(private val rootModule: Module,
override fun process(block: Block): IStatement { override fun process(block: Block): IStatement {
prog.newBlock(block.name, block.address, block.options()) prog.newBlock(block.name, block.address, block.options())
processVariables(block) processVariables(block)
prog.label("block."+block.name, false)
prog.line(block.position) prog.line(block.position)
translate(block.statements) translate(block.statements)
return super.process(block) return super.process(block)
@ -461,8 +460,8 @@ internal class Compiler(private val rootModule: Module,
} }
} else { } else {
// regular if..else branching // regular if..else branching
val labelElse = makeLabel("else") val labelElse = makeLabel(branch, "else")
val labelEnd = makeLabel("end") val labelEnd = makeLabel(branch, "end")
val opcode = branchOpcode(branch, true) val opcode = branchOpcode(branch, true)
if (branch.elsepart.isEmpty()) { if (branch.elsepart.isEmpty()) {
prog.instr(opcode, callLabel = labelEnd) prog.instr(opcode, callLabel = labelEnd)
@ -480,9 +479,9 @@ internal class Compiler(private val rootModule: Module,
} }
} }
private fun makeLabel(postfix: String): String { private fun makeLabel(scopeStmt: IStatement, postfix: String): String {
generatedLabelSequenceNumber++ generatedLabelSequenceNumber++
return "_prog8stmt_${generatedLabelSequenceNumber}_$postfix" return "${scopeStmt.makeScopedName("")}.<s-$generatedLabelSequenceNumber-$postfix>"
} }
private fun translate(stmt: IfStatement) { private fun translate(stmt: IfStatement) {
@ -528,13 +527,13 @@ internal class Compiler(private val rootModule: Module,
in WordDatatypes -> Opcode.JZW in WordDatatypes -> Opcode.JZW
else -> throw CompilerException("invalid condition datatype (expected byte or word) $stmt") else -> throw CompilerException("invalid condition datatype (expected byte or word) $stmt")
} }
val labelEnd = makeLabel("end") val labelEnd = makeLabel(stmt, "end")
if(stmt.elsepart.isEmpty()) { if(stmt.elsepart.isEmpty()) {
prog.instr(conditionJumpOpcode, callLabel = labelEnd) prog.instr(conditionJumpOpcode, callLabel = labelEnd)
translate(stmt.truepart) translate(stmt.truepart)
prog.label(labelEnd) prog.label(labelEnd)
} else { } else {
val labelElse = makeLabel("else") val labelElse = makeLabel(stmt, "else")
prog.instr(conditionJumpOpcode, callLabel = labelElse) prog.instr(conditionJumpOpcode, callLabel = labelElse)
translate(stmt.truepart) translate(stmt.truepart)
prog.instr(Opcode.JUMP, callLabel = labelEnd) prog.instr(Opcode.JUMP, callLabel = labelEnd)
@ -1764,9 +1763,9 @@ internal class Compiler(private val rootModule: Module,
* break: * break:
* nop * nop
*/ */
val loopLabel = makeLabel("loop") val loopLabel = makeLabel(loop, "loop")
val continueLabel = makeLabel("continue") val continueLabel = makeLabel(loop, "continue")
val breakLabel = makeLabel("break") val breakLabel = makeLabel(loop, "break")
val indexVarType = if (numElements <= 255) DataType.UBYTE else DataType.UWORD val indexVarType = if (numElements <= 255) DataType.UBYTE else DataType.UWORD
val indexVar = loop.body.getLabelOrVariable(ForLoop.iteratorLoopcounterVarname) as VarDecl val indexVar = loop.body.getLabelOrVariable(ForLoop.iteratorLoopcounterVarname) as VarDecl
@ -1825,9 +1824,9 @@ internal class Compiler(private val rootModule: Module,
* break: * break:
* nop * nop
*/ */
val loopLabel = makeLabel("loop") val loopLabel = makeLabel(body, "loop")
val continueLabel = makeLabel("continue") val continueLabel = makeLabel(body, "continue")
val breakLabel = makeLabel("break") val breakLabel = makeLabel(body, "break")
continueStmtLabelStack.push(continueLabel) continueStmtLabelStack.push(continueLabel)
breakStmtLabelStack.push(breakLabel) breakStmtLabelStack.push(breakLabel)
@ -1930,9 +1929,9 @@ internal class Compiler(private val rootModule: Module,
startAssignment.linkParents(body) startAssignment.linkParents(body)
translate(startAssignment) translate(startAssignment)
val loopLabel = makeLabel("loop") val loopLabel = makeLabel(body, "loop")
val continueLabel = makeLabel("continue") val continueLabel = makeLabel(body, "continue")
val breakLabel = makeLabel("break") val breakLabel = makeLabel(body, "break")
val literalStepValue = (range.step as? LiteralValue)?.asNumericValue?.toInt() val literalStepValue = (range.step as? LiteralValue)?.asNumericValue?.toInt()
continueStmtLabelStack.push(continueLabel) continueStmtLabelStack.push(continueLabel)
@ -2034,9 +2033,9 @@ internal class Compiler(private val rootModule: Module,
* break: * break:
* nop * nop
*/ */
val loopLabel = makeLabel("loop") val loopLabel = makeLabel(stmt, "loop")
val breakLabel = makeLabel("break") val breakLabel = makeLabel(stmt, "break")
val continueLabel = makeLabel("continue") val continueLabel = makeLabel(stmt, "continue")
prog.line(stmt.position) prog.line(stmt.position)
breakStmtLabelStack.push(breakLabel) breakStmtLabelStack.push(breakLabel)
continueStmtLabelStack.push(continueLabel) continueStmtLabelStack.push(continueLabel)
@ -2072,9 +2071,9 @@ internal class Compiler(private val rootModule: Module,
* break: * break:
* nop * nop
*/ */
val loopLabel = makeLabel("loop") val loopLabel = makeLabel(stmt, "loop")
val continueLabel = makeLabel("continue") val continueLabel = makeLabel(stmt, "continue")
val breakLabel = makeLabel("break") val breakLabel = makeLabel(stmt, "break")
prog.line(stmt.position) prog.line(stmt.position)
breakStmtLabelStack.push(breakLabel) breakStmtLabelStack.push(breakLabel)
continueStmtLabelStack.push(continueLabel) continueStmtLabelStack.push(continueLabel)

View File

@ -26,7 +26,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
// Because 64tass understands scoped names via .proc / .block, // Because 64tass understands scoped names via .proc / .block,
// we'll strip the block prefix from all scoped names in the program. // we'll strip the block prefix from all scoped names in the program.
// Also, convert invalid label names (such as "<anon-1>") to something that's allowed. // Also, convert invalid label names (such as "<anon-1>") to something that's allowed.
// Also have to do that for the variablesMarkedForZeropage! // Also have to do that for the variablesMarkedForZeropage! TODO is this true?
val newblocks = mutableListOf<IntermediateProgram.ProgramBlock>() val newblocks = mutableListOf<IntermediateProgram.ProgramBlock>()
for(block in program.blocks) { for(block in program.blocks) {
val newvars = block.variables.map { symname(it.key, block) to it.value }.toMap().toMutableMap() val newvars = block.variables.map { symname(it.key, block) to it.value }.toMap().toMutableMap()
@ -58,9 +58,10 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
program.blocks.clear() program.blocks.clear()
program.blocks.addAll(newblocks) program.blocks.addAll(newblocks)
val newAllocatedZp = program.allocatedZeropageVariables.map { symname(it.key, null) to it.value} // TODO is this still needed?????
program.allocatedZeropageVariables.clear() // val newAllocatedZp = program.allocatedZeropageVariables.map { symname(it.key, null) to it.value}
program.allocatedZeropageVariables.putAll(newAllocatedZp) // program.allocatedZeropageVariables.clear()
// program.allocatedZeropageVariables.putAll(newAllocatedZp)
// make a list of all const floats that are used // make a list of all const floats that are used
for(block in program.blocks) { for(block in program.blocks) {
@ -105,27 +106,18 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
} }
private fun symname(scoped: String, block: IntermediateProgram.ProgramBlock?): String { // convert a fully scoped name (defined in the given block) to a valid assembly symbol name
private fun symname(scoped: String, block: IntermediateProgram.ProgramBlock): String {
if(' ' in scoped) if(' ' in scoped)
return scoped return scoped
val blockLocal: Boolean val blockLocal: Boolean
var name = when { var name = if (scoped.startsWith("${block.name}.")) {
block==null -> { blockLocal = true
blockLocal=true scoped.substring(block.name.length+1)
scoped }
} else {
scoped.startsWith("${block.name}.") -> { // TODO DOES THIS EVER OCCUR? blockLocal = false
blockLocal = true scoped
scoped.substring(block.name.length+1)
}
scoped.startsWith("block.") -> {
blockLocal = false
scoped
}
else -> {
blockLocal = false
scoped
}
} }
name = name.replace("<", "prog8_").replace(">", "") // take care of the autogenerated invalid (anon) label names name = name.replace("<", "prog8_").replace(">", "") // take care of the autogenerated invalid (anon) label names
if(name=="-") if(name=="-")
@ -229,9 +221,9 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
out("* = ${block.address?.toHex()}") out("* = ${block.address?.toHex()}")
} }
// deal with zeropage variables // deal with zeropage variables TODO does this still work correctly (the symname was changed a little)
for(variable in blk.variables) { for(variable in blk.variables) {
val sym = symname(blk.name+"."+variable.key, null) val sym = symname(blk.name+"."+variable.key, blk)
val zpVar = program.allocatedZeropageVariables[sym] val zpVar = program.allocatedZeropageVariables[sym]
if(zpVar==null) { if(zpVar==null) {
// This var is not on the ZP yet. Attempt to move it there (if it's not a float, those take up too much space) // This var is not on the ZP yet. Attempt to move it there (if it's not a float, those take up too much space)
@ -426,9 +418,6 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
private fun simpleInstr2Asm(ins: Instruction): String? { private fun simpleInstr2Asm(ins: Instruction): String? {
// a label 'instruction' is simply translated into a asm label // a label 'instruction' is simply translated into a asm label
if(ins is LabelInstr) { if(ins is LabelInstr) {
if(ins.name.startsWith("block."))
return ""
val labelresult = val labelresult =
if(ins.name.startsWith("${block.name}.")) if(ins.name.startsWith("${block.name}."))
ins.name.substring(block.name.length+1) ins.name.substring(block.name.length+1)

View File

@ -2,29 +2,59 @@
; @todo fix this loop labeling problem (issue #11 on github): it generates invalid asm due to improper label names ; @todo fix this loop labeling problem (issue #11 on github): it generates invalid asm due to improper label names
~ main { ~ main {
label2:
sub start() { sub start() {
byte var1 label3:
byte var1 byte var1
label4:
sub subsub() { sub subsub() {
byte var1
label3:
label4:
byte var1 byte var1
} }
sub subsub() { sub subsub2() {
label3:
label4:
byte var1 byte var1
byte var2 byte var2
byte var3 byte var3
byte var2
label5ss2:
if A>10 {
label6ss2:
A=44
while true {
label7ss2:
;derp
}
} else {
gameoverss2:
goto gameoverss2
}
label8ss2:
} }
label5:
if A>10 { if A>10 {
label6:
A=44 A=44
while true { while true {
label7:
;derp ;derp
} }
} else { } else {
@ -32,6 +62,7 @@
gameover: gameover:
goto gameover goto gameover
} }
label8:
} }