From 4cd74daf53426d1681b9ae251182ce703ce54bc7 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Sun, 8 Nov 2020 18:54:02 +0100 Subject: [PATCH] float eval result var added, but some examples are broken --- compiler/src/prog8/ast/AstToplevel.kt | 11 --- .../src/prog8/ast/statements/AstStatements.kt | 17 ++++- .../compiler/target/c64/codegen/AsmGen.kt | 4 +- .../c64/codegen/BuiltinFunctionsAsmGen.kt | 74 ++++++++++--------- examples/cube3d-float.p8 | 2 + examples/cx16/cobramk3-gfx.p8 | 1 + examples/swirl-float.p8 | 1 + examples/test.p8 | 11 +++ examples/turtle-gfx.p8 | 1 + 9 files changed, 70 insertions(+), 52 deletions(-) diff --git a/compiler/src/prog8/ast/AstToplevel.kt b/compiler/src/prog8/ast/AstToplevel.kt index 68a34c1f7..48a39346f 100644 --- a/compiler/src/prog8/ast/AstToplevel.kt +++ b/compiler/src/prog8/ast/AstToplevel.kt @@ -57,19 +57,11 @@ interface IFunctionCall { } -class AsmGenInfo { - var usedAutoArrayIndexerForStatements = mutableMapOf>() - var usedRegsaveA = false - var usedRegsaveX = false - var usedRegsaveY = false -} - interface INameScope { val name: String val position: Position val statements: MutableList val parent: Node - val asmGenInfo: AsmGenInfo fun linkParents(parent: Node) @@ -288,7 +280,6 @@ class Module(override val name: String, override lateinit var parent: Node lateinit var program: Program - override val asmGenInfo = AsmGenInfo() val importedBy = mutableListOf() val imports = mutableSetOf() @@ -322,7 +313,6 @@ class GlobalNamespace(val modules: List): Node, INameScope { override val position = Position("<<>>", 0, 0, 0) override val statements = mutableListOf() // not used override var parent: Node = ParentSentinel - override val asmGenInfo = AsmGenInfo() override fun linkParents(parent: Node) { modules.forEach { it.linkParents(this) } @@ -375,7 +365,6 @@ object BuiltinFunctionScopePlaceholder : INameScope { override val position = Position("<>", 0, 0, 0) override var statements = mutableListOf() override var parent: Node = ParentSentinel - override val asmGenInfo = AsmGenInfo() override fun linkParents(parent: Node) {} } diff --git a/compiler/src/prog8/ast/statements/AstStatements.kt b/compiler/src/prog8/ast/statements/AstStatements.kt index f4157b0dd..f5040b4d8 100644 --- a/compiler/src/prog8/ast/statements/AstStatements.kt +++ b/compiler/src/prog8/ast/statements/AstStatements.kt @@ -52,7 +52,6 @@ class Block(override val name: String, val isInLibrary: Boolean, override val position: Position) : Statement(), INameScope { override lateinit var parent: Node - override val asmGenInfo = AsmGenInfo() override fun linkParents(parent: Node) { this.parent = parent @@ -642,7 +641,6 @@ class AnonymousScope(override var statements: MutableList, override val position: Position) : INameScope, Statement() { override val name: String override lateinit var parent: Node - override val asmGenInfo = AsmGenInfo() companion object { private var sequenceNumber = 1 @@ -681,6 +679,18 @@ class NopStatement(override val position: Position): Statement() { override fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent) } +class AsmGenInfo { + // This class contains various attributes that influence the assembly code generator. + // Conceptually it should be part of any INameScope. + // But because the resulting code only creates "real" scopes on a subroutine level, + // it's more consistent to only define these attributes on a Subroutine node. + var usedAutoArrayIndexerForStatements = mutableMapOf>() + var usedRegsaveA = false + var usedRegsaveX = false + var usedRegsaveY = false + var usedFloatEvalResultVar = false +} + // the subroutine class covers both the normal user-defined subroutines, // and also the predefined/ROM/register-based subroutines. // (multiple return types can only occur for the latter type) @@ -712,7 +722,7 @@ class Subroutine(override val name: String, } override lateinit var parent: Node - override val asmGenInfo = AsmGenInfo() + val asmGenInfo = AsmGenInfo() val scopedname: String by lazy { makeScopedName(name) } override fun linkParents(parent: Node) { @@ -996,7 +1006,6 @@ class StructDecl(override val name: String, override val position: Position): Statement(), INameScope { override lateinit var parent: Node - override val asmGenInfo = AsmGenInfo() override fun linkParents(parent: Node) { this.parent = parent diff --git a/compiler/src/prog8/compiler/target/c64/codegen/AsmGen.kt b/compiler/src/prog8/compiler/target/c64/codegen/AsmGen.kt index 62f637853..52af33030 100644 --- a/compiler/src/prog8/compiler/target/c64/codegen/AsmGen.kt +++ b/compiler/src/prog8/compiler/target/c64/codegen/AsmGen.kt @@ -796,6 +796,8 @@ internal class AsmGen(private val program: Program, out("_prog8_regsaveX .byte 0") if(sub.asmGenInfo.usedRegsaveY) out("_prog8_regsaveY .byte 0") + if(sub.asmGenInfo.usedFloatEvalResultVar) + out("_prog8_float_eval_result .byte 0,0,0,0,0") vardecls2asm(sub.statements) out(" .pend\n") } @@ -1179,7 +1181,7 @@ $counterVar .byte 0""") out(" lda #<${asmVar} | ldy #>${asmVar} | jsr floats.MOVFM") } else -> { - // todo evaluate into fac1 instead of stack + // todo evaluate directly into fac1 instead of stack translateExpression(returnvalue) out(" jsr floats.pop_float_fac1") } diff --git a/compiler/src/prog8/compiler/target/c64/codegen/BuiltinFunctionsAsmGen.kt b/compiler/src/prog8/compiler/target/c64/codegen/BuiltinFunctionsAsmGen.kt index 1ec15dabb..36abd4209 100644 --- a/compiler/src/prog8/compiler/target/c64/codegen/BuiltinFunctionsAsmGen.kt +++ b/compiler/src/prog8/compiler/target/c64/codegen/BuiltinFunctionsAsmGen.kt @@ -8,6 +8,7 @@ import prog8.ast.expressions.* import prog8.ast.statements.ArrayIndex import prog8.ast.statements.DirectMemoryWrite import prog8.ast.statements.FunctionCallStatement +import prog8.ast.statements.Subroutine import prog8.compiler.AssemblyError import prog8.compiler.target.CompilationTarget import prog8.compiler.target.Cx16Target @@ -36,24 +37,25 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val if(discardResult && resultToStack) throw AssemblyError("cannot both discard the result AND put it onto stack") + val scope = (fcall as Node).definingSubroutine()!! when (func.name) { "msb" -> funcMsb(fcall, resultToStack) "lsb" -> funcLsb(fcall, resultToStack) "mkword" -> funcMkword(fcall, resultToStack) - "abs" -> funcAbs(fcall, func, resultToStack) + "abs" -> funcAbs(fcall, func, resultToStack, scope) "swap" -> funcSwap(fcall) "min", "max" -> funcMinMax(fcall, func, resultToStack) "sum" -> funcSum(fcall, resultToStack) "any", "all" -> funcAnyAll(fcall, func, resultToStack) "sin8", "sin8u", "sin16", "sin16u", - "cos8", "cos8u", "cos16", "cos16u" -> funcSinCosInt(fcall, func, resultToStack) - "sgn" -> funcSgn(fcall, func, resultToStack) + "cos8", "cos8u", "cos16", "cos16u" -> funcSinCosInt(fcall, func, resultToStack, scope) + "sgn" -> funcSgn(fcall, func, resultToStack, scope) "sin", "cos", "tan", "atan", "ln", "log2", "sqrt", "rad", "deg", "round", "floor", "ceil", - "rndf" -> funcVariousFloatFuncs(fcall, func, resultToStack) + "rndf" -> funcVariousFloatFuncs(fcall, func, resultToStack, scope) "rnd", "rndw" -> funcRnd(func, resultToStack) - "sqrt16" -> funcSqrt16(fcall, func, resultToStack) + "sqrt16" -> funcSqrt16(fcall, func, resultToStack, scope) "rol" -> funcRol(fcall) "rol2" -> funcRol2(fcall) "ror" -> funcRor(fcall) @@ -80,21 +82,21 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val "clear_irqd" -> asmgen.out(" cli") "set_irqd" -> asmgen.out(" sei") "strlen" -> funcStrlen(fcall, resultToStack) - "strcmp" -> funcStrcmp(fcall, func, resultToStack) - "memcopy", "memset", "memsetw" -> funcMemSetCopy(fcall, func) + "strcmp" -> funcStrcmp(fcall, func, resultToStack, scope) + "memcopy", "memset", "memsetw" -> funcMemSetCopy(fcall, func, scope) "substr", "leftstr", "rightstr" -> { - translateArguments(fcall.args, func) + translateArguments(fcall.args, func, scope) asmgen.out(" jsr prog8_lib.func_${func.name}") } "exit" -> { - translateArguments(fcall.args, func) + translateArguments(fcall.args, func, scope) asmgen.out(" jmp prog8_lib.func_exit") } else -> TODO("missing asmgen for builtin func ${func.name}") } } - private fun funcMemSetCopy(fcall: IFunctionCall, func: FSignature) { + private fun funcMemSetCopy(fcall: IFunctionCall, func: FSignature, scope: Subroutine) { if(CompilationTarget.instance is Cx16Target) { when(func.name) { "memset" -> { @@ -121,7 +123,7 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val val countDt = fcall.args[2].inferType(program) if((count!=null && count <= 255) || countDt.istype(DataType.UBYTE) || countDt.istype(DataType.BYTE)) { // fast memcopy of up to 255 - translateArguments(fcall.args, func) + translateArguments(fcall.args, func, scope) asmgen.out(" jsr prog8_lib.func_memcopy255") return } @@ -145,7 +147,7 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val asmgen.restoreRegister(CpuRegister.X, false) } "memsetw" -> { - translateArguments(fcall.args, func) + translateArguments(fcall.args, func, scope) asmgen.out(" jsr prog8_lib.func_memsetw") } } @@ -154,34 +156,34 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val val count = fcall.args[2].constValue(program)?.number?.toInt() val countDt = fcall.args[2].inferType(program) if((count!=null && count <= 255) || countDt.istype(DataType.UBYTE) || countDt.istype(DataType.BYTE)) { - translateArguments(fcall.args, func) + translateArguments(fcall.args, func, scope) asmgen.out(" jsr prog8_lib.func_memcopy255") return } } - translateArguments(fcall.args, func) + translateArguments(fcall.args, func, scope) asmgen.out(" jsr prog8_lib.func_${func.name}") } } - private fun funcStrcmp(fcall: IFunctionCall, func: FSignature, resultToStack: Boolean) { - translateArguments(fcall.args, func) + private fun funcStrcmp(fcall: IFunctionCall, func: FSignature, resultToStack: Boolean, scope: Subroutine) { + translateArguments(fcall.args, func, scope) if(resultToStack) asmgen.out(" jsr prog8_lib.func_strcmp_stack") else asmgen.out(" jsr prog8_lib.func_strcmp") } - private fun funcSqrt16(fcall: IFunctionCall, func: FSignature, resultToStack: Boolean) { - translateArguments(fcall.args, func) + private fun funcSqrt16(fcall: IFunctionCall, func: FSignature, resultToStack: Boolean, scope: Subroutine) { + translateArguments(fcall.args, func, scope) if(resultToStack) asmgen.out(" jsr prog8_lib.func_sqrt16_stack") else asmgen.out(" jsr prog8_lib.func_sqrt16_into_A") } - private fun funcSinCosInt(fcall: IFunctionCall, func: FSignature, resultToStack: Boolean) { - translateArguments(fcall.args, func) + private fun funcSinCosInt(fcall: IFunctionCall, func: FSignature, resultToStack: Boolean, scope: Subroutine) { + translateArguments(fcall.args, func, scope) if(resultToStack) asmgen.out(" jsr prog8_lib.func_${func.name}_stack") else @@ -458,16 +460,16 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val asmgen.translateNormalAssignment(assign) } - private fun funcVariousFloatFuncs(fcall: IFunctionCall, func: FSignature, resultToStack: Boolean) { - translateArguments(fcall.args, func) + private fun funcVariousFloatFuncs(fcall: IFunctionCall, func: FSignature, resultToStack: Boolean, scope: Subroutine) { + translateArguments(fcall.args, func, scope) if(resultToStack) asmgen.out(" jsr floats.func_${func.name}_stack") else asmgen.out(" jsr floats.func_${func.name}_fac1") } - private fun funcSgn(fcall: IFunctionCall, func: FSignature, resultToStack: Boolean) { - translateArguments(fcall.args, func) + private fun funcSgn(fcall: IFunctionCall, func: FSignature, resultToStack: Boolean, scope: Subroutine) { + translateArguments(fcall.args, func, scope) val dt = fcall.args.single().inferType(program) if(resultToStack) { when (dt.typeOrElse(DataType.STRUCT)) { @@ -930,8 +932,8 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val } } - private fun funcAbs(fcall: IFunctionCall, func: FSignature, resultToStack: Boolean) { - translateArguments(fcall.args, func) + private fun funcAbs(fcall: IFunctionCall, func: FSignature, resultToStack: Boolean, scope: Subroutine) { + translateArguments(fcall.args, func, scope) val dt = fcall.args.single().inferType(program).typeOrElse(DataType.STRUCT) if(resultToStack) { when (dt) { @@ -1040,7 +1042,7 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val """) } - private fun translateArguments(args: MutableList, signature: FSignature) { + private fun translateArguments(args: MutableList, signature: FSignature, scope: Subroutine) { val callConv = signature.callConvention(args.map { it.inferType(program).typeOrElse(DataType.STRUCT) }) fun getSourceForFloat(value: Expression): AsmAssignSource { @@ -1053,15 +1055,15 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val throw AssemblyError("float literals should have been converted into autovar") } else -> { - TODO("evaluate float expression, store float in (to be defined) result variable, get address of that variable.") -// val variable = IdentifierReference(listOf("p8_float_eval_result"), value.position) -// variable.linkParents(value) -// val assign = AsmAssignment(AsmAssignSource.fromAstSource(value, program, asmgen), -// AsmAssignTarget(TargetStorageKind.VARIABLE, program, asmgen, DataType.FLOAT, null, variableAsmName = asmgen.asmVariableName(variable)), -// false, Position.DUMMY) -// asmgen.translateNormalAssignment(assign) -// val addr = AddressOf(variable, value.position) -// AsmAssignSource.fromAstSource(addr, program, asmgen) + scope.asmGenInfo.usedFloatEvalResultVar = true + val variable = IdentifierReference(listOf("_prog8_float_eval_result"), value.position) + variable.linkParents(value) + val assign = AsmAssignment(AsmAssignSource.fromAstSource(value, program, asmgen), + AsmAssignTarget(TargetStorageKind.VARIABLE, program, asmgen, DataType.FLOAT, null, variableAsmName = asmgen.asmVariableName(variable)), + false, Position.DUMMY) + asmgen.translateNormalAssignment(assign) + val addr = AddressOf(variable, value.position) + AsmAssignSource.fromAstSource(addr, program, asmgen) } } } diff --git a/examples/cube3d-float.p8 b/examples/cube3d-float.p8 index 87cd3fabe..728f4a8e9 100644 --- a/examples/cube3d-float.p8 +++ b/examples/cube3d-float.p8 @@ -5,6 +5,8 @@ ; Note: this program is compatible with C64 and CX16. ; TODO why has the prg become bigger since register args? +; TODO doesn't work properly anymore + main { diff --git a/examples/cx16/cobramk3-gfx.p8 b/examples/cx16/cobramk3-gfx.p8 index 03a58108b..c2a4148c5 100644 --- a/examples/cx16/cobramk3-gfx.p8 +++ b/examples/cx16/cobramk3-gfx.p8 @@ -3,6 +3,7 @@ %import conv ; TODO add all other Elite's ships, show their name, advance to next ship on keypress +; TODO doesn't draw anything on cx16 anymore... main { diff --git a/examples/swirl-float.p8 b/examples/swirl-float.p8 index dd3622a77..c9e9b885b 100644 --- a/examples/swirl-float.p8 +++ b/examples/swirl-float.p8 @@ -5,6 +5,7 @@ ; Note: this program is compatible with C64 and CX16. ; TODO why has the prg become bigger since register args? +; TODO doesn't work properly anymore main { diff --git a/examples/test.p8 b/examples/test.p8 index 626b785bc..3ef92e80d 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -6,6 +6,17 @@ main { sub start() { + float t = 0.0 + + repeat 10 { + float cosa = cos(t) + float sina = sin(t) + float cosb = cos(t*0.33) + float sinb = sin(t*0.33) + float cosc = cos(t*0.78) + float sinc = sin(t*0.78) + } + testX() } diff --git a/examples/turtle-gfx.p8 b/examples/turtle-gfx.p8 index cb6f91604..bbe421e8a 100644 --- a/examples/turtle-gfx.p8 +++ b/examples/turtle-gfx.p8 @@ -3,6 +3,7 @@ %import graphics %zeropage floatsafe +; TODO doesn't work anymore main {