labels no longer start with '_' fixes #62

This commit is contained in:
Irmen de Jong 2022-01-17 22:03:53 +01:00
parent 8966d2aa06
commit d916027e75
9 changed files with 57 additions and 116 deletions

View File

@ -3,10 +3,10 @@ package prog8.codegen.target.cbm
import com.github.michaelbull.result.Ok import com.github.michaelbull.result.Ok
import com.github.michaelbull.result.Result import com.github.michaelbull.result.Result
import com.github.michaelbull.result.mapError import com.github.michaelbull.result.mapError
import prog8.codegen.target.cpu6502.codegen.generatedLabelPrefix
import prog8.compilerinterface.CompilationOptions import prog8.compilerinterface.CompilationOptions
import prog8.compilerinterface.IAssemblyProgram import prog8.compilerinterface.IAssemblyProgram
import prog8.compilerinterface.OutputType import prog8.compilerinterface.OutputType
import prog8.compilerinterface.generatedLabelPrefix
import prog8.parser.SourceCode import prog8.parser.SourceCode
import java.io.File import java.io.File
import java.nio.file.Path import java.nio.file.Path

View File

@ -29,6 +29,11 @@ import kotlin.io.path.writeLines
import kotlin.math.absoluteValue import kotlin.math.absoluteValue
const val generatedLabelPrefix = "prog8_label_"
const val subroutineFloatEvalResultVar1 = "prog8_float_eval_result1"
const val subroutineFloatEvalResultVar2 = "prog8_float_eval_result2"
class AsmGen(private val program: Program, class AsmGen(private val program: Program,
val errors: IErrorReporter, val errors: IErrorReporter,
val zeropage: Zeropage, val zeropage: Zeropage,
@ -196,9 +201,9 @@ class AsmGen(private val program: Program,
out("* = ${program.actualLoadAddress.toHex()}") out("* = ${program.actualLoadAddress.toHex()}")
val year = LocalDate.now().year val year = LocalDate.now().year
out(" .word (+), $year") out(" .word (+), $year")
out(" .null $9e, format(' %d ', _prog8_entrypoint), $3a, $8f, ' prog8'") out(" .null $9e, format(' %d ', prog8_entrypoint), $3a, $8f, ' prog8'")
out("+\t.word 0") out("+\t.word 0")
out("_prog8_entrypoint\t; assembly code starts here\n") out("prog8_entrypoint\t; assembly code starts here\n")
if(!options.noSysInit) if(!options.noSysInit)
out(" jsr ${compTarget.name}.init_system") out(" jsr ${compTarget.name}.init_system")
out(" jsr ${compTarget.name}.init_system_phase2") out(" jsr ${compTarget.name}.init_system_phase2")
@ -620,34 +625,16 @@ class AsmGen(private val program: Program,
return identifier.nameInSource.joinToString(".") return identifier.nameInSource.joinToString(".")
val tgt2 = identifier.targetStatement(program) val tgt2 = identifier.targetStatement(program)
if (tgt2 == null && (identifier.nameInSource[0].startsWith("_prog8") || identifier.nameInSource[0].startsWith( if (tgt2 == null && (identifier.nameInSource[0].startsWith("prog8")))
"prog8"
))
)
return identifier.nameInSource.joinToString(".") return identifier.nameInSource.joinToString(".")
val target = identifier.targetStatement(program)!! val target = identifier.targetStatement(program)!!
val targetScope = target.definingSubroutine val targetScope = target.definingSubroutine
val identScope = identifier.definingSubroutine val identScope = identifier.definingSubroutine
return if (targetScope !== identScope) { return if (targetScope !== identScope)
val scopedName = (target as INamedStatement).scopedName fixNameSymbols((target as INamedStatement).scopedName.joinToString("."))
if (target is Label) { else
// make labels locally scoped in the asm. Is slightly problematic, see GitHub issue #62 fixNameSymbols(identifier.nameInSource.joinToString("."))
val newName = scopedName.dropLast(1) + ("_${scopedName.last()}")
fixNameSymbols(newName.joinToString("."))
}
else {
fixNameSymbols(scopedName.joinToString("."))
}
} else {
if (target is Label) {
// make labels locally scoped in the asm. Is slightly problematic, see GitHub issue #62
val scopedName = identifier.nameInSource.toMutableList()
val last = scopedName.removeLast()
scopedName.add("_$last")
fixNameSymbols(scopedName.joinToString("."))
} else fixNameSymbols(identifier.nameInSource.joinToString("."))
}
} }
return fixNameSymbols(internalName()) return fixNameSymbols(internalName())
@ -789,11 +776,11 @@ class AsmGen(private val program: Program,
out(" pha") out(" pha")
} }
CpuRegister.X -> { CpuRegister.X -> {
out(" stx _prog8_regsaveX") out(" stx prog8_regsaveX")
scope.asmGenInfo.usedRegsaveX = true scope.asmGenInfo.usedRegsaveX = true
} }
CpuRegister.Y -> { CpuRegister.Y -> {
out(" sty _prog8_regsaveY") out(" sty prog8_regsaveY")
scope.asmGenInfo.usedRegsaveY = true scope.asmGenInfo.usedRegsaveY = true
} }
} }
@ -836,8 +823,8 @@ class AsmGen(private val program: Program,
} else { } else {
when (register) { when (register) {
CpuRegister.A -> out(" pla") // this just used the stack but only for A CpuRegister.A -> out(" pla") // this just used the stack but only for A
CpuRegister.X -> out(" ldx _prog8_regsaveX") CpuRegister.X -> out(" ldx prog8_regsaveX")
CpuRegister.Y -> out(" ldy _prog8_regsaveY") CpuRegister.Y -> out(" ldy prog8_regsaveY")
} }
} }
} }
@ -1163,12 +1150,12 @@ class AsmGen(private val program: Program,
else -> throw AssemblyError("weird dt") else -> throw AssemblyError("weird dt")
} }
} }
if(sub.asmGenInfo.usedRegsaveA) if(sub.asmGenInfo.usedRegsaveA) // will probably never occur
out("_prog8_regsaveA .byte 0") out("prog8_regsaveA .byte 0")
if(sub.asmGenInfo.usedRegsaveX) if(sub.asmGenInfo.usedRegsaveX)
out("_prog8_regsaveX .byte 0") out("prog8_regsaveX .byte 0")
if(sub.asmGenInfo.usedRegsaveY) if(sub.asmGenInfo.usedRegsaveY)
out("_prog8_regsaveY .byte 0") out("prog8_regsaveY .byte 0")
if(sub.asmGenInfo.usedFloatEvalResultVar1) if(sub.asmGenInfo.usedFloatEvalResultVar1)
out("$subroutineFloatEvalResultVar1 .byte 0,0,0,0,0") out("$subroutineFloatEvalResultVar1 .byte 0,0,0,0,0")
if(sub.asmGenInfo.usedFloatEvalResultVar2) if(sub.asmGenInfo.usedFloatEvalResultVar2)
@ -1561,8 +1548,7 @@ $repeatLabel lda $counterVar
} }
private fun translate(stmt: Label) { private fun translate(stmt: Label) {
// underscore prefix to make sure it's a local label. Is slightly problematic, see GitHub issue #62 out(stmt.name)
out("_${stmt.name}")
} }
private fun translate(scope: AnonymousScope) { private fun translate(scope: AnonymousScope) {
@ -1636,6 +1622,9 @@ $repeatLabel lda $counterVar
"%breakpoint" -> { "%breakpoint" -> {
val label = "_prog8_breakpoint_${breakpointLabels.size+1}" val label = "_prog8_breakpoint_${breakpointLabels.size+1}"
breakpointLabels.add(label) breakpointLabels.add(label)
// TODO still need 2 nops to make 64tass generate correc breakpoint list for vice???
out(""" out("""
nop nop
$label nop""") $label nop""")

View File

@ -16,7 +16,7 @@ import prog8.codegen.target.cpu6502.codegen.assignment.*
import prog8.compilerinterface.BuiltinFunctions import prog8.compilerinterface.BuiltinFunctions
import prog8.compilerinterface.CpuType import prog8.compilerinterface.CpuType
import prog8.compilerinterface.FSignature import prog8.compilerinterface.FSignature
import prog8.compilerinterface.subroutineFloatEvalResultVar2
internal class BuiltinFunctionsAsmGen(private val program: Program, private val asmgen: AsmGen, private val assignAsmGen: AssignmentAsmGen) { internal class BuiltinFunctionsAsmGen(private val program: Program, private val asmgen: AsmGen, private val assignAsmGen: AssignmentAsmGen) {

View File

@ -163,7 +163,7 @@ graphics {
lda addr+1 lda addr+1
sta P8ZP_SCRATCH_W1+1 sta P8ZP_SCRATCH_W1+1
ldy separate_pixels ldy separate_pixels
lda _filled_right,y lda hline_filled_right,y
eor #255 eor #255
ldy #0 ldy #0
ora (P8ZP_SCRATCH_W1),y ora (P8ZP_SCRATCH_W1),y
@ -207,18 +207,18 @@ _modified stx $ffff ; modified
_zero ldx P8ZP_SCRATCH_REG _zero ldx P8ZP_SCRATCH_REG
ldy separate_pixels ldy separate_pixels
beq _zero2 beq hline_zero2
lda _modified+1 lda _modified+1
sta P8ZP_SCRATCH_W1 sta P8ZP_SCRATCH_W1
lda _modified+2 lda _modified+2
sta P8ZP_SCRATCH_W1+1 sta P8ZP_SCRATCH_W1+1
lda _filled_right,y lda hline_filled_right,y
ldy #0 ldy #0
ora (P8ZP_SCRATCH_W1),y ora (P8ZP_SCRATCH_W1),y
sta (P8ZP_SCRATCH_W1),y sta (P8ZP_SCRATCH_W1),y
jmp _zero2 jmp hline_zero2
_filled_right .byte 0, %10000000, %11000000, %11100000, %11110000, %11111000, %11111100, %11111110 hline_filled_right .byte 0, %10000000, %11000000, %11100000, %11110000, %11111000, %11111100, %11111110
_zero2 hline_zero2
}} }}
} }
} }

