mirror of
https://github.com/irmen/prog8.git
synced 2025-01-12 04:30:03 +00:00
expression optimizations
This commit is contained in:
parent
ec770b0f5f
commit
30e6bc92e5
@ -36,8 +36,8 @@ enum class DataType {
|
|||||||
fun assignableTo(targetType: DataType) =
|
fun assignableTo(targetType: DataType) =
|
||||||
// what types are assignable to others without loss of precision?
|
// what types are assignable to others without loss of precision?
|
||||||
when(this) {
|
when(this) {
|
||||||
UBYTE -> targetType == UBYTE || targetType == UWORD || targetType == FLOAT
|
UBYTE -> targetType == BYTE || targetType == UBYTE || targetType == UWORD || targetType==WORD || targetType == FLOAT
|
||||||
BYTE -> targetType == BYTE || targetType == WORD || targetType == FLOAT
|
BYTE -> targetType == BYTE || targetType == UBYTE || targetType == WORD || targetType == FLOAT
|
||||||
UWORD -> targetType == UWORD || targetType == FLOAT
|
UWORD -> targetType == UWORD || targetType == FLOAT
|
||||||
WORD -> targetType == WORD || targetType == FLOAT
|
WORD -> targetType == WORD || targetType == FLOAT
|
||||||
FLOAT -> targetType == FLOAT
|
FLOAT -> targetType == FLOAT
|
||||||
|
@ -68,6 +68,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
|
|||||||
fun compileToAssembly(): AssemblyProgram {
|
fun compileToAssembly(): AssemblyProgram {
|
||||||
println("\nGenerating assembly code from intermediate code... ")
|
println("\nGenerating assembly code from intermediate code... ")
|
||||||
|
|
||||||
|
assemblyLines.clear()
|
||||||
header()
|
header()
|
||||||
for(b in program.blocks)
|
for(b in program.blocks)
|
||||||
block2asm(b)
|
block2asm(b)
|
||||||
@ -143,9 +144,14 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
|
|||||||
return numberOfOptimizations
|
return numberOfOptimizations
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun out(str: String) {
|
private fun out(str: String, splitlines: Boolean=true) {
|
||||||
// TODO: line splitting should be done here instead of at outputFragment
|
if(splitlines) {
|
||||||
assemblyLines.add(str)
|
for (line in str.split('\n')) {
|
||||||
|
var trimmed = if (line.startsWith(' ')) "\t" + line.trim() else line.trim()
|
||||||
|
// trimmed = trimmed.replace(Regex("^\\+\\s+"), "+\t") // sanitize local label indentation
|
||||||
|
assemblyLines.add(trimmed)
|
||||||
|
}
|
||||||
|
} else assemblyLines.add(str)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -414,17 +420,10 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
|
|||||||
private fun outputAsmFragment(singleAsm: String) {
|
private fun outputAsmFragment(singleAsm: String) {
|
||||||
if (singleAsm.isNotEmpty()) {
|
if (singleAsm.isNotEmpty()) {
|
||||||
if(singleAsm.startsWith("@inline@"))
|
if(singleAsm.startsWith("@inline@"))
|
||||||
out(singleAsm.substring(8))
|
out(singleAsm.substring(8), false)
|
||||||
else {
|
else {
|
||||||
val withNewlines = singleAsm.replace('|', '\n')
|
val withNewlines = singleAsm.replace('|', '\n')
|
||||||
for (line in withNewlines.split('\n')) {
|
out(withNewlines)
|
||||||
// TODO move line splitting to out() function
|
|
||||||
if (line.isNotEmpty()) {
|
|
||||||
var trimmed = if (line.startsWith(' ')) "\t" + line.trim() else line.trim()
|
|
||||||
trimmed = trimmed.replace(Regex("^\\+\\s+"), "+\t") // sanitize local label indentation
|
|
||||||
out(trimmed)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,33 +6,27 @@ import kotlin.math.abs
|
|||||||
import kotlin.math.log2
|
import kotlin.math.log2
|
||||||
|
|
||||||
/*
|
/*
|
||||||
todo simplify expression terms:
|
todo advanced expression optimization: common (sub) expression elimination (turn common expressions into single subroutine call + introduce variable to hold it)
|
||||||
|
|
||||||
X*Y - X -> X*(Y-1) ???
|
|
||||||
Y*X - X -> X*(Y-1) ???
|
|
||||||
|
|
||||||
todo expression optimization: common (sub) expression elimination (turn common expressions into single subroutine call + introduce variable to hold it)
|
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class SimplifyExpressions(private val namespace: INameScope, private val heap: HeapValues) : IAstProcessor {
|
class SimplifyExpressions(private val namespace: INameScope, private val heap: HeapValues) : IAstProcessor {
|
||||||
var optimizationsDone: Int = 0
|
var optimizationsDone: Int = 0
|
||||||
|
|
||||||
override fun process(assignment: Assignment): IStatement {
|
override fun process(assignment: Assignment): IStatement {
|
||||||
if(assignment.aug_op!=null)
|
if (assignment.aug_op != null)
|
||||||
throw AstException("augmented assignments should have been converted to normal assignments before this optimizer")
|
throw AstException("augmented assignments should have been converted to normal assignments before this optimizer")
|
||||||
return super.process(assignment)
|
return super.process(assignment)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun process(expr: PrefixExpression): IExpression {
|
override fun process(expr: PrefixExpression): IExpression {
|
||||||
if(expr.operator == "+") {
|
if (expr.operator == "+") {
|
||||||
// +X --> X
|
// +X --> X
|
||||||
optimizationsDone++
|
optimizationsDone++
|
||||||
return expr.expression.process(this)
|
return expr.expression.process(this)
|
||||||
} else if (expr.operator == "not") {
|
} else if (expr.operator == "not") {
|
||||||
(expr.expression as? BinaryExpression)?.let {
|
(expr.expression as? BinaryExpression)?.let {
|
||||||
// NOT (...) -> invert ...
|
// NOT (...) -> invert ...
|
||||||
when(it.operator) {
|
when (it.operator) {
|
||||||
"<" -> {
|
"<" -> {
|
||||||
it.operator = ">="
|
it.operator = ">="
|
||||||
optimizationsDone++
|
optimizationsDone++
|
||||||
@ -63,7 +57,8 @@ class SimplifyExpressions(private val namespace: INameScope, private val heap: H
|
|||||||
optimizationsDone++
|
optimizationsDone++
|
||||||
return it
|
return it
|
||||||
}
|
}
|
||||||
else -> {}
|
else -> {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -79,16 +74,16 @@ class SimplifyExpressions(private val namespace: INameScope, private val heap: H
|
|||||||
|
|
||||||
val leftDt = expr.left.resultingDatatype(namespace, heap)
|
val leftDt = expr.left.resultingDatatype(namespace, heap)
|
||||||
val rightDt = expr.right.resultingDatatype(namespace, heap)
|
val rightDt = expr.right.resultingDatatype(namespace, heap)
|
||||||
if(leftDt!=null && rightDt!=null && leftDt!=rightDt) {
|
if (leftDt != null && rightDt != null && leftDt != rightDt) {
|
||||||
// try to convert a datatype into the other
|
// try to convert a datatype into the other
|
||||||
if(adjustDatatypes(expr, leftVal, leftDt, rightVal, rightDt)) {
|
if (adjustDatatypes(expr, leftVal, leftDt, rightVal, rightDt)) {
|
||||||
optimizationsDone++
|
optimizationsDone++
|
||||||
return expr
|
return expr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Value <associativeoperator> X --> X <associativeoperator> Value
|
// Value <associativeoperator> X --> X <associativeoperator> Value
|
||||||
if(leftVal!=null && expr.operator in associativeOperators && rightVal==null) {
|
if (leftVal != null && expr.operator in associativeOperators && rightVal == null) {
|
||||||
val tmp = expr.left
|
val tmp = expr.left
|
||||||
expr.left = expr.right
|
expr.left = expr.right
|
||||||
expr.right = tmp
|
expr.right = tmp
|
||||||
@ -97,7 +92,7 @@ class SimplifyExpressions(private val namespace: INameScope, private val heap: H
|
|||||||
}
|
}
|
||||||
|
|
||||||
// X + (-A) --> X - A
|
// X + (-A) --> X - A
|
||||||
if(expr.operator=="+" && (expr.right as? PrefixExpression)?.operator=="-") {
|
if (expr.operator == "+" && (expr.right as? PrefixExpression)?.operator == "-") {
|
||||||
expr.operator = "-"
|
expr.operator = "-"
|
||||||
expr.right = (expr.right as PrefixExpression).expression
|
expr.right = (expr.right as PrefixExpression).expression
|
||||||
optimizationsDone++
|
optimizationsDone++
|
||||||
@ -105,7 +100,7 @@ class SimplifyExpressions(private val namespace: INameScope, private val heap: H
|
|||||||
}
|
}
|
||||||
|
|
||||||
// (-A) + X --> X - A
|
// (-A) + X --> X - A
|
||||||
if(expr.operator=="+" && (expr.left as? PrefixExpression)?.operator=="-") {
|
if (expr.operator == "+" && (expr.left as? PrefixExpression)?.operator == "-") {
|
||||||
expr.operator = "-"
|
expr.operator = "-"
|
||||||
val newRight = (expr.left as PrefixExpression).expression
|
val newRight = (expr.left as PrefixExpression).expression
|
||||||
expr.left = expr.right
|
expr.left = expr.right
|
||||||
@ -115,9 +110,9 @@ class SimplifyExpressions(private val namespace: INameScope, private val heap: H
|
|||||||
}
|
}
|
||||||
|
|
||||||
// X + (-value) --> X - value
|
// X + (-value) --> X - value
|
||||||
if(expr.operator=="+" && rightVal!=null) {
|
if (expr.operator == "+" && rightVal != null) {
|
||||||
val rv = rightVal.asNumericValue?.toDouble()
|
val rv = rightVal.asNumericValue?.toDouble()
|
||||||
if(rv!=null && rv<0.0) {
|
if (rv != null && rv < 0.0) {
|
||||||
expr.operator = "-"
|
expr.operator = "-"
|
||||||
expr.right = LiteralValue.fromNumber(-rv, rightVal.type, rightVal.position)
|
expr.right = LiteralValue.fromNumber(-rv, rightVal.type, rightVal.position)
|
||||||
optimizationsDone++
|
optimizationsDone++
|
||||||
@ -126,9 +121,9 @@ class SimplifyExpressions(private val namespace: INameScope, private val heap: H
|
|||||||
}
|
}
|
||||||
|
|
||||||
// (-value) + X --> X - value
|
// (-value) + X --> X - value
|
||||||
if(expr.operator=="+" && leftVal!=null) {
|
if (expr.operator == "+" && leftVal != null) {
|
||||||
val lv = leftVal.asNumericValue?.toDouble()
|
val lv = leftVal.asNumericValue?.toDouble()
|
||||||
if(lv!=null && lv<0.0) {
|
if (lv != null && lv < 0.0) {
|
||||||
expr.operator = "-"
|
expr.operator = "-"
|
||||||
expr.right = LiteralValue.fromNumber(-lv, leftVal.type, leftVal.position)
|
expr.right = LiteralValue.fromNumber(-lv, leftVal.type, leftVal.position)
|
||||||
optimizationsDone++
|
optimizationsDone++
|
||||||
@ -137,7 +132,7 @@ class SimplifyExpressions(private val namespace: INameScope, private val heap: H
|
|||||||
}
|
}
|
||||||
|
|
||||||
// X - (-A) --> X + A
|
// X - (-A) --> X + A
|
||||||
if(expr.operator=="-" && (expr.right as? PrefixExpression)?.operator=="-") {
|
if (expr.operator == "-" && (expr.right as? PrefixExpression)?.operator == "-") {
|
||||||
expr.operator = "+"
|
expr.operator = "+"
|
||||||
expr.right = (expr.right as PrefixExpression).expression
|
expr.right = (expr.right as PrefixExpression).expression
|
||||||
optimizationsDone++
|
optimizationsDone++
|
||||||
@ -145,9 +140,9 @@ class SimplifyExpressions(private val namespace: INameScope, private val heap: H
|
|||||||
}
|
}
|
||||||
|
|
||||||
// X - (-value) --> X + value
|
// X - (-value) --> X + value
|
||||||
if(expr.operator=="-" && rightVal!=null) {
|
if (expr.operator == "-" && rightVal != null) {
|
||||||
val rv = rightVal.asNumericValue?.toDouble()
|
val rv = rightVal.asNumericValue?.toDouble()
|
||||||
if(rv!=null && rv<0.0) {
|
if (rv != null && rv < 0.0) {
|
||||||
expr.operator = "+"
|
expr.operator = "+"
|
||||||
expr.right = LiteralValue.fromNumber(-rv, rightVal.type, rightVal.position)
|
expr.right = LiteralValue.fromNumber(-rv, rightVal.type, rightVal.position)
|
||||||
optimizationsDone++
|
optimizationsDone++
|
||||||
@ -155,70 +150,120 @@ class SimplifyExpressions(private val namespace: INameScope, private val heap: H
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (expr.operator == "+" || expr.operator == "-"
|
||||||
|
&& leftVal == null && rightVal == null
|
||||||
|
&& leftDt in NumericDatatypes && rightDt in NumericDatatypes) {
|
||||||
|
val leftBinExpr = expr.left as? BinaryExpression
|
||||||
|
val rightBinExpr = expr.right as? BinaryExpression
|
||||||
|
if (leftBinExpr?.operator == "*") {
|
||||||
|
if (expr.operator == "+") {
|
||||||
|
// Y*X + X -> X*(Y - 1)
|
||||||
|
// X*Y + X -> X*(Y - 1)
|
||||||
|
val x = expr.right
|
||||||
|
val y = determineY(x, leftBinExpr)
|
||||||
|
if(y!=null) {
|
||||||
|
val yPlus1 = BinaryExpression(y, "+", LiteralValue.fromNumber(1, leftDt!!, y.position), y.position)
|
||||||
|
return BinaryExpression(x, "*", yPlus1, x.position)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Y*X - X -> X*(Y - 1)
|
||||||
|
// X*Y - X -> X*(Y - 1)
|
||||||
|
val x = expr.right
|
||||||
|
val y = determineY(x, leftBinExpr)
|
||||||
|
if(y!=null) {
|
||||||
|
val yMinus1 = BinaryExpression(y, "-", LiteralValue.fromNumber(1, leftDt!!, y.position), y.position)
|
||||||
|
return BinaryExpression(x, "*", yMinus1, x.position)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(rightBinExpr?.operator=="*") {
|
||||||
|
if(expr.operator=="+") {
|
||||||
|
// X + Y*X -> X*(Y + 1)
|
||||||
|
// X + X*Y -> X*(Y + 1)
|
||||||
|
val x = expr.left
|
||||||
|
val y = determineY(x, rightBinExpr)
|
||||||
|
if(y!=null) {
|
||||||
|
val yPlus1 = BinaryExpression(y, "+", LiteralValue.optimalInteger(1, y.position), y.position)
|
||||||
|
return BinaryExpression(x, "*", yPlus1, x.position)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// X - Y*X -> X*(1 - Y)
|
||||||
|
// X - X*Y -> X*(1 - Y)
|
||||||
|
val x = expr.left
|
||||||
|
val y = determineY(x, rightBinExpr)
|
||||||
|
if(y!=null) {
|
||||||
|
val oneMinusY = BinaryExpression(LiteralValue.optimalInteger(1, y.position), "-", y, y.position)
|
||||||
|
return BinaryExpression(x, "*", oneMinusY, x.position)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// simplify when a term is constant and determines the outcome
|
// simplify when a term is constant and determines the outcome
|
||||||
when(expr.operator) {
|
when (expr.operator) {
|
||||||
"or" -> {
|
"or" -> {
|
||||||
if((leftVal!=null && leftVal.asBooleanValue) || (rightVal!=null && rightVal.asBooleanValue)) {
|
if ((leftVal != null && leftVal.asBooleanValue) || (rightVal != null && rightVal.asBooleanValue)) {
|
||||||
optimizationsDone++
|
optimizationsDone++
|
||||||
return constTrue
|
return constTrue
|
||||||
}
|
}
|
||||||
if(leftVal!=null && !leftVal.asBooleanValue) {
|
if (leftVal != null && !leftVal.asBooleanValue) {
|
||||||
optimizationsDone++
|
optimizationsDone++
|
||||||
return expr.right
|
return expr.right
|
||||||
}
|
}
|
||||||
if(rightVal!=null && !rightVal.asBooleanValue) {
|
if (rightVal != null && !rightVal.asBooleanValue) {
|
||||||
optimizationsDone++
|
optimizationsDone++
|
||||||
return expr.left
|
return expr.left
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"and" -> {
|
"and" -> {
|
||||||
if((leftVal!=null && !leftVal.asBooleanValue) || (rightVal!=null && !rightVal.asBooleanValue)) {
|
if ((leftVal != null && !leftVal.asBooleanValue) || (rightVal != null && !rightVal.asBooleanValue)) {
|
||||||
optimizationsDone++
|
optimizationsDone++
|
||||||
return constFalse
|
return constFalse
|
||||||
}
|
}
|
||||||
if(leftVal!=null && leftVal.asBooleanValue) {
|
if (leftVal != null && leftVal.asBooleanValue) {
|
||||||
optimizationsDone++
|
optimizationsDone++
|
||||||
return expr.right
|
return expr.right
|
||||||
}
|
}
|
||||||
if(rightVal!=null && rightVal.asBooleanValue) {
|
if (rightVal != null && rightVal.asBooleanValue) {
|
||||||
optimizationsDone++
|
optimizationsDone++
|
||||||
return expr.left
|
return expr.left
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"xor" -> {
|
"xor" -> {
|
||||||
if(leftVal!=null && !leftVal.asBooleanValue) {
|
if (leftVal != null && !leftVal.asBooleanValue) {
|
||||||
optimizationsDone++
|
optimizationsDone++
|
||||||
return expr.right
|
return expr.right
|
||||||
}
|
}
|
||||||
if(rightVal!=null && !rightVal.asBooleanValue) {
|
if (rightVal != null && !rightVal.asBooleanValue) {
|
||||||
optimizationsDone++
|
optimizationsDone++
|
||||||
return expr.left
|
return expr.left
|
||||||
}
|
}
|
||||||
if(leftVal!=null && leftVal.asBooleanValue) {
|
if (leftVal != null && leftVal.asBooleanValue) {
|
||||||
optimizationsDone++
|
optimizationsDone++
|
||||||
return PrefixExpression("not", expr.right, expr.right.position)
|
return PrefixExpression("not", expr.right, expr.right.position)
|
||||||
}
|
}
|
||||||
if(rightVal!=null && rightVal.asBooleanValue) {
|
if (rightVal != null && rightVal.asBooleanValue) {
|
||||||
optimizationsDone++
|
optimizationsDone++
|
||||||
return PrefixExpression("not", expr.left, expr.left.position)
|
return PrefixExpression("not", expr.left, expr.left.position)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"|", "^" -> {
|
"|", "^" -> {
|
||||||
if(leftVal!=null && !leftVal.asBooleanValue) {
|
if (leftVal != null && !leftVal.asBooleanValue) {
|
||||||
optimizationsDone++
|
optimizationsDone++
|
||||||
return expr.right
|
return expr.right
|
||||||
}
|
}
|
||||||
if(rightVal!=null && !rightVal.asBooleanValue) {
|
if (rightVal != null && !rightVal.asBooleanValue) {
|
||||||
optimizationsDone++
|
optimizationsDone++
|
||||||
return expr.left
|
return expr.left
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"&" -> {
|
"&" -> {
|
||||||
if(leftVal!=null && !leftVal.asBooleanValue) {
|
if (leftVal != null && !leftVal.asBooleanValue) {
|
||||||
optimizationsDone++
|
optimizationsDone++
|
||||||
return constFalse
|
return constFalse
|
||||||
}
|
}
|
||||||
if(rightVal!=null && !rightVal.asBooleanValue) {
|
if (rightVal != null && !rightVal.asBooleanValue) {
|
||||||
optimizationsDone++
|
optimizationsDone++
|
||||||
return constFalse
|
return constFalse
|
||||||
}
|
}
|
||||||
@ -233,6 +278,14 @@ class SimplifyExpressions(private val namespace: INameScope, private val heap: H
|
|||||||
return expr
|
return expr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun determineY(x: IExpression, subBinExpr: BinaryExpression): IExpression? {
|
||||||
|
return when {
|
||||||
|
same(subBinExpr.left, x) -> subBinExpr.right
|
||||||
|
same(subBinExpr.right, x) -> subBinExpr.left
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun adjustDatatypes(expr: BinaryExpression,
|
private fun adjustDatatypes(expr: BinaryExpression,
|
||||||
leftConstVal: LiteralValue?, leftDt: DataType,
|
leftConstVal: LiteralValue?, leftDt: DataType,
|
||||||
rightConstVal: LiteralValue?, rightDt: DataType): Boolean {
|
rightConstVal: LiteralValue?, rightDt: DataType): Boolean {
|
||||||
|
@ -8,16 +8,16 @@ import kotlin.math.floor
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
todo remove unused blocks
|
todo: implement usage counters for blocks, variables, subroutines, heap variables. Then:
|
||||||
todo remove unused variables
|
todo remove unused blocks
|
||||||
todo remove unused subroutines
|
todo remove unused variables
|
||||||
todo remove unused strings and arrays from the heap
|
todo remove unused subroutines
|
||||||
|
todo remove unused strings and arrays from the heap
|
||||||
|
todo inline subroutines that are called exactly once (regardless of their size)
|
||||||
|
todo inline subroutines that are only called a few times (3?) and that are "sufficiently small" (0-3 statements)
|
||||||
|
|
||||||
todo analyse for unreachable code and remove that (f.i. code after goto or return that has no label so can never be jumped to)
|
todo analyse for unreachable code and remove that (f.i. code after goto or return that has no label so can never be jumped to)
|
||||||
|
|
||||||
todo regular subroutines that have 1 or 2 (u)byte or 1 (u)word parameters -> change to asmsub to accept these in A/Y registers instead of on stack
|
|
||||||
|
|
||||||
todo inline subroutines that are called exactly once (regardless of their size)
|
|
||||||
todo inline subroutines that are only called a few times (3?) and that are "sufficiently small" (0-3 statements)
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class StatementOptimizer(private val namespace: INameScope, private val heap: HeapValues) : IAstProcessor {
|
class StatementOptimizer(private val namespace: INameScope, private val heap: HeapValues) : IAstProcessor {
|
||||||
@ -82,6 +82,16 @@ class StatementOptimizer(private val namespace: INameScope, private val heap: He
|
|||||||
return subroutine
|
return subroutine
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun returnregisters(subroutine: Subroutine): List<RegisterOrStatusflag> {
|
||||||
|
return when {
|
||||||
|
subroutine.returntypes.size==0 -> listOf()
|
||||||
|
subroutine.returntypes.size==1 && subroutine.returntypes[0] in setOf(DataType.BYTE, DataType.UBYTE) -> listOf(RegisterOrStatusflag(RegisterOrPair.A, null, null))
|
||||||
|
subroutine.returntypes.size==1 && subroutine.returntypes[0] in setOf(DataType.WORD, DataType.UWORD) -> listOf(RegisterOrStatusflag(RegisterOrPair.AY, null, null))
|
||||||
|
subroutine.returntypes.size==2 && subroutine.returntypes.all { it in setOf(DataType.BYTE, DataType.UBYTE)} -> listOf(RegisterOrStatusflag(RegisterOrPair.A, null, null), RegisterOrStatusflag(RegisterOrPair.Y, null, null))
|
||||||
|
else -> throw FatalAstException("can't convert return values to registers")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun isNotMemory(target: AssignTarget): Boolean {
|
private fun isNotMemory(target: AssignTarget): Boolean {
|
||||||
if(target.register!=null)
|
if(target.register!=null)
|
||||||
return true
|
return true
|
||||||
@ -440,21 +450,6 @@ class StatementOptimizer(private val namespace: INameScope, private val heap: He
|
|||||||
return super.process(assignment)
|
return super.process(assignment)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun same(left: IExpression, right: IExpression): Boolean {
|
|
||||||
if(left===right)
|
|
||||||
return true
|
|
||||||
when(left) {
|
|
||||||
is RegisterExpr ->
|
|
||||||
return (right is RegisterExpr && right.register==left.register)
|
|
||||||
is IdentifierReference ->
|
|
||||||
return (right is IdentifierReference && right.nameInSource==left.nameInSource)
|
|
||||||
is ArrayIndexedExpression ->
|
|
||||||
return (right is ArrayIndexedExpression && right.identifier==left.identifier && right.arrayspec==left.arrayspec)
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun same(target: AssignTarget, value: IExpression): Boolean {
|
private fun same(target: AssignTarget, value: IExpression): Boolean {
|
||||||
return when {
|
return when {
|
||||||
target.memoryAddress!=null -> false
|
target.memoryAddress!=null -> false
|
||||||
@ -491,3 +486,24 @@ class StatementOptimizer(private val namespace: INameScope, private val heap: He
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun same(left: IExpression, right: IExpression): Boolean {
|
||||||
|
if(left===right)
|
||||||
|
return true
|
||||||
|
when(left) {
|
||||||
|
is RegisterExpr ->
|
||||||
|
return (right is RegisterExpr && right.register==left.register)
|
||||||
|
is IdentifierReference ->
|
||||||
|
return (right is IdentifierReference && right.nameInSource==left.nameInSource)
|
||||||
|
is ArrayIndexedExpression ->
|
||||||
|
return (right is ArrayIndexedExpression && right.identifier==left.identifier && right.arrayspec==left.arrayspec)
|
||||||
|
is PrefixExpression ->
|
||||||
|
return (right is PrefixExpression && right.operator==left.operator && same(right.expression, left.expression))
|
||||||
|
is BinaryExpression ->
|
||||||
|
return (right is BinaryExpression && right.operator==left.operator
|
||||||
|
&& same(right.left, left.left)
|
||||||
|
&& same(right.right, left.right))
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
@ -70,8 +70,8 @@
|
|||||||
float rz = rotatedz[i]
|
float rz = rotatedz[i]
|
||||||
if rz >= 0.1 {
|
if rz >= 0.1 {
|
||||||
float persp = (5.0+rz)/height
|
float persp = (5.0+rz)/height
|
||||||
ubyte sx = rotatedx[i] / persp + width/2 as ubyte
|
ubyte sx = rotatedx[i] / persp + width/2.0 as ubyte
|
||||||
ubyte sy = rotatedy[i] / persp + height/2 as ubyte
|
ubyte sy = rotatedy[i] / persp + height/2.0 as ubyte
|
||||||
c64scr.setcc(sx, sy, 46, i+2)
|
c64scr.setcc(sx, sy, 46, i+2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -80,8 +80,8 @@
|
|||||||
float rz = rotatedz[i]
|
float rz = rotatedz[i]
|
||||||
if rz < 0.1 {
|
if rz < 0.1 {
|
||||||
float persp = (5.0+rz)/height
|
float persp = (5.0+rz)/height
|
||||||
ubyte sx = rotatedx[i] / persp + width/2 as ubyte
|
ubyte sx = rotatedx[i] / persp + width/2.0 as ubyte
|
||||||
ubyte sy = rotatedy[i] / persp + height/2 as ubyte
|
ubyte sy = rotatedy[i] / persp + height/2.0 as ubyte
|
||||||
c64scr.setcc(sx, sy, 81, i+2)
|
c64scr.setcc(sx, sy, 81, i+2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,32 +5,29 @@
|
|||||||
|
|
||||||
sub start() {
|
sub start() {
|
||||||
|
|
||||||
ubyte i=101
|
|
||||||
|
|
||||||
A=4
|
inlinecall(1,2,3)
|
||||||
A=5
|
ubyte r = inlinesub(3,4,5)
|
||||||
A=6
|
c64scr.print_ub(r)
|
||||||
A=i
|
c64.CHROUT('\n')
|
||||||
A=99 ; folded ok!
|
}
|
||||||
|
|
||||||
i=4
|
sub inlinecall(byte b1, byte b2, byte b3) {
|
||||||
i=5
|
float f=3.1415
|
||||||
i=6
|
c64scr.print("this is inlinecall!\n")
|
||||||
i=A
|
c64flt.print_f(f)
|
||||||
i=99 ; folded ok
|
f*=2.0
|
||||||
|
c64flt.print_f(f)
|
||||||
@($d020) = 4
|
c64.CHROUT('\n')
|
||||||
@($d020) = 5
|
c64scr.print("end of inlinecall!\n")
|
||||||
@($d020) = 6
|
}
|
||||||
@($d020) = 7
|
|
||||||
@($d020) = 8 ; @todo should not be folded
|
|
||||||
|
|
||||||
c64.EXTCOL = 4
|
|
||||||
c64.EXTCOL = 5
|
|
||||||
c64.EXTCOL = 6
|
|
||||||
c64.EXTCOL = 7
|
|
||||||
c64.EXTCOL = 8 ; @todo not fold
|
|
||||||
|
|
||||||
|
sub inlinesub(ubyte b1, ubyte b2, ubyte b3) -> ubyte {
|
||||||
|
c64scr.print("this is inlinesub!\n")
|
||||||
|
ubyte qq = b1+b2
|
||||||
|
qq += b3
|
||||||
|
c64scr.print("end of inlinesub!\n")
|
||||||
|
return qq
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user