mirror of
https://github.com/KarolS/millfork.git
synced 2024-11-17 16:05:31 +00:00
Fix several things:
– statement preprocessor – unused label removal – >>>> operator on 6502 – constant byte comparison on 6502
This commit is contained in:
parent
847a7255c6
commit
514e819ddf
@ -685,19 +685,19 @@ object AlwaysGoodOptimizations {
|
||||
needsFlowInfo = FlowInfoRequirement.NoRequirement,
|
||||
(Elidable & HasOpcode(JMP) & HasAddrMode(Absolute) & MatchParameter(0)) ~
|
||||
(Elidable & LinearOrBranch).* ~
|
||||
(HasOpcode(LABEL) & MatchParameter(0)) ~~> (_ => Nil),
|
||||
(HasOpcode(LABEL) & MatchParameter(0)) ~~> (code => List(code.last)),
|
||||
(Elidable & HasOpcode(BRA) & MatchParameter(0)) ~
|
||||
(Elidable & LinearOrBranch).* ~
|
||||
(HasOpcode(LABEL) & MatchParameter(0)) ~~> (_ => Nil),
|
||||
(HasOpcode(LABEL) & MatchParameter(0)) ~~> (code => List(code.last)),
|
||||
(Elidable & HasOpcode(JMP) & HasAddrMode(Absolute) & MatchParameter(0)) ~
|
||||
(Not(HasOpcode(LABEL)) & Not(MatchParameter(0))).* ~
|
||||
(HasOpcode(LABEL) & MatchParameter(0)) ~
|
||||
((HasOpcode(LABEL) & MatchParameter(0)) ~
|
||||
(HasOpcode(LABEL) | NoopDiscardsFlags).* ~
|
||||
HasOpcode(RTS) ~~> (code => AssemblyLine.implied(RTS) :: code.tail),
|
||||
HasOpcode(RTS)).capture(1) ~~> ((code, ctx) => ctx.get[List[AssemblyLine]](1) ++ code.tail),
|
||||
(Elidable & ShortBranching & MatchParameter(0)) ~
|
||||
(NoopDiscardsFlags.* ~
|
||||
(Elidable & HasOpcode(RTS))).capture(1) ~
|
||||
(HasOpcode(LABEL) & MatchParameter(0)) ~
|
||||
(Elidable & HasOpcode(RTS)) ~
|
||||
(HasOpcode(LABEL) & MatchParameter(0))).capture(1) ~
|
||||
NoopDiscardsFlags.* ~
|
||||
(Elidable & HasOpcode(RTS)) ~~> ((code, ctx) => ctx.get[List[AssemblyLine]](1)),
|
||||
)
|
||||
|
@ -19,7 +19,9 @@ abstract class AbstractStatementPreprocessor(ctx: CompilationContext, statements
|
||||
protected val localPrefix = ctx.function.name + "$"
|
||||
protected val usedIdentifiers = if (optimize) statements.flatMap(_.getAllExpressions).flatMap(_.getAllIdentifiers) else Set()
|
||||
protected val trackableVars: Set[String] = if (optimize) {
|
||||
env.getAllLocalVariables.map(_.name.stripPrefix(localPrefix))
|
||||
env.getAllLocalVariables
|
||||
.filterNot(_.typ.isSigned) // sadly, tracking loses signedness
|
||||
.map(_.name.stripPrefix(localPrefix))
|
||||
.filterNot(_.contains("."))
|
||||
.filterNot(_.contains("$"))
|
||||
.filterNot { vname =>
|
||||
@ -61,22 +63,25 @@ abstract class AbstractStatementPreprocessor(ctx: CompilationContext, statements
|
||||
stmt match {
|
||||
case Assignment(ve@VariableExpression(v), arg) if trackableVars(v) =>
|
||||
cv = search(arg, cv)
|
||||
|
||||
Assignment(ve, optimizeExpr(arg, cv)).pos(pos) -> (env.eval(arg, currentVarValues) match {
|
||||
case Some(c) => cv + (v -> c)
|
||||
case None => cv - v
|
||||
})
|
||||
case Assignment(ve, arg) =>
|
||||
cv = search(arg, cv)
|
||||
cv = search(ve, cv)
|
||||
Assignment(ve, optimizeExpr(arg, cv)).pos(pos) -> cv
|
||||
case ExpressionStatement(expr@FunctionCallExpression("+=", List(VariableExpression(v), arg)))
|
||||
if currentVarValues.contains(v) =>
|
||||
cv = search(arg, cv)
|
||||
ExpressionStatement(optimizeExpr(expr, cv)).pos(pos) -> (env.eval(expr, currentVarValues) match {
|
||||
ExpressionStatement(optimizeExpr(expr, cv - v)).pos(pos) -> (env.eval(expr, currentVarValues) match {
|
||||
case Some(c) => if (cv.contains(v)) cv + (v -> (cv(v) + c)) else cv
|
||||
case None => cv - v
|
||||
})
|
||||
case ExpressionStatement(expr@FunctionCallExpression(op, List(VariableExpression(v), arg)))
|
||||
if op.endsWith("=") && op != ">=" && op != "<=" && op != ":=" =>
|
||||
cv = search(arg, cv)
|
||||
ExpressionStatement(optimizeExpr(expr, cv)).pos(pos) -> (cv - v)
|
||||
ExpressionStatement(optimizeExpr(expr, cv - v)).pos(pos) -> (cv - v)
|
||||
case ExpressionStatement(expr) =>
|
||||
cv = search(expr, cv)
|
||||
ExpressionStatement(optimizeExpr(expr, cv)).pos(pos) -> cv
|
||||
@ -88,7 +93,7 @@ abstract class AbstractStatementPreprocessor(ctx: CompilationContext, statements
|
||||
IfStatement(c, t, e).pos(pos) -> commonVV(vt, ve)
|
||||
case WhileStatement(cond, body, inc, labels) =>
|
||||
cv = search(cond, cv)
|
||||
val c = optimizeExpr(cond, cv)
|
||||
val c = optimizeExpr(cond, Map())
|
||||
val (b, _) = optimizeStmts(body, Map())
|
||||
val (i, _) = optimizeStmts(inc, Map())
|
||||
WhileStatement(c, b, i, labels).pos(pos) -> Map()
|
||||
@ -161,13 +166,18 @@ abstract class AbstractStatementPreprocessor(ctx: CompilationContext, statements
|
||||
ErrorReporting.debug(s"Using node flow to replace $v with $constant", pos)
|
||||
GeneratedConstantExpression(constant, getExpressionType(ctx, expr)).pos(pos)
|
||||
case FunctionCallExpression(t1, List(FunctionCallExpression(t2, List(arg))))
|
||||
if optimize && pointlessDoubleCast(t1, t2, expr) =>
|
||||
if optimize && pointlessDoubleCast(t1, t2, arg) =>
|
||||
ErrorReporting.debug(s"Pointless double cast $t1($t2(...))", pos)
|
||||
optimizeExpr(FunctionCallExpression(t1, List(arg)), currentVarValues)
|
||||
case FunctionCallExpression(t1, List(arg))
|
||||
if optimize && pointlessCast(t1, expr) =>
|
||||
if optimize && pointlessCast(t1, arg) =>
|
||||
ErrorReporting.debug(s"Pointless cast $t1(...)", pos)
|
||||
optimizeExpr(arg, currentVarValues)
|
||||
case FunctionCallExpression("nonet", args) =>
|
||||
// Eliminating variables may eliminate carry
|
||||
FunctionCallExpression("nonet", args.map(arg => optimizeExpr(arg, Map()))).pos(pos)
|
||||
case FunctionCallExpression(name, args) =>
|
||||
FunctionCallExpression(name, args.map(arg => optimizeExpr(arg, currentVarValues))).pos(pos)
|
||||
case _ => expr // TODO
|
||||
}
|
||||
}
|
||||
|
@ -214,17 +214,21 @@ object BuiltIns {
|
||||
}
|
||||
}
|
||||
|
||||
def compileNonetOps(ctx: CompilationContext, lhs: LhsExpression, rhs: Expression): List[AssemblyLine] = {
|
||||
def compileNonetOps(ctx: CompilationContext, lhs: Expression, rhs: Expression): List[AssemblyLine] = {
|
||||
val env = ctx.env
|
||||
val b = env.get[Type]("byte")
|
||||
val (ldaHi, ldaLo) = lhs match {
|
||||
case v: VariableExpression =>
|
||||
val variable = env.get[Variable](v.name)
|
||||
AssemblyLine.variable(ctx, LDA, variable, 1) -> AssemblyLine.variable(ctx, LDA, variable, 0)
|
||||
case SeparateBytesExpression(h: VariableExpression, l: VariableExpression) =>
|
||||
AssemblyLine.variable(ctx, LDA, env.get[Variable](h.name), 0) -> AssemblyLine.variable(ctx, LDA, env.get[Variable](l.name), 0)
|
||||
case _ =>
|
||||
???
|
||||
val (ldaHi, ldaLo) = env.eval(lhs) match {
|
||||
case Some(c) =>
|
||||
List(AssemblyLine.immediate(LDA, c.hiByte)) -> List(AssemblyLine.immediate(LDA, c.loByte))
|
||||
case _ => lhs match {
|
||||
case v: VariableExpression =>
|
||||
val variable = env.get[Variable](v.name)
|
||||
AssemblyLine.variable(ctx, LDA, variable, 1) -> AssemblyLine.variable(ctx, LDA, variable, 0)
|
||||
case SeparateBytesExpression(h: VariableExpression, l: VariableExpression) =>
|
||||
AssemblyLine.variable(ctx, LDA, env.get[Variable](h.name), 0) -> AssemblyLine.variable(ctx, LDA, env.get[Variable](l.name), 0)
|
||||
case _ =>
|
||||
???
|
||||
}
|
||||
}
|
||||
env.eval(rhs) match {
|
||||
case Some(NumericConstant(0, _)) =>
|
||||
@ -394,6 +398,33 @@ object BuiltIns {
|
||||
case BranchIfTrue(l) => compType -> l
|
||||
case BranchIfFalse(l) => ComparisonType.negate(compType) -> l
|
||||
}
|
||||
(env.eval(lhs), env.eval(rhs)) match {
|
||||
case (Some(NumericConstant(lc, _)), Some(NumericConstant(rc, _))) =>
|
||||
return if (effectiveComparisonType match {
|
||||
// TODO: those masks are probably wrong
|
||||
case ComparisonType.Equal =>
|
||||
(lc & 0xff) == (rc & 0xff)
|
||||
case ComparisonType.NotEqual =>
|
||||
(lc & 0xff) != (rc & 0xff)
|
||||
case ComparisonType.LessOrEqualUnsigned =>
|
||||
(lc & 0xff) <= (rc & 0xff)
|
||||
case ComparisonType.GreaterOrEqualUnsigned =>
|
||||
(lc & 0xff) >= (rc & 0xff)
|
||||
case ComparisonType.GreaterUnsigned =>
|
||||
(lc & 0xff) > (rc & 0xff)
|
||||
case ComparisonType.LessUnsigned =>
|
||||
(lc & 0xff) < (rc & 0xff)
|
||||
case ComparisonType.LessOrEqualSigned =>
|
||||
lc.toByte <= rc.toByte
|
||||
case ComparisonType.GreaterOrEqualSigned =>
|
||||
lc.toByte >= rc.toByte
|
||||
case ComparisonType.GreaterSigned =>
|
||||
lc.toByte > rc.toByte
|
||||
case ComparisonType.LessSigned =>
|
||||
lc.toByte < rc.toByte
|
||||
}) List(AssemblyLine.absolute(JMP, Label(label))) else Nil
|
||||
case _ =>
|
||||
}
|
||||
val branchingCompiled = effectiveComparisonType match {
|
||||
case ComparisonType.Equal =>
|
||||
List(AssemblyLine.relative(BEQ, Label(label)))
|
||||
|
@ -777,11 +777,8 @@ object MosExpressionCompiler extends AbstractExpressionCompiler[AssemblyLine] {
|
||||
}
|
||||
case ">>>>" =>
|
||||
val (l, r, 2) = assertArithmeticBinary(ctx, params)
|
||||
l match {
|
||||
case v: LhsExpression =>
|
||||
zeroExtend = true
|
||||
BuiltIns.compileNonetOps(ctx, v, r)
|
||||
}
|
||||
zeroExtend = true
|
||||
BuiltIns.compileNonetOps(ctx, l, r)
|
||||
case "<<" =>
|
||||
val (l, r, size) = assertArithmeticBinary(ctx, params)
|
||||
size match {
|
||||
|
Loading…
Reference in New Issue
Block a user