added experimental codegen backend option

This commit is contained in:
Irmen de Jong
2022-02-05 21:25:19 +01:00
parent 1ab635bd7e
commit 312949f336
30 changed files with 176 additions and 62 deletions

1
.idea/modules.xml generated
View File

@@ -3,6 +3,7 @@
<component name="ProjectModuleManager"> <component name="ProjectModuleManager">
<modules> <modules>
<module fileurl="file://$PROJECT_DIR$/codeGenCpu6502/codeGenCpu6502.iml" filepath="$PROJECT_DIR$/codeGenCpu6502/codeGenCpu6502.iml" /> <module fileurl="file://$PROJECT_DIR$/codeGenCpu6502/codeGenCpu6502.iml" filepath="$PROJECT_DIR$/codeGenCpu6502/codeGenCpu6502.iml" />
<module fileurl="file://$PROJECT_DIR$/codeGenExperimental6502/codeGenExperimental6502.iml" filepath="$PROJECT_DIR$/codeGenExperimental6502/codeGenExperimental6502.iml" />
<module fileurl="file://$PROJECT_DIR$/codeGenTargets/codeGenTargets.iml" filepath="$PROJECT_DIR$/codeGenTargets/codeGenTargets.iml" /> <module fileurl="file://$PROJECT_DIR$/codeGenTargets/codeGenTargets.iml" filepath="$PROJECT_DIR$/codeGenTargets/codeGenTargets.iml" />
<module fileurl="file://$PROJECT_DIR$/codeOptimizers/codeOptimizers.iml" filepath="$PROJECT_DIR$/codeOptimizers/codeOptimizers.iml" /> <module fileurl="file://$PROJECT_DIR$/codeOptimizers/codeOptimizers.iml" filepath="$PROJECT_DIR$/codeOptimizers/codeOptimizers.iml" />
<module fileurl="file://$PROJECT_DIR$/compiler/compiler.iml" filepath="$PROJECT_DIR$/compiler/compiler.iml" /> <module fileurl="file://$PROJECT_DIR$/compiler/compiler.iml" filepath="$PROJECT_DIR$/compiler/compiler.iml" />

View File

