Пример #1
0
        // node id, var, version
        //private HashMap<String, HashMap<Integer, FastSet<Integer>>> inVarVersions = new HashMap<String, HashMap<Integer, FastSet<Integer>>>();
        // node id, var, version (direct branch)
        //private HashMap<String, HashMap<Integer, FastSet<Integer>>> outVarVersions = new HashMap<String, HashMap<Integer, FastSet<Integer>>>();
        // node id, var, version (negative branch)
        //private HashMap<String, HashMap<Integer, FastSet<Integer>>> outNegVarVersions = new HashMap<String, HashMap<Integer, FastSet<Integer>>>();
        // node id, var, version
        //private HashMap<String, HashMap<Integer, FastSet<Integer>>> extraVarVersions = new HashMap<String, HashMap<Integer, FastSet<Integer>>>();
        // var, version
        // version, protected ranges (catch, finally)
        // version, version
        // ++ and --
        // node.id, version, version
        // finally exits
        // versions memory dependencies
        // field access vars (exprent id, var id)
        // field access counter
        // set factory
        public virtual void SplitVariables(RootStatement root, StructMethod mt)
        {
            FlattenStatementsHelper flatthelper = new FlattenStatementsHelper();
            DirectGraph             dgraph      = flatthelper.BuildDirectGraph(root);
            HashSet <int>           setInit     = new HashSet <int>();

            for (int i = 0; i < 64; i++)
            {
                setInit.Add(i);
            }
            factory = new FastSparseSetFactory <int>(setInit);
            Sharpen.Collections.Put(extraVarVersions, dgraph.first.id, CreateFirstMap(mt, root
                                                                                      ));
            SetCatchMaps(root, dgraph, flatthelper);
            //		try {
            //			DotExporter.toDotFile(dgraph, new File("c:\\Temp\\gr12_my.dot"));
            //		} catch(Exception ex) {ex.printStackTrace();}
            HashSet <string> updated = new HashSet <string>();

            do
            {
                //			System.out.println("~~~~~~~~~~~~~ \r\n"+root.toJava());
                SsaStatements(dgraph, updated, false);
            }while (!(updated.Count == 0));
            //			System.out.println("~~~~~~~~~~~~~ \r\n"+root.toJava());
            SsaStatements(dgraph, updated, true);
            ssuversions.InitDominators();
        }
Пример #2
0
        private SFormsFastMapDirect CreateFirstMap(StructMethod mt, RootStatement root)
        {
            bool             thisvar = !mt.HasModifier(ICodeConstants.Acc_Static);
            MethodDescriptor md      = MethodDescriptor.ParseDescriptor(mt.GetDescriptor());
            int paramcount           = [email protected] + (thisvar ? 1 : 0);
            int varindex             = 0;
            SFormsFastMapDirect map  = new SFormsFastMapDirect();

            for (int i = 0; i < paramcount; i++)
            {
                int version = GetNextFreeVersion(varindex, root);
                // == 1
                FastSparseSetFactory <int> .FastSparseSet <int> set = factory.SpawnEmptySet();
                set.Add(version);
                map.Put(varindex, set);
                ssuversions.CreateNode(new VarVersionPair(varindex, version));
                if (thisvar)
                {
                    if (i == 0)
                    {
                        varindex++;
                    }
                    else
                    {
                        varindex += md.@params[i - 1].stackSize;
                    }
                }
                else
                {
                    varindex += md.@params[i].stackSize;
                }
            }
            return(map);
        }
Пример #3
0
 private void SetCurrentVar(SFormsFastMapDirect varmap, int?var, int vers)
 {
     FastSparseSetFactory <int> .FastSparseSet <int> set = factory.SpawnEmptySet();
     set.Add(vers);
     if (var.HasValue)
     {
         varmap.Put(var.Value, set);
     }
 }
