/// <summary>
        /// Visits each method and starts the visitation of each statement with the context of a method to collect intrumentation information
        /// </summary>
        public override void Visit(IMethodDefinition method)
        {
            System.Diagnostics.Debug.WriteLine("Visiting method: " + method.Name);

            var instrInfo = new InstrumentationInformation();

            //this dictionary contains all the type of tmp to instrument in the keys
            //and the statements where an increment should be done in the values
            instrInfo.TmpFieldsToInstrument = new Dictionary<FieldDefinition, List<IStatement>>();

            //this dictionary contains all the type of rsd to instrument in the keys
            //and the statements where an increment should be done in the values
            instrInfo.RsdFieldsToInstrument = new Dictionary<FieldDefinition, List<IStatement>>();

            //this boolean is true after finding a Contract.Memory.DestTmp() call
            instrInfo.StoreNextTmp = false;

            //this boolean is true after finding a Contract.Memory.DestRsd(rsdName) call
            instrInfo.StoreNextRsd = false;

            //stores the containing block of each statement, needed later for the instrumentation
            instrInfo.StatementsContainingBlocks = new Dictionary<IStatement, IBlockStatement>();

            //stores a list of statement after which a copy of tmp should be done
            instrInfo.StatementsTmpCopy = new List<StatementTmpCopyInformation>();

            //stores a list of statement after which a transference of rsd should be done
            instrInfo.StatementsRsdTransference = new List<StatementRsdTransferenceInformation>();

            //these two list store information about AddTmp and AddRsd calls
            instrInfo.AddToTmpRsdSources = new List<RsdNames>();
            instrInfo.AddToRsdRsdSources = new List<RsdNames>();

            //these dicts store the global poly info collected to verify with the calculator at the end of the method
            instrInfo.GlobalPolyInfoTmp = new Dictionary<string, GlobalPolyInfo>(); //<type, GlobalPolyInfo>
            instrInfo.GlobalPolyInfoRsd = new Dictionary<Tuple<string, string>, GlobalPolyInfo>(); //<<type, name>, GlobalPolyInfo>

            //stores the fields to add polys after loops
            instrInfo.LoopsPolyAdd = new List<PolyAddInformation>();

            _currentMethod = method;
            _currentInstrInfo = instrInfo;
            _loopNestLevel = 0;
            _visitedGotoStatements = new List<IGotoStatement>();
            _loopInvariants = new List<HashSet<string>>();
            _afterLoopAssignments = new List<Tuple<FieldDefinition, PolyCond>>();

            //set method info needed by PointsToInformation
            _pointsToInformation.CurrentMethodInfo = new PointsToInformation.CurrentMethodInfoData()
                {
                    ContainingType = method.ContainingTypeDefinition.ResolvedType,
                    Parameters = method.Parameters
                };

            //these call triggers the visitation of all the statements of the method,
            //instrumentation data will be collected in instrInfo
            base.Visit(method);

            //do tmp instrumentation for each type of tmp detected in the method
            foreach (var tmp in instrInfo.TmpFieldsToInstrument.Keys)
            {
                InstrumentTmp(method, tmp, instrInfo.TmpFieldsToInstrument[tmp], instrInfo.StatementsContainingBlocks);
            }

            //appends the statements to copy the tmps of the calls and calculate the maximum
            AppendStatementsTmpCopy(method, instrInfo.StatementsTmpCopy, instrInfo.StatementsContainingBlocks, instrInfo.GlobalPolyInfoTmp);

            //do rsd instrumentation for each type of rsd detected in the method
            foreach (var rsd in instrInfo.RsdFieldsToInstrument.Keys)
            {
                InstrumentRsd(method, rsd, instrInfo.RsdFieldsToInstrument[rsd], instrInfo.StatementsContainingBlocks);
            }

            //do rsd to tmp/rsd transference for each AddTmp/AddRsd detected in the methos
            AppendStatementsRsdTransference(method, instrInfo.StatementsRsdTransference, instrInfo.StatementsContainingBlocks);

            //do loop poly add instrumentation
            foreach (var loopPolyAdd in _currentInstrInfo.LoopsPolyAdd)
            {
                AppendStatementsLoopPolyAdd(method, loopPolyAdd, instrInfo.StatementsContainingBlocks);
            }

            //do global tmp poly verification
            foreach (var type in instrInfo.GlobalPolyInfoTmp.Keys)
            {
                GlobalPolyVerifcationTmp(method, instrInfo, type, instrInfo.GlobalPolyInfoTmp[type]);
            }

            //do global rsd poly verification
            foreach (var type in instrInfo.GlobalPolyInfoRsd.Keys)
            {
                GlobalPolyVerifcationRsd(method, instrInfo, type.Item1, type.Item2, instrInfo.GlobalPolyInfoRsd[type]);
            }
        }
        protected void GlobalPolyVerifcationRsd(IMethodDefinition method, InstrumentationInformation instrInfo, string type, string name, GlobalPolyInfo polyInfo)
        {
            var methodStatements = ((BasicBlock)((Microsoft.Cci.ILToCodeModel.SourceMethodBody)method.Body).Block).Statements;

            var int32Type = _host.PlatformType.SystemInt32;

            var rsdField = GetRsdField(method, name, type);

            if (polyInfo.AllContractsRequiredAvailable)
            {
                var candPolys = new List<string>();
                var conds = new List<string>();
                conds.AddRange(GetMethodRequiresExprs(method));
                foreach (var poly in polyInfo.DirectQuantityLoops)
                {
                    candPolys.Add(poly.Poly);
                    conds.Add(poly.Cond);
                }
                foreach (var poly in polyInfo.QuantityTransferLoops)
                {
                    candPolys.Add(poly.Poly);
                    conds.Add(poly.Cond);
                }
                if (polyInfo.DirectQuantity > 0)
                {
                    candPolys.Add(polyInfo.DirectQuantity.ToString());
                }
                candPolys.AddRange(polyInfo.QuantityTransfer);
                if (candPolys.Count > 0)
                {
                    var candPoly = string.Join(" + ", candPolys);
                    //find rsd contracts for the type and compare with candPoly
                    var methodName = method.ToString();
                    if (_memoryContractsInformation.MethodsRsdContractsWithConds.ContainsKey(methodName))
                    {
                        var methodRsdContracts = _memoryContractsInformation.MethodsRsdContractsWithConds[methodName];
                        //methodName -> rsd name -> type of rsd -> cond -> contract (string expr + code model expr)
                        //public Dictionary<string, Dictionary<string, Dictionary<ITypeReference, Dictionary<string, Tuple<string, IExpression>>>>> MethodsRsdContractsWithConds = new Dictionary<string, Dictionary<string, Dictionary<ITypeReference, Dictionary<string, Tuple<string, IExpression>>>>>();
                        foreach (var rsdName in methodRsdContracts.Keys)
                        {
                            foreach (var rsdType in methodRsdContracts[rsdName].Keys)
                            {
                                if (rsdName == name && rsdType.ToString() == type)
                                {
                                    foreach (var contractCond in methodRsdContracts[rsdName][rsdType].Keys)
                                    {
                                        var methodContract = methodRsdContracts[rsdName][rsdType][contractCond].Item1;
                                        var methodContractExpressionObject = methodRsdContracts[rsdName][rsdType][contractCond].Item2;
                                        //see if candPoly <= methodContract
                                        string cond;
                                        var newConds = new List<string>();
                                        newConds.AddRange(conds);
                                        if (contractCond != "true")
                                        {
                                            newConds.Add(contractCond);
                                        }
                                        if (PolytopesCalculator.LowerOrEqual(candPoly, methodContract, newConds, GetMethodFreeVars(method), out cond))
                                        {
                                            //insert the statement: if (cond) Contract.Assume(candPoly <= methodContract);
                                            var condExpr = ExpressionGenerator.GenerateExpressionFromString(cond, _host, method);

                                            if (condExpr != null)
                                            {
                                                InsertStatementAtBottom(methodStatements,
                                                    new ConditionalStatement()
                                                    {
                                                        Condition = condExpr,
                                                        TrueBranch =
                                                            new AssumeStatement()
                                                            {
                                                                Condition =
                                                                    new LessThanOrEqual()
                                                                    {
                                                                        LeftOperand = new BoundExpression()
                                                                        {
                                                                            Definition = rsdField,
                                                                            Type = rsdField.Type
                                                                        },
                                                                        RightOperand = methodContractExpressionObject,
                                                                        Type = _host.PlatformType.SystemBoolean,
                                                                    }
                                                            },
                                                        FalseBranch = new EmptyStatement()
                                                    });
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }