mirror of
https://github.com/irmen/prog8.git
synced 2025-01-11 13:29:45 +00:00
added -sourcelines cli option to include src lines in generated assembly (which is now off by default)
This commit is contained in:
parent
ba788bcf0f
commit
a4d093afa1
@ -16,6 +16,7 @@ class CompilationOptions(val output: OutputType,
|
|||||||
var optimize: Boolean = false,
|
var optimize: Boolean = false,
|
||||||
var asmQuiet: Boolean = false,
|
var asmQuiet: Boolean = false,
|
||||||
var asmListfile: Boolean = false,
|
var asmListfile: Boolean = false,
|
||||||
|
var includeSourcelines: Boolean = false,
|
||||||
var experimentalCodegen: Boolean = false,
|
var experimentalCodegen: Boolean = false,
|
||||||
var varsHighBank: Int? = null,
|
var varsHighBank: Int? = null,
|
||||||
var splitWordArrays: Boolean = false,
|
var splitWordArrays: Boolean = false,
|
||||||
|
@ -239,7 +239,7 @@ class AsmGen6502Internal (
|
|||||||
internal fun isTargetCpu(cpu: CpuType) = options.compTarget.machine.cpu == cpu
|
internal fun isTargetCpu(cpu: CpuType) = options.compTarget.machine.cpu == cpu
|
||||||
|
|
||||||
internal fun outputSourceLine(node: PtNode) {
|
internal fun outputSourceLine(node: PtNode) {
|
||||||
if(node.position===Position.DUMMY)
|
if(!options.includeSourcelines || node.position===Position.DUMMY)
|
||||||
return
|
return
|
||||||
val srcComment = "\t; source: ${node.position.file}:${node.position.line}"
|
val srcComment = "\t; source: ${node.position.file}:${node.position.line}"
|
||||||
val line = SourceLineCache.retrieveLine(node.position)
|
val line = SourceLineCache.retrieveLine(node.position)
|
||||||
|
@ -13,7 +13,9 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express
|
|||||||
if(assignment.target.children.single() is PtMachineRegister)
|
if(assignment.target.children.single() is PtMachineRegister)
|
||||||
throw AssemblyError("assigning to a register should be done by just evaluating the expression into resultregister")
|
throw AssemblyError("assigning to a register should be done by just evaluating the expression into resultregister")
|
||||||
|
|
||||||
return translateRegularAssign(assignment)
|
val chunks = translateRegularAssign(assignment)
|
||||||
|
chunks.filterIsInstance<IRCodeChunk>().firstOrNull()?.appendSrcPosition(assignment.position)
|
||||||
|
return chunks
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun translate(augAssign: PtAugmentedAssign): IRCodeChunks {
|
internal fun translate(augAssign: PtAugmentedAssign): IRCodeChunks {
|
||||||
@ -24,7 +26,7 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express
|
|||||||
val memory = augAssign.target.memory
|
val memory = augAssign.target.memory
|
||||||
val array = augAssign.target.array
|
val array = augAssign.target.array
|
||||||
|
|
||||||
return if(ident!=null) {
|
val chunks = if(ident!=null) {
|
||||||
assignVarAugmented(ident.name, augAssign)
|
assignVarAugmented(ident.name, augAssign)
|
||||||
} else if(memory != null) {
|
} else if(memory != null) {
|
||||||
if(memory.address is PtNumber)
|
if(memory.address is PtNumber)
|
||||||
@ -39,6 +41,8 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express
|
|||||||
} else {
|
} else {
|
||||||
fallbackAssign(augAssign)
|
fallbackAssign(augAssign)
|
||||||
}
|
}
|
||||||
|
chunks.filterIsInstance<IRCodeChunk>().firstOrNull()?.appendSrcPosition(augAssign.position)
|
||||||
|
return chunks
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun assignMemoryAugmented(
|
private fun assignMemoryAugmented(
|
||||||
|
@ -289,6 +289,8 @@ class IRCodeGen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
chunks.filterIsInstance<IRCodeChunk>().firstOrNull()?.appendSrcPosition(node.position)
|
||||||
|
|
||||||
return chunks
|
return chunks
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,7 +105,10 @@ class IRPeepholeOptimizer(private val irprog: IRProgram) {
|
|||||||
|
|
||||||
relabelChunks.forEach { (index, label) ->
|
relabelChunks.forEach { (index, label) ->
|
||||||
val chunk = IRCodeChunk(label, null)
|
val chunk = IRCodeChunk(label, null)
|
||||||
chunk.instructions += sub.chunks[index].instructions
|
val subChunk = sub.chunks[index]
|
||||||
|
chunk.instructions += subChunk.instructions
|
||||||
|
if(subChunk is IRCodeChunk)
|
||||||
|
chunk.appendSrcPositions(subChunk.sourceLinesPositions)
|
||||||
sub.chunks[index] = chunk
|
sub.chunks[index] = chunk
|
||||||
}
|
}
|
||||||
removeChunks.reversed().forEach { index -> sub.chunks.removeAt(index) }
|
removeChunks.reversed().forEach { index -> sub.chunks.removeAt(index) }
|
||||||
@ -140,6 +143,8 @@ class IRPeepholeOptimizer(private val irprog: IRProgram) {
|
|||||||
if(mayJoinCodeChunks(lastChunk, candidate)) {
|
if(mayJoinCodeChunks(lastChunk, candidate)) {
|
||||||
lastChunk.instructions += candidate.instructions
|
lastChunk.instructions += candidate.instructions
|
||||||
lastChunk.next = candidate.next
|
lastChunk.next = candidate.next
|
||||||
|
if(lastChunk is IRCodeChunk)
|
||||||
|
lastChunk.appendSrcPositions(candidate.sourceLinesPositions)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
chunks += candidate
|
chunks += candidate
|
||||||
|
@ -46,11 +46,12 @@ private fun compileMain(args: Array<String>): Boolean {
|
|||||||
val outputDir by cli.option(ArgType.String, fullName = "out", description = "directory for output files instead of current directory").default(".")
|
val outputDir by cli.option(ArgType.String, fullName = "out", description = "directory for output files instead of current directory").default(".")
|
||||||
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 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 includeSourcelines by cli.option(ArgType.Boolean, fullName = "sourcelines", description = "include original Prog8 source lines in generated asm code")
|
||||||
|
val splitWordArrays by cli.option(ArgType.Boolean, fullName = "splitarrays", description = "treat all word arrays as tagged with @split to make them lsb/msb split in memory")
|
||||||
val compilationTarget by cli.option(ArgType.String, fullName = "target", description = "target output of the compiler (one of '${C64Target.NAME}', '${C128Target.NAME}', '${Cx16Target.NAME}', '${AtariTarget.NAME}', '${VMTarget.NAME}') (required)")
|
val compilationTarget by cli.option(ArgType.String, fullName = "target", description = "target output of the compiler (one of '${C64Target.NAME}', '${C128Target.NAME}', '${Cx16Target.NAME}', '${AtariTarget.NAME}', '${VMTarget.NAME}') (required)")
|
||||||
val startVm by cli.option(ArgType.Boolean, fullName = "vm", description = "load and run a .p8ir IR source file in the VM")
|
val startVm by cli.option(ArgType.Boolean, fullName = "vm", description = "load and run a .p8ir IR source file in the VM")
|
||||||
val watchMode by cli.option(ArgType.Boolean, fullName = "watch", description = "continuous compilation mode (watch for file changes)")
|
val watchMode by cli.option(ArgType.Boolean, fullName = "watch", description = "continuous compilation mode (watch for file changes)")
|
||||||
val varsHighBank by cli.option(ArgType.Int, fullName = "varshigh", description = "put uninitialized variables in high memory area instead of at the end of the program. On the cx16 target the value specifies the HiRAM bank (0=keep active), on other systems it is ignored.")
|
val varsHighBank by cli.option(ArgType.Int, fullName = "varshigh", description = "put uninitialized variables in high memory area instead of at the end of the program. On the cx16 target the value specifies the HiRAM bank (0=keep active), on other systems it is ignored.")
|
||||||
val splitWordArrays by cli.option(ArgType.Boolean, fullName = "splitarrays", description = "treat all word arrays as tagged with @split to make them lsb/msb split in memory")
|
|
||||||
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)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -114,6 +115,7 @@ private fun compileMain(args: Array<String>): Boolean {
|
|||||||
dontWriteAssembly != true,
|
dontWriteAssembly != true,
|
||||||
quietAssembler == true,
|
quietAssembler == true,
|
||||||
asmListfile == true,
|
asmListfile == true,
|
||||||
|
includeSourcelines == true,
|
||||||
experimentalCodegen == true,
|
experimentalCodegen == true,
|
||||||
varsHighBank,
|
varsHighBank,
|
||||||
compilationTarget!!,
|
compilationTarget!!,
|
||||||
@ -180,6 +182,7 @@ private fun compileMain(args: Array<String>): Boolean {
|
|||||||
dontWriteAssembly != true,
|
dontWriteAssembly != true,
|
||||||
quietAssembler == true,
|
quietAssembler == true,
|
||||||
asmListfile == true,
|
asmListfile == true,
|
||||||
|
includeSourcelines == true,
|
||||||
experimentalCodegen == true,
|
experimentalCodegen == true,
|
||||||
varsHighBank,
|
varsHighBank,
|
||||||
compilationTarget!!,
|
compilationTarget!!,
|
||||||
|
@ -32,6 +32,7 @@ class CompilerArguments(val filepath: Path,
|
|||||||
val writeAssembly: Boolean,
|
val writeAssembly: Boolean,
|
||||||
val quietAssembler: Boolean,
|
val quietAssembler: Boolean,
|
||||||
val asmListfile: Boolean,
|
val asmListfile: Boolean,
|
||||||
|
val includeSourcelines: Boolean,
|
||||||
val experimentalCodegen: Boolean,
|
val experimentalCodegen: Boolean,
|
||||||
val varsHighBank: Int?,
|
val varsHighBank: Int?,
|
||||||
val compilationTarget: String,
|
val compilationTarget: String,
|
||||||
@ -68,6 +69,7 @@ fun compileProgram(args: CompilerArguments): CompilationResult? {
|
|||||||
optimize = args.optimize
|
optimize = args.optimize
|
||||||
asmQuiet = args.quietAssembler
|
asmQuiet = args.quietAssembler
|
||||||
asmListfile = args.asmListfile
|
asmListfile = args.asmListfile
|
||||||
|
includeSourcelines = args.includeSourcelines
|
||||||
experimentalCodegen = args.experimentalCodegen
|
experimentalCodegen = args.experimentalCodegen
|
||||||
varsHighBank = args.varsHighBank
|
varsHighBank = args.varsHighBank
|
||||||
splitWordArrays = args.splitWordArrays
|
splitWordArrays = args.splitWordArrays
|
||||||
|
@ -29,6 +29,7 @@ private fun compileTheThing(filepath: Path, optimize: Boolean, target: ICompilat
|
|||||||
writeAssembly = true,
|
writeAssembly = true,
|
||||||
quietAssembler = true,
|
quietAssembler = true,
|
||||||
asmListfile = false,
|
asmListfile = false,
|
||||||
|
includeSourcelines = false,
|
||||||
experimentalCodegen = false,
|
experimentalCodegen = false,
|
||||||
varsHighBank = null,
|
varsHighBank = null,
|
||||||
compilationTarget = target.name,
|
compilationTarget = target.name,
|
||||||
|
@ -46,6 +46,7 @@ class TestCompilerOptionSourcedirs: FunSpec({
|
|||||||
writeAssembly = true,
|
writeAssembly = true,
|
||||||
quietAssembler = true,
|
quietAssembler = true,
|
||||||
asmListfile = false,
|
asmListfile = false,
|
||||||
|
includeSourcelines = false,
|
||||||
experimentalCodegen = false,
|
experimentalCodegen = false,
|
||||||
varsHighBank = null,
|
varsHighBank = null,
|
||||||
compilationTarget = Cx16Target.NAME,
|
compilationTarget = Cx16Target.NAME,
|
||||||
|
@ -26,6 +26,7 @@ internal fun compileFile(
|
|||||||
writeAssembly = writeAssembly,
|
writeAssembly = writeAssembly,
|
||||||
quietAssembler = true,
|
quietAssembler = true,
|
||||||
asmListfile = false,
|
asmListfile = false,
|
||||||
|
includeSourcelines = false,
|
||||||
experimentalCodegen = false,
|
experimentalCodegen = false,
|
||||||
varsHighBank = null,
|
varsHighBank = null,
|
||||||
platform.name,
|
platform.name,
|
||||||
|
@ -160,6 +160,11 @@ One or more .p8 module files
|
|||||||
``-expericodegen``
|
``-expericodegen``
|
||||||
Use experimental code generation backend (*incomplete*).
|
Use experimental code generation backend (*incomplete*).
|
||||||
|
|
||||||
|
``-sourcelines``
|
||||||
|
Also include the original prog8 source code lines as comments in the generated assembly code file,
|
||||||
|
mixed in between the actual generated assembly code.
|
||||||
|
This can be useful for debugging purposes to see what assembly was generated for what prog8 source code.
|
||||||
|
|
||||||
``-splitarrays``
|
``-splitarrays``
|
||||||
Treat all word arrays as tagged with @split so they are all lsb/msb split into memory.
|
Treat all word arrays as tagged with @split so they are all lsb/msb split into memory.
|
||||||
This removes the need to add @split yourself but some programs may fail to compile with
|
This removes the need to add @split yourself but some programs may fail to compile with
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
TODO
|
TODO
|
||||||
====
|
====
|
||||||
|
|
||||||
- add command line option to enable/disable the inclusion of p8 source lines into the generated assembly / p8ir see outputSourceLine()
|
|
||||||
- add a mechanism to pass the original p8 source lines into the p8ir file as comments. Remove the position xml tags.
|
|
||||||
- try to reduce the number of uses of temp variables for example in array[idx] -= amount /
|
- try to reduce the number of uses of temp variables for example in array[idx] -= amount /
|
||||||
- investigate McCarthy evaluation again? this may also reduce code size perhaps for things like if a>4 or a<2 .... / - investigate McCarthy evaluation again? this may also reduce code size perhaps for things like if a>4 or a<2 ....
|
- investigate McCarthy evaluation again? this may also reduce code size perhaps for things like if a>4 or a<2 .... / - investigate McCarthy evaluation again? this may also reduce code size perhaps for things like if a>4 or a<2 ....
|
||||||
|
|
||||||
|
@ -37,6 +37,7 @@ class RequestParser : Take {
|
|||||||
compilationTarget = "c64",
|
compilationTarget = "c64",
|
||||||
symbolDefs = emptyMap(),
|
symbolDefs = emptyMap(),
|
||||||
quietAssembler = false,
|
quietAssembler = false,
|
||||||
|
includeSourcelines = false,
|
||||||
asmListfile = false,
|
asmListfile = false,
|
||||||
experimentalCodegen = false,
|
experimentalCodegen = false,
|
||||||
splitWordArrays = false,
|
splitWordArrays = false,
|
||||||
|
@ -294,6 +294,11 @@ class IRFileReader {
|
|||||||
skipText(reader)
|
skipText(reader)
|
||||||
val start = reader.nextEvent().asStartElement()
|
val start = reader.nextEvent().asStartElement()
|
||||||
require(start.name.localPart=="CODE") { "missing CODE" }
|
require(start.name.localPart=="CODE") { "missing CODE" }
|
||||||
|
val next = reader.peek()
|
||||||
|
if(next.isStartElement && next.asStartElement().name.localPart=="P8SRC") {
|
||||||
|
reader.nextEvent() // skip the P8SRC node
|
||||||
|
while(!reader.nextEvent().isEndElement) { /* skip until end of P8SRC node */ }
|
||||||
|
}
|
||||||
val label = start.attributes.asSequence().singleOrNull { it.name.localPart == "LABEL" }?.value?.ifBlank { null }
|
val label = start.attributes.asSequence().singleOrNull { it.name.localPart == "LABEL" }?.value?.ifBlank { null }
|
||||||
val text = readText(reader).trim()
|
val text = readText(reader).trim()
|
||||||
val chunk = IRCodeChunk(label, null)
|
val chunk = IRCodeChunk(label, null)
|
||||||
|
@ -3,6 +3,7 @@ package prog8.intermediate
|
|||||||
import prog8.code.core.*
|
import prog8.code.core.*
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
import javax.xml.stream.XMLOutputFactory
|
import javax.xml.stream.XMLOutputFactory
|
||||||
|
import javax.xml.stream.XMLStreamWriter
|
||||||
import kotlin.io.path.bufferedWriter
|
import kotlin.io.path.bufferedWriter
|
||||||
import kotlin.io.path.div
|
import kotlin.io.path.div
|
||||||
|
|
||||||
@ -126,6 +127,7 @@ class IRFileWriter(private val irProgram: IRProgram, outfileOverride: Path?) {
|
|||||||
xml.writeStartElement("CODE")
|
xml.writeStartElement("CODE")
|
||||||
chunk.label?.let { xml.writeAttribute("LABEL", chunk.label) }
|
chunk.label?.let { xml.writeAttribute("LABEL", chunk.label) }
|
||||||
// xml.writeAttribute("used-registers", chunk.usedRegisters().toString())
|
// xml.writeAttribute("used-registers", chunk.usedRegisters().toString())
|
||||||
|
writeSourcelines(xml, chunk)
|
||||||
xml.writeCharacters("\n")
|
xml.writeCharacters("\n")
|
||||||
chunk.instructions.forEach { instr ->
|
chunk.instructions.forEach { instr ->
|
||||||
numInstr++
|
numInstr++
|
||||||
@ -136,6 +138,23 @@ class IRFileWriter(private val irProgram: IRProgram, outfileOverride: Path?) {
|
|||||||
xml.writeCharacters("\n")
|
xml.writeCharacters("\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun writeSourcelines(xml: XMLStreamWriter, code: IRCodeChunk) {
|
||||||
|
if(irProgram.options.includeSourcelines) {
|
||||||
|
if(code.sourceLinesPositions.any {it !== Position.DUMMY}) {
|
||||||
|
xml.writeStartElement("P8SRC")
|
||||||
|
var sourceTxt = StringBuilder("\n")
|
||||||
|
code.sourceLinesPositions.forEach { pos ->
|
||||||
|
val line = SourceLineCache.retrieveLine(pos)
|
||||||
|
if(line!=null) {
|
||||||
|
sourceTxt.append("$pos $line\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
xml.writeCData(sourceTxt.toString())
|
||||||
|
xml.writeEndElement()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun writeInlineBytes(chunk: IRInlineBinaryChunk) {
|
private fun writeInlineBytes(chunk: IRInlineBinaryChunk) {
|
||||||
xml.writeStartElement("BYTES")
|
xml.writeStartElement("BYTES")
|
||||||
chunk.label?.let { xml.writeAttribute("LABEL", chunk.label) }
|
chunk.label?.let { xml.writeAttribute("LABEL", chunk.label) }
|
||||||
|
@ -447,6 +447,17 @@ class IRCodeChunk(label: String?, next: IRCodeChunkBase?): IRCodeChunkBase(label
|
|||||||
operator fun plusAssign(chunk: IRCodeChunkBase) {
|
operator fun plusAssign(chunk: IRCodeChunkBase) {
|
||||||
instructions.addAll(chunk.instructions)
|
instructions.addAll(chunk.instructions)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun appendSrcPosition(position: Position) {
|
||||||
|
if(sourceLinesPositions.lastOrNull()!=position)
|
||||||
|
sourceLinesPositions.add(position)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun appendSrcPositions(positions: Collection<Position>) {
|
||||||
|
positions.forEach { appendSrcPosition(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
val sourceLinesPositions = mutableListOf<Position>()
|
||||||
}
|
}
|
||||||
|
|
||||||
class IRInlineAsmChunk(label: String?,
|
class IRInlineAsmChunk(label: String?,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user