ir: Block can now contain inline binary

This commit is contained in:
Irmen de Jong 2022-11-12 20:17:23 +01:00
parent d8e785aed0
commit d08451bccc
6 changed files with 29 additions and 19 deletions

View File

@ -75,12 +75,12 @@ class IRCodeGen(
// make sure that first chunks in Blocks and Subroutines share the name of the block/sub as label.
irProg.blocks.forEach { block ->
if(block.inlineAssembly.isNotEmpty()) {
val first = block.inlineAssembly.first()
if(block.inlineAssemblies.isNotEmpty()) {
val first = block.inlineAssemblies.first()
if(first.label==null) {
val replacement = IRInlineAsmChunk(block.name, first.assembly, first.isIR, first.next)
block.inlineAssembly.removeAt(0)
block.inlineAssembly.add(0, replacement)
block.inlineAssemblies.removeAt(0)
block.inlineAssemblies.add(0, replacement)
} else if(first.label != block.name) {
throw AssemblyError("first chunk in block has label that differs from block name")
}

View File

@ -3,7 +3,6 @@ TODO
For next release
^^^^^^^^^^^^^^^^
- IRBlock should be able to contain inline binary data (with optional label etc)
- 6502 codegen: make it possible to use cpu opcodes such as 'nop' as variable names by prefixing all asm vars with something such as ``p8v_``? Or not worth it (most 3 letter opcodes as variables are nonsensical anyway)
then we can get rid of the instruction lists in the machinedefinitions as well. This is already no problem at all in the IR codegen.
- create BSS section in output program and put StStaticVariables in there with bss=true. Don't forget to add init code to zero out everything that was put in bss. If array in bss->only zero ONCE! So requires self-modifying code

View File

@ -320,6 +320,7 @@ class IRFileReader {
"SUB" -> block += parseSubroutine(reader)
"ASMSUB" -> block += parseAsmSubroutine(reader)
"INLINEASM" -> block += parseInlineAssembly(reader)
"BYTES" -> block += parseBinaryBytes(reader)
else -> throw IRParseException("invalid line in BLOCK: ${reader.peek()}")
}
skipText(reader)

View File

@ -46,7 +46,7 @@ class IRFileWriter(private val irProgram: IRProgram, outfileOverride: Path?) {
private fun writeBlocks() {
irProgram.blocks.forEach { block ->
out.write("\n<BLOCK NAME=\"${block.name}\" ADDRESS=\"${block.address?.toHex()}\" ALIGN=\"${block.alignment}\" POS=\"${block.position}\">\n")
block.inlineAssembly.forEach {
block.inlineAssemblies.forEach {
writeInlineAsm(it)
}
block.subroutines.forEach {
@ -82,6 +82,9 @@ class IRFileWriter(private val irProgram: IRProgram, outfileOverride: Path?) {
writeInlineAsm(it.asmChunk)
out.write("</ASMSUB>\n")
}
block.inlineBinaries.forEach {
writeInlineBytes(it)
}
out.write("</BLOCK>\n")
}
}

View File

@ -80,8 +80,9 @@ class IRProgram(val name: String,
if(globalInits.next==null) {
val firstBlock = blocks.firstOrNull()
if(firstBlock!=null) {
if(firstBlock.inlineAssembly.isNotEmpty()) {
globalInits.next = firstBlock.inlineAssembly.first()
// TODO what is the first chunk in a block?
if(firstBlock.inlineAssemblies.isNotEmpty()) {
globalInits.next = firstBlock.inlineAssemblies.first()
} else if(firstBlock.subroutines.isNotEmpty()) {
val firstSub = firstBlock.subroutines.first()
if(firstSub.chunks.isNotEmpty())
@ -140,10 +141,11 @@ class IRProgram(val name: String,
fun validate() {
blocks.forEach { block ->
if(block.inlineAssembly.isNotEmpty()) {
require(block.inlineAssembly.first().label == block.name) { "first block chunk should have block name as its label" }
// TODO what is the *first* chunk in the block?
if(block.inlineAssemblies.isNotEmpty()) {
require(block.inlineAssemblies.first().label == block.name) { "first block chunk should have block name as its label" }
}
block.inlineAssembly.forEach { chunk ->
block.inlineAssemblies.forEach { chunk ->
require(chunk.instructions.isEmpty())
}
block.subroutines.forEach { sub ->
@ -187,7 +189,7 @@ class IRProgram(val name: String,
globalInits.instructions.forEach { it.addUsedRegistersCounts(inputRegs, outputRegs, inputFpRegs, outputFpRegs) }
blocks.forEach {
it.inlineAssembly.forEach { chunk -> addUsed(chunk.usedRegisters()) }
it.inlineAssemblies.forEach { chunk -> addUsed(chunk.usedRegisters()) }
it.subroutines.flatMap { sub->sub.chunks }.forEach { chunk -> addUsed(chunk.usedRegisters()) }
it.asmSubroutines.forEach { asmsub -> addUsed(asmsub.usedRegisters()) }
}
@ -202,10 +204,11 @@ class IRBlock(
val alignment: BlockAlignment,
val position: Position
) {
// TODO not separate lists but just a single list of chunks, like IRSubroutine?
val inlineAssembly = mutableListOf<IRInlineAsmChunk>()
// TODO not separate lists but just a single list of chunks, like IRSubroutine? (but these are not all chunks...)
val inlineAssemblies = mutableListOf<IRInlineAsmChunk>()
val subroutines = mutableListOf<IRSubroutine>()
val asmSubroutines = mutableListOf<IRAsmSubroutine>()
val inlineBinaries = mutableListOf<IRInlineBinaryChunk>()
enum class BlockAlignment {
NONE,
@ -217,14 +220,15 @@ class IRBlock(
subroutines += sub
}
operator fun plusAssign(sub: IRAsmSubroutine) { asmSubroutines += sub }
operator fun plusAssign(asm: IRInlineAsmChunk) { inlineAssembly += asm }
operator fun plusAssign(binary: IRInlineBinaryChunk) { TODO("IR BLOCK can't contain inline binary data yet") }
operator fun plusAssign(asm: IRInlineAsmChunk) { inlineAssemblies += asm }
operator fun plusAssign(binary: IRInlineBinaryChunk) { inlineBinaries += binary }
fun isEmpty(): Boolean {
val noAsm = inlineAssembly.isEmpty() || inlineAssembly.all { it.isEmpty() }
val noAsm = inlineAssemblies.isEmpty() || inlineAssemblies.all { it.isEmpty() }
val noSubs = subroutines.isEmpty() || subroutines.all { it.isEmpty() }
val noAsmSubs = asmSubroutines.isEmpty() || asmSubroutines.all { it.isEmpty() }
return noAsm && noSubs && noAsmSubs
val noBins = inlineBinaries.isEmpty() || inlineBinaries.all { it.isEmpty() }
return noAsm && noSubs && noAsmSubs && noBins
}
}

View File

@ -37,7 +37,7 @@ class VmProgramLoader {
if(block.address!=null)
throw IRParseException("blocks cannot have a load address for vm: ${block.name}")
block.inlineAssembly.forEach {
block.inlineAssemblies.forEach {
val replacement = addAssemblyToProgram(it, programChunks, variableAddresses)
chunkReplacements += replacement
}
@ -62,6 +62,9 @@ class VmProgramLoader {
chunkReplacements += replacement
}
}
block.inlineBinaries.forEach {
throw IRParseException("inline binary data not yet supported in the VM") // TODO
}
}
pass2translateSyscalls(programChunks)