in src/org/jetbrains/java/decompiler/modules/decompiler/sforms/SSAUConstructorSparseEx.java [155:411]
private void processExprent(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 VarVersion(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 VarVersion(varindex, nextver));
setCurrentVar(varmap, varindex, nextver);
}
else {
if (calcLiveVars) {
varMapToGraph(new VarVersion(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();
VarVersion varpaar = new VarVersion(varindex.intValue(), var.getVersion());
// ssu graph
VarVersion phantomver = phantomppnodes.get(varpaar);
if (phantomver == null) {
// get next version
Integer nextver = getNextFreeVersion(varindex, null);
phantomver = new VarVersion(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 VarVersion(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 VarVersion(varindex, lastver));
VarVersionNode usenode = ssuversions.createNode(new VarVersion(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 VarVersion(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 VarVersion(varindex, usever));
setCurrentVar(varmap, varindex, usever);
current_vers = usever;
}
createOrUpdatePhiNode(new VarVersion(varindex, current_vers), vers, stat);
} // vers.size() == 0 means uninitialized variable, which is impossible
}
}