mirror of
https://github.com/irmen/prog8.git
synced 2025-07-24 20:24:09 +00:00
added experimental codegen backend option
This commit is contained in:
1
.idea/modules.xml
generated
1
.idea/modules.xml
generated
@@ -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" />
|
||||||
|
@@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@@ -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() {
|
||||||
|
@@ -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)
|
||||||
|
@@ -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) {
|
||||||
|
@@ -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)
|
||||||
|
@@ -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)
|
||||||
|
@@ -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
|
||||||
|
@@ -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)
|
||||||
|
@@ -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)
|
||||||
|
|
||||||
|
@@ -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)
|
||||||
|
46
codeGenExperimental6502/build.gradle
Normal file
46
codeGenExperimental6502/build.gradle
Normal 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!
|
16
codeGenExperimental6502/codeGenExperimental6502.iml
Normal file
16
codeGenExperimental6502/codeGenExperimental6502.iml
Normal 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>
|
@@ -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
|
||||||
|
}
|
||||||
|
}
|
@@ -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")
|
||||||
|
}
|
||||||
|
}
|
@@ -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"
|
||||||
|
@@ -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>
|
@@ -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
|
||||||
|
@@ -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}")
|
||||||
}
|
}
|
||||||
|
@@ -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
|
||||||
)
|
)
|
||||||
|
@@ -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
|
||||||
|
@@ -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") {
|
||||||
|
@@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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()
|
||||||
}
|
}
|
||||||
|
@@ -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
|
||||||
)
|
)
|
||||||
|
@@ -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"
|
||||||
|
@@ -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
|
||||||
------------------------
|
------------------------
|
||||||
|
@@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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())
|
||||||
|
@@ -5,6 +5,7 @@ include(
|
|||||||
':codeOptimizers',
|
':codeOptimizers',
|
||||||
':codeGenTargets',
|
':codeGenTargets',
|
||||||
':codeGenCpu6502',
|
':codeGenCpu6502',
|
||||||
|
':codeGenExperimental6502',
|
||||||
':compiler',
|
':compiler',
|
||||||
':dbusCompilerService',
|
':dbusCompilerService',
|
||||||
':httpCompilerService'
|
':httpCompilerService'
|
||||||
|
Reference in New Issue
Block a user