mirror of https://github.com/irmen/prog8.git
cleanups
This commit is contained in:
parent
8babad9c7c
commit
53df0eb707
|
@ -139,13 +139,9 @@ class PtAddressOf(position: Position) : PtExpression(DataType.UWORD, position) {
|
||||||
|
|
||||||
class PtArrayIndexer(elementType: DataType, position: Position): PtExpression(elementType, position) {
|
class PtArrayIndexer(elementType: DataType, position: Position): PtExpression(elementType, position) {
|
||||||
val variable: PtIdentifier
|
val variable: PtIdentifier
|
||||||
get() {
|
get() = children[0] as PtIdentifier
|
||||||
require((children[0] as? PtIdentifier)?.type in ArrayDatatypes+DataType.STR) // TODO remove
|
|
||||||
return children[0] as PtIdentifier
|
|
||||||
}
|
|
||||||
val index: PtExpression
|
val index: PtExpression
|
||||||
get() = children[1] as PtExpression
|
get() = children[1] as PtExpression
|
||||||
|
|
||||||
val splitWords: Boolean
|
val splitWords: Boolean
|
||||||
get() = variable.type in SplitWordArrayTypes
|
get() = variable.type in SplitWordArrayTypes
|
||||||
|
|
||||||
|
|
|
@ -65,8 +65,6 @@ internal fun optimizeAssembly(lines: MutableList<String>, machine: IMachineDefin
|
||||||
numberOfOptimizations++
|
numberOfOptimizations++
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO more assembly peephole optimizations
|
|
||||||
|
|
||||||
return numberOfOptimizations
|
return numberOfOptimizations
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -193,7 +193,7 @@ internal class IfElseAsmGen(private val program: PtProgram,
|
||||||
else
|
else
|
||||||
translateIfElseBodies("beq", stmt)
|
translateIfElseBodies("beq", stmt)
|
||||||
} else {
|
} else {
|
||||||
errors.warn("SLOW FALLBACK FOR 'IF' CODEGEN - ask for support", stmt.position) // TODO should have no more of these at all
|
errors.warn("SLOW FALLBACK FOR 'IF' CODEGEN - ask for support", stmt.position) // should not occur ;-)
|
||||||
assignConditionValueToRegisterAndTest(stmt.condition)
|
assignConditionValueToRegisterAndTest(stmt.condition)
|
||||||
if(jumpAfterIf!=null)
|
if(jumpAfterIf!=null)
|
||||||
translateJumpElseBodies("bne", "beq", jumpAfterIf, stmt.elseScope)
|
translateJumpElseBodies("bne", "beq", jumpAfterIf, stmt.elseScope)
|
||||||
|
|
|
@ -635,8 +635,7 @@ internal class ProgramAndVarsGen(
|
||||||
} else 0
|
} else 0
|
||||||
|
|
||||||
when (variable.dt) {
|
when (variable.dt) {
|
||||||
DataType.BOOL -> TODO("bool var to asm")
|
DataType.BOOL, DataType.UBYTE -> asmgen.out("${variable.name}\t.byte ${initialValue.toHex()}")
|
||||||
DataType.UBYTE -> asmgen.out("${variable.name}\t.byte ${initialValue.toHex()}")
|
|
||||||
DataType.BYTE -> asmgen.out("${variable.name}\t.char $initialValue")
|
DataType.BYTE -> asmgen.out("${variable.name}\t.char $initialValue")
|
||||||
DataType.UWORD -> asmgen.out("${variable.name}\t.word ${initialValue.toHex()}")
|
DataType.UWORD -> asmgen.out("${variable.name}\t.word ${initialValue.toHex()}")
|
||||||
DataType.WORD -> asmgen.out("${variable.name}\t.sint $initialValue")
|
DataType.WORD -> asmgen.out("${variable.name}\t.sint $initialValue")
|
||||||
|
|
|
@ -35,7 +35,7 @@ internal class AnyExprAsmGen(
|
||||||
require(expr.left.type in WordDatatypes && expr.right.type in WordDatatypes) {
|
require(expr.left.type in WordDatatypes && expr.right.type in WordDatatypes) {
|
||||||
"both operands must be words"
|
"both operands must be words"
|
||||||
}
|
}
|
||||||
return assignWordBinExpr(expr)
|
throw AssemblyError("expression should have been handled otherwise: word ${expr.operator} at ${expr.position}")
|
||||||
}
|
}
|
||||||
DataType.FLOAT -> {
|
DataType.FLOAT -> {
|
||||||
require(expr.left.type==DataType.FLOAT && expr.right.type==DataType.FLOAT) {
|
require(expr.left.type==DataType.FLOAT && expr.right.type==DataType.FLOAT) {
|
||||||
|
@ -47,30 +47,6 @@ internal class AnyExprAsmGen(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun assignWordBinExpr(expr: PtBinaryExpression): Boolean {
|
|
||||||
when(expr.operator) {
|
|
||||||
"+" -> TODO("word + at ${expr.position}")
|
|
||||||
"-" -> TODO("word - at ${expr.position}")
|
|
||||||
"*" -> TODO("word * at ${expr.position}")
|
|
||||||
"/" -> TODO("word / at ${expr.position}")
|
|
||||||
"<<" -> TODO("word << at ${expr.position}")
|
|
||||||
">>" -> TODO("word >> at ${expr.position}")
|
|
||||||
"%" -> TODO("word % at ${expr.position}")
|
|
||||||
"and" -> TODO("word logical and (with optional shortcircuit) ${expr.position}")
|
|
||||||
"or" -> TODO("word logical or (with optional shortcircuit) ${expr.position}")
|
|
||||||
"&" -> TODO("word and at ${expr.position}")
|
|
||||||
"|" -> TODO("word or at ${expr.position}")
|
|
||||||
"^", "xor" -> TODO("word xor at ${expr.position}")
|
|
||||||
"==" -> TODO("word == at ${expr.position}")
|
|
||||||
"!=" -> TODO("word != at ${expr.position}")
|
|
||||||
"<" -> TODO("word < at ${expr.position}")
|
|
||||||
"<=" -> TODO("word <= at ${expr.position}")
|
|
||||||
">" -> TODO("word > at ${expr.position}")
|
|
||||||
">=" -> TODO("word >= at ${expr.position}")
|
|
||||||
else -> return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun assignByteBinExpr(expr: PtBinaryExpression, assign: AsmAssignment): Boolean {
|
private fun assignByteBinExpr(expr: PtBinaryExpression, assign: AsmAssignment): Boolean {
|
||||||
when(expr.operator) {
|
when(expr.operator) {
|
||||||
"+" -> {
|
"+" -> {
|
||||||
|
@ -89,21 +65,11 @@ internal class AnyExprAsmGen(
|
||||||
asmgen.assignRegister(RegisterOrPair.A, assign.target)
|
asmgen.assignRegister(RegisterOrPair.A, assign.target)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
"*" -> {
|
"*" -> TODO("byte * at ${expr.position}")
|
||||||
TODO("byte * at ${expr.position}")
|
"/" -> TODO("byte / at ${expr.position}")
|
||||||
}
|
"<<" -> TODO("byte << at ${expr.position}")
|
||||||
"/" -> {
|
">>" -> TODO("byte >> at ${expr.position}")
|
||||||
TODO("byte / at ${expr.position}")
|
"%" -> TODO("byte % at ${expr.position}")
|
||||||
}
|
|
||||||
"<<" -> {
|
|
||||||
TODO("byte << at ${expr.position}")
|
|
||||||
}
|
|
||||||
">>" -> {
|
|
||||||
TODO("byte >> at ${expr.position}")
|
|
||||||
}
|
|
||||||
"%" -> {
|
|
||||||
TODO("byte % at ${expr.position}")
|
|
||||||
}
|
|
||||||
"and" -> TODO("logical and (with optional shortcircuit) ${expr.position}")
|
"and" -> TODO("logical and (with optional shortcircuit) ${expr.position}")
|
||||||
"or" -> TODO("logical or (with optional shortcircuit) ${expr.position}")
|
"or" -> TODO("logical or (with optional shortcircuit) ${expr.position}")
|
||||||
"&" -> {
|
"&" -> {
|
||||||
|
@ -130,24 +96,12 @@ internal class AnyExprAsmGen(
|
||||||
asmgen.assignRegister(RegisterOrPair.A, assign.target)
|
asmgen.assignRegister(RegisterOrPair.A, assign.target)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
"==" -> {
|
"==" -> TODO("byte == at ${expr.position}")
|
||||||
TODO("byte == at ${expr.position}")
|
"!=" -> TODO("byte != at ${expr.position}")
|
||||||
}
|
"<" -> TODO("byte < at ${expr.position}")
|
||||||
"!=" -> {
|
"<=" -> TODO("byte <= at ${expr.position}")
|
||||||
TODO("byte != at ${expr.position}")
|
">" -> TODO("byte > at ${expr.position}")
|
||||||
}
|
">=" -> TODO("byte >= at ${expr.position}")
|
||||||
"<" -> {
|
|
||||||
TODO("byte < at ${expr.position}")
|
|
||||||
}
|
|
||||||
"<=" -> {
|
|
||||||
TODO("byte <= at ${expr.position}")
|
|
||||||
}
|
|
||||||
">" -> {
|
|
||||||
TODO("byte > at ${expr.position}")
|
|
||||||
}
|
|
||||||
">=" -> {
|
|
||||||
TODO("byte >= at ${expr.position}")
|
|
||||||
}
|
|
||||||
else -> return false
|
else -> return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,15 +52,12 @@ class IRPeepholeOptimizer(private val irprog: IRProgram) {
|
||||||
|| removeWeirdBranches(chunk1, chunk2, indexedInstructions)
|
|| removeWeirdBranches(chunk1, chunk2, indexedInstructions)
|
||||||
|| removeDoubleSecClc(chunk1, indexedInstructions)
|
|| removeDoubleSecClc(chunk1, indexedInstructions)
|
||||||
|| cleanupPushPop(chunk1, indexedInstructions)
|
|| cleanupPushPop(chunk1, indexedInstructions)
|
||||||
// TODO other optimizations
|
|
||||||
} while (changed)
|
} while (changed)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
removeEmptyChunks(sub)
|
removeEmptyChunks(sub)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO also do register optimization step here at the end?
|
|
||||||
|
|
||||||
irprog.linkChunks() // re-link
|
irprog.linkChunks() // re-link
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -451,12 +448,13 @@ class IRPeepholeOptimizer(private val irprog: IRProgram) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
// TODO: detect multiple loads to the same target registers, only keep first (if source is not I/O memory)
|
Possible other optimizations:
|
||||||
// TODO: detect multiple stores to the same target, only keep first (if target is not I/O memory)
|
// detect multiple loads to the same target registers, only keep first (if source is not I/O memory)
|
||||||
// TODO: detect multiple float ffrom/fto to the same target, only keep first
|
// detect multiple stores to the same target, only keep first (if target is not I/O memory)
|
||||||
// TODO: detect subsequent same xors/nots/negs, remove the pairs completely as they cancel out
|
// detect multiple float ffrom/fto to the same target, only keep first
|
||||||
// TODO: detect multiple same ands, ors; only keep first
|
// detect subsequent same xors/nots/negs, remove the pairs completely as they cancel out
|
||||||
// TODO: (hard) detect multiple registers being assigned the same value (and not changed) - use only 1 of them
|
// detect multiple same ands, ors; only keep first
|
||||||
|
// detect multiple registers being assigned the same value (and not changed) - use only 1 of them (hard!)
|
||||||
// ...
|
// ...
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
|
@ -435,7 +435,6 @@ class ConstantFoldingOptimizer(private val program: Program, private val errors:
|
||||||
subrightIsConst: Boolean): IAstModification?
|
subrightIsConst: Boolean): IAstModification?
|
||||||
{
|
{
|
||||||
// NOTE: THESE REORDERINGS ARE ONLY VALID FOR FLOATING POINT CONSTANTS
|
// NOTE: THESE REORDERINGS ARE ONLY VALID FOR FLOATING POINT CONSTANTS
|
||||||
// TODO: this implements only a small set of possible reorderings at this time, we could perhaps add more
|
|
||||||
|
|
||||||
if(expr.operator==subExpr.operator) {
|
if(expr.operator==subExpr.operator) {
|
||||||
// both operators are the same.
|
// both operators are the same.
|
||||||
|
|
|
@ -13,8 +13,6 @@ import kotlin.math.abs
|
||||||
import kotlin.math.log2
|
import kotlin.math.log2
|
||||||
import kotlin.math.pow
|
import kotlin.math.pow
|
||||||
|
|
||||||
// TODO add more peephole expression optimizations? Investigate what optimizations binaryen has?
|
|
||||||
|
|
||||||
class ExpressionSimplifier(private val program: Program, private val options: CompilationOptions, private val errors: IErrorReporter) : AstWalker() {
|
class ExpressionSimplifier(private val program: Program, private val options: CompilationOptions, private val errors: IErrorReporter) : AstWalker() {
|
||||||
private val powersOfTwo = (1..16).map { (2.0).pow(it) }.toSet()
|
private val powersOfTwo = (1..16).map { (2.0).pow(it) }.toSet()
|
||||||
private val negativePowersOfTwo = powersOfTwo.map { -it }.toSet()
|
private val negativePowersOfTwo = powersOfTwo.map { -it }.toSet()
|
||||||
|
@ -740,7 +738,7 @@ class ExpressionSimplifier(private val program: Program, private val options: Co
|
||||||
in powersOfTwo -> {
|
in powersOfTwo -> {
|
||||||
if (leftDt==DataType.UBYTE || leftDt==DataType.UWORD) {
|
if (leftDt==DataType.UBYTE || leftDt==DataType.UWORD) {
|
||||||
// Unsigned number divided by a power of two => shift right
|
// Unsigned number divided by a power of two => shift right
|
||||||
// Signed number can't simply be bitshifted in this case (due to rounding issues for negative values), TODO is this correct???
|
// Signed number can't simply be bitshifted in this case (due to rounding issues for negative values),
|
||||||
// so we leave that as is and let the code generator deal with it.
|
// so we leave that as is and let the code generator deal with it.
|
||||||
val numshifts = log2(cv).toInt()
|
val numshifts = log2(cv).toInt()
|
||||||
return BinaryExpression(expr.left, ">>", NumericLiteral.optimalInteger(numshifts, expr.position), expr.position)
|
return BinaryExpression(expr.left, ">>", NumericLiteral.optimalInteger(numshifts, expr.position), expr.position)
|
||||||
|
|
|
@ -156,28 +156,6 @@ internal class VariousCleanups(val program: Program, val errors: IErrorReporter,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: is this really no longer needed in boolean branch?
|
|
||||||
if(expr.operator in LogicalOperators) {
|
|
||||||
// remove redundant !=0 comparisons from logical expressions such as: a!=0 xor b --> a xor b (only for byte operands!)
|
|
||||||
val leftExpr = expr.left as? BinaryExpression
|
|
||||||
if(leftExpr != null &&
|
|
||||||
leftExpr.operator == "!=" &&
|
|
||||||
!leftExpr.left.isSimple &&
|
|
||||||
leftExpr.left.inferType(program).isBytes &&
|
|
||||||
leftExpr.right.constValue(program)?.number == 0.0) {
|
|
||||||
return listOf(IAstModification.ReplaceNode(leftExpr, leftExpr.left, expr))
|
|
||||||
}
|
|
||||||
val rightExpr = expr.right as? BinaryExpression
|
|
||||||
if(rightExpr != null &&
|
|
||||||
rightExpr.operator == "!=" &&
|
|
||||||
!rightExpr.left.isSimple &&
|
|
||||||
rightExpr.left.inferType(program).isBytes &&
|
|
||||||
rightExpr.right.constValue(program)?.number == 0.0) {
|
|
||||||
return listOf(IAstModification.ReplaceNode(rightExpr, rightExpr.left, expr))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
return noModifications
|
return noModifications
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -97,7 +97,7 @@ private fun StatementContext.toAst() : Statement {
|
||||||
val operator = it.operator.text
|
val operator = it.operator.text
|
||||||
val pos = it.toPosition()
|
val pos = it.toPosition()
|
||||||
// print("\u001b[92mINFO\u001B[0m ") // bright green
|
// print("\u001b[92mINFO\u001B[0m ") // bright green
|
||||||
// println("${pos}: ++ and -- will be removed in a future version, please use +=1 or -=1 instead.") // TODO
|
// println("${pos}: ++ and -- will be removed in a future version, please use +=1 or -=1 instead.") // .... if we decode to remove them one day
|
||||||
val addSubOne = BinaryExpression(tgt.toExpression(), if(operator=="++") "+" else "-", NumericLiteral.optimalInteger(1, pos), pos, false)
|
val addSubOne = BinaryExpression(tgt.toExpression(), if(operator=="++") "+" else "-", NumericLiteral.optimalInteger(1, pos), pos, false)
|
||||||
return Assignment(tgt, addSubOne, AssignmentOrigin.USERCODE, pos)
|
return Assignment(tgt, addSubOne, AssignmentOrigin.USERCODE, pos)
|
||||||
}
|
}
|
||||||
|
|
|
@ -538,8 +538,7 @@ data class AssignTarget(var identifier: IdentifierReference?,
|
||||||
if (memoryAddress != null)
|
if (memoryAddress != null)
|
||||||
return InferredTypes.knownFor(DataType.UBYTE)
|
return InferredTypes.knownFor(DataType.UBYTE)
|
||||||
|
|
||||||
// a multi-assign has no 1 type... TODO although it could perhaps be the type of the first target?
|
// a multi-target has no 1 particular type
|
||||||
|
|
||||||
return InferredTypes.unknown()
|
return InferredTypes.unknown()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,18 +3,47 @@
|
||||||
%option no_sysinit
|
%option no_sysinit
|
||||||
|
|
||||||
main {
|
main {
|
||||||
sub start() {
|
ubyte[255] array1
|
||||||
sys.clear_carry()
|
ubyte[255] array2
|
||||||
cx16.r0s=-42
|
uword block1 = memory("b1", 6000 ,0)
|
||||||
|
uword block2 = memory("b2", 6000 ,0)
|
||||||
|
|
||||||
if_z
|
sub start() {
|
||||||
txt.print("zero")
|
cbm.SETTIM(0,0,0)
|
||||||
else if_cs
|
|
||||||
txt.print("carry")
|
repeat 2000 {
|
||||||
else if_neg
|
sys.memcopy(array1, array2, sizeof(array1))
|
||||||
txt.print("negative")
|
}
|
||||||
else
|
|
||||||
txt.print("nothing")
|
txt.print_uw(cbm.RDTIM16())
|
||||||
|
txt.nl()
|
||||||
|
|
||||||
|
cbm.SETTIM(0,0,0)
|
||||||
|
|
||||||
|
repeat 2000 {
|
||||||
|
cx16.memory_copy(array1, array2, sizeof(array1))
|
||||||
|
}
|
||||||
|
|
||||||
|
txt.print_uw(cbm.RDTIM16())
|
||||||
|
txt.nl()
|
||||||
|
|
||||||
|
cbm.SETTIM(0,0,0)
|
||||||
|
|
||||||
|
repeat 100 {
|
||||||
|
sys.memcopy(block1, block2, 6000)
|
||||||
|
}
|
||||||
|
|
||||||
|
txt.print_uw(cbm.RDTIM16())
|
||||||
|
txt.nl()
|
||||||
|
|
||||||
|
cbm.SETTIM(0,0,0)
|
||||||
|
|
||||||
|
repeat 100 {
|
||||||
|
cx16.memory_copy(block1, block2, 6000)
|
||||||
|
}
|
||||||
|
|
||||||
|
txt.print_uw(cbm.RDTIM16())
|
||||||
|
txt.nl()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -202,7 +202,7 @@ class IRFileReader {
|
||||||
var initNumeric: Double? = null
|
var initNumeric: Double? = null
|
||||||
var initArray: StArray? = null
|
var initArray: StArray? = null
|
||||||
when(dt) {
|
when(dt) {
|
||||||
DataType.BOOL -> TODO("parse boolean $value")
|
DataType.BOOL -> initNumeric = if(value.lowercase()=="false") 0.0 else 1.0
|
||||||
in NumericDatatypes -> initNumeric = parseIRValue(value)
|
in NumericDatatypes -> initNumeric = parseIRValue(value)
|
||||||
in ArrayDatatypes -> {
|
in ArrayDatatypes -> {
|
||||||
initArray = value.split(',').map {
|
initArray = value.split(',').map {
|
||||||
|
|
|
@ -235,7 +235,6 @@ class IRStArrayElement(val number: Double?, val addressOfSymbol: String?) {
|
||||||
}
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
// TODO TEMPORARY
|
|
||||||
require(number!=null || addressOfSymbol!=null)
|
require(number!=null || addressOfSymbol!=null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue