don't allow ~ on booleans, also introduce SZ and SNZ instructions in IR to complete the conditional-set instruction list.

This commit is contained in:
Irmen de Jong 2022-12-28 21:19:38 +01:00
parent 1e6fa77633
commit a7df094ff4
5 changed files with 52 additions and 37 deletions

View File

@ -72,27 +72,13 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
} }
result result
} }
is PtTypeCast -> { is PtTypeCast -> translate(expr, resultRegister, resultFpRegister)
translate(expr, resultRegister, resultFpRegister) is PtPrefix -> translate(expr, resultRegister, resultFpRegister)
} is PtArrayIndexer -> translate(expr, resultRegister, resultFpRegister)
is PtPrefix -> { is PtBinaryExpression -> translate(expr, resultRegister, resultFpRegister)
translate(expr, resultRegister, resultFpRegister) is PtBuiltinFunctionCall -> codeGen.translateBuiltinFunc(expr, resultRegister)
} is PtFunctionCall -> translate(expr, resultRegister, resultFpRegister)
is PtArrayIndexer -> { is PtContainmentCheck -> translate(expr, resultRegister, resultFpRegister)
translate(expr, resultRegister, resultFpRegister)
}
is PtBinaryExpression -> {
translate(expr, resultRegister, resultFpRegister)
}
is PtBuiltinFunctionCall -> {
codeGen.translateBuiltinFunc(expr, resultRegister)
}
is PtFunctionCall -> {
translate(expr, resultRegister, resultFpRegister)
}
is PtContainmentCheck -> {
translate(expr, resultRegister, resultFpRegister)
}
is PtRange, is PtRange,
is PtArray, is PtArray,
is PtString -> throw AssemblyError("range/arrayliteral/string should no longer occur as expression") is PtString -> throw AssemblyError("range/arrayliteral/string should no longer occur as expression")
@ -429,6 +415,11 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
it += IRInstruction(Opcode.INV, vmDt, reg1 = resultRegister) it += IRInstruction(Opcode.INV, vmDt, reg1 = resultRegister)
it += IRInstruction(Opcode.AND, vmDt, reg1 = resultRegister, value = 1) it += IRInstruction(Opcode.AND, vmDt, reg1 = resultRegister, value = 1)
} }
} else {
if(constValue(binExpr.right)==0.0) {
result += translateExpression(binExpr.left, resultRegister, -1)
val opcode = if (notEquals) Opcode.SNZ else Opcode.SZ
addInstr(result, IRInstruction(opcode, vmDt, reg1 = resultRegister, reg2 = resultRegister), null)
} else { } else {
val rightResultReg = codeGen.registers.nextFree() val rightResultReg = codeGen.registers.nextFree()
result += translateExpression(binExpr.left, resultRegister, -1) result += translateExpression(binExpr.left, resultRegister, -1)
@ -437,6 +428,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
addInstr(result, IRInstruction(opcode, vmDt, reg1 = resultRegister, reg2 = rightResultReg), null) addInstr(result, IRInstruction(opcode, vmDt, reg1 = resultRegister, reg2 = rightResultReg), null)
} }
} }
}
return result return result
} }

View File

@ -835,6 +835,8 @@ internal class AstChecker(private val program: Program,
else if(expr.operator == "~") { else if(expr.operator == "~") {
if(dt !in IntegerDatatypes) if(dt !in IntegerDatatypes)
errors.err("can only use bitwise invert on integer types", expr.position) errors.err("can only use bitwise invert on integer types", expr.position)
if(dt==DataType.BOOL)
errors.err("bitwise invert is for integer types, use 'not' on booleans", expr.position)
} }
super.visit(expr) super.visit(expr)
} }

View File

@ -6,7 +6,6 @@ For next release
- make sure bool value is always 0 or 1 (all casts should convert), then: - make sure bool value is always 0 or 1 (all casts should convert), then:
- rewrite bool=bool^1 into bool=not bool - rewrite bool=bool^1 into bool=not bool
- should solve: bool bb = not bb -> larger code than bool bb ^= 1 - should solve: bool bb = not bb -> larger code than bool bb ^= 1
- should solve: bool xx = ~xx -> larger code than xx ^= 1
... ...

View File

