mirror of
https://github.com/irmen/prog8.git
synced 2025-01-11 13:29:45 +00:00
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:
parent
63f5ef9e14
commit
54bffc91ae
@ -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,
|
||||
|
@ -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'
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
})
|
@ -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()
|
||||
|
Loading…
x
Reference in New Issue
Block a user