Наследование: CodeTraverser
Пример #1
0
        public override IStatement Rewrite(IConditionalStatement conditionalStatement)
        {
            var result = base.Rewrite(conditionalStatement);
            var mutableConditionalStatement = result as ConditionalStatement;

            if (mutableConditionalStatement == null)
            {
                return(result);
            }
            var expressionPushedByTrueBranch  = GetPushedExpressionFrom(conditionalStatement.TrueBranch);
            var expressionPushedByFalseBranch = GetPushedExpressionFrom(conditionalStatement.FalseBranch);

            if (expressionPushedByFalseBranch != null && expressionPushedByTrueBranch != null)
            {
                return(new PushStatement()
                {
                    ValueToPush = TypeInferencer.FixUpType(new Conditional()
                    {
                        Condition = conditionalStatement.Condition, ResultIfFalse = expressionPushedByFalseBranch,
                        ResultIfTrue = expressionPushedByTrueBranch
                    }),
                    Locations = mutableConditionalStatement.Locations
                });
            }
            return(result);
        }
Пример #2
0
        public override void RewriteChildren(BinaryOperation binaryOperation)
        {
            var leftPop  = binaryOperation.LeftOperand is IPopValue && binaryOperation.LeftOperand.Type.TypeCode != PrimitiveTypeCode.Boolean;
            var rightPop = binaryOperation.RightOperand is IPopValue && binaryOperation.RightOperand.Type.TypeCode != PrimitiveTypeCode.Boolean;

            base.RewriteChildren(binaryOperation);
            if (leftPop && !rightPop && binaryOperation.LeftOperand.Type.TypeCode == PrimitiveTypeCode.Boolean)
            {
                // then left went from int to bool
                binaryOperation.RightOperand = TypeInferencer.Convert(binaryOperation.RightOperand, this.systemBool);
            }
            else if (rightPop && !leftPop && binaryOperation.RightOperand.Type.TypeCode == PrimitiveTypeCode.Boolean)
            {
                // then right went from int to bool
                binaryOperation.LeftOperand = TypeInferencer.Convert(binaryOperation.LeftOperand, this.systemBool);
            }
        }
