Example #1
0
        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();
        }
Example #2
0
 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);
 }
Example #3
0
        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);
        }
Example #4
0
        /* 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);
        }
Example #5
0
        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);
        }
Example #6
0
        /* 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));
            }
        }