mirror of
https://github.com/irmen/prog8.git
synced 2024-10-17 10:24:55 +00:00
add "-rpn" command line switch to transform exprs to RPN in codegen
This commit is contained in:
parent
8ffca93cd5
commit
9241479da4
@ -53,7 +53,8 @@ sealed class PtNamedNode(var name: String, position: Position): PtNode(position)
|
|||||||
class PtProgram(
|
class PtProgram(
|
||||||
val name: String,
|
val name: String,
|
||||||
val memsizer: IMemSizer,
|
val memsizer: IMemSizer,
|
||||||
val encoding: IStringEncoding
|
val encoding: IStringEncoding,
|
||||||
|
var binaryExpressionsAreRPN: Boolean = false
|
||||||
) : PtNode(Position.DUMMY) {
|
) : PtNode(Position.DUMMY) {
|
||||||
|
|
||||||
// fun allModuleDirectives(): Sequence<PtDirective> =
|
// fun allModuleDirectives(): Sequence<PtDirective> =
|
||||||
@ -68,7 +69,8 @@ class PtProgram(
|
|||||||
// If the code generator wants, it can transform binary expression nodes into flat RPN nodes.
|
// If the code generator wants, it can transform binary expression nodes into flat RPN nodes.
|
||||||
// This will destroy the original binaryexpression nodes!
|
// This will destroy the original binaryexpression nodes!
|
||||||
fun transformBinExprToRPN() {
|
fun transformBinExprToRPN() {
|
||||||
|
if(binaryExpressionsAreRPN)
|
||||||
|
return
|
||||||
fun transformToRPN(originalExpr: PtBinaryExpression): PtRpn {
|
fun transformToRPN(originalExpr: PtBinaryExpression): PtRpn {
|
||||||
fun makeRpn(expr: PtExpression): PtRpn {
|
fun makeRpn(expr: PtExpression): PtRpn {
|
||||||
val rpn = PtRpn(expr.type, expr.position)
|
val rpn = PtRpn(expr.type, expr.position)
|
||||||
@ -97,6 +99,7 @@ class PtProgram(
|
|||||||
}
|
}
|
||||||
|
|
||||||
children.forEach { transformBinExprToRPN(it, this) }
|
children.forEach { transformBinExprToRPN(it, this) }
|
||||||
|
binaryExpressionsAreRPN = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -170,12 +170,12 @@ class PtRpn(type: DataType, position: Position): PtExpression(type, position) {
|
|||||||
require(node is PtRpnOperator || node is PtExpression)
|
require(node is PtRpnOperator || node is PtExpression)
|
||||||
if(node is PtRpn) {
|
if(node is PtRpn) {
|
||||||
node.children.forEach {
|
node.children.forEach {
|
||||||
children += it
|
children.add(it)
|
||||||
it.parent = this
|
it.parent = this
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
children += node
|
children.add(node)
|
||||||
node.parent = this
|
node.parent = this
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -264,19 +264,24 @@ class PtRpn(type: DataType, position: Position): PtExpression(type, position) {
|
|||||||
}
|
}
|
||||||
return Pair(maxDepths, numPushes)
|
return Pair(maxDepths, numPushes)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun finalOperator(): String? = (children.last() as? PtRpnOperator)?.operator
|
||||||
|
fun finalFirstOperand() = children[children.size-3]
|
||||||
|
fun finalSecondOperand() = children[children.size-2]
|
||||||
}
|
}
|
||||||
|
|
||||||
class PtRpnOperator(val operator: String, val type: DataType, val operand1Type: DataType, val operand2Type: DataType, position: Position): PtNode(position) {
|
class PtRpnOperator(val operator: String, val type: DataType, val operand1Type: DataType, val operand2Type: DataType, position: Position): PtNode(position) {
|
||||||
// init {
|
init {
|
||||||
// require(operand1Type equalsSize operand2Type) {
|
// NOTE: For now, we require that the types of the operands are the same size as the output type of the operator node.
|
||||||
// "operator $operator : operand1 and 2 types aren't equal sizes: $operand1Type $operand2Type"
|
require(operand1Type equalsSize operand2Type) {
|
||||||
// }
|
"operand type size(s) differ: $operand1Type $operand2Type oper: $operator"
|
||||||
// if(operator !in ComparisonOperators) {
|
}
|
||||||
// require(type equalsSize operand1Type && type equalsSize operand2Type) {
|
if(operator !in ComparisonOperators) {
|
||||||
// "operator $operator : type $type size not equal to operand1 and 2 types: $operand1Type $operand2Type"
|
require(type equalsSize operand1Type && type equalsSize operand2Type) {
|
||||||
// }
|
"operand type size(s) differ from operator result type $type: $operand1Type $operand2Type oper: $operator"
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -101,7 +101,7 @@ class PtForLoop(position: Position) : PtNode(position) {
|
|||||||
|
|
||||||
class PtIfElse(position: Position) : PtNode(position) {
|
class PtIfElse(position: Position) : PtNode(position) {
|
||||||
val condition: PtNode
|
val condition: PtNode
|
||||||
get() = children[0] as PtNode
|
get() = children[0]
|
||||||
val ifScope: PtNodeGroup
|
val ifScope: PtNodeGroup
|
||||||
get() = children[1] as PtNodeGroup
|
get() = children[1] as PtNodeGroup
|
||||||
val elseScope: PtNodeGroup
|
val elseScope: PtNodeGroup
|
||||||
|
@ -20,6 +20,7 @@ class CompilationOptions(val output: OutputType,
|
|||||||
var asmListfile: Boolean = false,
|
var asmListfile: Boolean = false,
|
||||||
var experimentalCodegen: Boolean = false,
|
var experimentalCodegen: Boolean = false,
|
||||||
var varsHigh: Boolean = false,
|
var varsHigh: Boolean = false,
|
||||||
|
var useRPN: Boolean = false,
|
||||||
var evalStackBaseAddress: UInt? = null,
|
var evalStackBaseAddress: UInt? = null,
|
||||||
var outputDir: Path = Path(""),
|
var outputDir: Path = Path(""),
|
||||||
var symbolDefs: Map<String, String> = emptyMap()
|
var symbolDefs: Map<String, String> = emptyMap()
|
||||||
|
@ -21,8 +21,8 @@ class AsmGen6502: ICodeGeneratorBackend {
|
|||||||
options: CompilationOptions,
|
options: CompilationOptions,
|
||||||
errors: IErrorReporter
|
errors: IErrorReporter
|
||||||
): IAssemblyProgram? {
|
): IAssemblyProgram? {
|
||||||
// If we want RPN expressions instead, use this:
|
if(options.useRPN)
|
||||||
// TODO program.transformBinExprToRPN()
|
program.transformBinExprToRPN()
|
||||||
|
|
||||||
val asmgen = AsmGen6502Internal(program, symbolTable, options, errors)
|
val asmgen = AsmGen6502Internal(program, symbolTable, options, errors)
|
||||||
return asmgen.compileToAssembly()
|
return asmgen.compileToAssembly()
|
||||||
@ -547,35 +547,38 @@ class AsmGen6502Internal (
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun translate(stmt: PtIfElse) {
|
private fun translate(stmt: PtIfElse) {
|
||||||
val condition = stmt.condition as PtBinaryExpression
|
if(stmt.condition is PtRpn) {
|
||||||
requireComparisonExpression(condition) // IfStatement: condition must be of form 'x <comparison> <value>'
|
TODO("RPN")
|
||||||
|
} else {
|
||||||
|
val condition = stmt.condition as PtBinaryExpression
|
||||||
|
requireComparisonExpression(condition) // IfStatement: condition must be of form 'x <comparison> <value>'
|
||||||
|
|
||||||
if (stmt.elseScope.children.isEmpty()) {
|
if (stmt.elseScope.children.isEmpty()) {
|
||||||
val jump = stmt.ifScope.children.singleOrNull()
|
val jump = stmt.ifScope.children.singleOrNull()
|
||||||
if(jump is PtJump) {
|
if (jump is PtJump) {
|
||||||
translateCompareAndJumpIfTrue(condition, jump)
|
translateCompareAndJumpIfTrue(condition, jump)
|
||||||
|
} else {
|
||||||
|
val endLabel = makeLabel("if_end")
|
||||||
|
translateCompareAndJumpIfFalse(condition, endLabel)
|
||||||
|
translate(stmt.ifScope)
|
||||||
|
out(endLabel)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// both true and else parts
|
||||||
|
val elseLabel = makeLabel("if_else")
|
||||||
val endLabel = makeLabel("if_end")
|
val endLabel = makeLabel("if_end")
|
||||||
translateCompareAndJumpIfFalse(condition, endLabel)
|
translateCompareAndJumpIfFalse(condition, elseLabel)
|
||||||
translate(stmt.ifScope)
|
translate(stmt.ifScope)
|
||||||
|
jmp(endLabel)
|
||||||
|
out(elseLabel)
|
||||||
|
translate(stmt.elseScope)
|
||||||
out(endLabel)
|
out(endLabel)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
// both true and else parts
|
|
||||||
val elseLabel = makeLabel("if_else")
|
|
||||||
val endLabel = makeLabel("if_end")
|
|
||||||
translateCompareAndJumpIfFalse(condition, elseLabel)
|
|
||||||
translate(stmt.ifScope)
|
|
||||||
jmp(endLabel)
|
|
||||||
out(elseLabel)
|
|
||||||
translate(stmt.elseScope)
|
|
||||||
out(endLabel)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun requireComparisonExpression(condition: PtExpression) {
|
private fun requireComparisonExpression(condition: PtExpression) {
|
||||||
if(condition !is PtBinaryExpression || condition.operator !in ComparisonOperators)
|
if (!(condition is PtRpn && condition.finalOperator() in ComparisonOperators) && !(condition is PtBinaryExpression && condition.operator in ComparisonOperators))
|
||||||
throw AssemblyError("expected boolean comparison expression $condition")
|
throw AssemblyError("expected boolean comparison expression $condition")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -980,7 +983,11 @@ $repeatLabel lda $counterVar
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal fun pointerViaIndexRegisterPossible(pointerOffsetExpr: PtExpression): Pair<PtExpression, PtExpression>? {
|
internal fun pointerViaIndexRegisterPossible(pointerOffsetExpr: PtExpression): Pair<PtExpression, PtExpression>? {
|
||||||
if(pointerOffsetExpr is PtBinaryExpression && pointerOffsetExpr.operator=="+") {
|
if (pointerOffsetExpr is PtRpn) {
|
||||||
|
TODO("RPN")
|
||||||
|
}
|
||||||
|
else if (pointerOffsetExpr is PtBinaryExpression) {
|
||||||
|
if (pointerOffsetExpr.operator != "+") return null
|
||||||
val leftDt = pointerOffsetExpr.left.type
|
val leftDt = pointerOffsetExpr.left.type
|
||||||
val rightDt = pointerOffsetExpr.left.type
|
val rightDt = pointerOffsetExpr.left.type
|
||||||
if(leftDt == DataType.UWORD && rightDt == DataType.UBYTE)
|
if(leftDt == DataType.UWORD && rightDt == DataType.UBYTE)
|
||||||
@ -1001,7 +1008,6 @@ $repeatLabel lda $counterVar
|
|||||||
if(leftTc!=null && leftTc.value.type == DataType.UBYTE)
|
if(leftTc!=null && leftTc.value.type == DataType.UBYTE)
|
||||||
return Pair(pointerOffsetExpr.right, leftTc.value)
|
return Pair(pointerOffsetExpr.right, leftTc.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
@ -1022,7 +1028,6 @@ $repeatLabel lda $counterVar
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if(expr.operator=="+") {
|
if(expr.operator=="+") {
|
||||||
val ptrAndIndex = pointerViaIndexRegisterPossible(expr)
|
val ptrAndIndex = pointerViaIndexRegisterPossible(expr)
|
||||||
if(ptrAndIndex!=null) {
|
if(ptrAndIndex!=null) {
|
||||||
|
@ -17,8 +17,8 @@ class ExperiCodeGen: ICodeGeneratorBackend {
|
|||||||
errors: IErrorReporter
|
errors: IErrorReporter
|
||||||
): IAssemblyProgram? {
|
): IAssemblyProgram? {
|
||||||
|
|
||||||
// If we want RPN expressions instead, use this:
|
if(options.useRPN)
|
||||||
// program.transformBinExprToRPN()
|
program.transformBinExprToRPN()
|
||||||
|
|
||||||
// you could write a code generator directly on the PtProgram AST,
|
// you could write a code generator directly on the PtProgram AST,
|
||||||
// but you can also use the Intermediate Representation to build a codegen on:
|
// but you can also use the Intermediate Representation to build a codegen on:
|
||||||
|
@ -92,10 +92,14 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express
|
|||||||
value.add(origAssign.value)
|
value.add(origAssign.value)
|
||||||
} else {
|
} else {
|
||||||
require(origAssign.operator.endsWith('='))
|
require(origAssign.operator.endsWith('='))
|
||||||
value = PtBinaryExpression(origAssign.operator.dropLast(1), origAssign.value.type, origAssign.value.position)
|
if(codeGen.program.binaryExpressionsAreRPN) {
|
||||||
val left: PtExpression = origAssign.target.children.single() as PtExpression
|
TODO("RPN")
|
||||||
value.add(left)
|
} else {
|
||||||
value.add(origAssign.value)
|
value = PtBinaryExpression(origAssign.operator.dropLast(1), origAssign.value.type, origAssign.value.position)
|
||||||
|
val left: PtExpression = origAssign.target.children.single() as PtExpression
|
||||||
|
value.add(left)
|
||||||
|
value.add(origAssign.value)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
normalAssign.add(value)
|
normalAssign.add(value)
|
||||||
return translateRegularAssign(normalAssign)
|
return translateRegularAssign(normalAssign)
|
||||||
@ -262,10 +266,14 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express
|
|||||||
val tr = if(itemsize==1) {
|
val tr = if(itemsize==1) {
|
||||||
expressionEval.translateExpression(array.index)
|
expressionEval.translateExpression(array.index)
|
||||||
} else {
|
} else {
|
||||||
val mult = PtBinaryExpression("*", DataType.UBYTE, array.position)
|
if(codeGen.program.binaryExpressionsAreRPN) {
|
||||||
mult.children += array.index
|
TODO("RPN")
|
||||||
mult.children += PtNumber(DataType.UBYTE, itemsize.toDouble(), array.position)
|
} else {
|
||||||
expressionEval.translateExpression(mult)
|
val mult = PtBinaryExpression("*", DataType.UBYTE, array.position)
|
||||||
|
mult.children += array.index
|
||||||
|
mult.children += PtNumber(DataType.UBYTE, itemsize.toDouble(), array.position)
|
||||||
|
expressionEval.translateExpression(mult)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
addToResult(result, tr, tr.resultReg, -1)
|
addToResult(result, tr, tr.resultReg, -1)
|
||||||
return Pair(result, tr.resultReg)
|
return Pair(result, tr.resultReg)
|
||||||
|
@ -898,57 +898,67 @@ class IRCodeGen(
|
|||||||
|
|
||||||
private fun translate(ifElse: PtIfElse): IRCodeChunks {
|
private fun translate(ifElse: PtIfElse): IRCodeChunks {
|
||||||
val condition = ifElse.condition
|
val condition = ifElse.condition
|
||||||
if(condition is PtBinaryExpression) {
|
when (condition) {
|
||||||
if(condition.operator !in ComparisonOperators)
|
is PtBinaryExpression -> {
|
||||||
throw AssemblyError("if condition should only be a binary comparison expression")
|
if(condition.operator !in ComparisonOperators)
|
||||||
|
throw AssemblyError("if condition should only be a binary comparison expression")
|
||||||
|
|
||||||
val signed = condition.left.type in SignedDatatypes
|
val signed = condition.left.type in SignedDatatypes
|
||||||
val irDtLeft = irType(condition.left.type)
|
val irDtLeft = irType(condition.left.type)
|
||||||
val goto = ifElse.ifScope.children.firstOrNull() as? PtJump
|
val goto = ifElse.ifScope.children.firstOrNull() as? PtJump
|
||||||
return when {
|
return when {
|
||||||
goto!=null && ifElse.elseScope.children.isEmpty() -> translateIfFollowedByJustGoto(ifElse, goto, irDtLeft, signed)
|
goto!=null && ifElse.elseScope.children.isEmpty() -> translateIfFollowedByJustGoto(ifElse, goto, irDtLeft, signed)
|
||||||
constValue(condition.right) == 0.0 -> translateIfElseZeroComparison(ifElse, irDtLeft, signed)
|
constValue(condition.right) == 0.0 -> translateIfElseZeroComparison(ifElse, irDtLeft, signed)
|
||||||
else -> translateIfElseNonZeroComparison(ifElse, irDtLeft, signed)
|
else -> translateIfElseNonZeroComparison(ifElse, irDtLeft, signed)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
is PtRpn -> {
|
||||||
|
TODO("RPN")
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
TODO("weird condition node: $condition")
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
TODO("weird condition node: $condition")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun translateIfFollowedByJustGoto(ifElse: PtIfElse, goto: PtJump, irDtLeft: IRDataType, signed: Boolean): MutableList<IRCodeChunkBase> {
|
private fun translateIfFollowedByJustGoto(ifElse: PtIfElse, goto: PtJump, irDtLeft: IRDataType, signed: Boolean): MutableList<IRCodeChunkBase> {
|
||||||
val result = mutableListOf<IRCodeChunkBase>()
|
if(program.binaryExpressionsAreRPN) {
|
||||||
val condition = ifElse.condition as PtBinaryExpression
|
TODO ("RPN")
|
||||||
if(irDtLeft==IRDataType.FLOAT) {
|
|
||||||
val leftTr = expressionEval.translateExpression(condition.left)
|
|
||||||
addToResult(result, leftTr, -1, leftTr.resultFpReg)
|
|
||||||
val rightTr = expressionEval.translateExpression(condition.right)
|
|
||||||
addToResult(result, rightTr, -1, rightTr.resultFpReg)
|
|
||||||
result += IRCodeChunk(null,null).also {
|
|
||||||
val compResultReg = registers.nextFree()
|
|
||||||
it += IRInstruction(Opcode.FCOMP, IRDataType.FLOAT, reg1=compResultReg, fpReg1 = leftTr.resultFpReg, fpReg2 = rightTr.resultFpReg)
|
|
||||||
val gotoOpcode = when (condition.operator) {
|
|
||||||
"==" -> Opcode.BZ
|
|
||||||
"!=" -> Opcode.BNZ
|
|
||||||
"<" -> Opcode.BLEZS
|
|
||||||
">" -> Opcode.BGEZS
|
|
||||||
"<=" -> Opcode.BLZS
|
|
||||||
">=" -> Opcode.BGZS
|
|
||||||
else -> throw AssemblyError("weird operator")
|
|
||||||
}
|
|
||||||
it += if (goto.address != null)
|
|
||||||
IRInstruction(gotoOpcode, IRDataType.BYTE, reg1 = compResultReg, value = goto.address?.toInt())
|
|
||||||
else if (goto.generatedLabel != null)
|
|
||||||
IRInstruction(gotoOpcode, IRDataType.BYTE, reg1 = compResultReg, labelSymbol = goto.generatedLabel)
|
|
||||||
else
|
|
||||||
IRInstruction(gotoOpcode, IRDataType.BYTE, reg1 = compResultReg, labelSymbol = goto.identifier!!.name)
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
} else {
|
} else {
|
||||||
val rightConst = condition.right.asConstInteger()
|
val result = mutableListOf<IRCodeChunkBase>()
|
||||||
return if(rightConst==0)
|
val condition = ifElse.condition as PtBinaryExpression
|
||||||
ifZeroIntThenJump(result, ifElse, signed, irDtLeft, goto)
|
if(irDtLeft==IRDataType.FLOAT) {
|
||||||
else {
|
val leftTr = expressionEval.translateExpression(condition.left)
|
||||||
ifNonZeroIntThenJump(result, ifElse, signed, irDtLeft, goto)
|
addToResult(result, leftTr, -1, leftTr.resultFpReg)
|
||||||
|
val rightTr = expressionEval.translateExpression(condition.right)
|
||||||
|
addToResult(result, rightTr, -1, rightTr.resultFpReg)
|
||||||
|
result += IRCodeChunk(null,null).also {
|
||||||
|
val compResultReg = registers.nextFree()
|
||||||
|
it += IRInstruction(Opcode.FCOMP, IRDataType.FLOAT, reg1=compResultReg, fpReg1 = leftTr.resultFpReg, fpReg2 = rightTr.resultFpReg)
|
||||||
|
val gotoOpcode = when (condition.operator) {
|
||||||
|
"==" -> Opcode.BZ
|
||||||
|
"!=" -> Opcode.BNZ
|
||||||
|
"<" -> Opcode.BLEZS
|
||||||
|
">" -> Opcode.BGEZS
|
||||||
|
"<=" -> Opcode.BLZS
|
||||||
|
">=" -> Opcode.BGZS
|
||||||
|
else -> throw AssemblyError("weird operator")
|
||||||
|
}
|
||||||
|
it += if (goto.address != null)
|
||||||
|
IRInstruction(gotoOpcode, IRDataType.BYTE, reg1 = compResultReg, value = goto.address?.toInt())
|
||||||
|
else if (goto.generatedLabel != null)
|
||||||
|
IRInstruction(gotoOpcode, IRDataType.BYTE, reg1 = compResultReg, labelSymbol = goto.generatedLabel)
|
||||||
|
else
|
||||||
|
IRInstruction(gotoOpcode, IRDataType.BYTE, reg1 = compResultReg, labelSymbol = goto.identifier!!.name)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
} else {
|
||||||
|
val rightConst = condition.right.asConstInteger()
|
||||||
|
return if(rightConst==0)
|
||||||
|
ifZeroIntThenJump(result, ifElse, signed, irDtLeft, goto)
|
||||||
|
else {
|
||||||
|
ifNonZeroIntThenJump(result, ifElse, signed, irDtLeft, goto)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -960,6 +970,7 @@ class IRCodeGen(
|
|||||||
irDtLeft: IRDataType,
|
irDtLeft: IRDataType,
|
||||||
goto: PtJump
|
goto: PtJump
|
||||||
): MutableList<IRCodeChunkBase> {
|
): MutableList<IRCodeChunkBase> {
|
||||||
|
require(!program.binaryExpressionsAreRPN)
|
||||||
val condition = ifElse.condition as PtBinaryExpression
|
val condition = ifElse.condition as PtBinaryExpression
|
||||||
val leftTr = expressionEval.translateExpression(condition.left)
|
val leftTr = expressionEval.translateExpression(condition.left)
|
||||||
addToResult(result, leftTr, leftTr.resultReg, -1)
|
addToResult(result, leftTr, leftTr.resultReg, -1)
|
||||||
@ -988,6 +999,7 @@ class IRCodeGen(
|
|||||||
irDtLeft: IRDataType,
|
irDtLeft: IRDataType,
|
||||||
goto: PtJump
|
goto: PtJump
|
||||||
): MutableList<IRCodeChunkBase> {
|
): MutableList<IRCodeChunkBase> {
|
||||||
|
require(!program.binaryExpressionsAreRPN)
|
||||||
val condition = ifElse.condition as PtBinaryExpression
|
val condition = ifElse.condition as PtBinaryExpression
|
||||||
val leftTr = expressionEval.translateExpression(condition.left)
|
val leftTr = expressionEval.translateExpression(condition.left)
|
||||||
addToResult(result, leftTr, leftTr.resultReg, -1)
|
addToResult(result, leftTr, leftTr.resultReg, -1)
|
||||||
@ -1041,6 +1053,7 @@ class IRCodeGen(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun translateIfElseZeroComparison(ifElse: PtIfElse, irDtLeft: IRDataType, signed: Boolean): IRCodeChunks {
|
private fun translateIfElseZeroComparison(ifElse: PtIfElse, irDtLeft: IRDataType, signed: Boolean): IRCodeChunks {
|
||||||
|
require(!program.binaryExpressionsAreRPN)
|
||||||
val result = mutableListOf<IRCodeChunkBase>()
|
val result = mutableListOf<IRCodeChunkBase>()
|
||||||
val elseBranch: Opcode
|
val elseBranch: Opcode
|
||||||
val compResultReg: Int
|
val compResultReg: Int
|
||||||
@ -1102,8 +1115,8 @@ class IRCodeGen(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun translateIfElseNonZeroComparison(ifElse: PtIfElse, irDtLeft: IRDataType, signed: Boolean): IRCodeChunks {
|
private fun translateIfElseNonZeroComparison(ifElse: PtIfElse, irDtLeft: IRDataType, signed: Boolean): IRCodeChunks {
|
||||||
|
require(!program.binaryExpressionsAreRPN)
|
||||||
val result = mutableListOf<IRCodeChunkBase>()
|
val result = mutableListOf<IRCodeChunkBase>()
|
||||||
|
|
||||||
val elseBranchOpcode: Opcode
|
val elseBranchOpcode: Opcode
|
||||||
val elseBranchFirstReg: Int
|
val elseBranchFirstReg: Int
|
||||||
val elseBranchSecondReg: Int
|
val elseBranchSecondReg: Int
|
||||||
|
@ -17,8 +17,10 @@ class VmCodeGen: ICodeGeneratorBackend {
|
|||||||
options: CompilationOptions,
|
options: CompilationOptions,
|
||||||
errors: IErrorReporter
|
errors: IErrorReporter
|
||||||
): IAssemblyProgram? {
|
): IAssemblyProgram? {
|
||||||
// If we want RPN expressions instead, use this:
|
|
||||||
// program.transformBinExprToRPN()
|
if(options.useRPN)
|
||||||
|
program.transformBinExprToRPN()
|
||||||
|
|
||||||
val irCodeGen = IRCodeGen(program, symbolTable, options, errors)
|
val irCodeGen = IRCodeGen(program, symbolTable, options, errors)
|
||||||
val irProgram = irCodeGen.generate()
|
val irProgram = irCodeGen.generate()
|
||||||
return VmAssemblyProgram(irProgram.name, irProgram)
|
return VmAssemblyProgram(irProgram.name, irProgram)
|
||||||
|
@ -52,6 +52,7 @@ private fun compileMain(args: Array<String>): Boolean {
|
|||||||
val startVm by cli.option(ArgType.Boolean, fullName = "vm", description = "load and run a .p8ir IR source file in the VM")
|
val startVm by cli.option(ArgType.Boolean, fullName = "vm", description = "load and run a .p8ir IR source file in the VM")
|
||||||
val watchMode by cli.option(ArgType.Boolean, fullName = "watch", description = "continuous compilation mode (watch for file changes)")
|
val watchMode by cli.option(ArgType.Boolean, fullName = "watch", description = "continuous compilation mode (watch for file changes)")
|
||||||
val varsHigh by cli.option(ArgType.Boolean, fullName = "varshigh", description = "put uninitialized variables in high memory area instead of at the end of the program")
|
val varsHigh by cli.option(ArgType.Boolean, fullName = "varshigh", description = "put uninitialized variables in high memory area instead of at the end of the program")
|
||||||
|
val useRPN by cli.option(ArgType.Boolean, fullName = "rpn", description = "use RPN for expression code-generation (experimental)")
|
||||||
val moduleFiles by cli.argument(ArgType.String, fullName = "modules", description = "main module file(s) to compile").multiple(999)
|
val moduleFiles by cli.argument(ArgType.String, fullName = "modules", description = "main module file(s) to compile").multiple(999)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -126,6 +127,7 @@ private fun compileMain(args: Array<String>): Boolean {
|
|||||||
asmListfile == true,
|
asmListfile == true,
|
||||||
experimentalCodegen == true,
|
experimentalCodegen == true,
|
||||||
varsHigh == true,
|
varsHigh == true,
|
||||||
|
useRPN == true,
|
||||||
compilationTarget,
|
compilationTarget,
|
||||||
evalStackAddr,
|
evalStackAddr,
|
||||||
processedSymbols,
|
processedSymbols,
|
||||||
@ -190,6 +192,7 @@ private fun compileMain(args: Array<String>): Boolean {
|
|||||||
asmListfile == true,
|
asmListfile == true,
|
||||||
experimentalCodegen == true,
|
experimentalCodegen == true,
|
||||||
varsHigh == true,
|
varsHigh == true,
|
||||||
|
useRPN == true,
|
||||||
compilationTarget,
|
compilationTarget,
|
||||||
evalStackAddr,
|
evalStackAddr,
|
||||||
processedSymbols,
|
processedSymbols,
|
||||||
|
@ -36,6 +36,7 @@ class CompilerArguments(val filepath: Path,
|
|||||||
val asmListfile: Boolean,
|
val asmListfile: Boolean,
|
||||||
val experimentalCodegen: Boolean,
|
val experimentalCodegen: Boolean,
|
||||||
val varsHigh: Boolean,
|
val varsHigh: Boolean,
|
||||||
|
val useRPN: Boolean,
|
||||||
val compilationTarget: String,
|
val compilationTarget: String,
|
||||||
val evalStackBaseAddress: UInt?,
|
val evalStackBaseAddress: UInt?,
|
||||||
val symbolDefs: Map<String, String>,
|
val symbolDefs: Map<String, String>,
|
||||||
@ -76,6 +77,7 @@ fun compileProgram(args: CompilerArguments): CompilationResult? {
|
|||||||
asmListfile = args.asmListfile
|
asmListfile = args.asmListfile
|
||||||
experimentalCodegen = args.experimentalCodegen
|
experimentalCodegen = args.experimentalCodegen
|
||||||
varsHigh = args.varsHigh
|
varsHigh = args.varsHigh
|
||||||
|
useRPN = args.useRPN
|
||||||
evalStackBaseAddress = args.evalStackBaseAddress
|
evalStackBaseAddress = args.evalStackBaseAddress
|
||||||
outputDir = args.outputDir.normalize()
|
outputDir = args.outputDir.normalize()
|
||||||
symbolDefs = args.symbolDefs
|
symbolDefs = args.symbolDefs
|
||||||
|
@ -33,6 +33,7 @@ private fun compileTheThing(filepath: Path, optimize: Boolean, target: ICompilat
|
|||||||
asmListfile = false,
|
asmListfile = false,
|
||||||
experimentalCodegen = false,
|
experimentalCodegen = false,
|
||||||
varsHigh = false,
|
varsHigh = false,
|
||||||
|
useRPN = false,
|
||||||
compilationTarget = target.name,
|
compilationTarget = target.name,
|
||||||
evalStackBaseAddress = null,
|
evalStackBaseAddress = null,
|
||||||
symbolDefs = emptyMap(),
|
symbolDefs = emptyMap(),
|
||||||
|
@ -50,6 +50,7 @@ class TestCompilerOptionSourcedirs: FunSpec({
|
|||||||
asmListfile = false,
|
asmListfile = false,
|
||||||
experimentalCodegen = false,
|
experimentalCodegen = false,
|
||||||
varsHigh = false,
|
varsHigh = false,
|
||||||
|
useRPN = false,
|
||||||
compilationTarget = Cx16Target.NAME,
|
compilationTarget = Cx16Target.NAME,
|
||||||
evalStackBaseAddress = null,
|
evalStackBaseAddress = null,
|
||||||
symbolDefs = emptyMap(),
|
symbolDefs = emptyMap(),
|
||||||
|
@ -31,6 +31,7 @@ internal fun compileFile(
|
|||||||
asmListfile = false,
|
asmListfile = false,
|
||||||
experimentalCodegen = false,
|
experimentalCodegen = false,
|
||||||
varsHigh = false,
|
varsHigh = false,
|
||||||
|
useRPN = false,
|
||||||
platform.name,
|
platform.name,
|
||||||
evalStackBaseAddress = null,
|
evalStackBaseAddress = null,
|
||||||
symbolDefs = emptyMap(),
|
symbolDefs = emptyMap(),
|
||||||
|
@ -1,11 +1,26 @@
|
|||||||
main {
|
%import textio
|
||||||
uword[10] answers_animals
|
%import test_stack
|
||||||
|
%zeropage basicsafe
|
||||||
|
%option no_sysinit
|
||||||
|
|
||||||
sub start() {
|
main {
|
||||||
ubyte current_question = 1
|
|
||||||
uword previous_animals = 33
|
sub start() {
|
||||||
current_question = msb(answers_animals[current_question]) ; TODO takes 1 more vm registers than 8.10
|
test_stack.test()
|
||||||
answers_animals[current_question] = mkword(msb(previous_animals), 0) ; TODO takes 1 more vm registers than 8.10
|
uword xx=32
|
||||||
; TODO expected result: 7 registers in 8.10, now takes 9 instead
|
cx16.r0L = 3
|
||||||
|
|
||||||
|
if cx16.r0L in "derp" {
|
||||||
|
xx++
|
||||||
}
|
}
|
||||||
|
|
||||||
|
xx = xx+(3*func(xx)+xx*2*cx16.r0L)
|
||||||
|
txt.print_uw(xx)
|
||||||
|
test_stack.test()
|
||||||
|
}
|
||||||
|
|
||||||
|
sub func(uword value) -> uword {
|
||||||
|
value ++
|
||||||
|
return value
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -42,7 +42,8 @@ class RequestParser : Take {
|
|||||||
quietAssembler = false,
|
quietAssembler = false,
|
||||||
asmListfile = false,
|
asmListfile = false,
|
||||||
experimentalCodegen = false,
|
experimentalCodegen = false,
|
||||||
varsHigh = false
|
varsHigh = false,
|
||||||
|
useRPN = false
|
||||||
)
|
)
|
||||||
val compilationResult = compileProgram(args)
|
val compilationResult = compileProgram(args)
|
||||||
return RsJson(Jsonding())
|
return RsJson(Jsonding())
|
||||||
|
Loading…
Reference in New Issue
Block a user