mirror of
https://github.com/irmen/prog8.git
synced 2024-12-26 14:29:35 +00:00
fixing up p8_ prefixing
This commit is contained in:
parent
bdf8aa9168
commit
c544b7f5ba
@ -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,14 +134,18 @@ 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 -> {
|
||||
if(elt.definingBlock()?.noSymbolPrefixing==true)
|
||||
newValue.add(elt)
|
||||
else {
|
||||
val newAddr = PtAddressOf(elt.position)
|
||||
newAddr.children.add(elt.identifier.prefix(newAddr))
|
||||
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,10 +172,16 @@ 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 {
|
||||
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
|
||||
|
@ -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")
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
})
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
...
|
||||
|
||||
|
@ -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()
|
||||
}
|
||||
}
|
@ -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
|
||||
|
@ -66,9 +66,9 @@ 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.
|
||||
|
@ -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
|
||||
|
@ -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!
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user