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.
|
// make sure that first chunks in Blocks and Subroutines share the name of the block/sub as label.
|
||||||
|
|
||||||
irProg.blocks.forEach { block ->
|
irProg.blocks.forEach { block ->
|
||||||
if(block.inlineAssembly.isNotEmpty()) {
|
if(block.inlineAssemblies.isNotEmpty()) {
|
||||||
val first = block.inlineAssembly.first()
|
val first = block.inlineAssemblies.first()
|
||||||
if(first.label==null) {
|
if(first.label==null) {
|
||||||
val replacement = IRInlineAsmChunk(block.name, first.assembly, first.isIR, first.next)
|
val replacement = IRInlineAsmChunk(block.name, first.assembly, first.isIR, first.next)
|
||||||
block.inlineAssembly.removeAt(0)
|
block.inlineAssemblies.removeAt(0)
|
||||||
block.inlineAssembly.add(0, replacement)
|
block.inlineAssemblies.add(0, replacement)
|
||||||
} else if(first.label != block.name) {
|
} else if(first.label != block.name) {
|
||||||
throw AssemblyError("first chunk in block has label that differs from block name")
|
throw AssemblyError("first chunk in block has label that differs from block name")
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,6 @@ TODO
|
|||||||
|
|
||||||
For next release
|
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)
|
- 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.
|
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
|
- 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)
|
"SUB" -> block += parseSubroutine(reader)
|
||||||
"ASMSUB" -> block += parseAsmSubroutine(reader)
|
"ASMSUB" -> block += parseAsmSubroutine(reader)
|
||||||
"INLINEASM" -> block += parseInlineAssembly(reader)
|
"INLINEASM" -> block += parseInlineAssembly(reader)
|
||||||
|
"BYTES" -> block += parseBinaryBytes(reader)
|
||||||
else -> throw IRParseException("invalid line in BLOCK: ${reader.peek()}")
|
else -> throw IRParseException("invalid line in BLOCK: ${reader.peek()}")
|
||||||
}
|
}
|
||||||
skipText(reader)
|
skipText(reader)
|
||||||
|
@ -46,7 +46,7 @@ class IRFileWriter(private val irProgram: IRProgram, outfileOverride: Path?) {
|
|||||||
private fun writeBlocks() {
|
private fun writeBlocks() {
|
||||||
irProgram.blocks.forEach { block ->
|
irProgram.blocks.forEach { block ->
|
||||||
out.write("\n<BLOCK NAME=\"${block.name}\" ADDRESS=\"${block.address?.toHex()}\" ALIGN=\"${block.alignment}\" POS=\"${block.position}\">\n")
|
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)
|
writeInlineAsm(it)
|
||||||
}
|
}
|
||||||
block.subroutines.forEach {
|
block.subroutines.forEach {
|
||||||
@ -82,6 +82,9 @@ class IRFileWriter(private val irProgram: IRProgram, outfileOverride: Path?) {
|
|||||||
writeInlineAsm(it.asmChunk)
|
writeInlineAsm(it.asmChunk)
|
||||||
out.write("</ASMSUB>\n")
|
out.write("</ASMSUB>\n")
|
||||||
}
|
}
|
||||||
|
block.inlineBinaries.forEach {
|
||||||
|
writeInlineBytes(it)
|
||||||
|
}
|
||||||
out.write("</BLOCK>\n")
|
out.write("</BLOCK>\n")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -80,8 +80,9 @@ class IRProgram(val name: String,
|
|||||||
if(globalInits.next==null) {
|
if(globalInits.next==null) {
|
||||||
val firstBlock = blocks.firstOrNull()
|
val firstBlock = blocks.firstOrNull()
|
||||||
if(firstBlock!=null) {
|
if(firstBlock!=null) {
|
||||||
if(firstBlock.inlineAssembly.isNotEmpty()) {
|
// TODO what is the first chunk in a block?
|
||||||
globalInits.next = firstBlock.inlineAssembly.first()
|
if(firstBlock.inlineAssemblies.isNotEmpty()) {
|
||||||
|
globalInits.next = firstBlock.inlineAssemblies.first()
|
||||||
} else if(firstBlock.subroutines.isNotEmpty()) {
|
} else if(firstBlock.subroutines.isNotEmpty()) {
|
||||||
val firstSub = firstBlock.subroutines.first()
|
val firstSub = firstBlock.subroutines.first()
|
||||||
if(firstSub.chunks.isNotEmpty())
|
if(firstSub.chunks.isNotEmpty())
|
||||||
@ -140,10 +141,11 @@ class IRProgram(val name: String,
|
|||||||
|
|
||||||
fun validate() {
|
fun validate() {
|
||||||
blocks.forEach { block ->
|
blocks.forEach { block ->
|
||||||
if(block.inlineAssembly.isNotEmpty()) {
|
// TODO what is the *first* chunk in the block?
|
||||||
require(block.inlineAssembly.first().label == block.name) { "first block chunk should have block name as its label" }
|
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())
|
require(chunk.instructions.isEmpty())
|
||||||
}
|
}
|
||||||
block.subroutines.forEach { sub ->
|
block.subroutines.forEach { sub ->
|
||||||
@ -187,7 +189,7 @@ class IRProgram(val name: String,
|
|||||||
|
|
||||||
globalInits.instructions.forEach { it.addUsedRegistersCounts(inputRegs, outputRegs, inputFpRegs, outputFpRegs) }
|
globalInits.instructions.forEach { it.addUsedRegistersCounts(inputRegs, outputRegs, inputFpRegs, outputFpRegs) }
|
||||||
blocks.forEach {
|
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.subroutines.flatMap { sub->sub.chunks }.forEach { chunk -> addUsed(chunk.usedRegisters()) }
|
||||||
it.asmSubroutines.forEach { asmsub -> addUsed(asmsub.usedRegisters()) }
|
it.asmSubroutines.forEach { asmsub -> addUsed(asmsub.usedRegisters()) }
|
||||||
}
|
}
|
||||||
@ -202,10 +204,11 @@ class IRBlock(
|
|||||||
val alignment: BlockAlignment,
|
val alignment: BlockAlignment,
|
||||||
val position: Position
|
val position: Position
|
||||||
) {
|
) {
|
||||||
// TODO not separate lists but just a single list of chunks, like IRSubroutine?
|
// TODO not separate lists but just a single list of chunks, like IRSubroutine? (but these are not all chunks...)
|
||||||
val inlineAssembly = mutableListOf<IRInlineAsmChunk>()
|
val inlineAssemblies = mutableListOf<IRInlineAsmChunk>()
|
||||||
val subroutines = mutableListOf<IRSubroutine>()
|
val subroutines = mutableListOf<IRSubroutine>()
|
||||||
val asmSubroutines = mutableListOf<IRAsmSubroutine>()
|
val asmSubroutines = mutableListOf<IRAsmSubroutine>()
|
||||||
|
val inlineBinaries = mutableListOf<IRInlineBinaryChunk>()
|
||||||
|
|
||||||
enum class BlockAlignment {
|
enum class BlockAlignment {
|
||||||
NONE,
|
NONE,
|
||||||
@ -217,14 +220,15 @@ class IRBlock(
|
|||||||
subroutines += sub
|
subroutines += sub
|
||||||
}
|
}
|
||||||
operator fun plusAssign(sub: IRAsmSubroutine) { asmSubroutines += sub }
|
operator fun plusAssign(sub: IRAsmSubroutine) { asmSubroutines += sub }
|
||||||
operator fun plusAssign(asm: IRInlineAsmChunk) { inlineAssembly += asm }
|
operator fun plusAssign(asm: IRInlineAsmChunk) { inlineAssemblies += asm }
|
||||||
operator fun plusAssign(binary: IRInlineBinaryChunk) { TODO("IR BLOCK can't contain inline binary data yet") }
|
operator fun plusAssign(binary: IRInlineBinaryChunk) { inlineBinaries += binary }
|
||||||
|
|
||||||
fun isEmpty(): Boolean {
|
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 noSubs = subroutines.isEmpty() || subroutines.all { it.isEmpty() }
|
||||||
val noAsmSubs = asmSubroutines.isEmpty() || asmSubroutines.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)
|
if(block.address!=null)
|
||||||
throw IRParseException("blocks cannot have a load address for vm: ${block.name}")
|
throw IRParseException("blocks cannot have a load address for vm: ${block.name}")
|
||||||
|
|
||||||
block.inlineAssembly.forEach {
|
block.inlineAssemblies.forEach {
|
||||||
val replacement = addAssemblyToProgram(it, programChunks, variableAddresses)
|
val replacement = addAssemblyToProgram(it, programChunks, variableAddresses)
|
||||||
chunkReplacements += replacement
|
chunkReplacements += replacement
|
||||||
}
|
}
|
||||||
@ -62,6 +62,9 @@ class VmProgramLoader {
|
|||||||
chunkReplacements += replacement
|
chunkReplacements += replacement
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
block.inlineBinaries.forEach {
|
||||||
|
throw IRParseException("inline binary data not yet supported in the VM") // TODO
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pass2translateSyscalls(programChunks)
|
pass2translateSyscalls(programChunks)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user