/// <summary> /// Rewrites the children of the given block expression. /// </summary> /// <param name="blockExpression"></param> public override void RewriteChildren(BlockExpression blockExpression) { var block = blockExpression.BlockStatement as BlockStatement; Contract.Assume(block != null); if (this.scopesWithCapturedLocals.ContainsKey(block)) { this.AllocateClosureFor(block, block.Statements, () => { base.RewriteChildren(block); blockExpression.Expression = this.Rewrite(blockExpression.Expression); }); } else base.RewriteChildren(blockExpression); }
/// <summary> /// Visits the specified block expression. /// </summary> /// <param name="blockExpression">The block expression.</param> public override void Visit(IBlockExpression blockExpression) { BlockExpression mutableBlockExpression = new BlockExpression(blockExpression); this.resultExpression = this.myCodeCopier.DeepCopy(mutableBlockExpression); }
/// <summary> /// Visits the specified block expression. /// </summary> /// <param name="blockExpression">The block expression.</param> /// <returns></returns> protected virtual IExpression DeepCopy(BlockExpression blockExpression) { blockExpression.BlockStatement = (IBlockStatement)this.Substitute(blockExpression.BlockStatement); blockExpression.Expression = Substitute(blockExpression.Expression); blockExpression.Type = this.Substitute(blockExpression.Type); return blockExpression; }
public override void RewriteChildren(ContractElement contractElement) { base.RewriteChildren(contractElement); var be = contractElement.Condition as IBlockExpression; if (be != null) { var lb = new LocalBinder(this.host); contractElement.Condition = lb.Rewrite(contractElement.Condition); if (lb.localDeclarations.Any()) { var be2 = new BlockExpression() { BlockStatement = new BlockStatement() { Statements = lb.localDeclarations, }, Expression = contractElement.Condition, }; contractElement.Condition = be2; } } }
/// <summary> /// The source expression "new C(){ f1 = e1, f2 = e2, ... }" (where the f's can be fields /// or properties) turns into "cgl = new C(); cgl.f1 = e1; cg1.f2 = e2; ...". /// ("cgl" means "compiler-generated local".) /// Turn it into a block expression whose Statements are the statements above (but where /// the first one becomes a local declaration statement), and with an Expression that is /// just the local, cgl', where cgl' is a freshly created local. /// </summary> private bool ReplaceCompilerGeneratedLocalUsedForInitializersPattern(BlockStatement b) { Contract.Requires(b != null); bool replacedPattern = false; var statements = b.Statements; for (int i = 0; i < statements.Count - 1; i++) { var expressionStatement = statements[i] as ExpressionStatement; if (expressionStatement == null) continue; var assignment = expressionStatement.Expression as Assignment; if (assignment == null) continue; var local = assignment.Target.Definition as ILocalDefinition; if (local == null || local is CapturedLocalDefinition) continue; if (this.numberOfAssignmentsToLocal[local] != 1) continue; if (this.sourceLocationProvider != null) { bool isCompilerGenerated; var sourceName = this.sourceLocationProvider.GetSourceNameFor(local, out isCompilerGenerated); if (!isCompilerGenerated) continue; } var createObject = assignment.Source as ICreateObjectInstance; if (createObject == null) continue; if (!this.singleUseExpressionChecker.ExpressionCanBeMovedAndDoesNotReference(assignment.Source, local)) continue; var j = 1; while (i + j < statements.Count - 1 && IsAssignmentToFieldOrProperty(local, statements[i + j])) j++; if (j == 1) continue; if (this.numberOfReferencesToLocal[local] != (uint)j) continue; Contract.Assume(i + j < statements.Count); //i < statements.Count-1 and (j == 1 or the loop above established i+j < statements.Count-1) Contract.Assume(statements[i + j] != null); if (LocalFinder.LocalOccursIn(statements[i+j], local) && this.singleAssignmentReferenceFinder.LocalCanBeReplacedIn(statements[i + j], local)) { var newLocal = new LocalDefinition() { Name = this.host.NameTable.GetNameFor(local.Name.Value + "_prime"), MethodDefinition = local.MethodDefinition, Type = local.Type, }; var lds = new LocalDeclarationStatement() { InitialValue = assignment.Source, LocalVariable = newLocal, }; var stmts = new List<IStatement>(j) { lds, }; var boundExpression = new BoundExpression() { Definition = newLocal, Instance = null, Type = newLocal.Type, }; foreach (var s in statements.GetRange(i + 1, j - 1)) { Contract.Assume(s != null); this.singleAssignmentLocalReplacer.Replace(boundExpression, local, s); stmts.Add(s); } var blockExpression = new BlockExpression() { BlockStatement = new BlockStatement() { Statements = stmts, }, Expression = new BoundExpression() { Definition = newLocal, Instance = null, Type = newLocal.Type, }, Type = newLocal.Type, }; if (this.singleAssignmentLocalReplacer.Replace(blockExpression, local, statements[i + j])) { this.numberOfAssignmentsToLocal[newLocal] = 1; this.numberOfReferencesToLocal[newLocal] = (uint)j; this.numberOfAssignmentsToLocal[local]--; this.numberOfReferencesToLocal[local] = 0; statements.RemoveRange(i, j); replacedPattern = true; } else Contract.Assume(false); // replacement should succeed since the combination of LocalOccursIn and LocalCanBeReplacedIn returned true } } return replacedPattern; }
private IExpression/*?*/ GetFilterCondition(DecompiledBlock block) { Contract.Requires(block != null); BlockExpression result = null; List<IStatement> statements = null; foreach (var statement in block.Statements) { var nestedBlock = statement as DecompiledBlock; if (nestedBlock != null) { var nestedResult = this.GetFilterCondition(nestedBlock); if (nestedResult != null) { if (result == null) return nestedResult; result.Expression = nestedResult; return result; } } else { var endFilter = statement as EndFilter; if (endFilter != null) { if (result == null) return endFilter.FilterResult; result.Expression = endFilter.FilterResult; return result; } } if (statements == null) { statements = new List<IStatement>(); result = new BlockExpression() { BlockStatement = new BlockStatement() { Statements = statements } }; } statements.Add(statement); } if (result != null && result.Expression == CodeDummy.Expression) return null; return result; }
private static IExpression ExtractFilterCondition(BasicBlock handlerBlock) { int endFilterIndex = -1; IExpression result = CodeDummy.Expression; for (int i = 0; i < handlerBlock.Statements.Count; i++) { var endFilter = handlerBlock.Statements[i] as EndFilter; if (endFilter != null) { result = endFilter.FilterResult; endFilterIndex = i; break; } } if (endFilterIndex < 0) return result; if (endFilterIndex == 0) { handlerBlock.Statements.RemoveAt(0); return result; } var blockExpression = new BlockExpression(); blockExpression.BlockStatement = ExtractAsBasicBlock(handlerBlock, 0, endFilterIndex); blockExpression.Expression = result; blockExpression.Type = result.Type; handlerBlock.Statements.RemoveRange(0, endFilterIndex+1); return blockExpression; }
/// <summary> /// Rewrites the children of the given block expression. /// </summary> public virtual void RewriteChildren(BlockExpression blockExpression) { this.RewriteChildren((Expression)blockExpression); blockExpression.BlockStatement = this.Rewrite((BlockStatement)blockExpression.BlockStatement); blockExpression.Expression = this.Rewrite(blockExpression.Expression); }
/// <summary> /// Visits the specified block expression. /// </summary> /// <param name="blockExpression">The block expression.</param> public override void Visit(IBlockExpression blockExpression) { BlockExpression mutableBlockExpression = blockExpression as BlockExpression; if (alwaysMakeACopy || mutableBlockExpression == null) mutableBlockExpression = new BlockExpression(blockExpression); this.resultExpression = this.myCodeMutator.Visit(mutableBlockExpression); }
/// <summary> /// Visits the specified block expression. /// </summary> /// <param name="blockExpression">The block expression.</param> /// <returns></returns> public virtual IExpression Visit(BlockExpression blockExpression) { blockExpression.BlockStatement = this.Visit(blockExpression.BlockStatement); blockExpression.Expression = Visit(blockExpression.Expression); blockExpression.Type = this.Visit(blockExpression.Type); return blockExpression; }