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); }
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); } }
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)); }