@ -85,16 +85,18 @@ bgts reg1, reg2, address - jump to location in program given by l
bge reg1, reg2, address - jump to location in program given by location, if reg1 >= reg2 (unsigned) bge reg1, reg2, address - jump to location in program given by location, if reg1 >= reg2 (unsigned)
bges reg1, reg2, address - jump to location in program given by location, if reg1 >= reg2 (signed) bges reg1, reg2, address - jump to location in program given by location, if reg1 >= reg2 (signed)
( NOTE: there are no blt/ble instructions because these are equivalent to bgt/bge with the operands swapped around.) ( NOTE: there are no blt/ble instructions because these are equivalent to bgt/bge with the operands swapped around.)
seq reg1, reg2 - set reg=1 if reg1 == reg2, otherwise set reg1=0 sz reg1, reg2 - set reg1=1 if reg2==0, otherwise set reg1=0
sne reg1, reg2 - set reg=1 if reg1 != reg2, otherwise set reg1=0 snz reg1, reg2 - set reg1=1 if reg2!=0, otherwise set reg1=0
slt reg1, reg2 - set reg=1 if reg1 < reg2 (unsigned), otherwise set reg1=0 seq reg1, reg2 - set reg1=1 if reg1 == reg2, otherwise set reg1=0
slts reg1, reg2 - set reg=1 if reg1 < reg2 (signed), otherwise set reg1=0 sne reg1, reg2 - set reg1=1 if reg1 != reg2, otherwise set reg1=0
sle reg1, reg2 - set reg=1 if reg1 <= reg2 (unsigned), otherwise set reg1=0 slt reg1, reg2 - set reg1=1 if reg1 < reg2 (unsigned), otherwise set reg1=0
sles reg1, reg2 - set reg=1 if reg1 <= reg2 (signed), otherwise set reg1=0 slts reg1, reg2 - set reg1=1 if reg1 < reg2 (signed), otherwise set reg1=0
sgt reg1, reg2 - set reg=1 if reg1 > reg2 (unsigned), otherwise set reg1=0 sle reg1, reg2 - set reg1=1 if reg1 <= reg2 (unsigned), otherwise set reg1=0
sgts reg1, reg2 - set reg=1 if reg1 > reg2 (signed), otherwise set reg1=0 sles reg1, reg2 - set reg1=1 if reg1 <= reg2 (signed), otherwise set reg1=0
sge reg1, reg2 - set reg=1 if reg1 >= reg2 (unsigned), otherwise set reg1=0 sgt reg1, reg2 - set reg1=1 if reg1 > reg2 (unsigned), otherwise set reg1=0
sges reg1, reg2 - set reg=1 if reg1 >= reg2 (signed), otherwise set reg1=0 sgts reg1, reg2 - set reg1=1 if reg1 > reg2 (signed), otherwise set reg1=0
sge reg1, reg2 - set reg1=1 if reg1 >= reg2 (unsigned), otherwise set reg1=0
sges reg1, reg2 - set reg1=1 if reg1 >= reg2 (signed), otherwise set reg1=0
ARITHMETIC ARITHMETIC
@ -253,6 +255,8 @@ enum class Opcode {
BGTS, BGTS,
BGE, BGE,
BGES, BGES,
SZ,
SNZ,
SEQ, SEQ,
SNE, SNE,
SLT, SLT,
@ -569,6 +573,8 @@ val instructionFormats = mutableMapOf(
Opcode.BGTS to InstructionFormat.from("BW,<r1,<r2,<v"), Opcode.BGTS to InstructionFormat.from("BW,<r1,<r2,<v"),
Opcode.BGE to InstructionFormat.from("BW,<r1,<r2,<v"), Opcode.BGE to InstructionFormat.from("BW,<r1,<r2,<v"),
Opcode.BGES to InstructionFormat.from("BW,<r1,<r2,<v"), Opcode.BGES to InstructionFormat.from("BW,<r1,<r2,<v"),
Opcode.SZ to InstructionFormat.from("BW,>r1,<r2"),
Opcode.SNZ to InstructionFormat.from("BW,>r1,<r2"),
Opcode.SEQ to InstructionFormat.from("BW,<>r1,<r2"), Opcode.SEQ to InstructionFormat.from("BW,<>r1,<r2"),
Opcode.SNE to InstructionFormat.from("BW,<>r1,<r2"), Opcode.SNE to InstructionFormat.from("BW,<>r1,<r2"),
Opcode.SLT to InstructionFormat.from("BW,<>r1,<r2"), Opcode.SLT to InstructionFormat.from("BW,<>r1,<r2"),

View File

@ -186,6 +186,8 @@ class VirtualMachine(irProgram: IRProgram) {
Opcode.BGTS -> InsBGTS(ins) Opcode.BGTS -> InsBGTS(ins)
Opcode.BGE -> InsBGEU(ins) Opcode.BGE -> InsBGEU(ins)
Opcode.BGES -> InsBGES(ins) Opcode.BGES -> InsBGES(ins)
Opcode.SZ -> InsSZ(ins)
Opcode.SNZ -> InsSNZ(ins)
Opcode.SEQ -> InsSEQ(ins) Opcode.SEQ -> InsSEQ(ins)
Opcode.SNE -> InsSNE(ins) Opcode.SNE -> InsSNE(ins)
Opcode.SLT -> InsSLT(ins) Opcode.SLT -> InsSLT(ins)
@ -782,6 +784,20 @@ class VirtualMachine(irProgram: IRProgram) {
nextPc() nextPc()
} }
private fun InsSZ(i: IRInstruction) {
val (_: Int, right: Int) = getSetOnConditionOperands(i)
val value = if(right==0) 1 else 0
setResultReg(i.reg1!!, value, i.type!!)
nextPc()
}
private fun InsSNZ(i: IRInstruction) {
val (_: Int, right: Int) = getSetOnConditionOperands(i)
val value = if(right!=0) 1 else 0
setResultReg(i.reg1!!, value, i.type!!)
nextPc()
}
private fun InsSEQ(i: IRInstruction) { private fun InsSEQ(i: IRInstruction) {
val (left: Int, right: Int) = getSetOnConditionOperands(i) val (left: Int, right: Int) = getSetOnConditionOperands(i)
val value = if(left==right) 1 else 0 val value = if(left==right) 1 else 0