static public InstructionCode CodeFromBinaryOp(BinaryOp.ArithOp op) { switch (op) { case BinaryOp.ArithOp.ADD: return(InstructionCode.ADD); case BinaryOp.ArithOp.AND: return(InstructionCode.AND); case BinaryOp.ArithOp.CEQ: return(InstructionCode.CEQ); case BinaryOp.ArithOp.CGT: return(InstructionCode.CGT); case BinaryOp.ArithOp.CLT: return(InstructionCode.CLT); case BinaryOp.ArithOp.DIV: return(InstructionCode.DIV); case BinaryOp.ArithOp.MUL: return(InstructionCode.MUL); case BinaryOp.ArithOp.OR: return(InstructionCode.OR); case BinaryOp.ArithOp.REM: return(InstructionCode.REM); case BinaryOp.ArithOp.SHL: return(InstructionCode.SHL); case BinaryOp.ArithOp.SHR: return(InstructionCode.SHR); case BinaryOp.ArithOp.SUB: return(InstructionCode.SUB); case BinaryOp.ArithOp.XOR: return(InstructionCode.XOR); } throw new ConvertionException(); }
private static Verifier.OpType GetOpType(BinaryOp.ArithOp op, bool un, bool ovf) { if (op == BinaryOp.ArithOp.SHL || op == BinaryOp.ArithOp.SHR) { return(Verifier.OpType.Shift); } if (op == BinaryOp.ArithOp.CEQ || op == BinaryOp.ArithOp.CLT || op == BinaryOp.ArithOp.CGT) { return(Verifier.OpType.Compare); } if (Verifier.IsFloatOperation(Converter.CodeFromBinaryOp(op), un, ovf)) { return(Verifier.OpType.FloatOrInt); } return(Verifier.OpType.Int); }
private bool detectedRemoval(Node n1, Node n2) { bool result = false; if (n2 is RemoveStackTop) { result = n1 is LoadConst || n1 is LoadVar || n1 is LoadVarAddr || n1 is DuplicateStackTop || n1 is LoadField && (n1 as LoadField).Field.IsStatic || n1 is LoadFieldAddr && (n1 as LoadFieldAddr).Field.IsStatic || n1 is LoadVar && n2 is StoreVar && (n1 as LoadVar).Var == (n2 as LoadVar).Var; } else if (n1 is LoadConst && n2 is BinaryOp) { object constantObj = (n1 as LoadConst).Constant; BinaryOp.ArithOp op = (n2 as BinaryOp).Op; if (constantObj != null && (constantObj.GetType() == typeof(Int32) || constantObj.GetType() == typeof(Int64) || constantObj.GetType() == typeof(Double))) { double constant; if (constantObj.GetType() == typeof(Int32)) { constant = (Int32)constantObj; } else if (constantObj.GetType() == typeof(Int64)) { constant = (Int64)constantObj; } else { constant = (Double)constantObj; } result = constant == 0 && (op == BinaryOp.ArithOp.ADD || op == BinaryOp.ArithOp.SUB) || constant == 1.0 && (op == BinaryOp.ArithOp.MUL || op == BinaryOp.ArithOp.DIV); } } return(result); }
/* Returns the category of binary operation */ private OpCategory getCategory(BinaryOp.ArithOp op, bool overflow, bool unsigned) { OpCategory category = OpCategory.InvalidOp; if (!overflow) { if ((op == BinaryOp.ArithOp.ADD || op == BinaryOp.ArithOp.DIV || op == BinaryOp.ArithOp.MUL || op == BinaryOp.ArithOp.REM || op == BinaryOp.ArithOp.SUB) && !unsigned) { category = OpCategory.NumericOp; } else if (op == BinaryOp.ArithOp.CEQ && !unsigned || op == BinaryOp.ArithOp.CGT || op == BinaryOp.ArithOp.CLT) { category = OpCategory.ComparisonOp; } else if (op == BinaryOp.ArithOp.AND && !unsigned || op == BinaryOp.ArithOp.DIV && unsigned || op == BinaryOp.ArithOp.OR && !unsigned || op == BinaryOp.ArithOp.REM && unsigned || op == BinaryOp.ArithOp.XOR && !unsigned) { category = OpCategory.IntegerOp; } else if (op == BinaryOp.ArithOp.SHL && !unsigned || op == BinaryOp.ArithOp.SHR) { category = OpCategory.ShiftOp; } } else if (op == BinaryOp.ArithOp.ADD || op == BinaryOp.ArithOp.MUL || op == BinaryOp.ArithOp.SUB) { category = OpCategory.OverflowOp; } return(category); }
private bool detectedOperandExchange(Node n1, Node n2, Node n3, Node n4) { bool result = n1 is StoreVar && (n2 is LoadVar || n2 is LoadConst) && n3 is LoadVar && n4 is BinaryOp; if (result) { result = (n1 as StoreVar).Var == (n3 as LoadVar).Var; if (result) { BinaryOp.ArithOp op = (n4 as BinaryOp).Op; result = op == BinaryOp.ArithOp.ADD || op == BinaryOp.ArithOp.AND || op == BinaryOp.ArithOp.CEQ || op == BinaryOp.ArithOp.MUL || op == BinaryOp.ArithOp.OR || op == BinaryOp.ArithOp.XOR; } } return(result); }
/* Performs binary operation on two values on top of the stack * (corresponds to CILPE.CFG.BinaryOp class) */ public void Perform_BinaryOp(BinaryOp.ArithOp op, bool overflow, bool unsigned, out Exception exc) { exc = null; /* Determining category of binary operation */ OpCategory category = getCategory(op, overflow, unsigned); if (category == OpCategory.InvalidOp) { throw new InvalidBinaryOpException(); } /* Getting operands from stack */ Value val1, val2; val2 = Pop(); val1 = Pop(); /* Performing binary operation */ object res = null; if (val1 is StructValue && val2 is StructValue) { StructValue.TypeIndex typeA = (val1 as StructValue).getTypeIndex(), typeB = (val2 as StructValue).getTypeIndex(); if (typeA == StructValue.TypeIndex.INVALID || typeB == StructValue.TypeIndex.INVALID) { throw new InvalidOperandException(); } ValueType a = (val1 as StructValue).Obj, b = (val2 as StructValue).Obj; int operandsKind = 0; bool success = true; if (category == OpCategory.ShiftOp) /* shl, shr, shr_un */ { if (typeA == StructValue.TypeIndex.FLOAT64 || typeB == StructValue.TypeIndex.FLOAT64 || typeB == StructValue.TypeIndex.INT64) { throw new InvalidOperandException(); } operandsKind = ((typeB == StructValue.TypeIndex.INT32) ? 0 : 3) + (int)typeA; DataModelUtils.ShiftOp((int)op, unsigned, a, b, operandsKind, out res); } else { if (typeA == typeB) { operandsKind = (int)typeA; } else if (typeA == StructValue.TypeIndex.INT32 && typeB == StructValue.TypeIndex.NATIVEINT) { operandsKind = 4; } else if (typeA == StructValue.TypeIndex.NATIVEINT && typeB == StructValue.TypeIndex.INT32) { operandsKind = 5; } else { throw new InvalidOperandException(); } switch (category) { case OpCategory.NumericOp: /* add, div, mul, rem, sub */ success = DataModelUtils.NumericOp((int)op, a, b, operandsKind, out res); break; case OpCategory.ComparisonOp: /* ceq, cgt, cgt.un, clt, clt.un */ DataModelUtils.ComparisonOp((int)op, unsigned, a, b, operandsKind, out res); break; case OpCategory.IntegerOp: /* and, div.un, or, rem.un, xor */ case OpCategory.OverflowOp: /* add.ovf, add.ovf.un, mul.ovf, mul.ovf.un, sub.ovf, sub.ovf.un */ if (operandsKind == 3) { throw new InvalidOperandException(); } success = DataModelUtils.IntOvfOp((int)op, unsigned, a, b, operandsKind, out res); break; } } if (!success) { exc = res as Exception; res = null; } } else if (op == BinaryOp.ArithOp.CEQ) { if ((val1 is NullValue || val1 is ObjectReferenceValue) && (val2 is NullValue || val2 is ObjectReferenceValue) || (val1 is NullValue || val1 is PointerValue) && (val2 is NullValue || val2 is PointerValue)) { res = Equals(val1, val2) ? (Int32)1 : (Int32)0; } else { throw new InvalidOperandException(); } } else if (op == BinaryOp.ArithOp.CGT) { if (val1 is ObjectReferenceValue && val2 is NullValue && unsigned) { res = (Int32)1; } else if (val1 is NullValue && val2 is NullValue) { res = (Int32)0; } else if (val1 is PointerValue && val2 is NullValue) { res = (Int32)1; } else { throw new InvalidOperandException(); } } else if (op == BinaryOp.ArithOp.CLT) { if (val1 is NullValue && val2 is ObjectReferenceValue && unsigned) { res = (Int32)1; } else if (val1 is NullValue && val2 is NullValue) { res = (Int32)0; } else if (val1 is NullValue && val2 is PointerValue) { res = (Int32)1; } else { throw new InvalidOperandException(); } } else { throw new InvalidOperandException(); } if (res != null) { push(new StructValue(res as ValueType)); } }