public IIfStatementOptions True(IExpression condition) { var ifStatement = new ConditionalStatement(); ifStatement.Condition = condition; return new IfStatementOptions(ifStatement); }
public override IStatement Visit(ConditionalStatement conditionalStatement) { var condition = conditionalStatement.Condition; var logicalNot = condition as ILogicalNot; if (logicalNot != null) condition = logicalNot.Operand; var equal = condition as IEquality; if (equal != null && equal.RightOperand is IDefaultValue) condition = equal.LeftOperand; var boundExpression = condition as IBoundExpression; if (boundExpression != null) { var locations = conditionalStatement.Locations; var fieldReference = boundExpression.Definition as IFieldReference; if (fieldReference != null) { if (this.cachedDelegateFieldsOrLocals.ContainsKey(fieldReference.Name.Value)) { if (locations.Count == 0) return CodeDummy.Block; else return new EmptyStatement() { Locations = locations, }; } } var localDefinition = boundExpression.Definition as ILocalDefinition; if (localDefinition != null) { if (this.cachedDelegateFieldsOrLocals.ContainsKey(localDefinition.Name.Value)) { if (locations.Count == 0) return CodeDummy.Block; else return new EmptyStatement() { Locations = locations, }; } } } return base.Visit(conditionalStatement); }
private Statement ParseBinaryConditionalBranch(IOperation currentOperation) { BinaryOperation condition; switch (currentOperation.OperationCode) { case OperationCode.Beq: case OperationCode.Beq_S: condition = this.ParseBinaryOperation(new Equality()); break; case OperationCode.Bge: case OperationCode.Bge_S: condition = this.ParseBinaryOperation(new GreaterThanOrEqual()); break; case OperationCode.Bge_Un: case OperationCode.Bge_Un_S: condition = this.ParseUnsignedBinaryOperation(new GreaterThanOrEqual()); break; case OperationCode.Bgt: case OperationCode.Bgt_S: condition = this.ParseBinaryOperation(new GreaterThan()); break; case OperationCode.Bgt_Un: case OperationCode.Bgt_Un_S: condition = this.ParseUnsignedBinaryOperation(new GreaterThan()); break; case OperationCode.Ble: case OperationCode.Ble_S: condition = this.ParseBinaryOperation(new LessThanOrEqual()); break; case OperationCode.Ble_Un: case OperationCode.Ble_Un_S: condition = this.ParseUnsignedBinaryOperation(new LessThanOrEqual()); break; case OperationCode.Blt: case OperationCode.Blt_S: condition = this.ParseBinaryOperation(new LessThan()); break; case OperationCode.Blt_Un: case OperationCode.Blt_Un_S: condition = this.ParseUnsignedBinaryOperation(new LessThan()); break; case OperationCode.Bne_Un: case OperationCode.Bne_Un_S: default: condition = this.ParseBinaryOperation(new NotEquality()); break; } condition.Type = this.platformType.SystemBoolean; if (this.host.PreserveILLocations) { condition.Locations.Add(currentOperation.Location); } GotoStatement gotoStatement = MakeGoto(currentOperation); ConditionalStatement ifStatement = new ConditionalStatement(); ifStatement.Condition = condition; ifStatement.TrueBranch = gotoStatement; ifStatement.FalseBranch = new EmptyStatement(); return ifStatement; }
private Statement ParseUnaryConditionalBranch(IOperation currentOperation) { Expression condition = this.PopOperandStack(); var castIfPossible = condition as CastIfPossible; if (castIfPossible != null) { condition = new CheckIfInstance() { Locations = castIfPossible.Locations, Operand = castIfPossible.ValueToCast, TypeToCheck = castIfPossible.TargetType, }; } else if (condition.Type != Dummy.TypeReference && condition.Type.TypeCode != PrimitiveTypeCode.Boolean) { var defaultValue = new DefaultValue() { DefaultValueType = condition.Type, Type = condition.Type }; condition = new NotEquality() { LeftOperand = condition, RightOperand = defaultValue }; } condition.Type = this.platformType.SystemBoolean; GotoStatement gotoStatement = MakeGoto(currentOperation); ConditionalStatement ifStatement = new ConditionalStatement(); ifStatement.Condition = condition; switch (currentOperation.OperationCode) { case OperationCode.Brfalse: case OperationCode.Brfalse_S: ifStatement.TrueBranch = new EmptyStatement(); ifStatement.FalseBranch = gotoStatement; break; case OperationCode.Brtrue: case OperationCode.Brtrue_S: default: ifStatement.TrueBranch = gotoStatement; ifStatement.FalseBranch = new EmptyStatement(); break; } return ifStatement; }
public IfBranchOptions(ConditionalStatement ifStatement) { this.ifStatement = ifStatement; }
/// <summary> /// Rewrites the given anonymous delegate expression. /// </summary> public override IExpression Rewrite(IAnonymousDelegate anonymousDelegate) { if (this.isInsideAnonymousMethod) return base.Rewrite(anonymousDelegate); IMethodReference method = this.CreateClosureMethod((AnonymousDelegate)anonymousDelegate); var createDelegate = new CreateDelegateInstance() { MethodToCallViaDelegate = method, Type = anonymousDelegate.Type }; if (!method.IsStatic) { //TODO: if there is reason to believe the delegate will be constructed in a loop, but its closure is constructed before the loop, then cache the delegate in a local //that is in the same scope as the closure instance if (method.ContainingType == this.currentClosureInstance) createDelegate.Instance = this.currentClosureObject; else //non static peer method createDelegate.Instance = new ThisReference() { Type = NamedTypeDefinition.SelfInstance((INamedTypeDefinition)this.method.ContainingTypeDefinition, this.host.InternFactory) }; } else if ((method.CallingConvention & CallingConvention.Generic) == 0) { //cache the delegate in a static field (we can only do this if method is not generic, i.e. when at most one instance will be created). var cache = this.CreateStaticCacheField(anonymousDelegate.Type); var boundField = new BoundExpression() { Definition = cache, Type = cache.Type }; var statements = new List<IStatement>(1); var conditional = new ConditionalStatement() { Condition = new Equality() { LeftOperand = boundField, RightOperand = new CompileTimeConstant() { Value = null, Type = cache.Type }, Type = this.host.PlatformType.SystemBoolean }, TrueBranch = new ExpressionStatement() { Expression = new Assignment() { Target = new TargetExpression() { Definition = cache, Type = cache.Type }, Source = createDelegate, Type = cache.Type } } }; statements.Add(conditional); return new BlockExpression() { BlockStatement = new BlockStatement() { Statements = statements }, Expression = boundField }; } return createDelegate; }
public override void RewriteChildren(ConditionalStatement conditionalStatement) { // exactly the same code as the base visitor. just need to reset stack // depth for each branch. this.RewriteChildren((Statement)conditionalStatement); conditionalStatement.Condition = this.Rewrite(conditionalStatement.Condition); var savedInThenBranch = this.inThenBranch; var savedInElseBranch = this.inElseBranch; this.inThenBranch = true; this.inElseBranch = false; var savedThenBranchPushes = this.thenBranchPushes; this.thenBranchPushes = new Dictionary<int, Assignment>(); var savedStack = Copy(this.locals); conditionalStatement.TrueBranch = this.Rewrite(conditionalStatement.TrueBranch); var stackAfterTrue = Copy(this.locals); this.locals = Copy(savedStack); this.inThenBranch = false; this.inElseBranch = true; conditionalStatement.FalseBranch = this.Rewrite(conditionalStatement.FalseBranch); Contract.Assume(stackAfterTrue.Count == this.locals.Count); // and that the things pushed in both branches are type-compatible // (one branch might push a bool and the other an int) // continuing on with the stack being the one from the else-branch. // is that okay? should it be the one from the then-branch? // currently it is important that it is the one from the else-branch // because of the fixup code in Rewrite(IPushStatement) that deals // with the bool/int confusion this.inThenBranch = savedInThenBranch; this.inElseBranch = savedInElseBranch; this.thenBranchPushes = savedThenBranchPushes; }
/// <summary> /// Visits the specified conditional statement. /// </summary> /// <param name="conditionalStatement">The conditional statement.</param> /// <returns></returns> protected virtual IStatement DeepCopy(ConditionalStatement conditionalStatement) { conditionalStatement.Condition = Substitute(conditionalStatement.Condition); conditionalStatement.TrueBranch = Substitute(conditionalStatement.TrueBranch); conditionalStatement.FalseBranch = Substitute(conditionalStatement.FalseBranch); return conditionalStatement; }
/// <summary> /// Visits the specified conditional statement. /// </summary> /// <param name="conditionalStatement">The conditional statement.</param> public override void Visit(IConditionalStatement conditionalStatement) { ConditionalStatement mutableConditionalStatement = new ConditionalStatement(conditionalStatement); this.resultStatement = this.myCodeCopier.DeepCopy(mutableConditionalStatement); }
// i : loc := e0; // i+1 : if (loc) S0; else S1; // // ==> // // if (e0) S0; else S1; // // and delete statement i // // This is done only if loc is in this.branchConditionLocals // private void FindPattern(List<IStatement> statements) { for (int i = 0; i < statements.Count - 1; i++) { IExpressionStatement/*?*/ expressionStatement = statements[i] as IExpressionStatement; if (expressionStatement == null) continue; IAssignment/*?*/ assignmentStatement = expressionStatement.Expression as IAssignment; if (assignmentStatement == null) continue; if (assignmentStatement.Source is Pop) continue; ILocalDefinition/*?*/ localDefinition = assignmentStatement.Target.Definition as ILocalDefinition; if (localDefinition == null) continue; if (localDefinition.Type.TypeCode != PrimitiveTypeCode.Boolean) continue; // cheaper test than looking in the table if (!this.branchConditionLocals.ContainsKey(localDefinition)) continue; IConditionalStatement/*?*/ conditional = statements[i + 1] as IConditionalStatement; if (conditional == null) continue; BoundExpression/*?*/ boundExpression = conditional.Condition as BoundExpression; if (boundExpression == null) continue; ILocalDefinition/*?*/ localDefinition2 = boundExpression.Definition as ILocalDefinition; if (localDefinition2 == null) continue; if (localDefinition != localDefinition2) continue; var newLocs = new List<ILocation>(expressionStatement.Locations); newLocs.AddRange(conditional.Locations); statements[i + 1] = new ConditionalStatement() { Condition = assignmentStatement.Source, TrueBranch = conditional.TrueBranch, FalseBranch = conditional.FalseBranch, Locations = newLocs, }; this.sourceMethodBody.numberOfAssignments[localDefinition]--; this.sourceMethodBody.numberOfReferences[localDefinition]--; statements.RemoveAt(i); } }
/// <summary> /// Create the body of the generic version of GetEnumerator for the iterator closure class. /// /// The body's pseudo code. /// { /// if (Thread.CurrentThread.ManagedThreadId == this.l_initialThreadId AND this.state == -2) { /// this.state = 0; /// return this; /// } /// else { /// return a new copy of the iterator instance with state being zero. /// } /// } /// </summary> private BlockStatement GetBodyOfGenericGetEnumerator(IteratorClosureInformation iteratorClosure) { var thisDotState = new BoundExpression() { Definition = iteratorClosure.StateFieldReference, Instance = new ThisReference(), Type = this.host.PlatformType.SystemInt32 }; var thisDotThreadId = new BoundExpression() { Definition = iteratorClosure.InitThreadIdFieldReference, Instance = new ThisReference(), Type = this.host.PlatformType.SystemInt32 }; var currentThreadId = new MethodCall() { MethodToCall = ThreadDotManagedThreadId.Getter, ThisArgument = ThreadDotCurrentThread, Type = this.host.PlatformType.SystemInt32 }; var stateEqMinus2 = new Equality() { LeftOperand = thisDotState, RightOperand = new CompileTimeConstant() { Type = this.host.PlatformType.SystemInt32, Value = -2 }, Type = this.host.PlatformType.SystemBoolean }; var threadIdEqCurrentThreadId = new Equality { LeftOperand = thisDotThreadId, RightOperand = currentThreadId, Type = this.host.PlatformType.SystemBoolean }; var thisDotStateEq0 = new ExpressionStatement() { Expression = new Assignment() { Source = new CompileTimeConstant() { Type = this.host.PlatformType.SystemInt32, Value = 0 }, Target = new TargetExpression() { Definition = iteratorClosure.StateFieldReference, Instance = new ThisReference(), Type = this.host.PlatformType.SystemInt32 }, Type = this.host.PlatformType.SystemInt32 }, }; var returnThis = new BlockStatement(); returnThis.Statements.Add(thisDotStateEq0); returnThis.Statements.Add(new ReturnStatement() { Expression = new ThisReference() }); var returnNew = new BlockStatement(); var args = new List<IExpression>(); args.Add(new CompileTimeConstant() { Value = 0, Type = this.host.PlatformType.SystemInt32 }); var closureInstanceLocalDecl = new LocalDeclarationStatement() { LocalVariable = new LocalDefinition() { Name = this.host.NameTable.GetNameFor("local0"), Type = iteratorClosure.ClosureDefinitionReference }, InitialValue = new CreateObjectInstance() { MethodToCall = iteratorClosure.ConstructorReference, Arguments = args, Type = iteratorClosure.ClosureDefinitionReference } }; var returnNewClosureInstance = new ReturnStatement() { Expression = new BoundExpression() { Instance = null, Type = iteratorClosure.ClosureDefinitionReference, Definition = closureInstanceLocalDecl.LocalVariable } }; returnNew.Statements.Add(closureInstanceLocalDecl); if (!method.IsStatic) { ExpressionStatement assignThisDotThisToNewClosureDotThis = new ExpressionStatement() { Expression = new Assignment() { Source = new BoundExpression() { Definition = iteratorClosure.ThisFieldReference, Instance = new ThisReference(), Type = iteratorClosure.ClosureDefinitionReference }, Type = iteratorClosure.ClosureDefinition, Target = new TargetExpression() { Instance = new BoundExpression() { Instance = null, Definition = closureInstanceLocalDecl.LocalVariable, Type = iteratorClosure.ClosureDefinitionReference }, Definition = iteratorClosure.ThisFieldReference, Type = iteratorClosure.ClosureDefinitionReference } } }; returnNew.Statements.Add(assignThisDotThisToNewClosureDotThis); } returnNew.Statements.Add(returnNewClosureInstance); ConditionalStatement returnThisOrNew = new ConditionalStatement() { Condition = new Conditional() { Condition = stateEqMinus2, ResultIfTrue = threadIdEqCurrentThreadId, ResultIfFalse = new CompileTimeConstant() { Type = this.host.PlatformType.SystemBoolean, Value = false }, Type = this.host.PlatformType.SystemBoolean }, TrueBranch = returnThis, FalseBranch = returnNew }; BlockStatement block = new BlockStatement(); block.Statements.Add(returnThisOrNew); return block; }
/// <summary> /// Rewrites the children of the given conditional statement. /// </summary> public virtual void RewriteChildren(ConditionalStatement conditionalStatement) { this.RewriteChildren((Statement)conditionalStatement); conditionalStatement.Condition = this.Rewrite(conditionalStatement.Condition); conditionalStatement.TrueBranch = this.Rewrite(conditionalStatement.TrueBranch); conditionalStatement.FalseBranch = this.Rewrite(conditionalStatement.FalseBranch); }
/// <summary> /// Visits the specified conditional statement. /// </summary> /// <param name="conditionalStatement">The conditional statement.</param> public override void Visit(IConditionalStatement conditionalStatement) { ConditionalStatement mutableConditionalStatement = conditionalStatement as ConditionalStatement; if (alwaysMakeACopy || mutableConditionalStatement == null) mutableConditionalStatement = new ConditionalStatement(conditionalStatement); this.resultStatement = this.myCodeMutator.Visit(mutableConditionalStatement); }
/// <summary> /// Visits the specified conditional statement. /// </summary> /// <param name="conditionalStatement">The conditional statement.</param> /// <returns></returns> public virtual IStatement Visit(ConditionalStatement conditionalStatement) { conditionalStatement.Condition = Visit(conditionalStatement.Condition); conditionalStatement.TrueBranch = Visit(conditionalStatement.TrueBranch); conditionalStatement.FalseBranch = Visit(conditionalStatement.FalseBranch); return conditionalStatement; }