fix faulty binexpr splitting

This commit is contained in:
Irmen de Jong 2020-11-03 21:31:08 +01:00
parent e0c5ccc16b
commit 526e4b8bdc
4 changed files with 45 additions and 34 deletions

View File

@ -1053,26 +1053,29 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val
when { when {
conv.variable -> { conv.variable -> {
val varname = "prog8_lib.func_${signature.name}_cc._arg_${paramName}" // TODO after all builtin funcs have been changed into _cc, remove that suffix again val varname = "prog8_lib.func_${signature.name}_cc._arg_${paramName}" // TODO after all builtin funcs have been changed into _cc, remove that suffix again
val src = AsmAssignSource.fromAstSource(value, program, asmgen) val src = if(conv.dt==DataType.FLOAT || conv.dt in PassByReferenceDatatypes) {
// put the address of the argument in AY
val addr = AddressOf(value as IdentifierReference, value.position)
AsmAssignSource.fromAstSource(addr, program, asmgen)
} else {
AsmAssignSource.fromAstSource(value, program, asmgen)
}
val tgt = AsmAssignTarget(TargetStorageKind.VARIABLE, program, asmgen, conv.dt, null, variableAsmName = varname) val tgt = AsmAssignTarget(TargetStorageKind.VARIABLE, program, asmgen, conv.dt, null, variableAsmName = varname)
val assign = AsmAssignment(src, tgt, false, value.position) val assign = AsmAssignment(src, tgt, false, value.position)
asmgen.translateNormalAssignment(assign) asmgen.translateNormalAssignment(assign)
} }
conv.reg != null -> { conv.reg != null -> {
if(conv.dt==DataType.FLOAT || conv.dt in PassByReferenceDatatypes) { val src = if(conv.dt==DataType.FLOAT || conv.dt in PassByReferenceDatatypes) {
// put the address of the argument in AY // put the address of the argument in AY
val addr = AddressOf(value as IdentifierReference, value.position) val addr = AddressOf(value as IdentifierReference, value.position)
val src = AsmAssignSource.fromAstSource(addr, program, asmgen) AsmAssignSource.fromAstSource(addr, program, asmgen)
val tgt = AsmAssignTarget.fromRegisters(conv.reg, null, program, asmgen)
val assign = AsmAssignment(src, tgt, false, value.position)
asmgen.translateNormalAssignment(assign)
} else { } else {
val src = AsmAssignSource.fromAstSource(value, program, asmgen) AsmAssignSource.fromAstSource(value, program, asmgen)
}
val tgt = AsmAssignTarget.fromRegisters(conv.reg, null, program, asmgen) val tgt = AsmAssignTarget.fromRegisters(conv.reg, null, program, asmgen)
val assign = AsmAssignment(src, tgt, false, value.position) val assign = AsmAssignment(src, tgt, false, value.position)
asmgen.translateNormalAssignment(assign) asmgen.translateNormalAssignment(assign)
} }
}
else -> throw AssemblyError("callconv") else -> throw AssemblyError("callconv")
} }
} }

View File

