mirror of
https://github.com/irmen/prog8.git
synced 2024-08-18 23:29:32 +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:
|
||||
// - 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)
|
||||
// - do NOT do this is the statement can be transformed into an asm subroutine later!
|
||||
if(subroutine.asmAddress==null && !subroutine.canBeAsmSubroutine) {
|
||||
if(subroutine.asmAddress==null) {
|
||||
if(subroutine.asmParameterRegisters.isEmpty()) {
|
||||
subroutine.parameters
|
||||
.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)
|
||||
}
|
||||
|
@ -1,10 +1,12 @@
|
||||
package prog8.ast.processing
|
||||
|
||||
import prog8.ast.*
|
||||
import prog8.ast.Module
|
||||
import prog8.ast.Program
|
||||
import prog8.ast.base.DataType
|
||||
import prog8.ast.base.FatalAstException
|
||||
import prog8.ast.base.initvarsSubName
|
||||
import prog8.ast.expressions.*
|
||||
import prog8.ast.mangledStructMemberName
|
||||
import prog8.ast.statements.*
|
||||
|
||||
|
||||
|
@ -1,6 +1,8 @@
|
||||
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.FatalAstException
|
||||
import prog8.ast.base.printWarning
|
||||
|
@ -599,40 +599,6 @@ class Subroutine(override val name: String,
|
||||
.filter { it is InlineAssembly }
|
||||
.map { (it as InlineAssembly).assembly }
|
||||
.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,
|
||||
|
@ -96,7 +96,7 @@ fun compileProgram(filepath: Path,
|
||||
programAst.checkValid(compilerOptions) // check if final tree is valid
|
||||
programAst.checkRecursion() // check if there are recursive subroutine calls
|
||||
|
||||
printAst(programAst)
|
||||
// printAst(programAst)
|
||||
|
||||
if(writeAssembly) {
|
||||
// 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?)
|
||||
*/
|
||||
|
||||
@ -108,11 +106,6 @@ internal class StatementOptimizer(private val program: Program) : IAstModifyingV
|
||||
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) {
|
||||
printWarning("removing unused subroutine '${subroutine.name}'", subroutine.position)
|
||||
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.
|
||||
|
||||
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
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
@ -38,11 +27,6 @@ Add more compiler optimizations to the existing ones.
|
||||
- on the language AST level
|
||||
- on the final assembly source level
|
||||
- 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)
|
||||
|
||||
Also some library routines and code patterns could perhaps be optimized further
|
||||
|
@ -27,4 +27,12 @@ main {
|
||||
; uw *= 2
|
||||
; ub *= 2
|
||||
}
|
||||
|
||||
|
||||
asmsub aa(byte arg @ Y) clobbers() {
|
||||
%asm {{
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user