From 68df1730f56f705872f77d8eb350dc5466c330e5 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Wed, 14 Aug 2019 23:17:50 +0200 Subject: [PATCH] cleaned up some stuff, improved checking of asmsub statement body --- .../ast/processing/AstIdentifiersChecker.kt | 7 ++-- .../ast/processing/StatementReorderer.kt | 4 ++- .../prog8/ast/processing/TypecastsAdder.kt | 4 ++- .../src/prog8/ast/statements/AstStatements.kt | 34 ------------------- compiler/src/prog8/compiler/Main.kt | 2 +- .../src/prog8/optimizer/StatementOptimizer.kt | 9 +---- docs/source/todo.rst | 16 --------- examples/test.p8 | 8 +++++ 8 files changed, 21 insertions(+), 63 deletions(-) diff --git a/compiler/src/prog8/ast/processing/AstIdentifiersChecker.kt b/compiler/src/prog8/ast/processing/AstIdentifiersChecker.kt index dd671899c..56ab1dd19 100644 --- a/compiler/src/prog8/ast/processing/AstIdentifiersChecker.kt +++ b/compiler/src/prog8/ast/processing/AstIdentifiersChecker.kt @@ -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) } diff --git a/compiler/src/prog8/ast/processing/StatementReorderer.kt b/compiler/src/prog8/ast/processing/StatementReorderer.kt index 11d6a5a66..d30047f4d 100644 --- a/compiler/src/prog8/ast/processing/StatementReorderer.kt +++ b/compiler/src/prog8/ast/processing/StatementReorderer.kt @@ -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.* diff --git a/compiler/src/prog8/ast/processing/TypecastsAdder.kt b/compiler/src/prog8/ast/processing/TypecastsAdder.kt index 09ef54ddd..bc2053b3d 100644 --- a/compiler/src/prog8/ast/processing/TypecastsAdder.kt +++ b/compiler/src/prog8/ast/processing/TypecastsAdder.kt @@ -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 diff --git a/compiler/src/prog8/ast/statements/AstStatements.kt b/compiler/src/prog8/ast/statements/AstStatements.kt index 4499b9b3c..1bcd79aae 100644 --- a/compiler/src/prog8/ast/statements/AstStatements.kt +++ b/compiler/src/prog8/ast/statements/AstStatements.kt @@ -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, diff --git a/compiler/src/prog8/compiler/Main.kt b/compiler/src/prog8/compiler/Main.kt index 5d2eae91c..d0daeaff4 100644 --- a/compiler/src/prog8/compiler/Main.kt +++ b/compiler/src/prog8/compiler/Main.kt @@ -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 diff --git a/compiler/src/prog8/optimizer/StatementOptimizer.kt b/compiler/src/prog8/optimizer/StatementOptimizer.kt index b43675418..5842228c8 100644 --- a/compiler/src/prog8/optimizer/StatementOptimizer.kt +++ b/compiler/src/prog8/optimizer/StatementOptimizer.kt @@ -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++ diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 00112afcd..8b3b8f1f0 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -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 diff --git a/examples/test.p8 b/examples/test.p8 index 9c1cab312..e7c22c18e 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -27,4 +27,12 @@ main { ; uw *= 2 ; ub *= 2 } + + + asmsub aa(byte arg @ Y) clobbers() { + %asm {{ + rts + }} + } + }