mirror of
https://github.com/KarolS/millfork.git
synced 2025-04-05 13:37:25 +00:00
#10 Fix removal of unused global structs and preserve reads in assignments from volatiles to unuseds.
This commit is contained in:
parent
f5b6d9999c
commit
9e8b889533
@ -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))
|
||||
|
@ -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 {
|
||||
|
@ -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")
|
||||
|
@ -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)
|
||||
|
@ -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(
|
||||
|
@ -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) =>
|
||||
|
@ -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 => }
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user