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);
        }
Пример #2
0
        /// <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;
        }
Пример #4
0
        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;
        }
Пример #6
0
        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);
                    }
                }
            }
        }
Пример #7
0
        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);
        }
Пример #8
0
 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";
     }
 }
Пример #9
0
        /// <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);
        }
Пример #10
0
        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);
        }
Пример #11
0
        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);
                }
            }
        }
Пример #12
0
        /// <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;
        }
Пример #13
0
        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();
        }