From cac4c1eb1e509bbee274a1ea0dc2b309d6403a92 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Mon, 16 Sep 2024 21:49:20 +0200 Subject: [PATCH] improve callgraph unused subroutine check for routines called from inline asm --- compilerAst/src/prog8/compiler/CallGraph.kt | 21 ++++++++++++---- docs/source/todo.rst | 4 --- examples/cx16/kefrenbars.p8 | 8 ++++-- examples/test.p8 | 28 +++++++++++++-------- 4 files changed, 40 insertions(+), 21 deletions(-) diff --git a/compilerAst/src/prog8/compiler/CallGraph.kt b/compilerAst/src/prog8/compiler/CallGraph.kt index 28218be75..8b5ec582d 100644 --- a/compilerAst/src/prog8/compiler/CallGraph.kt +++ b/compilerAst/src/prog8/compiler/CallGraph.kt @@ -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 = emptyList()): Boolean { + private fun nameInAssemblyCode(name: String, knownAsmPrefixes: List = 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 } } } diff --git a/docs/source/todo.rst b/docs/source/todo.rst index ce1024254..fb5d3198b 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -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!) diff --git a/examples/cx16/kefrenbars.p8 b/examples/cx16/kefrenbars.p8 index 903005ffd..26bee4a3e 100644 --- a/examples/cx16/kefrenbars.p8 +++ b/examples/cx16/kefrenbars.p8 @@ -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) diff --git a/examples/test.p8 b/examples/test.p8 index aeb1f29ce..57a1f5728 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -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 } } }