/// <summary>
        /// Merges two instances based on the stronger of both variabilities and the set union of their reaching definitions
        /// </summary>
        /// <param name="a">first instance</param>
        /// <param name="b">second instance</param>
        /// <returns>instance representing the merged information of both instances</returns>
        public static VariabilityInfo MergeDefs(VariabilityInfo a, VariabilityInfo b)
        {
            Contract.Requires(a.Definitions != null);
            Contract.Requires(b.Definitions != null);

            return(new VariabilityInfo(
                       VariabilityOperations.Stronger(a.Variability, b.Variability),
                       a.Definitions.Union(b.Definitions).Distinct().ToArray()));
        }
        private AbstractStackState <VariabilityInfo> HandleBinBranch(ILInstruction ili, AbstractStackState <VariabilityInfo> pre)
        {
            VariabilityInfo a    = pre[0];
            VariabilityInfo b    = pre[1];
            var             next = pre.Pop().Pop();

            if (VariabilityOperations.Stronger(a.Variability, b.Variability) == EVariability.Constant)
            {
                next = next.UniqueSuccessor();
            }
            else
            {
                next = next.AmbiguousSuccessor();
            }
            return(next);
        }
        private AbstractStackState <VariabilityInfo> HandleCall(ILInstruction ili, AbstractStackState <VariabilityInfo> pre, bool isCalli)
        {
            MethodBase   callee  = (MethodBase)ili.Operand;
            bool         hasThis = callee.CallingConvention.HasFlag(CallingConventions.HasThis);
            EVariability callVar = EVariability.Constant;

            ParameterInfo[] args        = callee.GetParameters();
            MethodFacts     myFacts     = FactUniverse.Instance.GetFacts(Method);
            MethodFacts     calleeFacts = FactUniverse.Instance.GetFacts(callee);
            AbstractStackState <VariabilityInfo> next = pre;

            if (hasThis)
            {
                callVar = VariabilityOperations.Stronger(callVar, pre[0].Variability);
                next    = pre.Pop();
            }
            for (int i = 0; i < args.Length; i++)
            {
                callVar = VariabilityOperations.Stronger(callVar, next[0].Variability);
                next    = next.Pop();
            }
            if (!calleeFacts.IsSideEffectFree)
            {
                callVar = EVariability.ExternVariable;
            }
            if (calleeFacts.IsStaticEvaluation)
            {
                callVar = EVariability.Constant;
            }
            if (isCalli)
            {
                next = pre.Pop();
            }
            VariabilityInfo callVarI = VariabilityInfo.CreateBySingleDef(callVar, ili.Index);

            next = UpdateStackState(ili, callVarI, next);
            Type returnType;

            if (callee.IsFunction(out returnType))
            {
                next = next.Push(callVarI);
            }
            return(next.UniqueSuccessor());
        }
 /// <summary>
 /// Merges two instances under assumption of a single reaching definition
 /// </summary>
 /// <param name="a">first instance</param>
 /// <param name="b">second instance</param>
 /// <param name="def">the one and only reaching definition</param>
 /// <returns>merged instance, based on the stronger of both variabilities</returns>
 public static VariabilityInfo MergeByNewDef(VariabilityInfo a, VariabilityInfo b, int def)
 {
     return(CreateBySingleDef(
                VariabilityOperations.Stronger(a.Variability, b.Variability),
                def));
 }