An object that represents the declaration of a local variable, with optional initializer.
Inheritance: Statement, ILocalDeclarationStatement
Example #1
0
 internal void Traverse(SourceMethodBody body, BasicBlock rootBlock)
 {
     this.Traverse(rootBlock);
       //Now add declarations for any locals declared only on the body (for example temporary variables introduced by Unstacker).
       List<IStatement> prelude = new List<IStatement>();
       var localsAndTemps = body.localVariablesAndTemporaries;
       this.AddDeclarationsWithInitialValues(localsAndTemps, rootBlock);
       foreach (var localDef in localsAndTemps) {
     if (this.declaredLocals.ContainsKey(localDef)) continue;
     LocalDeclarationStatement localDecl = new LocalDeclarationStatement();
     localDecl.LocalVariable = localDef;
     prelude.Add(localDecl);
       }
       if (prelude.Count > 0)
     rootBlock.Statements.InsertRange(0, prelude); //TODO: use pdb info to insert them in the same order they appear in the source
 }
Example #2
0
 public override void TraverseChildren(IBlockStatement block)
 {
     BasicBlock basicBlock = (BasicBlock)block;
       List<ILocalDefinition>/*?*/ localsInCurrentScope = basicBlock.LocalVariables;
       if (localsInCurrentScope != null) {
     this.AddDeclarationsWithInitialValues(localsInCurrentScope, basicBlock);
     List<IStatement> prelude = new List<IStatement>(localsInCurrentScope.Count);
     foreach (ILocalDefinition localDef in localsInCurrentScope) {
       if (this.declaredLocals.ContainsKey(localDef)) continue;
       LocalDeclarationStatement localDecl = new LocalDeclarationStatement();
       localDecl.LocalVariable = localDef;
       prelude.Add(localDecl);
     }
     if (prelude.Count > 0)
       basicBlock.Statements.InsertRange(0, prelude); //TODO: use pdb info to insert them in the same order they appear in the source
       }
       this.Traverse(basicBlock.Statements);
 }
Example #3
0
 public static IBlockStatement GetRidOfStack(SourceMethodBody methodBody, IBlockStatement block)
 {
     var me = new Unstacker(methodBody);
     var result = me.Rewrite(block);
     var stmts = new List<IStatement>();
     foreach (var loc in me.createdLocals.Values)
     {
         var decl = new LocalDeclarationStatement()
         {
             InitialValue = null,
             LocalVariable = loc,
         };
         stmts.Add(decl);
     }
     stmts.AddRange(result.Statements);
     var newBlock = new BlockStatement()
     {
         Statements = stmts,
         Locations = new List<ILocation>(result.Locations),
     };
     return newBlock;
 }
      public override IExpression Rewrite(IArrayIndexer arrayIndexer) {
        if (ExpressionTraverser.IsAtomicInstance(arrayIndexer.IndexedObject)) return arrayIndexer;

        // arrayIndexer == AI(inst, [index]), i.e., inst[index0, index1,...]
        // return { loc := e; [assert loc != null;] | AI(BE(null,loc), [index]) }
        //   where e is the rewritten array instance

        var e = base.Rewrite(arrayIndexer.IndexedObject);

        var loc = new LocalDefinition() {
          Name = this.host.NameTable.GetNameFor("_loc" + this.sink.LocalCounter.ToString()),
          Type = e.Type
        };
        var locDecl = new LocalDeclarationStatement() {
          InitialValue = e,
          LocalVariable = loc,
        };
        return new BlockExpression() {
          BlockStatement = new BlockStatement() {
            Statements = new List<IStatement> { locDecl },
          },
          Expression = new ArrayIndexer() {
            IndexedObject = new BoundExpression() {
              Definition = loc,
              Instance = null,
              Type = loc.Type,
            },
            Indices = new List<IExpression>(arrayIndexer.Indices),
            Type = arrayIndexer.Type,
          },
        };
      }
 public override IStatement Visit(LocalDeclarationStatement localDeclarationStatement)
 {
     var localDefinition = localDeclarationStatement.LocalVariable;
       if (this.cachedDelegateFieldsOrLocals.ContainsKey(localDefinition.Name.Value))
     return CodeDummy.Block;
       else
     return base.Visit(localDeclarationStatement);
 }
Example #6
0
 /// <summary>
 /// Visits the specified local declaration statement.
 /// </summary>
 /// <param name="localDeclarationStatement">The local declaration statement.</param>
 /// <returns></returns>
 protected virtual IStatement DeepCopy(LocalDeclarationStatement localDeclarationStatement)
 {
     localDeclarationStatement.LocalVariable = this.Substitute(localDeclarationStatement.LocalVariable);
       if (localDeclarationStatement.InitialValue != null)
     localDeclarationStatement.InitialValue = Substitute(localDeclarationStatement.InitialValue);
       return localDeclarationStatement;
 }
      public override IExpression Rewrite(IBoundExpression boundExpression) {

        if (boundExpression.Instance == null || ExpressionTraverser.IsAtomicInstance(boundExpression.Instance)) return boundExpression;

        // boundExpression == BE(inst, def), i.e., inst.def
        // return { loc := e; [assert loc != null;] | BE(BE(null,loc), def) }, i.e., "loc := e; loc.def"
        //   where e is the rewritten inst

        var e = base.Rewrite(boundExpression.Instance);

        var loc = new LocalDefinition() {
          Name = this.host.NameTable.GetNameFor("_loc" + this.sink.LocalCounter.ToString()),
          Type = e.Type,
        };
        var locDecl = new LocalDeclarationStatement() {
          InitialValue = e,
          LocalVariable = loc,
        };
        return new BlockExpression() {
          BlockStatement = new BlockStatement() {
            Statements = new List<IStatement> { locDecl },
          },
          Expression = new BoundExpression() {
            Definition = boundExpression.Definition,
            Instance = new BoundExpression() {
              Definition = loc,
              Instance = null,
              Type = loc.Type,
            },
            Type = boundExpression.Type,
          },
        };

      }
Example #8
0
 /// <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;
 }
