Skip to content

Commit ff72e60

Browse files
jaskarthKroppeb
authored andcommitted
More work on IR tests
- Change result to .res for ease of searching - Fix some issues with statement parsing - Render statements for input and output graphs
1 parent 138f572 commit ff72e60

File tree

17 files changed

+316
-82
lines changed

17 files changed

+316
-82
lines changed

src/org/jetbrains/java/decompiler/main/collectors/ImportCollector.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,13 @@ public ImportCollector(ImportCollector other) {
7575
this.writeLocked = other.writeLocked;
7676
}
7777

78+
// Unit testing use only!
79+
public ImportCollector() {
80+
currentPackageSlash = "pkg/";
81+
currentPackagePoint = "pkg.";
82+
83+
}
84+
7885
/**
7986
* Check whether the package-less name ClassName is shaded by variable in a context of
8087
* the decompiled class

src/org/jetbrains/java/decompiler/modules/decompiler/LabelHelper.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ private static void liftClosures(Statement stat) {
4848
case StatEdge.TYPE_CONTINUE:
4949
// If the continue is pointing somewhere that is not it's enclosed statement, move it to it's enclosed statement (and remove it from it's previous closure)
5050
if (edge.getDestination() != edge.closure) {
51+
ValidationHelper.assertTrue(false, "Continue edge is not pointing to it's closure");
5152
edge.getDestination().addLabeledEdge(edge);
5253
}
5354
break;
@@ -287,8 +288,7 @@ private static HashMap<Statement, List<StatEdge>> setExplicitEdges(Statement sta
287288
for (Entry<Statement, List<StatEdge>> entr : mapEdges1.entrySet()) {
288289
if (mapEdges.containsKey(entr.getKey())) {
289290
mapEdges.get(entr.getKey()).addAll(entr.getValue());
290-
}
291-
else {
291+
} else {
292292
mapEdges.put(entr.getKey(), entr.getValue());
293293
}
294294
}
@@ -417,9 +417,10 @@ private static void processEdgesWithNext(Statement stat, HashMap<Statement, List
417417
}
418418
}
419419

420-
if (edge.closure instanceof DoStatement && stat instanceof IfStatement && edge.getDestination() instanceof DummyExitStatement) {
421-
continue;
422-
}
420+
// TODO: is this needed anymore? It's never hit in the test suite
421+
// if (edge.closure instanceof DoStatement && stat instanceof IfStatement && edge.getDestination() instanceof DummyExitStatement) {
422+
// continue;
423+
// }
423424

424425
edge.explicit = false;
425426
}

src/org/jetbrains/java/decompiler/modules/decompiler/StatEdge.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ public static int fromEdgeTypeString(String s) {
123123
case "FinExit":
124124
return TYPE_FINALLYEXIT;
125125
default:
126-
throw new RuntimeException("Invalid edge type");
126+
throw new RuntimeException("Invalid edge type: " + s);
127127
}
128128
}
129129

src/org/jetbrains/java/decompiler/modules/decompiler/exps/ConstExprent.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -614,16 +614,14 @@ public static Exprent fromTapestry(ExprParser.Arg arg) {
614614
String rawVal = arg.getNextString();
615615
Object val = rawVal;
616616

617-
if (type.typeFamily == TypeFamily.INTEGER) {
617+
if (type.typeFamily == TypeFamily.INTEGER || type.typeFamily == TypeFamily.BOOLEAN) {
618618
val = Integer.parseInt(rawVal);
619619
} else if (type == VarType.VARTYPE_LONG) {
620620
val = Long.parseLong(rawVal);
621621
} else if (type == VarType.VARTYPE_FLOAT) {
622622
val = Float.parseFloat(rawVal);
623623
} else if (type == VarType.VARTYPE_DOUBLE) {
624624
val = Double.parseDouble(rawVal);
625-
} else if (type == VarType.VARTYPE_BOOLEAN) {
626-
val = Boolean.parseBoolean(rawVal);
627625
} else if (type == VarType.VARTYPE_CHAR) {
628626
val = rawVal.charAt(0);
629627
} else if (type == VarType.VARTYPE_NULL) {

src/org/jetbrains/java/decompiler/modules/serializer/TapestryReader.java

Lines changed: 81 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import java.util.stream.Collectors;
1111

1212
public final class TapestryReader {
13+
public static final String BLOCK_SEP = "=======================================";
1314
private static final Map<String, Statement.StatementType> TYPES = Arrays.stream(Statement.StatementType.values())
1415
.collect(Collectors.toMap(Statement.StatementType::getPrettyId, t -> t));
1516
public static RootStatement readTapestry(String data) {
@@ -24,6 +25,9 @@ public static RootStatement readTapestry(String data) {
2425
s = s.replaceAll("\\s+", " ");
2526

2627
String[] components = s.split(" ");
28+
if (components[0].equals(BLOCK_SEP) || components[0].startsWith("#")) {
29+
break;
30+
}
2731

2832
if (components[1].equals("->")) {
2933
// Edge
@@ -85,12 +89,14 @@ public static RootStatement readTapestry(String data) {
8589

8690
if (edge.ifId != -1) {
8791
((IfStatement)stats.get(edge.ifId)).setIfEdge(statEdge);
88-
((IfStatement)stats.get(edge.ifId)).setIfstat(statEdge.getDestination());
92+
if (edge.hasIfStat) {
93+
((IfStatement) stats.get(edge.ifId)).setIfstat(statEdge.getDestination());
94+
}
8995
}
9096

9197
if (edge.elseId != -1) {
92-
((IfStatement)stats.get(edge.elseId)).setIfEdge(statEdge);
93-
((IfStatement)stats.get(edge.ifId)).setElsestat(statEdge.getDestination());
98+
((IfStatement)stats.get(edge.elseId)).setElseEdge(statEdge);
99+
((IfStatement)stats.get(edge.elseId)).setElsestat(statEdge.getDestination());
94100
}
95101

96102
if (edge.defaultId != -1) {
@@ -207,6 +213,10 @@ private static EdgeRec readEdge(String[] components) {
207213
builder.setClosureId(Integer.parseInt(component.substring(2)));
208214
} else if (component.startsWith("If:")) {
209215
builder.setIfId(Integer.parseInt(component.substring(3)));
216+
builder.setHasIfStat(true);
217+
} else if (component.startsWith("IfN:")) {
218+
builder.setIfId(Integer.parseInt(component.substring(4)));
219+
builder.setHasIfStat(false);
210220
} else if (component.startsWith("IfE:")) {
211221
builder.setElseId(Integer.parseInt(component.substring(4)));
212222
} else if (component.startsWith("D:")) {
@@ -271,8 +281,9 @@ static class EdgeRec {
271281
private final int ifId;
272282
private final int elseId;
273283
private final int defaultId;
284+
private final boolean hasIfStat;
274285

275-
EdgeRec(int edgeType, int sourceId, int destId, int closureId, boolean labeled, boolean explicit, boolean canInline, boolean phantomContinue, int ifId, int elseId, int defaultId) {
286+
EdgeRec(int edgeType, int sourceId, int destId, int closureId, boolean labeled, boolean explicit, boolean canInline, boolean phantomContinue, int ifId, int elseId, int defaultId, boolean hasIfStat) {
276287
this.edgeType = edgeType;
277288
this.sourceId = sourceId;
278289
this.destId = destId;
@@ -284,79 +295,86 @@ static class EdgeRec {
284295
this.ifId = ifId;
285296
this.elseId = elseId;
286297
this.defaultId = defaultId;
298+
this.hasIfStat = hasIfStat;
287299
}
288300
}
289301

290302
public static class EdgeRecBuilder {
291-
private int edgeType;
292-
private int sourceId;
293-
private int destId;
294-
private int closureId = -1;
295-
private boolean labeled;
296-
private boolean explicit;
297-
private boolean canInline = true;
298-
private boolean phantomContinue;
299-
private int ifId = -1;
300-
private int elseId = -1;
301-
private int defaultId = -1;
302-
303-
public EdgeRecBuilder setEdgeType(int edgeType) {
304-
this.edgeType = edgeType;
305-
return this;
306-
}
303+
private int edgeType;
304+
private int sourceId;
305+
private int destId;
306+
private int closureId = -1;
307+
private boolean labeled;
308+
private boolean explicit;
309+
private boolean canInline = true;
310+
private boolean phantomContinue;
311+
private int ifId = -1;
312+
private int elseId = -1;
313+
private int defaultId = -1;
314+
private boolean hasIfStat = false;
315+
316+
public EdgeRecBuilder setEdgeType(int edgeType) {
317+
this.edgeType = edgeType;
318+
return this;
319+
}
307320

308-
public EdgeRecBuilder setSourceId(int sourceId) {
309-
this.sourceId = sourceId;
310-
return this;
311-
}
321+
public EdgeRecBuilder setSourceId(int sourceId) {
322+
this.sourceId = sourceId;
323+
return this;
324+
}
312325

313-
public EdgeRecBuilder setDestId(int destId) {
314-
this.destId = destId;
315-
return this;
316-
}
326+
public EdgeRecBuilder setDestId(int destId) {
327+
this.destId = destId;
328+
return this;
329+
}
317330

318-
public EdgeRecBuilder setClosureId(int closureId) {
319-
this.closureId = closureId;
320-
return this;
321-
}
331+
public EdgeRecBuilder setClosureId(int closureId) {
332+
this.closureId = closureId;
333+
return this;
334+
}
322335

323-
public EdgeRecBuilder setLabeled(boolean labeled) {
324-
this.labeled = labeled;
325-
return this;
326-
}
336+
public EdgeRecBuilder setLabeled(boolean labeled) {
337+
this.labeled = labeled;
338+
return this;
339+
}
327340

328-
public EdgeRecBuilder setExplicit(boolean explicit) {
329-
this.explicit = explicit;
330-
return this;
331-
}
341+
public EdgeRecBuilder setExplicit(boolean explicit) {
342+
this.explicit = explicit;
343+
return this;
344+
}
332345

333-
public EdgeRecBuilder setCanInline(boolean canInline) {
334-
this.canInline = canInline;
335-
return this;
336-
}
346+
public EdgeRecBuilder setCanInline(boolean canInline) {
347+
this.canInline = canInline;
348+
return this;
349+
}
337350

338-
public EdgeRecBuilder setPhantomContinue(boolean phantomContinue) {
339-
this.phantomContinue = phantomContinue;
340-
return this;
341-
}
351+
public EdgeRecBuilder setPhantomContinue(boolean phantomContinue) {
352+
this.phantomContinue = phantomContinue;
353+
return this;
354+
}
342355

343-
public EdgeRecBuilder setIfId(int ifId) {
344-
this.ifId = ifId;
345-
return this;
346-
}
356+
public EdgeRecBuilder setIfId(int ifId) {
357+
this.ifId = ifId;
358+
return this;
359+
}
347360

348-
public EdgeRecBuilder setElseId(int elseId) {
349-
this.elseId = elseId;
350-
return this;
351-
}
361+
public EdgeRecBuilder setElseId(int elseId) {
362+
this.elseId = elseId;
363+
return this;
364+
}
352365

353-
public EdgeRecBuilder setDefaultId(int defaultId) {
354-
this.defaultId = defaultId;
355-
return this;
356-
}
366+
public EdgeRecBuilder setDefaultId(int defaultId) {
367+
this.defaultId = defaultId;
368+
return this;
369+
}
357370

358-
public EdgeRec createEdgeRec() {
359-
return new EdgeRec(edgeType, sourceId, destId, closureId, labeled, explicit, canInline, phantomContinue, ifId, elseId, defaultId);
360-
}
371+
public EdgeRecBuilder setHasIfStat(boolean hasIfStat) {
372+
this.hasIfStat = hasIfStat;
373+
return this;
374+
}
375+
376+
public EdgeRec createEdgeRec() {
377+
return new EdgeRec(edgeType, sourceId, destId, closureId, labeled, explicit, canInline, phantomContinue, ifId, elseId, defaultId, hasIfStat);
378+
}
361379
}
362380
}

src/org/jetbrains/java/decompiler/modules/serializer/TapestryWriter.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ public static String serialize(RootStatement root) {
116116
if (st instanceof IfStatement) {
117117
IfStatement ifStat = (IfStatement) st;
118118
edgeMap.get(ifStat.getIfEdge()).ifId = ifStat.id;
119+
edgeMap.get(ifStat.getIfEdge()).hasIfStat = ifStat.getIfstat() != null;
119120

120121
if (ifStat.getElsestat() != null) {
121122
edgeMap.get(ifStat.getElseEdge()).elseId = ifStat.id;
@@ -124,7 +125,7 @@ public static String serialize(RootStatement root) {
124125

125126
if (st instanceof SwitchStatement) {
126127
SwitchStatement switchStat = (SwitchStatement) st;
127-
edgeMap.get(switchStat.getDefaultEdge()).ifId = switchStat.id;
128+
edgeMap.get(switchStat.getDefaultEdge()).defaultId = switchStat.id;
128129
}
129130
}
130131

@@ -166,7 +167,11 @@ public static String serialize(RootStatement root) {
166167
}
167168

168169
if (ed.ifId != -1) {
169-
eb.append(" If:").append(ed.ifId);
170+
if (ed.hasIfStat) {
171+
eb.append(" If:").append(ed.ifId);
172+
} else {
173+
eb.append(" IfN:").append(ed.ifId);
174+
}
170175
}
171176

172177
if (ed.elseId != -1) {
@@ -241,6 +246,7 @@ private static class StatEdgeData {
241246
private int ifId = -1;
242247
private int elseId = -1;
243248
private int defaultId = -1;
249+
private boolean hasIfStat = false;
244250

245251
private StatEdgeData(StatEdge edge) {
246252
this.edge = edge;

test/org/jetbrains/java/decompiler/MinimalQuiltflowerEnvironment.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import org.jetbrains.java.decompiler.main.ClassesProcessor;
44
import org.jetbrains.java.decompiler.main.DecompilerContext;
55
import org.jetbrains.java.decompiler.main.decompiler.PrintStreamLogger;
6+
import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences;
67
import org.jetbrains.java.decompiler.struct.StructContext;
78

89
import java.util.HashMap;
@@ -14,7 +15,7 @@ public final class MinimalQuiltflowerEnvironment {
1415
public static void setup() {
1516
StructContext sc = new StructContext(null, null, null);
1617
DecompilerContext context = new DecompilerContext(
17-
new HashMap<>(),
18+
IFernflowerPreferences.getDefaults(),
1819
new PrintStreamLogger(System.out),
1920
sc,
2021
new ClassesProcessor(sc),

test/org/jetbrains/java/decompiler/ir/IdentifyLabelsTest.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ public class IdentifyLabelsTest extends IrTestBase {
77
@Override
88
protected void registerAll() {
99
register("TestLoopBreak");
10+
register("TestLoopBreakEmptyIf");
11+
register("TestLiftSequenceLabel");
12+
register("TestIfElse");
1013
}
1114

1215
@Override

test/org/jetbrains/java/decompiler/ir/IrTestBase.java

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
import org.jetbrains.java.decompiler.DecompilerTestFixture;
44
import org.jetbrains.java.decompiler.MinimalQuiltflowerEnvironment;
5+
import org.jetbrains.java.decompiler.main.DecompilerContext;
6+
import org.jetbrains.java.decompiler.main.collectors.ImportCollector;
57
import org.jetbrains.java.decompiler.modules.decompiler.stats.RootStatement;
68
import org.jetbrains.java.decompiler.modules.serializer.TapestryReader;
79
import org.jetbrains.java.decompiler.modules.serializer.TapestryWriter;
@@ -47,22 +49,41 @@ protected Stream<DynamicNode> makeTests() {
4749
Path outDir = new DecompilerTestFixture().getTestDataDir().resolve("results/transforms/" + transformName() + "/");
4850

4951
return tests.stream().map(s -> {
50-
return DynamicTest.dynamicTest(s, () -> {
52+
return DynamicTest.dynamicTest(s, outDir.resolve(s + ".res").toUri(), () -> {
5153
MinimalQuiltflowerEnvironment.setup();
52-
String input = Files.readString(baseDir.resolve(s + ".qir"));
54+
ImportCollector importCollector = new ImportCollector();
55+
DecompilerContext.startClass(importCollector);
56+
57+
Path inPath = baseDir.resolve(s + ".qir");
58+
String input = Files.readString(inPath);
5359
RootStatement root = TapestryReader.readTapestry(input);
60+
int indexOf = input.indexOf(TapestryReader.BLOCK_SEP);
61+
if (indexOf > 0) {
62+
input = input.substring(0, indexOf).stripTrailing();
63+
}
64+
65+
input = appendTransform(root, input);
5466
runTransform(root);
5567

5668
String output = TapestryWriter.serialize(root);
69+
output = appendTransform(root, output);
5770

58-
Path outPath = outDir.resolve(s + ".qir");
71+
Path outPath = outDir.resolve(s + ".res");
5972
if (outPath.toFile().exists()) {
60-
assertEquals(Files.readString(outPath).replace("\r\n", "\n"), output);
73+
assertEquals(output, Files.readString(outPath).replaceAll("\r\n", "\n"));
74+
75+
String existing = Files.readString(inPath).replaceAll("\r\n", "\n");
76+
// Ensuring the input file has a rendered statement at the end
77+
assumeTrue(existing.equals(input), "input file must be\n\"\"\n" + input + "\n\"\"\n");
6178
} else {
62-
assumeTrue(false, outPath + " was not present yet");
6379
Files.writeString(outPath, output);
80+
assumeTrue(false, outPath + " was not present yet");
6481
}
6582
});
6683
});
6784
}
85+
86+
private static String appendTransform(RootStatement root, String output) {
87+
return output + "\n" + TapestryReader.BLOCK_SEP + "\n" + root.toJava().convertToStringAndAllowDataDiscard().replaceAll("\r\n", "\n").stripTrailing();
88+
}
6889
}

0 commit comments

Comments
 (0)