public static IMethodReference FindMethodImplementation(this ITypeReference receiverType, IMethodReference method) { var originalReceiverType = receiverType; IMethodReference result = null; if (method.ToString().Contains("Current")) { } if (method.ToString().Contains("GetEnumerator")) { } while (receiverType != null && IsSubtypeOrImplements(receiverType, method.ContainingType)) { var receiverTypeDef = receiverType.ResolvedType; if (receiverTypeDef == null) { break; } // var matchingMethod = receiverTypeDef.Methods.SingleOrDefault(m => MemberHelper.GetMemberSignature(m,NameFormattingOptions.PreserveSpecialNames) // .EndsWith(MemberHelper.GetMemberSignature(method,NameFormattingOptions.PreserveSpecialNames))); var matchingMethods = receiverTypeDef.Methods.Where(m => m.Name.Value == method.Name.Value && ParametersAreCompatible(m, method)); if (matchingMethods.Count() > 1) { matchingMethods = receiverTypeDef.Methods.Where(m => m.Name.UniqueKey == method.Name.UniqueKey && MemberHelper.SignaturesAreEqual(m, method)); } var matchingMethod = matchingMethods.SingleOrDefault(); if (matchingMethod != null) { result = matchingMethod; return(result); } else { receiverType = receiverTypeDef.BaseClasses.SingleOrDefault(); } } if (result == null) { } return(result); }
public static IMethodDefinition ResolveMethodThrowing(IMethodReference method) { IMethodDefinition result = method.ResolvedMethod; if (result == Dummy.Method || result == null) { throw new Exception(String.Format("Cannot resolve member '{0}'. Are all dependent assemblies loaded?", method.ToString())); } Debug.Assert(!result.GetType().Name.Contains("Dummy")); return result; }
public static IMethodDefinition ResolveMethodThrowing(IMethodReference method) { IMethodDefinition result = method.ResolvedMethod; if (result == Dummy.Method || result == null) { throw new Exception(String.Format("Cannot resolve member '{0}'. Are all dependent assemblies loaded?", method.ToString())); } Debug.Assert(!result.GetType().Name.Contains("Dummy")); return(result); }
/// <summary> /// Detects calls to memory contracts methods and stores the needed information for the instrumentation /// </summary> public void VisitMethodCall(IMethodReference methodReference, IEnumerable<IExpression> arguments) { System.Diagnostics.Debug.WriteLine("Visiting method call: " + methodReference.ToString()); if (methodReference.ContainingType.ToString() == "Contracts.Contract.Memory") { switch (methodReference.Name.Value) { #region Tmp case "Tmp": { if (methodReference is Microsoft.Cci.MutableCodeModel.GenericMethodInstanceReference) { var methodToCall = (Microsoft.Cci.MutableCodeModel.GenericMethodInstanceReference)methodReference; var argsIt = arguments.GetEnumerator(); argsIt.MoveNext(); var limit = argsIt.Current; var cond = (IExpression)null; if (argsIt.MoveNext()) { cond = argsIt.Current; } var tmpField = AddTmpContractToMethod(_currentMethod, methodToCall.GenericArguments[0], limit, cond); if (!_currentInstrInfo.TmpFieldsToInstrument.ContainsKey(tmpField)) { _currentInstrInfo.TmpFieldsToInstrument.Add(tmpField, new List<IStatement>()); } } } break; #endregion #region DestTmp case "DestTmp": { _currentInstrInfo.StoreNextTmp = true; var argsIt = arguments.GetEnumerator(); _currentInstrInfo.TrustNextAnnotation = argsIt.MoveNext() && argsIt.Current is CompileTimeConstant && (int)((CompileTimeConstant)argsIt.Current).Value == 1; _currentInstrInfo.Instrument = true; //if inside loop and we have all the necessary invariants if (_loopNestLevel > 0 && _loopInvariants.TrueForAll(s => s.Count > 0)) { _currentInstrInfo.Instrument = false; _currentInstrInfo.NextStmtPoly = PolytopesCalculator.CountPoints(JoinLoopInvariants(_loopInvariants), GetMethodFreeVars(_currentMethod)); //if the count failed, do regular instrumentation if (_currentInstrInfo.NextStmtPoly == null) { _currentInstrInfo.Instrument = true; } } } break; #endregion #region Rsd case "Rsd": { if (methodReference is Microsoft.Cci.MutableCodeModel.GenericMethodInstanceReference) { var methodToCall = (Microsoft.Cci.MutableCodeModel.GenericMethodInstanceReference)methodReference; var argsIt = arguments.GetEnumerator(); argsIt.MoveNext(); var rsdName = ""; if (argsIt.Current is BoundExpression) { rsdName = ((BoundExpression)argsIt.Current).Definition.ToString(); } argsIt.MoveNext(); var limit = argsIt.Current; var cond = (IExpression)null; if (argsIt.MoveNext()) { cond = argsIt.Current; } var rsdField = AddRsdContractToMethod(_currentMethod, methodToCall.GenericArguments[0], rsdName, limit, cond); if (!_currentInstrInfo.RsdFieldsToInstrument.ContainsKey(rsdField)) { _currentInstrInfo.RsdFieldsToInstrument.Add(rsdField, new List<IStatement>()); } } } break; #endregion #region DestRsd case "DestRsd": { var argsIt = arguments.GetEnumerator(); argsIt.MoveNext(); var rsdName = ""; if (argsIt.Current is BoundExpression) { rsdName = ((BoundExpression)argsIt.Current).Definition.ToString(); } _currentInstrInfo.TrustNextAnnotation = argsIt.MoveNext() && argsIt.Current is CompileTimeConstant && (int)((CompileTimeConstant)argsIt.Current).Value == 1; _currentInstrInfo.StoreNextRsd = true; _currentInstrInfo.NextStoreRsdName = rsdName; _currentInstrInfo.Instrument = true; //if inside loop and we have all the necessary invariants if (_loopNestLevel > 0 && _loopInvariants.TrueForAll(s => s.Count > 0)) { _currentInstrInfo.Instrument = false; _currentInstrInfo.NextStmtPoly = PolytopesCalculator.CountPoints(JoinLoopInvariants(_loopInvariants), GetMethodFreeVars(_currentMethod)); //if the count failed, do regular instrumentation if (_currentInstrInfo.NextStmtPoly == null) { _currentInstrInfo.Instrument = true; } } } break; #endregion #region AddTmp/AddRsd case "AddTmp": case "AddRsd": { var argsIt = arguments.GetEnumerator(); argsIt.MoveNext(); var rsdNameLocal = ""; if (argsIt.Current is BoundExpression) { rsdNameLocal = ((BoundExpression)argsIt.Current).Definition.ToString(); } var rsdNameCall = ""; if (argsIt.MoveNext()) { if (argsIt.Current is BoundExpression) { rsdNameCall = ((BoundExpression)argsIt.Current).Definition.ToString(); } //two parameters, Rsd to Rsd _currentInstrInfo.AddToRsdRsdSources.Add( new RsdNames() { LocalRsdName = rsdNameLocal, CallRsdName = rsdNameCall, Trust = argsIt.MoveNext() && argsIt.Current is CompileTimeConstant && (int)((CompileTimeConstant)argsIt.Current).Value == 1, Statement = _currentStatement }); } else { rsdNameCall = rsdNameLocal; //in this case rsdNameLocal is actually the name of the rsd in the called method //one parameter, Rsd to Tmp _currentInstrInfo.AddToTmpRsdSources.Add( new RsdNames() { CallRsdName = rsdNameCall, Trust = argsIt.MoveNext() && argsIt.Current is CompileTimeConstant && (int)((CompileTimeConstant)argsIt.Current).Value == 1, Statement = _currentStatement }); } } break; #endregion #region IterationSpace case "IterationSpace": { //store the loop invariant _loopInvariants for the current loop according to _loopNestLevel var argsIt = arguments.GetEnumerator(); argsIt.MoveNext(); var cond = argsIt.Current; var locsIt = cond.Locations.GetEnumerator(); if (locsIt.MoveNext()) { var match = reLoopInv.Match(((IPrimarySourceLocation)locsIt.Current).Source); if (match.Success) { _loopInvariants[_loopNestLevel - 1].Add(match.Groups[1].Value); } } } break; #endregion } } else { var currentMethodName = _currentMethod.ToString(); var calledMethodName = methodReference.ToString(); //register the tmps of the called method to calculate the maximum later if (_memoryContractsInformation.MethodsTmpTypes.ContainsKey(currentMethodName)) { var calledMethodTmps = new List<ITypeReference>(); if (_memoryContractsInformation.MethodsTmpTypes.ContainsKey(calledMethodName)) { calledMethodTmps = _memoryContractsInformation.MethodsTmpTypes[calledMethodName]; } foreach (var tmpType in _memoryContractsInformation.MethodsTmpTypes[currentMethodName]) { //if the called method has a contract for the tmp type if (TypeListContainsType(calledMethodTmps, tmpType)) { //register the copy statement to be added later --> int local_tmp = called_class.tmp; var tmpInfo = new StatementTmpCopyInformation() { AfterStatement = _currentStatement, CalledMethod = methodReference.ResolvedMethod, TmpType = tmpType, InsideLoop = _loopNestLevel > 0, LoopStartAt = _loopNestLevel > 0 ? _outmostLoopStart : null, LoopInvariants = _loopNestLevel > 0 && _loopInvariants.TrueForAll(s => s.Count > 0) ? JoinLoopInvariants(_loopInvariants) : null, CalledMethodReference = methodReference, CalledMethodArguments = arguments }; _currentInstrInfo.StatementsTmpCopy.Add(tmpInfo); if (_loopNestLevel > 0) { _pendingOutmostLoopEndToRegister.Add(tmpInfo); } } } } //register the copy of Rsd to Tmp if there were previous AddTmp statements if (_currentInstrInfo.AddToTmpRsdSources.Count > 0) { //intrumentation if (_memoryContractsInformation.MethodsRsdTypes.ContainsKey(calledMethodName)) { foreach (var rsdName in _currentInstrInfo.AddToTmpRsdSources) { //find all the rsds in the called method with the given name foreach (var rsdType in _memoryContractsInformation.MethodsRsdTypes[calledMethodName]) { if (rsdType.Name == rsdName.CallRsdName) { //see if there is a local tmp for the rsd type in the called method contract if (_memoryContractsInformation.MethodsTmpTypes.ContainsKey(currentMethodName) && TypeListContainsType(_memoryContractsInformation.MethodsTmpTypes[currentMethodName], rsdType.Type)) { bool doRegularInstrumentation = true; if (!_currentInstrInfo.GlobalPolyInfoTmp.ContainsKey(rsdType.Type.ToString())) { _currentInstrInfo.GlobalPolyInfoTmp.Add(rsdType.Type.ToString(), new GlobalPolyInfo()); } //see if we can calculate the sum inside a loop using the polytopes calc if (_loopNestLevel > 0 && _loopInvariants.TrueForAll(s => s.Count > 0)) { if (_memoryContractsInformation.MethodsRsdContracts.ContainsKey(calledMethodName) && _memoryContractsInformation.MethodsRsdContracts[calledMethodName].ContainsKey(rsdName.CallRsdName) && _memoryContractsInformation.MethodsRsdContracts[calledMethodName][rsdName.CallRsdName].ContainsKey(rsdType.Type)) { var contractLocalExpr = TranslateMethodContractToLocalExpression( methodReference, _currentStatement, _memoryContractsInformation.MethodsRsdContracts[calledMethodName][rsdName.CallRsdName][rsdType.Type], arguments); var sumExprPolyCond = PolytopesCalculator.SumOver(contractLocalExpr, JoinLoopInvariants(_loopInvariants), GetMethodFreeVars(_currentMethod)); var sumPolyExpr = ExpressionGenerator.GenerateExpressionFromString(sumExprPolyCond.Poly, _host, _currentMethod); var sumCondExpr = ExpressionGenerator.GenerateExpressionFromString(sumExprPolyCond.Cond, _host, _currentMethod); if (sumPolyExpr != null && sumCondExpr != null) { //register the poly to be added to the tmp field after the loop _afterLoopAssignments.Add(new Tuple<FieldDefinition, PolyCond>(GetTmpField(_currentMethod, rsdType.Type), sumExprPolyCond)); doRegularInstrumentation = false; //store in the global poly info _currentInstrInfo.GlobalPolyInfoTmp[rsdType.Type.ToString()].QuantityTransferLoops.Add(sumExprPolyCond); } } } if (doRegularInstrumentation) { //register the transference statement to be added later --> local_tmp += called_class.rsd; if (_loopNestLevel > 0) { _currentInstrInfo.GlobalPolyInfoTmp[rsdType.Type.ToString()].AllContractsRequiredAvailable = false; } else if (_memoryContractsInformation.MethodsRsdContracts.ContainsKey(calledMethodName) && _memoryContractsInformation.MethodsRsdContracts[calledMethodName].ContainsKey(rsdName.CallRsdName) && _memoryContractsInformation.MethodsRsdContracts[calledMethodName][rsdName.CallRsdName].ContainsKey(rsdType.Type)) { var contractLocalExpr = TranslateMethodContractToLocalExpression( methodReference, _currentStatement, _memoryContractsInformation.MethodsRsdContracts[calledMethodName][rsdName.CallRsdName][rsdType.Type], arguments); _currentInstrInfo.GlobalPolyInfoTmp[rsdType.Type.ToString()].QuantityTransfer.Add(contractLocalExpr); } _currentInstrInfo.StatementsRsdTransference.Add( new StatementRsdTransferenceInformation() { AfterStatement = _currentStatement, AddSource = GetRsdField(methodReference.ResolvedMethod, rsdName.CallRsdName, rsdType.Type), AddTarget = GetTmpField(_currentMethod, rsdType.Type) }); } } } } } } //verify the correctness foreach (var rsdName in _currentInstrInfo.AddToTmpRsdSources) { //if not trust if (!rsdName.Trust) { var rsdNameCall = rsdName.CallRsdName; var localExpr = ""; if (rsdNameCall == "Contracts.Contract.Memory.Return") { localExpr = GetReturnExprFromStatement(_currentStatement); } else if (rsdNameCall == "Contracts.Contract.Memory.This") { localExpr = GetCallStatementThisExpr(methodReference, _currentStatement); } else if (_memoryContractsInformation.MethodsRsdExprs.ContainsKey(methodReference.ResolvedMethod.ToString()) && _memoryContractsInformation.MethodsRsdExprs[methodReference.ResolvedMethod.ToString()].ContainsKey(rsdNameCall)) { var calledMethodExpr = _memoryContractsInformation.MethodsRsdExprs[methodReference.ResolvedMethod.ToString()][rsdNameCall]; localExpr = GetBoundRsdExprFromStatement(methodReference, _currentStatement, calledMethodExpr, arguments); } if (localExpr != "") { if (_pointsToInformation.Escapes(_currentMethod.ContainingType.ToString(), _currentMethod.Name.Value, localExpr)) { string location = LocationsToString(rsdName.Statement.Locations); if (location != null) { _errorReportItems.Add(new ErrorReportItem() { Message = "The called method rsd destination escapes from the method.", Location = location }); } } } } } //clean the list for the next call _currentInstrInfo.AddToTmpRsdSources = new List<RsdNames>(); } //register the copy of Rsd to Rsd if there were previous AddRsd statements if (_currentInstrInfo.AddToRsdRsdSources.Count > 0) { //instrumentation if (_memoryContractsInformation.MethodsRsdTypes.ContainsKey(calledMethodName)) { foreach (var rsdNames in _currentInstrInfo.AddToRsdRsdSources) { //find all the rsds in the called method with the given name foreach (var rsdType in _memoryContractsInformation.MethodsRsdTypes[calledMethodName]) { if (rsdType.Name == rsdNames.CallRsdName) { //see if there is a local rsd for the rsd type in the called method contract if (_memoryContractsInformation.MethodsRsdTypes.ContainsKey(currentMethodName) && _memoryContractsInformation.MethodsRsdTypes[currentMethodName].Contains(new RsdType() { Name = rsdNames.LocalRsdName, Type = rsdType.Type })) { bool doRegularInstrumentation = true; var typeAndName = new Tuple<string, string>(rsdType.Type.ToString(), rsdNames.LocalRsdName); if (!_currentInstrInfo.GlobalPolyInfoRsd.ContainsKey(typeAndName)) { _currentInstrInfo.GlobalPolyInfoRsd.Add(typeAndName, new GlobalPolyInfo()); } //see if we can calculate the sum inside a loop using the polytopes calc if (_loopNestLevel > 0 && _loopInvariants.TrueForAll(s => s.Count > 0)) { if (_memoryContractsInformation.MethodsRsdContracts.ContainsKey(calledMethodName) && _memoryContractsInformation.MethodsRsdContracts[calledMethodName].ContainsKey(rsdNames.CallRsdName) && _memoryContractsInformation.MethodsRsdContracts[calledMethodName][rsdNames.CallRsdName].ContainsKey(rsdType.Type)) { var contractLocalExpr = TranslateMethodContractToLocalExpression( methodReference, _currentStatement, _memoryContractsInformation.MethodsRsdContracts[calledMethodName][rsdNames.CallRsdName][rsdType.Type], arguments); var sumExprPolyCond = PolytopesCalculator.SumOver(contractLocalExpr, JoinLoopInvariants(_loopInvariants), GetMethodFreeVars(_currentMethod)); var sumPolyExpr = ExpressionGenerator.GenerateExpressionFromString(sumExprPolyCond.Poly, _host, _currentMethod); var sumCondExpr = ExpressionGenerator.GenerateExpressionFromString(sumExprPolyCond.Cond, _host, _currentMethod); if (sumPolyExpr != null && sumCondExpr != null) { //register the poly to be added to the rsd field after the loop _afterLoopAssignments.Add(new Tuple<FieldDefinition, PolyCond>(GetRsdField(_currentMethod, rsdNames.LocalRsdName, rsdType.Type), sumExprPolyCond)); doRegularInstrumentation = false; //store in the global poly info _currentInstrInfo.GlobalPolyInfoRsd[typeAndName].QuantityTransferLoops.Add(sumExprPolyCond); } } } if (doRegularInstrumentation) { //register the transference statement to be added later --> local_rsd += called_class.rsd; if (_loopNestLevel > 0) { _currentInstrInfo.GlobalPolyInfoRsd[typeAndName].AllContractsRequiredAvailable = false; } else if (_memoryContractsInformation.MethodsRsdContracts.ContainsKey(calledMethodName) && _memoryContractsInformation.MethodsRsdContracts[calledMethodName].ContainsKey(rsdNames.CallRsdName) && _memoryContractsInformation.MethodsRsdContracts[calledMethodName][rsdNames.CallRsdName].ContainsKey(rsdType.Type)) { var contractLocalExpr = TranslateMethodContractToLocalExpression( methodReference, _currentStatement, _memoryContractsInformation.MethodsRsdContracts[calledMethodName][rsdNames.CallRsdName][rsdType.Type], arguments); _currentInstrInfo.GlobalPolyInfoRsd[typeAndName].QuantityTransfer.Add(contractLocalExpr); } _currentInstrInfo.StatementsRsdTransference.Add( new StatementRsdTransferenceInformation() { AfterStatement = _currentStatement, AddSource = GetRsdField(methodReference.ResolvedMethod, rsdNames.CallRsdName, rsdType.Type), AddTarget = GetRsdField(_currentMethod, rsdNames.LocalRsdName, rsdType.Type) }); } } } } } } //verify the correctness foreach (var rsdName in _currentInstrInfo.AddToRsdRsdSources) { //if not trust if (!rsdName.Trust) { var rsdNameCall = rsdName.CallRsdName; var localExpr = ""; if (rsdNameCall == "Contracts.Contract.Memory.Return") { localExpr = GetReturnExprFromStatement(_currentStatement); } else if (rsdNameCall == "Contracts.Contract.Memory.This") { localExpr = GetCallStatementThisExpr(methodReference, _currentStatement); } else if (_memoryContractsInformation.MethodsRsdExprs.ContainsKey(methodReference.ResolvedMethod.ToString()) && _memoryContractsInformation.MethodsRsdExprs[methodReference.ResolvedMethod.ToString()].ContainsKey(rsdNameCall)) { var calledMethodExpr = _memoryContractsInformation.MethodsRsdExprs[methodReference.ResolvedMethod.ToString()][rsdNameCall]; localExpr = GetBoundRsdExprFromStatement(methodReference, _currentStatement, calledMethodExpr, arguments); } if (localExpr != "") { if (!_pointsToInformation.Escapes(_currentMethod.ContainingType.ToString(), _currentMethod.Name.Value, localExpr)) { string location = LocationsToString(rsdName.Statement.Locations); if (location != null) { _errorReportItems.Add(new ErrorReportItem() { Message = "The called method rsd destination doesn't escape from the method.", Location = location }); } } else { //verify that it effectively escapes through the expression given in BindRsd var localRsdName = rsdName.LocalRsdName; var localRsdExpr = ""; if (localRsdName == "Contracts.Contract.Memory.Return") { localRsdExpr = "vRet"; } else if (localRsdName == "Contracts.Contract.Memory.This") { localRsdExpr = "this"; } else if (_memoryContractsInformation.MethodsRsdExprs.ContainsKey(_currentMethod.ToString()) && _memoryContractsInformation.MethodsRsdExprs[_currentMethod.ToString()].ContainsKey(localRsdName)) { localRsdExpr = _memoryContractsInformation.MethodsRsdExprs[_currentMethod.ToString()][localRsdName]; } if (!_pointsToInformation.Escapes(_currentMethod.ContainingType.ToString(), _currentMethod.Name.Value, localExpr, localRsdExpr)) { string location = LocationsToString(rsdName.Statement.Locations); if (location != null) { _errorReportItems.Add(new ErrorReportItem() { Message = string.Format("The called method rsd destination escapes from the method but not through the expression '{0}'.", localRsdExpr), Location = location }); } } } } } } //clean the list for the next call _currentInstrInfo.AddToRsdRsdSources = new List<RsdNames>(); } } }