Add object equality and reference ops to bytecode
This commit is contained in:
1 parent
9c56cf751b
commit
fd1548c86c
7 files changed
+121
-8
No files matched your search
@@ -133,6 +133,7 @@ class BytecodeBuilder {
|
||||
Opcode.CMP_EQ_INT_REAL, Opcode.CMP_EQ_REAL_INT, Opcode.CMP_LT_INT_REAL, Opcode.CMP_LT_REAL_INT,
|
||||
Opcode.CMP_LTE_INT_REAL, Opcode.CMP_LTE_REAL_INT, Opcode.CMP_GT_INT_REAL, Opcode.CMP_GT_REAL_INT,
|
||||
Opcode.CMP_GTE_INT_REAL, Opcode.CMP_GTE_REAL_INT, Opcode.CMP_NEQ_INT_REAL, Opcode.CMP_NEQ_REAL_INT,
|
||||
Opcode.CMP_EQ_OBJ, Opcode.CMP_NEQ_OBJ, Opcode.CMP_REF_EQ_OBJ, Opcode.CMP_REF_NEQ_OBJ,
|
||||
Opcode.AND_BOOL, Opcode.OR_BOOL ->
|
||||
listOf(OperandKind.SLOT, OperandKind.SLOT, OperandKind.SLOT)
|
||||
Opcode.INC_INT, Opcode.DEC_INT, Opcode.RET ->
|
||||
|
||||
@@ -253,6 +253,16 @@ class BytecodeCompiler {
|
||||
BinOp.GTE -> {
|
||||
compileCompareGte(a, b, out)
|
||||
}
|
||||
BinOp.REF_EQ -> {
|
||||
if (a.type != SlotType.OBJ || b.type != SlotType.OBJ) return null
|
||||
builder.emit(Opcode.CMP_REF_EQ_OBJ, a.slot, b.slot, out)
|
||||
CompiledValue(out, SlotType.BOOL)
|
||||
}
|
||||
BinOp.REF_NEQ -> {
|
||||
if (a.type != SlotType.OBJ || b.type != SlotType.OBJ) return null
|
||||
builder.emit(Opcode.CMP_REF_NEQ_OBJ, a.slot, b.slot, out)
|
||||
CompiledValue(out, SlotType.BOOL)
|
||||
}
|
||||
BinOp.AND -> {
|
||||
if (a.type != SlotType.BOOL) return null
|
||||
builder.emit(Opcode.AND_BOOL, a.slot, b.slot, out)
|
||||
@@ -336,6 +346,10 @@ class BytecodeCompiler {
|
||||
builder.emit(Opcode.CMP_EQ_REAL_INT, a.slot, b.slot, out)
|
||||
CompiledValue(out, SlotType.BOOL)
|
||||
}
|
||||
a.type == SlotType.OBJ && b.type == SlotType.OBJ -> {
|
||||
builder.emit(Opcode.CMP_EQ_OBJ, a.slot, b.slot, out)
|
||||
CompiledValue(out, SlotType.BOOL)
|
||||
}
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
@@ -363,6 +377,10 @@ class BytecodeCompiler {
|
||||
builder.emit(Opcode.CMP_NEQ_REAL_INT, a.slot, b.slot, out)
|
||||
CompiledValue(out, SlotType.BOOL)
|
||||
}
|
||||
a.type == SlotType.OBJ && b.type == SlotType.OBJ -> {
|
||||
builder.emit(Opcode.CMP_NEQ_OBJ, a.slot, b.slot, out)
|
||||
CompiledValue(out, SlotType.BOOL)
|
||||
}
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,6 +101,7 @@ object BytecodeDisassembler {
|
||||
Opcode.CMP_EQ_INT_REAL, Opcode.CMP_EQ_REAL_INT, Opcode.CMP_LT_INT_REAL, Opcode.CMP_LT_REAL_INT,
|
||||
Opcode.CMP_LTE_INT_REAL, Opcode.CMP_LTE_REAL_INT, Opcode.CMP_GT_INT_REAL, Opcode.CMP_GT_REAL_INT,
|
||||
Opcode.CMP_GTE_INT_REAL, Opcode.CMP_GTE_REAL_INT, Opcode.CMP_NEQ_INT_REAL, Opcode.CMP_NEQ_REAL_INT,
|
||||
Opcode.CMP_EQ_OBJ, Opcode.CMP_NEQ_OBJ, Opcode.CMP_REF_EQ_OBJ, Opcode.CMP_REF_NEQ_OBJ,
|
||||
Opcode.AND_BOOL, Opcode.OR_BOOL ->
|
||||
listOf(OperandKind.SLOT, OperandKind.SLOT, OperandKind.SLOT)
|
||||
Opcode.INC_INT, Opcode.DEC_INT, Opcode.RET ->
|
||||
|
||||
@@ -72,14 +72,18 @@ class BytecodeVm {
|
||||
ip += fn.constIdWidth
|
||||
val dst = decoder.readSlot(code, ip)
|
||||
ip += fn.slotWidth
|
||||
val c = fn.constants[constId] as? BytecodeConst.ObjRef
|
||||
?: error("CONST_OBJ expects ObjRef at $constId")
|
||||
val obj = c.value
|
||||
when (obj) {
|
||||
is ObjInt -> frame.setInt(dst, obj.value)
|
||||
is ObjReal -> frame.setReal(dst, obj.value)
|
||||
is ObjBool -> frame.setBool(dst, obj.value)
|
||||
else -> frame.setObj(dst, obj)
|
||||
when (val c = fn.constants[constId]) {
|
||||
is BytecodeConst.ObjRef -> {
|
||||
val obj = c.value
|
||||
when (obj) {
|
||||
is ObjInt -> frame.setInt(dst, obj.value)
|
||||
is ObjReal -> frame.setReal(dst, obj.value)
|
||||
is ObjBool -> frame.setBool(dst, obj.value)
|
||||
else -> frame.setObj(dst, obj)
|
||||
}
|
||||
}
|
||||
is BytecodeConst.StringVal -> frame.setObj(dst, ObjString(c.value))
|
||||
else -> error("CONST_OBJ expects ObjRef/StringVal at $constId")
|
||||
}
|
||||
}
|
||||
Opcode.CONST_NULL -> {
|
||||
@@ -543,6 +547,42 @@ class BytecodeVm {
|
||||
ip += fn.slotWidth
|
||||
frame.setBool(dst, frame.getReal(a) != frame.getInt(b).toDouble())
|
||||
}
|
||||
Opcode.CMP_EQ_OBJ -> {
|
||||
val a = decoder.readSlot(code, ip)
|
||||
ip += fn.slotWidth
|
||||
val b = decoder.readSlot(code, ip)
|
||||
ip += fn.slotWidth
|
||||
val dst = decoder.readSlot(code, ip)
|
||||
ip += fn.slotWidth
|
||||
frame.setBool(dst, frame.getObj(a).equals(scope, frame.getObj(b)))
|
||||
}
|
||||
Opcode.CMP_NEQ_OBJ -> {
|
||||
val a = decoder.readSlot(code, ip)
|
||||
ip += fn.slotWidth
|
||||
val b = decoder.readSlot(code, ip)
|
||||
ip += fn.slotWidth
|
||||
val dst = decoder.readSlot(code, ip)
|
||||
ip += fn.slotWidth
|
||||
frame.setBool(dst, !frame.getObj(a).equals(scope, frame.getObj(b)))
|
||||
}
|
||||
Opcode.CMP_REF_EQ_OBJ -> {
|
||||
val a = decoder.readSlot(code, ip)
|
||||
ip += fn.slotWidth
|
||||
val b = decoder.readSlot(code, ip)
|
||||
ip += fn.slotWidth
|
||||
val dst = decoder.readSlot(code, ip)
|
||||
ip += fn.slotWidth
|
||||
frame.setBool(dst, frame.getObj(a) === frame.getObj(b))
|
||||
}
|
||||
Opcode.CMP_REF_NEQ_OBJ -> {
|
||||
val a = decoder.readSlot(code, ip)
|
||||
ip += fn.slotWidth
|
||||
val b = decoder.readSlot(code, ip)
|
||||
ip += fn.slotWidth
|
||||
val dst = decoder.readSlot(code, ip)
|
||||
ip += fn.slotWidth
|
||||
frame.setBool(dst, frame.getObj(a) !== frame.getObj(b))
|
||||
}
|
||||
Opcode.NOT_BOOL -> {
|
||||
val src = decoder.readSlot(code, ip)
|
||||
ip += fn.slotWidth
|
||||
|
||||
@@ -83,6 +83,10 @@ enum class Opcode(val code: Int) {
|
||||
CMP_GTE_REAL_INT(0x69),
|
||||
CMP_NEQ_INT_REAL(0x6A),
|
||||
CMP_NEQ_REAL_INT(0x6B),
|
||||
CMP_EQ_OBJ(0x6C),
|
||||
CMP_NEQ_OBJ(0x6D),
|
||||
CMP_REF_EQ_OBJ(0x6E),
|
||||
CMP_REF_NEQ_OBJ(0x6F),
|
||||
|
||||
NOT_BOOL(0x70),
|
||||
AND_BOOL(0x71),
|
||||
|
||||
Reference in new issue
Block a user