mirror of
https://github.com/irmen/prog8.git
synced 2025-01-10 20:30:23 +00:00
ir: Block can now contain inline binary
This commit is contained in:
parent
d8e785aed0
commit
d08451bccc
@ -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")
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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")
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user