View File

@ -242,18 +242,18 @@ close_end:
void c64.CHKIN(11) ; use #11 as input channel again void c64.CHKIN(11) ; use #11 as input channel again
%asm {{ %asm {{
lda bufferpointer lda bufferpointer
sta _in_buffer+1 sta m_in_buffer+1
lda bufferpointer+1 lda bufferpointer+1
sta _in_buffer+2 sta m_in_buffer+2
}} }}
repeat num_bytes { repeat num_bytes {
%asm {{ %asm {{
jsr c64.CHRIN jsr c64.CHRIN
sta cx16.r5 sta cx16.r5
_in_buffer sta $ffff m_in_buffer sta $ffff
inc _in_buffer+1 inc m_in_buffer+1
bne + bne +
inc _in_buffer+2 inc m_in_buffer+2
+ inc list_blocks + inc list_blocks
bne + bne +
inc list_blocks+1 inc list_blocks+1

View File

@ -1,6 +1,5 @@
package prog8tests.codegeneration package prog8tests.codegeneration
import io.kotest.assertions.withClue
import io.kotest.core.spec.style.StringSpec import io.kotest.core.spec.style.StringSpec
import io.kotest.matchers.shouldBe import io.kotest.matchers.shouldBe
import prog8.ast.Module import prog8.ast.Module
@ -121,28 +120,20 @@ class TestAsmGenSymbols: StringSpec({
// local label // local label
val localLabelIdent = (sub.statements.asSequence().filterIsInstance<Assignment>().first { (it.value as? AddressOf)?.identifier?.nameInSource==listOf("locallabel") }.value as AddressOf).identifier val localLabelIdent = (sub.statements.asSequence().filterIsInstance<Assignment>().first { (it.value as? AddressOf)?.identifier?.nameInSource==listOf("locallabel") }.value as AddressOf).identifier
asmgen.asmSymbolName(localLabelIdent) shouldBe "_locallabel" asmgen.asmSymbolName(localLabelIdent) shouldBe "locallabel"
withClue("as a variable it uses different naming rules (no underscore prefix)") {
asmgen.asmVariableName(localLabelIdent) shouldBe "locallabel" asmgen.asmVariableName(localLabelIdent) shouldBe "locallabel"
}
val localLabelIdentScoped = (sub.statements.asSequence().filterIsInstance<Assignment>().first { (it.value as? AddressOf)?.identifier?.nameInSource==listOf("main","start","locallabel") }.value as AddressOf).identifier val localLabelIdentScoped = (sub.statements.asSequence().filterIsInstance<Assignment>().first { (it.value as? AddressOf)?.identifier?.nameInSource==listOf("main","start","locallabel") }.value as AddressOf).identifier
asmgen.asmSymbolName(localLabelIdentScoped) shouldBe "main.start._locallabel" asmgen.asmSymbolName(localLabelIdentScoped) shouldBe "main.start.locallabel"
withClue("as a variable it uses different naming rules (no underscore prefix)") {
asmgen.asmVariableName(localLabelIdentScoped) shouldBe "main.start.locallabel" asmgen.asmVariableName(localLabelIdentScoped) shouldBe "main.start.locallabel"
}
// label from outer scope needs sope prefixes because it is outputted as a locally scoped symbol for the assembler // label from outer scope needs sope prefixes because it is outputted as a locally scoped symbol for the assembler
val scopedLabelIdent = (sub.statements.asSequence().filterIsInstance<Assignment>().first { (it.value as? AddressOf)?.identifier?.nameInSource==listOf("label_outside") }.value as AddressOf).identifier val scopedLabelIdent = (sub.statements.asSequence().filterIsInstance<Assignment>().first { (it.value as? AddressOf)?.identifier?.nameInSource==listOf("label_outside") }.value as AddressOf).identifier
asmgen.asmSymbolName(scopedLabelIdent) shouldBe "main._label_outside" asmgen.asmSymbolName(scopedLabelIdent) shouldBe "main.label_outside"
withClue("as a variable it uses different naming rules (no underscore prefix)") {
asmgen.asmVariableName(scopedLabelIdent) shouldBe "label_outside" asmgen.asmVariableName(scopedLabelIdent) shouldBe "label_outside"
}
val scopedLabelIdentScoped = (sub.statements.asSequence().filterIsInstance<Assignment>().first { (it.value as? AddressOf)?.identifier?.nameInSource==listOf("main","label_outside") }.value as AddressOf).identifier val scopedLabelIdentScoped = (sub.statements.asSequence().filterIsInstance<Assignment>().first { (it.value as? AddressOf)?.identifier?.nameInSource==listOf("main","label_outside") }.value as AddressOf).identifier
asmgen.asmSymbolName(scopedLabelIdentScoped) shouldBe "main._label_outside" asmgen.asmSymbolName(scopedLabelIdentScoped) shouldBe "main.label_outside"
withClue("as a variable it uses different naming rules (no underscore prefix)") {
asmgen.asmVariableName(scopedLabelIdentScoped) shouldBe "main.label_outside" asmgen.asmVariableName(scopedLabelIdentScoped) shouldBe "main.label_outside"
} }
}
"asm names for hooks to zp temp vars" { "asm names for hooks to zp temp vars" {
/* /*

View File

@ -4,10 +4,6 @@ interface IAssemblyGenerator {
fun compileToAssembly(): IAssemblyProgram fun compileToAssembly(): IAssemblyProgram
} }
const val generatedLabelPrefix = "_prog8_label_"
const val subroutineFloatEvalResultVar1 = "_prog8_float_eval_result1"
const val subroutineFloatEvalResultVar2 = "_prog8_float_eval_result2"
interface IAssemblyProgram { interface IAssemblyProgram {
val valid: Boolean val valid: Boolean
val name: String val name: String

View File

@ -3,7 +3,8 @@ TODO
For next compiler release (7.7) For next compiler release (7.7)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
... check AsmGen translate(stmt: Directive) breakpoint nop issue
Need help with Need help with
^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^
@ -25,7 +26,6 @@ Future Things and Ideas
- for the pipe operator: recognise a placeholder (``?`` or ``%`` or ``_``) in a non-unary function call to allow things as ``4 |> mkword(?, $44) |> print_uw`` - for the pipe operator: recognise a placeholder (``?`` or ``%`` or ``_``) in a non-unary function call to allow things as ``4 |> mkword(?, $44) |> print_uw``
- make it possible to use cpu opcodes such as 'nop' as variable names by prefixing all asm vars with something such as ``v_`` - make it possible to use cpu opcodes such as 'nop' as variable names by prefixing all asm vars with something such as ``v_``
then we can get rid of the instruction lists in the machinedefinitions as well? then we can get rid of the instruction lists in the machinedefinitions as well?
- fix the asm-labels problem (github issue #62)
- make it possible to inline non-asmsub routines that just contain a single statement (return, functioncall, assignment) - make it possible to inline non-asmsub routines that just contain a single statement (return, functioncall, assignment)
but this requires all identifiers in the inlined expression to be changed to fully scoped names but this requires all identifiers in the inlined expression to be changed to fully scoped names
- simplifyConditionalExpression() should not split expression if it still results in stack-based evaluation - simplifyConditionalExpression() should not split expression if it still results in stack-based evaluation

View File

@ -1,51 +1,16 @@
%import textio %import textio
%import test_stack
main { main {
%option force_output str myBar = "main.bar"
foo_bar:
%asm {{
nop
}}
sub start() { sub start() {
test_stack.test() txt.print(myBar)
uword ww = 10 txt.print(&foo_bar)
repeat 10 { return
ww++
txt.print_uw(ww)
txt.nl()
}
test_stack.test()
repeat {
}
} }
} }
;main {
; sub start() {
; %asm {{
; lda #<float5_111
; ldy #>float5_111
; jsr floats.MOVFM
; lda #<float5_122
; ldy #>float5_122
; jsr floats.FADD
; jsr floats.FOUT
; sta $7e
; sty $7f
; ldy #64
;_loop
; lda ($7e),y
; beq _done
; jsr c64.CHROUT
; iny
; bne _loop
;_done
; rts
;
;float5_111 .byte $81, $64e, $14, $7a, $e1 ; float 1.11
;float5_122 .byte $81, $1c, $28, $f5, $c2 ; float 1.22
;
; }}
; }
;
;}