properly generate PUSH and POP instructions for push() and pop() calls in IR.

Also switch to a fork of shadowJar to avoid Gradle deprecation errors.
This commit is contained in:
Irmen de Jong 2024-06-25 22:39:20 +02:00
parent 63f5ef9e14
commit 54bffc91ae
4 changed files with 74 additions and 5 deletions

View File

@ -1,5 +1,6 @@
package prog8.codegen.intermediate
import prog8.code.StNode
import prog8.code.StRomSub
import prog8.code.StSub
import prog8.code.ast.*
@ -451,7 +452,14 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
}
fun translate(fcall: PtFunctionCall): ExpressionCodeResult {
when (val callTarget = codeGen.symbolTable.flat.getValue(fcall.name)) {
val callTarget = codeGen.symbolTable.flat.getValue(fcall.name)
if(callTarget.scopedName in listOf("sys.push", "sys.pushw", "sys.pop", "sys.popw")) {
// special case, these should be inlined, or even use specialized instructions. Instead of doing a normal subroutine call.
return translateStackFunctions(fcall, callTarget)
}
when (callTarget) {
is StSub -> {
val result = mutableListOf<IRCodeChunkBase>()
addInstr(result, IRInstruction(Opcode.PREPARECALL, immediate = callTarget.parameters.size), null)
@ -590,6 +598,39 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
}
}
private fun translateStackFunctions(fcall: PtFunctionCall, callTarget: StNode): ExpressionCodeResult {
val chunk = mutableListOf<IRCodeChunkBase>()
when(callTarget.scopedName) {
"sys.push" -> {
// push byte
val tr = translateExpression(fcall.args.single())
chunk += tr.chunks
addInstr(chunk, IRInstruction(Opcode.PUSH, IRDataType.BYTE, reg1=tr.resultReg), null)
return ExpressionCodeResult(chunk, IRDataType.BYTE, -1, -1)
}
"sys.pushw" -> {
// push word
val tr = translateExpression(fcall.args.single())
chunk += tr.chunks
addInstr(chunk, IRInstruction(Opcode.PUSH, IRDataType.WORD, reg1=tr.resultReg), null)
return ExpressionCodeResult(chunk, IRDataType.WORD, -1, -1)
}
"sys.pop" -> {
// pop byte
val popReg = codeGen.registers.nextFree()
addInstr(chunk, IRInstruction(Opcode.POP, IRDataType.BYTE, reg1=popReg), null)
return ExpressionCodeResult(chunk, IRDataType.BYTE, popReg, -1)
}
"sys.popw" -> {
// pop word
val popReg = codeGen.registers.nextFree()
addInstr(chunk, IRInstruction(Opcode.POP, IRDataType.WORD, reg1=popReg), null)
return ExpressionCodeResult(chunk, IRDataType.WORD, popReg, -1)
}
else -> throw AssemblyError("unknown stack subroutine called")
}
}
private fun callRomSubWithMultipleReturnValues(
callTarget: StRomSub,
fcall: PtFunctionCall,

View File

@ -2,7 +2,8 @@ plugins {
id 'java'
id 'application'
id 'org.jetbrains.kotlin.jvm'
id 'com.github.johnrengelman.shadow' version '8.1.1'
// id 'com.github.johnrengelman.shadow' version '8.1.1'
id 'io.github.goooler.shadow' version '8.1.7'
id 'com.peterabeles.gversion' version '1.10.2'
}

View File

@ -11,6 +11,7 @@ import prog8.ast.statements.Assignment
import prog8.code.target.C64Target
import prog8.code.target.Cx16Target
import prog8.code.target.VMTarget
import prog8.intermediate.IRDataType
import prog8.intermediate.IRFileReader
import prog8.intermediate.IRSubroutine
import prog8.intermediate.Opcode
@ -475,6 +476,34 @@ main {
compileText(VMTarget(), true, src, writeAssembly = true) shouldNotBe null
}
test("push() and pop() generate correct IR instructions") {
val src="""
main {
sub start() {
ubyte bb
uword ww
sys.push(42)
bb++
bb=sys.pop()
sys.pushw(9999)
ww++
ww=sys.popw()
}
}"""
val result = compileText(VMTarget(), true, src, writeAssembly = true)!!
val virtfile = result.compilationOptions.outputDir.resolve(result.compilerAst.name + ".p8ir")
val irProgram = IRFileReader().read(virtfile)
val start = irProgram.blocks[0].children[0] as IRSubroutine
val instructions = start.chunks.flatMap { c->c.instructions }
instructions.size shouldBe 13
instructions[3].opcode shouldBe Opcode.PUSH
instructions[3].type shouldBe IRDataType.BYTE
instructions[5].opcode shouldBe Opcode.POP
instructions[5].type shouldBe IRDataType.BYTE
instructions[8].opcode shouldBe Opcode.PUSH
instructions[8].type shouldBe IRDataType.WORD
instructions[10].opcode shouldBe Opcode.POP
instructions[10].type shouldBe IRDataType.WORD
}
})

View File

@ -7,8 +7,6 @@ https://github.com/irmen/prog8/issues/136 (string.find register order issue)
optimization: for 65c02 sometimes clc adc #1 is generated, this can be optimized into inc a (always? or not? mind the carry flag!)
IR: sys.push() and sys.pop() etc should be translated into PUSH/POP instructions instead of subroutine calls
if-optimization:
if row == NUMQUEENS {
print_solution()