mirror of
https://github.com/irmen/prog8.git
synced 2024-10-07 00:55:33 +00:00
ir: fix asmsub contents not appearing in IR file
This commit is contained in:
parent
b22804efaf
commit
e67c05c274
@ -56,6 +56,15 @@ class IRCodeGen(
|
||||
if(options.optimize) {
|
||||
val optimizer = IRPeepholeOptimizer(irProg)
|
||||
optimizer.optimize()
|
||||
|
||||
// TODO FIX & REENABLE:
|
||||
// val remover = IRUnusedCodeRemover(irProg, errors)
|
||||
// do {
|
||||
// val numRemoved = remover.optimize()
|
||||
// } while(numRemoved>0 && errors.noErrors())
|
||||
//
|
||||
// errors.report()
|
||||
|
||||
irProg.linkChunks() // re-link
|
||||
}
|
||||
|
||||
@ -249,6 +258,7 @@ class IRCodeGen(
|
||||
sub.retvalRegisters,
|
||||
sub.inline,
|
||||
sub.position)
|
||||
renamedSub.add(sub.children.single())
|
||||
parent.children.remove(sub)
|
||||
parent.add(renamedSub)
|
||||
}
|
||||
@ -1082,9 +1092,9 @@ class IRCodeGen(
|
||||
irBlock += sub
|
||||
}
|
||||
is PtAsmSub -> {
|
||||
val assemblyChild = if(child.children.isEmpty()) null else (child.children.single() as PtInlineAssembly)
|
||||
val assemblyChild = child.children.single() as PtInlineAssembly
|
||||
val asmChunk = IRInlineAsmChunk(
|
||||
child.name, assemblyChild?.assembly ?: "", assemblyChild?.isIR==true, child.position, null
|
||||
child.name, assemblyChild.assembly, assemblyChild.isIR, child.position, null
|
||||
)
|
||||
irBlock += IRAsmSubroutine(
|
||||
child.name,
|
||||
|
@ -27,6 +27,8 @@ internal class IRPeepholeOptimizer(private val irprog: IRProgram) {
|
||||
}
|
||||
removeEmptyChunks(sub)
|
||||
}
|
||||
|
||||
irprog.linkChunks() // re-link
|
||||
}
|
||||
|
||||
private fun removeEmptyChunks(sub: IRSubroutine) {
|
||||
|
@ -0,0 +1,38 @@
|
||||
package prog8.codegen.intermediate
|
||||
|
||||
import prog8.code.core.IErrorReporter
|
||||
import prog8.code.core.SourceCode.Companion.libraryFilePrefix
|
||||
import prog8.intermediate.*
|
||||
|
||||
internal class IRUnusedCodeRemover(private val irprog: IRProgram, private val errors: IErrorReporter) {
|
||||
fun optimize(): Int {
|
||||
val linkedChunks = mutableSetOf<IRCodeChunkBase>()
|
||||
var numRemoved = 0
|
||||
|
||||
irprog.blocks.asSequence().flatMap { it.subroutines }.forEach { sub ->
|
||||
sub.chunks.forEach { chunk ->
|
||||
if(chunk.next!=null)
|
||||
linkedChunks += chunk.next!!
|
||||
chunk.instructions.forEach {
|
||||
if(it.branchTarget!=null)
|
||||
linkedChunks += it.branchTarget!!
|
||||
}
|
||||
if(chunk.label=="main.start")
|
||||
linkedChunks += chunk
|
||||
}
|
||||
}
|
||||
|
||||
irprog.blocks.asSequence().flatMap { it.subroutines }.forEach { sub ->
|
||||
sub.chunks.reversed().forEach { chunk ->
|
||||
if(chunk !in linkedChunks) {
|
||||
if(!chunk.position.file.startsWith(libraryFilePrefix))
|
||||
errors.warn("unreachable code", chunk.position)
|
||||
sub.chunks.remove(chunk)
|
||||
numRemoved++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return numRemoved
|
||||
}
|
||||
}
|
@ -240,6 +240,6 @@ main {
|
||||
val exc = shouldThrow<Exception> {
|
||||
VmRunner().runProgram(virtfile.readText())
|
||||
}
|
||||
exc.message shouldContain("does not support asmsubs")
|
||||
exc.message shouldContain("does not support non-IR asmsubs")
|
||||
}
|
||||
})
|
@ -3,7 +3,8 @@ TODO
|
||||
|
||||
For next release
|
||||
^^^^^^^^^^^^^^^^
|
||||
- ir: asmsub contents remains blank in IR file ?
|
||||
- ir: position of chunk of text.print("abc") seems to point to the string arg instead of the call
|
||||
- fix unused chunk remover that now causes code execution error (IRCodeGen should enable it)
|
||||
- ir: improve dead code elimination by checking chunk linkage. Does this solve the next issue?:
|
||||
- ir: how to remove all unused subroutines? (the 6502 assembly codegen relies on 64tass solve this for us)
|
||||
|
||||
|
@ -107,8 +107,10 @@ class IRProgram(val name: String,
|
||||
if(next!=null) {
|
||||
if (next is IRCodeChunk && chunk.instructions.lastOrNull()?.opcode !in OpcodesThatJump)
|
||||
chunk.next = next
|
||||
else if(next is IRInlineAsmChunk)
|
||||
chunk.next = next
|
||||
else
|
||||
throw AssemblyError("code chunk flows into following non-code chunk")
|
||||
throw AssemblyError("code chunk flows into following non-executable chunk")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -40,7 +40,6 @@ class VmProgramLoader {
|
||||
|
||||
block.inlineAssembly.forEach {
|
||||
val replacement = addAssemblyToProgram(it, programChunks, variableAddresses)
|
||||
if(replacement!=null)
|
||||
chunkReplacements += replacement
|
||||
}
|
||||
block.subroutines.forEach {
|
||||
@ -48,7 +47,6 @@ class VmProgramLoader {
|
||||
when (chunk) {
|
||||
is IRInlineAsmChunk -> {
|
||||
val replacement = addAssemblyToProgram(chunk, programChunks, variableAddresses)
|
||||
if(replacement!=null)
|
||||
chunkReplacements += replacement
|
||||
}
|
||||
is IRInlineBinaryChunk -> TODO("inline binary data not yet supported in the VM")
|
||||
@ -57,8 +55,14 @@ class VmProgramLoader {
|
||||
}
|
||||
}
|
||||
}
|
||||
if(block.asmSubroutines.any())
|
||||
throw IRParseException("vm currently does not support asmsubs: ${block.asmSubroutines.first().name}")
|
||||
block.asmSubroutines.forEach {
|
||||
if(!it.asmChunk.isIR)
|
||||
throw IRParseException("vm currently does not support non-IR asmsubs: ${block.asmSubroutines.first().name}")
|
||||
else {
|
||||
val replacement = addAssemblyToProgram(it.asmChunk, programChunks, variableAddresses)
|
||||
chunkReplacements += replacement
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pass2translateSyscalls(programChunks)
|
||||
|
@ -82,7 +82,7 @@ class TestVm: FunSpec( {
|
||||
}
|
||||
}
|
||||
|
||||
test("vm asmsub not supported") {
|
||||
test("non-IR asmsub not supported in vm") {
|
||||
val program = IRProgram("test", IRSymbolTable(null), getTestOptions(), VMTarget())
|
||||
val block = IRBlock("main", null, IRBlock.BlockAlignment.NONE, Position.DUMMY)
|
||||
val startSub = IRAsmSubroutine(
|
||||
@ -91,16 +91,33 @@ class TestVm: FunSpec( {
|
||||
emptySet(),
|
||||
emptyList(),
|
||||
emptyList(),
|
||||
IRInlineAsmChunk("main.asmstart", "inlined asm here", true, Position.DUMMY, null),
|
||||
IRInlineAsmChunk("main.asmstart", "inlined asm here", false, Position.DUMMY, null),
|
||||
Position.DUMMY
|
||||
)
|
||||
block += startSub
|
||||
program.addBlock(block)
|
||||
shouldThrowWithMessage<IRParseException>("vm currently does not support asmsubs: main.asmstart") {
|
||||
shouldThrowWithMessage<IRParseException>("vm currently does not support non-IR asmsubs: main.asmstart") {
|
||||
VirtualMachine(program)
|
||||
}
|
||||
}
|
||||
|
||||
test("IR asmsub ok in vm") {
|
||||
val program = IRProgram("test", IRSymbolTable(null), getTestOptions(), VMTarget())
|
||||
val block = IRBlock("main", null, IRBlock.BlockAlignment.NONE, Position.DUMMY)
|
||||
val startSub = IRAsmSubroutine(
|
||||
"main.start",
|
||||
0x2000u,
|
||||
emptySet(),
|
||||
emptyList(),
|
||||
emptyList(),
|
||||
IRInlineAsmChunk("main.start", "return", true, Position.DUMMY, null),
|
||||
Position.DUMMY
|
||||
)
|
||||
block += startSub
|
||||
program.addBlock(block)
|
||||
VirtualMachine(program).run()
|
||||
}
|
||||
|
||||
test("vmrunner") {
|
||||
val runner = VmRunner()
|
||||
val irSource="""<PROGRAM NAME=test>
|
||||
|
Loading…
Reference in New Issue
Block a user