mirror of
https://github.com/irmen/prog8.git
synced 2024-07-22 08:29:01 +00:00
reducing dependencies
This commit is contained in:
parent
f4cef3eaf2
commit
781915d2cf
@ -267,14 +267,14 @@ private fun optimizeAst(programAst: Program, errors: IErrorReporter, functions:
|
|||||||
// keep optimizing expressions and statements until no more steps remain
|
// keep optimizing expressions and statements until no more steps remain
|
||||||
val optsDone1 = programAst.simplifyExpressions()
|
val optsDone1 = programAst.simplifyExpressions()
|
||||||
val optsDone2 = programAst.splitBinaryExpressions(compTarget)
|
val optsDone2 = programAst.splitBinaryExpressions(compTarget)
|
||||||
val optsDone3 = programAst.optimizeStatements(errors, functions, compTarget)
|
val optsDone3 = programAst.optimizeStatements(errors, functions, compTarget, ::loadAsmIncludeFile)
|
||||||
programAst.constantFold(errors, compTarget) // because simplified statements and expressions can result in more constants that can be folded away
|
programAst.constantFold(errors, compTarget) // because simplified statements and expressions can result in more constants that can be folded away
|
||||||
errors.report()
|
errors.report()
|
||||||
if (optsDone1 + optsDone2 + optsDone3 == 0)
|
if (optsDone1 + optsDone2 + optsDone3 == 0)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
val remover = UnusedCodeRemover(programAst, errors, compTarget)
|
val remover = UnusedCodeRemover(programAst, errors, compTarget, ::loadAsmIncludeFile)
|
||||||
remover.visit(programAst)
|
remover.visit(programAst)
|
||||||
remover.applyModifications()
|
remover.applyModifications()
|
||||||
errors.report()
|
errors.report()
|
||||||
@ -286,7 +286,7 @@ private fun postprocessAst(programAst: Program, errors: IErrorReporter, compiler
|
|||||||
programAst.variousCleanups()
|
programAst.variousCleanups()
|
||||||
programAst.checkValid(compilerOptions, errors, compilerOptions.compTarget) // check if final tree is still valid
|
programAst.checkValid(compilerOptions, errors, compilerOptions.compTarget) // check if final tree is still valid
|
||||||
errors.report()
|
errors.report()
|
||||||
val callGraph = CallGraph(programAst)
|
val callGraph = CallGraph(programAst, ::loadAsmIncludeFile)
|
||||||
callGraph.checkRecursiveCalls(errors)
|
callGraph.checkRecursiveCalls(errors)
|
||||||
errors.report()
|
errors.report()
|
||||||
programAst.verifyFunctionArgTypes()
|
programAst.verifyFunctionArgTypes()
|
||||||
|
@ -12,7 +12,7 @@ import prog8.ast.expressions.IdentifierReference
|
|||||||
import prog8.ast.statements.*
|
import prog8.ast.statements.*
|
||||||
import prog8.ast.walk.IAstVisitor
|
import prog8.ast.walk.IAstVisitor
|
||||||
import prog8.compiler.IErrorReporter
|
import prog8.compiler.IErrorReporter
|
||||||
import prog8.compiler.loadAsmIncludeFile
|
import java.nio.file.Path
|
||||||
|
|
||||||
private val alwaysKeepSubroutines = setOf(
|
private val alwaysKeepSubroutines = setOf(
|
||||||
Pair("main", "start"),
|
Pair("main", "start"),
|
||||||
@ -23,7 +23,7 @@ private val asmJumpRx = Regex("""[\-+a-zA-Z0-9_ \t]+(jmp|jsr)[ \t]+(\S+).*""", R
|
|||||||
private val asmRefRx = Regex("""[\-+a-zA-Z0-9_ \t]+(...)[ \t]+(\S+).*""", RegexOption.IGNORE_CASE)
|
private val asmRefRx = Regex("""[\-+a-zA-Z0-9_ \t]+(...)[ \t]+(\S+).*""", RegexOption.IGNORE_CASE)
|
||||||
|
|
||||||
|
|
||||||
class CallGraph(private val program: Program) : IAstVisitor {
|
class CallGraph(private val program: Program, private val asmFileLoader: (filename: String, source: Path)->String) : IAstVisitor {
|
||||||
|
|
||||||
val imports = mutableMapOf<Module, List<Module>>().withDefault { mutableListOf() }
|
val imports = mutableMapOf<Module, List<Module>>().withDefault { mutableListOf() }
|
||||||
val importedBy = mutableMapOf<Module, List<Module>>().withDefault { mutableListOf() }
|
val importedBy = mutableMapOf<Module, List<Module>>().withDefault { mutableListOf() }
|
||||||
@ -80,7 +80,7 @@ class CallGraph(private val program: Program) : IAstVisitor {
|
|||||||
imports[thisModule] = imports.getValue(thisModule).plus(importedModule)
|
imports[thisModule] = imports.getValue(thisModule).plus(importedModule)
|
||||||
importedBy[importedModule] = importedBy.getValue(importedModule).plus(thisModule)
|
importedBy[importedModule] = importedBy.getValue(importedModule).plus(thisModule)
|
||||||
} else if (directive.directive == "%asminclude") {
|
} else if (directive.directive == "%asminclude") {
|
||||||
val asm = loadAsmIncludeFile(directive.args[0].str!!, thisModule.source)
|
val asm = asmFileLoader(directive.args[0].str!!, thisModule.source)
|
||||||
val scope = directive.definingSubroutine()
|
val scope = directive.definingSubroutine()
|
||||||
if(scope!=null) {
|
if(scope!=null) {
|
||||||
scanAssemblyCode(asm, directive, scope)
|
scanAssemblyCode(asm, directive, scope)
|
||||||
|
@ -4,6 +4,7 @@ import prog8.ast.IBuiltinFunctions
|
|||||||
import prog8.ast.Program
|
import prog8.ast.Program
|
||||||
import prog8.compiler.IErrorReporter
|
import prog8.compiler.IErrorReporter
|
||||||
import prog8.compiler.target.ICompilationTarget
|
import prog8.compiler.target.ICompilationTarget
|
||||||
|
import java.nio.file.Path
|
||||||
|
|
||||||
|
|
||||||
internal fun Program.constantFold(errors: IErrorReporter, compTarget: ICompilationTarget) {
|
internal fun Program.constantFold(errors: IErrorReporter, compTarget: ICompilationTarget) {
|
||||||
@ -40,8 +41,11 @@ internal fun Program.constantFold(errors: IErrorReporter, compTarget: ICompilati
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
internal fun Program.optimizeStatements(errors: IErrorReporter, functions: IBuiltinFunctions, compTarget: ICompilationTarget): Int {
|
internal fun Program.optimizeStatements(errors: IErrorReporter,
|
||||||
val optimizer = StatementOptimizer(this, errors, functions, compTarget)
|
functions: IBuiltinFunctions,
|
||||||
|
compTarget: ICompilationTarget,
|
||||||
|
asmFileLoader: (filename: String, source: Path)->String): Int {
|
||||||
|
val optimizer = StatementOptimizer(this, errors, functions, compTarget, asmFileLoader)
|
||||||
optimizer.visit(this)
|
optimizer.visit(this)
|
||||||
val optimizationCount = optimizer.applyModifications()
|
val optimizationCount = optimizer.applyModifications()
|
||||||
|
|
||||||
|
@ -12,17 +12,19 @@ import prog8.ast.walk.IAstModification
|
|||||||
import prog8.ast.walk.IAstVisitor
|
import prog8.ast.walk.IAstVisitor
|
||||||
import prog8.compiler.IErrorReporter
|
import prog8.compiler.IErrorReporter
|
||||||
import prog8.compiler.target.ICompilationTarget
|
import prog8.compiler.target.ICompilationTarget
|
||||||
|
import java.nio.file.Path
|
||||||
import kotlin.math.floor
|
import kotlin.math.floor
|
||||||
|
|
||||||
|
|
||||||
internal class StatementOptimizer(private val program: Program,
|
internal class StatementOptimizer(private val program: Program,
|
||||||
private val errors: IErrorReporter,
|
private val errors: IErrorReporter,
|
||||||
private val functions: IBuiltinFunctions,
|
private val functions: IBuiltinFunctions,
|
||||||
private val compTarget: ICompilationTarget
|
private val compTarget: ICompilationTarget,
|
||||||
|
private val asmFileLoader: (filename: String, source: Path)->String
|
||||||
) : AstWalker() {
|
) : AstWalker() {
|
||||||
|
|
||||||
private val noModifications = emptyList<IAstModification>()
|
private val noModifications = emptyList<IAstModification>()
|
||||||
private val callgraph = CallGraph(program)
|
private val callgraph = CallGraph(program, asmFileLoader)
|
||||||
|
|
||||||
override fun after(block: Block, parent: Node): Iterable<IAstModification> {
|
override fun after(block: Block, parent: Node): Iterable<IAstModification> {
|
||||||
if("force_output" !in block.options()) {
|
if("force_output" !in block.options()) {
|
||||||
|
@ -12,12 +12,16 @@ import prog8.ast.walk.AstWalker
|
|||||||
import prog8.ast.walk.IAstModification
|
import prog8.ast.walk.IAstModification
|
||||||
import prog8.compiler.IErrorReporter
|
import prog8.compiler.IErrorReporter
|
||||||
import prog8.compiler.target.ICompilationTarget
|
import prog8.compiler.target.ICompilationTarget
|
||||||
|
import java.nio.file.Path
|
||||||
|
|
||||||
|
|
||||||
internal class UnusedCodeRemover(private val program: Program, private val errors: IErrorReporter, private val compTarget: ICompilationTarget): AstWalker() {
|
internal class UnusedCodeRemover(private val program: Program,
|
||||||
|
private val errors: IErrorReporter,
|
||||||
|
private val compTarget: ICompilationTarget,
|
||||||
|
private val asmFileLoader: (filename: String, source: Path)->String): AstWalker() {
|
||||||
|
|
||||||
override fun before(program: Program, parent: Node): Iterable<IAstModification> {
|
override fun before(program: Program, parent: Node): Iterable<IAstModification> {
|
||||||
val callgraph = CallGraph(program)
|
val callgraph = CallGraph(program, asmFileLoader)
|
||||||
val removals = mutableListOf<IAstModification>()
|
val removals = mutableListOf<IAstModification>()
|
||||||
|
|
||||||
// remove all subroutines that aren't called, or are empty
|
// remove all subroutines that aren't called, or are empty
|
||||||
|
@ -5,8 +5,6 @@ TODO
|
|||||||
- add sound to the cx16 tehtriz
|
- add sound to the cx16 tehtriz
|
||||||
|
|
||||||
- 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)
|
- 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)
|
||||||
- refactor the asmgen into their own submodule?
|
|
||||||
- refactor the compiler optimizers into their own submodule?
|
|
||||||
- optimize swap of two memread values with index, using the same pointer expression/variable, like swap(@(ptr+1), @(ptr+2))
|
- optimize swap of two memread values with index, using the same pointer expression/variable, like swap(@(ptr+1), @(ptr+2))
|
||||||
- optimize several inner loops in gfx2 (highres 4 color mode)
|
- optimize several inner loops in gfx2 (highres 4 color mode)
|
||||||
- use the 65c02 bit clear/set/test instructions for single-bit operations
|
- use the 65c02 bit clear/set/test instructions for single-bit operations
|
||||||
@ -14,6 +12,8 @@ TODO
|
|||||||
- add modes 2 and 3 to gfx2 (lowres 4 color and 16 color)
|
- add modes 2 and 3 to gfx2 (lowres 4 color and 16 color)
|
||||||
- add a flood fill routine to gfx2?
|
- add a flood fill routine to gfx2?
|
||||||
- add a f_seek() routine for the Cx16 that uses its seek dos api?
|
- add a f_seek() routine for the Cx16 that uses its seek dos api?
|
||||||
|
- refactor the asmgen into their own submodule?
|
||||||
|
- refactor the compiler optimizers into their own submodule?
|
||||||
- optimizer: detect variables that are written but never read - mark those as unused too and remove them, such as uword unused = memory("unused222", 20) - also remove the memory slab allocation
|
- optimizer: detect variables that are written but never read - mark those as unused too and remove them, such as uword unused = memory("unused222", 20) - also remove the memory slab allocation
|
||||||
- add a compiler option to not remove unused subroutines. this allows for building library programs
|
- add a compiler option to not remove unused subroutines. this allows for building library programs
|
||||||
- make it possible to use cpu opcodes such as 'nop' as variable names by prefixing all asm vars with something such as 'v_'
|
- make it possible to use cpu opcodes such as 'nop' as variable names by prefixing all asm vars with something such as 'v_'
|
||||||
|
Loading…
Reference in New Issue
Block a user