1
0
mirror of https://github.com/KarolS/millfork.git synced 2024-12-24 15:29:23 +00:00

Multiple improvements:

- fixed some invalid LDX(zp),Y instructions
- better error reporting
- removing unused extern functions
- a new testcase
This commit is contained in:
Karol Stasiak 2018-06-09 00:08:17 +02:00
parent 775707801c
commit 5dc1bba8ed
4 changed files with 27 additions and 7 deletions

View File

@ -695,7 +695,7 @@ object ExpressionCompiler {
case Register.A =>
List(AssemblyLine.indexedY(LDA, reg))
case Register.X =>
List(AssemblyLine.indexedY(LDX, reg))
List(AssemblyLine.indexedY(LDA, reg), AssemblyLine.implied(TAX))
case Register.Y =>
List(AssemblyLine.indexedY(LDA, reg), AssemblyLine.implied(TAY))
}
@ -716,7 +716,7 @@ object ExpressionCompiler {
case Register.Y =>
List(AssemblyLine.immediate(LDY, constantIndex), AssemblyLine.indexedY(LDA, p.addr), AssemblyLine.implied(TAY))
case Register.X =>
List(AssemblyLine.immediate(LDY, constantIndex), AssemblyLine.indexedY(LDX, p.addr))
List(AssemblyLine.immediate(LDY, constantIndex), AssemblyLine.indexedY(LDA, p.addr), AssemblyLine.implied(TAX))
}
case (p:VariablePointy, Some(_), 0 | 1, _) =>
val calculatingIndex = compile(ctx, indexExpr, Some(b, RegisterVariable(Register.Y, b)), NoBranching)
@ -724,7 +724,7 @@ object ExpressionCompiler {
case Register.A =>
calculatingIndex :+ AssemblyLine.indexedY(LDA, p.addr)
case Register.X =>
calculatingIndex :+ AssemblyLine.indexedY(LDX, p.addr)
calculatingIndex ++ List(AssemblyLine.indexedY(LDA, p.addr), AssemblyLine.implied(TAX))
case Register.Y =>
calculatingIndex ++ List(AssemblyLine.indexedY(LDA, p.addr), AssemblyLine.implied(TAY))
}
@ -1270,7 +1270,7 @@ object ExpressionCompiler {
def expressionStorageFromAX(ctx: CompilationContext, exprTypeAndVariable: Option[(Type, Variable)], position: Option[Position]): List[AssemblyLine] = {
exprTypeAndVariable.fold(noop) {
case (VoidType, _) => ???
case (VoidType, _) => ErrorReporting.fatal("Cannot assign word to void", position)
case (_, RegisterVariable(Register.A, _)) => noop
case (_, RegisterVariable(Register.AW, _)) => List(AssemblyLine.implied(XBA), AssemblyLine.implied(TXA), AssemblyLine.implied(XBA))
case (_, RegisterVariable(Register.X, _)) => List(AssemblyLine.implied(TAX))
@ -1421,7 +1421,7 @@ object ExpressionCompiler {
def lookupFunction(ctx: CompilationContext, f: FunctionCallExpression): MangledFunction = {
val paramsWithTypes = f.expressions.map(x => getExpressionType(ctx, x) -> x)
ctx.env.lookupFunction(f.functionName, paramsWithTypes).getOrElse(
ErrorReporting.fatal(s"Cannot find function `${f.functionName}` with given params `${paramsWithTypes.map(_._1)}`", f.position))
ErrorReporting.fatal(s"Cannot find function `${f.functionName}` with given params `${paramsWithTypes.map(_._1).mkString("(", ",", ")")}`", f.position))
}
def arrayBoundsCheck(ctx: CompilationContext, pointy: Pointy, register: Register.Value, index: Expression): List[AssemblyLine] = {

View File

@ -13,7 +13,7 @@ object UnusedFunctions extends NodeOptimization {
override def optimize(nodes: List[Node], options: CompilationOptions): List[Node] = {
val panicRequired = options.flags(CompilationFlag.CheckIndexOutOfBounds)
val allNormalFunctions = nodes.flatMap {
case v: FunctionDeclarationStatement => if (v.address.isDefined || v.interrupt || v.name == "main" || panicRequired && v.name == "_panic") Nil else List(v.name)
case v: FunctionDeclarationStatement => if (v.address.isDefined && v.statements.isDefined || v.interrupt || v.name == "main" || panicRequired && v.name == "_panic") Nil else List(v.name)
case _ => Nil
}.toSet
val allCalledFunctions = getAllCalledFunctions(nodes).toSet

View File

@ -15,7 +15,7 @@ class TextCodec(val name: String, private val map: String, private val extra: Ma
if (index >= 0) {
List(index)
} else {
ErrorReporting.fatal("Invalid character in string")
ErrorReporting.fatal("Invalid character in string", position)
}
}
}

View File

@ -59,6 +59,26 @@ class ByteMathSuite extends FunSuite with Matchers {
""".stripMargin)(_.readByte(0xc001) should equal(42))
}
test("LHS evaluation during in-place byte addition") {
EmuBenchmarkRun(
"""
| array output[1] @$c000
| byte call_count @$c001
| void main () {
| output[0] = 1
| output[identity(0)] += identity(1)
| }
| noinline byte identity(byte a) {
| call_count += 1
| return a
| }
""".stripMargin){m =>
m.readByte(0xc000) should equal(2)
// TODO: currently the compiler emits separate evaluations of the left hand side for reading and writing
// m.readByte(0xc001) should equal(2)
}
}
test("Parameter order") {
EmuBenchmarkRun(
"""