mirror of
https://github.com/irmen/prog8.git
synced 2024-11-22 00:31:56 +00:00
fix double %option merge problem where it deleted all of the blocks
This commit is contained in:
parent
66fc109ce5
commit
9f84aa5fb2
@ -734,8 +734,9 @@ asmsub vpeek(ubyte bank @A, uword address @XY) -> ubyte @A {
|
||||
}
|
||||
|
||||
asmsub vaddr(ubyte bank @A, uword address @R0, ubyte addrsel @R1, byte autoIncrOrDecrByOne @Y) clobbers(A) {
|
||||
; -- setup the VERA's data address register 0 or 1
|
||||
; with optional auto increment or decrement of 1.
|
||||
; -- setup the VERA's data address register 0 or 1 with optional auto increment or decrement of 1.
|
||||
; This is a convenience routine, and not very efficient if you call it often;
|
||||
; it's usually better to write a tailor made version of it that accounts for the repeated values.
|
||||
; Note that the vaddr_autoincr() and vaddr_autodecr() routines allow to set all possible strides, not just 1.
|
||||
; Note also that Vera's addrset is reset to 0 on exit, even if you set port #1's address.
|
||||
%asm {{
|
||||
@ -764,6 +765,8 @@ asmsub vaddr(ubyte bank @A, uword address @R0, ubyte addrsel @R1, byte autoIncrO
|
||||
|
||||
asmsub vaddr_clone(ubyte port @A) clobbers (A,X,Y) {
|
||||
; -- clones Vera addresses from the given source port to the other one.
|
||||
; This is a convenience routine, and not very efficient if you call it often;
|
||||
; it's usually better to write a tailor made version of it that accounts for the repeated values.
|
||||
%asm {{
|
||||
sta VERA_CTRL
|
||||
ldx VERA_ADDR_L
|
||||
@ -783,9 +786,10 @@ asmsub vaddr_clone(ubyte port @A) clobbers (A,X,Y) {
|
||||
}
|
||||
|
||||
asmsub vaddr_autoincr(ubyte bank @A, uword address @R0, ubyte addrsel @R1, uword autoIncrAmount @R2) clobbers(A,Y) {
|
||||
; -- setup the VERA's data address register 0 or 1
|
||||
; including setting up optional auto increment amount.
|
||||
; -- setup the VERA's data address register 0 or 1, including setting up optional auto increment amount.
|
||||
; Specifiying an unsupported amount results in amount of zero. See the Vera docs about what amounts are possible.
|
||||
; This is a convenience routine, and not very efficient if you call it often;
|
||||
; it's usually better to write a tailor made version of it that accounts for the repeated values.
|
||||
%asm {{
|
||||
jsr _setup
|
||||
lda cx16.r2H
|
||||
@ -847,9 +851,10 @@ _strides_lsb .byte 0,1,2,4,8,16,32,64,128,255,255,40,80,160,255,255
|
||||
}
|
||||
|
||||
asmsub vaddr_autodecr(ubyte bank @A, uword address @R0, ubyte addrsel @R1, uword autoDecrAmount @R2) clobbers(A,Y) {
|
||||
; -- setup the VERA's data address register 0 or 1
|
||||
; including setting up optional auto decrement amount.
|
||||
; -- setup the VERA's data address register 0 or 1 including setting up optional auto decrement amount.
|
||||
; Specifiying an unsupported amount results in amount of zero. See the Vera docs about what amounts are possible.
|
||||
; This is a convenience routine, and not very efficient if you call it often;
|
||||
; it's usually better to write a tailor made version of it that accounts for the repeated values.
|
||||
%asm {{
|
||||
jsr vaddr_autoincr._setup
|
||||
lda cx16.r2H
|
||||
|
@ -11,6 +11,8 @@ class BlockMerger(val errors: IErrorReporter) {
|
||||
// will be joined into a block with the same name, coming from a library.
|
||||
// (or a normal block if no library block with that name was found)
|
||||
|
||||
private val mergedBlocks = mutableSetOf<Block>() // to make sure blocks aren't merged more than once
|
||||
|
||||
fun visit(program: Program) {
|
||||
val allBlocks = program.allBlocks
|
||||
for(block in allBlocks) {
|
||||
@ -31,6 +33,9 @@ class BlockMerger(val errors: IErrorReporter) {
|
||||
}
|
||||
|
||||
private fun merge(block: Block, target: Block) {
|
||||
if(block===target || block in mergedBlocks || target in mergedBlocks)
|
||||
return
|
||||
|
||||
val named = target.statements.filterIsInstance<Subroutine>().associateBy { it.name }
|
||||
|
||||
for(stmt in block.statements.filter { it !is Directive }) {
|
||||
@ -47,7 +52,9 @@ class BlockMerger(val errors: IErrorReporter) {
|
||||
target.statements.add(stmt)
|
||||
stmt.parent = target
|
||||
}
|
||||
|
||||
block.statements.clear()
|
||||
block.definingScope.remove(block)
|
||||
mergedBlocks.add(block)
|
||||
}
|
||||
}
|
||||
|
@ -135,5 +135,34 @@ main {
|
||||
compileText(VMTarget(), optimize = false, src) shouldNotBe null
|
||||
}
|
||||
|
||||
test("double merge works") {
|
||||
val src="""
|
||||
main {
|
||||
|
||||
sub start() {
|
||||
block1.sub1()
|
||||
block1.sub2()
|
||||
}
|
||||
}
|
||||
|
||||
block1 {
|
||||
%option merge
|
||||
|
||||
sub sub1() {
|
||||
cx16.r1++
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
block1 {
|
||||
%option merge
|
||||
|
||||
sub sub2() {
|
||||
cx16.r2++
|
||||
}
|
||||
}"""
|
||||
compileText(VMTarget(), optimize = false, src) shouldNotBe null
|
||||
}
|
||||
|
||||
|
||||
})
|
||||
|
@ -724,7 +724,7 @@ Multiple return values
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
Normal subroutines can only return zero or one return values.
|
||||
However, the special ``asmsub`` routines (implemented in assembly code) or ``romsub`` routines
|
||||
(referencing an external routine in ROM or elsewhere in memory) can return more than one return value.
|
||||
(referencing an external routine in ROM or elsewhere in RAM) can return more than one return value.
|
||||
For example a status in the carry bit and a number in A, or a 16-bit value in A/Y registers and some more values in R0 and R1.
|
||||
In all of these cases, you have to "multi assign" all return values of the subroutine call to something.
|
||||
You simply write the assignment targets as a comma separated list,
|
||||
@ -784,14 +784,19 @@ The return type has to be specified if the subroutine returns a value.
|
||||
Assembly / ROM subroutines
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
External subroutines implemented in ROM (or elsewhere in memory) are usually defined by compiler library files, with the following syntax::
|
||||
External subroutines implemented in ROM are usually defined by compiler library files, with the following syntax::
|
||||
|
||||
romsub $FFD5 = LOAD(ubyte verify @ A, uword address @ XY) -> clobbers() -> bool @Pc, ubyte @ A, ubyte @ X, ubyte @ Y
|
||||
romsub $FFD5 = LOAD(ubyte verify @ A, uword address @ XY) clobbers()
|
||||
-> bool @Pc, ubyte @ A, ubyte @ X, ubyte @ Y
|
||||
|
||||
This defines the ``LOAD`` subroutine at memory address $FFD5, taking arguments in all three registers A, X and Y,
|
||||
and returning stuff in several registers as well. The ``clobbers`` clause is used to signify to the compiler
|
||||
what CPU registers are clobbered by the call instead of being unchanged or returning a meaningful result value.
|
||||
|
||||
.. note::
|
||||
Unlike what it's name may suggest, ``romsub`` can also define an external subroutine elsewhere in normal RAM.
|
||||
It's just that you explicitly define the memory address where it is located and it doesn't matter if that is in ROM or in RAM.
|
||||
|
||||
User-written subroutines in the program source code itself, implemented purely in assembly and which have an assembly calling convention (i.e.
|
||||
the parameters are strictly passed via cpu registers), are defined with ``asmsub`` like this::
|
||||
|
||||
|
@ -1,8 +1,6 @@
|
||||
TODO
|
||||
====
|
||||
|
||||
merge problem: if 2 library modules both have merge, stuff breaks (math & prog8_math where prog8_math used to have math block.... didn't work)
|
||||
|
||||
for releasenotes: gfx2.width and gfx2.height got renamed as gfx_lores.WIDTH/HEIGHT or gfx_hires4.WIDTH/HEIGTH constants. Screen mode routines also renamed.
|
||||
|
||||
regenerate symbol dump files
|
||||
|
@ -5,62 +5,25 @@
|
||||
main {
|
||||
|
||||
sub start() {
|
||||
cx16.r0=0
|
||||
|
||||
if cx16.r0==0
|
||||
cx16.r1L=42
|
||||
else
|
||||
cx16.r1L=99
|
||||
|
||||
cx16.r2L = if cx16.r0==0 42 else 99
|
||||
|
||||
if cx16.r0==33
|
||||
cx16.r1L=42
|
||||
else
|
||||
cx16.r1L=99
|
||||
|
||||
cx16.r2L = if cx16.r0==33 42 else 99
|
||||
|
||||
if cx16.r0!=3333
|
||||
cx16.r1L=42
|
||||
else
|
||||
cx16.r1L=99
|
||||
|
||||
cx16.r2L = if cx16.r0!=3333 42 else 99
|
||||
|
||||
if cx16.r0!=0
|
||||
cx16.r1L=42
|
||||
else
|
||||
cx16.r1L=99
|
||||
|
||||
cx16.r2L = if cx16.r0!=0 42 else 99
|
||||
|
||||
if cx16.r0!=33
|
||||
cx16.r1L=42
|
||||
else
|
||||
cx16.r1L=99
|
||||
|
||||
cx16.r2L = if cx16.r0!=0 42 else 99
|
||||
|
||||
if cx16.r0==cx16.r9
|
||||
cx16.r1L=42
|
||||
else
|
||||
cx16.r1L=99
|
||||
|
||||
cx16.r2L = if cx16.r0==cx16.r9 42 else 99
|
||||
|
||||
if cx16.r0!=cx16.r9
|
||||
cx16.r1L=42
|
||||
else
|
||||
cx16.r1L=99
|
||||
|
||||
cx16.r2L = if cx16.r0!=cx16.r9 42 else 99
|
||||
|
||||
if cx16.r0>cx16.r1
|
||||
cx16.r1L=42
|
||||
else
|
||||
cx16.r1L=99
|
||||
|
||||
cx16.r2L = if cx16.r0>cx16.r1 42 else 99
|
||||
block1.sub1()
|
||||
block1.sub2()
|
||||
}
|
||||
}
|
||||
|
||||
block1 {
|
||||
%option merge
|
||||
|
||||
sub sub1() {
|
||||
txt.print("sub1")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
block1 {
|
||||
%option merge
|
||||
|
||||
sub sub2() {
|
||||
txt.print("sub2")
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user