1
0
mirror of https://github.com/KarolS/millfork.git synced 2024-07-04 16:29:52 +00:00

8080: Fix certain bulk array operations

This commit is contained in:
Karol Stasiak 2019-07-09 21:59:02 +02:00
parent fe3b7ec5e0
commit 4ab45aba2e
2 changed files with 12 additions and 7 deletions

View File

@ -10,4 +10,6 @@ class LabelGenerator {
private val labelCounter = new AtomicLong
def apply(prefix: String): String = "." + prefix + "__" + labelCounter.incrementAndGet().formatted("%05d")
def asNumber(): Long = labelCounter.incrementAndGet()
}

View File

@ -41,7 +41,7 @@ class Z80StatementPreprocessor(ctx: CompilationContext, statements: List[Executa
def maybeOptimizeForStatement(f: ForStatement): Option[(ExecutableStatement, VV)] = {
if (!ctx.options.flag(CompilationFlag.DangerousOptimizations)) return None
// TODO: figure out when this is useful
// Currently all instances of arr[i] are replaced with arr`popt`i[0], where arr`popt`i is a new pointer variable.
// Currently all instances of arr[i] are replaced with arr`popt##`i[0], where arr`popt`i is a new pointer variable.
// This breaks the main Millfork promise of not using hidden variables!
// This may be increase code size or runtime in certain circumstances, more experimentation is needed.
if (!optimize) return None
@ -60,11 +60,13 @@ class Z80StatementPreprocessor(ctx: CompilationContext, statements: List[Executa
val indexedArrays = findIndexedArrays(f.body, f.variable).toSet
if (indexedArrays.isEmpty) return None
if (indexedArrays.size > 2) return None // TODO: is this the optimal limit?
for (a <- indexedArrays) {
val newVariables: Map[(String, String), String] = (for (a <- indexedArrays) yield {
val array = ctx.env.get[MfArray](a + ".array")
val infix = "`popt" + ctx.nextLabel.asNumber() + "`"
// Evil hidden memory usage:
val newVariable = a + infix + f.variable
env.registerVariable(VariableDeclarationStatement(
a + "`popt`" + f.variable,
newVariable,
"pointer",
None,
global = false,
@ -76,7 +78,8 @@ class Z80StatementPreprocessor(ctx: CompilationContext, statements: List[Executa
None,
None
), ctx.options, isPointy = true)
}
(a -> f.variable) -> (a + infix + f.variable)
}).toMap
def replaceArrayIndexingsE(node: Expression): Expression = node.replaceIndexedExpression(
i => i.index match {
@ -86,7 +89,7 @@ class Z80StatementPreprocessor(ctx: CompilationContext, statements: List[Executa
i => {
val array = ctx.env.get[MfArray](i.name + ".array")
optimizeExpr(IndirectFieldExpression(
FunctionCallExpression("pointer." + array.elementType.name, List(VariableExpression(i.name + "`popt`" + f.variable))),
FunctionCallExpression("pointer." + array.elementType.name, List(VariableExpression(newVariables(i.name, f.variable)))),
Seq(LiteralExpression(0, 1)),
Seq()), Map())
}
@ -118,7 +121,7 @@ class Z80StatementPreprocessor(ctx: CompilationContext, statements: List[Executa
val newBody = replaceArrayIndexings(f.body) ++ indexedArrays.map(name => {
val array = ctx.env.get[MfArray](name + ".array")
ExpressionStatement(FunctionCallExpression(operator, List(
VariableExpression(name + "`popt`" + f.variable),
VariableExpression(newVariables(name, f.variable)),
LiteralExpression(1, 1))))
})
val optStart = optimizeExpr(f.start, Map())
@ -126,7 +129,7 @@ class Z80StatementPreprocessor(ctx: CompilationContext, statements: List[Executa
indexedArrays.map(name => {
val array = ctx.env.get[MfArray](name + ".array")
Assignment(
VariableExpression(name + "`popt`" + f.variable),
VariableExpression(newVariables(name, f.variable)),
FunctionCallExpression("pointer." + array.elementType.name, List(
SumExpression(List(false -> VariableExpression(name + ".addr"), false -> optStart), decimal = false)
)))