1
0
mirror of https://github.com/KarolS/millfork.git synced 2024-06-26 11:29:28 +00:00

#10 Fix removal of unused global structs and preserve reads in assignments from volatiles to unuseds.

This commit is contained in:
Karol Stasiak 2019-10-22 00:05:44 +02:00
parent f5b6d9999c
commit 9e8b889533
7 changed files with 36 additions and 13 deletions

View File

@ -543,6 +543,7 @@ object AbstractExpressionCompiler {
def checkAssignmentTypeAndGetSourceType(ctx: CompilationContext, source: Expression, target: LhsExpression): Type = {
val sourceType = getExpressionType(ctx, source)
if (target == BlackHoleExpression) return sourceType
val targetType = getExpressionType(ctx, target)
if (!sourceType.isAssignableTo(targetType)) {
ctx.log.error(s"Cannot assign `$sourceType` to `$targetType`", target.position.orElse(source.position))

View File

@ -3,7 +3,7 @@ package millfork.compiler.m6809
import millfork.assembly.BranchingOpcodeMapping
import millfork.assembly.m6809.{MLine, NonExistent}
import millfork.compiler.{AbstractCompiler, AbstractExpressionCompiler, AbstractStatementCompiler, BranchSpec, CompilationContext}
import millfork.node.{Assignment, BreakStatement, ContinueStatement, DoWhileStatement, ExecutableStatement, Expression, ExpressionStatement, ForEachStatement, ForStatement, IfStatement, M6809AssemblyStatement, ReturnDispatchStatement, ReturnStatement, VariableExpression, WhileStatement}
import millfork.node.{Assignment, BlackHoleExpression, BreakStatement, ContinueStatement, DoWhileStatement, ExecutableStatement, Expression, ExpressionStatement, ForEachStatement, ForStatement, IfStatement, M6809AssemblyStatement, ReturnDispatchStatement, ReturnStatement, VariableExpression, WhileStatement}
import millfork.assembly.m6809.MOpcode._
import millfork.env.{FatBooleanType, Label, ThingInMemory}
@ -43,6 +43,7 @@ object M6809StatementCompiler extends AbstractStatementCompiler[MLine] {
???
}
case Assignment(destination, source) =>
if (destination == BlackHoleExpression) return M6809ExpressionCompiler.compile(ctx, source, MExpressionTarget.NOTHING, BranchSpec.None) -> Nil
val destinationType = AbstractExpressionCompiler.getExpressionType(ctx, destination)
AbstractExpressionCompiler.checkAssignmentType(ctx, source, destinationType)
destinationType.size match {

View File

@ -2038,6 +2038,7 @@ object MosExpressionCompiler extends AbstractExpressionCompiler[AssemblyLine] {
def compileAssignment(ctx: CompilationContext, source: Expression, target: LhsExpression): List[AssemblyLine] = {
val env = ctx.env
val sourceType = AbstractExpressionCompiler.checkAssignmentTypeAndGetSourceType(ctx, source, target)
if (target == BlackHoleExpression) return compile(ctx, source, None, NoBranching)
val lhsType = AbstractExpressionCompiler.getExpressionType(ctx, target)
val b = env.get[Type]("byte")
val w = env.get[Type]("word")

View File

@ -94,6 +94,7 @@ object Z80StatementCompiler extends AbstractStatementCompiler[ZLine] {
case s: LabelStatement =>
List(ZLine.label(env.prefix + s.name)) -> Nil
case Assignment(destination, source) =>
if (destination == BlackHoleExpression) return Z80ExpressionCompiler.compile(ctx, source, ZExpressionTarget.NOTHING, NoBranching) -> Nil
val sourceType = AbstractExpressionCompiler.getExpressionType(ctx, source)
val targetType = AbstractExpressionCompiler.getExpressionType(ctx, destination)
AbstractExpressionCompiler.checkAssignmentType(ctx, source, targetType)

View File

@ -79,29 +79,31 @@ object UnusedGlobalVariables extends NodeOptimization {
case x => Some(ExpressionStatement(x).pos(s.position))
}
} else Some(s)
case s@Assignment(VariableExpression(n), VariableExpression(_)) =>
if (globalsToRemove(n)) Nil else Some(s)
case s@Assignment(VariableExpression(n), expr@VariableExpression(n2)) =>
if (globalsToRemove(extractThingName(n))) {
if (globalsToRemove(extractThingName(n))) None else Some(Assignment(BlackHoleExpression, expr).pos(s.position))
} else Some(s)
case s@Assignment(VariableExpression(n), LiteralExpression(_, _)) =>
if (globalsToRemove(n)) Nil else Some(s)
if (globalsToRemove(extractThingName(n))) Nil else Some(s)
case s@Assignment(VariableExpression(n), expr) =>
if (globalsToRemove(n)) Some(ExpressionStatement(expr).pos(s.position)) else Some(s)
if (globalsToRemove(extractThingName(n))) Some(ExpressionStatement(expr).pos(s.position)) else Some(s)
case s@Assignment(SeparateBytesExpression(he@VariableExpression(h), le@VariableExpression(l)), expr) =>
if (globalsToRemove(h)) {
if (globalsToRemove(l))
if (globalsToRemove(extractThingName(h))) {
if (globalsToRemove(extractThingName(l)))
Some(ExpressionStatement(expr).pos(s.position))
else
Some(Assignment(SeparateBytesExpression(BlackHoleExpression, le).pos(he.position), expr).pos(s.position))
} else {
if (globalsToRemove(l))
if (globalsToRemove(extractThingName(l)))
Some(Assignment(SeparateBytesExpression(he, BlackHoleExpression).pos(he.position), expr).pos(s.position))
else
Some(s)
}
case s@Assignment(SeparateBytesExpression(h, le@VariableExpression(l)), expr) =>
if (globalsToRemove(l)) Some(Assignment(SeparateBytesExpression(h, BlackHoleExpression).pos(h.position), expr).pos(s.position))
if (globalsToRemove(extractThingName(l))) Some(Assignment(SeparateBytesExpression(h, BlackHoleExpression).pos(h.position), expr).pos(s.position))
else Some(s)
case s@Assignment(SeparateBytesExpression(he@VariableExpression(h), l), expr) =>
if (globalsToRemove(h)) Some(Assignment(SeparateBytesExpression(BlackHoleExpression, l).pos(he.position), expr).pos(s.position))
if (globalsToRemove(extractThingName(h))) Some(Assignment(SeparateBytesExpression(BlackHoleExpression, l).pos(he.position), expr).pos(s.position))
else Some(s)
case s: IfStatement =>
Some(s.copy(

View File

@ -81,8 +81,10 @@ object UnusedLocalVariables extends NodeOptimization {
case x => Some(ExpressionStatement(x).pos(s.position))
}
} else Some(s)
case s@Assignment(VariableExpression(n), VariableExpression(_)) =>
if (localsToRemove(extractThingName(n))) Nil else Some(s)
case s@Assignment(VariableExpression(n), expr@VariableExpression(_)) =>
if (localsToRemove(extractThingName(n))) {
if (localsToRemove(extractThingName(n))) None else Some(Assignment(BlackHoleExpression, expr).pos(s.position))
} else Some(s)
case s@Assignment(VariableExpression(n), LiteralExpression(_, _)) =>
if (localsToRemove(extractThingName(n))) Nil else Some(s)
case s@Assignment(VariableExpression(n), expr) =>

View File

@ -1,7 +1,7 @@
package millfork.test
import millfork.Cpu
import millfork.test.emu.{EmuNodeOptimizedRun, EmuUnoptimizedCrossPlatformRun}
import millfork.test.emu.{EmuCrossPlatformBenchmarkRun, EmuNodeOptimizedRun, EmuUnoptimizedCrossPlatformRun}
import org.scalatest.{FunSuite, Matchers}
/**
@ -53,4 +53,19 @@ class NodeOptimizationSuite extends FunSuite with Matchers {
m.readLong(0xc000) should equal (0x3000000)
}
}
test("Unused global struct variable") {
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Motorola6809)(
"""
| struct p { byte x }
| p b
| void foo (byte x) {
| byte y
| b.x = x
|}
| void main () {
| foo(1)
| }
""".stripMargin) { m => }
}
}