void (Exprent expr, SFormsFastMapDirect[] varmaparr, Statement stat, boolean calcLiveVars) { if (expr == null) { return; } VarExprent varassign = null; boolean 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; } } } case Exprent.EXPRENT_FUNCTION -> { FunctionExprent func = (FunctionExprent)expr; switch (func.getFuncType()) { case FunctionExprent.FUNCTION_IIF -> { processExprent(func.getLstOperands().get(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().get(1), varmaparr, stat, calcLiveVars); SFormsFastMapDirect[] varmaparrNeg = new SFormsFastMapDirect[]{varmapFalse, null}; processExprent(func.getLstOperands().get(2), varmaparrNeg, stat, calcLiveVars); mergeMaps(varmaparr[0], varmaparrNeg[0]); varmaparr[1] = null; finished = true; } case FunctionExprent.FUNCTION_CADD -> { processExprent(func.getLstOperands().get(0), varmaparr, stat, calcLiveVars); SFormsFastMapDirect[] varmaparrAnd = new SFormsFastMapDirect[]{new SFormsFastMapDirect(varmaparr[0]), null}; processExprent(func.getLstOperands().get(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; } case FunctionExprent.FUNCTION_COR -> { processExprent(func.getLstOperands().get(0), varmaparr, stat, calcLiveVars); SFormsFastMapDirect[] varmaparrOr = new SFormsFastMapDirect[]{new SFormsFastMapDirect(varmaparr[varmaparr[1] == null ? 0 : 1]), null}; processExprent(func.getLstOperands().get(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; } } } } if (!finished) { List<Exprent> lst = expr.getAllExprents(); lst.remove(varassign); for (Exprent ex : 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.get(expr.id); } else { index = fieldvarcounter--; mapFieldVars.put(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().getType() == CodeConstants.TYPE_OBJECT) || expr.type == Exprent.EXPRENT_FUNCTION) { boolean 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().get(0).type == Exprent.EXPRENT_FIELD) { ismmpp = true; } } } if (ismmpp) { varmap.removeAllFields(); } } if (varassign != null) { Integer varindex = varassign.getIndex(); if (varassign.getVersion() == 0) { // get next version Integer 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.intValue(), varassign.getVersion()), varmap); } setCurrentVar(varmap, varindex, varassign.getVersion()); } } else if (expr.type == Exprent.EXPRENT_FUNCTION) { // MM or PP function FunctionExprent func = (FunctionExprent)expr; switch (func.getFuncType()) { case FunctionExprent.FUNCTION_IMM, FunctionExprent.FUNCTION_MMI, FunctionExprent.FUNCTION_IPP, FunctionExprent.FUNCTION_PPI -> { if (func.getLstOperands().get(0).type == Exprent.EXPRENT_VAR) { VarExprent var = (VarExprent)func.getLstOperands().get(0); Integer varindex = var.getIndex(); VarVersionPair varpaar = new VarVersionPair(varindex.intValue(), var.getVersion()); // ssu graph VarVersionPair phantomver = phantomppnodes.get(varpaar); if (phantomver == null) { // get next version Integer nextver = getNextFreeVersion(varindex, null); phantomver = new VarVersionPair(varindex, nextver); //ssuversions.createOrGetNode(phantomver); ssuversions.createNode(phantomver); VarVersionNode vernode = ssuversions.nodes.getWithKey(varpaar); FastSparseSet<Integer> vers = factory.spawnEmptySet(); if (vernode.predecessors.size() == 1) { vers.add(vernode.predecessors.iterator().next().source.version); } else { for (VarVersionEdge edge : vernode.predecessors) { vers.add(edge.source.predecessors.iterator().next().source.version); } } vers.add(nextver); createOrUpdatePhiNode(varpaar, vers, stat); phantomppnodes.put(varpaar, phantomver); } if (calcLiveVars) { varMapToGraph(varpaar, varmap); } setCurrentVar(varmap, varindex, var.getVersion()); } } } } else if (expr.type == Exprent.EXPRENT_VAR) { VarExprent vardest = (VarExprent)expr; Integer varindex = vardest.getIndex(); Integer current_vers = vardest.getVersion(); FastSparseSet<Integer> 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 Integer usever = getNextFreeVersion(varindex, stat); // set version vardest.setVersion(usever); setCurrentVar(varmap, varindex, usever); // ssu graph Integer lastver = vers.iterator().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 Integer 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); } // vers.size() == 0 means uninitialized variable, which is impossible } }