Skip to content

Commit

Permalink
fixed 'unroll CONSTANTEXPR' compiler errors
Browse files Browse the repository at this point in the history
  • Loading branch information
irmen committed Sep 4, 2023
1 parent 9fca978 commit c15c10a
Show file tree
Hide file tree
Showing 10 changed files with 31 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -628,5 +628,4 @@ class ConstantFoldingOptimizer(private val program: Program) : AstWalker() {
return null
}
}

}
3 changes: 2 additions & 1 deletion codeOptimizers/src/prog8/optimizer/StatementOptimizer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
21 changes: 13 additions & 8 deletions compiler/src/prog8/compiler/astprocessing/AstChecker.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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))
}
Expand Down
2 changes: 1 addition & 1 deletion compilerAst/src/prog8/ast/antlr/Antlr2Kotlin.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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())
Expand Down
7 changes: 5 additions & 2 deletions compilerAst/src/prog8/ast/statements/AstStatements.kt
Original file line number Diff line number Diff line change
Expand Up @@ -931,25 +931,28 @@ 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)
}

override fun copy() = throw NotImplementedError("no support for duplicating an UnrollLoop")

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,
Expand Down
1 change: 1 addition & 0 deletions compilerAst/src/prog8/ast/walk/AstWalker.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down
3 changes: 0 additions & 3 deletions docs/source/todo.rst
Original file line number Diff line number Diff line change
@@ -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
Expand Down
21 changes: 7 additions & 14 deletions examples/test.p8
Original file line number Diff line number Diff line change
@@ -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]
Expand Down
2 changes: 1 addition & 1 deletion parser/antlr/Prog8ANTLR.g4
Original file line number Diff line number Diff line change
Expand Up @@ -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? ;

Expand Down

0 comments on commit c15c10a

Please sign in to comment.