mirror of
https://github.com/KarolS/millfork.git
synced 2025-04-04 22:29:32 +00:00
panic()
This commit is contained in:
parent
309f12cf82
commit
502faa3694
3
examples/c64/panic_test.mfk
Normal file
3
examples/c64/panic_test.mfk
Normal file
@ -0,0 +1,3 @@
|
||||
void main() {
|
||||
panic()
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
[compilation]
|
||||
arch=strict
|
||||
modules=a8_kernel
|
||||
modules=a8_kernel,default_panic
|
||||
|
||||
|
||||
[allocation]
|
||||
|
@ -1,6 +1,6 @@
|
||||
[compilation]
|
||||
arch=nmos
|
||||
modules=c128_hardware,loader_1c01,c128_kernal
|
||||
modules=c128_hardware,loader_1c01,c128_kernal,default_panic
|
||||
|
||||
|
||||
[allocation]
|
||||
|
@ -1,6 +1,6 @@
|
||||
[compilation]
|
||||
arch=nmos
|
||||
modules=loader_1001,c264_kernal,c264_hardware
|
||||
modules=loader_1001,c264_kernal,c264_hardware,default_panic
|
||||
|
||||
|
||||
[allocation]
|
||||
|
@ -5,7 +5,7 @@
|
||||
; CPU architecture: nmos, strictnmos, ricoh, strictricoh, cmos
|
||||
arch=nmos
|
||||
; modules to load
|
||||
modules=c64_hardware,loader_0801,c64_kernal,stdlib
|
||||
modules=c64_hardware,loader_0801,c64_kernal,c64_panic,stdlib
|
||||
; optionally: default flags
|
||||
emit_illegals=true
|
||||
|
||||
|
27
include/c64_panic.mfk
Normal file
27
include/c64_panic.mfk
Normal file
@ -0,0 +1,27 @@
|
||||
void _panic() {
|
||||
asm {
|
||||
SEI
|
||||
PLA // status register
|
||||
PLA
|
||||
TAY
|
||||
PLA
|
||||
|
||||
TAX
|
||||
JSR hi_nibble_to_hex
|
||||
JSR putchar
|
||||
TXA
|
||||
JSR lo_nibble_to_hex
|
||||
JSR putchar
|
||||
|
||||
TYA
|
||||
JSR hi_nibble_to_hex
|
||||
JSR putchar
|
||||
TYA
|
||||
JSR lo_nibble_to_hex
|
||||
JSR putchar
|
||||
|
||||
LDA #2
|
||||
STA $D020
|
||||
}
|
||||
while(true){}
|
||||
}
|
3
include/default_panic.mfk
Normal file
3
include/default_panic.mfk
Normal file
@ -0,0 +1,3 @@
|
||||
void _panic() {
|
||||
while(true){}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
[compilation]
|
||||
arch=nmos
|
||||
modules=loader_0401,pet_kernal
|
||||
modules=loader_0401,pet_kernal,default_panic
|
||||
|
||||
|
||||
[allocation]
|
||||
|
@ -1,6 +1,6 @@
|
||||
[compilation]
|
||||
arch=nmos
|
||||
modules=c264_loader,c264_kernal,c264_hardware
|
||||
modules=c264_loader,c264_kernal,c264_hardware,default_panic
|
||||
|
||||
|
||||
[allocation]
|
||||
|
@ -21,3 +21,25 @@ inline asm void enable_irq() {
|
||||
CLI
|
||||
}
|
||||
|
||||
asm byte hi_nibble_to_hex(byte a) {
|
||||
LSR
|
||||
LSR
|
||||
LSR
|
||||
LSR
|
||||
JMP lo_nibble_to_hex
|
||||
}
|
||||
|
||||
asm byte lo_nibble_to_hex(byte a) {
|
||||
AND #$F
|
||||
CLC
|
||||
ADC #$30
|
||||
CMP #$3A
|
||||
BCC _lo_nibble_to_hex_lbl
|
||||
ADC #$6 // carry is set
|
||||
_lo_nibble_to_hex_lbl:
|
||||
RTS
|
||||
}
|
||||
|
||||
inline asm void panic() {
|
||||
JSR _panic
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
[compilation]
|
||||
arch=nmos
|
||||
modules=loader_1001,vic20_kernal
|
||||
modules=loader_1001,vic20_kernal,default_panic
|
||||
|
||||
|
||||
[allocation]
|
||||
|
@ -1,6 +1,6 @@
|
||||
[compilation]
|
||||
arch=nmos
|
||||
modules=loader_0401,vic20_kernal
|
||||
modules=loader_0401,vic20_kernal,default_panic
|
||||
|
||||
|
||||
[allocation]
|
||||
|
@ -1,6 +1,6 @@
|
||||
[compilation]
|
||||
arch=nmos
|
||||
modules=loader_1201,vic20_kernal
|
||||
modules=loader_1201,vic20_kernal,default_panic
|
||||
|
||||
|
||||
[allocation]
|
||||
|
@ -78,6 +78,8 @@ object CompilationFlag extends Enumeration {
|
||||
DetailedFlowAnalysis, DangerousOptimizations, InlineFunctions,
|
||||
// memory allocation options
|
||||
VariableOverlap,
|
||||
// runtime check options
|
||||
CheckIndexOutOfBounds,
|
||||
// warning options
|
||||
ExtraComparisonWarnings,
|
||||
RorWarning,
|
||||
|
@ -77,7 +77,7 @@ object Main {
|
||||
options = options).run()
|
||||
|
||||
val program = if (optLevel > 0) {
|
||||
OptimizationPresets.NodeOpt.foldLeft(unoptimized)((p, opt) => p.applyNodeOptimization(opt))
|
||||
OptimizationPresets.NodeOpt.foldLeft(unoptimized)((p, opt) => p.applyNodeOptimization(opt, options))
|
||||
} else {
|
||||
unoptimized
|
||||
}
|
||||
@ -191,10 +191,13 @@ object Main {
|
||||
}.description("Whether should prevent indirect JMP bug on page boundary.")
|
||||
boolean("-fdecimal-mode", "-fno-decimal-mode").action { (c, v) =>
|
||||
c.changeFlag(CompilationFlag.DecimalMode, v)
|
||||
}.description("Whether should decimal mode be available.")
|
||||
}.description("Whether decimal mode should be available.")
|
||||
boolean("-fvariable-overlap", "-fno-variable-overlap").action { (c, v) =>
|
||||
c.changeFlag(CompilationFlag.VariableOverlap, v)
|
||||
}.description("Whether should variables overlap if their scopes do not intersect.")
|
||||
}.description("Whether variables should overlap if their scopes do not intersect.")
|
||||
boolean("-fbounds-checking", "-fno-bounds-checking").action { (c, v) =>
|
||||
c.changeFlag(CompilationFlag.VariableOverlap, v)
|
||||
}.description("Whether should insert bounds checking on array access.")
|
||||
|
||||
fluff("", "Optimization options:", "")
|
||||
|
||||
|
@ -1,11 +1,12 @@
|
||||
package millfork.node
|
||||
|
||||
import millfork.CompilationOptions
|
||||
import millfork.node.opt.NodeOptimization
|
||||
|
||||
/**
|
||||
* @author Karol Stasiak
|
||||
*/
|
||||
case class Program(declarations: List[DeclarationStatement]) {
|
||||
def applyNodeOptimization(o: NodeOptimization) = Program(o.optimize(declarations).asInstanceOf[List[DeclarationStatement]])
|
||||
def applyNodeOptimization(o: NodeOptimization, options: CompilationOptions) = Program(o.optimize(declarations, options).asInstanceOf[List[DeclarationStatement]])
|
||||
def +(p:Program): Program = Program(this.declarations ++ p.declarations)
|
||||
}
|
||||
|
@ -1,16 +1,17 @@
|
||||
package millfork.node.opt
|
||||
|
||||
import millfork.CompilationOptions
|
||||
import millfork.node.{ExecutableStatement, Expression, Node, Statement}
|
||||
|
||||
/**
|
||||
* @author Karol Stasiak
|
||||
*/
|
||||
trait NodeOptimization {
|
||||
def optimize(nodes: List[Node]): List[Node]
|
||||
def optimize(nodes: List[Node], options: CompilationOptions): List[Node]
|
||||
|
||||
def optimizeExecutableStatements(nodes: List[ExecutableStatement]): List[ExecutableStatement] =
|
||||
optimize(nodes).asInstanceOf[List[ExecutableStatement]]
|
||||
def optimizeExecutableStatements(nodes: List[ExecutableStatement], options: CompilationOptions): List[ExecutableStatement] =
|
||||
optimize(nodes, options).asInstanceOf[List[ExecutableStatement]]
|
||||
|
||||
def optimizeStatements(nodes: List[Statement]): List[Statement] =
|
||||
optimize(nodes).asInstanceOf[List[Statement]]
|
||||
def optimizeStatements(nodes: List[Statement], options: CompilationOptions): List[Statement] =
|
||||
optimize(nodes, options).asInstanceOf[List[Statement]]
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package millfork.node.opt
|
||||
|
||||
import millfork.CompilationOptions
|
||||
import millfork.node._
|
||||
|
||||
/**
|
||||
@ -7,21 +8,21 @@ import millfork.node._
|
||||
*/
|
||||
object UnreachableCode extends NodeOptimization {
|
||||
|
||||
override def optimize(nodes: List[Node]): List[Node] = nodes match {
|
||||
override def optimize(nodes: List[Node], options: CompilationOptions): List[Node] = nodes match {
|
||||
case (x:FunctionDeclarationStatement)::xs =>
|
||||
x.copy(statements = x.statements.map(optimizeStatements)) :: optimize(xs)
|
||||
x.copy(statements = x.statements.map(optimizeStatements(_, options))) :: optimize(xs, options)
|
||||
case (x:IfStatement)::xs =>
|
||||
x.copy(
|
||||
thenBranch = optimizeExecutableStatements(x.thenBranch),
|
||||
elseBranch = optimizeExecutableStatements(x.elseBranch)) :: optimize(xs)
|
||||
thenBranch = optimizeExecutableStatements(x.thenBranch, options),
|
||||
elseBranch = optimizeExecutableStatements(x.elseBranch, options)) :: optimize(xs, options)
|
||||
case (x:WhileStatement)::xs =>
|
||||
x.copy(body = optimizeExecutableStatements(x.body)) :: optimize(xs)
|
||||
x.copy(body = optimizeExecutableStatements(x.body, options)) :: optimize(xs, options)
|
||||
case (x:DoWhileStatement)::xs =>
|
||||
x.copy(body = optimizeExecutableStatements(x.body)) :: optimize(xs)
|
||||
x.copy(body = optimizeExecutableStatements(x.body, options)) :: optimize(xs, options)
|
||||
case (x:ReturnStatement) :: xs =>
|
||||
x :: Nil
|
||||
case x :: xs =>
|
||||
x :: optimize(xs)
|
||||
x :: optimize(xs, options)
|
||||
case Nil =>
|
||||
Nil
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package millfork.node.opt
|
||||
|
||||
import millfork.{CompilationFlag, CompilationOptions}
|
||||
import millfork.env._
|
||||
import millfork.error.ErrorReporting
|
||||
import millfork.node._
|
||||
@ -9,25 +10,28 @@ import millfork.node._
|
||||
*/
|
||||
object UnusedFunctions extends NodeOptimization {
|
||||
|
||||
override def optimize(nodes: List[Node]): List[Node] = {
|
||||
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") Nil else List(v.name)
|
||||
case v: FunctionDeclarationStatement => if (v.address.isDefined || v.interrupt || v.name == "main" || panicRequired && v.name == "_panic") Nil else List(v.name)
|
||||
case _ => Nil
|
||||
}.toSet
|
||||
val allCalledFunctions = getAllCalledFunctions(nodes).toSet
|
||||
val unusedFunctions = allNormalFunctions -- allCalledFunctions
|
||||
if (unusedFunctions.nonEmpty) {
|
||||
ErrorReporting.debug("Removing unused functions: " + unusedFunctions.mkString(", "))
|
||||
optimize(removeFunctionsFromProgram(nodes, unusedFunctions), options)
|
||||
} else {
|
||||
nodes
|
||||
}
|
||||
removeFunctionsFromProgram(nodes, unusedFunctions)
|
||||
}
|
||||
|
||||
private def removeFunctionsFromProgram(nodes: List[Node], unusedVariables: Set[String]): List[Node] = {
|
||||
private def removeFunctionsFromProgram(nodes: List[Node], unusedFunctions: Set[String]): List[Node] = {
|
||||
nodes match {
|
||||
case (x: FunctionDeclarationStatement) :: xs if unusedVariables(x.name) =>
|
||||
removeFunctionsFromProgram(xs, unusedVariables)
|
||||
case (x: FunctionDeclarationStatement) :: xs if unusedFunctions(x.name) =>
|
||||
removeFunctionsFromProgram(xs, unusedFunctions)
|
||||
case x :: xs =>
|
||||
x :: removeFunctionsFromProgram(xs, unusedVariables)
|
||||
x :: removeFunctionsFromProgram(xs, unusedFunctions)
|
||||
case Nil =>
|
||||
Nil
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package millfork.node.opt
|
||||
|
||||
import millfork.CompilationOptions
|
||||
import millfork.env._
|
||||
import millfork.error.ErrorReporting
|
||||
import millfork.node._
|
||||
@ -9,7 +10,7 @@ import millfork.node._
|
||||
*/
|
||||
object UnusedGlobalVariables extends NodeOptimization {
|
||||
|
||||
override def optimize(nodes: List[Node]): List[Node] = {
|
||||
override def optimize(nodes: List[Node], options: CompilationOptions): List[Node] = {
|
||||
|
||||
// TODO: volatile
|
||||
val allNonvolatileGlobalVariables = nodes.flatMap {
|
||||
|
@ -1,5 +1,6 @@
|
||||
package millfork.node.opt
|
||||
|
||||
import millfork.CompilationOptions
|
||||
import millfork.assembly.AssemblyLine
|
||||
import millfork.env._
|
||||
import millfork.error.ErrorReporting
|
||||
@ -10,11 +11,11 @@ import millfork.node._
|
||||
*/
|
||||
object UnusedLocalVariables extends NodeOptimization {
|
||||
|
||||
override def optimize(nodes: List[Node]): List[Node] = nodes match {
|
||||
override def optimize(nodes: List[Node], options: CompilationOptions): List[Node] = nodes match {
|
||||
case (x: FunctionDeclarationStatement) :: xs =>
|
||||
x.copy(statements = x.statements.map(optimizeVariables)) :: optimize(xs)
|
||||
x.copy(statements = x.statements.map(optimizeVariables)) :: optimize(xs, options)
|
||||
case x :: xs =>
|
||||
x :: optimize(xs)
|
||||
x :: optimize(xs, options)
|
||||
case Nil =>
|
||||
Nil
|
||||
}
|
||||
|
@ -94,17 +94,18 @@ class EmuRun(cpu: millfork.Cpu.Value, nodeOptimizations: List[NodeOptimization],
|
||||
CompilationFlag.EmitIllegals -> this.emitIllegals,
|
||||
CompilationFlag.DetailedFlowAnalysis -> quantum,
|
||||
CompilationFlag.InlineFunctions -> this.inline,
|
||||
// CompilationFlag.CheckIndexOutOfBounds -> true,
|
||||
))
|
||||
ErrorReporting.hasErrors = false
|
||||
ErrorReporting.verbosity = 999
|
||||
val parserF = MfParser("", source, "", options)
|
||||
val parserF = MfParser("", source + "\n void _panic(){while(true){}}", "", options)
|
||||
parserF.toAst match {
|
||||
case Success(unoptimized, _) =>
|
||||
ErrorReporting.assertNoErrors("Parse failed")
|
||||
|
||||
|
||||
// prepare
|
||||
val program = nodeOptimizations.foldLeft(unoptimized)((p, opt) => p.applyNodeOptimization(opt))
|
||||
val program = nodeOptimizations.foldLeft(unoptimized)((p, opt) => p.applyNodeOptimization(opt, options))
|
||||
val callGraph = new StandardCallGraph(program)
|
||||
val env = new Environment(None, "")
|
||||
env.collectDeclarations(program, options)
|
||||
|
Loading…
x
Reference in New Issue
Block a user