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