@@ -24,17 +24,17 @@ const val subroutineFloatEvalResultVar1 = "prog8_float_eval_result1"
const val subroutineFloatEvalResultVar2 = "prog8_float_eval_result2" const val subroutineFloatEvalResultVar2 = "prog8_float_eval_result2"
class AsmGen(private val program: Program, class AsmGen6502(internal val program: Program,
val errors: IErrorReporter, internal val errors: IErrorReporter,
val zeropage: Zeropage, internal val options: CompilationOptions,
val options: CompilationOptions, internal val outputDir: Path): IAssemblyGenerator {
private val compTarget: ICompilationTarget,
private val outputDir: Path): IAssemblyGenerator {
// for expressions and augmented assignments: // for expressions and augmented assignments:
val optimizedByteMultiplications = setOf(3,5,6,7,9,10,11,12,13,14,15,20,25,40,50,80,100) val optimizedByteMultiplications = setOf(3,5,6,7,9,10,11,12,13,14,15,20,25,40,50,80,100)
val optimizedWordMultiplications = setOf(3,5,6,7,9,10,12,15,20,25,40,50,80,100,320,640) val optimizedWordMultiplications = setOf(3,5,6,7,9,10,12,15,20,25,40,50,80,100,320,640)
private val callGraph = CallGraph(program) private val callGraph = CallGraph(program)
private val compTarget = options.compTarget
internal val zeropage = compTarget.machine.zeropage
private val assemblyLines = mutableListOf<String>() private val assemblyLines = mutableListOf<String>()
private val globalFloatConsts = mutableMapOf<Double, String>() // all float values in the entire program (value -> varname) private val globalFloatConsts = mutableMapOf<Double, String>() // all float values in the entire program (value -> varname)
@@ -50,7 +50,7 @@ class AsmGen(private val program: Program,
internal val removals = mutableListOf<Pair<Statement, IStatementContainer>>() internal val removals = mutableListOf<Pair<Statement, IStatementContainer>>()
private val blockVariableInitializers = program.allBlocks.associateWith { it.statements.filterIsInstance<Assignment>() } private val blockVariableInitializers = program.allBlocks.associateWith { it.statements.filterIsInstance<Assignment>() }
override fun compileToAssembly(): IAssemblyProgram { override fun compileToAssembly(): IAssemblyProgram? {
assemblyLines.clear() assemblyLines.clear()
loopEndLabels.clear() loopEndLabels.clear()
@@ -90,10 +90,10 @@ class AsmGen(private val program: Program,
} }
return if(errors.noErrors()) return if(errors.noErrors())
AssemblyProgram(true, program.name, outputDir, compTarget.name) AssemblyProgram(program.name, outputDir, compTarget.name)
else { else {
errors.report() errors.report()
AssemblyProgram(false, "<error>", outputDir, compTarget.name) return null
} }
} }

View File

@@ -15,7 +15,6 @@ import kotlin.io.path.isRegularFile
class AssemblyProgram( class AssemblyProgram(
override val valid: Boolean,
override val name: String, override val name: String,
outputDir: Path, outputDir: Path,
private val compTarget: String) : IAssemblyProgram { private val compTarget: String) : IAssemblyProgram {
@@ -26,7 +25,7 @@ class AssemblyProgram(
private val viceMonListFile = outputDir.resolve(viceMonListName(name)) private val viceMonListFile = outputDir.resolve(viceMonListName(name))
private val listFile = outputDir.resolve("$name.list") private val listFile = outputDir.resolve("$name.list")
override fun assemble(options: CompilationOptions): Int { override fun assemble(options: CompilationOptions): Boolean {
// add "-Wlong-branch" to see warnings about conversion of branch instructions to jumps (default = do this silently) // add "-Wlong-branch" to see warnings about conversion of branch instructions to jumps (default = do this silently)
val command = mutableListOf("64tass", "--ascii", "--case-sensitive", "--long-branch", val command = mutableListOf("64tass", "--ascii", "--case-sensitive", "--long-branch",
"-Wall", "-Wno-strict-bool", "-Wno-shadow", // "-Werror", "-Wall", "-Wno-strict-bool", "-Wno-shadow", // "-Werror",
@@ -59,7 +58,7 @@ class AssemblyProgram(
removeGeneratedLabelsFromMonlist() removeGeneratedLabelsFromMonlist()
generateBreakpointList() generateBreakpointList()
} }
return result return result==0
} }
private fun removeGeneratedLabelsFromMonlist() { private fun removeGeneratedLabelsFromMonlist() {

View File

@@ -17,7 +17,7 @@ import prog8.compilerinterface.CpuType
import prog8.compilerinterface.FSignature import prog8.compilerinterface.FSignature
internal class BuiltinFunctionsAsmGen(private val program: Program, private val asmgen: AsmGen, private val assignAsmGen: AssignmentAsmGen) { internal class BuiltinFunctionsAsmGen(private val program: Program, private val asmgen: AsmGen6502, private val assignAsmGen: AssignmentAsmGen) {
internal fun translateFunctioncallExpression(fcall: FunctionCallExpression, func: FSignature, resultToStack: Boolean, resultRegister: RegisterOrPair?) { internal fun translateFunctioncallExpression(fcall: FunctionCallExpression, func: FSignature, resultToStack: Boolean, resultRegister: RegisterOrPair?) {
translateFunctioncall(fcall, func, discardResult = false, resultToStack = resultToStack, resultRegister = resultRegister) translateFunctioncall(fcall, func, discardResult = false, resultToStack = resultToStack, resultRegister = resultRegister)

View File

@@ -11,7 +11,7 @@ import prog8.compilerinterface.BuiltinFunctions
import prog8.compilerinterface.CpuType import prog8.compilerinterface.CpuType
import kotlin.math.absoluteValue import kotlin.math.absoluteValue
internal class ExpressionsAsmGen(private val program: Program, private val asmgen: AsmGen, private val functioncallAsmGen: FunctionCallAsmGen) { internal class ExpressionsAsmGen(private val program: Program, private val asmgen: AsmGen6502, private val functioncallAsmGen: FunctionCallAsmGen) {
@Deprecated("avoid calling this as it generates slow evalstack based code") @Deprecated("avoid calling this as it generates slow evalstack based code")
internal fun translateExpression(expression:Expression) { internal fun translateExpression(expression:Expression) {

View File

@@ -12,7 +12,7 @@ import prog8.ast.toHex
import prog8.compilerinterface.AssemblyError import prog8.compilerinterface.AssemblyError
import kotlin.math.absoluteValue import kotlin.math.absoluteValue
internal class ForLoopsAsmGen(private val program: Program, private val asmgen: AsmGen) { internal class ForLoopsAsmGen(private val program: Program, private val asmgen: AsmGen6502) {
internal fun translate(stmt: ForLoop) { internal fun translate(stmt: ForLoop) {
val iterableDt = stmt.iterable.inferType(program) val iterableDt = stmt.iterable.inferType(program)

View File

@@ -17,7 +17,7 @@ import prog8.compilerinterface.AssemblyError
import prog8.compilerinterface.CpuType import prog8.compilerinterface.CpuType
internal class FunctionCallAsmGen(private val program: Program, private val asmgen: AsmGen) { internal class FunctionCallAsmGen(private val program: Program, private val asmgen: AsmGen6502) {
internal fun translateFunctionCallStatement(stmt: IFunctionCall) { internal fun translateFunctionCallStatement(stmt: IFunctionCall) {
saveXbeforeCall(stmt) saveXbeforeCall(stmt)

View File

@@ -9,7 +9,7 @@ import prog8.ast.toHex
import prog8.compilerinterface.AssemblyError import prog8.compilerinterface.AssemblyError
internal class PostIncrDecrAsmGen(private val program: Program, private val asmgen: AsmGen) { internal class PostIncrDecrAsmGen(private val program: Program, private val asmgen: AsmGen6502) {
internal fun translate(stmt: PostIncrDecr) { internal fun translate(stmt: PostIncrDecr) {
val incr = stmt.operator=="++" val incr = stmt.operator=="++"
val targetIdent = stmt.target.identifier val targetIdent = stmt.target.identifier

View File

@@ -4,7 +4,7 @@ import prog8.ast.Program
import prog8.ast.base.* import prog8.ast.base.*
import prog8.ast.expressions.* import prog8.ast.expressions.*
import prog8.ast.statements.* import prog8.ast.statements.*
import prog8.codegen.cpu6502.AsmGen import prog8.codegen.cpu6502.AsmGen6502
import prog8.compilerinterface.AssemblyError import prog8.compilerinterface.AssemblyError
import prog8.compilerinterface.IMemSizer import prog8.compilerinterface.IMemSizer
@@ -29,7 +29,7 @@ internal enum class SourceStorageKind {
internal class AsmAssignTarget(val kind: TargetStorageKind, internal class AsmAssignTarget(val kind: TargetStorageKind,
private val program: Program, private val program: Program,
private val asmgen: AsmGen, private val asmgen: AsmGen6502,
val datatype: DataType, val datatype: DataType,
val scope: Subroutine?, val scope: Subroutine?,
private val variableAsmName: String? = null, private val variableAsmName: String? = null,
@@ -56,7 +56,7 @@ internal class AsmAssignTarget(val kind: TargetStorageKind,
} }
companion object { companion object {
fun fromAstAssignment(assign: Assignment, program: Program, asmgen: AsmGen): AsmAssignTarget { fun fromAstAssignment(assign: Assignment, program: Program, asmgen: AsmGen6502): AsmAssignTarget {
with(assign.target) { with(assign.target) {
val idt = inferType(program) val idt = inferType(program)
val dt = idt.getOrElse { throw AssemblyError("unknown dt") } val dt = idt.getOrElse { throw AssemblyError("unknown dt") }
@@ -82,7 +82,7 @@ internal class AsmAssignTarget(val kind: TargetStorageKind,
} }
} }
fun fromRegisters(registers: RegisterOrPair, signed: Boolean, scope: Subroutine?, program: Program, asmgen: AsmGen): AsmAssignTarget = fun fromRegisters(registers: RegisterOrPair, signed: Boolean, scope: Subroutine?, program: Program, asmgen: AsmGen6502): AsmAssignTarget =
when(registers) { when(registers) {
RegisterOrPair.A, RegisterOrPair.A,
RegisterOrPair.X, RegisterOrPair.X,
@@ -114,7 +114,7 @@ internal class AsmAssignTarget(val kind: TargetStorageKind,
internal class AsmAssignSource(val kind: SourceStorageKind, internal class AsmAssignSource(val kind: SourceStorageKind,
private val program: Program, private val program: Program,
private val asmgen: AsmGen, private val asmgen: AsmGen6502,
val datatype: DataType, val datatype: DataType,
private val variableAsmName: String? = null, private val variableAsmName: String? = null,
val array: ArrayIndexedExpression? = null, val array: ArrayIndexedExpression? = null,
@@ -134,9 +134,9 @@ internal class AsmAssignSource(val kind: SourceStorageKind,
asmgen.asmVariableName(array.arrayvar) asmgen.asmVariableName(array.arrayvar)
companion object { companion object {
fun fromAstSource(indexer: ArrayIndex, program: Program, asmgen: AsmGen): AsmAssignSource = fromAstSource(indexer.indexExpr, program, asmgen) fun fromAstSource(indexer: ArrayIndex, program: Program, asmgen: AsmGen6502): AsmAssignSource = fromAstSource(indexer.indexExpr, program, asmgen)
fun fromAstSource(value: Expression, program: Program, asmgen: AsmGen): AsmAssignSource { fun fromAstSource(value: Expression, program: Program, asmgen: AsmGen6502): AsmAssignSource {
val cv = value.constValue(program) val cv = value.constValue(program)
if(cv!=null) if(cv!=null)
return AsmAssignSource(SourceStorageKind.LITERALNUMBER, program, asmgen, cv.type, number = cv) return AsmAssignSource(SourceStorageKind.LITERALNUMBER, program, asmgen, cv.type, number = cv)

View File

@@ -5,14 +5,14 @@ import prog8.ast.base.*
import prog8.ast.expressions.* import prog8.ast.expressions.*
import prog8.ast.statements.* import prog8.ast.statements.*
import prog8.ast.toHex import prog8.ast.toHex
import prog8.codegen.cpu6502.AsmGen import prog8.codegen.cpu6502.AsmGen6502
import prog8.compilerinterface.AssemblyError import prog8.compilerinterface.AssemblyError
import prog8.compilerinterface.BuiltinFunctions import prog8.compilerinterface.BuiltinFunctions
import prog8.compilerinterface.CpuType import prog8.compilerinterface.CpuType
import prog8.compilerinterface.builtinFunctionReturnType import prog8.compilerinterface.builtinFunctionReturnType
internal class AssignmentAsmGen(private val program: Program, private val asmgen: AsmGen) { internal class AssignmentAsmGen(private val program: Program, private val asmgen: AsmGen6502) {
private val augmentableAsmGen = AugmentableAssignmentAsmGen(program, this, asmgen) private val augmentableAsmGen = AugmentableAssignmentAsmGen(program, this, asmgen)

View File

@@ -5,14 +5,14 @@ import prog8.ast.base.*
import prog8.ast.expressions.* import prog8.ast.expressions.*
import prog8.ast.statements.Subroutine import prog8.ast.statements.Subroutine
import prog8.ast.toHex import prog8.ast.toHex
import prog8.codegen.cpu6502.AsmGen import prog8.codegen.cpu6502.AsmGen6502
import prog8.compilerinterface.AssemblyError import prog8.compilerinterface.AssemblyError
import prog8.compilerinterface.CpuType import prog8.compilerinterface.CpuType
internal class AugmentableAssignmentAsmGen(private val program: Program, internal class AugmentableAssignmentAsmGen(private val program: Program,
private val assignmentAsmGen: AssignmentAsmGen, private val assignmentAsmGen: AssignmentAsmGen,
private val asmgen: AsmGen private val asmgen: AsmGen6502
) { ) {
fun translate(assign: AsmAssignment) { fun translate(assign: AsmAssignment) {
require(assign.isAugmentable) require(assign.isAugmentable)

View File

@@ -0,0 +1,46 @@
plugins {
id 'java'
id 'application'
id "org.jetbrains.kotlin.jvm"
}
java {
toolchain {
languageVersion = JavaLanguageVersion.of(javaVersion)
}
}
compileKotlin {
kotlinOptions {
jvmTarget = javaVersion
}
}
compileTestKotlin {
kotlinOptions {
jvmTarget = javaVersion
}
}
dependencies {
implementation project(':compilerInterfaces')
implementation project(':compilerAst')
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
// implementation "org.jetbrains.kotlin:kotlin-reflect"
implementation "com.michael-bull.kotlin-result:kotlin-result-jvm:1.1.12"
}
sourceSets {
main {
java {
srcDirs = ["${project.projectDir}/src"]
}
resources {
srcDirs = ["${project.projectDir}/res"]
}
}
}
// note: there are no unit tests in this module!

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<excludeFolder url="file://$MODULE_DIR$/build" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="KotlinJavaRuntime" level="project" />
<orderEntry type="module" module-name="compilerAst" />
<orderEntry type="module" module-name="compilerInterfaces" />
<orderEntry type="library" name="michael.bull.kotlin.result.jvm" level="project" />
</component>
</module>

View File

@@ -0,0 +1,13 @@
package prog8.codegen.experimental6502
import prog8.compilerinterface.CompilationOptions
import prog8.compilerinterface.IAssemblyProgram
class AssemblyProgram(override val name: String) : IAssemblyProgram
{
override fun assemble(options: CompilationOptions): Boolean {
println("..todo: assemble code into binary..")
return false
}
}

View File

@@ -0,0 +1,22 @@
package prog8.codegen.experimental6502
import prog8.ast.Program
import prog8.compilerinterface.CompilationOptions
import prog8.compilerinterface.IAssemblyGenerator
import prog8.compilerinterface.IAssemblyProgram
import prog8.compilerinterface.IErrorReporter
import java.nio.file.Path
class ExperimentalAsmGen6502(internal val program: Program,
internal val errors: IErrorReporter,
internal val options: CompilationOptions,
internal val outputDir: Path
): IAssemblyGenerator {
override fun compileToAssembly(): IAssemblyProgram? {
println("\n** experimental 65(c)02 code generator **\n")
println("..todo: create assembly code..")
return AssemblyProgram("dummy")
}
}

View File

@@ -32,6 +32,7 @@ dependencies {
implementation project(':compilerAst') implementation project(':compilerAst')
implementation project(':codeGenTargets') implementation project(':codeGenTargets')
implementation project(':codeGenCpu6502') implementation project(':codeGenCpu6502')
implementation project(':codeGenExperimental6502')
implementation 'org.antlr:antlr4-runtime:4.9.2' implementation 'org.antlr:antlr4-runtime:4.9.2'
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8" implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
// implementation "org.jetbrains.kotlin:kotlin-reflect" // implementation "org.jetbrains.kotlin:kotlin-reflect"

View File

@@ -21,5 +21,6 @@
<orderEntry type="library" name="io.kotest.runner.junit5.jvm" level="project" /> <orderEntry type="library" name="io.kotest.runner.junit5.jvm" level="project" />
<orderEntry type="library" name="antlr.antlr4" level="project" /> <orderEntry type="library" name="antlr.antlr4" level="project" />
<orderEntry type="module" module-name="codeGenCpu6502" /> <orderEntry type="module" module-name="codeGenCpu6502" />
<orderEntry type="module" module-name="codeGenExperimental6502" />
</component> </component>
</module> </module>

View File

@@ -43,6 +43,7 @@ private fun compileMain(args: Array<String>): Boolean {
val slowCodegenWarnings by cli.option(ArgType.Boolean, fullName = "slowwarn", description="show debug warnings about slow/problematic assembly code generation") val slowCodegenWarnings by cli.option(ArgType.Boolean, fullName = "slowwarn", description="show debug warnings about slow/problematic assembly code generation")
val quietAssembler by cli.option(ArgType.Boolean, fullName = "quietasm", description = "don't print assembler output results") val quietAssembler by cli.option(ArgType.Boolean, fullName = "quietasm", description = "don't print assembler output results")
val asmListfile by cli.option(ArgType.Boolean, fullName = "asmlist", description = "make the assembler produce a listing file as well") val asmListfile by cli.option(ArgType.Boolean, fullName = "asmlist", description = "make the assembler produce a listing file as well")
val experimentalCodegen by cli.option(ArgType.Boolean, fullName = "expericodegen", description = "use experimental codegen")
val compilationTarget by cli.option(ArgType.String, fullName = "target", description = "target output of the compiler (one of '${C64Target.name}', '${C128Target.name}', '${Cx16Target.name}')").default(C64Target.name) val compilationTarget by cli.option(ArgType.String, fullName = "target", description = "target output of the compiler (one of '${C64Target.name}', '${C128Target.name}', '${Cx16Target.name}')").default(C64Target.name)
val sourceDirs by cli.option(ArgType.String, fullName="srcdirs", description = "list of extra paths, separated with ${File.pathSeparator}, to search in for imported modules").multiple().delimiter(File.pathSeparator) val sourceDirs by cli.option(ArgType.String, fullName="srcdirs", description = "list of extra paths, separated with ${File.pathSeparator}, to search in for imported modules").multiple().delimiter(File.pathSeparator)
val moduleFiles by cli.argument(ArgType.String, fullName = "modules", description = "main module file(s) to compile").multiple(999) val moduleFiles by cli.argument(ArgType.String, fullName = "modules", description = "main module file(s) to compile").multiple(999)
@@ -93,6 +94,7 @@ private fun compileMain(args: Array<String>): Boolean {
slowCodegenWarnings == true, slowCodegenWarnings == true,
quietAssembler == true, quietAssembler == true,
asmListfile == true, asmListfile == true,
experimentalCodegen == true,
compilationTarget, compilationTarget,
srcdirs, srcdirs,
outputPath outputPath
@@ -143,6 +145,7 @@ private fun compileMain(args: Array<String>): Boolean {
slowCodegenWarnings == true, slowCodegenWarnings == true,
quietAssembler == true, quietAssembler == true,
asmListfile == true, asmListfile == true,
experimentalCodegen == true,
compilationTarget, compilationTarget,
srcdirs, srcdirs,
outputPath outputPath

View File

@@ -9,7 +9,8 @@ import prog8.ast.base.Position
import prog8.ast.expressions.Expression import prog8.ast.expressions.Expression
import prog8.ast.expressions.NumericLiteralValue import prog8.ast.expressions.NumericLiteralValue
import prog8.ast.statements.Directive import prog8.ast.statements.Directive
import prog8.codegen.cpu6502.AsmGen import prog8.codegen.cpu6502.AsmGen6502
import prog8.codegen.experimental6502.ExperimentalAsmGen6502
import prog8.codegen.target.C128Target import prog8.codegen.target.C128Target
import prog8.codegen.target.C64Target import prog8.codegen.target.C64Target
import prog8.codegen.target.Cx16Target import prog8.codegen.target.Cx16Target
@@ -37,6 +38,7 @@ class CompilerArguments(val filepath: Path,
val slowCodegenWarnings: Boolean, val slowCodegenWarnings: Boolean,
val quietAssembler: Boolean, val quietAssembler: Boolean,
val asmListfile: Boolean, val asmListfile: Boolean,
val experimentalCodegen: Boolean,
val compilationTarget: String, val compilationTarget: String,
val sourceDirs: List<String> = emptyList(), val sourceDirs: List<String> = emptyList(),
val outputDir: Path = Path(""), val outputDir: Path = Path(""),
@@ -72,6 +74,7 @@ fun compileProgram(args: CompilerArguments): CompilationResult {
dontReinitGlobals = args.dontReinitGlobals dontReinitGlobals = args.dontReinitGlobals
asmQuiet = args.quietAssembler asmQuiet = args.quietAssembler
asmListfile = args.asmListfile asmListfile = args.asmListfile
experimentalCodegen = args.experimentalCodegen
} }
program = programresult program = programresult
importedFiles = imported importedFiles = imported
@@ -347,21 +350,18 @@ private fun writeAssembly(program: Program,
// printProgram(program) // printProgram(program)
compilerOptions.compTarget.machine.initializeZeropage(compilerOptions) compilerOptions.compTarget.machine.initializeZeropage(compilerOptions)
val assembly = asmGeneratorFor(compilerOptions.compTarget, val assembly = asmGeneratorFor(
program, program,
errors, errors,
compilerOptions.compTarget.machine.zeropage,
compilerOptions, compilerOptions,
outputDir).compileToAssembly() outputDir).compileToAssembly()
errors.report() errors.report()
return if(assembly.valid && errors.noErrors()) { return if(assembly!=null && errors.noErrors()) {
val assemblerReturnStatus = assembly.assemble(compilerOptions) if(assembly.assemble(compilerOptions)) {
if(assemblerReturnStatus!=0)
WriteAssemblyResult.Fail("assembler step failed with return code $assemblerReturnStatus")
else {
WriteAssemblyResult.Ok(assembly.name) WriteAssemblyResult.Ok(assembly.name)
} } else
WriteAssemblyResult.Fail("assembler step failed")
} else { } else {
WriteAssemblyResult.Fail("compiler failed with errors") WriteAssemblyResult.Fail("compiler failed with errors")
} }
@@ -375,14 +375,19 @@ fun printProgram(program: Program) {
} }
internal fun asmGeneratorFor( internal fun asmGeneratorFor(
compTarget: ICompilationTarget,
program: Program, program: Program,
errors: IErrorReporter, errors: IErrorReporter,
zp: Zeropage,
options: CompilationOptions, options: CompilationOptions,
outputDir: Path outputDir: Path
): IAssemblyGenerator ): IAssemblyGenerator
{ {
// at the moment we only have one code generation backend (for 6502 and 65c02) if(options.experimentalCodegen) {
return AsmGen(program, errors, zp, options, compTarget, outputDir) if (options.compTarget.machine.cpu in arrayOf(CpuType.CPU6502, CpuType.CPU65c02))
return ExperimentalAsmGen6502(program, errors, options, outputDir)
} else {
if (options.compTarget.machine.cpu in arrayOf(CpuType.CPU6502, CpuType.CPU65c02))
return AsmGen6502(program, errors, options, outputDir)
}
throw NotImplementedError("no asm generator for cpu ${options.compTarget.machine.cpu}")
} }

View File

@@ -31,6 +31,7 @@ private fun compileTheThing(filepath: Path, optimize: Boolean, target: ICompilat
slowCodegenWarnings = false, slowCodegenWarnings = false,
quietAssembler = true, quietAssembler = true,
asmListfile = false, asmListfile = false,
experimentalCodegen = false,
compilationTarget = target.name, compilationTarget = target.name,
outputDir = outputDir outputDir = outputDir
) )

View File

@@ -45,6 +45,7 @@ class TestCompilerOptionSourcedirs: FunSpec({
slowCodegenWarnings = false, slowCodegenWarnings = false,
quietAssembler = true, quietAssembler = true,
asmListfile = false, asmListfile = false,
experimentalCodegen = false,
compilationTarget = Cx16Target.name, compilationTarget = Cx16Target.name,
sourceDirs, sourceDirs,
outputDir outputDir

View File

@@ -6,6 +6,7 @@ import io.kotest.core.spec.style.FunSpec
import io.kotest.matchers.shouldBe import io.kotest.matchers.shouldBe
import io.kotest.matchers.shouldNotBe import io.kotest.matchers.shouldNotBe
import io.kotest.matchers.string.shouldContain import io.kotest.matchers.string.shouldContain
import io.kotest.matchers.string.shouldNotBeBlank
import io.kotest.matchers.types.instanceOf import io.kotest.matchers.types.instanceOf
import io.kotest.matchers.types.shouldBeSameInstanceAs import io.kotest.matchers.types.shouldBeSameInstanceAs
import prog8.ast.Program import prog8.ast.Program
@@ -326,7 +327,8 @@ class TestOptimization: FunSpec({
bbAssigns1expr.inferType(result.program).getOrElse { fail("dt") } shouldBe DataType.UBYTE bbAssigns1expr.inferType(result.program).getOrElse { fail("dt") } shouldBe DataType.UBYTE
val asm = generateAssembly(result.program, options) val asm = generateAssembly(result.program, options)
asm.valid shouldBe true asm shouldNotBe null
asm!!.name.shouldNotBeBlank()
} }
test("intermediate assignment steps generated for typecasted expression") { test("intermediate assignment steps generated for typecasted expression") {
@@ -384,7 +386,8 @@ class TestOptimization: FunSpec({
value.right shouldBe instanceOf<TypecastExpression>() value.right shouldBe instanceOf<TypecastExpression>()
val asm = generateAssembly(result.program) val asm = generateAssembly(result.program)
asm.valid shouldBe true asm shouldNotBe null
asm!!.name.shouldNotBeBlank()
} }
test("unused variable removal") { test("unused variable removal") {

View File

@@ -12,7 +12,7 @@ import prog8.ast.expressions.AddressOf
import prog8.ast.expressions.IdentifierReference import prog8.ast.expressions.IdentifierReference
import prog8.ast.expressions.NumericLiteralValue import prog8.ast.expressions.NumericLiteralValue
import prog8.ast.statements.* import prog8.ast.statements.*
import prog8.codegen.cpu6502.AsmGen import prog8.codegen.cpu6502.AsmGen6502
import prog8.codegen.target.C64Target import prog8.codegen.target.C64Target
import prog8.codegen.target.c64.C64Zeropage import prog8.codegen.target.c64.C64Zeropage
import prog8.compilerinterface.CompilationOptions import prog8.compilerinterface.CompilationOptions
@@ -75,11 +75,11 @@ class TestAsmGenSymbols: StringSpec({
return Program("test", DummyFunctions, DummyMemsizer, DummyStringEncoder).addModule(module) return Program("test", DummyFunctions, DummyMemsizer, DummyStringEncoder).addModule(module)
} }
fun createTestAsmGen(program: Program): AsmGen { fun createTestAsmGen(program: Program): AsmGen6502 {
val errors = ErrorReporterForTests() val errors = ErrorReporterForTests()
val options = CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, emptyList(), false, true, C64Target) val options = CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, emptyList(), false, true, C64Target)
val zp = C64Zeropage(options) options.compTarget.machine.zeropage = C64Zeropage(options)
val asmgen = AsmGen(program, errors, zp, options, C64Target, Path.of("")) val asmgen = AsmGen6502(program, errors, options, Path.of(""))
return asmgen return asmgen
} }

View File

@@ -3,7 +3,7 @@ package prog8tests.helpers
import io.kotest.assertions.withClue import io.kotest.assertions.withClue
import io.kotest.matchers.shouldBe import io.kotest.matchers.shouldBe
import prog8.ast.Program import prog8.ast.Program
import prog8.codegen.cpu6502.AsmGen import prog8.codegen.cpu6502.AsmGen6502
import prog8.codegen.target.C64Target import prog8.codegen.target.C64Target
import prog8.codegen.target.c64.C64Zeropage import prog8.codegen.target.c64.C64Zeropage
import prog8.compiler.CompilationResult import prog8.compiler.CompilationResult
@@ -53,6 +53,7 @@ internal fun compileFile(
slowCodegenWarnings = false, slowCodegenWarnings = false,
quietAssembler = true, quietAssembler = true,
asmListfile = false, asmListfile = false,
experimentalCodegen = false,
platform.name, platform.name,
outputDir = outputDir, outputDir = outputDir,
errors = errors ?: ErrorReporterForTests() errors = errors ?: ErrorReporterForTests()
@@ -83,10 +84,9 @@ internal fun compileText(
internal fun generateAssembly( internal fun generateAssembly(
program: Program, program: Program,
options: CompilationOptions? = null options: CompilationOptions? = null
): IAssemblyProgram { ): IAssemblyProgram? {
val coptions = options ?: CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.DONTUSE, emptyList(), true, true, C64Target) val coptions = options ?: CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.DONTUSE, emptyList(), true, true, C64Target)
val zp = C64Zeropage(coptions) coptions.compTarget.machine.zeropage = C64Zeropage(coptions)
coptions.compTarget.machine.zeropage=zp val asmgen = AsmGen6502(program, ErrorReporterForTests(), coptions, outputDir)
val asmgen = AsmGen(program, ErrorReporterForTests(), zp, coptions, C64Target, outputDir)
return asmgen.compileToAssembly() return asmgen.compileToAssembly()
} }

View File

@@ -31,5 +31,6 @@ class CompilationOptions(val output: OutputType,
var optimizeFloatExpressions: Boolean = false, var optimizeFloatExpressions: Boolean = false,
var dontReinitGlobals: Boolean = false, var dontReinitGlobals: Boolean = false,
var asmQuiet: Boolean = false, var asmQuiet: Boolean = false,
var asmListfile: Boolean = false var asmListfile: Boolean = false,
var experimentalCodegen: Boolean = false
) )

View File

@@ -1,13 +1,13 @@
package prog8.compilerinterface package prog8.compilerinterface
interface IAssemblyGenerator { interface IAssemblyGenerator {
fun compileToAssembly(): IAssemblyProgram fun compileToAssembly(): IAssemblyProgram?
} }
interface IAssemblyProgram { interface IAssemblyProgram {
val valid: Boolean
val name: String val name: String
fun assemble(options: CompilationOptions): Int fun assemble(options: CompilationOptions): Boolean
} }
fun viceMonListName(baseFilename: String) = "$baseFilename.vice-mon-list" fun viceMonListName(baseFilename: String) = "$baseFilename.vice-mon-list"

View File

@@ -154,6 +154,9 @@ One or more .p8 module files
``-asmlist`` ``-asmlist``
Generate an assembler listing file as well. Generate an assembler listing file as well.
``-expericodegen``
Use experimental code generation backend (*incomplete*).
Module source code files Module source code files
------------------------ ------------------------

View File

@@ -2,12 +2,8 @@
main { main {
sub start() { sub start() {
word w1 = -10 txt.print("ok")
byte bb = 2
w1 -= bb-1 - - -
txt.print_w(w1)
txt.nl() txt.nl()
sys.wait(999) sys.wait(999)
} }
} }

View File

@@ -39,7 +39,8 @@ class RequestParser : Take {
slowCodegenWarnings = true, slowCodegenWarnings = true,
compilationTarget = "c64", compilationTarget = "c64",
quietAssembler = false, quietAssembler = false,
asmListfile = false asmListfile = false,
experimentalCodegen = false
) )
val compilationResult = compileProgram(args) val compilationResult = compileProgram(args)
return RsJson(Jsonding()) return RsJson(Jsonding())

View File

@@ -5,6 +5,7 @@ include(
':codeOptimizers', ':codeOptimizers',
':codeGenTargets', ':codeGenTargets',
':codeGenCpu6502', ':codeGenCpu6502',
':codeGenExperimental6502',
':compiler', ':compiler',
':dbusCompilerService', ':dbusCompilerService',
':httpCompilerService' ':httpCompilerService'