mirror of
https://github.com/irmen/prog8.git
synced 2024-11-22 15:33:02 +00:00
multi assign
This commit is contained in:
parent
edc83305a4
commit
03e486c082
@ -34,7 +34,7 @@ fun printAst(root: PtNode, skipLibraries: Boolean, output: (text: String) -> Uni
|
||||
str + node.name + "()"
|
||||
}
|
||||
is PtIdentifier -> "${node.name} ${type(node.type)}"
|
||||
is PtIrRegister -> "VMREG#${node.register} ${type(node.type)}"
|
||||
is PtIrRegister -> "IRREG#${node.register} ${type(node.type)}"
|
||||
is PtMemoryByte -> "@()"
|
||||
is PtNumber -> {
|
||||
val numstr = if(node.type == DataType.FLOAT) node.number.toString() else node.number.toHex()
|
||||
|
@ -1,6 +1,7 @@
|
||||
package prog8.codegen.intermediate
|
||||
|
||||
import prog8.code.StRomSub
|
||||
import prog8.code.StRomSubParameter
|
||||
import prog8.code.ast.*
|
||||
import prog8.code.core.*
|
||||
import prog8.intermediate.*
|
||||
@ -17,14 +18,18 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express
|
||||
?: throw AssemblyError("only asmsubs can return multiple values")
|
||||
|
||||
val result = mutableListOf<IRCodeChunkBase>()
|
||||
sub.returns.zip(assignment.children).forEach { (returns, target) ->
|
||||
val singleAssign = PtAssignment(assignment.position)
|
||||
singleAssign.children.add(target)
|
||||
TODO("IR cannot store machine register results yet ${assignment.position}")
|
||||
// singleAssign.children.add(PtMachineRegister(4242, returns.type, assignment.position))
|
||||
// result += translateRegularAssign(singleAssign)
|
||||
}
|
||||
return result
|
||||
val funcCall = this.expressionEval.translate(values)
|
||||
require(funcCall.multipleResultRegs.size + funcCall.multipleResultFpRegs.size >= 2)
|
||||
if(funcCall.multipleResultFpRegs.isNotEmpty())
|
||||
TODO("deal with (multiple?) FP return registers")
|
||||
|
||||
TODO("add to result multi return regs from expression")
|
||||
// addToResult(result, funcCall, funcCall.resultReg, funcCall.resultFpReg)
|
||||
// sub.returns.zip(assignment.children).forEach { (returns, target) ->
|
||||
// result += assignCpuRegister(returns, funcCall, target as PtAssignTarget)
|
||||
// }
|
||||
// result.filterIsInstance<IRCodeChunk>().firstOrNull()?.appendSrcPosition(assignment.position)
|
||||
// return result
|
||||
} else {
|
||||
if (assignment.target.children.single() is PtIrRegister)
|
||||
throw AssemblyError("assigning to a register should be done by just evaluating the expression into resultregister")
|
||||
@ -35,6 +40,48 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express
|
||||
}
|
||||
}
|
||||
|
||||
private fun assignCpuRegister(returns: StRomSubParameter, target: PtAssignTarget): IRCodeChunk {
|
||||
val targetIdentifier = target.identifier
|
||||
val chunk = IRCodeChunk(null, null)
|
||||
if(targetIdentifier!=null) {
|
||||
TODO()
|
||||
val regNum = 4242 // TODO??
|
||||
when(returns.register.registerOrPair) {
|
||||
RegisterOrPair.A -> chunk += IRInstruction(Opcode.LOADHA, IRDataType.BYTE, reg1=regNum)
|
||||
RegisterOrPair.X -> chunk += IRInstruction(Opcode.LOADHX, IRDataType.BYTE, reg1=regNum)
|
||||
RegisterOrPair.Y -> chunk += IRInstruction(Opcode.LOADHY, IRDataType.BYTE, reg1=regNum)
|
||||
RegisterOrPair.AX -> chunk += IRInstruction(Opcode.LOADHAX, IRDataType.WORD, reg1=regNum)
|
||||
RegisterOrPair.AY -> chunk += IRInstruction(Opcode.LOADHAY, IRDataType.WORD, reg1=regNum)
|
||||
RegisterOrPair.XY -> chunk += IRInstruction(Opcode.LOADHXY, IRDataType.WORD, reg1=regNum)
|
||||
null -> {
|
||||
when(returns.register.statusflag) {
|
||||
Statusflag.Pc -> chunk += IRInstruction(Opcode.LOADHA, IRDataType.BYTE, reg1=regNum)
|
||||
else -> throw AssemblyError("weird statusflag as returnvalue")
|
||||
}
|
||||
}
|
||||
else -> throw AssemblyError("cannot load register")
|
||||
}
|
||||
chunk += IRInstruction(Opcode.STOREM, irType(target.type), reg1=regNum, labelSymbol = targetIdentifier.name)
|
||||
return chunk
|
||||
}
|
||||
val targetMem = target.memory
|
||||
if(targetMem!=null) {
|
||||
TODO("assign $returns to $targetMem")
|
||||
return chunk
|
||||
}
|
||||
val targetArray = target.array
|
||||
if(targetArray!=null) {
|
||||
TODO("assign $returns to $targetArray")
|
||||
return chunk
|
||||
}
|
||||
throw AssemblyError("weird target")
|
||||
// val singleAssign = PtAssignment(target.position)
|
||||
// singleAssign.children.add(target)
|
||||
// TODO("use the new IR instructions to store machine regs STOREHxx ${target.position}")
|
||||
// singleAssign.children.add(PtMachineRegister(4242, returns.type, assignment.position))
|
||||
// result += translateRegularAssign(singleAssign)
|
||||
}
|
||||
|
||||
internal fun translate(augAssign: PtAugmentedAssign): IRCodeChunks {
|
||||
// augmented assignment always has just a single target
|
||||
if(augAssign.target.children.single() is PtIrRegister)
|
||||
|
@ -7,8 +7,11 @@ import prog8.code.core.*
|
||||
import prog8.intermediate.*
|
||||
|
||||
|
||||
internal class ExpressionCodeResult(val chunks: IRCodeChunks, val dt: IRDataType, val resultReg: Int, val resultFpReg: Int) {
|
||||
constructor(chunks: IRCodeChunk, dt: IRDataType, resultReg: Int, resultFpReg: Int) : this(listOf(chunks), dt, resultReg, resultFpReg)
|
||||
internal class ExpressionCodeResult(val chunks: IRCodeChunks, val dt: IRDataType, val resultReg: Int, val resultFpReg: Int,
|
||||
val multipleResultRegs: List<Int> = emptyList(), val multipleResultFpRegs: List<Int> = emptyList()
|
||||
) {
|
||||
constructor(chunk: IRCodeChunk, dt: IRDataType, resultReg: Int, resultFpReg: Int, multipleResultRegs: List<Int> = emptyList(), multipleResultFpRegs: List<Int> = emptyList())
|
||||
: this(listOf(chunk), dt, resultReg, resultFpReg, multipleResultRegs, multipleResultFpRegs)
|
||||
|
||||
companion object {
|
||||
val EMPTY: ExpressionCodeResult = ExpressionCodeResult(emptyList(), IRDataType.BYTE, -1, -1)
|
||||
@ -493,29 +496,40 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
else
|
||||
argRegisters.add(FunctionCallArgs.ArgumentSpec("", null, FunctionCallArgs.RegSpec(paramDt, tr.resultReg, parameter.register)))
|
||||
result += tr.chunks
|
||||
when(parameter.register.registerOrPair) {
|
||||
RegisterOrPair.A -> addInstr(result, IRInstruction(Opcode.STOREHA, IRDataType.BYTE, reg1=tr.resultReg), null)
|
||||
RegisterOrPair.X -> addInstr(result, IRInstruction(Opcode.STOREHX, IRDataType.BYTE, reg1=tr.resultReg), null)
|
||||
RegisterOrPair.Y -> addInstr(result, IRInstruction(Opcode.STOREHY, IRDataType.BYTE, reg1=tr.resultReg), null)
|
||||
RegisterOrPair.AX -> addInstr(result, IRInstruction(Opcode.STOREHAX, IRDataType.WORD, reg1=tr.resultReg), null)
|
||||
RegisterOrPair.AY -> addInstr(result, IRInstruction(Opcode.STOREHAY, IRDataType.WORD, reg1=tr.resultReg), null)
|
||||
RegisterOrPair.XY -> addInstr(result, IRInstruction(Opcode.STOREHXY, IRDataType.WORD, reg1=tr.resultReg), null)
|
||||
in Cx16VirtualRegisters -> {
|
||||
addInstr(result, IRInstruction(Opcode.STOREM, paramDt, reg1=tr.resultReg, labelSymbol = "cx16.${parameter.register.registerOrPair.toString().lowercase()}"), null)
|
||||
}
|
||||
null -> when(parameter.register.statusflag) {
|
||||
// TODO: do the statusflag argument as last
|
||||
Statusflag.Pc -> addInstr(result, IRInstruction(Opcode.LSR, paramDt, reg1=tr.resultReg), null)
|
||||
else -> throw AssemblyError("weird statusflag as param")
|
||||
}
|
||||
else -> throw AssemblyError("unsupported register arg")
|
||||
}
|
||||
}
|
||||
// return value
|
||||
|
||||
if(callTarget.returns.size>1)
|
||||
return callWithMultipleReturnValues()
|
||||
|
||||
// return a single value
|
||||
var statusFlagResult: Statusflag? = null
|
||||
val returnRegSpec = if(fcall.void) null else {
|
||||
if(callTarget.returns.isEmpty())
|
||||
null
|
||||
else if(callTarget.returns.size==1) {
|
||||
val returns = callTarget.returns[0]
|
||||
val returnIrType = irType(returns.type)
|
||||
if(returnIrType==IRDataType.FLOAT)
|
||||
FunctionCallArgs.RegSpec(returnIrType, codeGen.registers.nextFreeFloat(), returns.register)
|
||||
else {
|
||||
val returnRegister = codeGen.registers.nextFree()
|
||||
FunctionCallArgs.RegSpec(returnIrType, returnRegister, returns.register)
|
||||
}
|
||||
} else {
|
||||
// multiple return values: take the first *register* (not status flag) return value and ignore the rest.
|
||||
val returns = callTarget.returns.first { it.register.registerOrPair!=null }
|
||||
val returnIrType = irType(returns.type)
|
||||
if(returnIrType==IRDataType.FLOAT)
|
||||
FunctionCallArgs.RegSpec(returnIrType, codeGen.registers.nextFreeFloat(), returns.register)
|
||||
else
|
||||
FunctionCallArgs.RegSpec(returnIrType, codeGen.registers.nextFree(), returns.register)
|
||||
val returns = callTarget.returns[0]
|
||||
val returnIrType = irType(returns.type)
|
||||
if(returnIrType==IRDataType.FLOAT)
|
||||
FunctionCallArgs.RegSpec(returnIrType, codeGen.registers.nextFreeFloat(), returns.register)
|
||||
else {
|
||||
val returnRegister = codeGen.registers.nextFree()
|
||||
FunctionCallArgs.RegSpec(returnIrType, returnRegister, returns.register)
|
||||
}
|
||||
}
|
||||
// create the call
|
||||
@ -572,6 +586,10 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
}
|
||||
}
|
||||
|
||||
private fun callWithMultipleReturnValues(): ExpressionCodeResult {
|
||||
TODO("call with multiple return values")
|
||||
}
|
||||
|
||||
private fun operatorGreaterThan(
|
||||
binExpr: PtBinaryExpression,
|
||||
vmDt: IRDataType,
|
||||
|
@ -1,4 +1,3 @@
|
||||
%import diskio
|
||||
%zeropage basicsafe
|
||||
%option no_sysinit
|
||||
|
||||
@ -6,13 +5,25 @@ main {
|
||||
sub start() {
|
||||
bool @shared flag
|
||||
|
||||
cx16.r0L = test(12345, flag, -42)
|
||||
cx16.r1=9999
|
||||
; flag = test(42)
|
||||
cx16.r0L, flag = test2(12345, 5566, flag, -42)
|
||||
|
||||
}
|
||||
|
||||
asmsub test(uword arg @AY, bool flag @Pc, byte value @X) -> ubyte @A, bool @Pc {
|
||||
asmsub test(ubyte arg @A) -> bool @Pc {
|
||||
%asm {{
|
||||
sec
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
||||
; TODO cx16.r1 as return reg
|
||||
|
||||
asmsub test2(uword arg @AY, uword arg2 @R1, bool flag @Pc, byte value @X) -> ubyte @A, bool @Pc {
|
||||
%asm {{
|
||||
txa
|
||||
sec
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user