mirror of
https://github.com/irmen/prog8.git
synced 2025-01-12 19:29:50 +00:00
fix codegen bug for pipe expressions to actually return correct value and not corrupt X register
This commit is contained in:
parent
d99d977d2b
commit
7135205299
@ -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<Expression>, 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")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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<Expression>, 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
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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 .
|
||||
|
@ -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
|
||||
}}
|
||||
|
Loading…
x
Reference in New Issue
Block a user