Example #9
0
 /// <summary>
 /// Visits the specified local declaration statement.
 /// </summary>
 /// <param name="localDeclarationStatement">The local declaration statement.</param>
 public override void Visit(ILocalDeclarationStatement localDeclarationStatement)
 {
     LocalDeclarationStatement mutableLocalDeclarationStatement = new LocalDeclarationStatement(localDeclarationStatement);
     this.resultStatement = this.myCodeCopier.DeepCopy(mutableLocalDeclarationStatement);
 }
Example #10
0
 /// <summary>
 /// Visits the specified local declaration statement.
 /// </summary>
 /// <param name="localDeclarationStatement">The local declaration statement.</param>
 /// <returns></returns>
 public virtual IStatement Visit(LocalDeclarationStatement localDeclarationStatement)
 {
     localDeclarationStatement.LocalVariable = this.Visit(localDeclarationStatement.LocalVariable);
       if (localDeclarationStatement.InitialValue != null)
     localDeclarationStatement.InitialValue = Visit(localDeclarationStatement.InitialValue);
       return localDeclarationStatement;
 }
Example #11
0
 /// <summary>
 /// Rewrites the children of the given local declaration statement.
 /// </summary>
 public virtual void RewriteChildren(LocalDeclarationStatement localDeclarationStatement)
 {
     this.RewriteChildren((Statement)localDeclarationStatement);
       localDeclarationStatement.LocalVariable = this.Rewrite(localDeclarationStatement.LocalVariable);
       if (localDeclarationStatement.InitialValue != null)
     localDeclarationStatement.InitialValue = this.Rewrite(localDeclarationStatement.InitialValue);
 }
Example #12
0
        /// <summary />
        public override IStatement Rewrite(IForEachStatement forEachStatement)
        {
            ILocalDefinition foreachLocal;
            var key = forEachStatement.Collection.Type.InternedKey;

            ITypeReference enumeratorType;
            IMethodReference getEnumerator;
            IMethodReference getCurrent;

            var gtir = forEachStatement.Collection.Type as IGenericTypeInstanceReference;
            if (gtir != null)
            {
                var typeArguments = gtir.GenericArguments;
                ITypeReference genericEnumeratorType = new Immutable.GenericTypeInstanceReference(this.host.PlatformType.SystemCollectionsGenericIEnumerator, typeArguments, this.host.InternFactory);
                ITypeReference genericEnumerableType = new Immutable.GenericTypeInstanceReference(this.host.PlatformType.SystemCollectionsGenericIEnumerable, typeArguments, this.host.InternFactory);
                enumeratorType = genericEnumeratorType;
                getEnumerator = new SpecializedMethodReference()
                {
                    CallingConvention = CallingConvention.HasThis,
                    ContainingType = genericEnumerableType,
                    InternFactory = this.host.InternFactory,
                    Name = this.host.NameTable.GetNameFor("GetEnumerator"),
                    Parameters = new List<IParameterTypeInformation>(),
                    Type = genericEnumeratorType,
                    UnspecializedVersion = new MethodReference()
                    {
                        CallingConvention = CallingConvention.HasThis,
                        ContainingType = this.host.PlatformType.SystemCollectionsGenericIEnumerable,
                        InternFactory = this.host.InternFactory,
                        Name = this.host.NameTable.GetNameFor("GetEnumerator"),
                        Parameters = new List<IParameterTypeInformation>(),
                        Type = this.host.PlatformType.SystemCollectionsGenericIEnumerator,
                    },
                };
                var getEnumerator2 = (IMethodReference) 
                    IteratorHelper.First(genericEnumerableType.ResolvedType.GetMembersNamed(this.host.NameTable.GetNameFor("GetEnumerator"), false));
                getEnumerator = getEnumerator2;
                getCurrent = (IMethodReference) IteratorHelper.First(genericEnumeratorType.ResolvedType.GetMembersNamed(this.host.NameTable.GetNameFor("get_Current"), false));
            }
            else
            {
                enumeratorType = this.host.PlatformType.SystemCollectionsIEnumerator;
                getEnumerator = new MethodReference()
                {
                    CallingConvention = CallingConvention.HasThis,
                    ContainingType = enumeratorType,
                    InternFactory = this.host.InternFactory,
                    Name = this.host.NameTable.GetNameFor("GetEnumerator"),
                    Parameters = new List<IParameterTypeInformation>(),
                    Type = this.host.PlatformType.SystemCollectionsIEnumerable,
                };
                getCurrent = new MethodReference()
                {
                    CallingConvention = CallingConvention.HasThis,
                    ContainingType = enumeratorType,
                    InternFactory = this.host.InternFactory,
                    Name = this.host.NameTable.GetNameFor("get_Current"),
                    Parameters = new List<IParameterTypeInformation>(),
                    Type = this.host.PlatformType.SystemObject,
                };
            }

            var initializer = new MethodCall()
                    {
                        Arguments = new List<IExpression>(),
                        IsStaticCall = false,
                        IsVirtualCall = true,
                        MethodToCall = getEnumerator,
                        ThisArgument = forEachStatement.Collection,
                        Type = enumeratorType,
                    };
            IStatement initialization;

            if (!this.foreachLocals.TryGetValue(key, out foreachLocal))
            {
                foreachLocal = new LocalDefinition() { Type = enumeratorType, Name = this.host.NameTable.GetNameFor("CS$5$" + this.foreachLocals.Count) };
                this.foreachLocals.Add(key, foreachLocal);
                initialization = new LocalDeclarationStatement()
                {
                    InitialValue = initializer,
                    LocalVariable = foreachLocal,
                };
            }
            else
            {
                initialization = new ExpressionStatement()
                {
                    Expression = new Assignment()
                    {
                        Source = initializer,
                        Target = new TargetExpression()
                        {
                            Definition = foreachLocal,
                            Instance = null,
                            Type = foreachLocal.Type,
                        },
                        Type = foreachLocal.Type,
                    },
                };
            }

            var newStmts = new List<IStatement>();
            newStmts.Add(new ExpressionStatement(){
                                                Expression = new Assignment(){
                                                     Source = new MethodCall(){
                                                          Arguments = new List<IExpression>(),
                                                          IsStaticCall = false,
                                                          IsVirtualCall = true,
                                                          MethodToCall = getCurrent,
                                                          ThisArgument = new BoundExpression(){
                                                               Definition = foreachLocal,
                                                               Instance = null,
                                                          },
                                                          Type = forEachStatement.Variable.Type,
                                                     },
                                                      Target = new TargetExpression(){
                                                           Definition = forEachStatement.Variable,
                                                           Instance = null,
                                                      },
                                                       Type = forEachStatement.Variable.Type,
                                                },
                                           });
            newStmts.Add(forEachStatement.Body);
            var newBody = new BlockStatement(){ Statements = newStmts,}; 
            var result = new BlockStatement()
            {
                Statements = new List<IStatement>(){
                   initialization,
                   new TryCatchFinallyStatement(){
                       TryBody = new BlockStatement() {
                           Statements = new List<IStatement>(){
                               new WhileDoStatement(){
                                   Body = newBody,
                                   Condition = new MethodCall(){
                                       Arguments = new List<IExpression>(),
                                       IsStaticCall = false,
                                       IsVirtualCall = true,
                                       MethodToCall = moveNext,
                                       ThisArgument = new BoundExpression(){ 
                                           Definition = foreachLocal,
                                           Instance = null,
                                       },
                                       Type = this.host.PlatformType.SystemBoolean,
                                   },
                               },
                           },
                       },
                       FinallyBody = new BlockStatement() {
                           Statements = new List<IStatement>(){
                               new ConditionalStatement(){
                                   Condition = new Equality(){
                                       LeftOperand = new BoundExpression(){ Definition = foreachLocal, Instance = null, Type = foreachLocal.Type, },
                                       RightOperand = new CompileTimeConstant(){ Type = foreachLocal.Type, Value = null, },
                                       Type = this.host.PlatformType.SystemBoolean,
                                   },
                                   FalseBranch = new EmptyStatement(),
                                   TrueBranch = new ExpressionStatement(){
                                       Expression = new MethodCall(){
                                           Arguments = new List<IExpression>(),
                                           IsStaticCall = false,
                                           IsVirtualCall = true,
                                           MethodToCall = this.disposeMethod,
                                           ThisArgument = new BoundExpression(){ 
                                               Definition = foreachLocal,
                                               Instance = null,
                                           },
                                           Type = this.host.PlatformType.SystemVoid,
                                       },
                                   },
                               },
                           },
                       },
                   },
                },
            };
            return result;
        }
 /// <summary>
 /// Rewrites the given assignment expression.
 /// </summary>
 public override IExpression Rewrite(IAssignment assignment) {
   var targetInstance = assignment.Target.Instance;
   var result = base.Rewrite(assignment);
   if (targetInstance == null && assignment.Target.Instance != null) {
     //The target now pushes something onto the stack that was not there before the rewrite.
     //It the right hand side uses the stack, then it will not see the stack it expected.
     //If so, we need to evaluate the right handside and squirrel it away in a temp before executing
     //the actual assignment.
     var popFinder = new PopFinder();
     popFinder.Traverse(assignment.Source);
     if (popFinder.foundAPop) {
       var temp = new LocalDefinition() { Name = this.host.NameTable.GetNameFor("PopTemp"+this.popTempCounter++), Type = assignment.Source.Type };
       var localDeclarationStatement = new LocalDeclarationStatement() { LocalVariable = temp, InitialValue = assignment.Source };
       var blockStatement = new BlockStatement();
       blockStatement.Statements.Add(localDeclarationStatement);
       Contract.Assume(assignment is Assignment);
       ((Assignment)assignment).Source = new BoundExpression() { Definition = temp, Type = temp.Type };
       return new BlockExpression() { BlockStatement = blockStatement, Expression = assignment, Type = assignment.Type };
     }        
   }
   return result;
 }
