private bool CheckModifiersOnParametersAndReturnValue(IDifferences differences, IMethodDefinition implMethod, IMethodDefinition contractMethod) { int paramCount = implMethod.ParameterCount; Contract.Assert(paramCount == contractMethod.ParameterCount); if (paramCount == 0) { return(true); } IParameterDefinition[] implParams = implMethod.Parameters.ToArray(); IParameterDefinition[] contractParams = contractMethod.Parameters.ToArray(); bool match = true; for (int i = 0; i < paramCount; i++) { IParameterDefinition implParam = implParams[i]; IParameterDefinition contractParam = contractParams[i]; //TODO: Do we care about the compatibility with marshalling attributes Out\In? They don't seem to be set consistently. if (GetModifier(implParam) != GetModifier(contractParam)) { differences.AddIncompatibleDifference(this, "Modifiers on parameter '{0}' on method '{1}' are '{2}' in the implementation but '{3}' in the contract.", implParam.Name.Value, implMethod.FullName(), GetModifier(implParam), GetModifier(contractParam)); match = false; } // Now check custom modifiers, primarily focused on const & volatile if (implParam.IsModified || contractParam.IsModified) { var union = implParam.CustomModifiers.Union(contractParam.CustomModifiers); if (implParam.CustomModifiers.Count() != union.Count()) { differences.AddIncompatibleDifference(this, "Custom modifiers on parameter '{0}' on method '{1}' are '{2}' in the implementation but '{3}' in the contract.", implParam.Name.Value, implMethod.FullName(), PrintCustomModifiers(implParam.CustomModifiers), PrintCustomModifiers(contractParam.CustomModifiers)); match = false; } } } string implReturnModifier = GetReturnValueModifier(implMethod); string contractReturnModifier = GetReturnValueModifier(contractMethod); if (implReturnModifier != contractReturnModifier) { differences.AddIncompatibleDifference(this, "Modifiers on return type of method '{0}' are '{1}' in the implementation but '{2}' in the contract.", implMethod.FullName(), implReturnModifier, contractReturnModifier); match = false; } return(match); }
/// <summary> /// Main method for performing Scope analysis on a method. /// </summary> /// <param name="methodDefinition"></param> public override void TraverseChildren(IMethodDefinition methodDefinition) { // We analyze only (interesting) processor methods. if (IsInterestingProcessor(methodDefinition)) { Utils.WriteLine("\n--------------------------------------------------"); Utils.WriteLine("Found interesting method " + methodDefinition.FullName()); // Create CFG and run basic analyses, such as copy-propagation. var methodResult = AnalyzeMethod(methodDefinition); Utils.WriteLine("Method has useful result: " + (!methodResult.UsedColumnsSummary.IsBottom && !methodResult.UsedColumnsSummary.IsTop)); Utils.WriteLine("Method has unsupported features: " + methodResult.Unsupported); Utils.WriteLine("\n--------------------------------------------------"); results.Add(methodResult); } else { var methodResult = new ScopeMethodAnalysisResult(methodDefinition, mhost); methodResult.Interesting = false; results.Add(methodResult); } return; }
private bool ParamNamesMatch(IDifferences differences, IMethodDefinition implMethod, IMethodDefinition contractMethod) { int paramCount = implMethod.ParameterCount; Contract.Assert(paramCount == contractMethod.ParameterCount); IParameterDefinition[] implParams = implMethod.Parameters.ToArray(); IParameterDefinition[] contractParams = contractMethod.Parameters.ToArray(); bool match = true; for (int i = 0; i < paramCount; i++) { IParameterDefinition implParam = implParams[i]; IParameterDefinition contractParam = contractParams[i]; if (!implParam.Name.Value.Equals(contractParam.Name.Value)) { differences.AddIncompatibleDifference(this, "Parameter name on member '{0}' is '{1}' in the implementation but '{2}' in the contract.", implMethod.FullName(), implParam.Name.Value, contractParam.Name.Value); match = false; } } return match; }
private bool ParamNamesMatch(IDifferences differences, IMethodDefinition implMethod, IMethodDefinition contractMethod) { int paramCount = implMethod.ParameterCount; Contract.Assert(paramCount == contractMethod.ParameterCount); IParameterDefinition[] implParams = implMethod.Parameters.ToArray(); IParameterDefinition[] contractParams = contractMethod.Parameters.ToArray(); bool match = true; for (int i = 0; i < paramCount; i++) { IParameterDefinition implParam = implParams[i]; IParameterDefinition contractParam = contractParams[i]; if (!implParam.Name.Value.Equals(contractParam.Name.Value)) { differences.AddIncompatibleDifference(this, "Parameter name on member '{0}' is '{1}' in the implementation but '{2}' in the contract.", implMethod.FullName(), implParam.Name.Value, contractParam.Name.Value); match = false; } } return(match); }
private bool ParamModifiersMatch(IDifferences differences, IMethodDefinition implMethod, IMethodDefinition contractMethod) { int paramCount = implMethod.ParameterCount; Contract.Assert(paramCount == contractMethod.ParameterCount); if (paramCount == 0) return true; IParameterDefinition[] implParams = implMethod.Parameters.ToArray(); IParameterDefinition[] contractParams = contractMethod.Parameters.ToArray(); bool match = true; for (int i = 0; i < paramCount; i++) { IParameterDefinition implParam = implParams[i]; IParameterDefinition contractParam = contractParams[i]; //TODO: Do we care about the compatibility with marshalling attributes Out\In? They don't seem to be set consistently. if (GetModifier(implParam) != GetModifier(contractParam)) { differences.AddIncompatibleDifference(this, "Modifiers on parameter '{0}' on method '{1}' are '{2}' in the implementation but '{3}' in the contract.", implParam.Name.Value, implMethod.FullName(), GetModifier(implParam), GetModifier(contractParam)); match = false; } // Now check custom modifiers, primarily focused on const & volatile if (implParam.IsModified || contractParam.IsModified) { var union = implParam.CustomModifiers.Union(contractParam.CustomModifiers); if (implParam.CustomModifiers.Count() != union.Count()) { differences.AddIncompatibleDifference(this, "Custom modifiers on parameter '{0}' on method '{1}' are '{2}' in the implementation but '{3}' in the contract.", implParam.Name.Value, implMethod.FullName(), PrintCustomModifiers(implParam.CustomModifiers), PrintCustomModifiers(contractParam.CustomModifiers)); match = false; } } } return match; }
private void LoadSavedMethods(IMetadataHost host, string methodsFN, IDictionary <string, ITypeDefinition> classNameToTypeMap, IDictionary <string, IMethodDefinition> methodNameToMethodMap) { using (StreamReader sr = new StreamReader(methodsFN)) { string line; while ((line = sr.ReadLine()) != null) { line = line.Trim(); int ndxOfClass = line.IndexOf(" CLASS:"); string className = line.Substring(ndxOfClass).Split(':')[1]; string methAndArgs = line.Substring(0, ndxOfClass); int ndxOfArgs = methAndArgs.IndexOf(" ARGS:"); string methName = methAndArgs.Substring(0, ndxOfArgs).Split(':')[1]; string args = methAndArgs.Substring(ndxOfArgs + 6); if (!classNameToTypeMap.ContainsKey(className)) { System.Console.WriteLine("WARNING: LoadSavedMethods: Skipping method {0}", methName); continue; } ITypeDefinition cl = classNameToTypeMap[className]; IMethodDefinition methDefn = Utils.GetMethodByFullName(cl, methName); if (methDefn == null) { System.Console.WriteLine("WARNING: LoadSavedMethods: Skipping method {0}", methName); continue; } if (methDefn.IsGeneric && args.Length > 0) { IList <ITypeReference> genArgs = getArgsList(args, classNameToTypeMap); if (genArgs != null) { GenericMethodInstance newInstMeth = new GenericMethodInstance(methDefn, genArgs, host.InternFactory); methDefn = newInstMeth; } else { methDefn = null; } } if (methDefn != null) { methodNameToMethodMap[methDefn.FullName()] = methDefn; methods.Add(methDefn); } } } }
public static bool MatchesSuppressM(IMethodDefinition m) { string mSign = m.FullName(); bool matches = false; foreach (string s in prefixesToSuppressMeth) { if (mSign.StartsWith(s)) { matches = true; break; } } return(matches); }
public InstructionWrapper(Instruction inst, IMethodDefinition meth) { instStr = inst.ToString(); methodName = meth.FullName(); className = meth.ContainingTypeDefinition.FullName(); if (inst.Location != null) { srcLine = inst.Location.StartLine; srcFile = inst.Location.PrimarySourceDocument.Location; } else { srcLine = -1; srcFile = "NA"; } }
/// <summary> /// Check if a method is a processor (reducer) method. Also, include the check /// for method being declared interesting by the class user. /// </summary> /// <param name="method"></param> /// <returns></returns> private bool IsInterestingProcessor(IMethodDefinition method) { // Containing type of a method needs to be a non-anonymous reference type. if (!(method.ContainingType is INamedTypeReference)) { return(false); } var mtype = method.ContainingType as INamedTypeReference; if (mtype.IsEnum || mtype.IsValueType) { return(false); } // Its definition must be available. var rmtype = mtype.Resolve(mhost); // Method needs to be contained in nested Reducer or Processor subclass. if (!(rmtype is INestedTypeDefinition)) { return(false); } var type = (rmtype as INestedTypeDefinition).ContainingTypeDefinition.Resolve(mhost); //TODO: push this check up later. Here currently to test CCI types for robustness. if (interestingProcessors != null && !interestingProcessors.Contains(type.FullName())) { return(false); } // We are interested in processors, reducers, and combiners. if (!type.SubtypeOf(reducerType, mhost) && !type.SubtypeOf(processorType, mhost) && !type.SubtypeOf(combinerType, mhost)) { return(false); } // We are currently focusing on MoveNext methods only. if (!method.FullName().EndsWith(".MoveNext()")) { return(false); } return(true); }
private ScopeMethodAnalysisResult AnalyzeMethod(IMethodDefinition methodDefinition) { var methodResult = new ScopeMethodAnalysisResult(methodDefinition, mhost); try { var cfg = PrepareMethod(methodDefinition); Utils.WriteLine("CFG size " + cfg.Nodes.Count); // Run escape analysis. var escAnalysis = DoEscapeAnalysis(cfg, methodDefinition, methodResult); methodResult.Unsupported = escAnalysis.Unsupported; // If some row has escaped or the method has unsupported features, // there is no need to analyze the method any further. if (escAnalysis.InterestingRowEscaped || escAnalysis.Unsupported) { if (escAnalysis.InterestingRowEscaped && !escAnalysis.Unsupported) { Utils.WriteLine("A rowish data structure has escaped, no dependency information available."); } methodResult.UsedColumnsSummary = ColumnsDomain.Top; } else { // Otherwise, do constant-set propagation (CSP) analysis. var cspAnalysis = DoConstantPropagationAnalysis(cfg, methodDefinition, methodResult); var cspInfo = new NaiveScopeConstantsProvider(cspAnalysis.PreResults, mhost); //Finally, do the actual used-columns analysis using results of the previous CSP analysis. var clsAnalysis = DoUsedColumnsAnalysis(cfg, cspInfo, methodResult); methodResult.Unsupported = cspAnalysis.Unsupported | clsAnalysis.Unsupported; } } catch (Exception e) { Utils.WriteLine(String.Format("{0} METHOD FAILURE: {1}", methodDefinition.FullName(), e.Message)); Utils.WriteLine(e.StackTrace); methodResult.Failed = true; } return(methodResult); }
public void Traverse(IMethodDefinition methodDefinition) { ControlFlowGraph cfg; MethodBody methodBody; IList <CatchExceptionHandler> ehInfoList; if (methodToCfgAndTacMap.ContainsKey(methodDefinition)) { MethodCfgAndTac mct = methodToCfgAndTacMap[methodDefinition]; if (mct == null) { return; } cfg = mct.cfg; methodBody = mct.methodBody; ehInfoList = mct.ehInfoList; } else { MethodCfgAndTac mct = AnalyzeIntraProcedural(methodDefinition); methodToCfgAndTacMap[methodDefinition] = mct; if (mct == null) { return; } cfg = mct.cfg; methodBody = mct.methodBody; ehInfoList = mct.ehInfoList; } if (rtaAnalyzer != null) { if (rtaAnalyzer.entryPtClasses.Contains(methodDefinition.ContainingTypeDefinition)) { if (rtaAnalyzer.rootIsExe) { // Add only the Main method as entry point if (Utils.IsMainMethod(methodDefinition)) { rtaAnalyzer.rtaLogSW.WriteLine("Adding main method: {0}", methodDefinition.FullName()); IMethodDefinition addedMeth = Stubber.CheckAndAdd(methodDefinition); // The assumption is that addedMeth is not a template method. Here it is safe because it holds for the main method. if (addedMeth != null) { rtaAnalyzer.entryPtMethods.Add(addedMeth); } } } else { if (methodDefinition.Visibility == TypeMemberVisibility.Public || methodDefinition.Visibility == TypeMemberVisibility.Family) { // Otherwise, add all public methods as entry points IMethodDefinition addedMeth = Stubber.CheckAndAdd(methodDefinition); rtaAnalyzer.rtaLogSW.WriteLine("Adding method: {0}", methodDefinition.FullName()); // The assumption here is that addedMeth is not a template method. // TODO: It may be the case that this assumption does not hold in some cases. if (addedMeth != null) { rtaAnalyzer.entryPtMethods.Add(addedMeth); } } } } if (rtaAnalyzer.methods.Contains(methodDefinition) && !rtaAnalyzer.visitedMethods.Contains(methodDefinition)) { rtaAnalyzer.visitedMethods.Add(methodDefinition); // rtaAnalyzer.rtaLogSW.WriteLine("SRK_DBG: Visiting method: {0}", methodDefinition.GetName()); rtaAnalyzer.VisitMethod(methodBody, cfg); } else { rtaAnalyzer.ignoredMethods.Add(methodDefinition); } } else if (factGen != null) { if (factGen.methods.Contains(methodDefinition)) { factGen.GenerateFacts(methodBody, cfg, ehInfoList); } } }
/// <summary> /// Main method for performing Scope analysis on a method. /// </summary> /// <param name="methodDefinition"></param> public override void TraverseChildren(IMethodDefinition methodDefinition) { //if (!methodDefinition.FullName().Contains("MMRV2.IndexSelection.DPGenDomainKeyProcessor")) // return; //if (!methodDefinition.FullName().Contains("ScopeML.Prediction.CompactModelBuilderReducer") || !methodDefinition.FullName().Contains("MoveNext")) // return; var methodResult = new ScopeMethodAnalysisResult(methodDefinition, mhost); try { // We analyze only (interesting) processor methods. if (IsInterestingProcessor(methodDefinition)) { Utils.WriteLine("\n--------------------------------------------------\n"); Utils.WriteLine("Found interesting method " + methodDefinition.FullName()); // Create CFG and run basic analyses, such as copy-propagation. var cfg = PrepareMethod(methodDefinition); Utils.WriteLine("CFG size " + cfg.Nodes.Count); //System.IO.File.WriteAllText(@"mbody-zvonimir.txt", _code); // Run escape analysis. var escAnalysis = DoEscapeAnalysis(cfg, methodDefinition, methodResult); methodResult.Unsupported = escAnalysis.Unsupported; // If some row has escaped or the method has unsupported features, // there is no need to analyze the method any further. if (escAnalysis.InterestingRowEscaped || escAnalysis.Unsupported) { if (escAnalysis.InterestingRowEscaped && !escAnalysis.Unsupported) { Utils.WriteLine("A rowish data structure has escaped, no dependency information available."); } methodResult.UsedColumnsSummary = ColumnsDomain.Top; } else { // Otherwise, do constant-set propagation (CSP) analysis. var cspAnalysis = DoConstantPropagationAnalysis(cfg, methodDefinition, methodResult); var cspInfo = new NaiveScopeConstantsProvider(cspAnalysis.PreResults, mhost); //Finally, do the actual used-columns analysis using results of the previous CSP analysis. var clsAnalysis = DoUsedColumnsAnalysis(cfg, cspInfo, methodResult); methodResult.Unsupported = cspAnalysis.Unsupported | clsAnalysis.Unsupported; } Utils.WriteLine("Method has useful result: " + (!methodResult.UsedColumnsSummary.IsBottom && !methodResult.UsedColumnsSummary.IsTop)); Utils.WriteLine("Method has unsupported features: " + methodResult.Unsupported); Utils.WriteLine("\n--------------------------------------------------\n"); } else { methodResult.Interesting = false; } } catch (Exception e) { Utils.WriteLine(String.Format("{0} METHOD FAILURE: {1}", methodDefinition.FullName(), e.Message)); Utils.WriteLine(e.StackTrace); methodResult.Failed = true; } results.Add(methodResult); return; }
public void SaveScope(IMetadataHost host) { string modulesFN = "modules.txt"; StreamWriter modulesSW = new StreamWriter(Path.Combine(ConfigParams.SaveScopePath, modulesFN)); List <IModule> moduleList = host.LoadedUnits.OfType <IModule>().ToList(); TypeDefinitionComparer tdc = new TypeDefinitionComparer(); ISet <ITypeDefinition> processedTypes = new HashSet <ITypeDefinition>(tdc); foreach (IModule module in moduleList) { if (module == null || module == Dummy.Module || module == Dummy.Assembly) { System.Console.WriteLine("WARNING: SaveScope - modules: Dummy or null module - skipping."); continue; } modulesSW.WriteLine("MODULE:" + module.Name.Value + " LOCATION:" + module.Location); } modulesSW.Close(); string classesFN = "classes.txt"; StreamWriter classesSW = new StreamWriter(Path.Combine(ConfigParams.SaveScopePath, classesFN)); foreach (ITypeDefinition cl in classes) { if (processedTypes.Contains(cl)) { continue; } IModule mod = TypeHelper.GetDefiningUnit(cl) as IModule; if (cl is IGenericTypeInstance) { ProcessGenericType(cl, classesSW, mod, processedTypes); } else { classesSW.WriteLine("CLASS:" + cl.FullName() + " ARGS: MODULE:" + mod.Name.Value); processedTypes.Add(cl); } } classesSW.Close(); string entClassesFN = "entrypt_classes.txt"; StreamWriter entClassesSW = new StreamWriter(Path.Combine(ConfigParams.SaveScopePath, entClassesFN)); foreach (ITypeDefinition cl in entryPtClasses) { IModule mod = TypeHelper.GetDefiningUnit(cl) as IModule; entClassesSW.WriteLine("CLASS:" + cl.FullName() + " ARGS: MODULE:" + mod.Name.Value); } entClassesSW.Close(); string methodsFN = "methods.txt"; StreamWriter methodsSW = new StreamWriter(Path.Combine(ConfigParams.SaveScopePath, methodsFN)); foreach (IMethodDefinition meth in methods) { string argStr = ""; IMethodDefinition methToRecord = meth; if (meth is IGenericMethodInstance) { IGenericMethodInstance genericM = meth as IGenericMethodInstance; IEnumerable <ITypeReference> genericArgs = genericM.GenericArguments; foreach (ITypeReference ty in genericArgs) { ITypeDefinition tyDefn = ty.ResolvedType; argStr += tyDefn.FullName() + ";"; } if (!argStr.Equals("")) { argStr = argStr.TrimEnd(';'); } methToRecord = genericM.GenericMethod.ResolvedMethod; } methodsSW.WriteLine("METHOD:" + methToRecord.FullName() + " ARGS:" + argStr + " CLASS:" + methToRecord.ContainingTypeDefinition.FullName()); } methodsSW.Close(); }