- ir codegen now allows subroutine having the same name as its block

this is not possible for the 6502 codegen due to 64tass scoping limitation
This commit is contained in:
Irmen de Jong 2022-11-28 19:22:35 +01:00
parent 3c698f1584
commit b8fb391022
13 changed files with 87 additions and 81 deletions

View File

@ -16,6 +16,7 @@ interface IMachineDefinition {
var ESTACK_LO: UInt
var ESTACK_HI: UInt
val PROGRAM_LOAD_ADDRESS : UInt
var GOLDEN: UIntRange
val opcodeNames: Set<String>
var zeropage: Zeropage
@ -31,5 +32,7 @@ interface IMachineDefinition {
require(evalStackBaseAddress and 255u == 0u)
ESTACK_LO = evalStackBaseAddress
ESTACK_HI = evalStackBaseAddress + 256u
require(ESTACK_LO !in GOLDEN && ESTACK_HI !in GOLDEN) { "user-set ESTACK can't be in GOLDEN ram" }
}
}

View File

@ -17,6 +17,7 @@ class AtariMachineDefinition: IMachineDefinition {
// the 2*256 byte evaluation stack (on which bytes, words, and even floats are stored during calculations)
override var ESTACK_LO = 0x1a00u // $1a00-$1aff inclusive // TODO
override var ESTACK_HI = 0x1b00u // $1b00-$1bff inclusive // TODO
override var GOLDEN = UIntRange.EMPTY
override lateinit var zeropage: Zeropage

View File

@ -18,6 +18,7 @@ class C128MachineDefinition: IMachineDefinition {
// the 2*256 byte evaluation stack (on which bytes, words, and even floats are stored during calculations)
override var ESTACK_LO = 0x1a00u // $1a00-$1aff inclusive
override var ESTACK_HI = 0x1b00u // $1b00-$1bff inclusive
override var GOLDEN = UIntRange.EMPTY // TODO does the c128 have some of this somewhere?
override lateinit var zeropage: Zeropage

View File

@ -18,6 +18,7 @@ class C64MachineDefinition: IMachineDefinition {
// the 2*256 byte evaluation stack (on which bytes, words, and even floats are stored during calculations)
override var ESTACK_LO = 0xce00u // $ce00-$ceff inclusive
override var ESTACK_HI = 0xcf00u // $ce00-$ceff inclusive
override var GOLDEN = 0xc000u until ESTACK_LO
override lateinit var zeropage: Zeropage

View File

@ -17,6 +17,7 @@ class CX16MachineDefinition: IMachineDefinition {
// the 2*256 byte evaluation stack (on which bytes, words, and even floats are stored during calculations)
override var ESTACK_LO = 0x0400u // $0400-$04ff inclusive
override var ESTACK_HI = 0x0500u // $0500-$05ff inclusive
override var GOLDEN = 0x0600u until 0x0800u
override lateinit var zeropage: Zeropage

View File

@ -20,6 +20,7 @@ class VirtualMachineDefinition: IMachineDefinition {
override var ESTACK_LO = 0u // not actually used
override var ESTACK_HI = 0u // not actually used
override var GOLDEN = UIntRange.EMPTY // not actually used
override lateinit var zeropage: Zeropage // not actually used

View File

@ -1071,7 +1071,7 @@ $repeatLabel lda $counterVar
if(saveA)
out(" pha")
assignExpressionToVariable(ptrAndIndex.first, "P8ZP_SCRATCH_W2", DataType.UWORD, null)
assignExpressionToRegister(ptrAndIndex.second, RegisterOrPair.Y)
assignExpressionToRegister(ptrAndIndex.second, RegisterOrPair.Y) // TODO TMP_REG_ISSUE_89
if(saveA)
out(" pla")
out(" sta (P8ZP_SCRATCH_W2),y")
@ -1083,7 +1083,7 @@ $repeatLabel lda $counterVar
} else {
// copy the pointer var to zp first
assignExpressionToVariable(ptrAndIndex.first, "P8ZP_SCRATCH_W2", DataType.UWORD, null)
assignExpressionToRegister(ptrAndIndex.second, RegisterOrPair.Y)
assignExpressionToRegister(ptrAndIndex.second, RegisterOrPair.Y) // TODO TMP_REG_ISSUE_89
out(" lda (P8ZP_SCRATCH_W2),y")
}
}
@ -1579,7 +1579,7 @@ $repeatLabel lda $counterVar
return
assignExpressionToVariable(right, "P8ZP_SCRATCH_B1", DataType.UBYTE, null)
assignExpressionToRegister(left, RegisterOrPair.A)
assignExpressionToRegister(left, RegisterOrPair.A) // TODO TMP_REG_ISSUE_89
return code("P8ZP_SCRATCH_B1")
}
@ -1614,7 +1614,7 @@ $repeatLabel lda $counterVar
return
assignExpressionToVariable(right, "P8ZP_SCRATCH_B1", DataType.UBYTE, null)
assignExpressionToRegister(left, RegisterOrPair.A)
assignExpressionToRegister(left, RegisterOrPair.A) // TODO TMP_REG_ISSUE_89
return code("P8ZP_SCRATCH_B1")
}
@ -1651,7 +1651,7 @@ $repeatLabel lda $counterVar
return
assignExpressionToVariable(right, "P8ZP_SCRATCH_W2", DataType.UWORD, null)
assignExpressionToRegister(left, RegisterOrPair.AY)
assignExpressionToRegister(left, RegisterOrPair.AY) // TODO TMP_REG_ISSUE_89
return out(" jsr prog8_lib.reg_less_uw | beq $jumpIfFalseLabel")
}
@ -1690,7 +1690,7 @@ $repeatLabel lda $counterVar
return
assignExpressionToVariable(right, "P8ZP_SCRATCH_W2", DataType.UWORD, null)
assignExpressionToRegister(left, RegisterOrPair.AY)
assignExpressionToRegister(left, RegisterOrPair.AY) // TODO TMP_REG_ISSUE_89
return out(" jsr prog8_lib.reg_less_w | beq $jumpIfFalseLabel")
}
@ -1730,7 +1730,7 @@ $repeatLabel lda $counterVar
return
assignExpressionToVariable(right, "P8ZP_SCRATCH_B1", DataType.UBYTE, null)
assignExpressionToRegister(left, RegisterOrPair.A)
assignExpressionToRegister(left, RegisterOrPair.A) // TODO TMP_REG_ISSUE_89
return code("P8ZP_SCRATCH_B1")
}
@ -1767,7 +1767,7 @@ $repeatLabel lda $counterVar
return
assignExpressionToVariable(right, "P8ZP_SCRATCH_B1", DataType.UBYTE, null)
assignExpressionToRegister(left, RegisterOrPair.A)
assignExpressionToRegister(left, RegisterOrPair.A) // TODO TMP_REG_ISSUE_89
return code("P8ZP_SCRATCH_B1")
}
@ -1810,7 +1810,7 @@ $repeatLabel lda $counterVar
return
assignExpressionToVariable(right, "P8ZP_SCRATCH_W2", DataType.UWORD, null)
assignExpressionToRegister(left, RegisterOrPair.AY)
assignExpressionToRegister(left, RegisterOrPair.AY) // TODO TMP_REG_ISSUE_89
return code("P8ZP_SCRATCH_W2+1", "P8ZP_SCRATCH_W2")
}
@ -1854,7 +1854,7 @@ $repeatLabel lda $counterVar
return
assignExpressionToVariable(left, "P8ZP_SCRATCH_W2", DataType.UWORD, null)
assignExpressionToRegister(right, RegisterOrPair.AY)
assignExpressionToRegister(right, RegisterOrPair.AY) // TODO TMP_REG_ISSUE_89
return out(" jsr prog8_lib.reg_less_w | beq $jumpIfFalseLabel")
}
@ -1895,7 +1895,7 @@ $repeatLabel lda $counterVar
return
assignExpressionToVariable(right, "P8ZP_SCRATCH_B1", DataType.UBYTE, null)
assignExpressionToRegister(left, RegisterOrPair.A)
assignExpressionToRegister(left, RegisterOrPair.A) // TODO TMP_REG_ISSUE_89
return code("P8ZP_SCRATCH_B1")
}
@ -1932,7 +1932,7 @@ $repeatLabel lda $counterVar
return
assignExpressionToVariable(right, "P8ZP_SCRATCH_B1", DataType.UBYTE, null)
assignExpressionToRegister(left, RegisterOrPair.A)
assignExpressionToRegister(left, RegisterOrPair.A) // TODO TMP_REG_ISSUE_89
return code("P8ZP_SCRATCH_B1")
}
@ -1977,7 +1977,7 @@ $repeatLabel lda $counterVar
return
assignExpressionToVariable(right, "P8ZP_SCRATCH_W2", DataType.UWORD, null)
assignExpressionToRegister(left, RegisterOrPair.AY)
assignExpressionToRegister(left, RegisterOrPair.AY) // TODO TMP_REG_ISSUE_89
return out(" jsr prog8_lib.reg_lesseq_uw | beq $jumpIfFalseLabel")
}
@ -2025,7 +2025,7 @@ $repeatLabel lda $counterVar
}
assignExpressionToVariable(left, "P8ZP_SCRATCH_W2", DataType.UWORD, null)
assignExpressionToRegister(right, RegisterOrPair.AY)
assignExpressionToRegister(right, RegisterOrPair.AY) // TODO TMP_REG_ISSUE_89
return out(" jsr prog8_lib.reg_lesseq_w | beq $jumpIfFalseLabel")
}
@ -2062,7 +2062,7 @@ $repeatLabel lda $counterVar
return
assignExpressionToVariable(right, "P8ZP_SCRATCH_B1", DataType.UBYTE, null)
assignExpressionToRegister(left, RegisterOrPair.A)
assignExpressionToRegister(left, RegisterOrPair.A) // TODO TMP_REG_ISSUE_89
return code("P8ZP_SCRATCH_B1")
}
@ -2096,7 +2096,7 @@ $repeatLabel lda $counterVar
return
assignExpressionToVariable(right, "P8ZP_SCRATCH_B1", DataType.UBYTE, null)
assignExpressionToRegister(left, RegisterOrPair.A)
assignExpressionToRegister(left, RegisterOrPair.A) // TODO TMP_REG_ISSUE_89
return code("P8ZP_SCRATCH_B1")
}
@ -2132,7 +2132,7 @@ $repeatLabel lda $counterVar
return
assignExpressionToVariable(left, "P8ZP_SCRATCH_W2", DataType.UWORD, null)
assignExpressionToRegister(right, RegisterOrPair.AY)
assignExpressionToRegister(right, RegisterOrPair.AY) // TODO TMP_REG_ISSUE_89
return out(" jsr prog8_lib.reg_lesseq_uw | beq $jumpIfFalseLabel")
}
@ -2171,7 +2171,7 @@ $repeatLabel lda $counterVar
return
assignExpressionToVariable(right, "P8ZP_SCRATCH_W2", DataType.UWORD, null)
assignExpressionToRegister(left, RegisterOrPair.AY)
assignExpressionToRegister(left, RegisterOrPair.AY) // TODO TMP_REG_ISSUE_89
return out(" jsr prog8_lib.reg_lesseq_w | beq $jumpIfFalseLabel")
}
@ -2207,7 +2207,7 @@ $repeatLabel lda $counterVar
return
assignExpressionToVariable(right, "P8ZP_SCRATCH_B1", DataType.UBYTE, null)
assignExpressionToRegister(left, RegisterOrPair.A)
assignExpressionToRegister(left, RegisterOrPair.A) // TODO TMP_REG_ISSUE_89
out(" cmp P8ZP_SCRATCH_B1 | bne $jumpIfFalseLabel")
}
@ -2244,7 +2244,7 @@ $repeatLabel lda $counterVar
return
assignExpressionToVariable(right, "P8ZP_SCRATCH_B1", DataType.UBYTE, null)
assignExpressionToRegister(left, RegisterOrPair.A)
assignExpressionToRegister(left, RegisterOrPair.A) // TODO TMP_REG_ISSUE_89
return code("P8ZP_SCRATCH_B1")
}
@ -2311,7 +2311,7 @@ $repeatLabel lda $counterVar
}
else -> {
assignExpressionToVariable(right, "P8ZP_SCRATCH_W2", DataType.UWORD, null)
assignExpressionToRegister(left, RegisterOrPair.AY)
assignExpressionToRegister(left, RegisterOrPair.AY) // TODO TMP_REG_ISSUE_89
out("""
cmp P8ZP_SCRATCH_W2
bne $jumpIfFalseLabel
@ -2387,7 +2387,7 @@ $repeatLabel lda $counterVar
}
else -> {
assignExpressionToVariable(right, "P8ZP_SCRATCH_W2", DataType.UWORD, null)
assignExpressionToRegister(left, RegisterOrPair.AY)
assignExpressionToRegister(left, RegisterOrPair.AY) // TODO TMP_REG_ISSUE_89
out("""
cmp P8ZP_SCRATCH_W2
bne +

View File

@ -255,13 +255,13 @@ internal class BuiltinFunctionsAsmGen(private val program: Program,
asmgen.out(" cmp ${arg2.addressExpression.constValue(program)!!.number.toHex()}")
} else {
asmgen.assignExpressionToVariable(arg2, "P8ZP_SCRATCH_B1", DataType.UBYTE, (fcall as Node).definingSubroutine)
asmgen.assignExpressionToRegister(arg1, RegisterOrPair.A)
asmgen.assignExpressionToRegister(arg1, RegisterOrPair.A) // TODO TMP_REG_ISSUE_89
asmgen.out(" cmp P8ZP_SCRATCH_B1")
}
}
else -> {
asmgen.assignExpressionToVariable(arg2, "P8ZP_SCRATCH_B1", DataType.UBYTE, (fcall as Node).definingSubroutine)
asmgen.assignExpressionToRegister(arg1, RegisterOrPair.A)
asmgen.assignExpressionToRegister(arg1, RegisterOrPair.A) // TODO TMP_REG_ISSUE_89
asmgen.out(" cmp P8ZP_SCRATCH_B1")
}
}
@ -289,7 +289,7 @@ internal class BuiltinFunctionsAsmGen(private val program: Program,
}
else -> {
asmgen.assignExpressionToVariable(arg2, "P8ZP_SCRATCH_W1", DataType.UWORD, (fcall as Node).definingSubroutine)
asmgen.assignExpressionToRegister(arg1, RegisterOrPair.AY)
asmgen.assignExpressionToRegister(arg1, RegisterOrPair.AY) // TODO TMP_REG_ISSUE_89
asmgen.out("""
cpy P8ZP_SCRATCH_W1+1
bne +

View File

@ -10,6 +10,7 @@ import prog8.ast.walk.IAstVisitor
import prog8.code.core.ICompilationTarget
import prog8.code.core.IErrorReporter
import prog8.code.core.Position
import prog8.code.target.VMTarget
import prog8.compiler.BuiltinFunctions
@ -107,10 +108,12 @@ internal class AstIdentifiersChecker(private val errors: IErrorReporter,
errors.err("asmsub can only contain inline assembly (%asm)", subroutine.position)
}
if(subroutine.name == subroutine.definingBlock.name) {
// subroutines cannot have the same name as their enclosing block,
// because this causes symbol scoping issues in the resulting assembly source
nameError(subroutine.name, subroutine.position, subroutine.definingBlock)
if(compTarget.name != VMTarget.NAME) {
if (subroutine.name == subroutine.definingBlock.name) {
// subroutines cannot have the same name as their enclosing block,
// because this causes symbol scoping issues in the resulting assembly source
errors.err("name conflict '${subroutine.name}', also defined at ${subroutine.definingBlock.position} (64tass scope nesting limitation)", subroutine.position)
}
}
}

View File

@ -270,4 +270,32 @@ mylabel:
}
exc.message shouldContain("cannot yet load a label address as a value")
}
test("nesting with overlapping names is ok (doesn't work for 64tass)") {
val src="""
%import textio
%zeropage basicsafe
main {
sub start() {
main()
main.start.start()
main.main()
sub main() {
cx16.r0++
}
sub start() {
cx16.r0++
}
}
sub main() {
cx16.r0++
}
}"""
val target = VMTarget()
compileText(target, false, src, writeAssembly = true) shouldNotBe null
}
})

View File

@ -3,8 +3,7 @@ TODO
For next release
^^^^^^^^^^^^^^^^
- AstIdentifiersChecker: can a subroutine really not have the same name as its enclosing block? 64tass problem?
- attempt to fix the expression codegen bug with reused temp vars (github #89)
- attempt to fix the expression codegen bug with reused temp vars (github #89) search for 'TMP_REG_ISSUE_89'
- 6502 codegen: make it possible to use cpu opcodes such as 'nop' as variable names by prefixing all asm vars with something such as ``p8v_``? Or not worth it (most 3 letter opcodes as variables are nonsensical anyway)
then we can get rid of the instruction lists in the machinedefinitions as well. This is already no problem at all in the IR codegen.
- create BSS section in output program and put StStaticVariables in there with bss=true. Don't forget to add init code to zero out everything that was put in bss. If array in bss->only zero ONCE! So requires self-modifying code
@ -24,7 +23,7 @@ Future Things and Ideas
^^^^^^^^^^^^^^^^^^^^^^^
Compiler:
- add a mechanism to allocate variables into golden ram ($0400-$07ff on x16, $c000-$.... on c64 , take care of evalstack)
- add a mechanism to allocate variables into golden ram (see MachineDefinition.GOLDEN)
- ir: mechanism to determine for chunks which registers are getting input values from "outside"
- ir: mechanism to determine for chunks which registers are passing values out? (i.e. are used again in another chunk)
- ir: peephole opt: renumber registers in chunks to start with 1 again every time (but keep entry values in mind!)

View File

@ -43,7 +43,7 @@ main {
txt.print_uw(count)
txt.print(" primes\n")
float time = c64.RDTIM16() / 60.0
float time = c64.RDTIM16() as float / 60.0
floats.print_f(time)
txt.print(" sec total = ")
floats.print_f(time/ITERS)

View File

@ -1,55 +1,23 @@
%import textio
%zeropage basicsafe
main {
bool[1] expected = [ true ]
alsostart:
sub get() -> bool {
txt.print("get() called. ")
return true
}
%asm {{
; inline asm in block #1
nop
}}
%asmbinary "../gradle.properties"
sub start() {
internalstart:
ubyte fact = 10
uword ww = 1<<fact
txt.print_uw(ww)
txt.nl()
ww++
ww = 1<<fact
txt.print_uw(ww)
txt.nl()
txt.nl()
txt.print_uwhex(start, true)
txt.nl()
txt.print_uwhex(alsostart, true)
txt.nl()
txt.print_uwhex(internalstart, true)
txt.nl()
txt.print_uwhex(startend, true)
txt.nl()
txt.print_uwhex(internalend, true)
txt.nl()
internalend:
}
%asm {{
; inline asm in block #2
nop
}}
startend:
%asmbinary "../settings.gradle"
%asm {{
; inline asm in block #3
nop
}}
sub start() {
if get() == expected[0]
txt.print("ok\n")
else
txt.print("fail\n")
; this is working fine:
if expected[0] == get()
txt.print("ok\n")
else
txt.print("fail\n")
}
}