From 3ab641aa2119868e34468531bf317ad3c5c9c844 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Fri, 30 Oct 2020 15:02:42 +0100 Subject: [PATCH] removed @stack in subroutine args and returnvalues, can only use variables or registers now --- compiler/src/prog8/ast/AstToSourceCode.kt | 1 - compiler/src/prog8/ast/antlr/Antr2Kotlin.kt | 7 +- .../src/prog8/ast/statements/AstStatements.kt | 10 +-- .../compiler/target/c64/codegen/AsmGen.kt | 1 - .../target/c64/codegen/ExpressionsAsmGen.kt | 66 +++++++++---------- .../target/c64/codegen/FunctionCallAsmGen.kt | 18 +---- docs/source/todo.rst | 1 - parser/antlr/prog8.g4 | 4 +- 8 files changed, 44 insertions(+), 64 deletions(-) diff --git a/compiler/src/prog8/ast/AstToSourceCode.kt b/compiler/src/prog8/ast/AstToSourceCode.kt index 7d6b01306..fd956b9aa 100644 --- a/compiler/src/prog8/ast/AstToSourceCode.kt +++ b/compiler/src/prog8/ast/AstToSourceCode.kt @@ -143,7 +143,6 @@ class AstToSourceCode(val output: (text: String) -> Unit, val program: Program): for(param in subroutine.parameters.zip(subroutine.asmParameterRegisters)) { val reg = when { - param.second.stack -> "stack" param.second.registerOrPair!=null -> param.second.registerOrPair.toString() param.second.statusflag!=null -> param.second.statusflag.toString() else -> "?????" diff --git a/compiler/src/prog8/ast/antlr/Antr2Kotlin.kt b/compiler/src/prog8/ast/antlr/Antr2Kotlin.kt index b1f99f336..c5435c98e 100644 --- a/compiler/src/prog8/ast/antlr/Antr2Kotlin.kt +++ b/compiler/src/prog8/ast/antlr/Antr2Kotlin.kt @@ -254,8 +254,8 @@ private fun prog8Parser.Asmsub_declContext.toAst(): AsmsubDecl { val clobbers = asmsub_clobbers()?.clobber()?.toAst() ?: emptySet() val normalParameters = params.map { SubroutineParameter(it.name, it.type, it.position) } val normalReturntypes = returns.map { it.type } - val paramRegisters = params.map { RegisterOrStatusflag(it.registerOrPair, it.statusflag, false) } - val returnRegisters = returns.map { RegisterOrStatusflag(it.registerOrPair, it.statusflag, it.stack) } + val paramRegisters = params.map { RegisterOrStatusflag(it.registerOrPair, it.statusflag) } + val returnRegisters = returns.map { RegisterOrStatusflag(it.registerOrPair, it.statusflag) } return AsmsubDecl(name, normalParameters, normalReturntypes, paramRegisters, returnRegisters, clobbers) } @@ -268,7 +268,6 @@ private class AsmSubroutineParameter(name: String, private class AsmSubroutineReturn(val type: DataType, val registerOrPair: RegisterOrPair?, val statusflag: Statusflag?, - val stack: Boolean, val position: Position) private fun prog8Parser.Asmsub_returnsContext.toAst(): List @@ -287,7 +286,7 @@ private fun prog8Parser.Asmsub_returnsContext.toAst(): List it.datatype().toAst(), registerorpair, statusregister, - !it.stack?.text.isNullOrEmpty(), toPosition()) + toPosition()) } private fun prog8Parser.Asmsub_paramsContext.toAst(): List diff --git a/compiler/src/prog8/ast/statements/AstStatements.kt b/compiler/src/prog8/ast/statements/AstStatements.kt index 9b46299bb..8fae929df 100644 --- a/compiler/src/prog8/ast/statements/AstStatements.kt +++ b/compiler/src/prog8/ast/statements/AstStatements.kt @@ -44,7 +44,7 @@ class BuiltinFunctionStatementPlaceholder(val name: String, override val positio } } -data class RegisterOrStatusflag(val registerOrPair: RegisterOrPair?, val statusflag: Statusflag?, val stack: Boolean) // TODO get rid of stack? +data class RegisterOrStatusflag(val registerOrPair: RegisterOrPair?, val statusflag: Statusflag?) class Block(override val name: String, val address: Int?, @@ -697,11 +697,11 @@ class Subroutine(override val name: String, private fun determineReturnRegisters(returntypes: List): List { // for non-asm subroutines, determine the return registers based on the type of the return value return when(returntypes.singleOrNull()) { - in ByteDatatypes -> listOf(RegisterOrStatusflag(RegisterOrPair.A, null, false)) - in WordDatatypes -> listOf(RegisterOrStatusflag(RegisterOrPair.AY, null, false)) - DataType.FLOAT -> listOf(RegisterOrStatusflag(RegisterOrPair.AY, null, false)) + in ByteDatatypes -> listOf(RegisterOrStatusflag(RegisterOrPair.A, null)) + in WordDatatypes -> listOf(RegisterOrStatusflag(RegisterOrPair.AY, null)) + DataType.FLOAT -> listOf(RegisterOrStatusflag(RegisterOrPair.AY, null)) null -> emptyList() - else -> listOf(RegisterOrStatusflag(RegisterOrPair.AY, null, false)) + else -> listOf(RegisterOrStatusflag(RegisterOrPair.AY, null)) } } } diff --git a/compiler/src/prog8/compiler/target/c64/codegen/AsmGen.kt b/compiler/src/prog8/compiler/target/c64/codegen/AsmGen.kt index bad1fc1f4..62d4281f7 100644 --- a/compiler/src/prog8/compiler/target/c64/codegen/AsmGen.kt +++ b/compiler/src/prog8/compiler/target/c64/codegen/AsmGen.kt @@ -1155,7 +1155,6 @@ $counterVar .byte 0""") val returnValueTarget = when { returnReg.registerOrPair!=null -> AsmAssignTarget.fromRegisters(returnReg.registerOrPair, sub, program, this) - returnReg.stack -> AsmAssignTarget(TargetStorageKind.STACK, program, this, returnType, sub) else -> throw AssemblyError("normal subroutines can't return value in status register directly") } diff --git a/compiler/src/prog8/compiler/target/c64/codegen/ExpressionsAsmGen.kt b/compiler/src/prog8/compiler/target/c64/codegen/ExpressionsAsmGen.kt index a1663e5c6..b694c0704 100644 --- a/compiler/src/prog8/compiler/target/c64/codegen/ExpressionsAsmGen.kt +++ b/compiler/src/prog8/compiler/target/c64/codegen/ExpressionsAsmGen.kt @@ -1055,41 +1055,41 @@ internal class ExpressionsAsmGen(private val program: Program, private val asmge asmgen.translateFunctionCall(expression, preserveStatusRegisterAfterCall) val returns = sub.returntypes.zip(sub.asmReturnvaluesRegisters) for ((_, reg) in returns) { - if (!reg.stack) { - // result value in cpu or status registers, put it on the stack - if (reg.registerOrPair != null) { - when (reg.registerOrPair) { - RegisterOrPair.A -> asmgen.out(" sta P8ESTACK_LO,x | dex") - RegisterOrPair.Y -> asmgen.out(" tya | sta P8ESTACK_LO,x | dex") - RegisterOrPair.AY -> asmgen.out(" sta P8ESTACK_LO,x | tya | sta P8ESTACK_HI,x | dex") - RegisterOrPair.X -> { - // return value in X register has been discarded, just push a zero - if(CompilationTarget.instance.machine.cpu==CpuType.CPU65c02) - asmgen.out(" stz P8ESTACK_LO,x") - else - asmgen.out(" lda #0 | sta P8ESTACK_LO,x") - asmgen.out(" dex") - } - RegisterOrPair.AX -> { - // return value in X register has been discarded, just push a zero in this place - asmgen.out(" sta P8ESTACK_LO,x") - if(CompilationTarget.instance.machine.cpu==CpuType.CPU65c02) - asmgen.out(" stz P8ESTACK_HI,x") - else - asmgen.out(" lda #0 | sta P8ESTACK_HI,x") - asmgen.out(" dex") - } - RegisterOrPair.XY -> { - // return value in X register has been discarded, just push a zero in this place - if(CompilationTarget.instance.machine.cpu==CpuType.CPU65c02) - asmgen.out(" stz P8ESTACK_LO,x") - else - asmgen.out(" lda #0 | sta P8ESTACK_LO,x") - asmgen.out(" tya | sta P8ESTACK_HI,x | dex") - } + // result value in cpu or status registers, put it on the stack + if (reg.registerOrPair != null) { + when (reg.registerOrPair) { + RegisterOrPair.A -> asmgen.out(" sta P8ESTACK_LO,x | dex") + RegisterOrPair.Y -> asmgen.out(" tya | sta P8ESTACK_LO,x | dex") + RegisterOrPair.AY -> asmgen.out(" sta P8ESTACK_LO,x | tya | sta P8ESTACK_HI,x | dex") + RegisterOrPair.X -> { + // return value in X register has been discarded, just push a zero + if(CompilationTarget.instance.machine.cpu==CpuType.CPU65c02) + asmgen.out(" stz P8ESTACK_LO,x") + else + asmgen.out(" lda #0 | sta P8ESTACK_LO,x") + asmgen.out(" dex") + } + RegisterOrPair.AX -> { + // return value in X register has been discarded, just push a zero in this place + asmgen.out(" sta P8ESTACK_LO,x") + if(CompilationTarget.instance.machine.cpu==CpuType.CPU65c02) + asmgen.out(" stz P8ESTACK_HI,x") + else + asmgen.out(" lda #0 | sta P8ESTACK_HI,x") + asmgen.out(" dex") + } + RegisterOrPair.XY -> { + // return value in X register has been discarded, just push a zero in this place + if(CompilationTarget.instance.machine.cpu==CpuType.CPU65c02) + asmgen.out(" stz P8ESTACK_LO,x") + else + asmgen.out(" lda #0 | sta P8ESTACK_LO,x") + asmgen.out(" tya | sta P8ESTACK_HI,x | dex") } } - // return value from a statusregister is not put on the stack, it should be acted on via a conditional branch such as if_cc + } + else if(reg.statusflag!=null) { + TODO("statusflag result onto stack") } } } diff --git a/compiler/src/prog8/compiler/target/c64/codegen/FunctionCallAsmGen.kt b/compiler/src/prog8/compiler/target/c64/codegen/FunctionCallAsmGen.kt index 8ae4d56c3..38eb28886 100644 --- a/compiler/src/prog8/compiler/target/c64/codegen/FunctionCallAsmGen.kt +++ b/compiler/src/prog8/compiler/target/c64/codegen/FunctionCallAsmGen.kt @@ -18,14 +18,7 @@ internal class FunctionCallAsmGen(private val program: Program, private val asmg val sub = stmt.target.targetSubroutine(program.namespace)!! val preserveStatusRegisterAfterCall = sub.asmReturnvaluesRegisters.any {it.statusflag!=null} translateFunctionCall(stmt, preserveStatusRegisterAfterCall) - // discard resultvalues that might be on the stack: - val returns = sub.returntypes.zip(sub.asmReturnvaluesRegisters) - for ((t, reg) in returns) { - if (reg.stack) { - if (t in IntegerDatatypes || t in PassByReferenceDatatypes) asmgen.out(" inx") - else if (t == DataType.FLOAT) asmgen.out(" inx | inx | inx") - } - } + // functioncalls no longer return results on the stack, so simply ignore the results in the registers if(preserveStatusRegisterAfterCall) asmgen.out(" plp\t; restore status flags from call") } @@ -104,7 +97,6 @@ internal class FunctionCallAsmGen(private val program: Program, private val asmg for(argi in stmt.args.zip(sub.asmParameterRegisters).withIndex()) { when { - argi.value.second.stack -> TODO("asmsub @stack parameter") argi.value.second.statusflag == Statusflag.Pc -> { require(argForCarry == null) argForCarry = argi @@ -191,20 +183,12 @@ internal class FunctionCallAsmGen(private val program: Program, private val asmg val paramRegister = sub.asmParameterRegisters[parameter.index] val statusflag = paramRegister.statusflag val register = paramRegister.registerOrPair - val stack = paramRegister.stack val requiredDt = parameter.value.type if(requiredDt!=valueDt) { if(valueDt largerThan requiredDt) throw AssemblyError("can only convert byte values to word param types") } when { - stack -> { - // push arg onto the stack - // note: argument order is reversed (first argument will be deepest on the stack) - asmgen.translateExpression(value) - if(requiredDt!=valueDt) - asmgen.signExtendStackLsb(valueDt) - } statusflag!=null -> { if(requiredDt!=valueDt) throw AssemblyError("for statusflag, byte value is required") diff --git a/docs/source/todo.rst b/docs/source/todo.rst index a4b7defdb..9a86282c7 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -6,7 +6,6 @@ TODO - make memset(w) and memcopy able to work with >256 bytes - make memset and memcopy use the ROM routines on the CX16 - calling convention for builtin functions no longer via stack but via statically allocated vars inside the subroutine proc (just as normal subroutines) -- get rid of @stack in asmsub (syntax, ast) altogether (because all subroutines are no longer using this calling convention anymore) - make it possible to use cpu opcodes such as 'nop' as variable names by prefixing all asm vars with something such as '_' - option to load the built-in library files from a directory instead of the embedded ones (for easier library development/debugging) - see if we can group some errors together for instance the (now single) errors about unidentified symbols diff --git a/parser/antlr/prog8.g4 b/parser/antlr/prog8.g4 index db30fd115..9a79c90c8 100644 --- a/parser/antlr/prog8.g4 +++ b/parser/antlr/prog8.g4 @@ -271,7 +271,7 @@ asmsub_decl : identifier '(' asmsub_params? ')' asmsub_clobbers? asmsub_returns? asmsub_params : asmsub_param (',' EOL? asmsub_param)* ; -asmsub_param : vardecl '@' identifier ; // A,X,Y,AX,AY,XY,Pc,Pz,Pn,Pv allowed. TODO implement stack='stack' +asmsub_param : vardecl '@' identifier ; // A,X,Y,AX,AY,XY,Pc,Pz,Pn,Pv allowed. asmsub_clobbers : 'clobbers' '(' clobber? ')' ; @@ -279,7 +279,7 @@ clobber : identifier (',' identifier)* ; // A,X,Y allowed asmsub_returns : '->' asmsub_return (',' EOL? asmsub_return)* ; -asmsub_return : datatype '@' (identifier | stack='stack') ; // A,X,Y,AX,AY,XY,Pc,Pz,Pn,Pv allowed +asmsub_return : datatype '@' identifier ; // A,X,Y,AX,AY,XY,Pc,Pz,Pn,Pv allowed if_stmt : 'if' expression EOL? (statement | statement_block) EOL? else_part? ; // statement is constrained later