Пример #4
0
        // vers.size() == 0 means uninitialized variable, which is impossible
        private void CreateOrUpdatePhiNode(VarVersionPair phivar, FastSparseSetFactory <int> .FastSparseSet <int> vers, Statement stat)
        {
            FastSparseSetFactory <int> .FastSparseSet <int> versCopy = vers.GetCopy();
            HashSet <int> phiVers = new HashSet <int>();
            // take into account the corresponding mm/pp node if existing
            int ppvers = phantomppnodes.ContainsKey(phivar) ? phantomppnodes.GetOrNull(phivar
                                                                                       ).version : -1;
            // ssu graph
            VarVersionNode        phinode  = ssuversions.nodes.GetWithKey(phivar);
            List <VarVersionEdge> lstPreds = new List <VarVersionEdge>(phinode.preds);

            if (lstPreds.Count == 1)
            {
                // not yet a phi node
                VarVersionEdge edge = lstPreds[0];
                edge.source.RemoveSuccessor(edge);
                phinode.RemovePredecessor(edge);
            }
            else
            {
                foreach (VarVersionEdge edge in lstPreds)
                {
                    int verssrc = new Sharpen.EnumeratorAdapter <VarVersionEdge>(edge.source.preds.GetEnumerator()).Next().source.version;
                    if (!vers.Contains(verssrc) && verssrc != ppvers)
                    {
                        edge.source.RemoveSuccessor(edge);
                        phinode.RemovePredecessor(edge);
                    }
                    else
                    {
                        versCopy.Remove(verssrc);
                        phiVers.Add(verssrc);
                    }
                }
            }
            List <VarVersionNode> colnodes = new List <VarVersionNode>();
            List <VarVersionPair> colpaars = new List <VarVersionPair>();

            foreach (int ver in versCopy)
            {
                VarVersionNode prenode = ssuversions.nodes.GetWithKey(new VarVersionPair(phivar.var
                                                                                         , ver));
                int            tempver  = GetNextFreeVersion(phivar.var, stat);
                VarVersionNode tempnode = new VarVersionNode(phivar.var, tempver);
                colnodes.Add(tempnode);
                colpaars.Add(new VarVersionPair(phivar.var, tempver));
                VarVersionEdge edge = new VarVersionEdge(VarVersionEdge.Edge_General, prenode, tempnode
                                                         );
                prenode.AddSuccessor(edge);
                tempnode.AddPredecessor(edge);
                edge = new VarVersionEdge(VarVersionEdge.Edge_General, tempnode, phinode);
                tempnode.AddSuccessor(edge);
                phinode.AddPredecessor(edge);
                phiVers.Add(tempver);
            }
            ssuversions.AddNodes(colnodes, colpaars);
        }
Пример #5
0
        private static bool IsVersionToBeReplaced(VarVersionPair usedvar, Dictionary <int
                                                                                      , HashSet <VarVersionPair> > mapVars, SSAUConstructorSparseEx ssau, VarVersionPair
                                                  leftpaar)
        {
            VarVersionsGraph    ssuversions = ssau.GetSsuversions();
            SFormsFastMapDirect mapLiveVars = ssau.GetLiveVarVersionsMap(usedvar);

            if (mapLiveVars == null)
            {
                // dummy version, predecessor of a phi node
                return(false);
            }
            // compare protected ranges
            if (!InterpreterUtil.EqualObjects(ssau.GetMapVersionFirstRange().GetOrNullable(leftpaar
                                                                                           ), ssau.GetMapVersionFirstRange().GetOrNullable(usedvar)))
            {
                return(false);
            }
            foreach (KeyValuePair <int, HashSet <VarVersionPair> > ent in mapVars)
            {
                FastSparseSetFactory <int> .FastSparseSet <int> liveverset = mapLiveVars.Get(ent.Key);
                if (liveverset == null)
                {
                    return(false);
                }
                HashSet <VarVersionNode> domset = new HashSet <VarVersionNode>();
                foreach (VarVersionPair verpaar in ent.Value)
                {
                    domset.Add(ssuversions.nodes.GetWithKey(verpaar));
                }
                bool isdom = false;
                foreach (int livever in liveverset)
                {
                    VarVersionNode node = ssuversions.nodes.GetWithKey(new VarVersionPair(ent.Key, livever
                                                                                          ));
                    if (ssuversions.IsDominatorSet(node, domset))
                    {
                        isdom = true;
                        break;
                    }
                }
                if (!isdom)
                {
                    return(false);
                }
            }
            return(true);
        }
