mirror of
https://github.com/irmen/prog8.git
synced 2025-02-27 03:29:22 +00:00
various
This commit is contained in:
parent
585009ac5c
commit
cfa7258ff4
@ -78,22 +78,20 @@ internal class IRPeepholeOptimizer(private val irprog: IRProgram) {
|
||||
}
|
||||
|
||||
private fun joinChunks(sub: IRSubroutine) {
|
||||
/*
|
||||
Subroutine contains a list of chunks.
|
||||
Some can be joined into one.
|
||||
TODO: this has to be changed later...
|
||||
*/
|
||||
// Subroutine contains a list of chunks. Some can be joined into one.
|
||||
|
||||
if(sub.chunks.isEmpty())
|
||||
return
|
||||
|
||||
/*
|
||||
fun mayJoin(previous: IRCodeChunkBase, chunk: IRCodeChunkBase): Boolean {
|
||||
if(chunk.label!=null)
|
||||
return false
|
||||
if(previous is IRCodeChunk && chunk is IRCodeChunk) {
|
||||
// if the previous chunk doesn't end in a jump or a return, flow continues into the next chunk
|
||||
val lastInstruction = previous.instructions.lastOrNull()
|
||||
if(lastInstruction!=null)
|
||||
return lastInstruction.opcode !in OpcodesThatJump
|
||||
return true
|
||||
|
||||
// TODO: only if all instructions are non-branching, allow it to join?
|
||||
// return !chunk.lines.filterIsInstance<IRInstruction>().any {it.opcode in OpcodesThatBranch }
|
||||
}
|
||||
return false
|
||||
}
|
||||
@ -107,7 +105,7 @@ internal class IRPeepholeOptimizer(private val irprog: IRProgram) {
|
||||
chunks += sub.chunks[ix]
|
||||
}
|
||||
sub.chunks.clear()
|
||||
sub.chunks += chunks*/
|
||||
sub.chunks += chunks
|
||||
}
|
||||
|
||||
private fun cleanupPushPop(chunk: IRCodeChunk, indexedInstructions: List<IndexedValue<IRInstruction>>): Boolean {
|
||||
@ -174,7 +172,7 @@ internal class IRPeepholeOptimizer(private val irprog: IRProgram) {
|
||||
// remove useless RETURN
|
||||
if(ins.opcode == Opcode.RETURN && idx>0) {
|
||||
val previous = chunk.instructions[idx-1] as? IRInstruction
|
||||
if(previous?.opcode in setOf(Opcode.JUMP, Opcode.JUMPA, Opcode.RETURN)) {
|
||||
if(previous?.opcode in OpcodesThatJump) {
|
||||
chunk.instructions.removeAt(idx)
|
||||
changed = true
|
||||
}
|
||||
|
@ -252,16 +252,8 @@ internal class AstChecker(private val program: Program,
|
||||
}
|
||||
|
||||
override fun visit(inlineAssembly: InlineAssembly) {
|
||||
val assembly = inlineAssembly.assembly
|
||||
if(compilerOptions.compTarget.name!=VMTarget.NAME) {
|
||||
if (" rti" in assembly || "\trti" in assembly || " rts" in assembly || "\trts" in assembly ||
|
||||
" jmp" in assembly || "\tjmp" in assembly || " bra" in assembly || "\tbra" in assembly
|
||||
)
|
||||
count++
|
||||
} else {
|
||||
if(" return" in assembly || "\treturn" in assembly || " jump" in assembly || "\tjump" in assembly)
|
||||
count++
|
||||
}
|
||||
if(inlineAssembly.hasReturnOrRts(compilerOptions.compTarget))
|
||||
count++
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -12,7 +12,6 @@ import prog8.ast.statements.VarDeclOrigin
|
||||
import prog8.ast.walk.AstWalker
|
||||
import prog8.ast.walk.IAstModification
|
||||
import prog8.code.core.*
|
||||
import prog8.code.target.VMTarget
|
||||
|
||||
|
||||
internal fun Program.checkValid(errors: IErrorReporter, compilerOptions: CompilationOptions) {
|
||||
@ -170,15 +169,8 @@ internal fun IdentifierReference.isSubroutineParameter(program: Program): Boolea
|
||||
}
|
||||
|
||||
internal fun Subroutine.hasRtsInAsm(compTarget: ICompilationTarget): Boolean {
|
||||
val instructions =
|
||||
if(compTarget.name == VMTarget.NAME)
|
||||
listOf(" return", "\treturn", " jump", "\tjump")
|
||||
else
|
||||
listOf(" rti", "\trti", " rts", "\trts", " jmp", "\tjmp", " bra", "\tbra")
|
||||
return statements
|
||||
.asSequence()
|
||||
.filterIsInstance<InlineAssembly>()
|
||||
.any {
|
||||
instructions.any { instr->instr in it.assembly }
|
||||
}
|
||||
.any { it.hasReturnOrRts(compTarget) }
|
||||
}
|
@ -7,6 +7,7 @@ import prog8.ast.expressions.*
|
||||
import prog8.ast.walk.AstWalker
|
||||
import prog8.ast.walk.IAstVisitor
|
||||
import prog8.code.core.*
|
||||
import prog8.code.target.VMTarget
|
||||
|
||||
|
||||
interface INamedStatement {
|
||||
@ -629,6 +630,15 @@ class InlineAssembly(val assembly: String, val isIR: Boolean, override val posit
|
||||
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
|
||||
override fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent)
|
||||
|
||||
fun hasReturnOrRts(target: ICompilationTarget): Boolean {
|
||||
return if(target.name!= VMTarget.NAME) {
|
||||
" rti" in assembly || "\trti" in assembly || " rts" in assembly || "\trts" in assembly ||
|
||||
" jmp" in assembly || "\tjmp" in assembly || " bra" in assembly || "\tbra" in assembly
|
||||
} else {
|
||||
" return" in assembly || "\treturn" in assembly || " jump" in assembly || "\tjump" in assembly || " jumpa" in assembly || "\tjumpa" in assembly
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
val names: Set<String> by lazy {
|
||||
// A cache of all the words (identifiers) present in this block of assembly code
|
||||
|
@ -3,14 +3,12 @@ TODO
|
||||
|
||||
For next release
|
||||
^^^^^^^^^^^^^^^^
|
||||
- ir: fix linkChunks() in IRProgram and addAssemblyToProgram() next pointer tracking
|
||||
- vm: program is list of chunks, fix dispatcher
|
||||
- maybe?: make sure last %ir chunk in a subroutine ends with a jump or a return instruction
|
||||
- ir: fix unit tests
|
||||
- ir: fix joinChunks() in the IR optimizer - there are WAY too many chunks with 1 instruction in them only
|
||||
- ir: fix removeWeirdBranches in IR optimizer
|
||||
- ir: next in IRCodeChunk can also be a Asm Chunk which can have next as well
|
||||
- add cx16diskio.vload_raw() to load headerless files into vram
|
||||
- mention the syntax highlighting files in the readme and the docs, and add note to the IDEA one that it can also be used in Rider
|
||||
- update diagram in technical.rst?
|
||||
|
||||
...
|
||||
|
||||
|
@ -1,11 +1,16 @@
|
||||
%import textio
|
||||
; %import textio
|
||||
|
||||
main {
|
||||
|
||||
sub start() {
|
||||
ubyte aa = 42
|
||||
ubyte bb = 99
|
||||
aa += bb
|
||||
txt.print_ub(aa)
|
||||
; should get a return after the nop
|
||||
%ir {{
|
||||
nop
|
||||
}}
|
||||
|
||||
; ubyte aa = 42
|
||||
; ubyte bb = 99
|
||||
; aa += bb
|
||||
; txt.print_ub(aa)
|
||||
}
|
||||
}
|
||||
|
@ -353,6 +353,12 @@ enum class Opcode {
|
||||
BINARYDATA
|
||||
}
|
||||
|
||||
val OpcodesThatJump = setOf(
|
||||
Opcode.JUMP,
|
||||
Opcode.JUMPA,
|
||||
Opcode.RETURN
|
||||
)
|
||||
|
||||
val OpcodesThatBranch = setOf(
|
||||
Opcode.JUMP,
|
||||
Opcode.JUMPA,
|
||||
|
@ -93,18 +93,22 @@ class IRProgram(val name: String,
|
||||
}
|
||||
|
||||
blocks.asSequence().flatMap { it.subroutines }.forEach { sub ->
|
||||
|
||||
|
||||
sub.chunks.withIndex().forEach { (index, chunk) ->
|
||||
|
||||
fun nextChunk(): IRCodeChunkBase? = if(index<sub.chunks.size-1) sub.chunks[index + 1] else null
|
||||
|
||||
when (chunk) {
|
||||
is IRCodeChunk -> {
|
||||
// link sequential chunks
|
||||
val jump = chunk.instructions.lastOrNull()?.opcode
|
||||
if (jump == null || jump !in setOf(Opcode.JUMP, Opcode.JUMPA, Opcode.RETURN)) {
|
||||
if (jump == null || jump !in OpcodesThatJump) {
|
||||
// no jump at the end, so link to next chunk (if it exists)
|
||||
if(index<sub.chunks.size-1) {
|
||||
val nextChunk = sub.chunks[index + 1]
|
||||
if (nextChunk is IRCodeChunk)
|
||||
chunk.next = nextChunk
|
||||
val next = nextChunk()
|
||||
if(next!=null) {
|
||||
if (next is IRCodeChunk)
|
||||
chunk.next = next
|
||||
else
|
||||
throw AssemblyError("code chunk flows into following non-code chunk")
|
||||
} else {
|
||||
@ -125,7 +129,10 @@ class IRProgram(val name: String,
|
||||
}
|
||||
}
|
||||
is IRInlineAsmChunk -> {
|
||||
// TODO("link next of asm chunk")
|
||||
val next = nextChunk()
|
||||
if(next!=null) {
|
||||
// TODO if chunk doesn't end in a jump or return statement, flow continues into the next chunk
|
||||
}
|
||||
}
|
||||
is IRInlineBinaryChunk -> {
|
||||
// TODO("link next of binary chunk")
|
||||
|
@ -136,7 +136,7 @@ class VirtualMachine(irProgram: IRProgram) {
|
||||
|
||||
private fun dispatch(ins: IRInstruction) {
|
||||
when(ins.opcode) {
|
||||
Opcode.NOP -> { nextPc() }
|
||||
Opcode.NOP -> nextPc()
|
||||
Opcode.LOAD -> InsLOAD(ins)
|
||||
Opcode.LOADM -> InsLOADM(ins)
|
||||
Opcode.LOADX -> InsLOADX(ins)
|
||||
|
@ -272,7 +272,7 @@ class VmProgramLoader {
|
||||
symbolAddresses: MutableMap<String, Int>,
|
||||
): Pair<IRCodeChunkBase, IRCodeChunk> {
|
||||
if(asmChunk.isIR) {
|
||||
val chunk = IRCodeChunk(asmChunk.label, asmChunk.position, null)
|
||||
val chunk = IRCodeChunk(asmChunk.label, asmChunk.position, null) // TODO keep track of the chunk's next pointer
|
||||
asmChunk.assembly.lineSequence().forEach {
|
||||
val parsed = parseIRCodeLine(it.trim(), Pair(chunk, chunk.instructions.size), placeholders)
|
||||
parsed.fold(
|
||||
|
Loading…
x
Reference in New Issue
Block a user