Ejemplo n.º 1
0
        public static bool TryTransformEnumHasFlagToIntOps(this CallMethod s, Log log, ref Expression result)
        {
            // Enum.HasFlag() -> (((int)a & (int)b) == (int)b)
            if (s.Method.DeclaringType is EnumType && s.Method.UnoName == "HasFlag" && s.Arguments.Length == 1)
            {
                var bt = s.Method.DeclaringType.Base;

                foreach (var o in bt.Operators)
                {
                    if (o.UnoName == "op_BitwiseAnd")
                    {
                        var a = new CastOp(s.Source, bt, s.Object.ActualValue);
                        var b = new CastOp(s.Source, bt, s.Arguments[0]);

                        foreach (var p in bt.Operators)
                        {
                            if (p.UnoName == "op_Equality")
                            {
                                result = new CallBinOp(s.Source, p, new CallBinOp(s.Source, o, a, b), b);
                                return(true);
                            }
                        }

                        log.Error(s.Source, ErrorCode.I0069, "'" + bt + ".op_Equality(" + bt + "," + bt + ")' was not found");
                        return(false);
                    }
                }

                log.Error(s.Source, ErrorCode.I0069, "'" + bt + ".op_BitwiseAnd(" + bt + "," + bt + ")' was not found");
            }

            return(false);
        }
Ejemplo n.º 2
0
        public static bool TryTransformEnumBinOpToIntBinOp(this CallBinOp s, Log log, ref Expression result)
        {
            // Enum.BinOps -> Int.BinOps
            if (s.Operator.DeclaringType is EnumType)
            {
                var bt = s.Operator.DeclaringType.Base;

                foreach (var o in bt.Operators)
                {
                    if (o.UnoName == s.Operator.UnoName)
                    {
                        result = new CallBinOp(s.Source, o,
                                               new CastOp(s.Source, bt, s.Left),
                                               new CastOp(s.Source, bt, s.Right));

                        if (s.ReturnType == s.Operator.DeclaringType)
                        {
                            result = new CastOp(s.Source, s.Operator.DeclaringType, result);
                        }

                        return(true);
                    }
                }

                log.Error(s.Source, ErrorCode.I0072, "'" + bt + "." + s.Operator.UnoName + "(" + bt + "," + bt + ")' was not found");
            }

            return(false);
        }
Ejemplo n.º 3
0
 public virtual void WriteCallBinOp(CallBinOp s, ExpressionUsage u)
 {
     Begin(u);
     WriteExpression(s.Left, ExpressionUsage.Operand);
     Write(Space + s.Operator.Symbol + Space);
     WriteExpression(s.Right, ExpressionUsage.Operand);
     End(u);
 }
Ejemplo n.º 4
0
        public override void WriteCallBinOp(CallBinOp s, ExpressionUsage u)
        {
            // Integer division
            if (s.Left.ReturnType.IsIntegralType && s.Operator.Type == OperatorType.Division)
            {
                Begin(u);
                base.WriteCallBinOp(s, ExpressionUsage.Operand);
                Write(" | 0");
                End(u);
                return;
            }

            base.WriteCallBinOp(s, u);
        }
Ejemplo n.º 5
0
        public static bool TryTransformDelegateBinOp(this CallBinOp s, ILFactory ilf, ref Expression result)
        {
            DataType dt = s.Operator.DeclaringType;

            if (dt is DelegateType)
            {
                if (s.Operator.Symbol == "+")
                {
                    result = new CastOp(s.Source, dt, ilf.CallMethod(s.Source, dt, "Combine", s.Left, s.Right));
                    return(true);
                }
                if (s.Operator.Symbol == "-")
                {
                    result = new CastOp(s.Source, dt, ilf.CallMethod(s.Source, dt, "Remove", s.Left, s.Right));
                    return(true);
                }
            }

            return(false);
        }
