mirror of
https://github.com/KarolS/millfork.git
synced 2024-09-10 11:54:30 +00:00
Give the preprocessor access to compilation options
This commit is contained in:
parent
2af8304512
commit
2b279ac5e8
@ -30,19 +30,35 @@ You can also define feature values using the `-D` command line option.
|
|||||||
|
|
||||||
### Built-in features
|
### Built-in features
|
||||||
|
|
||||||
|
The following features are defined based on the chosen CPU and compilation options:
|
||||||
|
|
||||||
* `ARCH_6502` – 1 if compiling for 6502, 0 otherwise
|
* `ARCH_6502` – 1 if compiling for 6502, 0 otherwise
|
||||||
|
|
||||||
* `CPUFEATURE_65C02` – 1 if compiling for 65C02-compatible processor, 0 otherwise
|
|
||||||
|
|
||||||
* `CPUFEATURE_65CE02` – 1 if compiling for 65CE02-compatible processor, 0 otherwise
|
|
||||||
|
|
||||||
* `ARCH_I80` – 1 if compiling for Intel 8080-like processor, 0 otherwise
|
* `ARCH_I80` – 1 if compiling for Intel 8080-like processor, 0 otherwise
|
||||||
|
|
||||||
* `CPUFEATURE_8080` – 1 if compiling for Intel 8080-compatible processor, 0 otherwise
|
* `CPU_65C02`, `CPU_65CE02`, `CPU_65816`, `CPU_HUC6280`, `CPU_8080`, `CPU_GAMEBOY`, `CPU_Z80`
|
||||||
|
– 1 if compiling for the exact given processor, 0 otherwise
|
||||||
|
|
||||||
* `CPUFEATURE_GAMEBOY` – 1 if compiling for Sharp LR35902-compatible processor, 0 otherwise
|
* `CPU_6502` – 1 if compiling for any pre-65C02 6502-like processor, 0 otherwise
|
||||||
|
|
||||||
* `CPUFEATURE_Z80` – 1 if compiling for Z80-compatible processor, 0 otherwise
|
* `CPUFEATURE_DECIMAL_MODE` – 1 if decimal mode is enabled, 0 otherwise
|
||||||
|
|
||||||
|
* `CPUFEATURE_65C02`, `CPUFEATURE_65CE02`, `CPUFEATURE_HUC6280`, `CPUFEATURE_65816_EMULATION`, `CPUFEATURE_65816_NATIVE`,
|
||||||
|
`CPUFEATURE_8080`, `CPUFEATURE_GAMEBOY`, `CPUFEATURE_Z80`,
|
||||||
|
`CPUFEATURE_6502_ILLEGALS`, `CPUFEATURE_Z80_ILLEGALS` – 1 if given instruction subset is enabled, 0 otherwise
|
||||||
|
|
||||||
|
* `OPTIMIZE_FOR_SIZE`, `OPTIMIZE_FOR_SPEED`, `OPTIMIZE_INLINE`, `OPTIMIZE_IPO`
|
||||||
|
– 1 if given optimization setting is enabled, 0 otherwise
|
||||||
|
|
||||||
|
* `SYNTAX_INTEL`, `SYNTAX_ZILOG` – 1 if given assembly syntax is chosen, 0 otherwise; doesn't take this file's pragmas into account
|
||||||
|
|
||||||
|
* `USES_ZPREG` – 1 if the zeropage pseudoregister is used, 0 otherwise
|
||||||
|
|
||||||
|
* `ZPREG_SIZE` – size of the pseudoregister in bytes
|
||||||
|
|
||||||
|
* `USES_IX_STACK`, `USES_IY_STACK` – 1 if given index register is used as a base pointer for stack-allocated variables, 0 otherwise
|
||||||
|
|
||||||
|
* `USES_SHADOW_REGISTERS` – 1 if interrupts preserve old registers in the shadow registers, 0 otherwise
|
||||||
|
|
||||||
### Commonly used features
|
### Commonly used features
|
||||||
|
|
||||||
@ -52,12 +68,18 @@ You can also define feature values using the `-D` command line option.
|
|||||||
|
|
||||||
* `CBM_64` – 1 if the target is an 8-bit Commodore computer compatible with Commodore 64, 0 otherwise
|
* `CBM_64` – 1 if the target is an 8-bit Commodore computer compatible with Commodore 64, 0 otherwise
|
||||||
|
|
||||||
|
* `CBM_264` – 1 if the target is an 8-bit Commodore computer from the 264 line, 0 otherwise
|
||||||
|
|
||||||
* `KEYBOARD` – 1 if the target has a keyboard, 0 otherwise
|
* `KEYBOARD` – 1 if the target has a keyboard, 0 otherwise
|
||||||
|
|
||||||
* `JOYSTICKS` – the maximum number of joysticks using standard hardware configurations, may be 0
|
* `JOYSTICKS` – the maximum number of joysticks using standard hardware configurations, may be 0
|
||||||
|
|
||||||
* `HAS_BITMAP_MODE` – 1 if the target has a display mode with every pixel addressable, 0 otherwise
|
* `HAS_BITMAP_MODE` – 1 if the target has a display mode with every pixel addressable, 0 otherwise
|
||||||
|
|
||||||
|
* `MOS_6510` – 1 if the target uses a MOS 6510-compatible processor (with an I/O port at $0000/$0001)
|
||||||
|
|
||||||
|
* `CPM` – 1 if the target is CP/M, 0 otherwise
|
||||||
|
|
||||||
### Built-in preprocessor functions and operators
|
### Built-in preprocessor functions and operators
|
||||||
|
|
||||||
The `defined` function returns 1 if the feature is defined, 0 otherwise.
|
The `defined` function returns 1 if the feature is defined, 0 otherwise.
|
||||||
|
@ -10,6 +10,7 @@ case class CompilationOptions(platform: Platform,
|
|||||||
commandLineFlags: Map[CompilationFlag.Value, Boolean],
|
commandLineFlags: Map[CompilationFlag.Value, Boolean],
|
||||||
outputFileName: Option[String],
|
outputFileName: Option[String],
|
||||||
zpRegisterSize: Int,
|
zpRegisterSize: Int,
|
||||||
|
featureOverrides: Map[String, Long],
|
||||||
jobContext: JobContext) {
|
jobContext: JobContext) {
|
||||||
|
|
||||||
import CompilationFlag._
|
import CompilationFlag._
|
||||||
@ -162,6 +163,38 @@ case class CompilationOptions(platform: Platform,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def features: Map[String, Long] = {
|
||||||
|
@inline
|
||||||
|
def toLong(b: Boolean): Long = if (b) 1L else 0L
|
||||||
|
val featuresFromOptions = Map[String, Long](
|
||||||
|
"OPTIMIZE_FOR_SIZE" -> toLong(flag(CompilationFlag.OptimizeForSize)),
|
||||||
|
"OPTIMIZE_FOR_SPEED" -> toLong(flag(CompilationFlag.OptimizeForSpeed)),
|
||||||
|
"OPTIMIZE_INLINE" -> toLong(flag(CompilationFlag.InlineFunctions)),
|
||||||
|
"OPTIMIZE_IPO" -> toLong(flag(CompilationFlag.InterproceduralOptimization)),
|
||||||
|
"CPUFEATURE_DECIMAL_MODE" -> toLong(flag(CompilationFlag.DecimalMode)),
|
||||||
|
"CPUFEATURE_Z80" -> toLong(flag(CompilationFlag.EmitZ80Opcodes)),
|
||||||
|
"CPUFEATURE_EZ80" -> toLong(flag(CompilationFlag.EmitEZ80Opcodes)),
|
||||||
|
"CPUFEATURE_8080" -> toLong(flag(CompilationFlag.EmitIntel8080Opcodes)),
|
||||||
|
"CPUFEATURE_GAMEBOY" -> toLong(flag(CompilationFlag.EmitSharpOpcodes)),
|
||||||
|
"CPUFEATURE_65C02" -> toLong(flag(CompilationFlag.EmitCmosOpcodes)),
|
||||||
|
"CPUFEATURE_65CE02" -> toLong(flag(CompilationFlag.Emit65CE02Opcodes)),
|
||||||
|
"CPUFEATURE_HUC6280" -> toLong(flag(CompilationFlag.EmitHudsonOpcodes)),
|
||||||
|
"CPUFEATURE_65816_EMULATION" -> toLong(flag(CompilationFlag.EmitEmulation65816Opcodes)),
|
||||||
|
"CPUFEATURE_65816_NATIVE" -> toLong(flag(CompilationFlag.EmitNative65816Opcodes)),
|
||||||
|
"CPUFEATURE_6502_ILLEGALS" -> toLong(platform.cpuFamily == CpuFamily.M6502 && flag(CompilationFlag.EmitIllegals)),
|
||||||
|
"CPUFEATURE_Z80_ILLEGALS" -> toLong(platform.cpuFamily == CpuFamily.I80 && flag(CompilationFlag.EmitIllegals)),
|
||||||
|
"SYNTAX_INTEL" -> toLong(platform.cpuFamily == CpuFamily.I80 && flag(CompilationFlag.UseIntelSyntaxForInput)),
|
||||||
|
"SYNTAX_ZILOG" -> toLong(platform.cpuFamily == CpuFamily.I80 && !flag(CompilationFlag.UseIntelSyntaxForInput)),
|
||||||
|
"USES_ZPREG" -> toLong(platform.cpuFamily == CpuFamily.M6502 && zpRegisterSize > 0),
|
||||||
|
"USES_IX_STACK" -> toLong(flag(CompilationFlag.UseIxForStack)),
|
||||||
|
"USES_IY_STACK" -> toLong(flag(CompilationFlag.UseIyForStack)),
|
||||||
|
"USES_SHADOW_REGISTERS" -> toLong(flag(CompilationFlag.UseShadowRegistersForInterrupts)),
|
||||||
|
"ZPREG_SIZE" -> (if (platform.cpuFamily == CpuFamily.M6502) zpRegisterSize.toLong else 0)
|
||||||
|
)
|
||||||
|
platform.features ++ featuresFromOptions ++ featureOverrides
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
object CpuFamily extends Enumeration {
|
object CpuFamily extends Enumeration {
|
||||||
|
@ -80,8 +80,8 @@ object Main {
|
|||||||
val platform = Platform.lookupPlatformFile(c.includePath, c.platform.getOrElse {
|
val platform = Platform.lookupPlatformFile(c.includePath, c.platform.getOrElse {
|
||||||
errorReporting.info("No platform selected, defaulting to `c64`")
|
errorReporting.info("No platform selected, defaulting to `c64`")
|
||||||
"c64"
|
"c64"
|
||||||
}, c.features)
|
})
|
||||||
val options = CompilationOptions(platform, c.flags, c.outputFileName, c.zpRegisterSize.getOrElse(platform.zpRegisterSize), JobContext(errorReporting, new LabelGenerator))
|
val options = CompilationOptions(platform, c.flags, c.outputFileName, c.zpRegisterSize.getOrElse(platform.zpRegisterSize), c.features, JobContext(errorReporting, new LabelGenerator))
|
||||||
errorReporting.debug("Effective flags: ")
|
errorReporting.debug("Effective flags: ")
|
||||||
options.flags.toSeq.sortBy(_._1).foreach{
|
options.flags.toSeq.sortBy(_._1).foreach{
|
||||||
case (f, b) => errorReporting.debug(f" $f%-30s : $b%s")
|
case (f, b) => errorReporting.debug(f" $f%-30s : $b%s")
|
||||||
|
@ -42,18 +42,18 @@ class Platform(
|
|||||||
|
|
||||||
object Platform {
|
object Platform {
|
||||||
|
|
||||||
def lookupPlatformFile(includePath: List[String], platformName: String, featureOverrides: Map[String, Long])(implicit log: Logger): Platform = {
|
def lookupPlatformFile(includePath: List[String], platformName: String)(implicit log: Logger): Platform = {
|
||||||
includePath.foreach { dir =>
|
includePath.foreach { dir =>
|
||||||
val file = Paths.get(dir, platformName + ".ini").toFile
|
val file = Paths.get(dir, platformName + ".ini").toFile
|
||||||
log.debug("Checking " + file)
|
log.debug("Checking " + file)
|
||||||
if (file.exists()) {
|
if (file.exists()) {
|
||||||
return load(file, featureOverrides)
|
return load(file)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
log.fatal(s"Platfom definition `$platformName` not found", None)
|
log.fatal(s"Platfom definition `$platformName` not found", None)
|
||||||
}
|
}
|
||||||
|
|
||||||
def load(file: File, featureOverrides: Map[String, Long])(implicit log: Logger): Platform = {
|
def load(file: File)(implicit log: Logger): Platform = {
|
||||||
val conf = new INIConfiguration()
|
val conf = new INIConfiguration()
|
||||||
val bytes = Files.readAllBytes(file.toPath)
|
val bytes = Files.readAllBytes(file.toPath)
|
||||||
conf.read(new StringReader(new String(bytes, StandardCharsets.UTF_8)))
|
conf.read(new StringReader(new String(bytes, StandardCharsets.UTF_8)))
|
||||||
@ -219,7 +219,7 @@ object Platform {
|
|||||||
startingModules,
|
startingModules,
|
||||||
codec,
|
codec,
|
||||||
srcCodec,
|
srcCodec,
|
||||||
builtInFeatures ++ definedFeatures ++ featureOverrides,
|
builtInFeatures ++ definedFeatures,
|
||||||
outputPackager,
|
outputPackager,
|
||||||
codeAllocators.toMap,
|
codeAllocators.toMap,
|
||||||
variableAllocators.toMap,
|
variableAllocators.toMap,
|
||||||
@ -232,29 +232,25 @@ object Platform {
|
|||||||
outputStyle)
|
outputStyle)
|
||||||
}
|
}
|
||||||
|
|
||||||
@inline
|
|
||||||
private def toLong(b: Boolean): Long = if (b) 1L else 0L
|
|
||||||
|
|
||||||
def builtInCpuFeatures(cpu: Cpu.Value): Map[String, Long] = {
|
def builtInCpuFeatures(cpu: Cpu.Value): Map[String, Long] = {
|
||||||
|
@inline
|
||||||
|
def toLong(b: Boolean): Long = if (b) 1L else 0L
|
||||||
Map[String, Long](
|
Map[String, Long](
|
||||||
"ARCH_6502" -> toLong(CpuFamily.forType(cpu) == CpuFamily.M6502),
|
"ARCH_6502" -> toLong(CpuFamily.forType(cpu) == CpuFamily.M6502),
|
||||||
"CPUFEATURE_65C02" -> toLong(Cpu.defaultFlags(cpu).contains(CompilationFlag.EmitCmosOpcodes)),
|
"CPU_6502" -> toLong(Set(Cpu.Mos, Cpu.StrictMos, Cpu.Ricoh, Cpu.StrictRicoh)(cpu)),
|
||||||
"CPUFEATURE_65CE02" -> toLong(Cpu.defaultFlags(cpu).contains(CompilationFlag.Emit65CE02Opcodes)),
|
"CPU_65C02" -> toLong(cpu == Cpu.Cmos),
|
||||||
|
"CPU_65CE02" -> toLong(cpu == Cpu.CE02),
|
||||||
|
"CPU_65816" -> toLong(cpu == Cpu.Sixteen),
|
||||||
|
"CPU_HUC6280" -> toLong(cpu == Cpu.HuC6280),
|
||||||
"ARCH_I80" -> toLong(CpuFamily.forType(cpu) == CpuFamily.I80),
|
"ARCH_I80" -> toLong(CpuFamily.forType(cpu) == CpuFamily.I80),
|
||||||
"CPUFEATURE_Z80" -> toLong(Cpu.defaultFlags(cpu).contains(CompilationFlag.EmitZ80Opcodes)),
|
"CPU_Z80" -> toLong(cpu == Cpu.Z80),
|
||||||
"CPUFEATURE_8080" -> toLong(Cpu.defaultFlags(cpu).contains(CompilationFlag.EmitIntel8080Opcodes)),
|
"CPU_EZ80" -> toLong(cpu == Cpu.EZ80),
|
||||||
"CPUFEATURE_GAMEBOY" -> toLong(Cpu.defaultFlags(cpu).contains(CompilationFlag.EmitSharpOpcodes)),
|
"CPU_8080" -> toLong(cpu == Cpu.Intel8080),
|
||||||
|
"CPU_GAMEBOY" -> toLong(cpu == Cpu.Sharp),
|
||||||
"ARCH_X86" -> toLong(CpuFamily.forType(cpu) == CpuFamily.I86),
|
"ARCH_X86" -> toLong(CpuFamily.forType(cpu) == CpuFamily.I86),
|
||||||
"ARCH_6800" -> toLong(CpuFamily.forType(cpu) == CpuFamily.M6800),
|
"ARCH_6800" -> toLong(CpuFamily.forType(cpu) == CpuFamily.M6800),
|
||||||
"ARCH_ARM" -> toLong(CpuFamily.forType(cpu) == CpuFamily.ARM),
|
"ARCH_ARM" -> toLong(CpuFamily.forType(cpu) == CpuFamily.ARM),
|
||||||
"ARCH_68K" -> toLong(CpuFamily.forType(cpu) == CpuFamily.M68K),
|
"ARCH_68K" -> toLong(CpuFamily.forType(cpu) == CpuFamily.M68K)
|
||||||
"HAS_HARDWARE_MULTIPLY" -> (cpu match {
|
|
||||||
case Cpu.EZ80 => 1L
|
|
||||||
case _ => CpuFamily.forType(cpu) match {
|
|
||||||
case CpuFamily.M6502 | CpuFamily.I80 | CpuFamily.M6800 => 0L
|
|
||||||
case CpuFamily.I86 | CpuFamily.ARM | CpuFamily.M68K => 1L
|
|
||||||
}
|
|
||||||
})
|
|
||||||
// TODO
|
// TODO
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@ object EmuRun {
|
|||||||
val source = Files.readAllLines(Paths.get(filename), StandardCharsets.US_ASCII).asScala.mkString("\n")
|
val source = Files.readAllLines(Paths.get(filename), StandardCharsets.US_ASCII).asScala.mkString("\n")
|
||||||
val options = CompilationOptions(EmuPlatform.get(millfork.Cpu.Mos), Map(
|
val options = CompilationOptions(EmuPlatform.get(millfork.Cpu.Mos), Map(
|
||||||
CompilationFlag.LenientTextEncoding -> true
|
CompilationFlag.LenientTextEncoding -> true
|
||||||
), None, 4, JobContext(TestErrorReporting.log, new LabelGenerator))
|
), None, 4, Map(), JobContext(TestErrorReporting.log, new LabelGenerator))
|
||||||
val PreprocessingResult(preprocessedSource, features, _) = Preprocessor.preprocessForTest(options, source)
|
val PreprocessingResult(preprocessedSource, features, _) = Preprocessor.preprocessForTest(options, source)
|
||||||
TestErrorReporting.log.info(s"Parsing $filename")
|
TestErrorReporting.log.info(s"Parsing $filename")
|
||||||
MosParser("", preprocessedSource, "", options, features).toAst match {
|
MosParser("", preprocessedSource, "", options, features).toAst match {
|
||||||
@ -139,7 +139,7 @@ class EmuRun(cpu: millfork.Cpu.Value, nodeOptimizations: List[NodeOptimization],
|
|||||||
CompilationFlag.OptimizeForSpeed -> blastProcessing,
|
CompilationFlag.OptimizeForSpeed -> blastProcessing,
|
||||||
CompilationFlag.OptimizeForSonicSpeed -> blastProcessing
|
CompilationFlag.OptimizeForSonicSpeed -> blastProcessing
|
||||||
// CompilationFlag.CheckIndexOutOfBounds -> true,
|
// CompilationFlag.CheckIndexOutOfBounds -> true,
|
||||||
), None, 4, JobContext(log, new LabelGenerator))
|
), None, 4, Map(), JobContext(log, new LabelGenerator))
|
||||||
log.hasErrors = false
|
log.hasErrors = false
|
||||||
log.verbosity = 999
|
log.verbosity = 999
|
||||||
var effectiveSource = source
|
var effectiveSource = source
|
||||||
|
@ -43,7 +43,7 @@ class EmuZ80Run(cpu: millfork.Cpu.Value, nodeOptimizations: List[NodeOptimizatio
|
|||||||
CompilationFlag.OptimizeForSize -> this.optimizeForSize,
|
CompilationFlag.OptimizeForSize -> this.optimizeForSize,
|
||||||
CompilationFlag.EmitIllegals -> (cpu == millfork.Cpu.Z80),
|
CompilationFlag.EmitIllegals -> (cpu == millfork.Cpu.Z80),
|
||||||
CompilationFlag.LenientTextEncoding -> true)
|
CompilationFlag.LenientTextEncoding -> true)
|
||||||
val options = CompilationOptions(platform, millfork.Cpu.defaultFlags(cpu).map(_ -> true).toMap ++ extraFlags, None, 0, JobContext(log, new LabelGenerator))
|
val options = CompilationOptions(platform, millfork.Cpu.defaultFlags(cpu).map(_ -> true).toMap ++ extraFlags, None, 0, Map(), JobContext(log, new LabelGenerator))
|
||||||
log.hasErrors = false
|
log.hasErrors = false
|
||||||
log.verbosity = 999
|
log.verbosity = 999
|
||||||
var effectiveSource = source
|
var effectiveSource = source
|
||||||
|
@ -28,7 +28,7 @@ object ShouldNotCompile extends Matchers {
|
|||||||
val log = TestErrorReporting.log
|
val log = TestErrorReporting.log
|
||||||
println(source)
|
println(source)
|
||||||
val platform = EmuPlatform.get(cpu)
|
val platform = EmuPlatform.get(cpu)
|
||||||
val options = CompilationOptions(platform, Map(CompilationFlag.LenientTextEncoding -> true), None, platform.zpRegisterSize, JobContext(log, new LabelGenerator))
|
val options = CompilationOptions(platform, Map(CompilationFlag.LenientTextEncoding -> true), None, platform.zpRegisterSize, Map(), JobContext(log, new LabelGenerator))
|
||||||
log.hasErrors = false
|
log.hasErrors = false
|
||||||
log.verbosity = 999
|
log.verbosity = 999
|
||||||
var effectiveSource = source
|
var effectiveSource = source
|
||||||
|
Loading…
Reference in New Issue
Block a user