Example #14
0
 public override void TraverseChildren(IBlockStatement block) {
   Contract.Assume(block is BlockStatement);
   var mutableBlock = (BlockStatement)block;
   this.Traverse(mutableBlock.Statements);
   foreach (var pair in this.declaringBlockMap) {
     if (pair.Value != mutableBlock) continue;
     var boundExpr = this.closureFieldToLocalOrParameterMap[pair.Key] as BoundExpression;
     if (boundExpr == null) { Contract.Assume(false); continue; }
     var local = boundExpr.Definition as ILocalDefinition;
     if (local == null) { Contract.Assume(false); continue; }
     var localDecl = new LocalDeclarationStatement() { LocalVariable = local };
     mutableBlock.Statements.Insert(0, localDecl);
   }
 }
        /// <summary>
        /// Appends the statements afters the calls used to calculate the max of the tmp of all the calls
        /// </summary>
        protected void AppendStatementsTmpCopy(IMethodDefinition method, List<StatementTmpCopyInformation> statementsTmpCopy, Dictionary<IStatement, IBlockStatement> statementsContainingBlocks, Dictionary<string, GlobalPolyInfo> globalPolyInfoTmp)
        {
            var block = ((BasicBlock)((Microsoft.Cci.ILToCodeModel.SourceMethodBody)method.Body).Block);
            var methodStatements = block.Statements;

            var int32Type = _host.PlatformType.SystemInt32;

            var callNumber = 1;

            var localsInsertedByType = new Dictionary<ITypeReference, List<LocalDeclarationStatement>>();

            foreach (var statementCopyInformation in statementsTmpCopy)
            {
                var stmt = statementCopyInformation.AfterStatement;
                var statements = ((BlockStatement)statementsContainingBlocks[stmt]).Statements;

                var index = statements.IndexOf(stmt);
                if (index >= 0)
                {
                    IExpression initialValue = new BoundExpression() { Type = int32Type, Definition = GetTmpField(statementCopyInformation.CalledMethod, statementCopyInformation.TmpType) };
                    
                    var localDecl = new LocalDeclarationStatement()
                    {
                        InitialValue = initialValue,
                        LocalVariable = new LocalDefinition() { Type = int32Type, Name = _host.NameTable.GetNameFor("tmp_call_" + callNumber) }
                    };

                    callNumber++;

                    var tmpType = statementCopyInformation.TmpType;
                    if (!localsInsertedByType.ContainsKey(tmpType))
                    {
                        localsInsertedByType.Add(tmpType, new List<LocalDeclarationStatement>());
                    }
                    localsInsertedByType[tmpType].Add(localDecl);

                    if (!statementCopyInformation.InsideLoop)
                    {
                        statements.Insert(index + 1, localDecl);

                        var calledMethodName = statementCopyInformation.CalledMethodReference.ToString();
                        var contractLocalExpr = TranslateMethodContractToLocalExpression(
                               statementCopyInformation.CalledMethodReference,
                               stmt,
                               _memoryContractsInformation.MethodsTmpContracts[calledMethodName][statementCopyInformation.TmpType],
                               statementCopyInformation.CalledMethodArguments);

                        if (!_currentInstrInfo.GlobalPolyInfoTmp.ContainsKey(tmpType.ToString()))
                        {
                            _currentInstrInfo.GlobalPolyInfoTmp.Add(tmpType.ToString(), new GlobalPolyInfo());
                        }
                        _currentInstrInfo.GlobalPolyInfoTmp[tmpType.ToString()].MaxCalls.Add(contractLocalExpr);
                    }
                    else
                    {
                        localDecl.InitialValue = new CompileTimeConstant() { Type = int32Type, Value = 0 };
                        var loopContainingStatements = ((BasicBlock)statementsContainingBlocks[statementCopyInformation.LoopStartAt]).Statements;
                        loopContainingStatements.Insert(0, localDecl);
                        
                        bool doRegularInstrumentation = true;

                        if (!_currentInstrInfo.GlobalPolyInfoTmp.ContainsKey(tmpType.ToString()))
                        {
                            _currentInstrInfo.GlobalPolyInfoTmp.Add(tmpType.ToString(), new GlobalPolyInfo());
                        }

                        if (statementCopyInformation.LoopInvariants != null)
                        {
                            //invariants available, calculate the max directly and insert the assignment after the loop
                            
                            var calledMethodName = statementCopyInformation.CalledMethodReference.ToString();
                            if (_memoryContractsInformation.MethodsTmpContracts.ContainsKey(calledMethodName) &&
                                _memoryContractsInformation.MethodsTmpContracts[calledMethodName].ContainsKey(statementCopyInformation.TmpType))
                            {
                                var contractLocalExpr = TranslateMethodContractToLocalExpression(
                                    statementCopyInformation.CalledMethodReference,
                                    stmt,
                                    _memoryContractsInformation.MethodsTmpContracts[calledMethodName][statementCopyInformation.TmpType],
                                    statementCopyInformation.CalledMethodArguments);
                                var maxExprPolyCond = PolytopesCalculator.MaxOver(contractLocalExpr, statementCopyInformation.LoopInvariants, GetMethodFreeVars(_currentMethod));
                                IExpression maxPolyExpr = null;
                                IExpression maxCondExpr = null;

                                if (maxExprPolyCond != null)
                                {
                                    maxPolyExpr = ExpressionGenerator.GenerateExpressionFromString(maxExprPolyCond.Poly, _host, _currentMethod);
                                    maxCondExpr = ExpressionGenerator.GenerateExpressionFromString(maxExprPolyCond.Cond, _host, _currentMethod);
                                }

                                index = loopContainingStatements.IndexOf(statementCopyInformation.LoopEndAt);
                                if (index >= 0 && maxPolyExpr != null && maxCondExpr != null)
                                {
                                    doRegularInstrumentation = false;
                                    loopContainingStatements.Insert(index + 1,
                                        new ConditionalStatement()
                                        {
                                            Condition = maxCondExpr,
                                            TrueBranch = new ExpressionStatement()
                                            {
                                                Expression = new Assignment()
                                                {
                                                    Type = int32Type,
                                                    Source = maxPolyExpr,
                                                    Target = new TargetExpression() { Type = int32Type, Definition = localDecl.LocalVariable }
                                                }
                                            },
                                            FalseBranch = new EmptyStatement()
                                        });

                                    //store in the global poly info
                                    _currentInstrInfo.GlobalPolyInfoTmp[tmpType.ToString()].MaxCallsLoops.Add(maxExprPolyCond);
                                }
                            }
                        }

                        if (doRegularInstrumentation)
                        {
                            //no invariants available or could not calculate max, calculate instrumenting Math.Max calls

                            if (statementCopyInformation.InsideLoop)
                            {
                                _currentInstrInfo.GlobalPolyInfoTmp[tmpType.ToString()].AllContractsRequiredAvailable = false;
                            }
                            index = statements.IndexOf(stmt); //adjust the index, it could have changed because of the previous localDecl insertion
                            statements.Insert(index + 1,
                                new ExpressionStatement()
                                {
                                    Expression = new Assignment()
                                    {
                                        Type = int32Type,
                                        Source = BuildMaxCall(new BoundExpression() { Definition = localDecl.LocalVariable, Type = int32Type }, initialValue),
                                        Target = new TargetExpression() { Type = int32Type, Definition = localDecl.LocalVariable }
                                    }
                                });
                        }
                    }
                }
            }

            var appendToStatementList = ((BasicBlock)statementsContainingBlocks[_currentStatement]).Statements;

            foreach (var tmpType in localsInsertedByType.Keys)
            {
                bool doRegularInstrumentation = true;
                var tmpField = GetTmpField(method, tmpType);
                var globalInfoForTmp = globalPolyInfoTmp[tmpType.ToString()];

                //check if we can calculate the max with the polytopes calculator
                if (globalInfoForTmp.AllContractsRequiredAvailable)
                {
                    var polys = new List<string>();
                    var conds = new List<string>();

                    conds.AddRange(GetMethodRequiresExprs(method));

                    polys.AddRange(globalInfoForTmp.MaxCalls);
                    foreach (var poly in globalInfoForTmp.MaxCallsLoops)
                    {
                        polys.Add(poly.Poly);
                        conds.Add(poly.Cond);
                    }

                    var max = PolytopesCalculator.MaxPoly(polys, conds, GetMethodFreeVars(method));

                    if (max != null)
                    {
                        var condExpr = ExpressionGenerator.GenerateExpressionFromString(max.Cond, _host, method);
                        var maxExpr = ExpressionGenerator.GenerateExpressionFromString(max.Poly, _host, method);

                        if (condExpr != null && maxExpr != null)
                        {
                            InsertStatementAtBottom(appendToStatementList,
                                new ConditionalStatement()
                                {
                                    Condition = condExpr,
                                    TrueBranch =
                                        new ExpressionStatement()
                                        {
                                            Expression = new Assignment()
                                            {
                                                Type = int32Type,
                                                Source = new Addition()
                                                {
                                                    Type = int32Type,
                                                    LeftOperand = new BoundExpression() { Type = int32Type, Definition = tmpField },
                                                    RightOperand = maxExpr
                                                },
                                                Target = new TargetExpression() { Type = int32Type, Definition = tmpField }
                                            }
                                        },
                                    FalseBranch = new EmptyStatement()
                                });

                            doRegularInstrumentation = false;
                        }
                    }
                }

                if (doRegularInstrumentation)
                {
                    var maxExpr = GetMaxExpressionOverLocals(localsInsertedByType[tmpType]);

                    //add the statement tmpField += Math.Max(...);
                    InsertStatementAtBottom(appendToStatementList,
                        new ExpressionStatement()
                        {
                            Expression = new Assignment()
                            {
                                Type = int32Type,
                                Source = new Addition()
                                {
                                    Type = int32Type,
                                    LeftOperand = new BoundExpression() { Type = int32Type, Definition = tmpField },
                                    RightOperand = maxExpr
                                },
                                Target = new TargetExpression() { Type = int32Type, Definition = tmpField }
                            }
                        });
                }
            }
        }
