mirror of
https://github.com/irmen/prog8.git
synced 2025-02-19 11:31:07 +00:00
cleaned up some stuff, improved checking of asmsub statement body
This commit is contained in:
parent
d62ab93b24
commit
68df1730f5
@ -144,8 +144,7 @@ internal class AstIdentifiersChecker(private val program: Program) : IAstModifyi
|
|||||||
// NOTE:
|
// NOTE:
|
||||||
// - numeric types BYTE and WORD and FLOAT are passed by value;
|
// - numeric types BYTE and WORD and FLOAT are passed by value;
|
||||||
// - strings, arrays, matrices are passed by reference (their 16-bit address is passed as an uword parameter)
|
// - strings, arrays, matrices are passed by reference (their 16-bit address is passed as an uword parameter)
|
||||||
// - do NOT do this is the statement can be transformed into an asm subroutine later!
|
if(subroutine.asmAddress==null) {
|
||||||
if(subroutine.asmAddress==null && !subroutine.canBeAsmSubroutine) {
|
|
||||||
if(subroutine.asmParameterRegisters.isEmpty()) {
|
if(subroutine.asmParameterRegisters.isEmpty()) {
|
||||||
subroutine.parameters
|
subroutine.parameters
|
||||||
.filter { it.name !in namesInSub }
|
.filter { it.name !in namesInSub }
|
||||||
@ -157,6 +156,10 @@ internal class AstIdentifiersChecker(private val program: Program) : IAstModifyi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(subroutine.isAsmSubroutine && subroutine.statements.any{it !is InlineAssembly}) {
|
||||||
|
checkResult.add(SyntaxError("asmsub can only contain inline assembly (%asm)", subroutine.position))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return super.visit(subroutine)
|
return super.visit(subroutine)
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
package prog8.ast.processing
|
package prog8.ast.processing
|
||||||
|
|
||||||
import prog8.ast.*
|
import prog8.ast.Module
|
||||||
|
import prog8.ast.Program
|
||||||
import prog8.ast.base.DataType
|
import prog8.ast.base.DataType
|
||||||
import prog8.ast.base.FatalAstException
|
import prog8.ast.base.FatalAstException
|
||||||
import prog8.ast.base.initvarsSubName
|
import prog8.ast.base.initvarsSubName
|
||||||
import prog8.ast.expressions.*
|
import prog8.ast.expressions.*
|
||||||
|
import prog8.ast.mangledStructMemberName
|
||||||
import prog8.ast.statements.*
|
import prog8.ast.statements.*
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package prog8.ast.processing
|
package prog8.ast.processing
|
||||||
|
|
||||||
import prog8.ast.*
|
import prog8.ast.IFunctionCall
|
||||||
|
import prog8.ast.INameScope
|
||||||
|
import prog8.ast.Program
|
||||||
import prog8.ast.base.DataType
|
import prog8.ast.base.DataType
|
||||||
import prog8.ast.base.FatalAstException
|
import prog8.ast.base.FatalAstException
|
||||||
import prog8.ast.base.printWarning
|
import prog8.ast.base.printWarning
|
||||||
|
@ -599,40 +599,6 @@ class Subroutine(override val name: String,
|
|||||||
.filter { it is InlineAssembly }
|
.filter { it is InlineAssembly }
|
||||||
.map { (it as InlineAssembly).assembly }
|
.map { (it as InlineAssembly).assembly }
|
||||||
.count { " rti" in it || "\trti" in it || " rts" in it || "\trts" in it || " jmp" in it || "\tjmp" in it }
|
.count { " rti" in it || "\trti" in it || " rts" in it || "\trts" in it || " jmp" in it || "\tjmp" in it }
|
||||||
|
|
||||||
val canBeAsmSubroutine =false // TODO disabled for now, see below about problem with converting to asm subroutine
|
|
||||||
// !isAsmSubroutine
|
|
||||||
// && ((parameters.size == 1 && parameters[0].type in setOf(DataType.BYTE, DataType.UBYTE, DataType.WORD, DataType.UWORD))
|
|
||||||
// || (parameters.size == 2 && parameters.map { it.type }.all { it == DataType.BYTE || it == DataType.UBYTE }))
|
|
||||||
|
|
||||||
fun intoAsmSubroutine(): Subroutine {
|
|
||||||
// TODO turn subroutine into asm calling convention. Requires rethinking of how parameters are handled (conflicts with local vardefs now, see AstIdentifierChecker...)
|
|
||||||
return this // TODO
|
|
||||||
|
|
||||||
// println("TO ASM $this") // TODO
|
|
||||||
// val paramregs = if (parameters.size == 1 && parameters[0].type in setOf(DataType.BYTE, DataType.UBYTE))
|
|
||||||
// listOf(RegisterOrStatusflag(RegisterOrPair.Y, null, null))
|
|
||||||
// else if (parameters.size == 1 && parameters[0].type in setOf(DataType.WORD, DataType.UWORD))
|
|
||||||
// listOf(RegisterOrStatusflag(RegisterOrPair.AY, null, null))
|
|
||||||
// else if (parameters.size == 2 && parameters.map { it.type }.all { it == DataType.BYTE || it == DataType.UBYTE })
|
|
||||||
// listOf(RegisterOrStatusflag(RegisterOrPair.A, null, null), RegisterOrStatusflag(RegisterOrPair.Y, null, null))
|
|
||||||
// else throw FatalAstException("cannot convert subroutine to asm parameters")
|
|
||||||
//
|
|
||||||
// val asmsub=Subroutine(
|
|
||||||
// name,
|
|
||||||
// parameters,
|
|
||||||
// returntypes,
|
|
||||||
// paramregs,
|
|
||||||
// emptyList(),
|
|
||||||
// emptySet(),
|
|
||||||
// null,
|
|
||||||
// true,
|
|
||||||
// statements,
|
|
||||||
// position
|
|
||||||
// )
|
|
||||||
// asmsub.linkParents(parent)
|
|
||||||
// return asmsub
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
open class SubroutineParameter(val name: String,
|
open class SubroutineParameter(val name: String,
|
||||||
|
@ -96,7 +96,7 @@ fun compileProgram(filepath: Path,
|
|||||||
programAst.checkValid(compilerOptions) // check if final tree is valid
|
programAst.checkValid(compilerOptions) // check if final tree is valid
|
||||||
programAst.checkRecursion() // check if there are recursive subroutine calls
|
programAst.checkRecursion() // check if there are recursive subroutine calls
|
||||||
|
|
||||||
printAst(programAst)
|
// printAst(programAst)
|
||||||
|
|
||||||
if(writeAssembly) {
|
if(writeAssembly) {
|
||||||
// asm generation directly from the Ast, no need for intermediate code
|
// asm generation directly from the Ast, no need for intermediate code
|
||||||
|
@ -16,9 +16,7 @@ import kotlin.math.floor
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
todo: subroutines with 1 or 2 byte args or 1 word arg can be converted to asm sub calling convention (args in registers)
|
TODO: analyse for unreachable code and remove that (f.i. code after goto or return that has no label so can never be jumped to) + print warning about this
|
||||||
todo analyse for unreachable code and remove that (f.i. code after goto or return that has no label so can never be jumped to) + print warning about this
|
|
||||||
|
|
||||||
TODO: proper inlining of small subroutines (correctly renaming/relocating all variables in them and refs to those as well, or restrict to subs without variables?)
|
TODO: proper inlining of small subroutines (correctly renaming/relocating all variables in them and refs to those as well, or restrict to subs without variables?)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -108,11 +106,6 @@ internal class StatementOptimizer(private val program: Program) : IAstModifyingV
|
|||||||
linesToRemove.reversed().forEach{subroutine.statements.removeAt(it)}
|
linesToRemove.reversed().forEach{subroutine.statements.removeAt(it)}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(subroutine.canBeAsmSubroutine) {
|
|
||||||
optimizationsDone++
|
|
||||||
return subroutine.intoAsmSubroutine() // TODO this doesn't work yet due to parameter vardecl issue
|
|
||||||
}
|
|
||||||
|
|
||||||
if(subroutine !in callgraph.usedSymbols && !forceOutput) {
|
if(subroutine !in callgraph.usedSymbols && !forceOutput) {
|
||||||
printWarning("removing unused subroutine '${subroutine.name}'", subroutine.position)
|
printWarning("removing unused subroutine '${subroutine.name}'", subroutine.position)
|
||||||
optimizationsDone++
|
optimizationsDone++
|
||||||
|
@ -19,17 +19,6 @@ these should call optimized pieces of assembly code, so they run as fast as poss
|
|||||||
|
|
||||||
For now, we have the ``memcopy``, ``memset`` and ``strlen`` builtin functions.
|
For now, we have the ``memcopy``, ``memset`` and ``strlen`` builtin functions.
|
||||||
|
|
||||||
Fixes
|
|
||||||
^^^^^
|
|
||||||
|
|
||||||
fix asmsub parameters so this works::
|
|
||||||
|
|
||||||
asmsub aa(byte arg @ Y) -> clobbers() -> () {
|
|
||||||
byte local = arg ; @todo fix 'undefined symbol arg' that occurs here
|
|
||||||
A=44
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
More optimizations
|
More optimizations
|
||||||
^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
@ -38,11 +27,6 @@ Add more compiler optimizations to the existing ones.
|
|||||||
- on the language AST level
|
- on the language AST level
|
||||||
- on the final assembly source level
|
- on the final assembly source level
|
||||||
- can the parameter passing to subroutines be optimized to avoid copying?
|
- can the parameter passing to subroutines be optimized to avoid copying?
|
||||||
|
|
||||||
- subroutines with 1 or 2 byte args (or 1 word arg) should be converted to asm calling convention with the args in A/Y register
|
|
||||||
this requires rethinking the way parameters are represented, simply injecting vardecls to
|
|
||||||
declare local variables for them is not always correct anymore
|
|
||||||
|
|
||||||
- working subroutine inlining (taking care of vars and identifier refs to them)
|
- working subroutine inlining (taking care of vars and identifier refs to them)
|
||||||
|
|
||||||
Also some library routines and code patterns could perhaps be optimized further
|
Also some library routines and code patterns could perhaps be optimized further
|
||||||
|
@ -27,4 +27,12 @@ main {
|
|||||||
; uw *= 2
|
; uw *= 2
|
||||||
; ub *= 2
|
; ub *= 2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
asmsub aa(byte arg @ Y) clobbers() {
|
||||||
|
%asm {{
|
||||||
|
rts
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user