fixed 'unroll CONSTANTEXPR' compiler errors

This commit is contained in:
Irmen de Jong 2023-09-05 00:53:58 +02:00
parent 9fca978725
commit c15c10a94e
10 changed files with 31 additions and 32 deletions

View File

@ -628,5 +628,4 @@ class ConstantFoldingOptimizer(private val program: Program) : AstWalker() {
return null
}
}
}

View File

@ -384,7 +384,8 @@ class StatementOptimizer(private val program: Program,
}
override fun before(unrollLoop: UnrollLoop, parent: Node): Iterable<IAstModification> {
return if(unrollLoop.iterations<1)
val iterations = unrollLoop.iterations.constValue(program)?.number?.toInt()
return if(iterations!=null && iterations<1)
listOf(IAstModification.Remove(unrollLoop, parent as IStatementContainer))
else
noModifications

View File

@ -76,14 +76,19 @@ internal class AstChecker(private val program: Program,
}
override fun visit(unrollLoop: UnrollLoop) {
if(unrollLoop.iterations<0 || unrollLoop.iterations>65535)
errors.err("invalid number of unrolls", unrollLoop.position)
unrollLoop.body.statements.forEach {
if(it !is InlineAssembly && it !is Assignment && it !is BuiltinFunctionCallStatement && it !is FunctionCallStatement && it !is PostIncrDecr)
errors.err("invalid statement in unroll loop", it.position)
}
if(unrollLoop.iterations * unrollLoop.body.statements.size > 256) {
errors.warn("large number of unrolls, potential code size issue", unrollLoop.position)
val iterations = unrollLoop.iterations.constValue(program)?.number?.toInt()
if(iterations==null) {
errors.err("unroll needs constant number of iterations", unrollLoop.position)
} else {
if (iterations < 0 || iterations > 65535)
errors.err("invalid number of unrolls", unrollLoop.position)
unrollLoop.body.statements.forEach {
if (it !is InlineAssembly && it !is Assignment && it !is BuiltinFunctionCallStatement && it !is FunctionCallStatement && it !is PostIncrDecr)
errors.err("invalid statement in unroll loop", it.position)
}
if (iterations * unrollLoop.body.statements.size > 256) {
errors.warn("large number of unrolls, potential code size issue", unrollLoop.position)
}
}
super.visit(unrollLoop)
}

View File

@ -326,7 +326,7 @@ class IntermediateAstMaker(private val program: Program) {
private fun transform(srcUnroll: UnrollLoop): PtNodeGroup {
val result = PtNodeGroup()
repeat(srcUnroll.iterations) {
repeat(srcUnroll.iterations.constValue(program)!!.number.toInt()) {
srcUnroll.body.statements.forEach {
result.add(transformStatement(it))
}

View File

@ -583,7 +583,7 @@ private fun Prog8ANTLRParser.RepeatloopContext.toAst(): RepeatLoop {
}
private fun Prog8ANTLRParser.UnrollloopContext.toAst(): UnrollLoop {
val iterations = integerliteral().toAst().number.toInt()
val iterations = expression().toAst()
val statements = statement_block()?.toAst() ?: mutableListOf(statement().toAst())
val scope = AnonymousScope(statements, statement_block()?.toPosition()
?: statement().toPosition())

View File

@ -931,11 +931,13 @@ class RepeatLoop(var iterations: Expression?, var body: AnonymousScope, override
iterations?.referencesIdentifier(nameInSource)==true || body.referencesIdentifier(nameInSource)
}
class UnrollLoop(val iterations: Int, var body: AnonymousScope, override val position: Position) : Statement() {
class UnrollLoop(var iterations: Expression, var body: AnonymousScope, override val position: Position) : Statement() {
// note: the iterations needs to evaluate to a constant number once parsed.
override lateinit var parent: Node
override fun linkParents(parent: Node) {
this.parent = parent
iterations.linkParents(this)
body.linkParents(this)
}
@ -943,13 +945,14 @@ class UnrollLoop(val iterations: Int, var body: AnonymousScope, override val pos
override fun replaceChildNode(node: Node, replacement: Node) {
if (node===body) body = replacement as AnonymousScope
else if (node===iterations) iterations = replacement as Expression
else throw FatalAstException("invalid replace")
replacement.parent = this
}
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent)
override fun referencesIdentifier(nameInSource: List<String>): Boolean = body.referencesIdentifier(nameInSource)
override fun referencesIdentifier(nameInSource: List<String>): Boolean = iterations.referencesIdentifier(nameInSource) || body.referencesIdentifier(nameInSource)
}
class UntilLoop(var body: AnonymousScope,

View File

@ -398,6 +398,7 @@ abstract class AstWalker {
fun visit(unrollLoop: UnrollLoop, parent: Node) {
track(before(unrollLoop, parent), unrollLoop, parent)
unrollLoop.iterations.accept(this, unrollLoop)
unrollLoop.body.accept(this, unrollLoop)
track(after(unrollLoop, parent), unrollLoop, parent)
}

View File

@ -1,9 +1,6 @@
TODO
====
- fix compiler crash on "unroll for x in 0 to txt.DEFAULT_WIDTH-1"
- fix compiler error on "unroll txt.DEFAULT_WIDTH"
- prefix prog8 subroutines with p8s_ instead of p8_ to not let them clash with variables in the asm??
- [on branch: shortcircuit] investigate McCarthy evaluation again? this may also reduce code size perhaps for things like if a>4 or a<2 ....
- IR: reduce the number of branch instructions such as BEQ, BEQR, etc (gradually), replace with CMP(I) + status branch instruction

View File

@ -1,22 +1,15 @@
%import textio
%zeropage basicsafe
%zeropage dontuse
main {
sub start() {
const ubyte CONSTANT=80
cx16.r0 = 0
unroll CONSTANT-10 {
cx16.r0++
}
txt.print_uw(cx16.r0)
ubyte[5] xx = [11,22,33,44,55]
ubyte[5] yy = [101,102,103,104,105]
ubyte i=3
ubyte j = 4
uword screen
ubyte result = xx[i] + yy[j]
txt.print_ub(result) ; 149
txt.nl()
result = xx[i] + yy[i]
txt.print_ub(result) ; 148
txt.nl()
@(screen+i) = xx[i] + yy[i]
; ubyte index = 100
; ubyte[] t_index = [1,2,3,4,5]

View File

@ -299,7 +299,7 @@ untilloop: 'do' (statement | statement_block) EOL? 'until' expression ;
repeatloop: 'repeat' expression? EOL? (statement | statement_block) ;
unrollloop: 'unroll' integerliteral? EOL? (statement | statement_block) ;
unrollloop: 'unroll' expression EOL? (statement | statement_block) ; // note: expression must evaluate to a constant
whenstmt: 'when' expression EOL? '{' EOL? (when_choice | EOL) * '}' EOL? ;