Example #16
0
    /// <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;
    }
Example #17
0
 /// <summary>
 /// Create the new body of the iterator method. 
 /// </summary>
 /// <remarks>
 /// Pseudo code:
 /// iteratorClosureLocal = new Closure(0);
 /// iteratorClosureLocal.field = parameter; // for each parameter including this. 
 /// return iteratorClosureLocal;
 /// </remarks>
 private BlockStatement CreateNewIteratorMethodBody(IteratorClosureInformation iteratorClosure) {
   BlockStatement result = new BlockStatement();
   // iteratorClosureLocal = new IteratorClosure(0);
   LocalDefinition localDefinition = new LocalDefinition() {
     Name = this.host.NameTable.GetNameFor("iteratorClosureLocal"),
     Type = GetClosureTypeReferenceFromIterator(iteratorClosure),
   };
   CreateObjectInstance createObjectInstance = new CreateObjectInstance() {
     MethodToCall = GetMethodReference(iteratorClosure, iteratorClosure.Constructor),
     Type = localDefinition.Type
   };
   // the start state depends on whether the iterator is an IEnumerable or an IEnumerator. For the former,
   // it must be created in state -2. Then it is the GetEnumerator method that puts it into its
   // "start" state, i.e., state 0.
   var startState = this.isEnumerable ? -2 : 0;
   createObjectInstance.Arguments.Add(new CompileTimeConstant() { Value = startState, Type = this.host.PlatformType.SystemInt32 });
   LocalDeclarationStatement localDeclarationStatement = new LocalDeclarationStatement() {
     InitialValue = createObjectInstance,
     LocalVariable = localDefinition
   };
   result.Statements.Add(localDeclarationStatement);
   // Generate assignments to closure instance's fields for each of the parameters captured by the closure. 
   foreach (object capturedLocalOrParameter in FieldForCapturedLocalOrParameter.Keys) {
     BoundField boundField = FieldForCapturedLocalOrParameter[capturedLocalOrParameter];
     Assignment assignment;
     ITypeReference localOrParameterType = GetLocalOrParameterType(capturedLocalOrParameter);
     if (capturedLocalOrParameter is ILocalDefinition) continue;
     if (capturedLocalOrParameter is IThisReference) {
       var thisR = new ThisReference();
       IExpression thisValue = thisR;
       if (!this.method.ContainingTypeDefinition.IsClass) {
         thisValue = new AddressDereference() {
           Address = thisR,
           Type = this.method.ContainingTypeDefinition.IsGeneric ? (ITypeReference)this.method.ContainingTypeDefinition.InstanceType : (ITypeReference)this.method.ContainingTypeDefinition
         };
       }
       assignment = new Assignment {
         Source = thisValue,
         Type = this.method.ContainingType,
         Target = new TargetExpression() {
           Definition = GetFieldReference(iteratorClosure, boundField.Field),
           Type = this.method.ContainingType,
           Instance = new BoundExpression() {
             Type = localDefinition.Type,
             Instance = null,
             Definition = localDefinition,
             IsVolatile = false
           }
         },
       };
     } else {
       assignment = new Assignment {
         Source = new BoundExpression() {
           Definition = capturedLocalOrParameter,
           Instance = null,
           IsVolatile = false,
           Type = localOrParameterType
         },
         Type = localOrParameterType,
         Target = new TargetExpression() {
           Definition = GetFieldReference(iteratorClosure, boundField.Field),
           Type = localOrParameterType,
           Instance = new BoundExpression() {
             Type = localDefinition.Type,
             Instance = null,
             Definition = localDefinition,
             IsVolatile = false
           }
         },
       };
     }
     ExpressionStatement expressionStatement = new ExpressionStatement() { Expression = assignment };
     result.Statements.Add(expressionStatement);
   }
   // Generate: return iteratorClosureLocal;
   result.Statements.Add(new ReturnStatement() {
     Expression = new BoundExpression() { Definition = localDeclarationStatement.LocalVariable, Instance = null, Type = localDeclarationStatement.LocalVariable.Type }
   });
   return result;
 }
