Fix call graph to no longer mark subroutines unused, that still get their variables referenced somewhere.

Revert palette.default_colors_16[] back to palette.set_default16.colors.
This commit is contained in:
Irmen de Jong 2024-01-11 22:12:01 +01:00
parent 06bedb7adb
commit bc3f2db3de
5 changed files with 66 additions and 39 deletions

View File

@ -152,27 +152,26 @@ palette {
set_rgb(colors, len(colors)) set_rgb(colors, len(colors))
} }
uword[] default_colors_16 = [
$000, ; 0 = black
$fff, ; 1 = white
$800, ; 2 = red
$afe, ; 3 = cyan
$c4c, ; 4 = purple
$0c5, ; 5 = green
$00a, ; 6 = blue
$ee7, ; 7 = yellow
$d85, ; 8 = orange
$640, ; 9 = brown
$f77, ; 10 = light red
$333, ; 11 = dark grey
$777, ; 12 = medium grey
$af6, ; 13 = light green
$08f, ; 14 = light blue
$bbb ; 15 = light grey
]
sub set_default16() { sub set_default16() {
; set first 16 colors to the defaults on the X16 ; set first 16 colors to the defaults on the X16
set_rgb(default_colors_16, len(default_colors_16)) uword[] colors = [
$000, ; 0 = black
$fff, ; 1 = white
$800, ; 2 = red
$afe, ; 3 = cyan
$c4c, ; 4 = purple
$0c5, ; 5 = green
$00a, ; 6 = blue
$ee7, ; 7 = yellow
$d85, ; 8 = orange
$640, ; 9 = brown
$f77, ; 10 = light red
$333, ; 11 = dark grey
$777, ; 12 = medium grey
$af6, ; 13 = light green
$08f, ; 14 = light blue
$bbb ; 15 = light grey
]
set_rgb(colors, len(colors))
} }
} }

View File

@ -2,6 +2,7 @@ package prog8tests
import io.kotest.assertions.withClue import io.kotest.assertions.withClue
import io.kotest.core.spec.style.FunSpec import io.kotest.core.spec.style.FunSpec
import io.kotest.matchers.collections.shouldContain
import io.kotest.matchers.ints.shouldBeGreaterThanOrEqual import io.kotest.matchers.ints.shouldBeGreaterThanOrEqual
import io.kotest.matchers.maps.shouldNotContainKey import io.kotest.matchers.maps.shouldNotContainKey
import io.kotest.matchers.shouldBe import io.kotest.matchers.shouldBe
@ -11,6 +12,7 @@ import prog8.ast.statements.Block
import prog8.ast.statements.Subroutine import prog8.ast.statements.Subroutine
import prog8.code.core.SourceCode import prog8.code.core.SourceCode
import prog8.code.target.C64Target import prog8.code.target.C64Target
import prog8.code.target.VMTarget
import prog8.compiler.CallGraph import prog8.compiler.CallGraph
import prog8.parser.Prog8Parser.parseModule import prog8.parser.Prog8Parser.parseModule
import prog8tests.helpers.* import prog8tests.helpers.*
@ -222,4 +224,28 @@ class TestCallgraph: FunSpec({
errors.errors.size shouldBe 0 errors.errors.size shouldBe 0
errors.warnings.size shouldBe 0 errors.warnings.size shouldBe 0
} }
test("subs that aren't called but only used as scope aren't unused") {
val src="""
main {
sub start() {
cx16.r0L = main.scopesub.variable
cx16.r0L = main.scopesub.array[1]
cx16.r0++
}
sub scopesub() {
ubyte variable
ubyte[] array = [1,2,3]
cx16.r0++
}
}"""
val result = compileText(VMTarget(), true, src)!!
val callgraph = CallGraph(result.compilerAst)
val scopeSub = result.compilerAst.entrypoint.lookup(listOf("main", "scopesub")) as Subroutine
scopeSub.name shouldBe "scopesub"
callgraph.notCalledButReferenced shouldContain scopeSub
callgraph.unused(scopeSub) shouldBe false
}
}) })

View File

@ -709,7 +709,7 @@ main {
ubyte counter ubyte counter
counter++ counter++
} }
test2(main.test.nested.counter) ; shouldn't crash but just give nice error test2(main.test.nested.counter)
} }
sub test2(ubyte value) { sub test2(ubyte value) {
@ -717,8 +717,7 @@ main {
} }
}""" }"""
val errors = ErrorReporterForTests() val errors = ErrorReporterForTests()
compileText(Cx16Target(), true, src, writeAssembly = false, errors = errors) shouldBe null compileText(Cx16Target(), true, src, writeAssembly = false, errors = errors) shouldNotBe null
errors.errors.single() shouldContain "undefined symbol"
} }
test("var to const") { test("var to const") {

View File

@ -100,6 +100,16 @@ class CallGraph(private val program: Program) : IAstVisitor {
val target = identifier.targetStatement(program) val target = identifier.targetStatement(program)
if(target!=null) if(target!=null)
allIdentifiersAndTargets[identifier] = target allIdentifiersAndTargets[identifier] = target
// if it's a scoped identifier, the subroutines in the name are also referenced!
val scope = identifier.definingScope
val name = identifier.nameInSource.toMutableList()
while(name.size>1) {
name.removeLast()
val scopeTarget = scope.lookup(name)
if(scopeTarget is Subroutine)
notCalledButReferenced += scopeTarget
}
} }
override fun visit(inlineAssembly: InlineAssembly) { override fun visit(inlineAssembly: InlineAssembly) {

View File

@ -1,26 +1,19 @@
%import textio %import textio
%import palette
%zeropage basicsafe %zeropage basicsafe
%option no_sysinit %option no_sysinit
main { main {
sub start() { sub start() {
ubyte xx = wobwob() cx16.r0L = main.dummy.variable
txt.print_ub(xx) cx16.r0L = main.dummy.array[1]
uword yy = wobwob2() cx16.r0++
txt.print_uw(yy) }
asmsub wobwob() -> bool @Pc { sub dummy() {
%asm {{ ubyte variable
sec ubyte[] array = [1,2,3]
rts
}}
}
asmsub wobwob2() -> bool @Pc { cx16.r0++
%asm {{
clc
rts
}}
}
} }
} }