Пример #6
0
        private static void ReplaceSingleVar(Exprent parent, VarExprent var, Exprent dest
                                             , SSAUConstructorSparseEx ssau)
        {
            parent.ReplaceExprent(var, dest);
            // live sets
            SFormsFastMapDirect      livemap = ssau.GetLiveVarVersionsMap(new VarVersionPair(var));
            HashSet <VarVersionPair> setVars = GetAllVersions(dest);

            foreach (VarVersionPair varpaar in setVars)
            {
                VarVersionNode node      = ssau.GetSsuversions().nodes.GetWithKey(varpaar);
                var            toRemove  = new List <KeyValuePair <int, FastSparseSetFactory <int> .FastSparseSet <int> > >();
                var            entryList = node.live.EntryList();
                for (var index = 0; index < entryList.Count; index++)
                {
                    var itent = entryList[index];
                    KeyValuePair <int, FastSparseSetFactory <int> .FastSparseSet <int> > ent =
                        entryList.ElementAtOrDefault(index + 1);
                    if (ent.Value == null)
                    {
                        break;
                    }

                    int key = ent.Key;
                    if (!livemap.ContainsKey(key))
                    {
                        toRemove.Add(itent);
                    }
                    else
                    {
                        FastSparseSetFactory <int> .FastSparseSet <int> set = ent.Value;
                        set.Complement(livemap.Get(key));
                        if (set.IsEmpty())
                        {
                            toRemove.Add(itent);
                        }
                    }
                }

                foreach (var keyValuePair in toRemove)
                {
                    node.live.PutInternal(keyValuePair.Key, keyValuePair.Value, true);
                    // entryList.RemoveAll(c => c.Key == keyValuePair.Key);
                }
            }
        }