Example #18
0
 public override void RewriteChildren(LocalDeclarationStatement localDeclarationStatement) {
   // then we don't need to replace this local, so put a dummy value in the table
   // so we don't muck with it.
   var loc = localDeclarationStatement.LocalVariable;
   // locals don't get removed (not tracking scopes) so if a local definition is re-used
   // (say in two for-loops), then we'd be trying to add the same key twice
   // shouldn't ever happen except for when the remaining body of the method is being
   // visited.
   if (!this.tableForLocalDefinition.ContainsKey(loc)) {
     this.tableForLocalDefinition.Add(loc, null);
   }
   if (localDeclarationStatement.InitialValue != null) {
     localDeclarationStatement.InitialValue = this.Rewrite(localDeclarationStatement.InitialValue);
   }
   return;
 }
        public override IStatement Visit(LocalDeclarationStatement localDeclarationStatement)
        {
            ILocalDefinition local = localDeclarationStatement.LocalVariable;
              if (0 < this.currentClosureLocals.Count) {
            //if this temp was introduced to hold a copy of the closure local, then delete it
            var deleteIt = false;
            foreach (var currentClosureLocal in this.currentClosureLocals.Keys) {
              if (TypeHelper.TypesAreEquivalent(currentClosureLocal.Type, local.Type)) {
            deleteIt = true;
            break;
              }
              // Or it might be that we are visiting the method that is being turned back into a lambda
              // and it might be a temp introduced to hold "this" because of decompilation inadequacies.
              // (E.g., if there was "f++" operator in the lambda for a captured local/parameter, then
              // it becomes "ldarg0; dup" in the IL in the closure class and that decompiles to
              // "t1 := this; t2 := t1; t1.f := t2.f + 1".
              ITypeReference t1 = UnspecializedMethods.AsUnspecializedTypeReference(currentClosureLocal.Type);
              ITypeReference t2 = UnspecializedMethods.AsUnspecializedTypeReference(local.Type);
              if (t1 == t2) {
            deleteIt = true;
            break;
              }
            }
            if (deleteIt) {
              if (localDeclarationStatement.InitialValue == null) {
            // then need to delete all assignments to this local because they are the
            // real initialization.
            this.currentClosureLocals[local] = true;
              }
              return CodeDummy.Block;
            }

              }
              base.Visit(localDeclarationStatement);
              int numberOfAssignments = 0;
              if (!this.sourceMethodBody.numberOfAssignments.TryGetValue(local, out numberOfAssignments) || numberOfAssignments > 1)
            return localDeclarationStatement;
              int numReferences = 0;
              this.sourceMethodBody.numberOfReferences.TryGetValue(local, out numReferences);
              if (this.sourceMethodBody.sourceLocationProvider != null) {
            bool isCompilerGenerated = false;
            this.sourceMethodBody.sourceLocationProvider.GetSourceNameFor(local, out isCompilerGenerated);
            if (!isCompilerGenerated) return localDeclarationStatement;
              }
              var val = localDeclarationStatement.InitialValue;
              if (val is CompileTimeConstant || val is TypeOf || val is ThisReference) {
            this.expressionToSubstituteForCompilerGeneratedSingleAssignmentLocal.Add(local, val);
            return CodeDummy.Block; //Causes the caller to omit this statement from the containing statement list.
              }
              if (numReferences == 0 && val == null) return CodeDummy.Block; //unused declaration
              return localDeclarationStatement;
        }
            private void FindCapturedLocals(List<IStatement> statements)
            {
                ILocalDefinition/*?*/ locDef = null;
                IFieldReference/*?*/ fieldRef = null;
                INestedTypeReference/*?*/ closureType = null;
                int i = 0;
                while (i < statements.Count && closureType == null) {
                  var statement = statements[i++];
                  var locDecl = statement as LocalDeclarationStatement;
                  if (locDecl == null) {
                var exprStatement = statement as ExpressionStatement;
                if (exprStatement == null) continue;
                var assignment = exprStatement.Expression as Assignment;
                if (assignment == null) continue;
                if (!(assignment.Source is ICreateObjectInstance)) continue;
                locDef = assignment.Target.Definition as ILocalDefinition;
                if (locDef != null)
                  closureType = UnspecializedMethods.AsUnspecializedNestedTypeReference(locDef.Type);
                else {
                  fieldRef = assignment.Target.Definition as IFieldReference;
                  if (fieldRef == null || !(assignment.Target.Instance is IThisReference)) continue;
                  closureType = UnspecializedMethods.AsUnspecializedNestedTypeReference(fieldRef.Type);
                }
                  } else {
                if (!(locDecl.InitialValue is ICreateObjectInstance)) continue;
                locDef = locDecl.LocalVariable;
                closureType = UnspecializedMethods.AsUnspecializedNestedTypeReference(locDef.Type);
                  }
                }
                if (closureType == null) return;
                //REVIEW: need to avoid resolving types that are not defined in the module we are analyzing.
                ITypeReference t1 = UnspecializedMethods.AsUnspecializedTypeReference(closureType.ContainingType.ResolvedType);
                ITypeReference t2 = UnspecializedMethods.AsUnspecializedTypeReference(this.remover.containingType);
                if (!TypeHelper.TypesAreEquivalent(t1, t2)) {
                  var nt2 = t2 as INestedTypeReference;
                  if (nt2 == null || !TypeHelper.TypesAreEquivalent(t1, nt2.ContainingType)) return;
                }
                var resolvedClosureType = closureType.ResolvedType;
                if (!UnspecializedMethods.IsCompilerGenerated(resolvedClosureType)) return;
                //Check if this is an iterator creating its state class, rather than just a method creating a closure class
                foreach (var iface in resolvedClosureType.Interfaces) {
                  if (TypeHelper.TypesAreEquivalent(iface, resolvedClosureType.PlatformType.SystemCollectionsIEnumerator)) return;
                }
                if (this.remover.sourceMethodBody.privateHelperTypesToRemove == null)
                  this.remover.sourceMethodBody.privateHelperTypesToRemove = new List<ITypeDefinition>();
                this.remover.sourceMethodBody.privateHelperTypesToRemove.Add(resolvedClosureType);
                if (locDef != null)
                  this.remover.currentClosureLocals.Add(locDef, true);
                else {
                  if (this.remover.sourceMethodBody.privateHelperFieldsToRemove == null)
                this.remover.sourceMethodBody.privateHelperFieldsToRemove = new Dictionary<IFieldDefinition, IFieldDefinition>();
                  var field = UnspecializedMethods.UnspecializedFieldDefinition(fieldRef.ResolvedField);
                  this.remover.sourceMethodBody.privateHelperFieldsToRemove.Add(field, field);
                }

                if (resolvedClosureType.IsGeneric && this.remover.sourceMethodBody.MethodDefinition.IsGeneric)
                  this.remover.genericParameterMapper = new GenericMethodParameterMapper(this.remover.host, this.remover.sourceMethodBody.MethodDefinition, resolvedClosureType);

                statements.RemoveAt(i - 1);

                // Walk the rest of the statements in the block (but *without* recursively
                // descending into them) looking for assignments that save local state into
                // fields in the closure. Such assignments do not belong in the method body.
                //
                // They were introduced by the compiler because the closure reads their value.
                // That is, such assignments are of the form:
                //  closureLocal.f := e
                // where "e" is either "this", a local, a parameter, (corner case) a value not held in a local of the original program,
                // or another closureLocal (because sometimes the compiler generates code so
                // that one closure class has access to another one).
                // When the RHS expression is a local/parameter, then rely on a naming
                // convention that the field f has the same name as the local/parameter.
                // If it does not follow the naming convention, then the statement corresponds to
                // a real statement that was in the original method body.
                //
                // For each such assignment statement, delete it from the list of statements and
                // add "e" to the remover's table as the expression to replace all occurrences of
                // "closureLocal.f" throughout the method body.
                //
                // [Note on corner case: this seems to arise when a value occurs in an anonymous delegate that
                // isn't used outside of the anonymous delegate.
                // For instance: { ... var x = new Object(); M((args for lambda) => ... body of lambda contains a reference to x ...) ... }
                // where there are no occurrences of x in the rest of the method body. The compiler plays it safe and still treats x as a
                // captured local.]
                //
                for (int j = i - 1; j < statements.Count; j++) {
                  if (statements[j] is IEmptyStatement) continue;
                  IExpressionStatement/*?*/ es = statements[j] as IExpressionStatement;
                  if (es == null) continue;
                  IAssignment/*?*/ assignment = es.Expression as IAssignment;
                  if (assignment == null) continue;
                  IFieldReference/*?*/ closureField = assignment.Target.Definition as IFieldReference;
                  if (closureField == null) {
                // check to see if it is of the form "loc := closureLocal".
                // I.e., a local has been introduced that is an alias for a local containing a closure instance.
                var targetLoc = this.TargetExpressionAsLocal(assignment.Target);
                var sourceLoc = this.ExpressionAsLocal(assignment.Source);
                if (targetLoc != null && sourceLoc != null && this.remover.currentClosureLocals.ContainsKey(sourceLoc)) {
                  this.remover.currentClosureLocals.Add(targetLoc, true);
                  statements.RemoveAt(j--);
                }
                continue;
                  }
                  var unspecializedClosureField = UnspecializedMethods.UnspecializedFieldReference(closureField);
                  var closureFieldContainingType = UnspecializedMethods.AsUnspecializedNestedTypeReference(closureField.ContainingType);
                  if (closureFieldContainingType == null) continue;
                  if (!TypeHelper.TypesAreEquivalent(closureFieldContainingType, closureType)) continue;
                  if (this.remover.capturedBinding.ContainsKey(unspecializedClosureField.InternedKey)) continue;
                  var thisReference = assignment.Source as IThisReference;
                  if (thisReference == null) {
                var/*?*/ binding = assignment.Source as IBoundExpression;
                //if (binding == null) {
                //  //The closure is capturing a local that is defined in the block being closed over. Need to introduce the local.
                //  var newLocal = new LocalDefinition() {
                //    Name = closureField.Name,
                //    Type = closureField.Type,
                //  };
                //  var newLocalDecl = new LocalDeclarationStatement() { LocalVariable = newLocal, InitialValue = assignment.Source };
                //  statements[j] = newLocalDecl;
                //  if (this.remover.sourceMethodBody.privateHelperFieldsToRemove == null)
                //    this.remover.sourceMethodBody.privateHelperFieldsToRemove = new Dictionary<IFieldDefinition, IFieldDefinition>();
                //  this.remover.sourceMethodBody.privateHelperFieldsToRemove[unspecializedClosureField.ResolvedField] = unspecializedClosureField.ResolvedField;
                //  this.remover.capturedBinding.Add(unspecializedClosureField.InternedKey, new BoundExpression() { Definition = newLocal, Type = newLocal.Type });
                //  continue;
                //}
                if (binding != null && (binding.Definition is IParameterDefinition || binding.Definition is ILocalDefinition)) {
                  var p = binding.Definition as IParameterDefinition;
                  if (p != null) {
                if (closureField.Name != p.Name) {
                  continue;
                } else {
                  this.remover.capturedBinding[unspecializedClosureField.InternedKey] = binding;
                }
                  } else {
                // must be a local
                var l = binding.Definition as ILocalDefinition;
                if (closureField.Name != l.Name) {
                  // Check to see if it is closureLocal.f := other_closure_local
                  // If so, delete it.
                  var sourceLoc = ExpressionAsLocal(assignment.Source);
                  if (sourceLoc != null && (this.remover.currentClosureLocals.ContainsKey(sourceLoc) || this.exceptionContainer == sourceLoc)) {
                    statements.RemoveAt(j--);
                    if (this.exceptionContainer == sourceLoc)
                      this.remover.capturedBinding[unspecializedClosureField.InternedKey] = binding;
                  }
                  continue;
                } else {
                  this.remover.capturedBinding[unspecializedClosureField.InternedKey] = binding;
                }
                  }
                } else if (binding != null && fieldRef != null) {
                  //In this case the closure is inside an iterator and its closure fields get their values from iterator state class fields or expressions.
                  //In the former case, arrange for all references to the closure field to become references to the corresponding iterator state field.
                  //In the latter case, the loop below will introduce a local to hold the value of the expression and arrange for references to the closure
                  //field to become a reference to the local.
                  IFieldReference iteratorField = binding.Definition as IFieldReference;
                  if (iteratorField != null && binding.Instance is IThisReference) {
                this.remover.capturedBinding[unspecializedClosureField.InternedKey] = binding;
                  } else
                continue;
                } else if (binding != null) {
                  //In this case the closure is inside another closure and the closure fields get their values from the fields of the outer closure.
                  IFieldReference outerClosureField = binding.Definition as IFieldReference;
                  if (outerClosureField != null && binding.Instance is IThisReference) {
                this.remover.capturedBinding[unspecializedClosureField.InternedKey] = binding;
                  } else
                continue;
                } else {
                  // Corner case: see note above
                  LocalDefinition localDefinition = new LocalDefinition() {
                Name = closureField.ResolvedField.Name,
                Type = this.remover.genericParameterMapper == null ? closureField.Type : this.remover.genericParameterMapper.Visit(closureField.Type),
                  };
                  LocalDeclarationStatement localDeclStatement = new LocalDeclarationStatement() {
                LocalVariable = localDefinition,
                InitialValue = assignment.Source,
                  };
                  statements.Insert(j, localDeclStatement); j++;
                  this.remover.capturedBinding[unspecializedClosureField.InternedKey] = new BoundExpression() { Definition = localDefinition };
                  if (this.remover.sourceMethodBody.privateHelperFieldsToRemove == null)
                this.remover.sourceMethodBody.privateHelperFieldsToRemove = new Dictionary<IFieldDefinition, IFieldDefinition>();
                  this.remover.sourceMethodBody.privateHelperFieldsToRemove[closureField.ResolvedField] = closureField.ResolvedField;
                }
                  } else {
                this.remover.capturedBinding[unspecializedClosureField.InternedKey] = new BoundExpression() { Instance = thisReference };
                  }
                  statements.RemoveAt(j--);
                }

                foreach (var field in closureType.ResolvedType.Fields) {
                  if (this.remover.capturedBinding.ContainsKey(field.InternedKey)) continue;
                  var newLocal = new LocalDefinition() {
                Name = field.Name,
                Type = this.remover.genericParameterMapper == null ? field.Type : this.remover.genericParameterMapper.Visit(field.Type),
                  };
                  var newLocalDecl = new LocalDeclarationStatement() { LocalVariable = newLocal };
                  statements.Insert(i - 1, newLocalDecl);
                  if (this.remover.sourceMethodBody.privateHelperFieldsToRemove == null)
                this.remover.sourceMethodBody.privateHelperFieldsToRemove = new Dictionary<IFieldDefinition, IFieldDefinition>();
                  this.remover.sourceMethodBody.privateHelperFieldsToRemove[field] = field;
                  this.remover.capturedBinding.Add(field.InternedKey, new BoundExpression() { Definition = newLocal, Type = newLocal.Type });
                }
            }
