diff --git a/codeGenIntermediate/src/prog8/codegen/intermediate/IRUnusedCodeRemover.kt b/codeGenIntermediate/src/prog8/codegen/intermediate/IRUnusedCodeRemover.kt index 2627f642a..e5b9a34d4 100644 --- a/codeGenIntermediate/src/prog8/codegen/intermediate/IRUnusedCodeRemover.kt +++ b/codeGenIntermediate/src/prog8/codegen/intermediate/IRUnusedCodeRemover.kt @@ -7,7 +7,15 @@ import prog8.intermediate.* internal class IRUnusedCodeRemover(private val irprog: IRProgram, private val errors: IErrorReporter) { fun optimize(): Int { - var numRemoved = removeSimpleUnlinked() + removeUnreachable() + val allLabeledChunks = mutableMapOf() + + irprog.blocks.asSequence().flatMap { it.subroutines }.forEach { sub -> + sub.chunks.forEach { chunk -> + chunk.label?.let { allLabeledChunks[it] = chunk } + } + } + + var numRemoved = removeSimpleUnlinked(allLabeledChunks) + removeUnreachable(allLabeledChunks) // remove empty subs irprog.blocks.forEach { block -> @@ -32,14 +40,19 @@ internal class IRUnusedCodeRemover(private val irprog: IRProgram, private val er return numRemoved } - private fun removeUnreachable(): Int { + private fun removeUnreachable(allLabeledChunks: MutableMap): Int { val reachable = mutableSetOf(irprog.blocks.single { it.name=="main" }.subroutines.single { it.name=="main.start" }.chunks.first()) fun grow() { val new = mutableSetOf() reachable.forEach { it.next?.let { next -> new += next } - it.instructions.forEach { instr -> instr.branchTarget?.let { target -> new += target} } + it.instructions.forEach { instr -> + if (instr.branchTarget == null) + instr.labelSymbol?.let { label -> allLabeledChunks[label]?.let { chunk -> new += chunk } } + else + new += instr.branchTarget!! + } } reachable += new } @@ -55,13 +68,19 @@ internal class IRUnusedCodeRemover(private val irprog: IRProgram, private val er return removeUnlinkedChunks(reachable) } - private fun removeSimpleUnlinked(): Int { + private fun removeSimpleUnlinked(allLabeledChunks: Map): Int { val linkedChunks = mutableSetOf() irprog.blocks.asSequence().flatMap { it.subroutines }.forEach { sub -> sub.chunks.forEach { chunk -> chunk.next?.let { next -> linkedChunks += next } - chunk.instructions.forEach { it.branchTarget?.let { target -> linkedChunks += target } } + chunk.instructions.forEach { + if(it.branchTarget==null) { + it.labelSymbol?.let { label -> allLabeledChunks[label]?.let { cc -> linkedChunks += cc } } + } else { + linkedChunks += it.branchTarget!! + } + } if (chunk.label == "main.start") linkedChunks += chunk } diff --git a/intermediate/src/prog8/intermediate/IRProgram.kt b/intermediate/src/prog8/intermediate/IRProgram.kt index 86355fe81..a5b8bc0d5 100644 --- a/intermediate/src/prog8/intermediate/IRProgram.kt +++ b/intermediate/src/prog8/intermediate/IRProgram.kt @@ -109,8 +109,10 @@ class IRProgram(val name: String, chunk.next = next else if(next is IRInlineAsmChunk) chunk.next = next + else if(next is IRInlineBinaryChunk) + chunk.next =next else - throw AssemblyError("code chunk flows into following non-executable chunk") + throw AssemblyError("code chunk followed by invalid chunk type $next") } }