Пример #7
0
        private SFormsFastMapDirect GetFilteredOutMap(string nodeid, string predid, DirectGraph
                                                      dgraph, string destid)
        {
            SFormsFastMapDirect mapNew = new SFormsFastMapDirect();
            bool isFinallyExit         = dgraph.mapShortRangeFinallyPaths.ContainsKey(predid);

            if (nodeid.Equals(dgraph.mapNegIfBranch.GetOrNull(predid)))
            {
                if (outNegVarVersions.ContainsKey(predid))
                {
                    mapNew = outNegVarVersions.GetOrNull(predid).GetCopy();
                }
            }
            else if (outVarVersions.ContainsKey(predid))
            {
                mapNew = outVarVersions.GetOrNull(predid).GetCopy();
            }
            if (isFinallyExit)
            {
                SFormsFastMapDirect mapNewTemp    = mapNew.GetCopy();
                SFormsFastMapDirect mapTrueSource = new SFormsFastMapDirect();
                string exceptionDest = dgraph.mapFinallyMonitorExceptionPathExits.GetOrNull(predid
                                                                                            );
                bool isExceptionMonitorExit = (exceptionDest != null && !nodeid.Equals(exceptionDest
                                                                                       ));
                HashSet <string> setLongPathWrapper = new HashSet <string>();
                foreach (List <FlattenStatementsHelper.FinallyPathWrapper> lstwrapper in dgraph.mapLongRangeFinallyPaths
                         .Values)
                {
                    foreach (FlattenStatementsHelper.FinallyPathWrapper finwraplong in lstwrapper)
                    {
                        setLongPathWrapper.Add(finwraplong.destination + "##" + finwraplong.source);
                    }
                }
                foreach (FlattenStatementsHelper.FinallyPathWrapper finwrap in dgraph.mapShortRangeFinallyPaths
                         .GetOrNull(predid))
                {
                    SFormsFastMapDirect map;
                    bool recFinally = dgraph.mapShortRangeFinallyPaths.ContainsKey(finwrap.source);
                    if (recFinally)
                    {
                        // recursion
                        map = GetFilteredOutMap(finwrap.entry, finwrap.source, dgraph, destid);
                    }
                    else if (finwrap.entry.Equals(dgraph.mapNegIfBranch.GetOrNull(finwrap.source)))
                    {
                        map = outNegVarVersions.GetOrNull(finwrap.source);
                    }
                    else
                    {
                        map = outVarVersions.GetOrNull(finwrap.source);
                    }
                    // false path?
                    bool isFalsePath;
                    if (recFinally)
                    {
                        isFalsePath = !finwrap.destination.Equals(nodeid);
                    }
                    else
                    {
                        isFalsePath = !setLongPathWrapper.Contains(destid + "##" + finwrap.source);
                    }
                    if (isFalsePath)
                    {
                        mapNewTemp.Complement(map);
                    }
                    else if (mapTrueSource.IsEmpty())
                    {
                        if (map != null)
                        {
                            mapTrueSource = map.GetCopy();
                        }
                    }
                    else
                    {
                        MergeMaps(mapTrueSource, map);
                    }
                }
                if (isExceptionMonitorExit)
                {
                    mapNew = mapTrueSource;
                }
                else
                {
                    mapNewTemp.Union(mapTrueSource);
                    mapNew.Intersection(mapNewTemp);
                    if (!mapTrueSource.IsEmpty() && !mapNew.IsEmpty())
                    {
                        // FIXME: what for??
                        // replace phi versions with corresponding phantom ones
                        Dictionary <VarVersionPair, VarVersionPair> mapPhantom = phantomexitnodes.GetOrNull
                                                                                     (predid);
                        if (mapPhantom == null)
                        {
                            mapPhantom = new Dictionary <VarVersionPair, VarVersionPair>();
                        }
                        SFormsFastMapDirect mapExitVar = mapNew.GetCopy();
                        mapExitVar.Complement(mapTrueSource);
                        foreach (KeyValuePair <int, FastSparseSetFactory <int> .FastSparseSet <int> > ent in mapExitVar
                                 .EntryList())
                        {
                            foreach (int version in ent.Value)
                            {
                                int            varindex = ent.Key;
                                VarVersionPair exitvar  = new VarVersionPair(varindex, version);
                                FastSparseSetFactory <int> .FastSparseSet <int> newSet = mapNew.Get(varindex);
                                // remove the actual exit version
                                newSet.Remove(version);
                                // get or create phantom version
                                VarVersionPair phantomvar = mapPhantom.GetOrNull(exitvar);
                                if (phantomvar == null)
                                {
                                    int newversion = GetNextFreeVersion(exitvar.var, null);
                                    phantomvar = new VarVersionPair(exitvar.var, newversion);
                                    VarVersionNode exitnode    = ssuversions.nodes.GetWithKey(exitvar);
                                    VarVersionNode phantomnode = ssuversions.CreateNode(phantomvar);
                                    phantomnode.flags |= VarVersionNode.Flag_Phantom_Finexit;
                                    VarVersionEdge edge = new VarVersionEdge(VarVersionEdge.Edge_Phantom, exitnode, phantomnode
                                                                             );
                                    exitnode.AddSuccessor(edge);
                                    phantomnode.AddPredecessor(edge);
                                    Sharpen.Collections.Put(mapPhantom, exitvar, phantomvar);
                                }
                                // add phantom version
                                newSet.Add(phantomvar.version);
                            }
                        }
                        if (!(mapPhantom.Count == 0))
                        {
                            Sharpen.Collections.Put(phantomexitnodes, predid, mapPhantom);
                        }
                    }
                }
            }
            return(mapNew);
        }
