uniform symbol prefixing with p8_

This commit is contained in:
Irmen de Jong 2023-07-01 01:44:19 +02:00
parent cad18b8a3a
commit bb95484c8a
21 changed files with 260 additions and 233 deletions

View File

@ -94,6 +94,9 @@ class SymbolTableMaker(private val program: PtProgram, private val options: Comp
initialString = null initialString = null
numElements = node.arraySize?.toInt() numElements = node.arraySize?.toInt()
} }
// if(node.type in SplitWordArrayTypes) {
// TODO("split array also add _lsb and _msb to symboltable")
// }
StStaticVariable(node.name, node.type, initialNumeric, initialString, initialArray, numElements, node.zeropage, node) StStaticVariable(node.name, node.type, initialNumeric, initialString, initialArray, numElements, node.zeropage, node)
} }
is PtBuiltinFunctionCall -> { is PtBuiltinFunctionCall -> {

View File

@ -63,9 +63,9 @@ class PtProgram(
children.asSequence().filterIsInstance<PtBlock>() children.asSequence().filterIsInstance<PtBlock>()
fun entrypoint(): PtSub? = fun entrypoint(): PtSub? =
allBlocks().firstOrNull { it.name == "main" || it.name=="p8_main" } allBlocks().firstOrNull { it.name == "main" }
?.children ?.children
?.firstOrNull { it is PtSub && (it.name == "start" || it.name=="p8_start" || it.name=="main.start" || it.name=="p8_main.p8_start") } as PtSub? ?.firstOrNull { it is PtSub && (it.name == "start" || it.name=="main.start") } as PtSub?
} }
@ -73,6 +73,7 @@ class PtBlock(name: String,
val address: UInt?, val address: UInt?,
val library: Boolean, val library: Boolean,
val forceOutput: Boolean, val forceOutput: Boolean,
val noSymbolPrefixing: Boolean,
val alignment: BlockAlignment, val alignment: BlockAlignment,
val source: SourceCode, // taken from the module the block is defined in. val source: SourceCode, // taken from the module the block is defined in.
position: Position position: Position

View File

@ -3,6 +3,7 @@ package prog8.codegen.cpu6502
import com.github.michaelbull.result.fold import com.github.michaelbull.result.fold
import prog8.code.StNodeType import prog8.code.StNodeType
import prog8.code.SymbolTable import prog8.code.SymbolTable
import prog8.code.SymbolTableMaker
import prog8.code.ast.* import prog8.code.ast.*
import prog8.code.core.* import prog8.code.core.*
import prog8.codegen.cpu6502.assignment.* import prog8.codegen.cpu6502.assignment.*
@ -14,18 +15,162 @@ import kotlin.io.path.writeLines
internal const val subroutineFloatEvalResultVar1 = "prog8_float_eval_result1" internal const val subroutineFloatEvalResultVar1 = "prog8_float_eval_result1"
internal const val subroutineFloatEvalResultVar2 = "prog8_float_eval_result2" internal const val subroutineFloatEvalResultVar2 = "prog8_float_eval_result2"
class AsmGen6502: ICodeGeneratorBackend { class AsmGen6502(val prefixSymbols: Boolean): ICodeGeneratorBackend {
override fun generate( override fun generate(
program: PtProgram, program: PtProgram,
symbolTable: SymbolTable, symbolTable: SymbolTable,
options: CompilationOptions, options: CompilationOptions,
errors: IErrorReporter errors: IErrorReporter
): IAssemblyProgram? { ): IAssemblyProgram? {
val asmgen = AsmGen6502Internal(program, symbolTable, options, errors) val st = if(prefixSymbols) prefixSymbols(program, options, symbolTable) else symbolTable
val asmgen = AsmGen6502Internal(program, st, options, errors)
return asmgen.compileToAssembly() return asmgen.compileToAssembly()
} }
private fun prefixSymbols(program: PtProgram, options: CompilationOptions, st: SymbolTable): SymbolTable {
printAst(program, true, ::println)
val nodesToPrefix = mutableListOf<Pair<PtNode, Int>>()
fun prefixNamedNode(node: PtNamedNode) {
node.name = "p8_${node.name}"
}
fun prefixSymbols(node: PtNode) {
when(node) {
is PtAsmSub -> {
prefixNamedNode(node)
node.parameters.forEach { (_, param) -> prefixNamedNode(param) }
}
is PtSub -> {
prefixNamedNode(node)
node.parameters.forEach { prefixNamedNode(it) }
}
is PtFunctionCall -> {
val stNode = st.lookup(node.name)!!
if(stNode.astNode.definingBlock()?.noSymbolPrefixing!=true) {
val index = node.parent.children.indexOf(node)
nodesToPrefix += node.parent to index
}
}
is PtIdentifier -> {
var lookupName = node.name
if(node.type in SplitWordArrayTypes && (lookupName.endsWith("_lsb") || lookupName.endsWith("_msb"))) {
lookupName = lookupName.dropLast(4)
}
val stNode = st.lookup(lookupName)!!
if(stNode.astNode.definingBlock()?.noSymbolPrefixing!=true) {
val index = node.parent.children.indexOf(node)
nodesToPrefix += node.parent to index
}
}
is PtJump -> {
if(node.identifier!=null) {
val stNode = st.lookup(node.identifier!!.name)!!
if(stNode.astNode.definingBlock()?.noSymbolPrefixing!=true) {
val index = node.parent.children.indexOf(node)
nodesToPrefix += node.parent to index
}
}
else if(node.generatedLabel!=null) {
val stNode = st.lookup(node.generatedLabel!!)!!
if(stNode.astNode.definingBlock()?.noSymbolPrefixing!=true) {
val index = node.parent.children.indexOf(node)
nodesToPrefix += node.parent to index
}
}
}
is PtBlock -> prefixNamedNode(node)
is PtConstant -> prefixNamedNode(node)
is PtLabel -> prefixNamedNode(node)
is PtMemMapped -> prefixNamedNode(node)
is PtSubroutineParameter -> prefixNamedNode(node)
is PtVariable -> {
val index = node.parent.children.indexOf(node)
nodesToPrefix += node.parent to index
}
else -> { }
}
node.children.forEach { prefixSymbols(it) }
}
program.allBlocks().forEach { block ->
if (!block.noSymbolPrefixing) {
prefixSymbols(block)
}
}
nodesToPrefix.forEach { (parent, index) ->
val node = parent.children[index]
when(node) {
is PtIdentifier -> parent.children[index] = node.prefix(parent)
is PtFunctionCall -> parent.children[index] = node.prefix(parent)
is PtJump -> parent.children[index] = node.prefix(parent)
is PtVariable -> parent.children[index] = node.prefix(parent)
else -> throw AssemblyError("weird node to prefix $node")
}
}
return SymbolTableMaker(program, options).make()
}
} }
private fun PtVariable.prefix(parent: PtNode): PtVariable {
name = name.split('.').map {"p8_$it" }.joinToString(".")
if(value==null)
return this
val arrayValue = value as? PtArray
return if(arrayValue!=null && arrayValue.children.any { it !is PtNumber} ) {
val newValue = PtArray(arrayValue.type, arrayValue.position)
arrayValue.children.forEach { elt ->
when(elt) {
is PtIdentifier -> newValue.add(elt.prefix(arrayValue))
is PtNumber -> newValue.add(elt)
is PtAddressOf -> {
val newAddr = PtAddressOf(elt.position)
newAddr.children.add(elt.identifier.prefix(newAddr))
newAddr.parent = arrayValue
newValue.add(newAddr)
}
else -> throw AssemblyError("weird array value element $elt")
}
}
PtVariable(name, type, zeropage, newValue, arraySize, position)
}
else this
}
private fun PtJump.prefix(parent: PtNode): PtJump {
val jump = if(identifier!=null) {
val prefixedIdent = identifier!!.prefix(this)
PtJump(prefixedIdent, address, generatedLabel, position)
} else {
val prefixedLabel = generatedLabel!!.split('.').map {"p8_$it" }.joinToString(".")
PtJump(null, address, prefixedLabel, position)
}
jump.parent = parent
return jump
}
private fun PtFunctionCall.prefix(parent: PtNode): PtFunctionCall {
val newName = name.split('.').map {"p8_$it" }.joinToString(".")
val call = PtFunctionCall(newName, void, type, position)
call.children.addAll(children)
call.children.forEach { it.parent = call }
call.parent = parent
return call
}
private fun PtIdentifier.prefix(parent: PtNode): PtIdentifier {
val newName = name.split('.').map {"p8_$it" }.joinToString(".")
val node = PtIdentifier(newName, type, position)
node.parent = parent
return node
}
class AsmGen6502Internal ( class AsmGen6502Internal (
val program: PtProgram, val program: PtProgram,
internal val symbolTable: SymbolTable, internal val symbolTable: SymbolTable,

View File

@ -40,9 +40,9 @@ class TestCodegen: FunSpec({
// xx += cx16.r0 // xx += cx16.r0
// } // }
//} //}
val codegen = AsmGen6502() val codegen = AsmGen6502(prefixSymbols = false)
val program = PtProgram("test", DummyMemsizer, DummyStringEncoder) val program = PtProgram("test", DummyMemsizer, DummyStringEncoder)
val block = PtBlock("main", null, false, false, PtBlock.BlockAlignment.NONE, SourceCode.Generated("test"), Position.DUMMY) val block = PtBlock("main", null, false, false, false, PtBlock.BlockAlignment.NONE, SourceCode.Generated("test"), Position.DUMMY)
val sub = PtSub("start", emptyList(), null, Position.DUMMY) val sub = PtSub("start", emptyList(), null, Position.DUMMY)
sub.add(PtVariable("pi", DataType.UBYTE, ZeropageWish.DONTCARE, PtNumber(DataType.UBYTE, 0.0, Position.DUMMY), null, Position.DUMMY)) sub.add(PtVariable("pi", DataType.UBYTE, ZeropageWish.DONTCARE, PtNumber(DataType.UBYTE, 0.0, Position.DUMMY), null, Position.DUMMY))
sub.add(PtVariable("particleX", DataType.ARRAY_UB, ZeropageWish.DONTCARE, null, 3u, Position.DUMMY)) sub.add(PtVariable("particleX", DataType.ARRAY_UB, ZeropageWish.DONTCARE, null, 3u, Position.DUMMY))
@ -92,7 +92,7 @@ class TestCodegen: FunSpec({
program.add(block) program.add(block)
// define the "cx16.r0" virtual register // define the "cx16.r0" virtual register
val cx16block = PtBlock("cx16", null, false, false, PtBlock.BlockAlignment.NONE, SourceCode.Generated("test"), Position.DUMMY) val cx16block = PtBlock("cx16", null, false, false, false, PtBlock.BlockAlignment.NONE, SourceCode.Generated("test"), Position.DUMMY)
cx16block.add(PtMemMapped("r0", DataType.UWORD, 100u, null, Position.DUMMY)) cx16block.add(PtMemMapped("r0", DataType.UWORD, 100u, null, Position.DUMMY))
program.add(cx16block) program.add(cx16block)

View File

@ -135,8 +135,8 @@ class IRUnusedCodeRemover(
} }
private fun removeUnreachable(allLabeledChunks: MutableMap<String, IRCodeChunkBase>): Int { private fun removeUnreachable(allLabeledChunks: MutableMap<String, IRCodeChunkBase>): Int {
val entrypointSub = irprog.blocks.single { it.label=="main" || it.label=="p8_main" } val entrypointSub = irprog.blocks.single { it.label=="main" }
.children.single { it is IRSubroutine && (it.label=="main.start" || it.label=="p8_main.p8_start") } .children.single { it is IRSubroutine && it.label=="main.start" }
val reachable = mutableSetOf((entrypointSub as IRSubroutine).chunks.first()) val reachable = mutableSetOf((entrypointSub as IRSubroutine).chunks.first())
fun grow() { fun grow() {

View File

@ -41,7 +41,7 @@ class TestVmCodeGen: FunSpec({
//} //}
val codegen = VmCodeGen() val codegen = VmCodeGen()
val program = PtProgram("test", DummyMemsizer, DummyStringEncoder) val program = PtProgram("test", DummyMemsizer, DummyStringEncoder)
val block = PtBlock("main", null, false, false, PtBlock.BlockAlignment.NONE, SourceCode.Generated("test"), Position.DUMMY) val block = PtBlock("main", null, false, false, false, PtBlock.BlockAlignment.NONE, SourceCode.Generated("test"), Position.DUMMY)
val sub = PtSub("start", emptyList(), null, Position.DUMMY) val sub = PtSub("start", emptyList(), null, Position.DUMMY)
sub.add(PtVariable("pi", DataType.UBYTE, ZeropageWish.DONTCARE, PtNumber(DataType.UBYTE, 0.0, Position.DUMMY), null, Position.DUMMY)) sub.add(PtVariable("pi", DataType.UBYTE, ZeropageWish.DONTCARE, PtNumber(DataType.UBYTE, 0.0, Position.DUMMY), null, Position.DUMMY))
sub.add(PtVariable("particleX", DataType.ARRAY_UB, ZeropageWish.DONTCARE, null, 3u, Position.DUMMY)) sub.add(PtVariable("particleX", DataType.ARRAY_UB, ZeropageWish.DONTCARE, null, 3u, Position.DUMMY))
@ -91,7 +91,7 @@ class TestVmCodeGen: FunSpec({
program.add(block) program.add(block)
// define the "cx16.r0" virtual register // define the "cx16.r0" virtual register
val cx16block = PtBlock("cx16", null, false, false, PtBlock.BlockAlignment.NONE, SourceCode.Generated("test"), Position.DUMMY) val cx16block = PtBlock("cx16", null, false, false, false, PtBlock.BlockAlignment.NONE, SourceCode.Generated("test"), Position.DUMMY)
cx16block.add(PtMemMapped("r0", DataType.UWORD, 100u, null, Position.DUMMY)) cx16block.add(PtMemMapped("r0", DataType.UWORD, 100u, null, Position.DUMMY))
program.add(cx16block) program.add(cx16block)
@ -120,7 +120,7 @@ class TestVmCodeGen: FunSpec({
//} //}
val codegen = VmCodeGen() val codegen = VmCodeGen()
val program = PtProgram("test", DummyMemsizer, DummyStringEncoder) val program = PtProgram("test", DummyMemsizer, DummyStringEncoder)
val block = PtBlock("main", null, false, false, PtBlock.BlockAlignment.NONE, SourceCode.Generated("test"), Position.DUMMY) val block = PtBlock("main", null, false, false, false, PtBlock.BlockAlignment.NONE, SourceCode.Generated("test"), Position.DUMMY)
val sub = PtSub("start", emptyList(), null, Position.DUMMY) val sub = PtSub("start", emptyList(), null, Position.DUMMY)
sub.add(PtVariable("f1", DataType.FLOAT, ZeropageWish.DONTCARE, null, null, Position.DUMMY)) sub.add(PtVariable("f1", DataType.FLOAT, ZeropageWish.DONTCARE, null, null, Position.DUMMY))
val if1 = PtIfElse(Position.DUMMY) val if1 = PtIfElse(Position.DUMMY)
@ -183,7 +183,7 @@ class TestVmCodeGen: FunSpec({
//} //}
val codegen = VmCodeGen() val codegen = VmCodeGen()
val program = PtProgram("test", DummyMemsizer, DummyStringEncoder) val program = PtProgram("test", DummyMemsizer, DummyStringEncoder)
val block = PtBlock("main", null, false, false, PtBlock.BlockAlignment.NONE, SourceCode.Generated("test"), Position.DUMMY) val block = PtBlock("main", null, false, false, false, PtBlock.BlockAlignment.NONE, SourceCode.Generated("test"), Position.DUMMY)
val sub = PtSub("start", emptyList(), null, Position.DUMMY) val sub = PtSub("start", emptyList(), null, Position.DUMMY)
sub.add(PtVariable("f1", DataType.FLOAT, ZeropageWish.DONTCARE, null, null, Position.DUMMY)) sub.add(PtVariable("f1", DataType.FLOAT, ZeropageWish.DONTCARE, null, null, Position.DUMMY))
val if1 = PtIfElse(Position.DUMMY) val if1 = PtIfElse(Position.DUMMY)
@ -242,7 +242,7 @@ class TestVmCodeGen: FunSpec({
//} //}
val codegen = VmCodeGen() val codegen = VmCodeGen()
val program = PtProgram("test", DummyMemsizer, DummyStringEncoder) val program = PtProgram("test", DummyMemsizer, DummyStringEncoder)
val block = PtBlock("main", null, false, false, PtBlock.BlockAlignment.NONE, SourceCode.Generated("test"), Position.DUMMY) val block = PtBlock("main", null, false, false, false, PtBlock.BlockAlignment.NONE, SourceCode.Generated("test"), Position.DUMMY)
val sub = PtSub("start", emptyList(), null, Position.DUMMY) val sub = PtSub("start", emptyList(), null, Position.DUMMY)
sub.add(PtVariable("f1", DataType.FLOAT, ZeropageWish.DONTCARE, null, null, Position.DUMMY)) sub.add(PtVariable("f1", DataType.FLOAT, ZeropageWish.DONTCARE, null, null, Position.DUMMY))
val if1 = PtIfElse(Position.DUMMY) val if1 = PtIfElse(Position.DUMMY)
@ -289,7 +289,7 @@ class TestVmCodeGen: FunSpec({
//} //}
val codegen = VmCodeGen() val codegen = VmCodeGen()
val program = PtProgram("test", DummyMemsizer, DummyStringEncoder) val program = PtProgram("test", DummyMemsizer, DummyStringEncoder)
val block = PtBlock("main", null, false, false, PtBlock.BlockAlignment.NONE, SourceCode.Generated("test"), Position.DUMMY) val block = PtBlock("main", null, false, false, false, PtBlock.BlockAlignment.NONE, SourceCode.Generated("test"), Position.DUMMY)
val sub = PtSub("start", emptyList(), null, Position.DUMMY) val sub = PtSub("start", emptyList(), null, Position.DUMMY)
sub.add(PtVariable("sb1", DataType.BYTE, ZeropageWish.DONTCARE, null, null, Position.DUMMY)) sub.add(PtVariable("sb1", DataType.BYTE, ZeropageWish.DONTCARE, null, null, Position.DUMMY))
val if1 = PtIfElse(Position.DUMMY) val if1 = PtIfElse(Position.DUMMY)
@ -352,7 +352,7 @@ class TestVmCodeGen: FunSpec({
//} //}
val codegen = VmCodeGen() val codegen = VmCodeGen()
val program = PtProgram("test", DummyMemsizer, DummyStringEncoder) val program = PtProgram("test", DummyMemsizer, DummyStringEncoder)
val block = PtBlock("main", null, false, false, PtBlock.BlockAlignment.NONE, SourceCode.Generated("test"), Position.DUMMY) val block = PtBlock("main", null, false, false, false, PtBlock.BlockAlignment.NONE, SourceCode.Generated("test"), Position.DUMMY)
val sub = PtSub("start", emptyList(), null, Position.DUMMY) val sub = PtSub("start", emptyList(), null, Position.DUMMY)
sub.add(PtVariable("sb1", DataType.BYTE, ZeropageWish.DONTCARE, null, null, Position.DUMMY)) sub.add(PtVariable("sb1", DataType.BYTE, ZeropageWish.DONTCARE, null, null, Position.DUMMY))
val if1 = PtIfElse(Position.DUMMY) val if1 = PtIfElse(Position.DUMMY)
@ -411,7 +411,7 @@ class TestVmCodeGen: FunSpec({
//} //}
val codegen = VmCodeGen() val codegen = VmCodeGen()
val program = PtProgram("test", DummyMemsizer, DummyStringEncoder) val program = PtProgram("test", DummyMemsizer, DummyStringEncoder)
val block = PtBlock("main", null, false, false, PtBlock.BlockAlignment.NONE, SourceCode.Generated("test"), Position.DUMMY) val block = PtBlock("main", null, false, false, false, PtBlock.BlockAlignment.NONE, SourceCode.Generated("test"), Position.DUMMY)
val sub = PtSub("start", emptyList(), null, Position.DUMMY) val sub = PtSub("start", emptyList(), null, Position.DUMMY)
sub.add(PtVariable("ub1", DataType.UBYTE, ZeropageWish.DONTCARE, null, null, Position.DUMMY)) sub.add(PtVariable("ub1", DataType.UBYTE, ZeropageWish.DONTCARE, null, null, Position.DUMMY))
val if1 = PtIfElse(Position.DUMMY) val if1 = PtIfElse(Position.DUMMY)
@ -451,7 +451,7 @@ class TestVmCodeGen: FunSpec({
//} //}
val codegen = VmCodeGen() val codegen = VmCodeGen()
val program = PtProgram("test", DummyMemsizer, DummyStringEncoder) val program = PtProgram("test", DummyMemsizer, DummyStringEncoder)
val block = PtBlock("main", null, false, false, PtBlock.BlockAlignment.NONE, SourceCode.Generated("test"), Position.DUMMY) val block = PtBlock("main", null, false, false, false, PtBlock.BlockAlignment.NONE, SourceCode.Generated("test"), Position.DUMMY)
val romsub = PtAsmSub("routine", 0x5000u, setOf(CpuRegister.Y), emptyList(), emptyList(), false, Position.DUMMY) val romsub = PtAsmSub("routine", 0x5000u, setOf(CpuRegister.Y), emptyList(), emptyList(), false, Position.DUMMY)
block.add(romsub) block.add(romsub)
val sub = PtSub("start", emptyList(), null, Position.DUMMY) val sub = PtSub("start", emptyList(), null, Position.DUMMY)

View File

@ -6,10 +6,10 @@ package prog8.buildversion
const val MAVEN_GROUP = "prog8" const val MAVEN_GROUP = "prog8"
const val MAVEN_NAME = "compiler" const val MAVEN_NAME = "compiler"
const val VERSION = "9.1-SNAPSHOT" const val VERSION = "9.1-SNAPSHOT"
const val GIT_REVISION = 3909 const val GIT_REVISION = -1
const val GIT_SHA = "04da44eb988e4c2abef4099f86888b95074cc453" const val GIT_SHA = "bf86e1f41d9c97d3b56e91e5217bcda258fa3e09"
const val GIT_DATE = "2023-06-29T20:56:26Z" const val GIT_DATE = "UNKNOWN"
const val GIT_BRANCH = "prefixing" const val GIT_BRANCH = "prefixing"
const val BUILD_DATE = "2023-06-29T21:18:59Z" const val BUILD_DATE = "2023-06-30T23:38:56Z"
const val BUILD_UNIX_TIME = 1688073539609L const val BUILD_UNIX_TIME = 1688168336048L
const val DIRTY = 1 const val DIRTY = 1

View File

@ -406,7 +406,7 @@ private fun createAssemblyAndAssemble(program: PtProgram,
val asmgen = if(compilerOptions.experimentalCodegen) val asmgen = if(compilerOptions.experimentalCodegen)
prog8.codegen.experimental.ExperiCodeGen() prog8.codegen.experimental.ExperiCodeGen()
else if (compilerOptions.compTarget.machine.cpu in arrayOf(CpuType.CPU6502, CpuType.CPU65c02)) else if (compilerOptions.compTarget.machine.cpu in arrayOf(CpuType.CPU6502, CpuType.CPU65c02))
prog8.codegen.cpu6502.AsmGen6502() prog8.codegen.cpu6502.AsmGen6502(prefixSymbols = true)
else if (compilerOptions.compTarget.name == VMTarget.NAME) else if (compilerOptions.compTarget.name == VMTarget.NAME)
VmCodeGen() VmCodeGen()
else else

View File

@ -1,88 +0,0 @@
package prog8.compiler.astprocessing
import prog8.ast.Node
import prog8.ast.Program
import prog8.ast.expressions.IdentifierReference
import prog8.ast.statements.*
import prog8.ast.walk.AstWalker
import prog8.ast.walk.IAstModification
class AsmSymbolsPrefixer(val program: Program): AstWalker() {
override fun after(identifier: IdentifierReference, parent: Node): Iterable<IAstModification> {
if("no_symbol_prefixing" in identifier.targetStatement(program)!!.definingBlock.options())
return noModifications
if(identifier.nameInSource.size==1 && identifier.nameInSource[0] in program.builtinFunctions.names)
return noModifications
val newName = identifier.nameInSource.map { part -> "p8_$part" }
return listOf(IAstModification.ReplaceNode(identifier, identifier.renamed(newName), parent))
}
override fun after(label: Label, parent: Node): Iterable<IAstModification> {
return if("no_symbol_prefixing" in label.definingBlock.options())
noModifications
else
listOf(IAstModification.ReplaceNode(label, label.renamed("p8_${label.name}"), parent))
}
override fun after(block: Block, parent: Node): Iterable<IAstModification> {
return if("no_symbol_prefixing" in block.options())
noModifications
else
listOf(IAstModification.ReplaceNode(block, block.renamed("p8_${block.name}"), parent))
}
override fun after(decl: VarDecl, parent: Node): Iterable<IAstModification> {
return if("no_symbol_prefixing" in decl.definingBlock.options())
noModifications
else
listOf(IAstModification.ReplaceNode(decl, decl.renamed("p8_${decl.name}"), parent))
}
override fun after(subroutine: Subroutine, parent: Node): Iterable<IAstModification> {
if("no_symbol_prefixing" in subroutine.definingBlock.options())
return noModifications
val changedParams = mutableListOf<Pair<Int, SubroutineParameter>>()
subroutine.parameters.withIndex().forEach { (index, param) ->
if((param.name.length==3 || param.name.length==1) && param.name.all { it.isLetter() } && !param.definingModule.isLibrary) {
changedParams.add(index to SubroutineParameter("p8_${param.name}", param.type, param.position))
}
}
changedParams.forEach { (index, newParam) -> subroutine.parameters[index] = newParam }
val newName = "p8_${subroutine.name}"
return if(newName!=subroutine.name || changedParams.isNotEmpty()) {
val newSub = Subroutine(newName, subroutine.parameters, subroutine.returntypes,
subroutine.asmParameterRegisters, subroutine.asmReturnvaluesRegisters, subroutine.asmClobbers, subroutine.asmAddress, subroutine.isAsmSubroutine,
subroutine.inline, false, subroutine.statements, subroutine.position)
if(changedParams.isNotEmpty())
subsWithParamRefsToFix += newSub
listOf(IAstModification.ReplaceNode(subroutine, newSub, parent))
} else {
if(changedParams.isNotEmpty())
subsWithParamRefsToFix += subroutine
noModifications
}
}
private val subsWithParamRefsToFix = mutableListOf<Subroutine>()
override fun applyModifications(): Int {
var count = super.applyModifications()
subsWithParamRefsToFix.forEach { subroutine ->
subroutine.statements.withIndex().reversed().forEach { (index,stmt) ->
if(stmt is VarDecl && stmt.origin==VarDeclOrigin.SUBROUTINEPARAM) {
val param = subroutine.parameters.single { it.name == stmt.name}
val decl = VarDecl.fromParameter(param)
subroutine.statements[index] = decl
decl.linkParents(subroutine)
count++
}
}
}
return count
}
}

View File

@ -24,16 +24,14 @@ internal class AstChecker(private val program: Program,
override fun visit(program: Program) { override fun visit(program: Program) {
require(program === this.program) require(program === this.program)
// there must be a single 'main' block with a 'start' subroutine for the program entry point. // there must be a single 'main' block with a 'start' subroutine for the program entry point.
val mainBlocks = program.modules.flatMap { it.statements }.filter { b -> b is Block && (b.name=="main" || b.name=="p8_main") }.map { it as Block } val mainBlocks = program.modules.flatMap { it.statements }.filter { b -> b is Block && b.name=="main" }.map { it as Block }
if(mainBlocks.size>1) if(mainBlocks.size>1)
errors.err("more than one 'main' block", mainBlocks[0].position) errors.err("more than one 'main' block", mainBlocks[0].position)
if(mainBlocks.isEmpty()) if(mainBlocks.isEmpty())
errors.err("there is no 'main' block", program.modules.firstOrNull()?.position ?: Position.DUMMY) errors.err("there is no 'main' block", program.modules.firstOrNull()?.position ?: Position.DUMMY)
for(mainBlock in mainBlocks) { for(mainBlock in mainBlocks) {
var startSub = mainBlock.subScope("start") as? Subroutine val startSub = mainBlock.subScope("start") as? Subroutine
if(startSub==null)
startSub = mainBlock.subScope("p8_start") as? Subroutine
if (startSub == null) { if (startSub == null) {
errors.err("missing program entrypoint ('start' subroutine in 'main' block)", mainBlock.position) errors.err("missing program entrypoint ('start' subroutine in 'main' block)", mainBlock.position)
} else { } else {

View File

@ -12,7 +12,6 @@ import prog8.ast.statements.VarDeclOrigin
import prog8.ast.walk.AstWalker import prog8.ast.walk.AstWalker
import prog8.ast.walk.IAstModification import prog8.ast.walk.IAstModification
import prog8.code.core.* import prog8.code.core.*
import prog8.code.target.VMTarget
internal fun Program.checkValid(errors: IErrorReporter, compilerOptions: CompilationOptions) { internal fun Program.checkValid(errors: IErrorReporter, compilerOptions: CompilationOptions) {
@ -28,12 +27,6 @@ internal fun Program.processAstBeforeAsmGeneration(compilerOptions: CompilationO
boolRemover.visit(this) boolRemover.visit(this)
boolRemover.applyModifications() boolRemover.applyModifications()
if(compilerOptions.compTarget.name!=VMTarget.NAME) {
val replacer = AsmSymbolsPrefixer(this)
replacer.visit(this)
replacer.applyModifications()
}
val fixer = BeforeAsmAstChanger(this, compilerOptions, errors) val fixer = BeforeAsmAstChanger(this, compilerOptions, errors)
fixer.visit(this) fixer.visit(this)
while (errors.noErrors() && fixer.applyModifications() > 0) { while (errors.noErrors() && fixer.applyModifications() > 0) {

View File

@ -161,21 +161,23 @@ class IntermediateAstMaker(private val program: Program, private val options: Co
private fun transform(srcBlock: Block): PtBlock { private fun transform(srcBlock: Block): PtBlock {
var alignment = PtBlock.BlockAlignment.NONE var alignment = PtBlock.BlockAlignment.NONE
var forceOutput = false var forceOutput = false
var noSymbolPrefixing = false
val directives = srcBlock.statements.filterIsInstance<Directive>() val directives = srcBlock.statements.filterIsInstance<Directive>()
for (directive in directives.filter { it.directive == "%option" }) { for (directive in directives.filter { it.directive == "%option" }) {
for (arg in directive.args) { for (arg in directive.args) {
when (arg.name) { when (arg.name) {
"align_word" -> alignment = PtBlock.BlockAlignment.WORD "align_word" -> alignment = PtBlock.BlockAlignment.WORD
"align_page" -> alignment = PtBlock.BlockAlignment.PAGE "align_page" -> alignment = PtBlock.BlockAlignment.PAGE
"no_symbol_prefixing" -> noSymbolPrefixing = true
"force_output" -> forceOutput=true "force_output" -> forceOutput=true
"merge", "splitarrays", "no_symbol_prefixing" -> { /* ignore this one */ } "merge", "splitarrays" -> { /* ignore this one */ }
else -> throw FatalAstException("weird directive option: ${arg.name}") else -> throw FatalAstException("weird directive option: ${arg.name}")
} }
} }
} }
val (vardecls, statements) = srcBlock.statements.partition { it is VarDecl } val (vardecls, statements) = srcBlock.statements.partition { it is VarDecl }
val src = srcBlock.definingModule.source val src = srcBlock.definingModule.source
val block = PtBlock(srcBlock.name, srcBlock.address, srcBlock.isInLibrary, forceOutput, alignment, src, srcBlock.position) val block = PtBlock(srcBlock.name, srcBlock.address, srcBlock.isInLibrary, forceOutput, noSymbolPrefixing, alignment, src, srcBlock.position)
makeScopeVarsDecls(vardecls).forEach { block.add(it) } makeScopeVarsDecls(vardecls).forEach { block.add(it) }
for (stmt in statements) for (stmt in statements)
block.add(transformStatement(stmt)) block.add(transformStatement(stmt))
@ -434,11 +436,10 @@ class IntermediateAstMaker(private val program: Program, private val options: Co
private fun transform(src: AddressOf): PtAddressOf { private fun transform(src: AddressOf): PtAddressOf {
val addr = PtAddressOf(src.position) val addr = PtAddressOf(src.position)
val (name, dt) = src.identifier.targetNameAndType(program) val (name, dt) = src.identifier.targetNameAndType(program)
if(dt in SplitWordArrayTypes) { if(dt in SplitWordArrayTypes)
addr.add(PtIdentifier(name+"_lsb", dt, src.identifier.position)) addr.add(PtIdentifier(name+"_lsb", dt, src.identifier.position)) // NOTE: assumes _lsb is first in memory! (immediately followed by _msb)
} else { else
addr.add(transform(src.identifier)) addr.add(transform(src.identifier))
}
return addr return addr
} }

View File

@ -28,7 +28,7 @@ internal class StatementReorderer(val program: Program,
val (blocks, other) = module.statements.partition { it is Block } val (blocks, other) = module.statements.partition { it is Block }
module.statements = other.asSequence().plus(blocks.sortedBy { (it as Block).address ?: UInt.MAX_VALUE }).toMutableList() module.statements = other.asSequence().plus(blocks.sortedBy { (it as Block).address ?: UInt.MAX_VALUE }).toMutableList()
val mainBlock = module.statements.asSequence().filterIsInstance<Block>().firstOrNull { it.name=="main" || it.name=="p8_main"} val mainBlock = module.statements.asSequence().filterIsInstance<Block>().firstOrNull { it.name=="main" }
if(mainBlock!=null && mainBlock.address==null) { if(mainBlock!=null && mainBlock.address==null) {
module.statements.remove(mainBlock) module.statements.remove(mainBlock)
module.statements.add(0, mainBlock) module.statements.add(0, mainBlock)

View File

@ -90,7 +90,7 @@ private fun makeSt(): SymbolTable {
// first build the AST // first build the AST
val astProgram = PtProgram("test", DummyMemsizer, DummyStringEncoder) val astProgram = PtProgram("test", DummyMemsizer, DummyStringEncoder)
val astBlock1 = PtBlock("block1", null, false, false, PtBlock.BlockAlignment.NONE, SourceCode.Generated("block1"), Position.DUMMY) val astBlock1 = PtBlock("block1", null, false, false, false, PtBlock.BlockAlignment.NONE, SourceCode.Generated("block1"), Position.DUMMY)
val astConstant1 = PtConstant("c1", DataType.UWORD, 12345.0, Position.DUMMY) val astConstant1 = PtConstant("c1", DataType.UWORD, 12345.0, Position.DUMMY)
val astConstant2 = PtConstant("blockc", DataType.UWORD, 999.0, Position.DUMMY) val astConstant2 = PtConstant("blockc", DataType.UWORD, 999.0, Position.DUMMY)
astBlock1.add(astConstant1) astBlock1.add(astConstant1)
@ -113,7 +113,7 @@ private fun makeSt(): SymbolTable {
astBlock1.add(astSub2) astBlock1.add(astSub2)
val astBfunc = PtIdentifier("msb", DataType.UBYTE, Position.DUMMY) val astBfunc = PtIdentifier("msb", DataType.UBYTE, Position.DUMMY)
astBlock1.add(astBfunc) astBlock1.add(astBfunc)
val astBlock2 = PtBlock("block2", null, false, false, PtBlock.BlockAlignment.NONE, SourceCode.Generated("block2"), Position.DUMMY) val astBlock2 = PtBlock("block2", null, false, false, false, PtBlock.BlockAlignment.NONE, SourceCode.Generated("block2"), Position.DUMMY)
val astSub21 = PtSub("sub1", emptyList(), null, Position.DUMMY) val astSub21 = PtSub("sub1", emptyList(), null, Position.DUMMY)
val astSub22 = PtSub("sub2", emptyList(), null, Position.DUMMY) val astSub22 = PtSub("sub2", emptyList(), null, Position.DUMMY)
val astSub221 = PtSub("subsub", emptyList(), null, Position.DUMMY) val astSub221 = PtSub("subsub", emptyList(), null, Position.DUMMY)

View File

@ -62,7 +62,7 @@ class TestTypecasts: FunSpec({
val expr2 = (stmts2[4] as Assignment).value as BinaryExpression val expr2 = (stmts2[4] as Assignment).value as BinaryExpression
expr2.operator shouldBe "&" expr2.operator shouldBe "&"
expr2.right shouldBe NumericLiteral(DataType.UBYTE, 1.0, Position.DUMMY) expr2.right shouldBe NumericLiteral(DataType.UBYTE, 1.0, Position.DUMMY)
(expr2.left as IdentifierReference).nameInSource shouldBe listOf("p8_bb") (expr2.left as IdentifierReference).nameInSource shouldBe listOf("bb")
} }
test("bool expressions with functioncalls") { test("bool expressions with functioncalls") {
@ -107,7 +107,7 @@ main {
val assignValue1 = (stmts[7] as Assignment).value as IdentifierReference val assignValue1 = (stmts[7] as Assignment).value as IdentifierReference
val assignValue2 = (stmts[11] as Assignment).value as BinaryExpression val assignValue2 = (stmts[11] as Assignment).value as BinaryExpression
val assignValue3 = (stmts[12] as Assignment).value as BinaryExpression val assignValue3 = (stmts[12] as Assignment).value as BinaryExpression
assignValue1.nameInSource shouldBe listOf("p8_ub1") assignValue1.nameInSource shouldBe listOf("ub1")
assignValue2.operator shouldBe "^" assignValue2.operator shouldBe "^"
assignValue3.operator shouldBe "&" assignValue3.operator shouldBe "&"
val right2 = assignValue2.right as BinaryExpression val right2 = assignValue2.right as BinaryExpression

View File

@ -121,11 +121,11 @@ main {
sub start() { sub start() {
%asm {{ %asm {{
lda normal lda p8_normal
lda uw_lsb lda p8_uw_lsb
lda uw_msb lda p8_uw_msb
lda sw_lsb lda p8_sw_lsb
lda sw_msb lda p8_sw_msb
}} }}
} }
}""" }"""

View File

@ -12,6 +12,7 @@ import prog8.code.ast.PtAssignment
import prog8.code.ast.PtVariable import prog8.code.ast.PtVariable
import prog8.code.core.DataType import prog8.code.core.DataType
import prog8.code.target.C64Target import prog8.code.target.C64Target
import prog8.code.target.Cx16Target
import prog8.code.target.VMTarget import prog8.code.target.VMTarget
import prog8tests.helpers.ErrorReporterForTests import prog8tests.helpers.ErrorReporterForTests
import prog8tests.helpers.compileText import prog8tests.helpers.compileText
@ -202,4 +203,60 @@ block2 {
compileText(C64Target(), true, src, writeAssembly = true) shouldNotBe null compileText(C64Target(), true, src, writeAssembly = true) shouldNotBe null
compileText(VMTarget(), true, src, writeAssembly = true) shouldNotBe null compileText(VMTarget(), true, src, writeAssembly = true) shouldNotBe null
} }
test("array with pointers") {
val src = """
main {
sub start() {
str localstr = "hello"
ubyte[] otherarray = [1,2,3]
uword[] words = [1111,2222,"three",&localstr,&otherarray]
uword @shared zz = &words
ubyte result = 2222 in words
zz = words[2]
zz++
zz = words[3]
}
}"""
val othertarget = Cx16Target()
compileText(othertarget, true, src, writeAssembly = true) shouldNotBe null
}
test("case sensitive symbols") {
val src = """
main {
sub start() {
ubyte bytevar = 11 ; var at 0
ubyte byteVAR = 22 ; var at 1
ubyte ByteVar = 33 ; var at 2
ubyte @shared total = bytevar+byteVAR+ByteVar ; var at 3
goto skipLABEL
SkipLabel:
return
skipLABEL:
bytevar = 42
}
}"""
val target = Cx16Target()
compileText(target, true, src, writeAssembly = true) shouldNotBe null
}
test("addresses from labels/subroutines") {
val src = """
main {
sub start() {
mylabel:
ubyte variable
uword @shared pointer1 = &main.start
uword @shared pointer2 = &start
uword @shared pointer3 = &main.start.mylabel
uword @shared pointer4 = &mylabel
uword[] @shared ptrs = [&variable, &start, &main.start, &mylabel, &main.start.mylabel]
}
}
"""
compileText(Cx16Target(), true, src, writeAssembly = true) shouldNotBe null
}
}) })

View File

@ -53,8 +53,6 @@ main {
zz = words[3] zz = words[3]
} }
}""" }"""
val othertarget = Cx16Target()
compileText(othertarget, true, src, writeAssembly = true) shouldNotBe null
val target = VMTarget() val target = VMTarget()
val result = compileText(target, true, src, writeAssembly = true)!! val result = compileText(target, true, src, writeAssembly = true)!!
val virtfile = result.compilationOptions.outputDir.resolve(result.compilerAst.name + ".p8ir") val virtfile = result.compilationOptions.outputDir.resolve(result.compilerAst.name + ".p8ir")
@ -165,10 +163,7 @@ skipLABEL:
bytevar = 42 bytevar = 42
} }
}""" }"""
val othertarget = Cx16Target() val result = compileText(VMTarget(), true, src, writeAssembly = true)!!
compileText(othertarget, true, src, writeAssembly = true) shouldNotBe null
val target = VMTarget()
val result = compileText(target, true, src, writeAssembly = true)!!
val virtfile = result.compilationOptions.outputDir.resolve(result.compilerAst.name + ".p8ir") val virtfile = result.compilationOptions.outputDir.resolve(result.compilerAst.name + ".p8ir")
VmRunner().runAndTestProgram(virtfile.readText()) { vm -> VmRunner().runAndTestProgram(virtfile.readText()) { vm ->
vm.memory.getUB(0) shouldBe 42u vm.memory.getUB(0) shouldBe 42u
@ -283,11 +278,7 @@ mylabel:
} }
""" """
val othertarget = Cx16Target() val result = compileText(VMTarget(), false, src, writeAssembly = true)!!
compileText(othertarget, true, src, writeAssembly = true) shouldNotBe null
val target = VMTarget()
val result = compileText(target, false, src, writeAssembly = true)!!
val virtfile = result.compilationOptions.outputDir.resolve(result.compilerAst.name + ".p8ir") val virtfile = result.compilationOptions.outputDir.resolve(result.compilerAst.name + ".p8ir")
val exc = shouldThrow<Exception> { val exc = shouldThrow<Exception> {
VmRunner().runProgram(virtfile.readText()) VmRunner().runProgram(virtfile.readText())

View File

@ -55,12 +55,10 @@ class Program(val name: String,
val entrypoint: Subroutine val entrypoint: Subroutine
get() { get() {
val mainBlocks = allBlocks.filter { it.name=="main" || it.name=="p8_main" } val mainBlocks = allBlocks.filter { it.name=="main" }
return when (mainBlocks.size) { return when (mainBlocks.size) {
0 -> throw FatalAstException("no 'main' block") 0 -> throw FatalAstException("no 'main' block")
1 -> { 1 -> mainBlocks[0].subScope("start") as Subroutine
mainBlocks[0].subScope("start") as? Subroutine ?: mainBlocks[0].subScope("p8_start") as Subroutine
}
else -> throw FatalAstException("more than one 'main' block") else -> throw FatalAstException("more than one 'main' block")
} }
} }

View File

@ -1,11 +1,10 @@
TODO TODO
==== ====
- AsmSymbolsPrefixer not on compiler Ast but on PtProgram - remove all "p8_main" and "p8_start" checks again - prog8->asm symbol name prefixing: prefix ALL symbols with p8_
- prog8->asm symbol name prefixing: prefix ALL symbols with p8_ Also update manual.
EXCEPTION: library symbols such as cbm.CHROUT, cx16.r0 etc. should NOT be prefixed. EXCEPTION: library symbols such as cbm.CHROUT, cx16.r0 etc. should NOT be prefixed.
Solution: add %option no_symbol_prefix to those blocks? Solution: add %option no_symbol_prefix to those blocks?
- Also update manual
... ...

View File

@ -1,80 +1,9 @@
%import textio
%zeropage basicsafe
main { main {
sub start() { sub start() {
uword count = 255 str name1 = "name1"
cx16.r0 = 0 str name2 = "name2"
repeat count { uword[] @split names = [name1, name2, "name3"]
cx16.r0++ cx16.r0++
} names = [1111,2222,3333]
txt.print_uw(255)
txt.spc()
txt.print_uw(cx16.r0)
txt.nl()
count=256
repeat count {
cx16.r0++
}
txt.print_uw(255+256)
txt.spc()
txt.print_uw(cx16.r0)
txt.nl()
count = 257
repeat count {
cx16.r0++
}
txt.print_uw(255+256+257)
txt.spc()
txt.print_uw(cx16.r0)
txt.nl()
count=1023
repeat count {
cx16.r0++
}
txt.print_uw(255+256+257+1023)
txt.spc()
txt.print_uw(cx16.r0)
txt.nl()
count=1024
repeat count {
cx16.r0++
}
txt.print_uw(255+256+257+1023+1024)
txt.spc()
txt.print_uw(cx16.r0)
txt.nl()
count = 1025
repeat count {
cx16.r0++
}
txt.print_uw(255+256+257+1023+1024+1025)
txt.spc()
txt.print_uw(cx16.r0)
txt.nl()
count = 65534
repeat count {
cx16.r0++
}
txt.print_uw(3838)
txt.spc()
txt.print_uw(cx16.r0)
txt.nl()
count = 65535
repeat count {
cx16.r0++
}
count=0
repeat count {
cx16.r0++
}
repeat 0 {
cx16.r0++
}
txt.print_uw(3837)
txt.spc()
txt.print_uw(cx16.r0)
txt.nl()
} }
} }