Пример #3
0
        public override IExpression Rewrite(IAssignment assignment)
        {
            var binOp = assignment.Source as BinaryOperation;

            if (binOp != null)
            {
                var addressDeref = binOp.LeftOperand as IAddressDereference;
                if (addressDeref != null)
                {
                    var dupValue = addressDeref.Address as IDupValue;
                    if (dupValue != null && assignment.Target.Definition is IAddressDereference)
                    {
                        if (binOp is IAddition || binOp is IBitwiseAnd || binOp is IBitwiseOr || binOp is IDivision || binOp is IExclusiveOr ||
                            binOp is ILeftShift || binOp is IModulus || binOp is IMultiplication || binOp is IRightShift || binOp is ISubtraction)
                        {
                            binOp.LeftOperand = assignment.Target;
                            return(binOp);
                        }
                    }
                }
                else
                {
                    var boundExpr = binOp.LeftOperand as IBoundExpression;
                    if (boundExpr != null && boundExpr.Definition == assignment.Target.Definition && boundExpr.Instance is IDupValue)
                    {
                        if (binOp is IAddition || binOp is IBitwiseAnd || binOp is IBitwiseOr || binOp is IDivision || binOp is IExclusiveOr ||
                            binOp is ILeftShift || binOp is IModulus || binOp is IMultiplication || binOp is IRightShift || binOp is ISubtraction)
                        {
                            binOp.LeftOperand = assignment.Target;
                            return(binOp);
                        }
                    }
                }
            }
            else
            {
                var assign2 = assignment.Source as Assignment;
                if (assign2 != null)
                {
                    var targetLocal = assign2.Target.Definition as ILocalDefinition;
                    if (targetLocal != null)
                    {
                        binOp = assign2.Source as BinaryOperation;
                        if (binOp != null)
                        {
                            var addressDeref = binOp.LeftOperand as IAddressDereference;
                            if (addressDeref != null)
                            {
                                var dupValue = addressDeref.Address as IDupValue;
                                if (dupValue != null && assignment.Target.Definition is IAddressDereference)
                                {
                                    if (binOp is IAddition || binOp is IBitwiseAnd || binOp is IBitwiseOr || binOp is IDivision || binOp is IExclusiveOr ||
                                        binOp is ILeftShift || binOp is IModulus || binOp is IMultiplication || binOp is IRightShift || binOp is ISubtraction)
                                    {
                                        binOp.LeftOperand = assignment.Target;
                                        if (this.numberOfReferencesToLocal[targetLocal] == 1 && this.numberOfAssignmentsToLocal[targetLocal] == 1)
                                        {
                                            this.currentSingleUseSingleReferenceLocal = targetLocal;
                                        }
                                        return(assign2);
                                    }
                                }
                            }
                        }
                    }
                }
                else
                {
                    var conversion = assignment.Source as IConversion;
                    if (conversion != null)
                    {
                        binOp = conversion.ValueToConvert as BinaryOperation;
                        if (binOp != null)
                        {
                            var addressDeref = binOp.LeftOperand as IAddressDereference;
                            if (addressDeref != null)
                            {
                                var dupValue = addressDeref.Address as IDupValue;
                                if (dupValue != null && assignment.Target.Definition is IAddressDereference)
                                {
                                    if (binOp is IAddition || binOp is IBitwiseAnd || binOp is IBitwiseOr || binOp is IDivision || binOp is IExclusiveOr ||
                                        binOp is ILeftShift || binOp is IModulus || binOp is IMultiplication || binOp is IRightShift || binOp is ISubtraction)
                                    {
                                        binOp.LeftOperand = assignment.Target;
                                        return(binOp);
                                    }
                                }
                            }
                            else
                            {
                                var boundExpr = binOp.LeftOperand as IBoundExpression;
                                if (boundExpr != null && boundExpr.Definition == assignment.Target.Definition && boundExpr.Instance is IDupValue)
                                {
                                    if (binOp is IAddition || binOp is IBitwiseAnd || binOp is IBitwiseOr || binOp is IDivision || binOp is IExclusiveOr ||
                                        binOp is ILeftShift || binOp is IModulus || binOp is IMultiplication || binOp is IRightShift || binOp is ISubtraction)
                                    {
                                        binOp.LeftOperand  = assignment.Target;
                                        binOp.RightOperand = TypeInferencer.Convert(binOp.RightOperand, assignment.Target.Type);
                                        return(binOp);
                                    }
                                }
                            }
                        }
                        else
                        {
                            // For a character-typed field, c, the C# source expressions:
                            //   o.c += (char)0, o.c -= (char)0, and o.c *= (char)1
                            // produce the IL: "load o; dup; ldfld c; stfld c;".
                            // (For some reason, the C# compiler does not do the same thing for "o.c /= (char)1".)
                            // Such IL shows up here as "o.c = convert(ushort, dup.c)".
                            // Arbitrarily turn it back into "o.c += (char)0".
                            if (IsBoundExpressionWithDupInstance(conversion.ValueToConvert))
                            {
                                var t = conversion.ValueToConvert.Type;
                                if (t.TypeCode == PrimitiveTypeCode.Char)
                                {
                                    return(new Addition()
                                    {
                                        LeftOperand = assignment.Target,
                                        RightOperand = new Conversion()
                                        {
                                            TypeAfterConversion = t,
                                            ValueToConvert = new CompileTimeConstant()
                                            {
                                                Value = 0, Type = assignment.Type,
                                            },
                                        },
                                        ResultIsUnmodifiedLeftOperand = false,
                                        Type = assignment.Type,
                                    });
                                }
                            }
                        }
                    }
                    else
                    {
                        // There are several C# source expressions that produce the IL: "load o; dup; ldfld f; stfld f;".
                        // Examples are: o.f += 0, o.f -= 0, o.f *= 1, o.f &= true, o.f |= false.
                        // (For some reason, the C# compiler does not do the same thing for "o.f /= 1".)
                        // Such IL shows up here as "o.f = dup.f".
                        // Arbitrarily turn it back into "o.f += 0" for arithmetic types and "o.f |= false" for boolean.
                        if (IsBoundExpressionWithDupInstance(assignment.Source))
                        {
                            if (TypeHelper.IsPrimitiveInteger(assignment.Type) && assignment.Type.TypeCode != PrimitiveTypeCode.Char)
                            {
                                return(new Addition()
                                {
                                    LeftOperand = assignment.Target,
                                    RightOperand = new CompileTimeConstant()
                                    {
                                        Value = 0, Type = assignment.Type,
                                    },
                                    ResultIsUnmodifiedLeftOperand = false,
                                    Type = assignment.Type,
                                });
                            }
                            else if (assignment.Type.TypeCode == PrimitiveTypeCode.Boolean)
                            {
                                return(new BitwiseOr()
                                {
                                    LeftOperand = assignment.Target,
                                    RightOperand = new CompileTimeConstant()
                                    {
                                        Value = false, Type = assignment.Type,
                                    },
                                    ResultIsUnmodifiedLeftOperand = false,
                                    Type = assignment.Type,
                                });
                            }
                        }
                    }
                }
            }
            return(base.Rewrite(assignment));
        }