From ff715881bca5e54f0e936fe64515cfe28e79c454 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Sun, 21 Nov 2021 23:21:39 +0100 Subject: [PATCH] allow scoped identifiers to reference a subroutine parameter directly. also for asmsubroutines, but the asm generation for that is not yet done. --- .../compiler/target/cpu6502/codegen/AsmGen.kt | 1 - .../codegen/assignment/AsmAssignment.kt | 12 +++++- codeGeneration/test/AsmGenSymbolsTests.kt | 6 +-- .../compiler/BeforeAsmGenerationAstChanger.kt | 18 +++++---- .../astprocessing/AstIdentifiersChecker.kt | 2 +- .../astprocessing/AstVariousTransforms.kt | 4 +- compiler/test/TestMemory.kt | 22 +++++------ compilerAst/src/prog8/ast/AstToplevel.kt | 28 ++++++++------ compilerAst/src/prog8/ast/Program.kt | 2 +- .../src/prog8/ast/antlr/Antlr2Kotlin.kt | 4 ++ .../src/prog8/ast/statements/AstStatements.kt | 38 ++++++++++++++++--- docs/source/todo.rst | 6 +++ examples/test.p8 | 28 +++++++++----- 13 files changed, 117 insertions(+), 54 deletions(-) diff --git a/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/AsmGen.kt b/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/AsmGen.kt index 289166bd8..6eb363063 100644 --- a/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/AsmGen.kt +++ b/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/AsmGen.kt @@ -720,7 +720,6 @@ class AsmGen(private val program: Program, internal fun translate(stmt: Statement) { outputSourceLine(stmt) when(stmt) { - is ParameterVarDecl -> { /* subroutine parameter vardecls don't get any special treatment here */ } is VarDecl -> translate(stmt) is NopStatement -> {} is Directive -> translate(stmt) diff --git a/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/assignment/AsmAssignment.kt b/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/assignment/AsmAssignment.kt index 436ba603a..96f678e73 100644 --- a/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/assignment/AsmAssignment.kt +++ b/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/assignment/AsmAssignment.kt @@ -62,7 +62,13 @@ internal class AsmAssignTarget(val kind: TargetStorageKind, throw AssemblyError("unknown dt") val dt = idt.getOr(DataType.UNDEFINED) when { - identifier != null -> AsmAssignTarget(TargetStorageKind.VARIABLE, program, asmgen, dt, assign.definingSubroutine, variableAsmName = asmgen.asmVariableName(identifier!!), origAstTarget = this) + identifier != null -> { + val parameter = identifier!!.targetVarDecl(program)?.subroutineParameter + if(parameter!=null && parameter.definingSubroutine!!.isAsmSubroutine) { + TODO("ASSIGN ASMPARAM $parameter :: $assign") + } + AsmAssignTarget(TargetStorageKind.VARIABLE, program, asmgen, dt, assign.definingSubroutine, variableAsmName = asmgen.asmVariableName(identifier!!), origAstTarget = this) + } arrayindexed != null -> AsmAssignTarget(TargetStorageKind.ARRAY, program, asmgen, dt, assign.definingSubroutine, array = arrayindexed, origAstTarget = this) memoryAddress != null -> AsmAssignTarget(TargetStorageKind.MEMORY, program, asmgen, dt, assign.definingSubroutine, memory = memoryAddress, origAstTarget = this) else -> throw AssemblyError("weird target") @@ -133,6 +139,10 @@ internal class AsmAssignSource(val kind: SourceStorageKind, is StringLiteralValue -> throw AssemblyError("string literal value should not occur anymore for asm generation") is ArrayLiteralValue -> throw AssemblyError("array literal value should not occur anymore for asm generation") is IdentifierReference -> { + val parameter = value.targetVarDecl(program)?.subroutineParameter + if(parameter!=null && parameter.definingSubroutine!!.isAsmSubroutine) { + TODO("ASSIGN SOURCE FROM ASMPARAM $parameter :: $value") + } val dt = value.inferType(program).getOr(DataType.UNDEFINED) val varName=asmgen.asmVariableName(value) // special case: "cx16.r[0-15]" are 16-bits virtual registers of the commander X16 system diff --git a/codeGeneration/test/AsmGenSymbolsTests.kt b/codeGeneration/test/AsmGenSymbolsTests.kt index c371671a6..4748ba7fd 100644 --- a/codeGeneration/test/AsmGenSymbolsTests.kt +++ b/codeGeneration/test/AsmGenSymbolsTests.kt @@ -46,8 +46,8 @@ class AsmGenSymbolsTests: StringSpec({ } */ - val varInSub = VarDecl(VarDeclType.VAR, DataType.UWORD, ZeropageWish.DONTCARE, null, "localvar", NumericLiteralValue.optimalInteger(1234, Position.DUMMY), false, false, false, Position.DUMMY) - val var2InSub = VarDecl(VarDeclType.VAR, DataType.UWORD, ZeropageWish.DONTCARE, null, "tgt", null, false, false, false, Position.DUMMY) + val varInSub = VarDecl(VarDeclType.VAR, DataType.UWORD, ZeropageWish.DONTCARE, null, "localvar", NumericLiteralValue.optimalInteger(1234, Position.DUMMY), false, false, false, null, Position.DUMMY) + val var2InSub = VarDecl(VarDeclType.VAR, DataType.UWORD, ZeropageWish.DONTCARE, null, "tgt", null, false, false, false, null, Position.DUMMY) val labelInSub = Label("locallabel", Position.DUMMY) val tgt = AssignTarget(IdentifierReference(listOf("tgt"), Position.DUMMY), null, null, Position.DUMMY) @@ -63,7 +63,7 @@ class AsmGenSymbolsTests: StringSpec({ val statements = mutableListOf(varInSub, var2InSub, labelInSub, assign1, assign2, assign3, assign4, assign5, assign6, assign7, assign8) val subroutine = Subroutine("start", mutableListOf(), emptyList(), emptyList(), emptyList(), emptySet(), null, false, false, statements, Position.DUMMY) val labelInBlock = Label("label_outside", Position.DUMMY) - val varInBlock = VarDecl(VarDeclType.VAR, DataType.UWORD, ZeropageWish.DONTCARE, null, "var_outside", null, false, false, false, Position.DUMMY) + val varInBlock = VarDecl(VarDeclType.VAR, DataType.UWORD, ZeropageWish.DONTCARE, null, "var_outside", null, false, false, false, null, Position.DUMMY) val block = Block("main", null, mutableListOf(labelInBlock, varInBlock, subroutine), false, Position.DUMMY) val module = Module(mutableListOf(block), Position.DUMMY, SourceCode.Generated("test")) diff --git a/compiler/src/prog8/compiler/BeforeAsmGenerationAstChanger.kt b/compiler/src/prog8/compiler/BeforeAsmGenerationAstChanger.kt index 9a7f3064e..5e54533f6 100644 --- a/compiler/src/prog8/compiler/BeforeAsmGenerationAstChanger.kt +++ b/compiler/src/prog8/compiler/BeforeAsmGenerationAstChanger.kt @@ -83,14 +83,18 @@ internal class BeforeAsmGenerationAstChanger(val program: Program, private val o IAstModification.ReplaceNode(it, uwordParam, subroutine) } - val stringParamNames = stringParams.map { it.name }.toSet() - val varsChanges = subroutine.statements - .filterIsInstance() - .filter { it.autogeneratedDontRemove && it.name in stringParamNames } - .map { - val newvar = VarDecl(it.type, DataType.UWORD, it.zeropage, null, it.name, null, false, true, it.sharedWithAsm, it.position) - IAstModification.ReplaceNode(it, newvar, subroutine) + val stringParamsByNames = stringParams.associateBy { it.name } + val varsChanges = + if(stringParamsByNames.isNotEmpty()) { + subroutine.statements + .filterIsInstance() + .filter { it.subroutineParameter!=null && it.name in stringParamsByNames } + .map { + val newvar = VarDecl(it.type, DataType.UWORD, it.zeropage, null, it.name, null, false, true, it.sharedWithAsm, stringParamsByNames.getValue(it.name), it.position) + IAstModification.ReplaceNode(it, newvar, subroutine) + } } + else emptyList() return parameterChanges + varsChanges } diff --git a/compiler/src/prog8/compiler/astprocessing/AstIdentifiersChecker.kt b/compiler/src/prog8/compiler/astprocessing/AstIdentifiersChecker.kt index 9fc2462c7..7ed5fc743 100644 --- a/compiler/src/prog8/compiler/astprocessing/AstIdentifiersChecker.kt +++ b/compiler/src/prog8/compiler/astprocessing/AstIdentifiersChecker.kt @@ -75,7 +75,7 @@ internal class AstIdentifiersChecker(private val errors: IErrorReporter, private val paramsToCheck = paramNames.intersect(namesInSub) for(name in paramsToCheck) { val symbol = subroutine.searchSymbol(name) - if(symbol!=null && symbol.position != subroutine.position) + if(symbol!=null && (symbol as? VarDecl)?.subroutineParameter==null) nameError(name, symbol.position, subroutine) } diff --git a/compiler/src/prog8/compiler/astprocessing/AstVariousTransforms.kt b/compiler/src/prog8/compiler/astprocessing/AstVariousTransforms.kt index 1b7d6a57d..73a9d7533 100644 --- a/compiler/src/prog8/compiler/astprocessing/AstVariousTransforms.kt +++ b/compiler/src/prog8/compiler/astprocessing/AstVariousTransforms.kt @@ -20,13 +20,13 @@ internal class AstVariousTransforms(private val program: Program) : AstWalker() val symbolsInSub = subroutine.allDefinedSymbols val namesInSub = symbolsInSub.map{ it.first }.toSet() if(subroutine.asmAddress==null) { - if(subroutine.asmParameterRegisters.isEmpty() && subroutine.parameters.isNotEmpty()) { + if(!subroutine.isAsmSubroutine && subroutine.parameters.isNotEmpty()) { val vars = subroutine.statements.filterIsInstance().map { it.name }.toSet() if(!vars.containsAll(subroutine.parameters.map{it.name})) { return subroutine.parameters .filter { it.name !in namesInSub } .map { - val vardecl = ParameterVarDecl(it.name, it.type, subroutine.position) + val vardecl = VarDecl.fromParameter(it) IAstModification.InsertFirst(vardecl, subroutine) } } diff --git a/compiler/test/TestMemory.kt b/compiler/test/TestMemory.kt index 648ac99ca..2a6beae1f 100644 --- a/compiler/test/TestMemory.kt +++ b/compiler/test/TestMemory.kt @@ -110,7 +110,7 @@ class TestMemory: FunSpec({ } fun createTestProgramForMemoryRefViaVar(address: UInt, vartype: VarDeclType): AssignTarget { - val decl = VarDecl(vartype, DataType.BYTE, ZeropageWish.DONTCARE, null, "address", NumericLiteralValue.optimalInteger(address, Position.DUMMY), false, false, false, Position.DUMMY) + val decl = VarDecl(vartype, DataType.BYTE, ZeropageWish.DONTCARE, null, "address", NumericLiteralValue.optimalInteger(address, Position.DUMMY), false, false, false, null, Position.DUMMY) val memexpr = IdentifierReference(listOf("address"), Position.DUMMY) val target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY) val assignment = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY) @@ -149,7 +149,7 @@ class TestMemory: FunSpec({ } test("regular variable not in mapped IO ram on C64") { - val decl = VarDecl(VarDeclType.VAR, DataType.BYTE, ZeropageWish.DONTCARE, null, "address", null, false, false, false, Position.DUMMY) + val decl = VarDecl(VarDeclType.VAR, DataType.BYTE, ZeropageWish.DONTCARE, null, "address", null, false, false, false, null, Position.DUMMY) val target = AssignTarget(IdentifierReference(listOf("address"), Position.DUMMY), null, null, Position.DUMMY) val assignment = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY) val subroutine = Subroutine("test", mutableListOf(), emptyList(), emptyList(), emptyList(), emptySet(), null, false, false, mutableListOf(decl, assignment), Position.DUMMY) @@ -160,8 +160,8 @@ class TestMemory: FunSpec({ } test("memory mapped variable not in mapped IO ram on C64") { - val address = 0x1000 - val decl = VarDecl(VarDeclType.MEMORY, DataType.UBYTE, ZeropageWish.DONTCARE, null, "address", NumericLiteralValue.optimalInteger(address, Position.DUMMY), false, false, false, Position.DUMMY) + val address = 0x1000u + val decl = VarDecl(VarDeclType.MEMORY, DataType.UBYTE, ZeropageWish.DONTCARE, null, "address", NumericLiteralValue.optimalInteger(address, Position.DUMMY), false, false, false, null, Position.DUMMY) val target = AssignTarget(IdentifierReference(listOf("address"), Position.DUMMY), null, null, Position.DUMMY) val assignment = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY) val subroutine = Subroutine("test", mutableListOf(), emptyList(), emptyList(), emptyList(), emptySet(), null, false, false, mutableListOf(decl, assignment), Position.DUMMY) @@ -172,8 +172,8 @@ class TestMemory: FunSpec({ } test("memory mapped variable in mapped IO ram on C64") { - val address = 0xd020 - val decl = VarDecl(VarDeclType.MEMORY, DataType.UBYTE, ZeropageWish.DONTCARE, null, "address", NumericLiteralValue.optimalInteger(address, Position.DUMMY), false, false, false, Position.DUMMY) + val address = 0xd020u + val decl = VarDecl(VarDeclType.MEMORY, DataType.UBYTE, ZeropageWish.DONTCARE, null, "address", NumericLiteralValue.optimalInteger(address, Position.DUMMY), false, false, false, null, Position.DUMMY) val target = AssignTarget(IdentifierReference(listOf("address"), Position.DUMMY), null, null, Position.DUMMY) val assignment = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY) val subroutine = Subroutine("test", mutableListOf(), emptyList(), emptyList(), emptyList(), emptySet(), null, false, false, mutableListOf(decl, assignment), Position.DUMMY) @@ -184,7 +184,7 @@ class TestMemory: FunSpec({ } test("array not in mapped IO ram") { - val decl = VarDecl(VarDeclType.VAR, DataType.ARRAY_UB, ZeropageWish.DONTCARE, null, "address", null, false, false, false, Position.DUMMY) + val decl = VarDecl(VarDeclType.VAR, DataType.ARRAY_UB, ZeropageWish.DONTCARE, null, "address", null, false, false, false, null, Position.DUMMY) val arrayindexed = ArrayIndexedExpression(IdentifierReference(listOf("address"), Position.DUMMY), ArrayIndex(NumericLiteralValue.optimalInteger(1, Position.DUMMY), Position.DUMMY), Position.DUMMY) val target = AssignTarget(null, arrayindexed, null, Position.DUMMY) val assignment = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY) @@ -196,8 +196,8 @@ class TestMemory: FunSpec({ } test("memory mapped array not in mapped IO ram") { - val address = 0x1000 - val decl = VarDecl(VarDeclType.MEMORY, DataType.ARRAY_UB, ZeropageWish.DONTCARE, null, "address", NumericLiteralValue.optimalInteger(address, Position.DUMMY), false, false, false, Position.DUMMY) + val address = 0x1000u + val decl = VarDecl(VarDeclType.MEMORY, DataType.ARRAY_UB, ZeropageWish.DONTCARE, null, "address", NumericLiteralValue.optimalInteger(address, Position.DUMMY), false, false, false, null, Position.DUMMY) val arrayindexed = ArrayIndexedExpression(IdentifierReference(listOf("address"), Position.DUMMY), ArrayIndex(NumericLiteralValue.optimalInteger(1, Position.DUMMY), Position.DUMMY), Position.DUMMY) val target = AssignTarget(null, arrayindexed, null, Position.DUMMY) val assignment = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY) @@ -209,8 +209,8 @@ class TestMemory: FunSpec({ } test("memory mapped array in mapped IO ram") { - val address = 0xd800 - val decl = VarDecl(VarDeclType.MEMORY, DataType.ARRAY_UB, ZeropageWish.DONTCARE, null, "address", NumericLiteralValue.optimalInteger(address, Position.DUMMY), false, false, false, Position.DUMMY) + val address = 0xd800u + val decl = VarDecl(VarDeclType.MEMORY, DataType.ARRAY_UB, ZeropageWish.DONTCARE, null, "address", NumericLiteralValue.optimalInteger(address, Position.DUMMY), false, false, false, null, Position.DUMMY) val arrayindexed = ArrayIndexedExpression(IdentifierReference(listOf("address"), Position.DUMMY), ArrayIndex(NumericLiteralValue.optimalInteger(1, Position.DUMMY), Position.DUMMY), Position.DUMMY) val target = AssignTarget(null, arrayindexed, null, Position.DUMMY) val assignment = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY) diff --git a/compilerAst/src/prog8/ast/AstToplevel.kt b/compilerAst/src/prog8/ast/AstToplevel.kt index 137bc015e..aee24c21e 100644 --- a/compilerAst/src/prog8/ast/AstToplevel.kt +++ b/compilerAst/src/prog8/ast/AstToplevel.kt @@ -7,7 +7,6 @@ import prog8.ast.statements.* import prog8.ast.walk.AstWalker import prog8.ast.walk.IAstVisitor import prog8.parser.SourceCode -import kotlin.reflect.typeOf const val internedStringsModuleName = "prog8_interned_strings" @@ -69,23 +68,28 @@ interface IStatementContainer { fun isNotEmpty(): Boolean = statements.isNotEmpty() fun searchSymbol(name: String): Statement? { + if(this is Subroutine && isAsmSubroutine) + return searchAsmParameter(name) + // this is called quite a lot and could perhaps be optimized a bit more, // but adding a memoization cache didn't make much of a practical runtime difference... for (stmt in statements) { when(stmt) { -// is INamedStatement -> { + is INamedStatement -> { + if(stmt.name==name) return stmt + } +// is VarDecl -> { +// // a variable was found with this name, which could also be the vardecl +// // that is (auto)generated for regular subroutine parameters. // if(stmt.name==name) return stmt // } - is VarDecl -> { - if(stmt.name==name) return stmt - } - is Label -> { - if(stmt.name==name) return stmt - } - is Subroutine -> { - if(stmt.name==name) - return stmt - } +// is Label -> { +// if(stmt.name==name) return stmt +// } +// is Subroutine -> { +// if(stmt.name==name) +// return stmt +// } is AnonymousScope -> { val found = stmt.searchSymbol(name) if(found!=null) diff --git a/compilerAst/src/prog8/ast/Program.kt b/compilerAst/src/prog8/ast/Program.kt index 22af56151..ffd06837e 100644 --- a/compilerAst/src/prog8/ast/Program.kt +++ b/compilerAst/src/prog8/ast/Program.kt @@ -94,7 +94,7 @@ class Program(val name: String, val varName = "string_${internedStringsBlock.statements.size}" val decl = VarDecl( VarDeclType.VAR, DataType.STR, ZeropageWish.NOT_IN_ZEROPAGE, null, varName, string, - isArray = false, autogeneratedDontRemove = true, sharedWithAsm = false, position = string.position + isArray = false, autogeneratedDontRemove = true, sharedWithAsm = false, subroutineParameter = null, position = string.position ) internedStringsBlock.statements.add(decl) decl.linkParents(internedStringsBlock) diff --git a/compilerAst/src/prog8/ast/antlr/Antlr2Kotlin.kt b/compilerAst/src/prog8/ast/antlr/Antlr2Kotlin.kt index fc9660010..ff673fd17 100644 --- a/compilerAst/src/prog8/ast/antlr/Antlr2Kotlin.kt +++ b/compilerAst/src/prog8/ast/antlr/Antlr2Kotlin.kt @@ -64,6 +64,7 @@ private fun Prog8ANTLRParser.VariabledeclarationContext.toAst() : Statement { vd.ARRAYSIG() != null || vd.arrayindex() != null, false, vd.SHARED()!=null, + null, it.toPosition() ) } @@ -81,6 +82,7 @@ private fun Prog8ANTLRParser.VariabledeclarationContext.toAst() : Statement { vd.ARRAYSIG() != null || vd.arrayindex() != null, false, vd.SHARED() != null, + null, cvarinit.toPosition() ) } @@ -98,6 +100,7 @@ private fun Prog8ANTLRParser.VariabledeclarationContext.toAst() : Statement { vd.ARRAYSIG() != null || vd.arrayindex() != null, false, vd.SHARED()!=null, + null, mvarinit.toPosition() ) } @@ -600,6 +603,7 @@ private fun Prog8ANTLRParser.VardeclContext.toAst(): VarDecl { ARRAYSIG() != null || arrayindex() != null, false, SHARED()!=null, + null, toPosition() ) } diff --git a/compilerAst/src/prog8/ast/statements/AstStatements.kt b/compilerAst/src/prog8/ast/statements/AstStatements.kt index 29bdd5494..05e9aea1a 100644 --- a/compilerAst/src/prog8/ast/statements/AstStatements.kt +++ b/compilerAst/src/prog8/ast/statements/AstStatements.kt @@ -185,6 +185,7 @@ open class VarDecl(val type: VarDeclType, val isArray: Boolean, val autogeneratedDontRemove: Boolean, val sharedWithAsm: Boolean, + val subroutineParameter: SubroutineParameter?, final override val position: Position) : Statement(), INamedStatement { override lateinit var parent: Node var allowInitializeWithZero = true @@ -194,6 +195,16 @@ open class VarDecl(val type: VarDeclType, companion object { private var autoHeapValueSequenceNumber = 0 + fun fromParameter(param: SubroutineParameter): VarDecl { + return VarDecl(VarDeclType.VAR, param.type, ZeropageWish.DONTCARE, null, param.name, null, + isArray = false, + autogeneratedDontRemove = true, + sharedWithAsm = false, + subroutineParameter = param, + position = param.position + ) + } + fun createAuto(array: ArrayLiteralValue): VarDecl { val autoVarName = "auto_heap_value_${++autoHeapValueSequenceNumber}" val arrayDt = @@ -204,7 +215,7 @@ open class VarDecl(val type: VarDeclType, val declaredType = ArrayToElementTypes.getValue(arrayDt) val arraysize = ArrayIndex.forArray(array) return VarDecl(VarDeclType.VAR, declaredType, ZeropageWish.NOT_IN_ZEROPAGE, arraysize, autoVarName, array, - isArray = true, autogeneratedDontRemove = true, sharedWithAsm = false, position = array.position) + isArray = true, autogeneratedDontRemove = true, sharedWithAsm = false, subroutineParameter = null, position = array.position) } fun defaultZero(dt: DataType, position: Position) = when(dt) { @@ -258,16 +269,13 @@ open class VarDecl(val type: VarDeclType, } override fun copy(): VarDecl { - val c = VarDecl(type, declaredDatatype, zeropage, arraysize?.copy(), name, value?.copy(), isArray, autogeneratedDontRemove, sharedWithAsm, position) + val c = VarDecl(type, declaredDatatype, zeropage, arraysize?.copy(), name, value?.copy(), + isArray, autogeneratedDontRemove, sharedWithAsm, subroutineParameter, position) c.allowInitializeWithZero = this.allowInitializeWithZero return c } } -// a vardecl used only for subroutine parameters -class ParameterVarDecl(name: String, declaredDatatype: DataType, position: Position) - : VarDecl(VarDeclType.VAR, declaredDatatype, ZeropageWish.DONTCARE, null, name, null, false, true, false, position) - class ArrayIndex(var indexExpr: Expression, override val position: Position) : Node { override lateinit var parent: Node @@ -709,6 +717,24 @@ 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 || " bra" in it || "\tbra" in it} + + + // code to provide the ability to reference asmsub parameters via qualified name: + private val asmParamsDecls = mutableMapOf() + + fun searchAsmParameter(name: String): VarDecl? { + require(isAsmSubroutine) + + val existingDecl = asmParamsDecls[name] + if(existingDecl!=null) + return existingDecl + + val param = parameters.firstOrNull {it.name==name} ?: return null + val decl = VarDecl.fromParameter(param) + decl.linkParents(this) + asmParamsDecls[name] = decl + return decl + } } open class SubroutineParameter(val name: String, diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 91127ae79..2811298e5 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -3,6 +3,12 @@ TODO For next compiler release (7.4) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Use GoSub to call subroutines (not in expressions?): + - [DONE] allow separate assigns to subroutine's parameter variables / registers + - for asmsubs: implement asmgen for assigning to asm parameter (register) + - for asmsubs: implement asmgen for reading asm parameter (register) + - replace subroutine param load code with just the right order of those assigns + - finally replace the actual call with a GoSub ... diff --git a/examples/test.p8 b/examples/test.p8 index 661aca586..bbda586da 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -1,22 +1,32 @@ -%import textio main { sub start() { + ubyte @shared xx + main.routine.r1arg = 20 + ; main.routine2.r2arg = 20 ; TODO asmgen - ubyte xx = 20 - routine(xx) + xx = main.routine.r1arg xx++ - routine(xx) - xx++ - routine(xx) + ;xx = main.routine2.r2arg ; TODO asmgen + ;xx++ + printstuff("hello") repeat { } } - sub routine(ubyte x) { - txt.print_ub(x) - txt.spc() + sub printstuff(str addr) { + } + sub routine(ubyte r1arg) { + r1arg++ + } + + asmsub routine2(ubyte r2arg @ A) { + %asm {{ + rts + }} + } + }