diff --git a/codeCore/src/prog8/code/SymbolTableMaker.kt b/codeCore/src/prog8/code/SymbolTableMaker.kt index 791add9ed..ed69b02cd 100644 --- a/codeCore/src/prog8/code/SymbolTableMaker.kt +++ b/codeCore/src/prog8/code/SymbolTableMaker.kt @@ -94,6 +94,9 @@ class SymbolTableMaker(private val program: PtProgram, private val options: Comp initialString = null 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) } is PtBuiltinFunctionCall -> { diff --git a/codeCore/src/prog8/code/ast/AstBase.kt b/codeCore/src/prog8/code/ast/AstBase.kt index 2d41e7825..f8dd3893e 100644 --- a/codeCore/src/prog8/code/ast/AstBase.kt +++ b/codeCore/src/prog8/code/ast/AstBase.kt @@ -63,9 +63,9 @@ class PtProgram( children.asSequence().filterIsInstance() fun entrypoint(): PtSub? = - allBlocks().firstOrNull { it.name == "main" || it.name=="p8_main" } + allBlocks().firstOrNull { it.name == "main" } ?.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 library: Boolean, val forceOutput: Boolean, + val noSymbolPrefixing: Boolean, val alignment: BlockAlignment, val source: SourceCode, // taken from the module the block is defined in. position: Position diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmGen.kt index 4486b2ada..27af64073 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmGen.kt @@ -3,6 +3,7 @@ package prog8.codegen.cpu6502 import com.github.michaelbull.result.fold import prog8.code.StNodeType import prog8.code.SymbolTable +import prog8.code.SymbolTableMaker import prog8.code.ast.* import prog8.code.core.* 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 subroutineFloatEvalResultVar2 = "prog8_float_eval_result2" -class AsmGen6502: ICodeGeneratorBackend { +class AsmGen6502(val prefixSymbols: Boolean): ICodeGeneratorBackend { override fun generate( program: PtProgram, symbolTable: SymbolTable, options: CompilationOptions, errors: IErrorReporter ): 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() } + + private fun prefixSymbols(program: PtProgram, options: CompilationOptions, st: SymbolTable): SymbolTable { + + printAst(program, true, ::println) + + val nodesToPrefix = mutableListOf>() + + 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 ( val program: PtProgram, internal val symbolTable: SymbolTable, diff --git a/codeGenCpu6502/test/TestCodegen.kt b/codeGenCpu6502/test/TestCodegen.kt index f65522269..e61e53aeb 100644 --- a/codeGenCpu6502/test/TestCodegen.kt +++ b/codeGenCpu6502/test/TestCodegen.kt @@ -40,9 +40,9 @@ class TestCodegen: FunSpec({ // xx += cx16.r0 // } //} - val codegen = AsmGen6502() + val codegen = AsmGen6502(prefixSymbols = false) 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) 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)) @@ -92,7 +92,7 @@ class TestCodegen: FunSpec({ program.add(block) // 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)) program.add(cx16block) diff --git a/codeGenIntermediate/src/prog8/codegen/intermediate/IRUnusedCodeRemover.kt b/codeGenIntermediate/src/prog8/codegen/intermediate/IRUnusedCodeRemover.kt index e360db31d..4d69c1688 100644 --- a/codeGenIntermediate/src/prog8/codegen/intermediate/IRUnusedCodeRemover.kt +++ b/codeGenIntermediate/src/prog8/codegen/intermediate/IRUnusedCodeRemover.kt @@ -135,8 +135,8 @@ class IRUnusedCodeRemover( } private fun removeUnreachable(allLabeledChunks: MutableMap): Int { - val entrypointSub = irprog.blocks.single { it.label=="main" || it.label=="p8_main" } - .children.single { it is IRSubroutine && (it.label=="main.start" || it.label=="p8_main.p8_start") } + val entrypointSub = irprog.blocks.single { it.label=="main" } + .children.single { it is IRSubroutine && it.label=="main.start" } val reachable = mutableSetOf((entrypointSub as IRSubroutine).chunks.first()) fun grow() { diff --git a/codeGenIntermediate/test/TestVmCodeGen.kt b/codeGenIntermediate/test/TestVmCodeGen.kt index 040290466..99e818e87 100644 --- a/codeGenIntermediate/test/TestVmCodeGen.kt +++ b/codeGenIntermediate/test/TestVmCodeGen.kt @@ -41,7 +41,7 @@ class TestVmCodeGen: FunSpec({ //} val codegen = VmCodeGen() 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) 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)) @@ -91,7 +91,7 @@ class TestVmCodeGen: FunSpec({ program.add(block) // 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)) program.add(cx16block) @@ -120,7 +120,7 @@ class TestVmCodeGen: FunSpec({ //} val codegen = VmCodeGen() 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) sub.add(PtVariable("f1", DataType.FLOAT, ZeropageWish.DONTCARE, null, null, Position.DUMMY)) val if1 = PtIfElse(Position.DUMMY) @@ -183,7 +183,7 @@ class TestVmCodeGen: FunSpec({ //} val codegen = VmCodeGen() 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) sub.add(PtVariable("f1", DataType.FLOAT, ZeropageWish.DONTCARE, null, null, Position.DUMMY)) val if1 = PtIfElse(Position.DUMMY) @@ -242,7 +242,7 @@ class TestVmCodeGen: FunSpec({ //} val codegen = VmCodeGen() 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) sub.add(PtVariable("f1", DataType.FLOAT, ZeropageWish.DONTCARE, null, null, Position.DUMMY)) val if1 = PtIfElse(Position.DUMMY) @@ -289,7 +289,7 @@ class TestVmCodeGen: FunSpec({ //} val codegen = VmCodeGen() 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) sub.add(PtVariable("sb1", DataType.BYTE, ZeropageWish.DONTCARE, null, null, Position.DUMMY)) val if1 = PtIfElse(Position.DUMMY) @@ -352,7 +352,7 @@ class TestVmCodeGen: FunSpec({ //} val codegen = VmCodeGen() 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) sub.add(PtVariable("sb1", DataType.BYTE, ZeropageWish.DONTCARE, null, null, Position.DUMMY)) val if1 = PtIfElse(Position.DUMMY) @@ -411,7 +411,7 @@ class TestVmCodeGen: FunSpec({ //} val codegen = VmCodeGen() 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) sub.add(PtVariable("ub1", DataType.UBYTE, ZeropageWish.DONTCARE, null, null, Position.DUMMY)) val if1 = PtIfElse(Position.DUMMY) @@ -451,7 +451,7 @@ class TestVmCodeGen: FunSpec({ //} val codegen = VmCodeGen() 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) block.add(romsub) val sub = PtSub("start", emptyList(), null, Position.DUMMY) diff --git a/compiler/src/prog8/buildversion/BuildVersion.kt b/compiler/src/prog8/buildversion/BuildVersion.kt index ee9cbd9c8..0c8d97b5d 100644 --- a/compiler/src/prog8/buildversion/BuildVersion.kt +++ b/compiler/src/prog8/buildversion/BuildVersion.kt @@ -6,10 +6,10 @@ package prog8.buildversion const val MAVEN_GROUP = "prog8" const val MAVEN_NAME = "compiler" const val VERSION = "9.1-SNAPSHOT" -const val GIT_REVISION = 3909 -const val GIT_SHA = "04da44eb988e4c2abef4099f86888b95074cc453" -const val GIT_DATE = "2023-06-29T20:56:26Z" +const val GIT_REVISION = -1 +const val GIT_SHA = "bf86e1f41d9c97d3b56e91e5217bcda258fa3e09" +const val GIT_DATE = "UNKNOWN" const val GIT_BRANCH = "prefixing" -const val BUILD_DATE = "2023-06-29T21:18:59Z" -const val BUILD_UNIX_TIME = 1688073539609L +const val BUILD_DATE = "2023-06-30T23:38:56Z" +const val BUILD_UNIX_TIME = 1688168336048L const val DIRTY = 1 diff --git a/compiler/src/prog8/compiler/Compiler.kt b/compiler/src/prog8/compiler/Compiler.kt index 3755e21a3..21b622e6e 100644 --- a/compiler/src/prog8/compiler/Compiler.kt +++ b/compiler/src/prog8/compiler/Compiler.kt @@ -406,7 +406,7 @@ private fun createAssemblyAndAssemble(program: PtProgram, val asmgen = if(compilerOptions.experimentalCodegen) prog8.codegen.experimental.ExperiCodeGen() 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) VmCodeGen() else diff --git a/compiler/src/prog8/compiler/astprocessing/AsmSymbolsPrefixer.kt b/compiler/src/prog8/compiler/astprocessing/AsmSymbolsPrefixer.kt deleted file mode 100644 index 728812b1f..000000000 --- a/compiler/src/prog8/compiler/astprocessing/AsmSymbolsPrefixer.kt +++ /dev/null @@ -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 { - 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 { - 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 { - 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 { - 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 { - if("no_symbol_prefixing" in subroutine.definingBlock.options()) - return noModifications - - val changedParams = mutableListOf>() - 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() - - 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 - } -} diff --git a/compiler/src/prog8/compiler/astprocessing/AstChecker.kt b/compiler/src/prog8/compiler/astprocessing/AstChecker.kt index 8ce0be491..534cc68e4 100644 --- a/compiler/src/prog8/compiler/astprocessing/AstChecker.kt +++ b/compiler/src/prog8/compiler/astprocessing/AstChecker.kt @@ -24,16 +24,14 @@ internal class AstChecker(private val program: Program, override fun visit(program: Program) { require(program === this.program) // 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) errors.err("more than one 'main' block", mainBlocks[0].position) if(mainBlocks.isEmpty()) errors.err("there is no 'main' block", program.modules.firstOrNull()?.position ?: Position.DUMMY) for(mainBlock in mainBlocks) { - var startSub = mainBlock.subScope("start") as? Subroutine - if(startSub==null) - startSub = mainBlock.subScope("p8_start") as? Subroutine + val startSub = mainBlock.subScope("start") as? Subroutine if (startSub == null) { errors.err("missing program entrypoint ('start' subroutine in 'main' block)", mainBlock.position) } else { diff --git a/compiler/src/prog8/compiler/astprocessing/AstExtensions.kt b/compiler/src/prog8/compiler/astprocessing/AstExtensions.kt index c9b78607f..30ce50201 100644 --- a/compiler/src/prog8/compiler/astprocessing/AstExtensions.kt +++ b/compiler/src/prog8/compiler/astprocessing/AstExtensions.kt @@ -12,7 +12,6 @@ import prog8.ast.statements.VarDeclOrigin import prog8.ast.walk.AstWalker import prog8.ast.walk.IAstModification import prog8.code.core.* -import prog8.code.target.VMTarget internal fun Program.checkValid(errors: IErrorReporter, compilerOptions: CompilationOptions) { @@ -28,12 +27,6 @@ internal fun Program.processAstBeforeAsmGeneration(compilerOptions: CompilationO boolRemover.visit(this) boolRemover.applyModifications() - if(compilerOptions.compTarget.name!=VMTarget.NAME) { - val replacer = AsmSymbolsPrefixer(this) - replacer.visit(this) - replacer.applyModifications() - } - val fixer = BeforeAsmAstChanger(this, compilerOptions, errors) fixer.visit(this) while (errors.noErrors() && fixer.applyModifications() > 0) { diff --git a/compiler/src/prog8/compiler/astprocessing/IntermediateAstMaker.kt b/compiler/src/prog8/compiler/astprocessing/IntermediateAstMaker.kt index 11ff06a20..d05e9cd1b 100644 --- a/compiler/src/prog8/compiler/astprocessing/IntermediateAstMaker.kt +++ b/compiler/src/prog8/compiler/astprocessing/IntermediateAstMaker.kt @@ -161,21 +161,23 @@ class IntermediateAstMaker(private val program: Program, private val options: Co private fun transform(srcBlock: Block): PtBlock { var alignment = PtBlock.BlockAlignment.NONE var forceOutput = false + var noSymbolPrefixing = false val directives = srcBlock.statements.filterIsInstance() for (directive in directives.filter { it.directive == "%option" }) { for (arg in directive.args) { when (arg.name) { "align_word" -> alignment = PtBlock.BlockAlignment.WORD "align_page" -> alignment = PtBlock.BlockAlignment.PAGE + "no_symbol_prefixing" -> noSymbolPrefixing = 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}") } } } val (vardecls, statements) = srcBlock.statements.partition { it is VarDecl } 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) } for (stmt in statements) block.add(transformStatement(stmt)) @@ -434,11 +436,10 @@ class IntermediateAstMaker(private val program: Program, private val options: Co private fun transform(src: AddressOf): PtAddressOf { val addr = PtAddressOf(src.position) val (name, dt) = src.identifier.targetNameAndType(program) - if(dt in SplitWordArrayTypes) { - addr.add(PtIdentifier(name+"_lsb", dt, src.identifier.position)) - } else { + if(dt in SplitWordArrayTypes) + addr.add(PtIdentifier(name+"_lsb", dt, src.identifier.position)) // NOTE: assumes _lsb is first in memory! (immediately followed by _msb) + else addr.add(transform(src.identifier)) - } return addr } diff --git a/compiler/src/prog8/compiler/astprocessing/StatementReorderer.kt b/compiler/src/prog8/compiler/astprocessing/StatementReorderer.kt index d0d575bd9..7cd4e7c1c 100644 --- a/compiler/src/prog8/compiler/astprocessing/StatementReorderer.kt +++ b/compiler/src/prog8/compiler/astprocessing/StatementReorderer.kt @@ -28,7 +28,7 @@ internal class StatementReorderer(val program: Program, val (blocks, other) = module.statements.partition { it is Block } module.statements = other.asSequence().plus(blocks.sortedBy { (it as Block).address ?: UInt.MAX_VALUE }).toMutableList() - val mainBlock = module.statements.asSequence().filterIsInstance().firstOrNull { it.name=="main" || it.name=="p8_main"} + val mainBlock = module.statements.asSequence().filterIsInstance().firstOrNull { it.name=="main" } if(mainBlock!=null && mainBlock.address==null) { module.statements.remove(mainBlock) module.statements.add(0, mainBlock) diff --git a/compiler/test/TestSymbolTable.kt b/compiler/test/TestSymbolTable.kt index f245ce40f..bbcf59089 100644 --- a/compiler/test/TestSymbolTable.kt +++ b/compiler/test/TestSymbolTable.kt @@ -90,7 +90,7 @@ private fun makeSt(): SymbolTable { // first build the AST 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 astConstant2 = PtConstant("blockc", DataType.UWORD, 999.0, Position.DUMMY) astBlock1.add(astConstant1) @@ -113,7 +113,7 @@ private fun makeSt(): SymbolTable { astBlock1.add(astSub2) val astBfunc = PtIdentifier("msb", DataType.UBYTE, Position.DUMMY) 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 astSub22 = PtSub("sub2", emptyList(), null, Position.DUMMY) val astSub221 = PtSub("subsub", emptyList(), null, Position.DUMMY) diff --git a/compiler/test/TestTypecasts.kt b/compiler/test/TestTypecasts.kt index 12bf5e5de..889d2032c 100644 --- a/compiler/test/TestTypecasts.kt +++ b/compiler/test/TestTypecasts.kt @@ -62,7 +62,7 @@ class TestTypecasts: FunSpec({ val expr2 = (stmts2[4] as Assignment).value as BinaryExpression expr2.operator shouldBe "&" 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") { @@ -107,7 +107,7 @@ main { val assignValue1 = (stmts[7] as Assignment).value as IdentifierReference val assignValue2 = (stmts[11] 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 "^" assignValue3.operator shouldBe "&" val right2 = assignValue2.right as BinaryExpression diff --git a/compiler/test/codegeneration/TestArrayThings.kt b/compiler/test/codegeneration/TestArrayThings.kt index 0486bcedf..5ae4d1cf0 100644 --- a/compiler/test/codegeneration/TestArrayThings.kt +++ b/compiler/test/codegeneration/TestArrayThings.kt @@ -121,11 +121,11 @@ main { sub start() { %asm {{ - lda normal - lda uw_lsb - lda uw_msb - lda sw_lsb - lda sw_msb + lda p8_normal + lda p8_uw_lsb + lda p8_uw_msb + lda p8_sw_lsb + lda p8_sw_msb }} } }""" diff --git a/compiler/test/codegeneration/TestVariousCodeGen.kt b/compiler/test/codegeneration/TestVariousCodeGen.kt index 3ecf3a101..067cba728 100644 --- a/compiler/test/codegeneration/TestVariousCodeGen.kt +++ b/compiler/test/codegeneration/TestVariousCodeGen.kt @@ -12,6 +12,7 @@ import prog8.code.ast.PtAssignment import prog8.code.ast.PtVariable import prog8.code.core.DataType import prog8.code.target.C64Target +import prog8.code.target.Cx16Target import prog8.code.target.VMTarget import prog8tests.helpers.ErrorReporterForTests import prog8tests.helpers.compileText @@ -202,4 +203,60 @@ block2 { compileText(C64Target(), 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 + } }) \ No newline at end of file diff --git a/compiler/test/vm/TestCompilerVirtual.kt b/compiler/test/vm/TestCompilerVirtual.kt index 7822674bd..3654bb50c 100644 --- a/compiler/test/vm/TestCompilerVirtual.kt +++ b/compiler/test/vm/TestCompilerVirtual.kt @@ -53,8 +53,6 @@ main { zz = words[3] } }""" - val othertarget = Cx16Target() - 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") @@ -165,10 +163,7 @@ skipLABEL: bytevar = 42 } }""" - val othertarget = Cx16Target() - compileText(othertarget, true, src, writeAssembly = true) shouldNotBe null - val target = VMTarget() - val result = compileText(target, true, src, writeAssembly = true)!! + val result = compileText(VMTarget(), true, src, writeAssembly = true)!! val virtfile = result.compilationOptions.outputDir.resolve(result.compilerAst.name + ".p8ir") VmRunner().runAndTestProgram(virtfile.readText()) { vm -> vm.memory.getUB(0) shouldBe 42u @@ -283,11 +278,7 @@ mylabel: } """ - val othertarget = Cx16Target() - compileText(othertarget, true, src, writeAssembly = true) shouldNotBe null - - val target = VMTarget() - val result = compileText(target, false, src, writeAssembly = true)!! + val result = compileText(VMTarget(), false, src, writeAssembly = true)!! val virtfile = result.compilationOptions.outputDir.resolve(result.compilerAst.name + ".p8ir") val exc = shouldThrow { VmRunner().runProgram(virtfile.readText()) diff --git a/compilerAst/src/prog8/ast/Program.kt b/compilerAst/src/prog8/ast/Program.kt index 034a49d78..0cb1a88f9 100644 --- a/compilerAst/src/prog8/ast/Program.kt +++ b/compilerAst/src/prog8/ast/Program.kt @@ -55,12 +55,10 @@ class Program(val name: String, val entrypoint: Subroutine get() { - val mainBlocks = allBlocks.filter { it.name=="main" || it.name=="p8_main" } + val mainBlocks = allBlocks.filter { it.name=="main" } return when (mainBlocks.size) { 0 -> throw FatalAstException("no 'main' block") - 1 -> { - mainBlocks[0].subScope("start") as? Subroutine ?: mainBlocks[0].subScope("p8_start") as Subroutine - } + 1 -> mainBlocks[0].subScope("start") as Subroutine else -> throw FatalAstException("more than one 'main' block") } } diff --git a/docs/source/todo.rst b/docs/source/todo.rst index bd5ec9efc..73f57a8cb 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -1,11 +1,10 @@ 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_ Also update manual. +- prog8->asm symbol name prefixing: prefix ALL symbols with p8_ EXCEPTION: library symbols such as cbm.CHROUT, cx16.r0 etc. should NOT be prefixed. Solution: add %option no_symbol_prefix to those blocks? +- Also update manual ... diff --git a/examples/test.p8 b/examples/test.p8 index 7f806aa71..3a5d7bca4 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -1,80 +1,9 @@ -%import textio -%zeropage basicsafe - main { sub start() { - uword count = 255 - cx16.r0 = 0 - repeat count { - cx16.r0++ - } - 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() + str name1 = "name1" + str name2 = "name2" + uword[] @split names = [name1, name2, "name3"] + cx16.r0++ + names = [1111,2222,3333] } }