Example #21
0
 // For the first assignment to a local variable in a block before a control statement is hit,
 // if the local variable is not mentioned previously, we turn this assignment into a local declaration.
 private void AddDeclarationsWithInitialValues(IEnumerable<ILocalDefinition> localVariables, BasicBlock block)
 {
     List<ILocalDefinition> topLevelLocals = new List<ILocalDefinition>(localVariables);
       List<ILocalDefinition> localsMet = new List<ILocalDefinition>();
       for (int i = 0; i < block.Statements.Count; i++) {
     if (topLevelLocals.Count == 0) break;
     IExpressionStatement expressionStatement = block.Statements[i] as IExpressionStatement;
     if (expressionStatement != null) {
       IAssignment assignment = expressionStatement.Expression as IAssignment;
       if (assignment != null) {
     ILocalDefinition localDef = assignment.Target.Definition as ILocalDefinition;
     if (localDef != null && topLevelLocals.Contains(localDef) && !localsMet.Contains(localDef) && !this.declaredLocals.ContainsKey(localDef)) {
       LocalDeclarationStatement localDecl = new LocalDeclarationStatement() {
         LocalVariable = localDef, InitialValue = assignment.Source, Locations = new List<ILocation>(expressionStatement.Locations),
       };
       this.declaredLocals.Add(localDef, true);
       block.Statements[i] = localDecl;
       topLevelLocals.Remove(localDef);
       localsMet.Add(localDef);
     }
       }
     }
     LocalFinder finder = new LocalFinder();
     finder.Traverse(block.Statements[i]);
     foreach (ILocalDefinition local in finder.FoundLocals) {
       if (!localsMet.Contains(local)) localsMet.Add(local);
     }
     //Once we see a statement that can transfer control somewhere else, we
     //no longer know that any subsequent assignment dominates all references
     //and hence cannot postpone adding the declaration until we can unify it with the assignment.
     IGotoStatement gotoStatement = block.Statements[i] as IGotoStatement;
     if (gotoStatement != null) break;
     IConditionalStatement conditionalStatement = block.Statements[i] as IConditionalStatement;
     if (conditionalStatement != null) break;
     ISwitchStatement switchStatement = block.Statements[i] as ISwitchStatement;
     if (switchStatement != null) break;
     IForEachStatement foreachStatement = block.Statements[i] as IForEachStatement;
     if (foreachStatement != null) break;
     IForStatement forStatement = block.Statements[i] as IForStatement;
     if (forStatement != null) break;
     ITryCatchFinallyStatement tryStatement = block.Statements[i] as ITryCatchFinallyStatement;
     if (tryStatement != null) break;
       }
 }
Example #22
0
 /// <summary>
 /// Visits the specified local declaration statement.
 /// </summary>
 /// <param name="localDeclarationStatement">The local declaration statement.</param>
 public override void Visit(ILocalDeclarationStatement localDeclarationStatement)
 {
     LocalDeclarationStatement mutableLocalDeclarationStatement = localDeclarationStatement as LocalDeclarationStatement;
     if (alwaysMakeACopy || mutableLocalDeclarationStatement == null) mutableLocalDeclarationStatement = new LocalDeclarationStatement(localDeclarationStatement);
     this.resultStatement = this.myCodeMutator.Visit(mutableLocalDeclarationStatement);
 }