mirror of
https://github.com/irmen/prog8.git
synced 2024-12-24 01:29:28 +00:00
- 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:
parent
3c698f1584
commit
b8fb391022
@ -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" }
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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 +
|
||||
|
@ -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 +
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
})
|
@ -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!)
|
||||
|
@ -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)
|
||||
|
@ -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")
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user