mirror of
https://github.com/irmen/prog8.git
synced 2024-11-23 07:32:10 +00:00
remove unused/empty modules
This commit is contained in:
parent
b35430214b
commit
b374af3526
@ -496,6 +496,8 @@ class Module(override val name: String,
|
|||||||
val source: Path) : Node, INameScope {
|
val source: Path) : Node, INameScope {
|
||||||
override lateinit var parent: Node
|
override lateinit var parent: Node
|
||||||
lateinit var program: Program
|
lateinit var program: Program
|
||||||
|
val imports = mutableSetOf<Module>()
|
||||||
|
val importedBy = mutableSetOf<Module>()
|
||||||
|
|
||||||
override fun linkParents(parent: Node) {
|
override fun linkParents(parent: Node) {
|
||||||
this.parent=parent
|
this.parent=parent
|
||||||
@ -1625,7 +1627,7 @@ class FunctionCallStatement(override var target: IdentifierReference,
|
|||||||
override fun process(processor: IAstProcessor) = processor.process(this)
|
override fun process(processor: IAstProcessor) = processor.process(this)
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
return "FunctionCall(target=$target, pos=$position)"
|
return "FunctionCallStatement(target=$target, pos=$position)"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1690,6 +1692,9 @@ class Subroutine(override val name: String,
|
|||||||
override var statements: MutableList<IStatement>,
|
override var statements: MutableList<IStatement>,
|
||||||
override val position: Position) : IStatement, INameScope {
|
override val position: Position) : IStatement, INameScope {
|
||||||
override lateinit var parent: Node
|
override lateinit var parent: Node
|
||||||
|
val calledBy = mutableSetOf<Subroutine>()
|
||||||
|
val calls = mutableSetOf<Subroutine>()
|
||||||
|
|
||||||
val scopedname: String by lazy { makeScopedName(name) }
|
val scopedname: String by lazy { makeScopedName(name) }
|
||||||
|
|
||||||
override fun linkParents(parent: Node) {
|
override fun linkParents(parent: Node) {
|
||||||
|
90
compiler/src/prog8/optimizing/CallGraphBuilder.kt
Normal file
90
compiler/src/prog8/optimizing/CallGraphBuilder.kt
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
package prog8.optimizing
|
||||||
|
|
||||||
|
import prog8.ast.*
|
||||||
|
|
||||||
|
|
||||||
|
class CallGraphBuilder(private val program: Program): IAstProcessor {
|
||||||
|
|
||||||
|
private val modulesImporting = mutableMapOf<Module, Set<Module>>().withDefault { mutableSetOf() }
|
||||||
|
private val modulesImportedBy = mutableMapOf<Module, Set<Module>>().withDefault { mutableSetOf() }
|
||||||
|
private val subroutinesCalling = mutableMapOf<Subroutine, Set<Subroutine>>().withDefault { mutableSetOf() }
|
||||||
|
private val subroutinesCalledBy = mutableMapOf<Subroutine, Set<Subroutine>>().withDefault { mutableSetOf() }
|
||||||
|
|
||||||
|
private fun forAllSubroutines(scope: INameScope, sub: (s: Subroutine) -> Unit) {
|
||||||
|
fun findSubs(scope: INameScope) {
|
||||||
|
scope.statements.forEach {
|
||||||
|
if(it is Subroutine)
|
||||||
|
sub(it)
|
||||||
|
if(it is INameScope)
|
||||||
|
findSubs(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
findSubs(scope)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun process(program: Program) {
|
||||||
|
super.process(program)
|
||||||
|
|
||||||
|
program.modules.forEach {
|
||||||
|
it.importedBy.clear()
|
||||||
|
it.imports.clear()
|
||||||
|
|
||||||
|
it.importedBy.addAll(modulesImportedBy.getValue(it))
|
||||||
|
it.imports.addAll(modulesImporting.getValue(it))
|
||||||
|
|
||||||
|
if(it.isLibraryModule && it.importedBy.isEmpty())
|
||||||
|
it.importedBy.add(it) // don't discard auto-imported library module
|
||||||
|
|
||||||
|
forAllSubroutines(it) { sub ->
|
||||||
|
sub.calledBy.clear()
|
||||||
|
sub.calls.clear()
|
||||||
|
|
||||||
|
sub.calledBy.addAll(subroutinesCalledBy.getValue(sub))
|
||||||
|
sub.calls.addAll(subroutinesCalling.getValue(sub))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val rootmodule = program.modules.first()
|
||||||
|
rootmodule.importedBy.add(rootmodule) // don't discard root module
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun process(directive: Directive): IStatement {
|
||||||
|
if(directive.directive=="%import") {
|
||||||
|
val importedModule: Module = program.modules.single { it.name==directive.args[0].name }
|
||||||
|
val thisModule = directive.definingModule()
|
||||||
|
modulesImporting[thisModule] = modulesImporting.getValue(thisModule).plus(importedModule)
|
||||||
|
modulesImportedBy[importedModule] = modulesImportedBy.getValue(importedModule).plus(thisModule)
|
||||||
|
}
|
||||||
|
return super.process(directive)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun process(functionCall: FunctionCall): IExpression {
|
||||||
|
val otherSub = functionCall.target.targetSubroutine(program.namespace)
|
||||||
|
if(otherSub!=null) {
|
||||||
|
val thisSub = functionCall.definingScope() as Subroutine
|
||||||
|
subroutinesCalling[thisSub] = subroutinesCalling.getValue(thisSub).plus(otherSub)
|
||||||
|
subroutinesCalledBy[otherSub] = subroutinesCalledBy.getValue(otherSub).plus(thisSub)
|
||||||
|
}
|
||||||
|
return super.process(functionCall)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun process(functionCallStatement: FunctionCallStatement): IStatement {
|
||||||
|
val otherSub = functionCallStatement.target.targetSubroutine(program.namespace)
|
||||||
|
if(otherSub!=null) {
|
||||||
|
val thisSub = functionCallStatement.definingScope() as Subroutine
|
||||||
|
subroutinesCalling[thisSub] = subroutinesCalling.getValue(thisSub).plus(otherSub)
|
||||||
|
subroutinesCalledBy[otherSub] = subroutinesCalledBy.getValue(otherSub).plus(thisSub)
|
||||||
|
}
|
||||||
|
return super.process(functionCallStatement)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun process(jump: Jump): IStatement {
|
||||||
|
val otherSub = jump.identifier?.targetSubroutine(program.namespace)
|
||||||
|
if(otherSub!=null) {
|
||||||
|
val thisSub = jump.definingScope() as Subroutine
|
||||||
|
subroutinesCalling[thisSub] = subroutinesCalling.getValue(thisSub).plus(otherSub)
|
||||||
|
subroutinesCalledBy[otherSub] = subroutinesCalledBy.getValue(otherSub).plus(thisSub)
|
||||||
|
}
|
||||||
|
return super.process(jump)
|
||||||
|
}
|
||||||
|
}
|
@ -11,7 +11,7 @@ import kotlin.math.floor
|
|||||||
|
|
||||||
|
|
||||||
todo: implement usage counters for blocks, variables, subroutines, heap variables. Then:
|
todo: implement usage counters for blocks, variables, subroutines, heap variables. Then:
|
||||||
todo remove unused: subroutines, blocks, modules (in this order)
|
todo remove unused: subroutines, blocks (in this order)
|
||||||
todo remove unused: variable declarations
|
todo remove unused: variable declarations
|
||||||
todo remove unused strings and arrays from the heap
|
todo remove unused strings and arrays from the heap
|
||||||
todo inline subroutines that are called exactly once (regardless of their size)
|
todo inline subroutines that are called exactly once (regardless of their size)
|
||||||
@ -28,6 +28,24 @@ class StatementOptimizer(private val program: Program) : IAstProcessor {
|
|||||||
private set
|
private set
|
||||||
private val pureBuiltinFunctions = BuiltinFunctions.filter { it.value.pure }
|
private val pureBuiltinFunctions = BuiltinFunctions.filter { it.value.pure }
|
||||||
|
|
||||||
|
|
||||||
|
override fun process(program: Program) {
|
||||||
|
val callgraph = CallGraphBuilder(program)
|
||||||
|
callgraph.process(program)
|
||||||
|
|
||||||
|
// remove modules that are not imported, or are empty
|
||||||
|
val removeModules = mutableSetOf<Module>()
|
||||||
|
program.modules.forEach {
|
||||||
|
if(it.importedBy.isEmpty() || it.isEmpty()) {
|
||||||
|
printWarning("discarding empty or unused module: ${it.name}")
|
||||||
|
removeModules.add(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
program.modules.removeAll(removeModules)
|
||||||
|
|
||||||
|
super.process(program)
|
||||||
|
}
|
||||||
|
|
||||||
override fun process(block: Block): IStatement {
|
override fun process(block: Block): IStatement {
|
||||||
if(block.statements.isEmpty()) {
|
if(block.statements.isEmpty()) {
|
||||||
// remove empty block
|
// remove empty block
|
||||||
@ -38,6 +56,7 @@ class StatementOptimizer(private val program: Program) : IAstProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun process(subroutine: Subroutine): IStatement {
|
override fun process(subroutine: Subroutine): IStatement {
|
||||||
|
println("STMT OPTIMIZE $subroutine ${subroutine.calledBy} ${subroutine.calls}")
|
||||||
super.process(subroutine)
|
super.process(subroutine)
|
||||||
|
|
||||||
if(subroutine.asmAddress==null) {
|
if(subroutine.asmAddress==null) {
|
||||||
|
Loading…
Reference in New Issue
Block a user