diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmGen.kt index dd8faad25..06970d1ee 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmGen.kt @@ -28,9 +28,6 @@ class AsmGen6502(val prefixSymbols: Boolean): ICodeGeneratorBackend { } private fun prefixSymbols(program: PtProgram, options: CompilationOptions, st: SymbolTable): SymbolTable { - - printAst(program, true, ::println) - val nodesToPrefix = mutableListOf>() // parent + index val functionCallsToPrefix = mutableListOf>() // parent + index @@ -105,15 +102,16 @@ class AsmGen6502(val prefixSymbols: Boolean): ICodeGeneratorBackend { nodesToPrefix.forEach { (parent, index) -> val node = parent.children[index] when(node) { - is PtIdentifier -> parent.children[index] = node.prefix(parent) + is PtIdentifier -> parent.children[index] = node.prefix(parent, st) is PtFunctionCall -> throw AssemblyError("PtFunctionCall should be processed in their own list, last") - is PtJump -> parent.children[index] = node.prefix(parent) - is PtVariable -> parent.children[index] = node.prefix(parent) + is PtJump -> parent.children[index] = node.prefix(parent, st) + is PtVariable -> parent.children[index] = node.prefix(st) else -> throw AssemblyError("weird node to prefix $node") } } - functionCallsToPrefix.forEach { (parent, index) -> + // reversed so inner calls (such as arguments to a function call) get processed before the actual function call itself + functionCallsToPrefix.reversed().forEach { (parent, index) -> val node = parent.children[index] if(node is PtFunctionCall) { parent.children[index] = node.prefix(parent) @@ -126,7 +124,7 @@ class AsmGen6502(val prefixSymbols: Boolean): ICodeGeneratorBackend { } } -private fun PtVariable.prefix(parent: PtNode): PtVariable { +private fun PtVariable.prefix(st: SymbolTable): PtVariable { name = name.split('.').map {"p8_$it" }.joinToString(".") if(value==null) return this @@ -136,13 +134,17 @@ private fun PtVariable.prefix(parent: PtNode): PtVariable { val newValue = PtArray(arrayValue.type, arrayValue.position) arrayValue.children.forEach { elt -> when(elt) { - is PtIdentifier -> newValue.add(elt.prefix(arrayValue)) + is PtIdentifier -> newValue.add(elt.prefix(arrayValue, st)) 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) + if(elt.definingBlock()?.noSymbolPrefixing==true) + newValue.add(elt) + else { + val newAddr = PtAddressOf(elt.position) + newAddr.children.add(elt.identifier.prefix(newAddr, st)) + newAddr.parent = arrayValue + newValue.add(newAddr) + } } else -> throw AssemblyError("weird array value element $elt") } @@ -152,9 +154,9 @@ private fun PtVariable.prefix(parent: PtNode): PtVariable { else this } -private fun PtJump.prefix(parent: PtNode): PtJump { +private fun PtJump.prefix(parent: PtNode, st: SymbolTable): PtJump { val jump = if(identifier!=null) { - val prefixedIdent = identifier!!.prefix(this) + val prefixedIdent = identifier!!.prefix(this, st) PtJump(prefixedIdent, address, generatedLabel, position) } else { val prefixedLabel = generatedLabel!!.split('.').map {"p8_$it" }.joinToString(".") @@ -170,11 +172,17 @@ private fun PtFunctionCall.prefix(parent: PtNode): PtFunctionCall { call.children.addAll(children) call.children.forEach { it.parent = call } call.parent = parent + if(name.endsWith("concat_string")) + println("CONCAT ${this.position}") return call } -private fun PtIdentifier.prefix(parent: PtNode): PtIdentifier { - val newName = name.split('.').map {"p8_$it" }.joinToString(".") +private fun PtIdentifier.prefix(parent: PtNode, st: SymbolTable): PtIdentifier { + val target = st.lookup(name) + if(target?.astNode?.definingBlock()?.noSymbolPrefixing==true) + return this + + val newName = name.split('.').map { "p8_$it" }.joinToString(".") val node = PtIdentifier(newName, type, position) node.parent = parent return node diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AsmAssignment.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AsmAssignment.kt index f5b72d305..93c2d2604 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AsmAssignment.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AsmAssignment.kt @@ -179,6 +179,8 @@ internal class AsmAssignSource(val kind: SourceStorageKind, } is PtFunctionCall -> { val symbol = asmgen.symbolTable.lookup(value.name) + if(symbol==null) + TODO("${value.name}") val sub = symbol!!.astNode as IPtSubroutine val returnType = sub.returnsWhatWhere().firstOrNull { rr -> rr.first.registerOrPair != null || rr.first.statusflag!=null }?.second ?: throw AssemblyError("can't translate zero return values in assignment") diff --git a/compiler/src/prog8/buildversion/BuildVersion.kt b/compiler/src/prog8/buildversion/BuildVersion.kt index 4cb2cb32f..50ce44e01 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 = 3914 -const val GIT_SHA = "bb95484c8abd6a65220e542913d59d337d833c86" -const val GIT_DATE = "2023-07-02T04:15:09Z" +const val GIT_REVISION = 3915 +const val GIT_SHA = "bdf8aa9168e16baa29543de041c90ad8f47bba3b" +const val GIT_DATE = "2023-07-02T13:26:04Z" const val GIT_BRANCH = "prefixing" -const val BUILD_DATE = "2023-07-02T13:23:24Z" -const val BUILD_UNIX_TIME = 1688304204488L +const val BUILD_DATE = "2023-07-02T17:14:33Z" +const val BUILD_UNIX_TIME = 1688318073184L const val DIRTY = 1 diff --git a/compiler/test/ast/TestIntermediateAst.kt b/compiler/test/ast/TestIntermediateAst.kt index 75170f530..168061267 100644 --- a/compiler/test/ast/TestIntermediateAst.kt +++ b/compiler/test/ast/TestIntermediateAst.kt @@ -66,7 +66,6 @@ class TestIntermediateAst: FunSpec({ val fcall = (entry.children[4] as PtAssignment).value as PtFunctionCall fcall.void shouldBe false fcall.type shouldBe DataType.UBYTE - printAst(ast, false, ::println) } }) \ No newline at end of file diff --git a/compilerAst/src/prog8/ast/Program.kt b/compilerAst/src/prog8/ast/Program.kt index 0cb1a88f9..1f873bb18 100644 --- a/compilerAst/src/prog8/ast/Program.kt +++ b/compilerAst/src/prog8/ast/Program.kt @@ -24,6 +24,8 @@ class Program(val name: String, val internedStringsModule = Module(mutableListOf(), Position.DUMMY, SourceCode.Generated(internedStringsModuleName)) val block = Block(internedStringsModuleName, null, mutableListOf(), true, Position.DUMMY) + val directive = Directive("%option", listOf(DirectiveArg(null,"no_symbol_prefixing", null, Position.DUMMY)), Position.DUMMY) + block.statements.add(directive) internedStringsModule.statements.add(block) _modules.add(0, internedStringsModule) @@ -92,12 +94,11 @@ class Program(val name: String, return Pair(listOf(internedStringsModuleName, decl.name), decl) } - val existingDecl = internedStringsBlock.statements.singleOrNull { - val declString = (it as VarDecl).value as StringLiteral + val existingDecl = internedStringsBlock.statements.filterIsInstance().singleOrNull { + val declString = it.value as StringLiteral declString.encoding == string.encoding && declString.value == string.value } return if (existingDecl != null) { - existingDecl as VarDecl internedStringsReferenceCounts[existingDecl] = internedStringsReferenceCounts.getValue(existingDecl)+1 existingDecl.scopedName } @@ -133,7 +134,7 @@ class Program(val name: String, .first { it.name == internedStringsModuleName }.statements .first { it is Block && it.name == internedStringsModuleName } as Block removals.forEach { scopedname -> - val decl = internedStringsBlock.statements.single { decl -> (decl as VarDecl).scopedName == scopedname } as VarDecl + val decl = internedStringsBlock.statements.filterIsInstance().single { decl -> decl.scopedName == scopedname } as VarDecl val numRefs = program.internedStringsReferenceCounts.getValue(decl) - 1 program.internedStringsReferenceCounts[decl] = numRefs if(numRefs==0) diff --git a/docs/source/syntaxreference.rst b/docs/source/syntaxreference.rst index 722c14955..e95daa9ec 100644 --- a/docs/source/syntaxreference.rst +++ b/docs/source/syntaxreference.rst @@ -130,6 +130,8 @@ Directives - ``align_page`` (in a block) will make the assembler align the start address of this block on a page boundary in memory (so, the LSB of the address is 0). - ``merge`` (in a block) will merge this block's contents into an already existing block with the same name. Useful in library scenarios. - ``splitarrays`` (block or module) makes all word-arrays in this scope lsb/msb split arrays (as if they all have the @split tag). See Arrays. + - ``no_symbol_prefixing`` (block) makes the compiler *not* use symbol-prefixing when translating prog8 code into assembly. + Only use this if you know what you're doing because it could result in invalid assembly code being generated. .. data:: %asmbinary "" [, [, ]] @@ -209,7 +211,7 @@ Directives If you use the correct scoping rules you can access symbols from the prog8 program from inside the assembly code. Sometimes you'll have to declare a variable in prog8 with `@shared` if it is only used in such assembly code. For symbols just consisting of 3 letters, prog8 will - add a special prefix to them, read more about this in :ref:`three-letter-prefixing`. + add a special prefix to them, read more about this in :ref:`symbol-prefixing`. Identifiers diff --git a/docs/source/technical.rst b/docs/source/technical.rst index de552d06e..77373c483 100644 --- a/docs/source/technical.rst +++ b/docs/source/technical.rst @@ -22,7 +22,7 @@ It is possible to relocate the BSS section using a compiler option so that more system ram is available for the program code itself. -.. _three-letter-prefixing: +.. _symbol-prefixing: Symbol prefixing in generated Assembly code ------------------------------------------- @@ -32,16 +32,16 @@ This is to avoid naming conflicts with CPU registers, assembly instructions, etc So if you're referencing symbols from the prog8 program in inlined assembly code, you have to take this into account. Stick a ``p8_`` in front of everything that you want to reference that is coming from a prog8 source file. +All elements in scoped names such as ``main.routine.var1`` are prefixed so this becomes ``p8_main.p8_routine.p8_var1``. .. attention:: - Many symbols from library modules are *not* prefixed. - - -**Exception** - -sdfasdf - + Symbols from library modules are *not* prefixed and can be used + in assembly code as-is. So you can write:: + %asm {{ + lda #'a' + jsr cbm.CHROUT + }} Software stack for expression evaluation diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 73f57a8cb..db28a8ee2 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -1,10 +1,7 @@ TODO ==== -- 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 +- fix type error with returning an array literal from a subroutine returning uword ... diff --git a/examples/c128/fpval.p8 b/examples/c128/fpval.p8 deleted file mode 100644 index 75c94e97a..000000000 --- a/examples/c128/fpval.p8 +++ /dev/null @@ -1,104 +0,0 @@ -%import textio -%import floats - -main { - sub start() { - - test_val() - - repeat { - } - } - - sub test_val() { - - ; TODO c128 how do I set this in "bank 1" ? VAL() needs that... - - str @shared value = "-1.23456" - uword @shared result - %asm {{ - stx P8ZP_SCRATCH_B1 - lda #value - sta $25 - lda #8 - jsr floats.VAL - jsr floats.FOUT - sta result - sty result+1 - ldx P8ZP_SCRATCH_B1 - }} - txt.print_uwhex(result, true) - txt.nl() - txt.print(result) - txt.nl() - txt.print($0100) - txt.nl() - } - - sub test_freadsa() { - uword @shared result - %asm {{ - stx P8ZP_SCRATCH_B1 - ;lda #-123 - ;jsr floats.FREADSA - lda #<55444 - ldy #>55444 - jsr floats.GIVUAYFAY - jsr floats.FOUT - sta result - sty result+1 - ldx P8ZP_SCRATCH_B1 - }} - txt.print_uwhex(result, true) - txt.nl() - txt.print(result) - txt.nl() - txt.print($0100) - txt.nl() - } - - sub test_getadr() { - uword @shared value - %asm {{ - stx P8ZP_SCRATCH_B1 - lda #<23456 - ldy #>23456 - jsr floats.GIVAYFAY - jsr floats.GETADRAY - sta value - sty value+1 - ldx P8ZP_SCRATCH_B1 - }} - txt.print_uw(value) - txt.nl() - } - - sub test_ayint() { - %asm {{ - stx P8ZP_SCRATCH_B1 - lda #<-23456 - ldy #>-23456 - jsr floats.GIVAYFAY - jsr floats.AYINT - ldx P8ZP_SCRATCH_B1 - }} - word value = mkword(@($66), @($67)) as word - txt.print_w(value) - txt.nl() - } - - sub test_printf() { - floats.print_f(0) - txt.nl() - floats.print_f(1) - txt.nl() - floats.print_f(-1) - txt.nl() - floats.print_f(floats.PI) - txt.nl() - floats.print_f(floats.TWOPI) - txt.nl() - } -} diff --git a/examples/cx16/colorbars.p8 b/examples/cx16/colorbars.p8 index 8c99fcd7c..38a66b101 100644 --- a/examples/cx16/colorbars.p8 +++ b/examples/cx16/colorbars.p8 @@ -87,14 +87,14 @@ irq { asmsub set_scanline_color(ubyte color_ix @Y) { ; uword color = mkword(reds[ix], (greens[ix] << 4) | blues[ix] ) %asm {{ - lda blinds_lines_reds,y + lda p8_blinds_lines_reds,y pha - lda blinds_lines_greens,y + lda p8_blinds_lines_greens,y asl a asl a asl a asl a - ora blinds_lines_blues,y + ora p8_blinds_lines_blues,y tay stz cx16.VERA_CTRL diff --git a/examples/cx16/keyboardhandler.p8 b/examples/cx16/keyboardhandler.p8 index ede7f157c..f53b3dd9c 100644 --- a/examples/cx16/keyboardhandler.p8 +++ b/examples/cx16/keyboardhandler.p8 @@ -66,12 +66,12 @@ main { %asm {{ pha - sta keyhdl_scancode + sta p8_keyhdl_scancode lda #1 - sta keyhdl_event + sta p8_keyhdl_event pla - lda #0 ; By setting A=0 we will eat this key event. leave A unchanged to pass it through. + lda #0 ; By setting A=0 we will eat this key event. leave A unchanged to pass it through. rts }} } diff --git a/examples/cx16/pcmaudio/stream-wav.p8 b/examples/cx16/pcmaudio/stream-wav.p8 index ca07d8293..19a2e9c31 100644 --- a/examples/cx16/pcmaudio/stream-wav.p8 +++ b/examples/cx16/pcmaudio/stream-wav.p8 @@ -148,9 +148,9 @@ interrupt { asmsub wait_and_clear_aflow_semaphore() { %asm {{ - wai - lda aflow_semaphore + lda p8_aflow_semaphore bne - - inc aflow_semaphore + inc p8_aflow_semaphore rts }} } @@ -182,9 +182,9 @@ interrupt { ; optimized loop to put 1024 bytes of data into the fifo as fast as possible ; converting unsigned wav 8 bit samples to signed 8 bit on the fly %asm {{ - lda main.start.buffer + lda p8_main.p8_start.p8_buffer sta cx16.r0L - lda main.start.buffer+1 + lda p8_main.p8_start.p8_buffer+1 sta cx16.r0H ldx #4 - ldy #0 @@ -212,9 +212,9 @@ interrupt { asmsub uncompressed_block_16() { ; optimized loop to put 1024 bytes of data into the fifo as fast as possible %asm {{ - lda main.start.buffer + lda p8_main.p8_start.p8_buffer sta cx16.r0L - lda main.start.buffer+1 + lda p8_main.p8_start.p8_buffer+1 sta cx16.r0H ldx #4 - ldy #0 diff --git a/examples/cx16/vtui/testvtui.p8 b/examples/cx16/vtui/testvtui.p8 index 1c47740a0..bce755ff2 100644 --- a/examples/cx16/vtui/testvtui.p8 +++ b/examples/cx16/vtui/testvtui.p8 @@ -110,6 +110,7 @@ char_loop: vtui $1000 { + %option no_symbol_prefixing %asmbinary "VTUI1.0.BIN", 2 ; skip the 2 dummy load address bytes ; NOTE: base address $1000 here must be the same as the block's memory address, for obvious reasons! diff --git a/examples/test.p8 b/examples/test.p8 index 3a5d7bca4..d750d0ca9 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -1,9 +1,11 @@ +%import textio +%zeropage basicsafe + main { + + romsub $FFD2 = chrout(ubyte ch @ A) sub start() { - str name1 = "name1" - str name2 = "name2" - uword[] @split names = [name1, name2, "name3"] - cx16.r0++ - names = [1111,2222,3333] + ubyte ch = '\n' + chrout(ch) } } diff --git a/examples/textelite.p8 b/examples/textelite.p8 index 7240f09a1..096b00c46 100644 --- a/examples/textelite.p8 +++ b/examples/textelite.p8 @@ -990,9 +990,9 @@ planet { sbc #$81 asl a tay - lda wordlists,y + lda p8_wordlists,y sta P8ZP_SCRATCH_W1 - lda wordlists+1,y + lda p8_wordlists+1,y sta P8ZP_SCRATCH_W1+1 lda P8ZP_SCRATCH_REG asl a