diff --git a/codeGeneration/src/prog8/codegen/target/cpu6502/codegen/AsmGen.kt b/codeGeneration/src/prog8/codegen/target/cpu6502/codegen/AsmGen.kt index 08c335367..e5f527222 100644 --- a/codeGeneration/src/prog8/codegen/target/cpu6502/codegen/AsmGen.kt +++ b/codeGeneration/src/prog8/codegen/target/cpu6502/codegen/AsmGen.kt @@ -850,7 +850,7 @@ class AsmGen(private val program: Program, is RepeatLoop -> translate(stmt) is When -> translate(stmt) is AnonymousScope -> translate(stmt) - is Pipe -> expressionsAsmGen.translatePipeExpression(stmt.expressions, stmt,true) + is Pipe -> translatePipeExpression(stmt.expressions, stmt, true, false) is BuiltinFunctionPlaceholder -> throw AssemblyError("builtin function should not have placeholder anymore") is UntilLoop -> throw AssemblyError("do..until should have been converted to jumps") is WhileLoop -> throw AssemblyError("while should have been converted to jumps") @@ -3411,4 +3411,54 @@ $label nop""") else -> return false } } + + internal fun translatePipeExpression(expressions: Iterable, scope: Node, isStatement: Boolean, pushResultOnEstack: Boolean) { + // NOTE: + + // TODO more efficient code generation to avoid needless assignments to the temp var + + val subroutine = scope.definingSubroutine + var valueDt = expressions.first().inferType(program).getOrElse { throw FatalAstException("invalid dt") } + var valueVar = getTempVarName(valueDt) + assignExpressionToVariable(expressions.first(), asmVariableName(valueVar), valueDt, subroutine) + expressions.drop(1).dropLast(1).forEach { + valueDt = functioncallAsmGen.translateFunctionCall(it as IdentifierReference, listOf(IdentifierReference(valueVar, it.position)), scope) + // assign result value from the functioncall back to the temp var: + valueVar = getTempVarName(valueDt) + val valueVarTarget = AsmAssignTarget(TargetStorageKind.VARIABLE, program, this, valueDt, subroutine, variableAsmName = valueVar.joinToString(".")) + val returnRegister = returnRegisterOfFunction(it)!! + assignRegister(returnRegister, valueVarTarget) + } + + if(isStatement) { + // the last term in the pipe, don't care about return var: + functioncallAsmGen.translateFunctionCallStatement( + expressions.last() as IdentifierReference, + listOf(IdentifierReference(valueVar, expressions.last().position)), + scope + ) + } else { + // the last term in the pipe, regular function call with returnvalue: + valueDt = functioncallAsmGen.translateFunctionCall( + expressions.last() as IdentifierReference, + listOf(IdentifierReference(valueVar, expressions.last().position)), + scope + ) + if(pushResultOnEstack) { + when (valueDt) { + in ByteDatatypes -> { + out(" sta P8ESTACK_LO,x | dex") + } + in WordDatatypes -> { + out(" sta P8ESTACK_LO,x | tya | sta P8ESTACK_HI,x | dex") + } + DataType.FLOAT -> { + out(" jsr floats.push_fac1") + } + else -> throw AssemblyError("invalid dt") + } + } + } + } + } diff --git a/codeGeneration/src/prog8/codegen/target/cpu6502/codegen/ExpressionsAsmGen.kt b/codeGeneration/src/prog8/codegen/target/cpu6502/codegen/ExpressionsAsmGen.kt index 5bbce43f3..c89d9c9ab 100644 --- a/codeGeneration/src/prog8/codegen/target/cpu6502/codegen/ExpressionsAsmGen.kt +++ b/codeGeneration/src/prog8/codegen/target/cpu6502/codegen/ExpressionsAsmGen.kt @@ -1,6 +1,5 @@ package prog8.codegen.target.cpu6502.codegen -import prog8.ast.Node import prog8.ast.Program import prog8.ast.base.* import prog8.ast.expressions.* @@ -8,8 +7,6 @@ import prog8.ast.statements.BuiltinFunctionPlaceholder import prog8.ast.statements.Subroutine import prog8.ast.toHex import prog8.codegen.target.AssemblyError -import prog8.codegen.target.cpu6502.codegen.assignment.AsmAssignTarget -import prog8.codegen.target.cpu6502.codegen.assignment.TargetStorageKind import prog8.compilerinterface.BuiltinFunctions import prog8.compilerinterface.CpuType import kotlin.math.absoluteValue @@ -40,7 +37,7 @@ internal class ExpressionsAsmGen(private val program: Program, private val asmge is NumericLiteralValue -> translateExpression(expression) is IdentifierReference -> translateExpression(expression) is FunctionCallExpression -> translateFunctionCallResultOntoStack(expression) - is PipeExpression -> translatePipeExpression(expression.expressions, expression,false) + is PipeExpression -> asmgen.translatePipeExpression(expression.expressions, expression,false, true) is ContainmentCheck -> throw AssemblyError("containment check as complex expression value is not supported") is ArrayLiteralValue, is StringLiteralValue -> throw AssemblyError("no asm gen for string/array literal value assignment - should have been replaced by a variable") is RangeExpression -> throw AssemblyError("range expression should have been changed into array values") @@ -793,38 +790,4 @@ internal class ExpressionsAsmGen(private val program: Program, private val asmge } asmgen.out(" dex") } - - internal fun translatePipeExpression(expressions: Iterable, scope: Node, isStatement: Boolean) { - - // TODO more efficient code generation to avoid needless assignments to the temp var - - val subroutine = scope.definingSubroutine - var valueDt = expressions.first().inferType(program).getOrElse { throw FatalAstException("invalid dt") } - var valueVar = asmgen.getTempVarName(valueDt) - asmgen.assignExpressionToVariable(expressions.first(), valueVar.joinToString("."), valueDt, subroutine) - expressions.drop(1).dropLast(1).forEach { - valueDt = functioncallAsmGen.translateFunctionCall(it as IdentifierReference, listOf(IdentifierReference(valueVar, it.position)), scope) - // assign result value from the functioncall back to the temp var: - valueVar = asmgen.getTempVarName(valueDt) - val valueVarTarget = AsmAssignTarget(TargetStorageKind.VARIABLE, program, asmgen, valueDt, subroutine, variableAsmName = valueVar.joinToString(".")) - val returnRegister = asmgen.returnRegisterOfFunction(it)!! - asmgen.assignRegister(returnRegister, valueVarTarget) - } - - if(isStatement) { - // the last term in the pipe, don't care about return var: - functioncallAsmGen.translateFunctionCallStatement( - expressions.last() as IdentifierReference, - listOf(IdentifierReference(valueVar, expressions.last().position)), - scope - ) - } else { - // the last term in the pipe, regular function call with returnvalue: - functioncallAsmGen.translateFunctionCall( - expressions.last() as IdentifierReference, - listOf(IdentifierReference(valueVar, expressions.last().position)), - scope - ) - } - } } diff --git a/codeGeneration/src/prog8/codegen/target/cpu6502/codegen/assignment/AssignmentAsmGen.kt b/codeGeneration/src/prog8/codegen/target/cpu6502/codegen/assignment/AssignmentAsmGen.kt index c21957626..ea4a6d573 100644 --- a/codeGeneration/src/prog8/codegen/target/cpu6502/codegen/assignment/AssignmentAsmGen.kt +++ b/codeGeneration/src/prog8/codegen/target/cpu6502/codegen/assignment/AssignmentAsmGen.kt @@ -275,6 +275,14 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen containmentCheckIntoA(value) assignRegisterByte(assign.target, CpuRegister.A) } + is PipeExpression -> { + // TODO NOT VIA STACK!! + asmgen.translateExpression(value) + if (assign.target.datatype in WordDatatypes && assign.source.datatype in ByteDatatypes) + asmgen.signExtendStackLsb(assign.source.datatype) + if(assign.target.kind!=TargetStorageKind.STACK || assign.target.datatype != assign.source.datatype) + assignStackValue(assign.target) + } else -> { // Everything else just evaluate via the stack. // (we can't use the assignment helper functions (assignExpressionTo...) to do it via registers here, diff --git a/docs/source/todo.rst b/docs/source/todo.rst index ff02f988e..b79dbd272 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -3,7 +3,6 @@ TODO For next compiler release (7.7) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -- fix codegen bug for pipe expressions to actually return correct value and not corrupt X register - why is wormfood 40 bytes larger now since 7.6??? - optimize codegen of pipe operator to avoid needless assigns to temp var - copying floats around: do it with a subroutine rather than 5 lda/sta pairs . diff --git a/examples/test.p8 b/examples/test.p8 index a923f9c80..06b90e57c 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -23,7 +23,7 @@ main { test_stack.test() ; TODO fix that the value is actually returned (398) and that X register is preserved: - uword @shared uw = 9+3 |> assemblything + uword @shared uw= 9+3 |> assemblything |> sin8u |> add_one |> times_two @@ -52,8 +52,9 @@ main { return input*$0002 } - asmsub assemblything(ubyte input @A) -> ubyte @A { + asmsub assemblything(ubyte input @A) clobbers(X,Y) -> ubyte @A { %asm {{ + ldx #0 asl a rts }}