mirror of
https://github.com/KarolS/millfork.git
synced 2024-12-25 06:29:17 +00:00
Don't emit branching instructions with broken offsets
This commit is contained in:
parent
0355495aff
commit
08544159d4
@ -209,11 +209,14 @@ object StatementCompiler {
|
||||
val largeThenBlock = thenBlock.map(_.sizeInBytes).sum > 100
|
||||
val largeElseBlock = elseBlock.map(_.sizeInBytes).sum > 100
|
||||
condType match {
|
||||
case ConstantBooleanType(_, true) => thenBlock
|
||||
case ConstantBooleanType(_, false) => elseBlock
|
||||
case ConstantBooleanType(_, true) =>
|
||||
ExpressionCompiler.compile(ctx, condition, someRegisterA, NoBranching) ++ thenBlock
|
||||
case ConstantBooleanType(_, false) =>
|
||||
ExpressionCompiler.compile(ctx, condition, someRegisterA, NoBranching) ++ elseBlock
|
||||
case FlagBooleanType(_, jumpIfTrue, jumpIfFalse) =>
|
||||
(thenPart, elsePart) match {
|
||||
case (Nil, Nil) => Nil
|
||||
case (Nil, Nil) =>
|
||||
ExpressionCompiler.compile(ctx, condition, someRegisterA, NoBranching)
|
||||
case (Nil, _) =>
|
||||
val conditionBlock = ExpressionCompiler.compile(ctx, condition, someRegisterA, NoBranching)
|
||||
if (largeElseBlock) {
|
||||
@ -229,36 +232,77 @@ object StatementCompiler {
|
||||
if (largeThenBlock) {
|
||||
val middle = MfCompiler.nextLabel("th")
|
||||
val end = MfCompiler.nextLabel("fi")
|
||||
List(conditionBlock, branchChunk(jumpIfTrue, middle), jmpChunk(end), labelChunk(middle), elseBlock, labelChunk(end)).flatten
|
||||
List(conditionBlock, branchChunk(jumpIfTrue, middle), jmpChunk(end), labelChunk(middle), thenBlock, labelChunk(end)).flatten
|
||||
} else {
|
||||
val end = MfCompiler.nextLabel("fi")
|
||||
List(conditionBlock, branchChunk(jumpIfFalse, end), thenBlock, labelChunk(end)).flatten
|
||||
}
|
||||
case _ =>
|
||||
// TODO: large blocks
|
||||
if (largeElseBlock || largeThenBlock) ErrorReporting.error("Large blocks in if statement", statement.position)
|
||||
val conditionBlock = ExpressionCompiler.compile(ctx, condition, someRegisterA, NoBranching)
|
||||
if (largeThenBlock) {
|
||||
if (largeElseBlock) {
|
||||
val middleT = MfCompiler.nextLabel("th")
|
||||
val middleE = MfCompiler.nextLabel("el")
|
||||
val end = MfCompiler.nextLabel("fi")
|
||||
List(conditionBlock, branchChunk(jumpIfTrue, middleT), jmpChunk(middleE), labelChunk(middleT), thenBlock, jmpChunk(end), labelChunk(middleE), elseBlock, labelChunk(end)).flatten
|
||||
} else {
|
||||
val middle = MfCompiler.nextLabel("th")
|
||||
val end = MfCompiler.nextLabel("fi")
|
||||
List(conditionBlock, branchChunk(jumpIfTrue, middle), elseBlock, jmpChunk(end), labelChunk(middle), thenBlock, labelChunk(end)).flatten
|
||||
}
|
||||
} else {
|
||||
val middle = MfCompiler.nextLabel("el")
|
||||
val end = MfCompiler.nextLabel("fi")
|
||||
val conditionBlock = ExpressionCompiler.compile(ctx, condition, someRegisterA, NoBranching)
|
||||
List(conditionBlock, branchChunk(jumpIfFalse, middle), thenBlock, jmpChunk(end), labelChunk(middle), elseBlock, labelChunk(end)).flatten
|
||||
}
|
||||
}
|
||||
case BuiltInBooleanType =>
|
||||
(thenPart, elsePart) match {
|
||||
case (Nil, Nil) => Nil
|
||||
case (Nil, Nil) =>
|
||||
ExpressionCompiler.compile(ctx, condition, someRegisterA, NoBranching)
|
||||
case (Nil, _) =>
|
||||
if (largeElseBlock) {
|
||||
val middle = MfCompiler.nextLabel("el")
|
||||
val end = MfCompiler.nextLabel("fi")
|
||||
val conditionBlock = ExpressionCompiler.compile(ctx, condition, someRegisterA, BranchIfFalse(middle))
|
||||
List(conditionBlock, jmpChunk(end), labelChunk(middle), elseBlock, labelChunk(end)).flatten
|
||||
} else {
|
||||
val end = MfCompiler.nextLabel("fi")
|
||||
val conditionBlock = ExpressionCompiler.compile(ctx, condition, someRegisterA, BranchIfTrue(end))
|
||||
List(conditionBlock, elseBlock, labelChunk(end)).flatten
|
||||
}
|
||||
case (_, Nil) =>
|
||||
if (largeThenBlock) {
|
||||
val middle = MfCompiler.nextLabel("th")
|
||||
val end = MfCompiler.nextLabel("fi")
|
||||
val conditionBlock = ExpressionCompiler.compile(ctx, condition, someRegisterA, BranchIfTrue(middle))
|
||||
List(conditionBlock, jmpChunk(end), labelChunk(middle), thenBlock, labelChunk(end)).flatten
|
||||
} else {
|
||||
val end = MfCompiler.nextLabel("fi")
|
||||
val conditionBlock = ExpressionCompiler.compile(ctx, condition, someRegisterA, BranchIfFalse(end))
|
||||
List(conditionBlock, thenBlock, labelChunk(end)).flatten
|
||||
}
|
||||
case _ =>
|
||||
if (largeThenBlock) {
|
||||
if (largeElseBlock) {
|
||||
val middleT = MfCompiler.nextLabel("th")
|
||||
val middleE = MfCompiler.nextLabel("el")
|
||||
val end = MfCompiler.nextLabel("fi")
|
||||
val conditionBlock = ExpressionCompiler.compile(ctx, condition, someRegisterA, BranchIfTrue(middleT))
|
||||
List(conditionBlock, jmpChunk(middleE), labelChunk(middleT), thenBlock, jmpChunk(end), labelChunk(middleE), elseBlock, labelChunk(end)).flatten
|
||||
} else {
|
||||
val middle = MfCompiler.nextLabel("th")
|
||||
val end = MfCompiler.nextLabel("fi")
|
||||
val conditionBlock = ExpressionCompiler.compile(ctx, condition, someRegisterA, BranchIfTrue(middle))
|
||||
List(conditionBlock, elseBlock, jmpChunk(end), labelChunk(middle), thenBlock, labelChunk(end)).flatten
|
||||
}
|
||||
} else {
|
||||
val middle = MfCompiler.nextLabel("el")
|
||||
val end = MfCompiler.nextLabel("fi")
|
||||
val conditionBlock = ExpressionCompiler.compile(ctx, condition, someRegisterA, BranchIfFalse(middle))
|
||||
List(conditionBlock, thenBlock, jmpChunk(end), labelChunk(middle), elseBlock, labelChunk(end)).flatten
|
||||
}
|
||||
}
|
||||
case _ =>
|
||||
ErrorReporting.error(s"Illegal type for a condition: `$condType`", condition.position)
|
||||
Nil
|
||||
|
10
src/main/scala/millfork/env/Constant.scala
vendored
10
src/main/scala/millfork/env/Constant.scala
vendored
@ -65,6 +65,16 @@ sealed trait Constant {
|
||||
def isRelatedTo(v: Variable): Boolean
|
||||
}
|
||||
|
||||
case class AssertByte(c: Constant) extends Constant {
|
||||
override def isProvablyZero: Boolean = c.isProvablyZero
|
||||
|
||||
override def requiredSize: Int = 1
|
||||
|
||||
override def isRelatedTo(v: Variable): Boolean = c.isRelatedTo(v)
|
||||
|
||||
override def quickSimplify: Constant = AssertByte(c.quickSimplify)
|
||||
}
|
||||
|
||||
case class UnexpandedConstant(name: String, requiredSize: Int) extends Constant {
|
||||
override def isRelatedTo(v: Variable): Boolean = false
|
||||
}
|
||||
|
@ -68,6 +68,12 @@ class Assembler(private val program: Program, private val rootEnv: Environment,
|
||||
def deepConstResolve(c: Constant): Long = {
|
||||
c match {
|
||||
case NumericConstant(v, _) => v
|
||||
case AssertByte(inner) =>
|
||||
val value = deepConstResolve(inner)
|
||||
if (value.toByte == value) value else {
|
||||
ErrorReporting.error("Invalid relative jump: " + c)
|
||||
-2 // spin
|
||||
}
|
||||
case MemoryAddressConstant(th) =>
|
||||
try {
|
||||
if (labelMap.contains(th.name)) return labelMap(th.name)
|
||||
@ -421,7 +427,7 @@ class Assembler(private val program: Program, private val rootEnv: Environment,
|
||||
index += 1
|
||||
case AssemblyLine(op, Relative, param, _) =>
|
||||
writeByte(bank, index, Assembler.opcodeFor(op, Relative, options))
|
||||
writeByte(bank, index + 1, param - (index + 2))
|
||||
writeByte(bank, index + 1, AssertByte(param - (index + 2)))
|
||||
index += 2
|
||||
case AssemblyLine(op, am@(Immediate | ZeroPage | ZeroPageX | ZeroPageY | IndexedY | IndexedX | IndexedZ | LongIndexedY | LongIndexedZ | Stack), param, _) =>
|
||||
writeByte(bank, index, Assembler.opcodeFor(op, am, options))
|
||||
|
Loading…
Reference in New Issue
Block a user