mirror of
https://github.com/KarolS/millfork.git
synced 2025-04-11 08:37:00 +00:00
Put almost all warnings behind internal flags
This commit is contained in:
parent
7939b0f2c1
commit
2eb8ef53ca
@ -409,7 +409,7 @@ object Cpu extends Enumeration {
|
||||
|
||||
private val alwaysDefaultFlags = Set(
|
||||
VariableOverlap, CompactReturnDispatchParams, FunctionFallthrough, RegisterVariables, FunctionDeduplication, EnableBreakpoints,
|
||||
NonZeroTerminatedLiteralWarning, CallToOverlappingBankWarning,
|
||||
GenericWarnings, UselessCodeWarning, BuggyCodeWarning, FallbackValueUseWarning, DeprecationWarning, NonZeroTerminatedLiteralWarning, CallToOverlappingBankWarning,
|
||||
)
|
||||
|
||||
private val mosAlwaysDefaultFlags = alwaysDefaultFlags
|
||||
@ -562,6 +562,11 @@ object CompilationFlag extends Enumeration {
|
||||
// special options
|
||||
SingleThreaded,
|
||||
// warning options
|
||||
GenericWarnings,
|
||||
UselessCodeWarning,
|
||||
BuggyCodeWarning,
|
||||
DeprecationWarning,
|
||||
FallbackValueUseWarning,
|
||||
ExtraComparisonWarnings,
|
||||
RorWarning,
|
||||
NonZeroTerminatedLiteralWarning,
|
||||
@ -571,7 +576,7 @@ object CompilationFlag extends Enumeration {
|
||||
EnableInternalTestSyntax,
|
||||
InternalCurrentlyOptimizingForMeasurement = Value
|
||||
|
||||
val allWarnings: Set[CompilationFlag.Value] = Set(ExtraComparisonWarnings)
|
||||
val allWarnings: Set[CompilationFlag.Value] = Set(GenericWarnings, UselessCodeWarning, BuggyCodeWarning, DeprecationWarning, FallbackValueUseWarning, ExtraComparisonWarnings, NonZeroTerminatedLiteralWarning, CallToOverlappingBankWarning)
|
||||
|
||||
val fromString: Map[String, CompilationFlag.Value] = Map(
|
||||
"lunix" -> LUnixRelocatableCode,
|
||||
|
@ -67,7 +67,7 @@ object CoarseFlowAnalyzer {
|
||||
var staSpIsNow = false
|
||||
codeArray(i) match {
|
||||
case AssemblyLine0(LABEL, _, MemoryAddressConstant(Label(l))) =>
|
||||
if (tFlag) {
|
||||
if (tFlag && optimizationContext.options.flag(CompilationFlag.BuggyCodeWarning)) {
|
||||
// T flag should not be set at a label!
|
||||
optimizationContext.log.warn("The SET instruction shouldn't occur before a label")
|
||||
}
|
||||
@ -177,7 +177,7 @@ object CoarseFlowAnalyzer {
|
||||
if (OpcodeClasses.ChangesStack(opcode) || OpcodeClasses.ChangesS(opcode)) currentStatus = currentStatus.copy(eqSX = false)
|
||||
}
|
||||
staSpWasLast = staSpIsNow
|
||||
if (tFlag) {
|
||||
if (tFlag && optimizationContext.options.flag(CompilationFlag.BuggyCodeWarning)) {
|
||||
if (OpcodeClasses.ShortBranching(codeArray(i).opcode) || codeArray(i).opcode == JMP || codeArray(i).opcode == JSR) {
|
||||
// T flag should not be set at a jump!
|
||||
optimizationContext.log.warn("The SET instruction shouldn't occur before a jump")
|
||||
|
@ -49,7 +49,7 @@ abstract class AbstractReturnDispatch[T <: AbstractCode] {
|
||||
if (indexerType.size != 1) {
|
||||
ctx.log.error("Return dispatch index expression type has to be a byte", stmt.indexer.position)
|
||||
}
|
||||
if (indexerType.isSigned) {
|
||||
if (indexerType.isSigned && ctx.options.flag(CompilationFlag.BuggyCodeWarning)) {
|
||||
ctx.log.warn("Return dispatch index expression type will be automatically casted to unsigned", stmt.indexer.position)
|
||||
}
|
||||
stmt.params.foreach {
|
||||
@ -81,7 +81,7 @@ abstract class AbstractReturnDispatch[T <: AbstractCode] {
|
||||
}
|
||||
val function: String = ctx.env.evalForAsm(branch.function) match {
|
||||
case Some(MemoryAddressConstant(f: FunctionInMemory)) =>
|
||||
if (f.returnType.name != returnType.name) {
|
||||
if (f.returnType.name != returnType.name && ctx.options.flag(CompilationFlag.BuggyCodeWarning)) {
|
||||
ctx.log.warn(s"Dispatching to a function of different return type: dispatcher return type: ${returnType.name}, dispatchee return type: ${f.returnType.name}", branch.function.position)
|
||||
}
|
||||
f.name
|
||||
|
@ -369,7 +369,7 @@ abstract class AbstractStatementCompiler[T <: AbstractCode] {
|
||||
)
|
||||
)._1 ++ callChunk(Label(callLabel)))
|
||||
return calls -> (labelChunk(callLabel) ++ extractedBody ++ extra ++ extra2)
|
||||
} else {
|
||||
} else if (ctx.options.flag(CompilationFlag.FallbackValueUseWarning)) {
|
||||
ctx.log.warn("For loop too complex to extract, inlining", f.position)
|
||||
}
|
||||
}
|
||||
|
@ -100,12 +100,30 @@ abstract class AbstractStatementPreprocessor(protected val ctx: CompilationConte
|
||||
// generic warnings:
|
||||
stmt match {
|
||||
case ExpressionStatement(expr@FunctionCallExpression("strzlen" | "putstrz" | "strzcmp" | "strzcopy", params)) =>
|
||||
for (param <- params) checkIfNullTerminated(stmt, param)
|
||||
for (param <- params) checkIfNullTerminated(ctx, stmt, param)
|
||||
|
||||
case ExpressionStatement(expr@FunctionCallExpression(f, List(VariableExpression(v)))) if hiddenEffectFreeFunctions(f)=>
|
||||
val volatile = ctx.env.maybeGet[ThingInMemory](v).fold(false)(_.isVolatile)
|
||||
if (!volatile && ctx.options.flag(CompilationFlag.UselessCodeWarning)) {
|
||||
ctx.log.warn("Pointless expression.", stmt.position)
|
||||
}
|
||||
|
||||
case ExpressionStatement(expr@FunctionCallExpression(f, List(_: LiteralExpression))) if hiddenEffectFreeFunctions(f) =>
|
||||
if (ctx.options.flag(CompilationFlag.UselessCodeWarning)) {
|
||||
ctx.log.warn("Pointless expression.", stmt.position)
|
||||
}
|
||||
|
||||
case ExpressionStatement(VariableExpression(v)) =>
|
||||
val volatile = ctx.env.maybeGet[ThingInMemory](v).fold(false)(_.isVolatile)
|
||||
if (!volatile) ctx.log.warn("Pointless expression.", stmt.position)
|
||||
case ExpressionStatement(LiteralExpression(_, _)) =>
|
||||
ctx.log.warn("Pointless expression.", stmt.position)
|
||||
if (!volatile && ctx.options.flag(CompilationFlag.UselessCodeWarning)) {
|
||||
ctx.log.warn("Pointless expression.", stmt.position)
|
||||
}
|
||||
|
||||
case ExpressionStatement(_: LiteralExpression) =>
|
||||
if (ctx.options.flag(CompilationFlag.UselessCodeWarning)) {
|
||||
ctx.log.warn("Pointless expression.", stmt.position)
|
||||
}
|
||||
|
||||
case _ =>
|
||||
}
|
||||
stmt match {
|
||||
@ -253,11 +271,13 @@ abstract class AbstractStatementPreprocessor(protected val ctx: CompilationConte
|
||||
}
|
||||
}
|
||||
|
||||
private def checkIfNullTerminated(stmt: ExecutableStatement, param: Expression): Unit = {
|
||||
private def checkIfNullTerminated(ctx: CompilationContext, stmt: ExecutableStatement, param: Expression): Unit = {
|
||||
if (!ctx.options.flag(CompilationFlag.BuggyCodeWarning)) return
|
||||
val TERMINATOR = ctx.options.platform.defaultCodec.stringTerminator.head
|
||||
param match {
|
||||
case TextLiteralExpression(ch) =>
|
||||
ch.last match {
|
||||
case LiteralExpression(0, _) => //ok
|
||||
case LiteralExpression(TERMINATOR, _) => //ok
|
||||
case _ => ctx.log.warn("Passing a non-null-terminated string to a function that expects a null-terminated string.", stmt.position)
|
||||
}
|
||||
case _ =>
|
||||
@ -327,17 +347,17 @@ abstract class AbstractStatementPreprocessor(protected val ctx: CompilationConte
|
||||
// generic warnings:
|
||||
expr match {
|
||||
case FunctionCallExpression("*" | "*=", params) =>
|
||||
if (params.exists {
|
||||
if (ctx.options.flag(CompilationFlag.UselessCodeWarning) && params.exists {
|
||||
case LiteralExpression(0, _) => true
|
||||
case _ => false
|
||||
}) ctx.log.warn("Multiplication by zero.", params.head.position)
|
||||
case FunctionCallExpression("/" | "/=" | "%%" | "%%=", params) =>
|
||||
if (params.tail.exists {
|
||||
if (ctx.options.flag(CompilationFlag.BuggyCodeWarning) && params.tail.exists {
|
||||
case LiteralExpression(0, _) => true
|
||||
case _ => false
|
||||
}) ctx.log.warn("Division by zero.", params.head.position)
|
||||
case FunctionCallExpression("<<" | ">>" | "<<'" | "<<=" | ">>=" | "<<'=" | ">>>>", List(lhs@_, LiteralExpression(0, _))) =>
|
||||
ctx.log.warn("Shift by zero.", lhs.position)
|
||||
if (ctx.options.flag(CompilationFlag.UselessCodeWarning)) ctx.log.warn("Shift by zero.", lhs.position)
|
||||
case _ =>
|
||||
}
|
||||
expr match {
|
||||
|
@ -1,5 +1,6 @@
|
||||
package millfork.compiler.m6809
|
||||
|
||||
import millfork.CompilationFlag
|
||||
import millfork.assembly.m6809.{DAccumulatorIndexed, Immediate, Indexed, InherentB, MLine, MLine0, MOpcode, RegisterSet, TwoRegisters}
|
||||
import millfork.compiler.{AbstractExpressionCompiler, BranchIfFalse, BranchIfTrue, BranchSpec, ComparisonType, CompilationContext, NoBranching}
|
||||
import millfork.node.{DerefExpression, Expression, FunctionCallExpression, GeneratedConstantExpression, IndexedExpression, LhsExpression, LiteralExpression, M6809Register, SumExpression, VariableExpression}
|
||||
@ -706,7 +707,9 @@ object M6809ExpressionCompiler extends AbstractExpressionCompiler[MLine] {
|
||||
case IndexedExpression(_, GeneratedConstantExpression(_, _)) =>
|
||||
case IndexedExpression(_, SumExpression(sumParams, false)) if isUpToOneVar(sumParams) =>
|
||||
case _ =>
|
||||
ctx.log.warn("A complex expression may be evaluated multiple times", e.position)
|
||||
if (ctx.options.flag(CompilationFlag.BuggyCodeWarning)) {
|
||||
ctx.log.warn("A complex expression may be evaluated multiple times", e.position)
|
||||
}
|
||||
}
|
||||
}
|
||||
val conjunction = params.init.zip(params.tail).map {
|
||||
|
@ -484,7 +484,7 @@ object BuiltIns {
|
||||
}
|
||||
val firstParamCompiled = MosExpressionCompiler.compile(ctx, lhs, Some(b -> RegisterVariable(MosRegister.A, b)), NoBranching)
|
||||
val maybeConstant = env.eval(rhs)
|
||||
maybeConstant match {
|
||||
if (ctx.options.flag(CompilationFlag.UselessCodeWarning)) maybeConstant match {
|
||||
case Some(NumericConstant(0, _)) =>
|
||||
compType match {
|
||||
case ComparisonType.LessUnsigned =>
|
||||
|
@ -1308,7 +1308,7 @@ object MosExpressionCompiler extends AbstractExpressionCompiler[AssemblyLine] {
|
||||
}
|
||||
case None =>
|
||||
assertAllArithmeticBytes("Nonet argument has to be a byte", ctx, params)
|
||||
params.head match {
|
||||
if (ctx.options.flag(CompilationFlag.BuggyCodeWarning)) params.head match {
|
||||
case SumExpression(addends, _) =>
|
||||
if (addends.exists(a => a._1)) {
|
||||
ctx.log.warn("Nonet subtraction may not work as expected", expr.position)
|
||||
@ -1734,7 +1734,7 @@ object MosExpressionCompiler extends AbstractExpressionCompiler[AssemblyLine] {
|
||||
if (nf.name == "main" && ctx.options.flag(CompilationFlag.SoftwareStack)) {
|
||||
if (nf.stackVariablesSize != 0 || env.things.values.exists(_.isInstanceOf[StackVariable])) {
|
||||
ctx.log.error("Calling the main function when using software stack is not allowed", expr.position)
|
||||
} else {
|
||||
} else if (ctx.options.flag(CompilationFlag.BuggyCodeWarning)) {
|
||||
ctx.log.warn("Calling the main function when using software stack is not allowed", expr.position)
|
||||
}
|
||||
}
|
||||
@ -1758,7 +1758,9 @@ object MosExpressionCompiler extends AbstractExpressionCompiler[AssemblyLine] {
|
||||
case Seq((MosRegister.A, pa), (_, pxy)) => pa ++ preserveRegisterIfNeeded(ctx, MosRegister.A, pxy)
|
||||
case Seq((_, pxy), (MosRegister.A, pa)) => pa ++ preserveRegisterIfNeeded(ctx, MosRegister.A, pxy)
|
||||
case other =>
|
||||
ctx.log.warn("Unsupported register parameter combination: " + other.map(_._1.toString).mkString("(", ",", ")"), expr.position)
|
||||
if (ctx.options.flag(CompilationFlag.BuggyCodeWarning)) {
|
||||
ctx.log.warn("Unsupported register parameter combination: " + other.map(_._1.toString).mkString("(", ",", ")"), expr.position)
|
||||
}
|
||||
other.flatMap(_._2) // TODO : make sure all registers are passed in correctly
|
||||
}
|
||||
secondViaMemory ++ thirdViaRegisters :+ AssemblyLine.absoluteOrLongAbsolute(JSR, function, ctx.options)
|
||||
@ -1811,7 +1813,7 @@ object MosExpressionCompiler extends AbstractExpressionCompiler[AssemblyLine] {
|
||||
case IndexedExpression(_, GeneratedConstantExpression(_, _)) =>
|
||||
case IndexedExpression(_, SumExpression(ps, false)) if isUpToOneVar(ps) =>
|
||||
case _ =>
|
||||
ctx.log.warn("A complex expression may be evaluated multiple times", e.position)
|
||||
if (ctx.options.flag(CompilationFlag.BuggyCodeWarning)) ctx.log.warn("A complex expression may be evaluated multiple times", e.position)
|
||||
}
|
||||
}
|
||||
val conjunction = params.init.zip(params.tail).map {
|
||||
|
@ -202,7 +202,9 @@ object MosStatementCompiler extends AbstractStatementCompiler[AssemblyLine] {
|
||||
case ExpressionStatement(e) =>
|
||||
e match {
|
||||
case VariableExpression(_) | LiteralExpression(_, _) | _:GeneratedConstantExpression =>
|
||||
ctx.log.warn("Pointless expression statement", statement.position)
|
||||
if (ctx.options.flag(CompilationFlag.UselessCodeWarning)) {
|
||||
ctx.log.warn("Pointless expression statement", statement.position)
|
||||
}
|
||||
case _ =>
|
||||
}
|
||||
MosExpressionCompiler.compile(ctx, e, None, NoBranching) -> Nil
|
||||
@ -217,19 +219,19 @@ object MosStatementCompiler extends AbstractStatementCompiler[AssemblyLine] {
|
||||
stackPointerFixBeforeReturn(ctx) ++
|
||||
List(AssemblyLine.discardAF(), AssemblyLine.discardXF(), AssemblyLine.discardYF()) ++ returnInstructions
|
||||
case 1 =>
|
||||
if (statement.position.isDefined){
|
||||
if (statement.position.isDefined && ctx.options.flag(CompilationFlag.BuggyCodeWarning)){
|
||||
ctx.log.warn("Returning without a value", statement.position)
|
||||
}
|
||||
stackPointerFixBeforeReturn(ctx) ++
|
||||
List(AssemblyLine.discardXF(), AssemblyLine.discardYF()) ++ returnInstructions
|
||||
case 2 =>
|
||||
if (statement.position.isDefined){
|
||||
if (statement.position.isDefined && ctx.options.flag(CompilationFlag.BuggyCodeWarning)){
|
||||
ctx.log.warn("Returning without a value", statement.position)
|
||||
}
|
||||
stackPointerFixBeforeReturn(ctx) ++
|
||||
List(AssemblyLine.discardYF()) ++ returnInstructions
|
||||
case _ =>
|
||||
if (statement.position.isDefined){
|
||||
if (statement.position.isDefined && ctx.options.flag(CompilationFlag.BuggyCodeWarning)){
|
||||
ctx.log.warn("Returning without a value", statement.position)
|
||||
}
|
||||
stackPointerFixBeforeReturn(ctx) ++
|
||||
|
@ -223,7 +223,9 @@ object Z80ExpressionCompiler extends AbstractExpressionCompiler[ZLine] {
|
||||
xs => ldhl.copy(parameter = param + 2) :: addhlsp :: fixTsx(ctx, xs)
|
||||
case (x@ZLine0(EX_SP, _, _)) :: xs =>
|
||||
// EX_SP should be only generated by the optimizer
|
||||
ctx.log.warn("Stray EX (SP) encountered, generated code might be invalid")
|
||||
if (ctx.options.flag(CompilationFlag.BuggyCodeWarning)) {
|
||||
ctx.log.warn("Stray EX (SP) encountered, generated code might be invalid")
|
||||
}
|
||||
x :: fixTsx(ctx, xs)
|
||||
case x :: xs => x :: fixTsx(ctx, xs)
|
||||
case Nil => Nil
|
||||
@ -1288,7 +1290,9 @@ object Z80ExpressionCompiler extends AbstractExpressionCompiler[ZLine] {
|
||||
case Seq((ZRegister.BC, pbc), (_, pxx)) => pbc ++ stashBCIfChanged(ctx, pxx)
|
||||
case Seq((_, pxx), (ZRegister.BC, pbc)) => pbc ++ stashBCIfChanged(ctx, pxx)
|
||||
case other =>
|
||||
ctx.log.warn("Unsupported register parameter combination: " + other.map(_._1.toString).mkString("(", ",", ")"), expression.position)
|
||||
if (ctx.options.flag(CompilationFlag.BuggyCodeWarning)) {
|
||||
ctx.log.warn("Unsupported register parameter combination: " + other.map(_._1.toString).mkString("(", ",", ")"), expression.position)
|
||||
}
|
||||
other.flatMap(_._2) // TODO : make sure all registers are passed in correctly
|
||||
}
|
||||
viaMemory ++ viaRegisters :+ ZLine(CALL, NoRegisters, function.toAddress)
|
||||
@ -2098,7 +2102,9 @@ object Z80ExpressionCompiler extends AbstractExpressionCompiler[ZLine] {
|
||||
case IndexedExpression(_, GeneratedConstantExpression(_, _)) =>
|
||||
case IndexedExpression(_, SumExpression(sumParams, false)) if isUpToOneVar(sumParams) =>
|
||||
case _ =>
|
||||
ctx.log.warn("A complex expression may be evaluated multiple times", e.position)
|
||||
if (ctx.options.flag(CompilationFlag.BuggyCodeWarning)) {
|
||||
ctx.log.warn("A complex expression may be evaluated multiple times", e.position)
|
||||
}
|
||||
}
|
||||
}
|
||||
val conjunction = params.init.zip(params.tail).map {
|
||||
|
16
src/main/scala/millfork/env/Environment.scala
vendored
16
src/main/scala/millfork/env/Environment.scala
vendored
@ -182,7 +182,7 @@ class Environment(val parent: Option[Environment], val prefix: String, val cpuFa
|
||||
)
|
||||
} else Nil
|
||||
case VariableAllocationMethod.Auto | VariableAllocationMethod.Register | VariableAllocationMethod.Static =>
|
||||
if (m.alloc == VariableAllocationMethod.Register) {
|
||||
if (m.alloc == VariableAllocationMethod.Register && options.flag(CompilationFlag.FallbackValueUseWarning)) {
|
||||
log.warn(s"Failed to inline variable `${m.name}` into a register", None)
|
||||
}
|
||||
if (m.sizeInBytes == 0) Nil else {
|
||||
@ -316,7 +316,7 @@ class Environment(val parent: Option[Environment], val prefix: String, val cpuFa
|
||||
} else {
|
||||
t match {
|
||||
case Alias(_, target, deprectated) =>
|
||||
if (deprectated) {
|
||||
if (deprectated && options.flag(CompilationFlag.DeprecationWarning)) {
|
||||
log.warn(s"Alias `$name` is deprecated, use `$target` instead", position)
|
||||
}
|
||||
root.get[T](target)
|
||||
@ -344,7 +344,7 @@ class Environment(val parent: Option[Environment], val prefix: String, val cpuFa
|
||||
val clazz = implicitly[Manifest[T]].runtimeClass
|
||||
t match {
|
||||
case Alias(_, target, deprectated) =>
|
||||
if (deprectated) {
|
||||
if (deprectated && options.flag(CompilationFlag.DeprecationWarning)) {
|
||||
log.warn(s"Alias `$name` is deprecated, use `$target` instead")
|
||||
}
|
||||
root.maybeGet[T](target)
|
||||
@ -1068,10 +1068,10 @@ class Environment(val parent: Option[Environment], val prefix: String, val cpuFa
|
||||
val name = stmt.name
|
||||
val resultType = get[Type](stmt.resultType)
|
||||
if (stmt.name == "main") {
|
||||
if (stmt.resultType != "void") {
|
||||
if (stmt.resultType != "void" && options.flag(CompilationFlag.UselessCodeWarning)) {
|
||||
log.warn("`main` should return `void`.", stmt.position)
|
||||
}
|
||||
if (stmt.params.nonEmpty) {
|
||||
if (stmt.params.nonEmpty && options.flag(CompilationFlag.BuggyCodeWarning)) {
|
||||
log.warn("`main` shouldn't have parameters.", stmt.position)
|
||||
}
|
||||
}
|
||||
@ -1186,7 +1186,7 @@ class Environment(val parent: Option[Environment], val prefix: String, val cpuFa
|
||||
val g = getAllSafeGotos(statements).toSet
|
||||
val bad = g.&(env.knownLocalLabels.map(_._1)).--(l)
|
||||
if (bad.nonEmpty) {
|
||||
log.warn("Detected cross-loop gotos to labels " + bad.mkString(", "), position)
|
||||
if (options.flag(CompilationFlag.BuggyCodeWarning)) log.warn("Detected cross-loop gotos to labels " + bad.mkString(", "), position)
|
||||
}
|
||||
}
|
||||
def recurse(statements: Seq[Statement]):Unit = statements.foreach {
|
||||
@ -1769,7 +1769,7 @@ class Environment(val parent: Option[Environment], val prefix: String, val cpuFa
|
||||
if (stmt.initialValue.isDefined && stmt.address.isDefined) {
|
||||
if (options.platform.ramInitialValuesBank.isDefined) {
|
||||
log.error(s"`$name` has both address and initial value, which is unsupported on this target", position)
|
||||
} else {
|
||||
} else if (options.flag(CompilationFlag.BuggyCodeWarning)) {
|
||||
log.warn(s"`$name` has both address and initial value - this may not work as expected!", position)
|
||||
}
|
||||
}
|
||||
@ -1792,7 +1792,7 @@ class Environment(val parent: Option[Environment], val prefix: String, val cpuFa
|
||||
else if (stmt.global) VariableAllocationMethod.Static
|
||||
else if (stmt.register) VariableAllocationMethod.Register
|
||||
else VariableAllocationMethod.Auto
|
||||
if (stmt.volatile && !stmt.global) {
|
||||
if (stmt.volatile && !stmt.global && options.flag(CompilationFlag.FallbackValueUseWarning)) {
|
||||
log.warn(s"Volatile variable `$name` assumed to be static", position)
|
||||
}
|
||||
if (stmt.volatile && stmt.stack) {
|
||||
|
@ -98,7 +98,7 @@ abstract class AbstractSourceLoadingQueue[T](val initialFilenames: List[String],
|
||||
val shortFileName = path.getFileName.toString
|
||||
val PreprocessingResult(src, featureConstants, pragmas) = Preprocessor(options, shortFileName, Files.readAllLines(path, StandardCharsets.UTF_8).toIndexedSeq)
|
||||
for (pragma <- pragmas) {
|
||||
if (!supportedPragmas(pragma._1)) {
|
||||
if (!supportedPragmas(pragma._1) && options.flag(CompilationFlag.BuggyCodeWarning)) {
|
||||
options.log.warn(s"Unsupported pragma: #pragma ${pragma._1}", Some(Position(moduleName, pragma._2, 1, 0)))
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ package millfork.parser
|
||||
import java.util.Locale
|
||||
|
||||
import fastparse.all._
|
||||
import millfork.CompilationOptions
|
||||
import millfork.{CompilationFlag, CompilationOptions}
|
||||
import millfork.assembly.Elidability
|
||||
import millfork.assembly.m6809.{AAccumulatorIndexed, Absolute, BAccumulatorIndexed, DAccumulatorIndexed, DirectPage, Immediate, Indexed, Inherent, InherentA, InherentB, LongRelative, MAddrMode, MLine, MOpcode, NonExistent, PostIncremented, PreDecremented, RegisterSet, Relative, TwoRegisters}
|
||||
import millfork.env.{ByM6809Register, ParamPassingConvention}
|
||||
@ -145,6 +145,7 @@ case class M6809Parser(filename: String,
|
||||
|
||||
|
||||
override def validateAsmFunctionBody(p: Position, flags: Set[String], name: String, statements: Option[List[Statement]]): Unit = {
|
||||
if (!options.flag(CompilationFlag.BuggyCodeWarning)) return
|
||||
statements match {
|
||||
case Some(Nil) => log.warn("Assembly function `$name` is empty, did you mean RTS, RTI, JMP, BRA or LBRA?", Some(p))
|
||||
case Some(xs) =>
|
||||
|
@ -274,10 +274,10 @@ abstract class MfParser[T](fileId: String, input: String, currentDirectory: Stri
|
||||
} yield {
|
||||
val fixedDirection = direction match {
|
||||
case ForDirection.ParallelUntil =>
|
||||
log.warn("`paralleluntil` is not allowed in array definitions, assuming `until`", Some(pos))
|
||||
if (options.flag(CompilationFlag.FallbackValueUseWarning)) log.warn("`paralleluntil` is not allowed in array definitions, assuming `until`", Some(pos))
|
||||
ForDirection.Until
|
||||
case ForDirection.ParallelTo =>
|
||||
log.warn("`parallelto` is not allowed in array definitions, assuming `to`", Some(pos))
|
||||
if (options.flag(CompilationFlag.FallbackValueUseWarning)) log.warn("`parallelto` is not allowed in array definitions, assuming `to`", Some(pos))
|
||||
ForDirection.To
|
||||
case x => x
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ import fastparse.all._
|
||||
import millfork.assembly.mos.{AddrMode, AssemblyLine, Opcode, OpcodeClasses}
|
||||
import millfork.env._
|
||||
import millfork.node._
|
||||
import millfork.CompilationOptions
|
||||
import millfork.{CompilationFlag, CompilationOptions}
|
||||
import millfork.assembly.Elidability
|
||||
import millfork.output.{MemoryAlignment, WithinPageAlignment}
|
||||
|
||||
@ -137,6 +137,7 @@ case class MosParser(filename: String, input: String, currentDirectory: String,
|
||||
} yield ParameterDeclaration(typ, appc).pos(p)
|
||||
|
||||
def validateAsmFunctionBody(p: Position, flags: Set[String], name: String, statements: Option[List[Statement]]): Unit = {
|
||||
if (!options.flag(CompilationFlag.BuggyCodeWarning)) return
|
||||
statements match {
|
||||
case Some(Nil) => log.warn("Assembly function `$name` is empty, did you mean RTS, RTI or JMP", Some(p))
|
||||
case Some(xs) =>
|
||||
|
@ -1,7 +1,7 @@
|
||||
package millfork.parser
|
||||
|
||||
import fastparse.core.Parsed.{Failure, Success}
|
||||
import millfork.{CompilationOptions, Platform, SeparatedList}
|
||||
import millfork.{CompilationFlag, CompilationOptions, Platform, SeparatedList}
|
||||
import millfork.error.{ConsoleLogger, Logger}
|
||||
import millfork.node.Position
|
||||
|
||||
@ -79,7 +79,7 @@ object Preprocessor {
|
||||
param.split("=", 2) match {
|
||||
case Array(p) =>
|
||||
featureConstants += param -> options.features.getOrElse(param, {
|
||||
log.warn(s"Undefined parameter $param, assuming 0", pos)
|
||||
if (options.flag(CompilationFlag.FallbackValueUseWarning)) log.warn(s"Undefined parameter $param, assuming 0", pos)
|
||||
0L
|
||||
})
|
||||
case Array(p0,p1) => featureConstants += assertIdentifier(p0.trim(), pos) -> evalParam(p1, pos)
|
||||
|
@ -77,7 +77,9 @@ class UnicodeTextCodec(override val name: String, val charset: Charset, override
|
||||
encode(log, position, List(c), options, lenient)
|
||||
case None =>
|
||||
if (lenient) {
|
||||
log.warn(s"Cannot encode escape sequence {$escSeq} in encoding `$name`, skipped it", position)
|
||||
if (options.flag(CompilationFlag.FallbackValueUseWarning)) {
|
||||
log.warn(s"Cannot encode escape sequence {$escSeq} in encoding `$name`, skipped it", position)
|
||||
}
|
||||
} else {
|
||||
log.error(s"Invalid escape sequence {$escSeq} for encoding `$name`", position)
|
||||
}
|
||||
@ -170,7 +172,9 @@ class TableTextCodec(override val name: String,
|
||||
Some(List(index))
|
||||
} else if (lenient) {
|
||||
val alternative = TextCodec.lossyAlternatives.getOrElse(c, Nil).:+("?").find(alts => alts.forall(alt => encodeChar(log, position, alt, options, lenient = false).isDefined)).getOrElse("")
|
||||
log.warn(s"Cannot encode ${format(c)} in encoding `$name`, replaced it with ${format(alternative)}", position)
|
||||
if (options.flag(CompilationFlag.FallbackValueUseWarning)) {
|
||||
log.warn(s"Cannot encode ${format(c)} in encoding `$name`, replaced it with ${format(alternative)}", position)
|
||||
}
|
||||
Some(alternative.toList.flatMap(encodeChar(log, position, _, options, lenient = false).get))
|
||||
} else {
|
||||
None
|
||||
@ -228,7 +232,9 @@ class TableTextCodec(override val name: String,
|
||||
}
|
||||
escapeSequences.getOrElse(escSeq, {
|
||||
if (lenient) {
|
||||
log.warn(s"Cannot encode escape sequence {$escSeq} in encoding `$name`, skipped it", position)
|
||||
if (options.flag(CompilationFlag.FallbackValueUseWarning)) {
|
||||
log.warn(s"Cannot encode escape sequence {$escSeq} in encoding `$name`, skipped it", position)
|
||||
}
|
||||
} else {
|
||||
log.error(s"Invalid escape sequence {$escSeq} for encoding `$name`", position)
|
||||
}
|
||||
|
@ -663,6 +663,7 @@ case class Z80Parser(filename: String,
|
||||
override val asmStatement: P[ExecutableStatement] = (position("assembly statement") ~ P(asmLabel | asmMacro | arrayContentsForAsm | asmInstruction)).map { case (p, s) => s.pos(p) } // TODO: macros
|
||||
|
||||
override def validateAsmFunctionBody(p: Position, flags: Set[String], name: String, statements: Option[List[Statement]]): Unit = {
|
||||
if (!options.flag(CompilationFlag.BuggyCodeWarning)) return
|
||||
statements match {
|
||||
case Some(Nil) => log.warn("Assembly function `$name` is empty, did you mean RET, RETI, RETN or JP", Some(p))
|
||||
case Some(xs) =>
|
||||
|
Loading…
x
Reference in New Issue
Block a user