@ -38,22 +38,26 @@ internal class BinExprSplitter(private val program: Program) : AstWalker() {
if (binExpr != null) { if (binExpr != null) {
/* /*
reduce the complexity of a (binary) expression that has to be evaluated on the eval stack, Reduce the complexity of a (binary) expression that has to be evaluated on the eval stack,
by attempting to splitting it up into individual simple steps: by attempting to splitting it up into individual simple steps.
We only consider a binary expression *one* level deep (so the operands must not be a combined expression)
X = BinExpr X = LeftExpr X = BinExpr X = LeftExpr
<operator> followed by <operator> followed by
/ \ IF 'X' not used X = BinExpr / \ IF 'X' not used X = BinExpr
/ \ IN LEFTEXPR ==> <operator> / \ IN expression ==> <operator>
/ \ / \ / \ / \
LeftExpr. RightExpr. / \ LeftExpr. RightExpr. / \
/ \ / \ X RightExpr. X RightExpr.
.. .. .. ..
*/ */
if(binExpr.operator in augmentAssignmentOperators && isSimpleTarget(assignment.target, program.namespace)) { if(binExpr.operator in augmentAssignmentOperators && isSimpleTarget(assignment.target, program.namespace)) {
if (!assignment.isAugmentable) { if(assignment.target isSameAs binExpr.left || assignment.target isSameAs binExpr.right)
return noModifications
if(isSimpleExpression(binExpr.left) && isSimpleExpression(binExpr.right) && !assignment.isAugmentable) {
val firstAssign = Assignment(assignment.target, binExpr.left, binExpr.left.position) val firstAssign = Assignment(assignment.target, binExpr.left, binExpr.left.position)
val targetExpr = assignment.target.toExpression() val targetExpr = assignment.target.toExpression()
val augExpr = BinaryExpression(targetExpr, binExpr.operator, binExpr.right, binExpr.right.position) val augExpr = BinaryExpression(targetExpr, binExpr.operator, binExpr.right, binExpr.right.position)
@ -71,6 +75,9 @@ X = BinExpr X = LeftExpr
return noModifications return noModifications
} }
private fun isSimpleExpression(expr: Expression) =
expr is IdentifierReference || expr is NumericLiteralValue || expr is AddressOf || expr is DirectMemoryRead || expr is StringLiteralValue || expr is ArrayLiteralValue || expr is RangeExpr
private fun isSimpleTarget(target: AssignTarget, namespace: INameScope) = private fun isSimpleTarget(target: AssignTarget, namespace: INameScope) =
if (target.identifier!=null || target.memoryAddress!=null || target.arrayindexed!=null) if (target.identifier!=null || target.memoryAddress!=null || target.arrayindexed!=null)
target.isInRegularRAM(namespace) target.isInRegularRAM(namespace)

View File

@ -8,9 +8,10 @@
; Cleanup and porting to C by Ullrich von Bassewitz. ; Cleanup and porting to C by Ullrich von Bassewitz.
; Converted to prog8 by Irmen de Jong. ; Converted to prog8 by Irmen de Jong.
; TODO the random charset is all wrong
; TODO why has the prg become bigger since register args? ; TODO why has the prg become bigger since register args?
main { main {
const uword SCREEN1 = $E000 const uword SCREEN1 = $E000
const uword SCREEN2 = $E400 const uword SCREEN2 = $E400

View File

@ -12,28 +12,28 @@ main {
const uword ADDR = $0400 const uword ADDR = $0400
byte zerob=0 byte zerob=0
word zerow=0 ; word zerow=0
float zerof=0 ; float zerof=0
byte bb byte bb
word ww ; word ww
float fl ; float fl
testX() testX()
bb = -100 bb = -100
bb = zerob+abs(bb) bb = zerob+abs(bb) ; TODO optimizer generates wrong code for this (wrong order of splitted expression?)
txt.print_b(bb) txt.print_b(bb)
txt.chrout('\n') txt.chrout('\n')
ww = -12345 ; ww = -12345
ww = zerow+abs(ww) ; ww = zerow+abs(ww) ; TODO optimizer generates wrong code for this (wrong order of splitted expression?)
txt.print_w(ww) ; txt.print_w(ww)
txt.chrout('\n') ; txt.chrout('\n')
;
fl = -9.876 ; fl = -9.876
fl = zerof+abs(fl) ; fl = zerof+abs(fl) ; TODO optimizer generates wrong code for this (wrong order of splitted expression?)
floats.print_f(fl) ; floats.print_f(fl)
txt.chrout('\n') ; txt.chrout('\n')
; memset(ADDR, 40*25, 100) ; memset(ADDR, 40*25, 100)
; memsetw(ADDR, 20*10, $3031) ; memsetw(ADDR, 20*10, $3031)