Improved goto handling

This commit is contained in:
Jindra Petřík
2021-02-28 16:53:36 +01:00
parent f2520550f5
commit 763784dbf3
2 changed files with 200 additions and 18 deletions

View File

@@ -537,7 +537,8 @@ public class Graph {
List<GraphTargetItem> ret = printGraph(gotos, new HashMap<>(), new HashMap<>(), new HashSet<>(), localData, stack, allParts, null, heads.get(0), null, null, loops, throwStates, staticOperation, path);
processIfGotos(gotos, ret);
processIfGotos2(new ArrayList<>(), gotos, ret, ret);
processIfGotos(gotos, ret, ret);
Map<String, Integer> usages = new HashMap<>();
Map<String, GotoItem> lastUsage = new HashMap<>();
@@ -809,6 +810,40 @@ public class Graph {
}
}
private void processIfGotos2(List<List<GraphTargetItem>> alreadyProcessedBlocks, List<GotoItem> allGotos, List<GraphTargetItem> list, List<GraphTargetItem> rootList) {
for (int i = 0; i < list.size(); i++) {
GraphTargetItem item = list.get(i);
if (item instanceof Block) {
List<List<GraphTargetItem>> subs = ((Block) item).getSubs();
for (List<GraphTargetItem> sub : subs) {
processIfGotos2(alreadyProcessedBlocks, allGotos, sub, rootList);
}
}
if (item instanceof GotoItem) {
GotoItem gi = (GotoItem) item;
loopblk:
for (List<GraphTargetItem> blk : alreadyProcessedBlocks) {
for (int j = 0; j < blk.size(); j++) {
GraphTargetItem ti = blk.get(j);
if (ti instanceof LabelItem) {
LabelItem label = (LabelItem) ti;
if (label.labelName.equals(gi.labelName)) {
if (blk.get(blk.size() - 1) instanceof ExitItem) {
int siz = blk.size();
for (int k = 0; k < siz - j; k++) {
list.add(i + 1 + k, blk.remove(j));
}
blk.add(j, list.remove(i));
}
break loopblk;
}
}
}
}
}
}
alreadyProcessedBlocks.add(list);
}
/**
* if (xxx) { y ; goto a } else { z ; goto a }
*
@@ -817,30 +852,17 @@ public class Graph {
* if (xxx) { y } else { z } goto a
*
*/
private void processIfGotos(List<GotoItem> allGotos, List<GraphTargetItem> list) {
private void processIfGotos(List<GotoItem> allGotos, List<GraphTargetItem> list, List<GraphTargetItem> rootList) {
for (int i = 0; i < list.size(); i++) {
GraphTargetItem item = list.get(i);
if (item instanceof Block) {
List<List<GraphTargetItem>> subs = ((Block) item).getSubs();
for (List<GraphTargetItem> sub : subs) {
processIfGotos(allGotos, sub);
processIfGotos(allGotos, sub, rootList);
}
}
if (item instanceof IfItem) {
IfItem ii = (IfItem) item;
if (!ii.onTrue.isEmpty() && ii.onFalse.isEmpty()) {
if (ii.onTrue.get(ii.onTrue.size() - 1) instanceof GotoItem) {
if (i + 1 < list.size()) {
if (list.get(i + 1) instanceof GotoItem) {
GotoItem g1 = (GotoItem) ii.onTrue.get(ii.onTrue.size() - 1);
GotoItem g2 = (GotoItem) list.get(i + 1);
if (g1.labelName.equals(g2.labelName)) {
ii.onTrue.remove(ii.onTrue.size() - 1);
}
}
}
}
}
if (!ii.onTrue.isEmpty() && !ii.onFalse.isEmpty()) {
if (ii.onTrue.get(ii.onTrue.size() - 1) instanceof GotoItem) {
if (ii.onFalse.get(ii.onFalse.size() - 1) instanceof GotoItem) {
@@ -879,6 +901,20 @@ public class Graph {
}
}
}
if (!ii.onTrue.isEmpty() && ii.onFalse.isEmpty()) {
if (ii.onTrue.get(ii.onTrue.size() - 1) instanceof GotoItem) {
GotoItem g1 = (GotoItem) ii.onTrue.get(ii.onTrue.size() - 1);
if (i + 1 < list.size()) {
if (list.get(i + 1) instanceof GotoItem) {
GotoItem g2 = (GotoItem) list.get(i + 1);
if (g1.labelName.equals(g2.labelName)) {
ii.onTrue.remove(ii.onTrue.size() - 1);
}
}
}
}
}
}
}
}
@@ -1652,7 +1688,7 @@ public class Graph {
}
if (ret == null) {
ret = new ArrayList<>();
ret = new GraphPartMarkedArrayList<>();
}
//try {
@@ -1806,6 +1842,15 @@ public class Graph {
if (firstCodePos > firstCode.size()) {
firstCodePos = firstCode.size();
}
if (firstCode instanceof GraphPartMarkedArrayList) {
GraphPartMarkedArrayList<GraphTargetItem> markedFirstCode = (GraphPartMarkedArrayList<GraphTargetItem>) firstCode;
firstCodePos = markedFirstCode.indexOfPart(part);
if (firstCodePos == -1) {
firstCodePos = firstCode.size();
}
((GraphPartMarkedArrayList<GraphTargetItem>) firstCode).startPart(part);
}
if (firstCode.size() > firstCodePos && (firstCode.get(firstCodePos) instanceof LabelItem)) {
labelName = ((LabelItem) firstCode.get(firstCodePos)).labelName;
} else {
@@ -1842,8 +1887,12 @@ public class Graph {
boolean parseNext = true;
//****************************DECOMPILING PART*************
List<GraphTargetItem> output = new ArrayList<>();
GraphPartMarkedArrayList<GraphTargetItem> output = new GraphPartMarkedArrayList<>();
output.startPart(part);
if (currentRet instanceof GraphPartMarkedArrayList) {
((GraphPartMarkedArrayList) currentRet).startPart(part);
}
if (checkPartOutput(currentRet, foundGotos, partCodes, partCodePos, visited, code, localData, allParts, stack, parent, part, stopPart, stopPartKind, loops, throwStates, currentLoop, staticOperation, path, recursionLevel)) {
parseNext = false;
} else {

View File

@@ -0,0 +1,133 @@
package com.jpexs.decompiler.graph;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
*
* @author JPEXS
*/
public class GraphPartMarkedArrayList<E> extends ArrayList<E> {
private List<GraphPart> listParts = new ArrayList<>();
private GraphPart currentPart = null;
public GraphPartMarkedArrayList(Collection<? extends E> collection) {
super(collection);
if (collection instanceof GraphPartMarkedArrayList) {
for (int i = 0; i < collection.size(); i++) {
listParts.add((GraphPart) ((GraphPartMarkedArrayList) collection).listParts.get(i));
}
currentPart = ((GraphPartMarkedArrayList) collection).currentPart;
} else {
for (int i = 0; i < collection.size(); i++) {
listParts.add(currentPart);
}
}
}
public GraphPartMarkedArrayList() {
}
public void startPart(GraphPart part) {
currentPart = part;
}
@Override
public boolean add(E e) {
listParts.add(currentPart);
return super.add(e);
}
@Override
public void add(int index, E element) {
listParts.add(index, currentPart);
super.add(index, element);
}
public GraphPart getPartAt(int index) {
return listParts.get(index);
}
public int indexOfPart(GraphPart part) {
return listParts.indexOf(part);
}
@Override
public boolean addAll(Collection<? extends E> c) {
if (c instanceof GraphPartMarkedArrayList) {
for (int i = 0; i < c.size(); i++) {
listParts.add((GraphPart) ((GraphPartMarkedArrayList) c).listParts.get(i));
}
} else {
for (int i = 0; i < c.size(); i++) {
listParts.add(currentPart);
}
}
return super.addAll(c);
}
@Override
public boolean addAll(int index, Collection<? extends E> c) {
if (c instanceof GraphPartMarkedArrayList) {
for (int i = 0; i < c.size(); i++) {
listParts.add(index + i, (GraphPart) ((GraphPartMarkedArrayList) c).listParts.get(i));
}
} else {
for (int i = 0; i < c.size(); i++) {
listParts.add(index + i, currentPart);
}
}
return super.addAll(index, c);
}
@Override
public boolean remove(Object o) {
if (contains(o)) {
listParts.remove(indexOf(o));
}
return super.remove(o);
}
@Override
public E remove(int index) {
listParts.remove(index);
return super.remove(index);
}
@Override
public void clear() {
listParts.clear();
super.clear();
}
@Override
public List<E> subList(int fromIndex, int toIndex) {
GraphPartMarkedArrayList<E> ret = new GraphPartMarkedArrayList<E>(this);
for (int i = size(); i > toIndex; i--) {
ret.remove(i);
}
for (int i = 0; i < fromIndex; i++) {
ret.remove(i);
}
return ret;
}
@Override
public Object clone() {
return new GraphPartMarkedArrayList<>(this);
}
@Override
public boolean removeAll(Collection<?> c) {
for (Object o : c) {
if (contains(o)) {
listParts.remove(indexOf(o));
}
}
return super.removeAll(c);
}
}