Пример #8
0
        private void ProcessExprent(Exprent expr, SFormsFastMapDirect[] varmaparr, Statement
                                    stat, bool calcLiveVars)
        {
            if (expr == null)
            {
                return;
            }
            VarExprent varassign = null;
            bool       finished  = false;

            switch (expr.type)
            {
            case Exprent.Exprent_Assignment:
            {
                AssignmentExprent assexpr = (AssignmentExprent)expr;
                if (assexpr.GetCondType() == AssignmentExprent.Condition_None)
                {
                    Exprent dest = assexpr.GetLeft();
                    if (dest.type == Exprent.Exprent_Var)
                    {
                        varassign = (VarExprent)dest;
                    }
                }
                break;
            }

            case Exprent.Exprent_Function:
            {
                FunctionExprent func = (FunctionExprent)expr;
                switch (func.GetFuncType())
                {
                case FunctionExprent.Function_Iif:
                {
                    ProcessExprent(func.GetLstOperands()[0], varmaparr, stat, calcLiveVars);
                    SFormsFastMapDirect varmapFalse;
                    if (varmaparr[1] == null)
                    {
                        varmapFalse = new SFormsFastMapDirect(varmaparr[0]);
                    }
                    else
                    {
                        varmapFalse  = varmaparr[1];
                        varmaparr[1] = null;
                    }
                    ProcessExprent(func.GetLstOperands()[1], varmaparr, stat, calcLiveVars);
                    SFormsFastMapDirect[] varmaparrNeg = new SFormsFastMapDirect[] { varmapFalse, null };
                    ProcessExprent(func.GetLstOperands()[2], varmaparrNeg, stat, calcLiveVars);
                    MergeMaps(varmaparr[0], varmaparrNeg[0]);
                    varmaparr[1] = null;
                    finished     = true;
                    break;
                }

                case FunctionExprent.Function_Cadd:
                {
                    ProcessExprent(func.GetLstOperands()[0], varmaparr, stat, calcLiveVars);
                    SFormsFastMapDirect[] varmaparrAnd = new SFormsFastMapDirect[] { new SFormsFastMapDirect
                                                                                         (varmaparr[0]), null };
                    ProcessExprent(func.GetLstOperands()[1], varmaparrAnd, stat, calcLiveVars);
                    // false map
                    varmaparr[1] = MergeMaps(varmaparr[varmaparr[1] == null ? 0 : 1], varmaparrAnd[varmaparrAnd
                                                                                                   [1] == null ? 0 : 1]);
                    // true map
                    varmaparr[0] = varmaparrAnd[0];
                    finished     = true;
                    break;
                }

                case FunctionExprent.Function_Cor:
                {
                    ProcessExprent(func.GetLstOperands()[0], varmaparr, stat, calcLiveVars);
                    SFormsFastMapDirect[] varmaparrOr = new SFormsFastMapDirect[] { new SFormsFastMapDirect
                                                                                        (varmaparr[varmaparr[1] == null ? 0 : 1]), null };
                    ProcessExprent(func.GetLstOperands()[1], varmaparrOr, stat, calcLiveVars);
                    // false map
                    varmaparr[1] = varmaparrOr[varmaparrOr[1] == null ? 0 : 1];
                    // true map
                    varmaparr[0] = MergeMaps(varmaparr[0], varmaparrOr[0]);
                    finished     = true;
                    break;
                }
                }
                break;
            }
            }
            if (!finished)
            {
                List <Exprent> lst = expr.GetAllExprents();
                lst.Remove(varassign);
                foreach (Exprent ex in lst)
                {
                    ProcessExprent(ex, varmaparr, stat, calcLiveVars);
                }
            }
            SFormsFastMapDirect varmap = varmaparr[0];

            // field access
            if (expr.type == Exprent.Exprent_Field)
            {
                int?index;
                if (mapFieldVars.ContainsKey(expr.id))
                {
                    index = mapFieldVars.GetOrNullable(expr.id);
                }
                else
                {
                    index = fieldvarcounter--;
                    Sharpen.Collections.Put(mapFieldVars, expr.id, index);
                    // ssu graph
                    ssuversions.CreateNode(new VarVersionPair(index, 1));
                }
                SetCurrentVar(varmap, index, 1);
            }
            else if (expr.type == Exprent.Exprent_Invocation || (expr.type == Exprent.Exprent_Assignment &&
                                                                 ((AssignmentExprent)expr).GetLeft().type == Exprent.Exprent_Field) || (expr.
                                                                                                                                        type == Exprent.Exprent_New && ((NewExprent)expr).GetNewType().type == ICodeConstants
                                                                                                                                        .Type_Object) || expr.type == Exprent.Exprent_Function)
            {
                bool ismmpp = true;
                if (expr.type == Exprent.Exprent_Function)
                {
                    ismmpp = false;
                    FunctionExprent fexpr = (FunctionExprent)expr;
                    if (fexpr.GetFuncType() >= FunctionExprent.Function_Imm && fexpr.GetFuncType() <=
                        FunctionExprent.Function_Ppi)
                    {
                        if (fexpr.GetLstOperands()[0].type == Exprent.Exprent_Field)
                        {
                            ismmpp = true;
                        }
                    }
                }
                if (ismmpp)
                {
                    varmap.RemoveAllFields();
                }
            }
            if (varassign != null)
            {
                int varindex = varassign.GetIndex();
                if (varassign.GetVersion() == 0)
                {
                    // get next version
                    int nextver = GetNextFreeVersion(varindex, stat);
                    // set version
                    varassign.SetVersion(nextver);
                    // ssu graph
                    ssuversions.CreateNode(new VarVersionPair(varindex, nextver));
                    SetCurrentVar(varmap, varindex, nextver);
                }
                else
                {
                    if (calcLiveVars)
                    {
                        VarMapToGraph(new VarVersionPair(varindex, varassign.GetVersion()), varmap);
                    }
                    SetCurrentVar(varmap, varindex, varassign.GetVersion());
                }
            }
            else if (expr.type == Exprent.Exprent_Function)
            {
                // MM or PP function
                FunctionExprent func_1 = (FunctionExprent)expr;
                switch (func_1.GetFuncType())
                {
                case FunctionExprent.Function_Imm:
                case FunctionExprent.Function_Mmi:
                case FunctionExprent.Function_Ipp:
                case FunctionExprent.Function_Ppi:
                {
                    if (func_1.GetLstOperands()[0].type == Exprent.Exprent_Var)
                    {
                        VarExprent     var      = (VarExprent)func_1.GetLstOperands()[0];
                        int            varindex = var.GetIndex();
                        VarVersionPair varpaar  = new VarVersionPair(varindex, var.GetVersion());
                        // ssu graph
                        VarVersionPair phantomver = phantomppnodes.GetOrNull(varpaar);
                        if (phantomver == null)
                        {
                            // get next version
                            int nextver = GetNextFreeVersion(varindex, null);
                            phantomver = new VarVersionPair(varindex, nextver);
                            //ssuversions.createOrGetNode(phantomver);
                            ssuversions.CreateNode(phantomver);
                            VarVersionNode vernode = ssuversions.nodes.GetWithKey(varpaar);
                            FastSparseSetFactory <int> .FastSparseSet <int> vers = factory.SpawnEmptySet();
                            if (vernode.preds.Count == 1)
                            {
                                vers.Add(new Sharpen.EnumeratorAdapter <VarVersionEdge>(vernode.preds.GetEnumerator()).Next().source.version);
                            }
                            else
                            {
                                foreach (VarVersionEdge edge in vernode.preds)
                                {
                                    vers.Add(new Sharpen.EnumeratorAdapter <VarVersionEdge>(edge.source.preds.GetEnumerator()).Next().source.version);
                                }
                            }
                            vers.Add(nextver);
                            CreateOrUpdatePhiNode(varpaar, vers, stat);
                            Sharpen.Collections.Put(phantomppnodes, varpaar, phantomver);
                        }
                        if (calcLiveVars)
                        {
                            VarMapToGraph(varpaar, varmap);
                        }
                        SetCurrentVar(varmap, varindex, var.GetVersion());
                    }
                    break;
                }
                }
            }
            else if (expr.type == Exprent.Exprent_Var)
            {
                VarExprent vardest      = (VarExprent)expr;
                int        varindex     = vardest.GetIndex();
                int        current_vers = vardest.GetVersion();
                FastSparseSetFactory <int> .FastSparseSet <int> vers = varmap.Get(varindex);
                int cardinality = vers.GetCardinality();
                if (cardinality == 1)
                {
                    // size == 1
                    if (current_vers != 0)
                    {
                        if (calcLiveVars)
                        {
                            VarMapToGraph(new VarVersionPair(varindex, current_vers), varmap);
                        }
                        SetCurrentVar(varmap, varindex, current_vers);
                    }
                    else
                    {
                        // split last version
                        int usever = GetNextFreeVersion(varindex, stat);
                        // set version
                        vardest.SetVersion(usever);
                        SetCurrentVar(varmap, varindex, usever);
                        // ssu graph
                        int            lastver = new Sharpen.EnumeratorAdapter <int>(vers.GetEnumerator()).Next();
                        VarVersionNode prenode = ssuversions.nodes.GetWithKey(new VarVersionPair(varindex
                                                                                                 , lastver));
                        VarVersionNode usenode = ssuversions.CreateNode(new VarVersionPair(varindex, usever
                                                                                           ));
                        VarVersionEdge edge = new VarVersionEdge(VarVersionEdge.Edge_General, prenode, usenode
                                                                 );
                        prenode.AddSuccessor(edge);
                        usenode.AddPredecessor(edge);
                    }
                }
                else if (cardinality == 2)
                {
                    // size > 1
                    if (current_vers != 0)
                    {
                        if (calcLiveVars)
                        {
                            VarMapToGraph(new VarVersionPair(varindex, current_vers), varmap);
                        }
                        SetCurrentVar(varmap, varindex, current_vers);
                    }
                    else
                    {
                        // split version
                        int usever = GetNextFreeVersion(varindex, stat);
                        // set version
                        vardest.SetVersion(usever);
                        // ssu node
                        ssuversions.CreateNode(new VarVersionPair(varindex, usever));
                        SetCurrentVar(varmap, varindex, usever);
                        current_vers = usever;
                    }
                    CreateOrUpdatePhiNode(new VarVersionPair(varindex, current_vers), vers, stat);
                }
            }
        }
        private void ProcessExprent(Exprent expr, SFormsFastMapDirect[] varmaparr)
        {
            if (expr == null)
            {
                return;
            }
            VarExprent varassign = null;
            bool       finished  = false;

            switch (expr.type)
            {
            case Exprent.Exprent_Assignment:
            {
                AssignmentExprent assexpr = (AssignmentExprent)expr;
                if (assexpr.GetCondType() == AssignmentExprent.Condition_None)
                {
                    Exprent dest = assexpr.GetLeft();
                    if (dest.type == Exprent.Exprent_Var)
                    {
                        varassign = (VarExprent)dest;
                    }
                }
                break;
            }

            case Exprent.Exprent_Function:
            {
                FunctionExprent func = (FunctionExprent)expr;
                switch (func.GetFuncType())
                {
                case FunctionExprent.Function_Iif:
                {
                    ProcessExprent(func.GetLstOperands()[0], varmaparr);
                    SFormsFastMapDirect varmapFalse;
                    if (varmaparr[1] == null)
                    {
                        varmapFalse = new SFormsFastMapDirect(varmaparr[0]);
                    }
                    else
                    {
                        varmapFalse  = varmaparr[1];
                        varmaparr[1] = null;
                    }
                    ProcessExprent(func.GetLstOperands()[1], varmaparr);
                    SFormsFastMapDirect[] varmaparrNeg = new SFormsFastMapDirect[] { varmapFalse, null };
                    ProcessExprent(func.GetLstOperands()[2], varmaparrNeg);
                    MergeMaps(varmaparr[0], varmaparrNeg[0]);
                    varmaparr[1] = null;
                    finished     = true;
                    break;
                }

                case FunctionExprent.Function_Cadd:
                {
                    ProcessExprent(func.GetLstOperands()[0], varmaparr);
                    SFormsFastMapDirect[] varmaparrAnd = new SFormsFastMapDirect[] { new SFormsFastMapDirect
                                                                                         (varmaparr[0]), null };
                    ProcessExprent(func.GetLstOperands()[1], varmaparrAnd);
                    // false map
                    varmaparr[1] = MergeMaps(varmaparr[varmaparr[1] == null ? 0 : 1], varmaparrAnd[varmaparrAnd
                                                                                                   [1] == null ? 0 : 1]);
                    // true map
                    varmaparr[0] = varmaparrAnd[0];
                    finished     = true;
                    break;
                }

                case FunctionExprent.Function_Cor:
                {
                    ProcessExprent(func.GetLstOperands()[0], varmaparr);
                    SFormsFastMapDirect[] varmaparrOr = new SFormsFastMapDirect[] { new SFormsFastMapDirect
                                                                                        (varmaparr[varmaparr[1] == null ? 0 : 1]), null };
                    ProcessExprent(func.GetLstOperands()[1], varmaparrOr);
                    // false map
                    varmaparr[1] = varmaparrOr[varmaparrOr[1] == null ? 0 : 1];
                    // true map
                    varmaparr[0] = MergeMaps(varmaparr[0], varmaparrOr[0]);
                    finished     = true;
                    break;
                }
                }
                break;
            }
            }
            if (finished)
            {
                return;
            }
            List <Exprent> lst = expr.GetAllExprents();

            lst.Remove(varassign);
            foreach (Exprent ex in lst)
            {
                ProcessExprent(ex, varmaparr);
            }
            SFormsFastMapDirect varmap = varmaparr[0];

            if (varassign != null)
            {
                int varindex = varassign.GetIndex();
                if (varassign.GetVersion() == 0)
                {
                    // get next version
                    int nextver = GetNextFreeVersion(varindex);
                    // set version
                    varassign.SetVersion(nextver);
                    SetCurrentVar(varmap, varindex, nextver);
                }
                else
                {
                    SetCurrentVar(varmap, varindex, varassign.GetVersion());
                }
            }
            else if (expr.type == Exprent.Exprent_Var)
            {
                VarExprent vardest  = (VarExprent)expr;
                int        varindex = vardest.GetIndex();
                FastSparseSetFactory <int> .FastSparseSet <int> vers = varmap.Get(varindex);
                int cardinality = vers.GetCardinality();
                if (cardinality == 1)
                {
                    // == 1
                    // set version
                    int it = new Sharpen.EnumeratorAdapter <int>(vers.GetEnumerator()).Next();
                    vardest.SetVersion(it);
                }
                else if (cardinality == 2)
                {
                    // size > 1
                    int            current_vers = vardest.GetVersion();
                    VarVersionPair currpaar     = new VarVersionPair(varindex, current_vers);
                    if (current_vers != 0 && phi.ContainsKey(currpaar))
                    {
                        SetCurrentVar(varmap, varindex, current_vers);
                        // update phi node
                        phi.GetOrNull(currpaar).Union(vers);
                    }
                    else
                    {
                        // increase version
                        int nextver = GetNextFreeVersion(varindex);
                        // set version
                        vardest.SetVersion(nextver);
                        SetCurrentVar(varmap, varindex, nextver);
                        // create new phi node
                        Sharpen.Collections.Put(phi, new VarVersionPair(varindex, nextver), vers);
                    }
                }
            }
        }