improve callgraph unused subroutine check for routines called from inline asm

This commit is contained in:
Irmen de Jong 2024-09-16 21:49:20 +02:00
parent 0b1f30d98c
commit cac4c1eb1e
4 changed files with 40 additions and 21 deletions

View File

@ -160,11 +160,22 @@ class CallGraph(private val program: Program) : IAstVisitor {
fun unused(module: Module) = module !in usedModules
fun unused(sub: Subroutine): Boolean {
return sub !in usedSubroutines && !nameInAssemblyCode(sub.name, listOf("p8s_", ""))
if(sub in usedSubroutines)
return false
val asm = nameInAssemblyCode(sub.name, listOf("p8s_", ""))
if(asm!=null) {
// check that the asm block that calls us, is inside a subroutine that is unused or not
val containingSub = asm.definingSubroutine
return if(containingSub != null && containingSub !== sub)
unused(containingSub)
else
false
}
return true
}
fun unused(block: Block): Boolean {
return block !in usedBlocks && !nameInAssemblyCode(block.name, listOf("p8b_", ""))
return block !in usedBlocks && nameInAssemblyCode(block.name, listOf("p8b_", ""))==null
}
fun unused(decl: VarDecl): Boolean {
@ -187,13 +198,13 @@ class CallGraph(private val program: Program) : IAstVisitor {
}
private val prefixes = listOf("p8b_", "p8v_", "p8s_", "p8c_", "p8l_", "p8_", "")
private fun nameInAssemblyCode(name: String, knownAsmPrefixes: List<String> = emptyList()): Boolean {
private fun nameInAssemblyCode(name: String, knownAsmPrefixes: List<String> = emptyList()): InlineAssembly? {
if(knownAsmPrefixes.isNotEmpty())
return allAssemblyNodes.any {
return allAssemblyNodes.firstOrNull {
knownAsmPrefixes.any { prefix -> prefix+name in it.names }
}
return allAssemblyNodes.any {
return allAssemblyNodes.firstOrNull {
prefixes.any { prefix -> prefix+name in it.names }
}
}

View File

@ -1,10 +1,6 @@
TODO
====
callgraph issue? : if a sub contains another sub and it calls that, the outer sub is never removed even if it doesn't get called?
(diskio, when read4hex is placed back inside internal_f_tell() )
Improve register load order in subroutine call args assignments:
in certain situations, the "wrong" order of evaluation of function call arguments is done which results
in overwriting registers that already got their value, which requires a lot of stack juggling (especially on plain 6502 cpu!)

View File

@ -35,7 +35,7 @@ main {
irq {
const ubyte BAR_Y_OFFSET = 6
const ubyte BAR_Y_OFFSET = 5
uword next_irq_line = 0
ubyte anim1 = 0
ubyte av1 = 0
@ -47,7 +47,7 @@ irq {
next_irq_line += BAR_Y_OFFSET
anim1 += 7
anim2 += 4
if next_irq_line > 480-BAR_Y_OFFSET {
if next_irq_line > 480 {
av1++
av2 += 2
anim1 = av1
@ -55,6 +55,10 @@ irq {
next_irq_line = 0
; erase the bars
gfx2.horizontal_line(0, 0, 320, 3)
; gfx2.position(0, 0)
; repeat 10 {
; gfx2.next_pixels(pixels, len(pixels))
; }
} else {
; add new bar on top
gfx2.position(math.sin8u(anim1)/2 + math.cos8u(anim2)/2 + $0010, 0)

View File

@ -1,19 +1,27 @@
%import monogfx
%option no_sysinit
%zeropage basicsafe
main {
sub start() {
monogfx.hires()
monogfx.circle(320, 240, 200, true)
sys.wait(60)
monogfx.drawmode(monogfx.MODE_STIPPLE)
monogfx.disc(320, 240, 200, true)
sys.wait(60)
monogfx.drawmode(monogfx.MODE_NORMAL)
monogfx.safe_disc(320, 240, 200, true)
; nothing!
}
}
repeat {
derp {
asmsub f_tell() -> uword @R0, uword @R1, uword @R2, uword @R3 {
%asm {{
jmp p8s_internal_f_tell
}}
}
sub internal_f_tell() {
cx16.r1 = read4hex()
sub read4hex() -> uword {
str @shared hex = "0000000000000000000000000000000000000000000"
cx16.r0++
return cx16.r0
}
}
}