fixing up p8_ prefixing

This commit is contained in:
Irmen de Jong 2023-07-02 19:38:44 +02:00
parent bdf8aa9168
commit c544b7f5ba
15 changed files with 71 additions and 163 deletions

View File

@ -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<Pair<PtNode, Int>>() // parent + index
val functionCallsToPrefix = mutableListOf<Pair<PtNode, Int>>() // 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

View File

@ -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")

View File

@ -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

View File

@ -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)
}
})

View File

@ -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<VarDecl>().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<VarDecl>().single { decl -> decl.scopedName == scopedname } as VarDecl
val numRefs = program.internedStringsReferenceCounts.getValue(decl) - 1
program.internedStringsReferenceCounts[decl] = numRefs
if(numRefs==0)

View File

@ -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 "<filename>" [, <offset>[, <length>]]
@ -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

View File

@ -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

View File

@ -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
...

View File

@ -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 $24
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()
}
}

View File

@ -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

View File

@ -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
}}
}

View File

@ -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

View File

@ -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!

View File

@ -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)
}
}

View File

@ -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