private static void InterpretCallAny(ReachabilitySummary summary, TypeSpecifier typeSpecifier, WholeProgram wholeProgram)
        {
            if (summary != null)
            {
                foreach (ITypeDefinition type in LookupTypesWithSpecifier(typeSpecifier, wholeProgram))
                {
                    // Note, for now this only looks at methods directly defined on that type
                    // not on any methods defined on super types (and inherited).
                    // This is probably not what we really want to expose to the user.
                    foreach (IMethodDefinition method in type.Methods)
                    {
                        if (!method.IsAbstract)
                        {
                            summary.NonvirtuallyCalledMethods.Add(method);

                            // If there is a constructor, we treat the type as constructed
                            if (method.IsConstructor && GarbageCollectHelper.TypeIsConstructable(type))
                            {
                                summary.ConstructedTypes.Add(type);
                            }
                        }
                    }
                }
            }
            else
            {
                throw new Exception("Cannot call any outside of a summarized method.");
            }
        }
        private static void InterpretConstruct(ReachabilitySummary summary, TypeSpecifier typeSpecifier, WholeProgram wholeProgram)
        {
            if (summary != null)
            {
                foreach (ITypeDefinition typeToConstruct in LookupTypesWithSpecifier(typeSpecifier, wholeProgram))
                {
                    if (GarbageCollectHelper.TypeIsConstructable(typeToConstruct))
                    {
                        summary.ConstructedTypes.Add(typeToConstruct);

                        // now we mark ALL the non-private constructors as reachable. This is perhaps too imprecise
                        // an alternative would be to allow the user to specify the constructor signature.
                        MarkNonPrivateConstructorsReachableForType(summary, typeToConstruct);
                    }
                }
            }
            else
            {
                throw new Exception("Cannot construct type outside of a summarized method.");
            }
        }
        public ReachabilitySummary SummarizeMethod(IMethodDefinition method, WholeProgram wholeProgram)
        {
            if (method.IsExternal == false && method.IsAbstract == false)
            {
                ReachabilitySummary summary = new ReachabilitySummary();
                IMethodDefinition   target;


                // foreach MSIL instruction in the method
                foreach (var op in method.Body.Operations)
                {
                    switch (op.OperationCode)
                    {
                    // non virtual method calls: just add static type
                    case OperationCode.Newobj:
                    case OperationCode.Call:
                    case OperationCode.Calli:
                        target = (op.Value as IMethodReference).ResolvedMethod;
                        summary.NonvirtuallyCalledMethods.Add(target);
                        break;

                    case OperationCode.Ldvirtftn:
                    case OperationCode.Callvirt:
                        target = (op.Value as IMethodReference).ResolvedMethod;

                        if (target.IsVirtual == false)
                        {
                            summary.NonvirtuallyCalledMethods.Add(target);
                        }
                        else
                        {
                            ITypeDefinition   typeDefiningTarget  = target.ContainingTypeDefinition;
                            IMethodDefinition targetUnspecialized = GarbageCollectHelper.UnspecializeAndResolveMethodReference(op.Value as IMethodReference);

                            // find all possible implementations of virtual call
                            foreach (ITypeDefinition subType in new ITypeDefinition[] { typeDefiningTarget }.Concat(wholeProgram.ClassHierarchy().AllSubClassesOfClass(typeDefiningTarget)))
                            {
                                if (GarbageCollectHelper.TypeIsConstructable(subType))
                                {
                                    // walk class hierarchy from subType up to (including) typeDefiningTarget, looking for targetUnspecialized.
                                    ICollection <IMethodDefinition> implementationsOfMethodDefinitionForSubType = GarbageCollectHelper.Implements(subType, typeDefiningTarget, targetUnspecialized);

                                    // we have to have found at least 1 implementation
                                    Contract.Assert(implementationsOfMethodDefinitionForSubType.Count() > 0);

                                    // add all of them as virtually called methods
                                    foreach (IMethodDefinition implementationOfTarget in implementationsOfMethodDefinitionForSubType)
                                    {
                                        summary.VirtuallyCalledMethods.Add(implementationOfTarget);
                                    }
                                }
                            }
                        }
                        break;

                    default:
                        break;
                    }
                }

                return(summary);
            }
            else
            {
                return(null);
            }
        }
            internal virtual void Visit(IOperation op)
            {
                IMethodDefinition target;

                switch (op.OperationCode)
                {
                case OperationCode.Newobj:
                    target = ResolveMethodReference(op.Value as IMethodReference);

                    if (target != null)
                    {
                        Contract.Assert(!(target is Dummy));

                        if (target.ContainingType is INamedTypeReference)
                        {
                            //Console.WriteLine("Got newobj to {0}", ((INamedTypeReference)target.ContainingType).Name);
                        }

                        ITypeDefinition constructedType = target.ContainingType.ResolvedType;
                        Contract.Assert(GarbageCollectHelper.TypeIsConstructable(constructedType));

                        summary.ReachableTypes.Add(constructedType);
                        summary.ConstructedTypes.Add(constructedType);
                        summary.NonvirtuallyCalledMethods.Add(target);
                    }
                    break;

                case OperationCode.Box:
                    // Boxing a struct means a callvirt could possibly
                    // dispatch to one of its methods.

                    ITypeDefinition boxedType = ResolveTypeReference(op.Value as ITypeReference);

                    if (boxedType != null)
                    {
                        // Guard for structs here because box to a reference type is a no-op but allowed and
                        // the Code Contracts instrumentation does this.
                        if (boxedType.IsStruct)
                        {
                            Contract.Assert(GarbageCollectHelper.TypeIsConstructable(boxedType));
                            summary.ConstructedTypes.Add(boxedType);
                        }
                    }
                    break;


                case OperationCode.Ldtoken:
                    if (op.Value is IFieldReference)
                    {
                        IFieldDefinition field = ResolveFieldReference(op.Value as IFieldReference);

                        if (field != null)
                        {
                            summary.ReachableFields.Add(field);
                        }
                    }

                    // t-devinc: Need to handle: method and type tokens, as well as generics.
                    // Fully supporting generics here may be very tricky -- this is a place
                    // where operating over specialized bytecode could perhaps help.
                    break;

                /* Notes on call/callvirt:
                 *
                 * We can get a call on a virtual method when that method is called via 'base'
                 * We can also get a callvirt on a non-virtual method whenever the compiler
                 * feels like it? This seems a little wonky.
                 */
                case OperationCode.Ldftn:
                case OperationCode.Call:
                    target = ResolveMethodReference(op.Value as IMethodReference);

                    if (target != null)
                    {
                        if (target.ContainingType is INamedTypeReference)
                        {
                            //Console.WriteLine("Got call to {0}", target);
                        }

                        summary.NonvirtuallyCalledMethods.Add(target);

                        if (target.Name.Value == "CreateInstance")
                        {
                            // t-devinc: gross, clean this up

                            INamespaceTypeDefinition containingTypeDefinition = target.ContainingTypeDefinition as INamespaceTypeDefinition;
                            if (containingTypeDefinition != null && containingTypeDefinition.Name.Value == "Activator")
                            {
                                if (containingTypeDefinition.ContainingNamespace.Name.Value == "System")
                                {
                                    IGenericMethodInstance targetAsGenericMethodInstance = target as IGenericMethodInstance;

                                    if (targetAsGenericMethodInstance != null)
                                    {
                                        // We have a call to 'new T()';
                                        ITypeDefinition definitionForT = targetAsGenericMethodInstance.GenericArguments.First().ResolvedType;

                                        summary.ConstructedTypeParameters.Add((IGenericParameter)definitionForT);
                                    }
                                }
                            }
                        }
                    }
                    break;

                case OperationCode.Ldvirtftn:
                case OperationCode.Callvirt:

                    target = ResolveMethodReference(op.Value as IMethodReference);

                    if (target != null)
                    {
                        if (target.ContainingType is INamedTypeReference)
                        {
                            //Console.WriteLine("Got callvirt to {0}", target);
                        }

                        if (target.IsVirtual)
                        {
                            summary.VirtuallyCalledMethods.Add(target);
                        }
                        else
                        {
                            // In its infinite wisdom, sometimes the compiler gives us a callvirt on a non-virtual method

                            summary.NonvirtuallyCalledMethods.Add(target);
                        }
                    }
                    break;

                case OperationCode.Ldfld:
                case OperationCode.Ldflda:
                case OperationCode.Ldsfld:
                case OperationCode.Ldsflda:

                /* For now we treat loads and stores as the same -- we'll want to be smarter about this in the future */
                case OperationCode.Stfld:
                case OperationCode.Stsfld:
                    IFieldDefinition fieldDefinition = ResolveFieldReference(op.Value as IFieldReference);

                    if (fieldDefinition != null)
                    {
                        summary.ReachableTypes.Add(fieldDefinition.ContainingTypeDefinition);
                        summary.ReachableFields.Add(fieldDefinition);
                    }
                    break;

                default:
                    break;
                }
            }