mirror of
https://github.com/irmen/prog8.git
synced 2024-10-18 01:24:51 +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 RepeatLoop -> translate(stmt)
|
||||||
is When -> translate(stmt)
|
is When -> translate(stmt)
|
||||||
is AnonymousScope -> 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 BuiltinFunctionPlaceholder -> throw AssemblyError("builtin function should not have placeholder anymore")
|
||||||
is UntilLoop -> throw AssemblyError("do..until should have been converted to jumps")
|
is UntilLoop -> throw AssemblyError("do..until should have been converted to jumps")
|
||||||
is WhileLoop -> throw AssemblyError("while 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
|
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
|
package prog8.codegen.target.cpu6502.codegen
|
||||||
|
|
||||||
import prog8.ast.Node
|
|
||||||
import prog8.ast.Program
|
import prog8.ast.Program
|
||||||
import prog8.ast.base.*
|
import prog8.ast.base.*
|
||||||
import prog8.ast.expressions.*
|
import prog8.ast.expressions.*
|
||||||
@ -8,8 +7,6 @@ import prog8.ast.statements.BuiltinFunctionPlaceholder
|
|||||||
import prog8.ast.statements.Subroutine
|
import prog8.ast.statements.Subroutine
|
||||||
import prog8.ast.toHex
|
import prog8.ast.toHex
|
||||||
import prog8.codegen.target.AssemblyError
|
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.BuiltinFunctions
|
||||||
import prog8.compilerinterface.CpuType
|
import prog8.compilerinterface.CpuType
|
||||||
import kotlin.math.absoluteValue
|
import kotlin.math.absoluteValue
|
||||||
@ -40,7 +37,7 @@ internal class ExpressionsAsmGen(private val program: Program, private val asmge
|
|||||||
is NumericLiteralValue -> translateExpression(expression)
|
is NumericLiteralValue -> translateExpression(expression)
|
||||||
is IdentifierReference -> translateExpression(expression)
|
is IdentifierReference -> translateExpression(expression)
|
||||||
is FunctionCallExpression -> translateFunctionCallResultOntoStack(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 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 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")
|
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")
|
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)
|
containmentCheckIntoA(value)
|
||||||
assignRegisterByte(assign.target, CpuRegister.A)
|
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 -> {
|
else -> {
|
||||||
// Everything else just evaluate via the stack.
|
// Everything else just evaluate via the stack.
|
||||||
// (we can't use the assignment helper functions (assignExpressionTo...) to do it via registers here,
|
// (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)
|
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???
|
- why is wormfood 40 bytes larger now since 7.6???
|
||||||
- optimize codegen of pipe operator to avoid needless assigns to temp var
|
- 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 .
|
- copying floats around: do it with a subroutine rather than 5 lda/sta pairs .
|
||||||
|
@ -23,7 +23,7 @@ main {
|
|||||||
|
|
||||||
test_stack.test()
|
test_stack.test()
|
||||||
; TODO fix that the value is actually returned (398) and that X register is preserved:
|
; 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
|
|> sin8u
|
||||||
|> add_one
|
|> add_one
|
||||||
|> times_two
|
|> times_two
|
||||||
@ -52,8 +52,9 @@ main {
|
|||||||
return input*$0002
|
return input*$0002
|
||||||
}
|
}
|
||||||
|
|
||||||
asmsub assemblything(ubyte input @A) -> ubyte @A {
|
asmsub assemblything(ubyte input @A) clobbers(X,Y) -> ubyte @A {
|
||||||
%asm {{
|
%asm {{
|
||||||
|
ldx #0
|
||||||
asl a
|
asl a
|
||||||
rts
|
rts
|
||||||
}}
|
}}
|
||||||
|
Loading…
Reference in New Issue
Block a user