uniform symbol prefixing with p8_

This commit is contained in:
Irmen de Jong 2023-06-30 00:29:50 +02:00
parent 0f6a98751a
commit cad18b8a3a
41 changed files with 176 additions and 180 deletions

View File

@ -63,7 +63,9 @@ class PtProgram(
children.asSequence().filterIsInstance<PtBlock>()
fun entrypoint(): PtSub? =
allBlocks().firstOrNull { it.name == "main" }?.children?.firstOrNull { it is PtSub && (it.name == "start" || it.name=="main.start") } as PtSub?
allBlocks().firstOrNull { it.name == "main" || it.name=="p8_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?
}

View File

@ -33,8 +33,9 @@ internal class ProgramAndVarsGen(
internal fun generate() {
header()
val allBlocks = program.allBlocks()
if(allBlocks.first().name != "main")
throw AssemblyError("first block should be 'main'")
if(allBlocks.first().name != "p8_main" && allBlocks.first().name != "main")
throw AssemblyError("first block should be 'main' or 'p8_main'")
if(errors.noErrors()) {
program.allBlocks().forEach { block2asm(it) }
@ -139,24 +140,24 @@ internal class ProgramAndVarsGen(
"cx16" -> {
if(options.floats)
asmgen.out(" lda #4 | sta $01") // to use floats, make sure Basic rom is banked in
asmgen.out(" jsr main.start")
asmgen.out(" jsr p8_main.p8_start")
asmgen.out(" jmp sys.cleanup_at_exit")
}
"c64" -> {
asmgen.out(" jsr main.start | lda #31 | sta $01")
asmgen.out(" jsr p8_main.p8_start | lda #31 | sta $01")
if(!options.noSysInit)
asmgen.out(" jmp sys.cleanup_at_exit")
else
asmgen.out(" rts")
}
"c128" -> {
asmgen.out(" jsr main.start | lda #0 | sta ${"$"}ff00")
asmgen.out(" jsr p8_main.p8_start | lda #0 | sta ${"$"}ff00")
if(!options.noSysInit)
asmgen.out(" jmp sys.cleanup_at_exit")
else
asmgen.out(" rts")
}
else -> asmgen.jmp("main.start")
else -> asmgen.jmp("p8_main.p8_start")
}
}
@ -332,7 +333,7 @@ internal class ProgramAndVarsGen(
asmsubs2asm(sub.children)
// the main.start subroutine is the program's entrypoint and should perform some initialization logic
if(sub.name=="start" && sub.definingBlock()!!.name=="main")
if((sub.name=="start" || sub.name=="p8_start") && (sub.definingBlock()!!.name=="main" || sub.definingBlock()!!.name=="p8_main"))
entrypointInitialization()
if(functioncallAsmGen.optimizeIntArgsViaRegisters(sub)) {

View File

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

View File

@ -2,6 +2,7 @@
; Including memory registers, I/O registers, Basic and Kernal subroutines.
atari {
%option no_symbol_prefixing
&uword NMI_VEC = $FFFA ; 6502 nmi vector, determined by the kernal if banked in
&uword RESET_VEC = $FFFC ; 6502 reset vector, determined by the kernal if banked in
@ -9,10 +10,11 @@ atari {
}
sys {
; ------- lowlevel system routines --------
%option no_symbol_prefixing
const ubyte target = 8 ; compilation target specifier. 64 = C64, 128 = C128, 16 = CommanderX16, 8 = atari800XL
asmsub init_system() {
@ -216,6 +218,7 @@ _longcopy
}
cx16 {
%option no_symbol_prefixing
; the sixteen virtual 16-bit registers that the CX16 has defined in the zeropage
; they are simulated on the Atari as well but their location in memory is different

View File

@ -6,6 +6,8 @@
txt {
%option no_symbol_prefixing
const ubyte DEFAULT_WIDTH = 40
const ubyte DEFAULT_HEIGHT = 24

View File

@ -6,6 +6,8 @@
; TODO c128 actually implement the graphics routines. Ideally a way to 'borrow' the code form the C64 version without just copy-pasting that here?
graphics {
%option no_symbol_prefixing
const uword WIDTH = 320
const ubyte HEIGHT = 200

View File

@ -3,6 +3,7 @@
cbm {
; Commodore (CBM) common variables, vectors and kernal routines
%option no_symbol_prefixing
&ubyte TIME_HI = $a0 ; software jiffy clock, hi byte
&ubyte TIME_MID = $a1 ; .. mid byte
@ -140,6 +141,7 @@ asmsub RDTIM16() -> uword @AY {
c64 {
; C64 I/O registers (VIC, SID, CIA)
%option no_symbol_prefixing
; the default locations of the 8 sprite pointers (store address of sprite / 64)
&ubyte SPRPTR0 = 2040
@ -294,6 +296,7 @@ c64 {
c128 {
; ---- C128 specific registers ----
%option no_symbol_prefixing
&ubyte VM1 = $0A2C ; shadow for VUC $d018 in text mode
&ubyte VM2 = $0A2D ; shadow for VIC $d018 in bitmap screen mode
@ -330,6 +333,7 @@ asmsub disable_basic() clobbers(A) {
sys {
; ------- lowlevel system routines --------
%option no_symbol_prefixing
const ubyte target = 128 ; compilation target specifier. 64 = C64, 128 = C128, 16 = CommanderX16.
@ -765,6 +769,7 @@ _longcopy
}
cx16 {
%option no_symbol_prefixing
; the sixteen virtual 16-bit registers that the CX16 has defined in the zeropage
; they are simulated on the C128 as well but their location in memory is different

View File

@ -5,6 +5,7 @@
txt {
%option no_symbol_prefixing
const ubyte DEFAULT_WIDTH = 40
const ubyte DEFAULT_HEIGHT = 25

View File

@ -5,6 +5,7 @@
floats {
; ---- this block contains C-64 floating point related functions ----
%option no_symbol_prefixing
const float PI = 3.141592653589793
const float TWOPI = 6.283185307179586

View File

@ -5,6 +5,8 @@
; assumes bitmap screen memory is $2000-$3fff
graphics {
%option no_symbol_prefixing
const uword BITMAP_ADDRESS = $2000
const uword WIDTH = 320
const ubyte HEIGHT = 200

View File

@ -6,6 +6,8 @@ cbm {
; Commodore (CBM) common variables, vectors and kernal routines
%option no_symbol_prefixing
&ubyte TIME_HI = $a0 ; software jiffy clock, hi byte
&ubyte TIME_MID = $a1 ; .. mid byte
&ubyte TIME_LO = $a2 ; .. lo byte. Updated by IRQ every 1/60 sec
@ -139,6 +141,8 @@ asmsub RDTIM16() -> uword @AY {
c64 {
; C64 I/O registers (VIC, SID, CIA)
%option no_symbol_prefixing
; the default locations of the 8 sprite pointers (store address of sprite / 64)
&ubyte SPRPTR0 = 2040
&ubyte SPRPTR1 = 2041
@ -293,6 +297,8 @@ c64 {
sys {
; ------- lowlevel system routines --------
%option no_symbol_prefixing
const ubyte target = 64 ; compilation target specifier. 64 = C64, 128 = C128, 16 = CommanderX16.
@ -732,6 +738,8 @@ _longcopy
cx16 {
%option no_symbol_prefixing
; the sixteen virtual 16-bit registers that the CX16 has defined in the zeropage
; they are simulated on the C64 as well but their location in memory is different
; (because there's no room for them in the zeropage)

View File

@ -6,6 +6,8 @@
txt {
%option no_symbol_prefixing
const ubyte DEFAULT_WIDTH = 40
const ubyte DEFAULT_HEIGHT = 25

View File

@ -2,6 +2,8 @@
conv {
%option no_symbol_prefixing
; ----- number conversions to decimal strings ----
str @shared string_out = "????????????????" ; result buffer for the string conversion routines

View File

@ -6,6 +6,7 @@
%import syslib
diskio {
%option no_symbol_prefixing
ubyte drivenumber = 8

View File

@ -6,6 +6,8 @@
floats {
; ---- this block contains C-64 compatible floating point related functions ----
%option no_symbol_prefixing
const float PI = 3.141592653589793
const float TWOPI = 6.283185307179586

View File

@ -23,6 +23,8 @@
gfx2 {
%option no_symbol_prefixing
; read-only control variables:
ubyte active_mode = 0
uword width = 0

View File

@ -10,6 +10,8 @@
graphics {
%option no_symbol_prefixing
const uword WIDTH = 320
const ubyte HEIGHT = 240

View File

@ -2,9 +2,10 @@
; Should you want to restore the default palette, you have to reinitialize the Vera yourself.
palette {
%option no_symbol_prefixing
uword vera_palette_ptr
ubyte c
ubyte cc
sub set_color(ubyte index, uword color) {
vera_palette_ptr = $fa00+(index as uword * 2)
@ -79,13 +80,13 @@ palette {
sub set_grayscale() {
vera_palette_ptr = $fa00
repeat 16 {
c=0
cc=0
repeat 16 {
cx16.vpoke(1, vera_palette_ptr, c)
cx16.vpoke(1, vera_palette_ptr, cc)
vera_palette_ptr++
cx16.vpoke(1, vera_palette_ptr, c)
cx16.vpoke(1, vera_palette_ptr, cc)
vera_palette_ptr++
c += $11
cc += $11
}
}
}
@ -150,11 +151,11 @@ palette {
sub set_c64pepto() {
vera_palette_ptr = $fa00
repeat 16 {
for c in 0 to 15 {
uword cc = C64_colorpalette_pepto[c]
cx16.vpoke(1, vera_palette_ptr, lsb(cc)) ; G, B
for cc in 0 to 15 {
uword ccp = C64_colorpalette_pepto[cc]
cx16.vpoke(1, vera_palette_ptr, lsb(ccp)) ; G, B
vera_palette_ptr++
cx16.vpoke(1, vera_palette_ptr, msb(cc)) ; R
cx16.vpoke(1, vera_palette_ptr, msb(ccp)) ; R
vera_palette_ptr++
}
}
@ -163,11 +164,11 @@ palette {
sub set_c64light() {
vera_palette_ptr = $fa00
repeat 16 {
for c in 0 to 15 {
uword cc = C64_colorpalette_light[c]
cx16.vpoke(1, vera_palette_ptr, lsb(cc)) ; G, B
for cc in 0 to 15 {
uword ccp = C64_colorpalette_light[cc]
cx16.vpoke(1, vera_palette_ptr, lsb(ccp)) ; G, B
vera_palette_ptr++
cx16.vpoke(1, vera_palette_ptr, msb(cc)) ; R
cx16.vpoke(1, vera_palette_ptr, msb(ccp)) ; R
vera_palette_ptr++
}
}
@ -176,11 +177,11 @@ palette {
sub set_c64dark() {
vera_palette_ptr = $fa00
repeat 16 {
for c in 0 to 15 {
uword cc = C64_colorpalette_dark[c]
cx16.vpoke(1, vera_palette_ptr, lsb(cc)) ; G, B
for cc in 0 to 15 {
uword ccp = C64_colorpalette_dark[cc]
cx16.vpoke(1, vera_palette_ptr, lsb(ccp)) ; G, B
vera_palette_ptr++
cx16.vpoke(1, vera_palette_ptr, msb(cc)) ; R
cx16.vpoke(1, vera_palette_ptr, msb(ccp)) ; R
vera_palette_ptr++
}
}

View File

@ -1,6 +1,8 @@
%import syslib
psg {
%option no_symbol_prefixing
; $1F9C0 - $1F9FF 16 blocks of 4 PSG registers (16 voices)
; 00 frequency word LSB
; 01 frequency word MSB. freqword = HERZ / 0.3725290298461914

View File

@ -5,6 +5,8 @@ cbm {
; Commodore (CBM) common variables, vectors and kernal routines
%option no_symbol_prefixing
; STROUT --> use txt.print
; CLEARSCR -> use txt.clear_screen
; HOMECRSR -> use txt.home or txt.plot
@ -88,6 +90,8 @@ asmsub RDTIM16() -> uword @AY {
cx16 {
%option no_symbol_prefixing
; irq, system and hardware vectors:
&uword IERROR = $0300
&uword IMAIN = $0302
@ -710,6 +714,8 @@ asmsub restore_vera_context() clobbers(A) {
sys {
; ------- lowlevel system routines --------
%option no_symbol_prefixing
const ubyte target = 16 ; compilation target specifier. 64 = C64, 128 = C128, 16 = CommanderX16.
asmsub init_system() {

View File

@ -6,6 +6,8 @@
txt {
%option no_symbol_prefixing
const ubyte DEFAULT_WIDTH = 80
const ubyte DEFAULT_HEIGHT = 60

View File

@ -3,6 +3,8 @@
%import textio
cx16logo {
%option no_symbol_prefixing
sub logo_at(ubyte column, ubyte row) {
uword strptr
for strptr in logo_lines {

View File

@ -5,6 +5,7 @@
%import syslib
diskio {
%option no_symbol_prefixing
ubyte drivenumber = 8

View File

@ -1,6 +1,6 @@
floats {
; the floating point functions shared across compiler targets
%option merge
%option merge, no_symbol_prefixing
sub print_f(float value) {
; ---- prints the floating point value (without a newline).

View File

@ -1,6 +1,8 @@
; Internal Math library routines - always included by the compiler
math {
%option no_symbol_prefixing
%asminclude "library:math.asm"
asmsub sin8u(ubyte angle @A) clobbers(Y) -> ubyte @A {

View File

@ -1,6 +1,8 @@
; Internal library routines - always included by the compiler
prog8_lib {
%option no_symbol_prefixing
%asminclude "library:prog8_lib.asm"
%asminclude "library:prog8_funcs.asm"
}

View File

@ -1,6 +1,7 @@
; 0-terminated string manipulation routines.
string {
%option no_symbol_prefixing
asmsub length(uword string @AY) clobbers(A) -> ubyte @Y {
; Returns the number of bytes in the string.

View File

@ -3,6 +3,7 @@
%import textio
test_stack {
%option no_symbol_prefixing
asmsub test() {
%asm {{

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 = 3907
const val GIT_SHA = "c9ef777e0f15922c06921c16e794576d3146b1c0"
const val GIT_DATE = "2023-06-28T21:24:48Z"
const val GIT_BRANCH = "master"
const val BUILD_DATE = "2023-06-29T18:58:57Z"
const val BUILD_UNIX_TIME = 1688065137839L
const val GIT_REVISION = 3909
const val GIT_SHA = "04da44eb988e4c2abef4099f86888b95074cc453"
const val GIT_DATE = "2023-06-29T20:56:26Z"
const val GIT_BRANCH = "prefixing"
const val BUILD_DATE = "2023-06-29T21:18:59Z"
const val BUILD_UNIX_TIME = 1688073539609L
const val DIRTY = 1

View File

@ -1,49 +0,0 @@
package prog8.compiler.astprocessing
import prog8.ast.statements.Block
import prog8.ast.statements.Label
import prog8.ast.statements.Subroutine
import prog8.ast.statements.VarDecl
import prog8.ast.walk.IAstVisitor
import prog8.code.core.ICompilationTarget
import prog8.code.target.VMTarget
class AsmInstructionNamesFinder(val target: ICompilationTarget): IAstVisitor {
val blocks = mutableSetOf<Block>()
val variables = mutableSetOf<VarDecl>()
val labels = mutableSetOf<Label>()
val subroutines = mutableSetOf<Subroutine>()
private fun isPossibleConfusingAsmName(name: String) = (name.length==3 || name.length==1) && name.all { it.isLetter() }
fun foundAny(): Boolean = blocks.isNotEmpty() || variables.isNotEmpty() || subroutines.isNotEmpty() || labels.isNotEmpty()
override fun visit(block: Block) {
if(target.name!=VMTarget.NAME && !block.isInLibrary && isPossibleConfusingAsmName(block.name)) {
blocks += block
}
super.visit(block)
}
override fun visit(decl: VarDecl) {
if(target.name!=VMTarget.NAME && !decl.definingModule.isLibrary && isPossibleConfusingAsmName(decl.name)) {
variables += decl
}
super.visit(decl)
}
override fun visit(label: Label) {
if(target.name!=VMTarget.NAME && !label.definingModule.isLibrary && isPossibleConfusingAsmName(label.name)) {
labels += label
}
super.visit(label)
}
override fun visit(subroutine: Subroutine) {
if(target.name!=VMTarget.NAME && !subroutine.definingModule.isLibrary && isPossibleConfusingAsmName(subroutine.name)) {
subroutines += subroutine
}
super.visit(subroutine)
}
}

View File

@ -7,60 +7,65 @@ import prog8.ast.statements.*
import prog8.ast.walk.AstWalker
import prog8.ast.walk.IAstModification
class AsmInstructionNamesReplacer(
val program: Program,
val blocks: Set<Block>,
val subroutines: Set<Subroutine>,
val variables: Set<VarDecl>,
val labels: Set<Label>): AstWalker() {
class AsmSymbolsPrefixer(val program: Program): AstWalker() {
override fun after(identifier: IdentifierReference, parent: Node): Iterable<IAstModification> {
if(identifier.nameInSource.size>1) {
val tgt = identifier.targetStatement(program)
if(tgt==null || tgt.definingModule.isLibrary)
return noModifications
}
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 { ident ->
if((ident.length==3 || ident.length==1) && !identifier.definingModule.isLibrary) {
val blockTarget = blocks.firstOrNull { it.name==ident }
val subTarget = subroutines.firstOrNull {it.name==ident }
val varTarget = variables.firstOrNull { it.name==ident }
val labelTarget = labels.firstOrNull { it.name==ident}
if(blockTarget!=null || subTarget!=null || varTarget!=null || labelTarget!=null) {
"p8p_$ident"
} else
ident
} else
ident
}
return if(newName!=identifier.nameInSource)
listOf(IAstModification.ReplaceNode(identifier, IdentifierReference(newName, identifier.position), parent))
else
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(label in labels)
listOf(IAstModification.ReplaceNode(label, Label("p8p_${label.name}", label.position), parent))
else
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(block in blocks)
listOf(IAstModification.ReplaceNode(block, Block("p8p_${block.name}", block.address, block.statements, block.isInLibrary, block.position), parent))
else
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(decl in variables)
listOf(IAstModification.ReplaceNode(decl, decl.renamed("p8p_${decl.name}"), parent))
else
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>()
@ -80,30 +85,4 @@ class AsmInstructionNamesReplacer(
}
return count
}
override fun after(subroutine: Subroutine, parent: Node): Iterable<IAstModification> {
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("p8p_${param.name}", param.type, param.position))
}
}
changedParams.forEach { (index, newParam) -> subroutine.parameters[index] = newParam }
val newName = if(subroutine in subroutines) "p8p_${subroutine.name}" else 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
}
}
}

View File

@ -24,14 +24,16 @@ 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" }.map { it as Block }
val mainBlocks = program.modules.flatMap { it.statements }.filter { b -> b is Block && (b.name=="main" || b.name=="p8_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) {
val startSub = mainBlock.subScope("start") as? Subroutine
var startSub = mainBlock.subScope("start") as? Subroutine
if(startSub==null)
startSub = mainBlock.subScope("p8_start") as? Subroutine
if (startSub == null) {
errors.err("missing program entrypoint ('start' subroutine in 'main' block)", mainBlock.position)
} else {
@ -812,7 +814,7 @@ internal class AstChecker(private val program: Program,
err("this directive may only occur in a block or at module level")
if(directive.args.isEmpty())
err("missing option directive argument(s)")
else if(directive.args.map{it.name in arrayOf("enable_floats", "force_output", "no_sysinit", "align_word", "align_page", "merge", "splitarrays")}.any { !it })
else if(directive.args.map{it.name in arrayOf("enable_floats", "force_output", "no_sysinit", "align_word", "align_page", "merge", "splitarrays", "no_symbol_prefixing")}.any { !it })
err("invalid option directive argument(s)")
}
else -> throw SyntaxError("invalid directive ${directive.directive}", directive.position)

View File

@ -29,18 +29,9 @@ internal fun Program.processAstBeforeAsmGeneration(compilerOptions: CompilationO
boolRemover.applyModifications()
if(compilerOptions.compTarget.name!=VMTarget.NAME) {
val finder = AsmInstructionNamesFinder(compilerOptions.compTarget)
finder.visit(this)
if(finder.foundAny()) {
val replacer = AsmInstructionNamesReplacer(
this,
finder.blocks,
finder.subroutines,
finder.variables,
finder.labels)
replacer.visit(this)
replacer.applyModifications()
}
val replacer = AsmSymbolsPrefixer(this)
replacer.visit(this)
replacer.applyModifications()
}
val fixer = BeforeAsmAstChanger(this, compilerOptions, errors)

View File

@ -168,7 +168,7 @@ class IntermediateAstMaker(private val program: Program, private val options: Co
"align_word" -> alignment = PtBlock.BlockAlignment.WORD
"align_page" -> alignment = PtBlock.BlockAlignment.PAGE
"force_output" -> forceOutput=true
"merge", "splitarrays" -> { /* ignore this one */ }
"merge", "splitarrays", "no_symbol_prefixing" -> { /* ignore this one */ }
else -> throw FatalAstException("weird directive option: ${arg.name}")
}
}

View File

@ -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<Block>().firstOrNull { it.name=="main" }
val mainBlock = module.statements.asSequence().filterIsInstance<Block>().firstOrNull { it.name=="main" || it.name=="p8_main"}
if(mainBlock!=null && mainBlock.address==null) {
module.statements.remove(mainBlock)
module.statements.add(0, mainBlock)

View File

@ -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("bb")
(expr2.left as IdentifierReference).nameInSource shouldBe listOf("p8_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("ub1")
assignValue1.nameInSource shouldBe listOf("p8_ub1")
assignValue2.operator shouldBe "^"
assignValue3.operator shouldBe "&"
val right2 = assignValue2.right as BinaryExpression

View File

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

View File

@ -932,7 +932,7 @@ data class IdentifierReference(val nameInSource: List<String>, override val posi
fun targetSubroutine(program: Program): Subroutine? = targetStatement(program) as? Subroutine
fun targetNameAndType(program: Program): Pair<String, DataType> {
val target=targetStatement(program)!! as INamedStatement
val target = targetStatement(program) as? INamedStatement ?: throw FatalAstException("can't find target for $nameInSource")
val targetname: String = if(target.name in program.builtinFunctions.names)
"<builtin>.${target.name}"
else
@ -985,6 +985,8 @@ data class IdentifierReference(val nameInSource: List<String>, override val posi
val scope=decl.definingModule
return scope.name==internedStringsModuleName
}
fun renamed(newName: List<String>): IdentifierReference = IdentifierReference(newName, position)
}
class FunctionCallExpression(override var target: IdentifierReference,

View File

@ -94,6 +94,7 @@ class Block(override val name: String,
override fun referencesIdentifier(nameInSource: List<String>): Boolean = statements.any { it.referencesIdentifier(nameInSource) }
fun options() = statements.filter { it is Directive && it.directive == "%option" }.flatMap { (it as Directive).args }.map {it.name!!}.toSet()
fun renamed(newName: String): Block = Block(newName, address, statements, isInLibrary, position)
}
data class Directive(val directive: String, val args: List<DirectiveArg>, override val position: Position) : Statement() {
@ -135,6 +136,7 @@ data class Label(override val name: String, override val position: Position) : S
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent)
override fun toString()= "Label(name=$name, pos=$position)"
fun renamed(newName: String): Label = Label(newName, position)
}
class Return(var value: Expression?, override val position: Position) : Statement() {

View File

@ -24,18 +24,24 @@ so that more system ram is available for the program code itself.
.. _three-letter-prefixing:
Three-letter symbols prefixing in Assembly
------------------------------------------
Symbol prefixing in generated Assembly code
-------------------------------------------
*All* symbols in the prog8 program will be prefixed with ``p8_`` in the generated assembly code.
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.
.. attention::
Many symbols from library modules are *not* prefixed.
**Exception**
sdfasdf
Symbols consisting of three letters such as "brk" or "tax", or variables named "a", "x" or "y" could
confuse the assembler to think these are cpu instructions or registers.
It will likely fail to assemble the program correctly.
Because of this, prog8 will prefix every 1- and 3-letter symbol with "``p8p_``" automatically during compilation.
So "tax" will become "p8p_tax", "a" will become "p8p_a" in the resulting assembly code.
If you're referencing symbols from the prog8 program in hand-written assembly code, you have to take
this into account. Either prefix the 1- and 3-letter symbols in the assembly with "``p8p_``" as well, or just
choose a symbol name of a different length in the first place.
Software stack for expression evaluation

View File

@ -1,6 +1,8 @@
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.
EXCEPTION: library symbols such as cbm.CHROUT, cx16.r0 etc. should NOT be prefixed.
Solution: add %option no_symbol_prefix to those blocks?