mirror of
https://github.com/irmen/prog8.git
synced 2024-12-23 09:32:43 +00:00
added -asmlist cli option to produce assembler listing output
This commit is contained in:
parent
b62183adcb
commit
5267e06969
@ -2,7 +2,7 @@ package prog8.codegen.target.c64
|
||||
|
||||
import prog8.ast.base.DataType
|
||||
import prog8.codegen.target.cbm.Mflpt5
|
||||
import prog8.codegen.target.cbm.viceMonListPostfix
|
||||
import prog8.codegen.target.cbm.viceMonListName
|
||||
import prog8.compilerinterface.*
|
||||
import java.io.IOException
|
||||
import java.nio.file.Path
|
||||
@ -42,7 +42,8 @@ class C64MachineDefinition: IMachineDefinition {
|
||||
|
||||
for(emulator in listOf("x64sc", "x64")) {
|
||||
println("\nStarting C-64 emulator $emulator...")
|
||||
val cmdline = listOf(emulator, "-silent", "-moncommands", "${programNameWithPath}.$viceMonListPostfix",
|
||||
val viceMonlist = viceMonListName(programNameWithPath.toString())
|
||||
val cmdline = listOf(emulator, "-silent", "-moncommands", viceMonlist,
|
||||
"-autostartprgmode", "1", "-autostart-warp", "-autostart", "${programNameWithPath}.prg")
|
||||
val processb = ProcessBuilder(cmdline).inheritIO()
|
||||
val process: Process
|
||||
|
@ -14,7 +14,7 @@ import kotlin.io.path.Path
|
||||
import kotlin.io.path.isRegularFile
|
||||
|
||||
|
||||
internal const val viceMonListPostfix = "vice-mon-list"
|
||||
internal fun viceMonListName(baseFilename: String) = "$baseFilename.vice-mon-list"
|
||||
|
||||
class AssemblyProgram(
|
||||
override val valid: Boolean,
|
||||
@ -25,17 +25,22 @@ class AssemblyProgram(
|
||||
private val assemblyFile = outputDir.resolve("$name.asm")
|
||||
private val prgFile = outputDir.resolve("$name.prg")
|
||||
private val binFile = outputDir.resolve("$name.bin")
|
||||
private val viceMonListFile = outputDir.resolve("$name.$viceMonListPostfix")
|
||||
private val viceMonListFile = outputDir.resolve(viceMonListName(name))
|
||||
private val listFile = outputDir.resolve("$name.list")
|
||||
|
||||
override fun assemble(quiet: Boolean, options: CompilationOptions): Int {
|
||||
override fun assemble(options: CompilationOptions): Int {
|
||||
// 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",
|
||||
"-Wall", "-Wno-strict-bool", "-Wno-shadow", // "-Werror",
|
||||
"--dump-labels", "--vice-labels", "-l", viceMonListFile.toString(), "--no-monitor")
|
||||
"--dump-labels", "--vice-labels", "--labels=$viceMonListFile", "--no-monitor"
|
||||
)
|
||||
|
||||
if(quiet)
|
||||
if(options.asmQuiet)
|
||||
command.add("--quiet")
|
||||
|
||||
if(options.asmListfile)
|
||||
command.add("--list=$listFile")
|
||||
|
||||
val outFile = when (options.output) {
|
||||
OutputType.PRG -> {
|
||||
command.add("--cbm-prg")
|
||||
|
@ -2,7 +2,7 @@ package prog8.codegen.target.cx16
|
||||
|
||||
import prog8.ast.base.DataType
|
||||
import prog8.codegen.target.cbm.Mflpt5
|
||||
import prog8.codegen.target.cbm.viceMonListPostfix
|
||||
import prog8.codegen.target.cbm.viceMonListName
|
||||
import prog8.compilerinterface.*
|
||||
import java.io.IOException
|
||||
import java.nio.file.Path
|
||||
@ -44,7 +44,7 @@ class CX16MachineDefinition: IMachineDefinition {
|
||||
}
|
||||
2 -> {
|
||||
emulatorName = "box16"
|
||||
extraArgs = listOf("-sym", "${programNameWithPath}.$viceMonListPostfix")
|
||||
extraArgs = listOf("-sym", viceMonListName(programNameWithPath.toString()))
|
||||
}
|
||||
else -> {
|
||||
System.err.println("Cx16 target only supports x16emu and box16 emulators.")
|
||||
|
@ -40,6 +40,7 @@ private fun compileMain(args: Array<String>): Boolean {
|
||||
val watchMode by cli.option(ArgType.Boolean, fullName = "watch", description = "continuous compilation mode (watches for file changes), greatly increases compilation speed")
|
||||
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 asmListfile by cli.option(ArgType.Boolean, fullName = "asmlist", description = "make the assembler produce a listing file as well")
|
||||
val compilationTarget by cli.option(ArgType.String, fullName = "target", description = "target output of the compiler, currently '${C64Target.name}' and '${Cx16Target.name}' available").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 moduleFiles by cli.argument(ArgType.String, fullName = "modules", description = "main module file(s) to compile").multiple(999)
|
||||
@ -88,6 +89,7 @@ private fun compileMain(args: Array<String>): Boolean {
|
||||
dontWriteAssembly != true,
|
||||
slowCodegenWarnings == true,
|
||||
quietAssembler == true,
|
||||
asmListfile == true,
|
||||
compilationTarget,
|
||||
srcdirs,
|
||||
outputPath
|
||||
@ -136,6 +138,7 @@ private fun compileMain(args: Array<String>): Boolean {
|
||||
dontWriteAssembly != true,
|
||||
slowCodegenWarnings == true,
|
||||
quietAssembler == true,
|
||||
asmListfile == true,
|
||||
compilationTarget,
|
||||
srcdirs,
|
||||
outputPath
|
||||
|
@ -34,6 +34,7 @@ class CompilerArguments(val filepath: Path,
|
||||
val writeAssembly: Boolean,
|
||||
val slowCodegenWarnings: Boolean,
|
||||
val quietAssembler: Boolean,
|
||||
val asmListfile: Boolean,
|
||||
val compilationTarget: String,
|
||||
val sourceDirs: List<String> = emptyList(),
|
||||
val outputDir: Path = Path(""),
|
||||
@ -59,9 +60,11 @@ fun compileProgram(args: CompilerArguments): CompilationResult {
|
||||
// import main module and everything it needs
|
||||
val (programresult, compilationOptions, imported) = parseImports(args.filepath, args.errors, compTarget, args.sourceDirs)
|
||||
with(compilationOptions) {
|
||||
this.slowCodegenWarnings = args.slowCodegenWarnings
|
||||
this.optimize = args.optimize
|
||||
this.optimizeFloatExpressions = optimizeFloatExpr
|
||||
slowCodegenWarnings = args.slowCodegenWarnings
|
||||
optimize = args.optimize
|
||||
optimizeFloatExpressions = optimizeFloatExpr
|
||||
asmQuiet = args.quietAssembler
|
||||
asmListfile = args.asmListfile
|
||||
}
|
||||
program = programresult
|
||||
importedFiles = imported
|
||||
@ -84,7 +87,7 @@ fun compileProgram(args: CompilerArguments): CompilationResult {
|
||||
// printProgram(program)
|
||||
|
||||
if (args.writeAssembly) {
|
||||
when (val result = writeAssembly(program, args.errors, args.outputDir, args.quietAssembler, compilationOptions)) {
|
||||
when (val result = writeAssembly(program, args.errors, args.outputDir, compilationOptions)) {
|
||||
is WriteAssemblyResult.Ok -> programName = result.filename
|
||||
is WriteAssemblyResult.Fail -> {
|
||||
System.err.println(result.error)
|
||||
@ -326,7 +329,6 @@ private sealed class WriteAssemblyResult {
|
||||
private fun writeAssembly(program: Program,
|
||||
errors: IErrorReporter,
|
||||
outputDir: Path,
|
||||
quietAssembler: Boolean,
|
||||
compilerOptions: CompilationOptions
|
||||
): WriteAssemblyResult {
|
||||
// asm generation directly from the Ast
|
||||
@ -346,7 +348,7 @@ private fun writeAssembly(program: Program,
|
||||
errors.report()
|
||||
|
||||
return if(assembly.valid && errors.noErrors()) {
|
||||
val assemblerReturnStatus = assembly.assemble(quietAssembler, compilerOptions)
|
||||
val assemblerReturnStatus = assembly.assemble(compilerOptions)
|
||||
if(assemblerReturnStatus!=0)
|
||||
WriteAssemblyResult.Fail("assembler step failed with return code $assemblerReturnStatus")
|
||||
else {
|
||||
|
@ -209,9 +209,9 @@ internal class ParentNodeChecker: AstWalker() {
|
||||
return noModifications
|
||||
}
|
||||
|
||||
override fun before(`when`: When, parent: Node): Iterable<IAstModification> {
|
||||
if(`when`.parent!==parent)
|
||||
throw FatalAstException("parent node mismatch at $`when`")
|
||||
override fun before(whenStmt: When, parent: Node): Iterable<IAstModification> {
|
||||
if(whenStmt.parent!==parent)
|
||||
throw FatalAstException("parent node mismatch at $whenStmt")
|
||||
return noModifications
|
||||
}
|
||||
|
||||
|
@ -262,19 +262,19 @@ internal class StatementReorderer(val program: Program,
|
||||
return noModifications
|
||||
}
|
||||
|
||||
override fun after(`when`: When, parent: Node): Iterable<IAstModification> {
|
||||
val lastChoiceValues = `when`.choices.lastOrNull()?.values
|
||||
override fun after(whenStmt: When, parent: Node): Iterable<IAstModification> {
|
||||
val lastChoiceValues = whenStmt.choices.lastOrNull()?.values
|
||||
if(lastChoiceValues?.isNotEmpty()==true) {
|
||||
val elseChoice = `when`.choices.indexOfFirst { it.values==null || it.values?.isEmpty()==true }
|
||||
val elseChoice = whenStmt.choices.indexOfFirst { it.values==null || it.values?.isEmpty()==true }
|
||||
if(elseChoice>=0)
|
||||
errors.err("else choice must be the last one", `when`.choices[elseChoice].position)
|
||||
errors.err("else choice must be the last one", whenStmt.choices[elseChoice].position)
|
||||
}
|
||||
|
||||
val choices = `when`.choiceValues(program).sortedBy {
|
||||
val choices = whenStmt.choiceValues(program).sortedBy {
|
||||
it.first?.first() ?: Int.MAX_VALUE
|
||||
}
|
||||
`when`.choices.clear()
|
||||
choices.mapTo(`when`.choices) { it.second }
|
||||
whenStmt.choices.clear()
|
||||
choices.mapTo(whenStmt.choices) { it.second }
|
||||
return noModifications
|
||||
}
|
||||
|
||||
|
@ -30,6 +30,7 @@ private fun compileTheThing(filepath: Path, optimize: Boolean, target: ICompilat
|
||||
writeAssembly = true,
|
||||
slowCodegenWarnings = false,
|
||||
quietAssembler = true,
|
||||
asmListfile = false,
|
||||
compilationTarget = target.name,
|
||||
outputDir = outputDir
|
||||
)
|
||||
|
@ -44,6 +44,7 @@ class TestCompilerOptionSourcedirs: FunSpec({
|
||||
writeAssembly = true,
|
||||
slowCodegenWarnings = false,
|
||||
quietAssembler = true,
|
||||
asmListfile = false,
|
||||
compilationTarget = Cx16Target.name,
|
||||
sourceDirs,
|
||||
outputDir
|
||||
|
@ -51,6 +51,7 @@ internal fun compileFile(
|
||||
writeAssembly = writeAssembly,
|
||||
slowCodegenWarnings = false,
|
||||
quietAssembler = true,
|
||||
asmListfile = false,
|
||||
platform.name,
|
||||
outputDir = outputDir,
|
||||
errors = errors ?: ErrorReporterForTests()
|
||||
|
@ -428,12 +428,12 @@ class AstToSourceTextConverter(val output: (text: String) -> Unit, val program:
|
||||
outputlni("}}")
|
||||
}
|
||||
|
||||
override fun visit(`when`: When) {
|
||||
override fun visit(whenStmt: When) {
|
||||
output("when ")
|
||||
`when`.condition.accept(this)
|
||||
whenStmt.condition.accept(this)
|
||||
outputln(" {")
|
||||
scopelevel++
|
||||
`when`.choices.forEach { it.accept(this) }
|
||||
whenStmt.choices.forEach { it.accept(this) }
|
||||
scopelevel--
|
||||
outputlni("}")
|
||||
}
|
||||
|
@ -1055,7 +1055,7 @@ class ContainmentCheck(var element: Expression,
|
||||
override fun referencesIdentifier(nameInSource: List<String>): Boolean {
|
||||
if(element is IdentifierReference)
|
||||
return element.referencesIdentifier(nameInSource)
|
||||
return iterable?.referencesIdentifier(nameInSource) ?: false
|
||||
return iterable.referencesIdentifier(nameInSource)
|
||||
}
|
||||
|
||||
override fun inferType(program: Program) = InferredTypes.knownFor(DataType.UBYTE)
|
||||
|
@ -28,7 +28,7 @@ interface IAstVisitor {
|
||||
|
||||
fun visit(containment: ContainmentCheck) {
|
||||
containment.element.accept(this)
|
||||
containment.iterable?.accept(this)
|
||||
containment.iterable.accept(this)
|
||||
}
|
||||
|
||||
fun visit(block: Block) {
|
||||
@ -172,9 +172,9 @@ interface IAstVisitor {
|
||||
fun visit(nop: Nop) {
|
||||
}
|
||||
|
||||
fun visit(`when`: When) {
|
||||
`when`.condition.accept(this)
|
||||
`when`.choices.forEach { it.accept(this) }
|
||||
fun visit(whenStmt: When) {
|
||||
whenStmt.condition.accept(this)
|
||||
whenStmt.choices.forEach { it.accept(this) }
|
||||
}
|
||||
|
||||
fun visit(whenChoice: WhenChoice) {
|
||||
|
@ -28,5 +28,7 @@ class CompilationOptions(val output: OutputType,
|
||||
// these are set based on command line arguments:
|
||||
var slowCodegenWarnings: Boolean = false,
|
||||
var optimize: Boolean = false,
|
||||
var optimizeFloatExpressions: Boolean = false
|
||||
var optimizeFloatExpressions: Boolean = false,
|
||||
var asmQuiet: Boolean = false,
|
||||
var asmListfile: Boolean = false
|
||||
)
|
||||
|
@ -11,5 +11,5 @@ const val subroutineFloatEvalResultVar2 = "_prog8_float_eval_result2"
|
||||
interface IAssemblyProgram {
|
||||
val valid: Boolean
|
||||
val name: String
|
||||
fun assemble(quiet: Boolean, options: CompilationOptions): Int
|
||||
fun assemble(options: CompilationOptions): Int
|
||||
}
|
||||
|
@ -144,6 +144,9 @@ One or more .p8 module files
|
||||
``-quietasm``
|
||||
Don't print assembler output results.
|
||||
|
||||
``-asmlist``
|
||||
Generate an assembler listing file as well.
|
||||
|
||||
|
||||
Module source code files
|
||||
------------------------
|
||||
|
@ -3,7 +3,7 @@ TODO
|
||||
|
||||
For next compiler release (7.6)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
- make (an option) to let 64tass produce a listing file as well as output.
|
||||
...
|
||||
|
||||
|
||||
Blocked by an official Commander-x16 v39 release
|
||||
|
@ -37,7 +37,8 @@ class RequestParser : Take {
|
||||
writeAssembly = true,
|
||||
slowCodegenWarnings = true,
|
||||
compilationTarget = "c64",
|
||||
quietAssembler = false
|
||||
quietAssembler = false,
|
||||
asmListfile = false
|
||||
)
|
||||
val compilationResult = compileProgram(args)
|
||||
return RsJson(Jsonding())
|
||||
|
Loading…
Reference in New Issue
Block a user