mirror of
https://github.com/irmen/prog8.git
synced 2025-01-11 13:29:45 +00:00
callgraph improved unused node checking
This commit is contained in:
parent
4c1eb1b12a
commit
3e3b0bcd8b
@ -21,18 +21,17 @@ class CallGraph(private val program: Program) : IAstVisitor {
|
||||
val calls = mutableMapOf<Subroutine, Set<Subroutine>>().withDefault { setOf() }
|
||||
val calledBy = mutableMapOf<Subroutine, Set<Node>>().withDefault { setOf() }
|
||||
private val allIdentifiersAndTargets = mutableMapOf<Pair<IdentifierReference, Position>, Statement>()
|
||||
private val allAssemblyNodes = mutableListOf<InlineAssembly>()
|
||||
|
||||
init {
|
||||
visit(program)
|
||||
}
|
||||
|
||||
private val usedSubroutines: Set<Subroutine> by lazy {
|
||||
// TODO also check inline assembly if it uses the subroutine
|
||||
calledBy.keys
|
||||
}
|
||||
|
||||
private val usedBlocks: Set<Block> by lazy {
|
||||
// TODO also check inline assembly if it uses the block
|
||||
val blocksFromSubroutines = usedSubroutines.map { it.definingBlock() }
|
||||
val blocksFromLibraries = program.allBlocks().filter { it.isInLibrary }
|
||||
val used = mutableSetOf<Block>()
|
||||
@ -110,6 +109,10 @@ class CallGraph(private val program: Program) : IAstVisitor {
|
||||
allIdentifiersAndTargets[Pair(identifier, identifier.position)] = identifier.targetStatement(program)!!
|
||||
}
|
||||
|
||||
override fun visit(inlineAssembly: InlineAssembly) {
|
||||
allAssemblyNodes.add(inlineAssembly)
|
||||
}
|
||||
|
||||
fun checkRecursiveCalls(errors: IErrorReporter) {
|
||||
val cycles = recursionCycles()
|
||||
if(cycles.any()) {
|
||||
@ -163,9 +166,13 @@ class CallGraph(private val program: Program) : IAstVisitor {
|
||||
|
||||
fun unused(module: Module) = module !in usedModules
|
||||
|
||||
fun unused(sub: Subroutine) = sub !in usedSubroutines
|
||||
fun unused(sub: Subroutine): Boolean {
|
||||
return sub !in usedSubroutines && !nameInAssemblyCode(sub.name)
|
||||
}
|
||||
|
||||
fun unused(block: Block) = block !in usedBlocks
|
||||
fun unused(block: Block): Boolean {
|
||||
return block !in usedBlocks && !nameInAssemblyCode(block.name)
|
||||
}
|
||||
|
||||
fun unused(decl: VarDecl): Boolean {
|
||||
if(decl.type!=VarDeclType.VAR || decl.datatype==DataType.STRUCT || decl.autogeneratedDontRemove || decl.parent is StructDecl)
|
||||
@ -174,19 +181,11 @@ class CallGraph(private val program: Program) : IAstVisitor {
|
||||
if(decl.definingBlock() !in usedBlocks)
|
||||
return false
|
||||
|
||||
// TODO also check inline asm for references to the var
|
||||
val allReferencedVardecls = allIdentifiersAndTargets.filter { it.value is VarDecl }.map { it.value }.toSet()
|
||||
|
||||
return decl !in allReferencedVardecls
|
||||
return decl !in allReferencedVardecls && !nameInAssemblyCode(decl.name)
|
||||
}
|
||||
|
||||
fun unused(struct: StructDecl): Boolean {
|
||||
if(struct.definingBlock() !in usedBlocks)
|
||||
return false
|
||||
|
||||
// TODO implement unused check for struct decls, also check inline asm
|
||||
return false
|
||||
}
|
||||
private fun nameInAssemblyCode(name: String) = allAssemblyNodes.any { it.assembly.contains(name) }
|
||||
|
||||
inline fun unused(label: Label) = false // just always output labels
|
||||
|
||||
@ -196,7 +195,6 @@ class CallGraph(private val program: Program) : IAstVisitor {
|
||||
is Block -> unused(stmt)
|
||||
is VarDecl -> unused(stmt)
|
||||
is Label -> false // just always output labels
|
||||
is StructDecl -> unused(stmt)
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
|
@ -948,7 +948,7 @@ class WhenChoice(var values: MutableList<Expression>?, // if null, th
|
||||
|
||||
class StructDecl(override val name: String,
|
||||
override var statements: MutableList<Statement>, // actually, only vardecls here
|
||||
override val position: Position): Statement(), INameScope, ISymbolStatement {
|
||||
override val position: Position): Statement(), INameScope {
|
||||
|
||||
override lateinit var parent: Node
|
||||
|
||||
|
@ -2,8 +2,6 @@
|
||||
TODO
|
||||
====
|
||||
|
||||
- implement new 'unused' in CallGraph for more node types
|
||||
|
||||
- allow inlining of subroutines with params
|
||||
- optimize several inner loops in gfx2
|
||||
- hoist all variable declarations up to the subroutine scope *before* even the constant folding takes place (to avoid undefined symbol errors when referring to a variable from another nested scope in the subroutine)
|
||||
|
Loading…
x
Reference in New Issue
Block a user