Ejemplo n.º 6
0
        public void CompileBinOp(CallBinOp s, bool pop, Condition cond)
        {
            Opcodes builtInOp   = Opcodes.Null;
            bool    isIntrinsic = false;

            switch (s.Operator.DeclaringType.BuiltinType)
            {
            case BuiltinType.Bool:
            case BuiltinType.Char:
            case BuiltinType.Byte:
            case BuiltinType.SByte:
            case BuiltinType.UShort:
            case BuiltinType.Short:
            case BuiltinType.ULong:
            case BuiltinType.Long:
            case BuiltinType.UInt:
            case BuiltinType.Int:
            case BuiltinType.Float:
            case BuiltinType.Double:
            case BuiltinType.Object:
            {
                isIntrinsic = true;
                switch (s.Operator.Type)
                {
                case OperatorType.Addition: builtInOp = Opcodes.Add; break;

                case OperatorType.Subtraction: builtInOp = Opcodes.Sub; break;

                case OperatorType.Multiply: builtInOp = Opcodes.Mul; break;

                case OperatorType.Division:
                    if (s.Left.ReturnType.IsUnsignedType)
                    {
                        builtInOp = Opcodes.Div_Un;
                    }
                    else
                    {
                        builtInOp = Opcodes.Div;
                    }
                    break;

                case OperatorType.Modulus:
                    if (s.Left.ReturnType.IsUnsignedType)
                    {
                        builtInOp = Opcodes.Rem_Un;
                    }
                    else
                    {
                        builtInOp = Opcodes.Rem;
                    }
                    break;

                case OperatorType.BitwiseAnd: builtInOp = Opcodes.And; break;

                case OperatorType.BitwiseOr: builtInOp = Opcodes.Or; break;

                case OperatorType.ExclusiveOr: builtInOp = Opcodes.Xor; break;

                case OperatorType.LeftShift: builtInOp = Opcodes.Shl; break;

                case OperatorType.RightShift:
                    if (s.Left.ReturnType.IsUnsignedType)
                    {
                        builtInOp = Opcodes.Shr_Un;
                    }
                    else
                    {
                        builtInOp = Opcodes.Shr;
                    }
                    break;
                }
            }
            break;
            }

            if (builtInOp != Opcodes.Null)
            {
                CompileExpression(s.Left);
                CompileExpression(s.Right);
                Emit(builtInOp);
                return;
            }

            if (isIntrinsic)
            {
                switch (s.Operator.Type)
                {
                case OperatorType.LessThan: builtInOp = Opcodes.Lt; break;

                case OperatorType.LessThanOrEqual: builtInOp = Opcodes.Lte; break;

                case OperatorType.GreaterThan: builtInOp = Opcodes.Gt; break;

                case OperatorType.GreaterThanOrEqual: builtInOp = Opcodes.Gte; break;

                case OperatorType.Equality: builtInOp = Opcodes.Eq; break;

                case OperatorType.Inequality: builtInOp = Opcodes.Neq; break;
                }

                if (s.Left.ReturnType.IsUnsignedType)
                {
                    switch (s.Operator.Type)
                    {
                    case OperatorType.LessThan: builtInOp = Opcodes.Lt_Unsigned; break;

                    case OperatorType.LessThanOrEqual: builtInOp = Opcodes.Lte_Unsigned; break;

                    case OperatorType.GreaterThan: builtInOp = Opcodes.Gt_Unsigned; break;

                    case OperatorType.GreaterThanOrEqual: builtInOp = Opcodes.Gte_Unsigned; break;
                    }
                }

                if (builtInOp != Opcodes.Null)
                {
                    CompileExpression(s.Left);
                    CompileExpression(s.Right);

                    if (cond != null && !cond.Handled)
                    {
                        if (cond.Sequence == ConditionSequence.TrueFollows)
                        {
                            builtInOp = InvertOp(builtInOp);
                            builtInOp = ToBranchOp(builtInOp);
                            Branch(builtInOp, cond.FalseLabel ?? (cond.FalseLabel = NewLabel()));
                        }
                        else if (cond.Sequence == ConditionSequence.FalseFollows)
                        {
                            builtInOp = ToBranchOp(builtInOp);
                            Branch(builtInOp, cond.TrueLabel ?? (cond.TrueLabel = NewLabel()));
                        }
                        else
                        {
                            builtInOp = ToBranchOp(builtInOp);
                            Branch(builtInOp, cond.TrueLabel ?? (cond.TrueLabel = NewLabel()));
                            Branch(Opcodes.Br, (cond.FalseLabel ?? (cond.FalseLabel = NewLabel())));
                        }

                        cond.Handled = true;
                        return;
                    }

                    Emit(builtInOp);
                    return;
                }
            }

            CompileExpression(s.Left);
            CompileExpression(s.Right);
            Call(null, s.Operator);

            if (pop && !s.Operator.ReturnType.IsVoid)
            {
                Pop();
            }
        }