diff --git a/README.md b/README.md index 35a6e6d..5e392a7 100644 --- a/README.md +++ b/README.md @@ -17,13 +17,13 @@ Please complete this checklist (turn [ ] into [X]) before you submit: - [x] I completed the above Submission Info - [x] I built the project in IntelliJ (Build > Build Project) -- [ ] I implemented the ControlFlowGraphBuilder -- [ ] I implemented the ControlFlowGraphRenderer -- [ ] I wrote the source code myself and did not look at the source code of my class mates -- [ ] I ran all the JUnit tests and verified that they all pass -- [ ] I manually checked that my implementation is correct by doing this: - - [ ] I studied the test-input/ExampleClass.java source code - - [ ] I ran App to produce the dot files (in test-output/) +- [x] I implemented the ControlFlowGraphBuilder +- [x] I implemented the ControlFlowGraphRenderer +- [x] I wrote the source code myself and did not look at the source code of my class mates +- [x] I ran all the JUnit tests and verified that they all pass +- [x] I manually checked that my implementation is correct by doing this: + - [x] I studied the test-input/ExampleClass.java source code + - [x] I ran App to produce the dot files (in test-output/) - [ ] I ran dot to turn the dot files in test-output into a PDF - [ ] I manually verified that the PDF contains one page per method of ExampleClass - [ ] I manually verified that those CFGs correspond to the methods' source code diff --git a/compile-tests.sh b/compile-tests.sh new file mode 100755 index 0000000..1e8bbac --- /dev/null +++ b/compile-tests.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash + +set -eou pipefail + +cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" +cat test-output/*.dot | gvpack -u | dot -Tpdf > test-output/all.pdf diff --git a/src/ch/usi/inf/sp/cfg/ControlFlowGraphBuilder.java b/src/ch/usi/inf/sp/cfg/ControlFlowGraphBuilder.java index 2f3c190..9d040fd 100644 --- a/src/ch/usi/inf/sp/cfg/ControlFlowGraphBuilder.java +++ b/src/ch/usi/inf/sp/cfg/ControlFlowGraphBuilder.java @@ -1,24 +1,139 @@ package ch.usi.inf.sp.cfg; +import ch.usi.inf.sp.bytecode.Disassembler; +import ch.usi.inf.sp.cfg.builder.JumpSource; +import ch.usi.inf.sp.cfg.builder.LookupSwitchInstructionNodeInfo; +import ch.usi.inf.sp.cfg.builder.MultiMap; +import ch.usi.inf.sp.cfg.builder.SwitchInstructionNodeInfo; +import ch.usi.inf.sp.cfg.builder.TableSwitchInstructionNodeInfo; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.tree.*; + import java.util.*; -import ch.usi.inf.sp.bytecode.Disassembler; -import ch.usi.inf.sp.cfg.builder.CFGBuilder; -import ch.usi.inf.sp.cfg.builder.Edge; -import ch.usi.inf.sp.cfg.builder.MultiMap; -import org.objectweb.asm.Opcodes; -import org.objectweb.asm.tree.AbstractInsnNode; -import org.objectweb.asm.tree.InsnList; -import org.objectweb.asm.tree.JumpInsnNode; -import org.objectweb.asm.tree.LabelNode; -import org.objectweb.asm.tree.LookupSwitchInsnNode; -import org.objectweb.asm.tree.MethodNode; -import org.objectweb.asm.tree.TableSwitchInsnNode; +public final class ControlFlowGraphBuilder { + private static final String DEFAULT_LABEL = "default"; + private static final String TRUE_LABEL = "T"; + private final MultiMap labelToIncomingEdges = new MultiMap<>(); + private final List labels = new ArrayList<>(); + private final Map insnToBlock = new HashMap<>(); + private final ControlFlowGraph graph = new ControlFlowGraph(); + private final MethodNode method; + private BasicBlock currentBasicBlock; -public class ControlFlowGraphBuilder { + private ControlFlowGraphBuilder(MethodNode method) { + this.method = method; + setNewBasicBlock(0); + graph.addEntryEdge(currentBasicBlock); + } public static ControlFlowGraph createControlFlowGraph(final MethodNode method) { - return new CFGBuilder(method).create(); + return new ControlFlowGraphBuilder(method).create(); + } + + private void setNewBasicBlock(int id) { + currentBasicBlock = new BasicBlock(id); + graph.addNode(currentBasicBlock); + } + + public ControlFlowGraph create() { + // get the list of all instructions in that method + final InsnList instructions = method.instructions; + for (int i = 0; i < instructions.size(); i++) { + final AbstractInsnNode instruction = instructions.get(i); + + switch (instruction.getType()) { + case AbstractInsnNode.JUMP_INSN -> + labelToIncomingEdges.put(((JumpInsnNode) instruction).label, new JumpSource(instruction, TRUE_LABEL)); + case AbstractInsnNode.LOOKUPSWITCH_INSN -> + captureSwitchEdges(new LookupSwitchInstructionNodeInfo((LookupSwitchInsnNode) instruction)); + case AbstractInsnNode.TABLESWITCH_INSN -> + captureSwitchEdges(new TableSwitchInstructionNodeInfo((TableSwitchInsnNode) instruction)); + } + } + + for (int i = 0; i < instructions.size(); i++) { + final AbstractInsnNode instruction = instructions.get(i); + + currentBasicBlock.appendInstruction(Disassembler.disassembleInstruction(instruction, i, instructions)); + + if (isReturnInstruction(instruction)) { + graph.addExitEdge(currentBasicBlock); + } + + insnToBlock.put(instruction, currentBasicBlock); + + if (isInsnSignificantLabel(instruction)) { + labels.add((LabelNode) instruction); + } + + if (isEndOfBlock(instruction)) { + final BasicBlock previousBasicBlock = currentBasicBlock; + setNewBasicBlock(i + 1); + + // GOTO and SWITCH instructions do not have a fallthrough edge, otherwise add one + if (instruction.getOpcode() != Opcodes.GOTO + && instruction.getType() != AbstractInsnNode.LOOKUPSWITCH_INSN + && instruction.getType() != AbstractInsnNode.TABLESWITCH_INSN) { + graph.addFallthroughEdge(previousBasicBlock, currentBasicBlock); + } + } + } + + for (final LabelNode label : labels) { + final BasicBlock toBB = Objects.requireNonNull(insnToBlock.get(label)); + for (final JumpSource jumpSource : labelToIncomingEdges.getAll(label)) { + final BasicBlock fromBB = jumpSource.block(insnToBlock); + final ControlFlowEdge edge = jumpSource.edge(); + + graph.addEdge(edge); + graph.connect(fromBB, edge, toBB); + } + } + + return graph; + } + + private void captureSwitchEdges(final SwitchInstructionNodeInfo info) { + for (int j = 0; j < info.getCaseCount(); j++) { + final LabelNode label = info.getLabelForCase(j); + final String value = info.getKeyForCase(j); + labelToIncomingEdges.put(label, new JumpSource(info.getNode(), value)); + } + if (info.getDefaultCase() != null) { + labelToIncomingEdges.put(info.getDefaultCase(), new JumpSource(info.getNode(), DEFAULT_LABEL)); + } + } + + private boolean isInsnSignificantLabel(final AbstractInsnNode node) { + return node instanceof LabelNode && labelToIncomingEdges.containsKey((LabelNode) node); + } + + private boolean isReturnInstruction(final AbstractInsnNode instruction) { + final int opcode = instruction.getOpcode(); + return opcode == Opcodes.RETURN || + opcode == Opcodes.ARETURN || + opcode == Opcodes.LRETURN || + opcode == Opcodes.IRETURN || + opcode == Opcodes.FRETURN; + } + + private boolean isEndOfBlock(final AbstractInsnNode instruction) { + final AbstractInsnNode nextInsn = instruction.getNext(); + + if (nextInsn == null) { + return false; // cannot start another bb at the end of the method with 0 instructions + } + + final int type = instruction.getType(); + if (type == AbstractInsnNode.JUMP_INSN || + type == AbstractInsnNode.LOOKUPSWITCH_INSN || + type == AbstractInsnNode.TABLESWITCH_INSN) { + return true; // if we're branching or jumping after this instruction, we NEED to cut the current bb short + } + + // if the next instruction is a label some other bb may jump into then cut, otherwise continue + return isInsnSignificantLabel(nextInsn); } } diff --git a/src/ch/usi/inf/sp/cfg/ControlFlowGraphRenderer.java b/src/ch/usi/inf/sp/cfg/ControlFlowGraphRenderer.java index 4ec24b7..7ee2535 100644 --- a/src/ch/usi/inf/sp/cfg/ControlFlowGraphRenderer.java +++ b/src/ch/usi/inf/sp/cfg/ControlFlowGraphRenderer.java @@ -1,11 +1,66 @@ package ch.usi.inf.sp.cfg; -public class ControlFlowGraphRenderer { +import java.util.stream.Collectors; +import java.util.stream.StreamSupport; - public static String renderControlFlowGraph(final String label, final ControlFlowGraph cfg) { - //TODO - return null; +public class ControlFlowGraphRenderer { + private static final String INDENTATION = " "; + private final StringBuilder code = new StringBuilder(); + private int indentationLevel = 0; + + private static String nodeIdentifier(final BasicBlock bb) { + if (bb.getInEdges().isEmpty()) { + return "e"; + } else if (bb.getOutEdges().isEmpty()) { + return "x"; + } else { + return "bb" + bb.getId(); + } } + private static String nodeStyle(final BasicBlock bb) { + if (bb.getInEdges().isEmpty()) { + return "[shape=circle,label=\"e\"]"; + } else if (bb.getOutEdges().isEmpty()) { + return "[shape=circle,label=\"x\"]"; + } else { + return "[label=\"" + bb.getId() + "|{" + + StreamSupport.stream(bb.getInstructions().spliterator(), false) + .collect(Collectors.joining("|")) + + "}\"]"; + } + } + + public static String renderControlFlowGraph(final String label, final ControlFlowGraph cfg) { + return new ControlFlowGraphRenderer().render(label, cfg); + } + + private void line(String line) { + code.append(INDENTATION.repeat(indentationLevel)).append(line).append('\n'); + } + + private String render(final String label, final ControlFlowGraph graph) { + line("digraph " + label + " {"); + indentationLevel++; + line("label=\"" + label + "\";"); + code.append('\n'); + + line("node [shape=record]"); + for (final BasicBlock bb : graph.getNodes()) { + line(nodeIdentifier(bb) + " " + nodeStyle(bb)); + } + code.append('\n'); + + for (var e : graph.getEdges()) { + final String l = e.getLabel(); + final String suffix = l == null || l.isBlank() ? "" : (" [label=\"" + e.getLabel() + "\"]"); + + line(nodeIdentifier(e.getFrom()) + " -> " + nodeIdentifier(e.getTo()) + suffix); + } + indentationLevel--; + line("}"); + + return code.toString(); + } } diff --git a/src/ch/usi/inf/sp/cfg/builder/CFGBuilder.java b/src/ch/usi/inf/sp/cfg/builder/CFGBuilder.java deleted file mode 100644 index 7622b13..0000000 --- a/src/ch/usi/inf/sp/cfg/builder/CFGBuilder.java +++ /dev/null @@ -1,134 +0,0 @@ -package ch.usi.inf.sp.cfg.builder; - -import ch.usi.inf.sp.bytecode.Disassembler; -import ch.usi.inf.sp.cfg.BasicBlock; -import ch.usi.inf.sp.cfg.ControlFlowEdge; -import ch.usi.inf.sp.cfg.ControlFlowGraph; -import org.objectweb.asm.Opcodes; -import org.objectweb.asm.tree.*; - -import java.util.*; - -public final class CFGBuilder { - private final MultiMap labelToIncomingEdges = new MultiMap<>(); - private final List labels = new ArrayList<>(); - private final Map insnToBlock = new HashMap<>(); - - private final ControlFlowGraph graph = new ControlFlowGraph(); - private final MethodNode method; - private BasicBlock currentBasicBlock; - - public CFGBuilder(MethodNode method) { - this.method = method; - setNewBasicBlock(0); - graph.addEntryEdge(currentBasicBlock); - } - - private void setNewBasicBlock(int id) { - currentBasicBlock = new BasicBlock(id); - graph.addNode(currentBasicBlock); - } - - public ControlFlowGraph create() { - // get the list of all instructions in that method - final InsnList instructions = method.instructions; - for (int i = 0; i < instructions.size(); i++) { - final AbstractInsnNode instruction = instructions.get(i); - - switch (instruction.getType()) { - case AbstractInsnNode.JUMP_INSN -> labelToIncomingEdges.put( - ((JumpInsnNode) instruction).label, - new Edge(instruction, "T") - ); - case AbstractInsnNode.LOOKUPSWITCH_INSN -> - captureSwitchEdges(new LookupSwitchInstructionNodeInfo((LookupSwitchInsnNode) instruction)); - case AbstractInsnNode.TABLESWITCH_INSN -> - captureSwitchEdges(new TableSwitchInstructionNodeInfo((TableSwitchInsnNode) instruction)); - } - } - - for (int i = 0; i < instructions.size(); i++) { - final AbstractInsnNode instruction = instructions.get(i); - - currentBasicBlock.appendInstruction(Disassembler.disassembleInstruction(instruction, i, instructions)); - - if (isReturnInstruction(instruction)) { - graph.addExitEdge(currentBasicBlock); - } - - insnToBlock.put(instruction, currentBasicBlock); - - if (isInsnSignificantLabel(instruction)) { - labels.add((LabelNode) instruction); - } - - if (isEndOfBlock(instruction)) { - final int nextI = i + 1; - - final BasicBlock previousBasicBlock = currentBasicBlock; - setNewBasicBlock(nextI); - - // Handle "implicit" edges from this basic block to the next one, or the exit node - if (instructions.get(nextI).getOpcode() != Opcodes.GOTO) { - graph.addFallthroughEdge(previousBasicBlock, currentBasicBlock); - } - } - } - - for (final LabelNode label : labels) { - final BasicBlock toBB = Objects.requireNonNull(insnToBlock.get(label)); - for (final ch.usi.inf.sp.cfg.builder.Edge incomingEdge : labelToIncomingEdges.getAll(label)) { - final BasicBlock fromBB = Objects.requireNonNull(insnToBlock.get(incomingEdge.instruction())); - - final ControlFlowEdge edge = new ControlFlowEdge(incomingEdge.condition()); - graph.addEdge(edge); - graph.connect(fromBB, edge, toBB); - } - } - - return graph; - } - - - private void captureSwitchEdges(final SwitchInstructionNodeInfo info) { - for (int j = 0; j < info.getCaseCount(); j++) { - final LabelNode label = info.getLabelForCase(j); - final String value = info.getKeyForCase(j); - labelToIncomingEdges.put(label, new Edge(info.getNode(), value)); - } - if (info.getDefaultCase() != null) { - labelToIncomingEdges.put(info.getDefaultCase(), new Edge(info.getNode(), "default")); - } - } - - private boolean isInsnSignificantLabel(final AbstractInsnNode node) { - return node instanceof LabelNode && labelToIncomingEdges.containsKey((LabelNode) node); - } - - private boolean isReturnInstruction(final AbstractInsnNode instruction) { - final int opcode = instruction.getOpcode(); - return opcode == Opcodes.RETURN || - opcode == Opcodes.ARETURN || - opcode == Opcodes.LRETURN || - opcode == Opcodes.IRETURN || - opcode == Opcodes.FRETURN; - } - - private boolean isEndOfBlock(final AbstractInsnNode instruction) { - final AbstractInsnNode nextInsn = instruction.getNext(); - - if (nextInsn == null) { - return false; // cannot start another bb at the end of the method with 0 instructions - } - - final int type = instruction.getType(); - if (type == AbstractInsnNode.JUMP_INSN || - type == AbstractInsnNode.LOOKUPSWITCH_INSN || - type == AbstractInsnNode.TABLESWITCH_INSN) { - return true; // if we're branching or jumping after this instruction, we NEED to cut the current bb short - } - - // if the next instruction is a label some other bb may jump into then cut, otherwise continue - return isInsnSignificantLabel(nextInsn); - } -} diff --git a/src/ch/usi/inf/sp/cfg/builder/Edge.java b/src/ch/usi/inf/sp/cfg/builder/Edge.java deleted file mode 100644 index 5602d66..0000000 --- a/src/ch/usi/inf/sp/cfg/builder/Edge.java +++ /dev/null @@ -1,6 +0,0 @@ -package ch.usi.inf.sp.cfg.builder; - -import org.objectweb.asm.tree.AbstractInsnNode; - -public record Edge(AbstractInsnNode instruction, String condition) { -} diff --git a/src/ch/usi/inf/sp/cfg/builder/JumpSource.java b/src/ch/usi/inf/sp/cfg/builder/JumpSource.java new file mode 100644 index 0000000..ad23ab4 --- /dev/null +++ b/src/ch/usi/inf/sp/cfg/builder/JumpSource.java @@ -0,0 +1,19 @@ +package ch.usi.inf.sp.cfg.builder; + +import ch.usi.inf.sp.cfg.BasicBlock; +import ch.usi.inf.sp.cfg.ControlFlowEdge; +import org.objectweb.asm.tree.AbstractInsnNode; + +import java.util.Map; +import java.util.Objects; + +public record JumpSource(AbstractInsnNode instruction, String condition) { + + public BasicBlock block(Map insnToBlock) { + return Objects.requireNonNull(insnToBlock.get(this.instruction)); + } + + public ControlFlowEdge edge() { + return new ControlFlowEdge(this.condition); + } +} diff --git a/test-output/.dot b/test-output/.dot index e69de29..767c1ca 100644 --- a/test-output/.dot +++ b/test-output/.dot @@ -0,0 +1,11 @@ +digraph { + label=""; + + node [shape=record] + e [shape=circle,label="e"] + x [shape=circle,label="x"] + bb0 [label="0|{0: // label|1: // line number information|2: ALOAD 0|3: INVOKESPECIAL java/lang/Object. ()V|4: RETURN }"] + + e -> bb0 + bb0 -> x +} diff --git a/test-output/all.pdf b/test-output/all.pdf new file mode 100644 index 0000000..8491671 Binary files /dev/null and b/test-output/all.pdf differ diff --git a/test-output/alloc2Of3dArrayMethod.dot b/test-output/alloc2Of3dArrayMethod.dot new file mode 100644 index 0000000..671d54e --- /dev/null +++ b/test-output/alloc2Of3dArrayMethod.dot @@ -0,0 +1,11 @@ +digraph alloc2Of3dArrayMethod { + label="alloc2Of3dArrayMethod"; + + node [shape=record] + e [shape=circle,label="e"] + x [shape=circle,label="x"] + bb0 [label="0|{0: // label|1: // line number information|2: ICONST_2 |3: ICONST_3 |4: MULTIANEWARRAY [[[I 2|5: ARETURN }"] + + e -> bb0 + bb0 -> x +} diff --git a/test-output/alloc2dArrayMethod.dot b/test-output/alloc2dArrayMethod.dot new file mode 100644 index 0000000..fd4494e --- /dev/null +++ b/test-output/alloc2dArrayMethod.dot @@ -0,0 +1,11 @@ +digraph alloc2dArrayMethod { + label="alloc2dArrayMethod"; + + node [shape=record] + e [shape=circle,label="e"] + x [shape=circle,label="x"] + bb0 [label="0|{0: // label|1: // line number information|2: ICONST_2 |3: ICONST_3 |4: MULTIANEWARRAY [[I 2|5: ARETURN }"] + + e -> bb0 + bb0 -> x +} diff --git a/test-output/allocAndInit2dArrayMethod.dot b/test-output/allocAndInit2dArrayMethod.dot new file mode 100644 index 0000000..8eec586 --- /dev/null +++ b/test-output/allocAndInit2dArrayMethod.dot @@ -0,0 +1,11 @@ +digraph allocAndInit2dArrayMethod { + label="allocAndInit2dArrayMethod"; + + node [shape=record] + e [shape=circle,label="e"] + x [shape=circle,label="x"] + bb0 [label="0|{0: // label|1: // line number information|2: ICONST_1 |3: ANEWARRAY [I|4: DUP |5: ICONST_0 |6: ICONST_1 |7: NEWARRAY T_INT|8: DUP |9: ICONST_0 |10: ICONST_1 |11: IASTORE |12: AASTORE |13: ARETURN }"] + + e -> bb0 + bb0 -> x +} diff --git a/test-output/allocAndInitIntArrayMethod.dot b/test-output/allocAndInitIntArrayMethod.dot new file mode 100644 index 0000000..7cff1b5 --- /dev/null +++ b/test-output/allocAndInitIntArrayMethod.dot @@ -0,0 +1,11 @@ +digraph allocAndInitIntArrayMethod { + label="allocAndInitIntArrayMethod"; + + node [shape=record] + e [shape=circle,label="e"] + x [shape=circle,label="x"] + bb0 [label="0|{0: // label|1: // line number information|2: ICONST_2 |3: NEWARRAY T_INT|4: DUP |5: ICONST_0 |6: ICONST_1 |7: IASTORE |8: DUP |9: ICONST_1 |10: ICONST_2 |11: IASTORE |12: ARETURN }"] + + e -> bb0 + bb0 -> x +} diff --git a/test-output/allocAndInitObjectArrayMethod.dot b/test-output/allocAndInitObjectArrayMethod.dot new file mode 100644 index 0000000..7e66631 --- /dev/null +++ b/test-output/allocAndInitObjectArrayMethod.dot @@ -0,0 +1,11 @@ +digraph allocAndInitObjectArrayMethod { + label="allocAndInitObjectArrayMethod"; + + node [shape=record] + e [shape=circle,label="e"] + x [shape=circle,label="x"] + bb0 [label="0|{0: // label|1: // line number information|2: ICONST_2 |3: ANEWARRAY java/lang/Object|4: DUP |5: ICONST_0 |6: LDC 1|7: AASTORE |8: DUP |9: ICONST_1 |10: LDC 2|11: AASTORE |12: ARETURN }"] + + e -> bb0 + bb0 -> x +} diff --git a/test-output/allocIncomplete2dArrayMethod.dot b/test-output/allocIncomplete2dArrayMethod.dot new file mode 100644 index 0000000..4be865e --- /dev/null +++ b/test-output/allocIncomplete2dArrayMethod.dot @@ -0,0 +1,11 @@ +digraph allocIncomplete2dArrayMethod { + label="allocIncomplete2dArrayMethod"; + + node [shape=record] + e [shape=circle,label="e"] + x [shape=circle,label="x"] + bb0 [label="0|{0: // label|1: // line number information|2: ICONST_2 |3: ANEWARRAY [I|4: ARETURN }"] + + e -> bb0 + bb0 -> x +} diff --git a/test-output/allocIntArrayMethod.dot b/test-output/allocIntArrayMethod.dot new file mode 100644 index 0000000..3870d39 --- /dev/null +++ b/test-output/allocIntArrayMethod.dot @@ -0,0 +1,11 @@ +digraph allocIntArrayMethod { + label="allocIntArrayMethod"; + + node [shape=record] + e [shape=circle,label="e"] + x [shape=circle,label="x"] + bb0 [label="0|{0: // label|1: // line number information|2: ICONST_3 |3: NEWARRAY T_INT|4: ARETURN }"] + + e -> bb0 + bb0 -> x +} diff --git a/test-output/allocObjectArrayMethod.dot b/test-output/allocObjectArrayMethod.dot new file mode 100644 index 0000000..4339049 --- /dev/null +++ b/test-output/allocObjectArrayMethod.dot @@ -0,0 +1,11 @@ +digraph allocObjectArrayMethod { + label="allocObjectArrayMethod"; + + node [shape=record] + e [shape=circle,label="e"] + x [shape=circle,label="x"] + bb0 [label="0|{0: // label|1: // line number information|2: ICONST_3 |3: ANEWARRAY java/lang/Object|4: ARETURN }"] + + e -> bb0 + bb0 -> x +} diff --git a/test-output/allocObjectMethod.dot b/test-output/allocObjectMethod.dot new file mode 100644 index 0000000..3362c01 --- /dev/null +++ b/test-output/allocObjectMethod.dot @@ -0,0 +1,11 @@ +digraph allocObjectMethod { + label="allocObjectMethod"; + + node [shape=record] + e [shape=circle,label="e"] + x [shape=circle,label="x"] + bb0 [label="0|{0: // label|1: // line number information|2: NEW java/lang/Object|3: DUP |4: INVOKESPECIAL java/lang/Object. ()V|5: ARETURN }"] + + e -> bb0 + bb0 -> x +} diff --git a/test-output/arrayLengthMethod.dot b/test-output/arrayLengthMethod.dot new file mode 100644 index 0000000..db26714 --- /dev/null +++ b/test-output/arrayLengthMethod.dot @@ -0,0 +1,11 @@ +digraph arrayLengthMethod { + label="arrayLengthMethod"; + + node [shape=record] + e [shape=circle,label="e"] + x [shape=circle,label="x"] + bb0 [label="0|{0: // label|1: // line number information|2: ALOAD 1|3: ARRAYLENGTH |4: IRETURN }"] + + e -> bb0 + bb0 -> x +} diff --git a/test-output/arrayReadMethod.dot b/test-output/arrayReadMethod.dot new file mode 100644 index 0000000..28fc7c6 --- /dev/null +++ b/test-output/arrayReadMethod.dot @@ -0,0 +1,11 @@ +digraph arrayReadMethod { + label="arrayReadMethod"; + + node [shape=record] + e [shape=circle,label="e"] + x [shape=circle,label="x"] + bb0 [label="0|{0: // label|1: // line number information|2: ALOAD 1|3: ICONST_0 |4: AALOAD |5: ARETURN }"] + + e -> bb0 + bb0 -> x +} diff --git a/test-output/arrayWriteMethod.dot b/test-output/arrayWriteMethod.dot new file mode 100644 index 0000000..59de2a0 --- /dev/null +++ b/test-output/arrayWriteMethod.dot @@ -0,0 +1,11 @@ +digraph arrayWriteMethod { + label="arrayWriteMethod"; + + node [shape=record] + e [shape=circle,label="e"] + x [shape=circle,label="x"] + bb0 [label="0|{0: // label|1: // line number information|2: ALOAD 1|3: ICONST_0 |4: ALOAD 2|5: AASTORE |6: // label|7: // line number information|8: RETURN }"] + + e -> bb0 + bb0 -> x +} diff --git a/test-output/condMethod.dot b/test-output/condMethod.dot new file mode 100644 index 0000000..40ec62b --- /dev/null +++ b/test-output/condMethod.dot @@ -0,0 +1,18 @@ +digraph condMethod { + label="condMethod"; + + node [shape=record] + e [shape=circle,label="e"] + x [shape=circle,label="x"] + bb0 [label="0|{0: // label|1: // line number information|2: ILOAD 1|3: ILOAD 2|4: IF_ICMPLE 7}"] + bb5 [label="5|{5: ILOAD 1|6: GOTO 10}"] + bb7 [label="7|{7: // label|8: // stack frame map|9: ILOAD 2}"] + bb10 [label="10|{10: // label|11: // stack frame map|12: IRETURN }"] + + e -> bb0 + bb0 -> bb5 + bb7 -> bb10 + bb10 -> x + bb0 -> bb7 [label="T"] + bb5 -> bb10 [label="T"] +} diff --git a/test-output/doWhileMethod.dot b/test-output/doWhileMethod.dot new file mode 100644 index 0000000..eefa2c0 --- /dev/null +++ b/test-output/doWhileMethod.dot @@ -0,0 +1,16 @@ +digraph doWhileMethod { + label="doWhileMethod"; + + node [shape=record] + e [shape=circle,label="e"] + x [shape=circle,label="x"] + bb0 [label="0|{0: // label|1: // line number information|2: ICONST_0 |3: ISTORE 2}"] + bb4 [label="4|{4: // label|5: // line number information|6: // stack frame map|7: ILOAD 2|8: ILOAD 1|9: IADD |10: ISTORE 2|11: // label|12: // line number information|13: IINC 1 -1|14: // label|15: // line number information|16: ILOAD 1|17: IFGT 4}"] + bb18 [label="18|{18: // label|19: // line number information|20: ILOAD 2|21: IRETURN }"] + + e -> bb0 + bb0 -> bb4 + bb4 -> bb18 + bb18 -> x + bb4 -> bb4 [label="T"] +} diff --git a/test-output/doWhileTrue.dot b/test-output/doWhileTrue.dot new file mode 100644 index 0000000..91220c1 --- /dev/null +++ b/test-output/doWhileTrue.dot @@ -0,0 +1,11 @@ +digraph doWhileTrue { + label="doWhileTrue"; + + node [shape=record] + e [shape=circle,label="e"] + e [shape=circle,label="e"] + bb0 [label="0|{0: // label|1: // line number information|2: // stack frame map|3: IINC 1 1|4: // label|5: // line number information|6: GOTO 0}"] + + e -> bb0 + bb0 -> bb0 [label="T"] +} diff --git a/test-output/emptyMethod.dot b/test-output/emptyMethod.dot new file mode 100644 index 0000000..b85c7b2 --- /dev/null +++ b/test-output/emptyMethod.dot @@ -0,0 +1,11 @@ +digraph emptyMethod { + label="emptyMethod"; + + node [shape=record] + e [shape=circle,label="e"] + x [shape=circle,label="x"] + bb0 [label="0|{0: // label|1: // line number information|2: RETURN }"] + + e -> bb0 + bb0 -> x +} diff --git a/test-output/fieldReadMethod.dot b/test-output/fieldReadMethod.dot new file mode 100644 index 0000000..fbdde10 --- /dev/null +++ b/test-output/fieldReadMethod.dot @@ -0,0 +1,11 @@ +digraph fieldReadMethod { + label="fieldReadMethod"; + + node [shape=record] + e [shape=circle,label="e"] + x [shape=circle,label="x"] + bb0 [label="0|{0: // label|1: // line number information|2: ALOAD 0|3: GETFIELD ExampleClass.field Ljava/lang/String;|4: ARETURN }"] + + e -> bb0 + bb0 -> x +} diff --git a/test-output/fieldWriteMethod.dot b/test-output/fieldWriteMethod.dot new file mode 100644 index 0000000..21da341 --- /dev/null +++ b/test-output/fieldWriteMethod.dot @@ -0,0 +1,11 @@ +digraph fieldWriteMethod { + label="fieldWriteMethod"; + + node [shape=record] + e [shape=circle,label="e"] + x [shape=circle,label="x"] + bb0 [label="0|{0: // label|1: // line number information|2: ALOAD 0|3: ALOAD 1|4: PUTFIELD ExampleClass.field Ljava/lang/String;|5: // label|6: // line number information|7: RETURN }"] + + e -> bb0 + bb0 -> x +} diff --git a/test-output/forEachArrayMethod.dot b/test-output/forEachArrayMethod.dot new file mode 100644 index 0000000..7cb1489 --- /dev/null +++ b/test-output/forEachArrayMethod.dot @@ -0,0 +1,18 @@ +digraph forEachArrayMethod { + label="forEachArrayMethod"; + + node [shape=record] + e [shape=circle,label="e"] + x [shape=circle,label="x"] + bb0 [label="0|{0: // label|1: // line number information|2: ICONST_0 |3: ISTORE 2|4: // label|5: // line number information|6: ALOAD 1|7: ASTORE 3|8: ALOAD 3|9: ARRAYLENGTH |10: ISTORE 4|11: ICONST_0 |12: ISTORE 5}"] + bb13 [label="13|{13: // label|14: // stack frame map|15: ILOAD 5|16: ILOAD 4|17: IF_ICMPGE 29}"] + bb18 [label="18|{18: ALOAD 3|19: ILOAD 5|20: AALOAD |21: ASTORE 6|22: // label|23: // line number information|24: IINC 2 1|25: // label|26: // line number information|27: IINC 5 1|28: GOTO 13}"] + bb29 [label="29|{29: // label|30: // line number information|31: // stack frame map|32: ILOAD 2|33: IRETURN }"] + + e -> bb0 + bb0 -> bb13 + bb13 -> bb18 + bb29 -> x + bb18 -> bb13 [label="T"] + bb13 -> bb29 [label="T"] +} diff --git a/test-output/forEachCollectionMethod.dot b/test-output/forEachCollectionMethod.dot new file mode 100644 index 0000000..cf91a87 --- /dev/null +++ b/test-output/forEachCollectionMethod.dot @@ -0,0 +1,18 @@ +digraph forEachCollectionMethod { + label="forEachCollectionMethod"; + + node [shape=record] + e [shape=circle,label="e"] + x [shape=circle,label="x"] + bb0 [label="0|{0: // label|1: // line number information|2: ICONST_0 |3: ISTORE 2|4: // label|5: // line number information|6: ALOAD 1|7: INVOKEINTERFACE java/util/Set.iterator ()Ljava/util/Iterator;|8: ASTORE 3}"] + bb9 [label="9|{9: // label|10: // stack frame map|11: ALOAD 3|12: INVOKEINTERFACE java/util/Iterator.hasNext ()Z|13: IFEQ 24}"] + bb14 [label="14|{14: ALOAD 3|15: INVOKEINTERFACE java/util/Iterator.next ()Ljava/lang/Object;|16: CHECKCAST java/lang/String|17: ASTORE 4|18: // label|19: // line number information|20: IINC 2 1|21: // label|22: // line number information|23: GOTO 9}"] + bb24 [label="24|{24: // label|25: // line number information|26: // stack frame map|27: ILOAD 2|28: IRETURN }"] + + e -> bb0 + bb0 -> bb9 + bb9 -> bb14 + bb24 -> x + bb14 -> bb9 [label="T"] + bb9 -> bb24 [label="T"] +} diff --git a/test-output/forEver.dot b/test-output/forEver.dot new file mode 100644 index 0000000..e517f58 --- /dev/null +++ b/test-output/forEver.dot @@ -0,0 +1,13 @@ +digraph forEver { + label="forEver"; + + node [shape=record] + e [shape=circle,label="e"] + e [shape=circle,label="e"] + bb0 [label="0|{0: // label|1: // line number information|2: ICONST_0 |3: ISTORE 2}"] + bb4 [label="4|{4: // label|5: // stack frame map|6: IINC 2 1|7: GOTO 4}"] + + e -> bb0 + bb0 -> bb4 + bb4 -> bb4 [label="T"] +} diff --git a/test-output/forMethod.dot b/test-output/forMethod.dot new file mode 100644 index 0000000..6233028 --- /dev/null +++ b/test-output/forMethod.dot @@ -0,0 +1,18 @@ +digraph forMethod { + label="forMethod"; + + node [shape=record] + e [shape=circle,label="e"] + x [shape=circle,label="x"] + bb0 [label="0|{0: // label|1: // line number information|2: ICONST_0 |3: ISTORE 2|4: // label|5: // line number information|6: ICONST_0 |7: ISTORE 3}"] + bb8 [label="8|{8: // label|9: // stack frame map|10: ILOAD 3|11: ILOAD 1|12: IF_ICMPGE 23}"] + bb13 [label="13|{13: // label|14: // line number information|15: ILOAD 2|16: ILOAD 3|17: IADD |18: ISTORE 2|19: // label|20: // line number information|21: IINC 1 1|22: GOTO 8}"] + bb23 [label="23|{23: // label|24: // line number information|25: // stack frame map|26: ILOAD 2|27: IRETURN }"] + + e -> bb0 + bb0 -> bb8 + bb8 -> bb13 + bb23 -> x + bb13 -> bb8 [label="T"] + bb8 -> bb23 [label="T"] +} diff --git a/test-output/forWithBreakMethod.dot b/test-output/forWithBreakMethod.dot new file mode 100644 index 0000000..349f0ce --- /dev/null +++ b/test-output/forWithBreakMethod.dot @@ -0,0 +1,23 @@ +digraph forWithBreakMethod { + label="forWithBreakMethod"; + + node [shape=record] + e [shape=circle,label="e"] + x [shape=circle,label="x"] + bb0 [label="0|{0: // label|1: // line number information|2: ICONST_0 |3: ISTORE 2|4: // label|5: // line number information|6: ICONST_0 |7: ISTORE 3}"] + bb8 [label="8|{8: // label|9: // stack frame map|10: ILOAD 3|11: ILOAD 1|12: IF_ICMPGE 32}"] + bb13 [label="13|{13: // label|14: // line number information|15: ILOAD 3|16: BIPUSH 10|17: IF_ICMPNE 21}"] + bb18 [label="18|{18: // label|19: // line number information|20: GOTO 32}"] + bb21 [label="21|{21: // label|22: // line number information|23: // stack frame map|24: ILOAD 2|25: ILOAD 3|26: IADD |27: ISTORE 2|28: // label|29: // line number information|30: IINC 3 1|31: GOTO 8}"] + bb32 [label="32|{32: // label|33: // line number information|34: // stack frame map|35: ILOAD 2|36: IRETURN }"] + + e -> bb0 + bb0 -> bb8 + bb8 -> bb13 + bb13 -> bb18 + bb32 -> x + bb21 -> bb8 [label="T"] + bb13 -> bb21 [label="T"] + bb8 -> bb32 [label="T"] + bb18 -> bb32 [label="T"] +} diff --git a/test-output/forWithContinueMethod.dot b/test-output/forWithContinueMethod.dot new file mode 100644 index 0000000..245949a --- /dev/null +++ b/test-output/forWithContinueMethod.dot @@ -0,0 +1,25 @@ +digraph forWithContinueMethod { + label="forWithContinueMethod"; + + node [shape=record] + e [shape=circle,label="e"] + x [shape=circle,label="x"] + bb0 [label="0|{0: // label|1: // line number information|2: ICONST_0 |3: ISTORE 2|4: // label|5: // line number information|6: ICONST_0 |7: ISTORE 3}"] + bb8 [label="8|{8: // label|9: // stack frame map|10: ILOAD 3|11: ILOAD 1|12: IF_ICMPGE 33}"] + bb13 [label="13|{13: // label|14: // line number information|15: ILOAD 3|16: BIPUSH 10|17: IF_ICMPNE 21}"] + bb18 [label="18|{18: // label|19: // line number information|20: GOTO 28}"] + bb21 [label="21|{21: // label|22: // line number information|23: // stack frame map|24: ILOAD 2|25: ILOAD 3|26: IADD |27: ISTORE 2}"] + bb28 [label="28|{28: // label|29: // line number information|30: // stack frame map|31: IINC 3 1|32: GOTO 8}"] + bb33 [label="33|{33: // label|34: // line number information|35: // stack frame map|36: ILOAD 2|37: IRETURN }"] + + e -> bb0 + bb0 -> bb8 + bb8 -> bb13 + bb13 -> bb18 + bb21 -> bb28 + bb33 -> x + bb28 -> bb8 [label="T"] + bb13 -> bb21 [label="T"] + bb18 -> bb28 [label="T"] + bb8 -> bb33 [label="T"] +} diff --git a/test-output/ifElseMethod.dot b/test-output/ifElseMethod.dot new file mode 100644 index 0000000..2385f04 --- /dev/null +++ b/test-output/ifElseMethod.dot @@ -0,0 +1,18 @@ +digraph ifElseMethod { + label="ifElseMethod"; + + node [shape=record] + e [shape=circle,label="e"] + x [shape=circle,label="x"] + bb0 [label="0|{0: // label|1: // line number information|2: ICONST_0 |3: ISTORE 2|4: // label|5: // line number information|6: ILOAD 1|7: IFLE 13}"] + bb8 [label="8|{8: // label|9: // line number information|10: ICONST_0 |11: ISTORE 2|12: GOTO 18}"] + bb13 [label="13|{13: // label|14: // line number information|15: // stack frame map|16: ILOAD 1|17: ISTORE 2}"] + bb18 [label="18|{18: // label|19: // line number information|20: // stack frame map|21: ILOAD 2|22: IRETURN }"] + + e -> bb0 + bb0 -> bb8 + bb13 -> bb18 + bb18 -> x + bb0 -> bb13 [label="T"] + bb8 -> bb18 [label="T"] +} diff --git a/test-output/ifMethod.dot b/test-output/ifMethod.dot new file mode 100644 index 0000000..40e0e82 --- /dev/null +++ b/test-output/ifMethod.dot @@ -0,0 +1,16 @@ +digraph ifMethod { + label="ifMethod"; + + node [shape=record] + e [shape=circle,label="e"] + x [shape=circle,label="x"] + bb0 [label="0|{0: // label|1: // line number information|2: ICONST_0 |3: ISTORE 2|4: // label|5: // line number information|6: ILOAD 1|7: IFGE 12}"] + bb8 [label="8|{8: // label|9: // line number information|10: ICONST_1 |11: ISTORE 2}"] + bb12 [label="12|{12: // label|13: // line number information|14: // stack frame map|15: ILOAD 2|16: IRETURN }"] + + e -> bb0 + bb0 -> bb8 + bb8 -> bb12 + bb12 -> x + bb0 -> bb12 [label="T"] +} diff --git a/test-output/instanceCallMethod.dot b/test-output/instanceCallMethod.dot new file mode 100644 index 0000000..3d534f2 --- /dev/null +++ b/test-output/instanceCallMethod.dot @@ -0,0 +1,11 @@ +digraph instanceCallMethod { + label="instanceCallMethod"; + + node [shape=record] + e [shape=circle,label="e"] + x [shape=circle,label="x"] + bb0 [label="0|{0: // label|1: // line number information|2: ALOAD 1|3: INVOKEVIRTUAL ExampleClass.instanceCallTarget ()V|4: // label|5: // line number information|6: ICONST_2 |7: IRETURN }"] + + e -> bb0 + bb0 -> x +} diff --git a/test-output/instanceCallTarget.dot b/test-output/instanceCallTarget.dot new file mode 100644 index 0000000..b190488 --- /dev/null +++ b/test-output/instanceCallTarget.dot @@ -0,0 +1,11 @@ +digraph instanceCallTarget { + label="instanceCallTarget"; + + node [shape=record] + e [shape=circle,label="e"] + x [shape=circle,label="x"] + bb0 [label="0|{0: // label|1: // line number information|2: RETURN }"] + + e -> bb0 + bb0 -> x +} diff --git a/test-output/interfaceCallMethod.dot b/test-output/interfaceCallMethod.dot new file mode 100644 index 0000000..ea008b2 --- /dev/null +++ b/test-output/interfaceCallMethod.dot @@ -0,0 +1,11 @@ +digraph interfaceCallMethod { + label="interfaceCallMethod"; + + node [shape=record] + e [shape=circle,label="e"] + x [shape=circle,label="x"] + bb0 [label="0|{0: // label|1: // line number information|2: ALOAD 1|3: INVOKEINTERFACE ExampleClass$Interface.interfaceCallTarget ()V|4: // label|5: // line number information|6: ICONST_2 |7: IRETURN }"] + + e -> bb0 + bb0 -> x +} diff --git a/test-output/nestedFor.dot b/test-output/nestedFor.dot new file mode 100644 index 0000000..44fc2d3 --- /dev/null +++ b/test-output/nestedFor.dot @@ -0,0 +1,25 @@ +digraph nestedFor { + label="nestedFor"; + + node [shape=record] + e [shape=circle,label="e"] + x [shape=circle,label="x"] + bb0 [label="0|{0: // label|1: // line number information|2: ICONST_0 |3: ISTORE 2|4: // label|5: // line number information|6: ICONST_0 |7: ISTORE 3}"] + bb8 [label="8|{8: // label|9: // stack frame map|10: ILOAD 3|11: ILOAD 1|12: IF_ICMPGE 37}"] + bb13 [label="13|{13: // label|14: // line number information|15: ICONST_0 |16: ISTORE 4}"] + bb17 [label="17|{17: // label|18: // stack frame map|19: ILOAD 4|20: ILOAD 3|21: IF_ICMPGE 32}"] + bb22 [label="22|{22: // label|23: // line number information|24: ILOAD 2|25: ILOAD 4|26: IADD |27: ISTORE 2|28: // label|29: // line number information|30: IINC 4 1|31: GOTO 17}"] + bb32 [label="32|{32: // label|33: // line number information|34: // stack frame map|35: IINC 3 1|36: GOTO 8}"] + bb37 [label="37|{37: // label|38: // line number information|39: // stack frame map|40: ILOAD 2|41: IRETURN }"] + + e -> bb0 + bb0 -> bb8 + bb8 -> bb13 + bb13 -> bb17 + bb17 -> bb22 + bb37 -> x + bb32 -> bb8 [label="T"] + bb22 -> bb17 [label="T"] + bb17 -> bb32 [label="T"] + bb8 -> bb37 [label="T"] +} diff --git a/test-output/nonShortCircuitMethod.dot b/test-output/nonShortCircuitMethod.dot new file mode 100644 index 0000000..cc42448 --- /dev/null +++ b/test-output/nonShortCircuitMethod.dot @@ -0,0 +1,31 @@ +digraph nonShortCircuitMethod { + label="nonShortCircuitMethod"; + + node [shape=record] + e [shape=circle,label="e"] + x [shape=circle,label="x"] + bb0 [label="0|{0: // label|1: // line number information|2: ILOAD 1|3: ILOAD 2|4: IF_ICMPLE 7}"] + bb5 [label="5|{5: ICONST_1 |6: GOTO 10}"] + bb7 [label="7|{7: // label|8: // stack frame map|9: ICONST_0 }"] + bb10 [label="10|{10: // label|11: // stack frame map|12: ILOAD 1|13: ILOAD 3|14: IF_ICMPGE 17}"] + bb15 [label="15|{15: ICONST_1 |16: GOTO 20}"] + bb17 [label="17|{17: // label|18: // stack frame map|19: ICONST_0 }"] + bb20 [label="20|{20: // label|21: // stack frame map|22: IAND |23: IFEQ 28}"] + bb24 [label="24|{24: // label|25: // line number information|26: ICONST_1 |27: IRETURN }"] + bb28 [label="28|{28: // label|29: // line number information|30: // stack frame map|31: ICONST_0 |32: IRETURN }"] + + e -> bb0 + bb0 -> bb5 + bb7 -> bb10 + bb10 -> bb15 + bb17 -> bb20 + bb20 -> bb24 + bb24 -> x + bb24 -> bb28 + bb28 -> x + bb0 -> bb7 [label="T"] + bb5 -> bb10 [label="T"] + bb10 -> bb17 [label="T"] + bb15 -> bb20 [label="T"] + bb20 -> bb28 [label="T"] +} diff --git a/test-output/privateInstanceCallMethod.dot b/test-output/privateInstanceCallMethod.dot new file mode 100644 index 0000000..a02673c --- /dev/null +++ b/test-output/privateInstanceCallMethod.dot @@ -0,0 +1,11 @@ +digraph privateInstanceCallMethod { + label="privateInstanceCallMethod"; + + node [shape=record] + e [shape=circle,label="e"] + x [shape=circle,label="x"] + bb0 [label="0|{0: // label|1: // line number information|2: ALOAD 1|3: INVOKESPECIAL ExampleClass.privateInstanceCallTarget ()V|4: // label|5: // line number information|6: ICONST_2 |7: IRETURN }"] + + e -> bb0 + bb0 -> x +} diff --git a/test-output/privateInstanceCallTarget.dot b/test-output/privateInstanceCallTarget.dot new file mode 100644 index 0000000..058ef84 --- /dev/null +++ b/test-output/privateInstanceCallTarget.dot @@ -0,0 +1,11 @@ +digraph privateInstanceCallTarget { + label="privateInstanceCallTarget"; + + node [shape=record] + e [shape=circle,label="e"] + x [shape=circle,label="x"] + bb0 [label="0|{0: // label|1: // line number information|2: RETURN }"] + + e -> bb0 + bb0 -> x +} diff --git a/test-output/shortCircuitMethod.dot b/test-output/shortCircuitMethod.dot new file mode 100644 index 0000000..3d84edb --- /dev/null +++ b/test-output/shortCircuitMethod.dot @@ -0,0 +1,20 @@ +digraph shortCircuitMethod { + label="shortCircuitMethod"; + + node [shape=record] + e [shape=circle,label="e"] + x [shape=circle,label="x"] + bb0 [label="0|{0: // label|1: // line number information|2: ILOAD 1|3: ILOAD 2|4: IF_ICMPLE 12}"] + bb5 [label="5|{5: ILOAD 1|6: ILOAD 3|7: IF_ICMPGE 12}"] + bb8 [label="8|{8: // label|9: // line number information|10: ICONST_1 |11: IRETURN }"] + bb12 [label="12|{12: // label|13: // line number information|14: // stack frame map|15: ICONST_0 |16: IRETURN }"] + + e -> bb0 + bb0 -> bb5 + bb5 -> bb8 + bb8 -> x + bb8 -> bb12 + bb12 -> x + bb0 -> bb12 [label="T"] + bb5 -> bb12 [label="T"] +} diff --git a/test-output/staticCallMethod.dot b/test-output/staticCallMethod.dot new file mode 100644 index 0000000..b004502 --- /dev/null +++ b/test-output/staticCallMethod.dot @@ -0,0 +1,11 @@ +digraph staticCallMethod { + label="staticCallMethod"; + + node [shape=record] + e [shape=circle,label="e"] + x [shape=circle,label="x"] + bb0 [label="0|{0: // label|1: // line number information|2: INVOKESTATIC ExampleClass.staticCallTarget ()V|3: // label|4: // line number information|5: ICONST_2 |6: IRETURN }"] + + e -> bb0 + bb0 -> x +} diff --git a/test-output/staticCallTarget.dot b/test-output/staticCallTarget.dot new file mode 100644 index 0000000..a2beb0e --- /dev/null +++ b/test-output/staticCallTarget.dot @@ -0,0 +1,11 @@ +digraph staticCallTarget { + label="staticCallTarget"; + + node [shape=record] + e [shape=circle,label="e"] + x [shape=circle,label="x"] + bb0 [label="0|{0: // label|1: // line number information|2: RETURN }"] + + e -> bb0 + bb0 -> x +} diff --git a/test-output/staticFieldReadMethod.dot b/test-output/staticFieldReadMethod.dot new file mode 100644 index 0000000..c175b80 --- /dev/null +++ b/test-output/staticFieldReadMethod.dot @@ -0,0 +1,11 @@ +digraph staticFieldReadMethod { + label="staticFieldReadMethod"; + + node [shape=record] + e [shape=circle,label="e"] + x [shape=circle,label="x"] + bb0 [label="0|{0: // label|1: // line number information|2: GETSTATIC ExampleClass.staticField Ljava/lang/String;|3: ARETURN }"] + + e -> bb0 + bb0 -> x +} diff --git a/test-output/staticFieldWriteMethod.dot b/test-output/staticFieldWriteMethod.dot new file mode 100644 index 0000000..6a99e8c --- /dev/null +++ b/test-output/staticFieldWriteMethod.dot @@ -0,0 +1,11 @@ +digraph staticFieldWriteMethod { + label="staticFieldWriteMethod"; + + node [shape=record] + e [shape=circle,label="e"] + x [shape=circle,label="x"] + bb0 [label="0|{0: // label|1: // line number information|2: ALOAD 1|3: PUTSTATIC ExampleClass.staticField Ljava/lang/String;|4: // label|5: // line number information|6: RETURN }"] + + e -> bb0 + bb0 -> x +} diff --git a/test-output/switchMethod.dot b/test-output/switchMethod.dot new file mode 100644 index 0000000..eb4d363 --- /dev/null +++ b/test-output/switchMethod.dot @@ -0,0 +1,24 @@ +digraph switchMethod { + label="switchMethod"; + + node [shape=record] + e [shape=circle,label="e"] + x [shape=circle,label="x"] + bb0 [label="0|{0: // label|1: // line number information|2: ICONST_0 |3: ISTORE 2|4: // label|5: // line number information|6: ILOAD 1|7: TABLESWITCH 0: 8, 1: 14, 2: 20, default: 26}"] + bb8 [label="8|{8: // label|9: // line number information|10: // stack frame map|11: ICONST_0 |12: ISTORE 2|13: GOTO 31}"] + bb14 [label="14|{14: // label|15: // line number information|16: // stack frame map|17: ICONST_1 |18: ISTORE 2|19: GOTO 31}"] + bb20 [label="20|{20: // label|21: // line number information|22: // stack frame map|23: ICONST_2 |24: ISTORE 2|25: GOTO 31}"] + bb26 [label="26|{26: // label|27: // line number information|28: // stack frame map|29: ICONST_M1 |30: ISTORE 2}"] + bb31 [label="31|{31: // label|32: // line number information|33: // stack frame map|34: ILOAD 2|35: IRETURN }"] + + e -> bb0 + bb26 -> bb31 + bb31 -> x + bb0 -> bb8 [label="0"] + bb0 -> bb14 [label="1"] + bb0 -> bb20 [label="2"] + bb0 -> bb26 [label="default"] + bb8 -> bb31 [label="T"] + bb14 -> bb31 [label="T"] + bb20 -> bb31 [label="T"] +} diff --git a/test-output/switchMethod2.dot b/test-output/switchMethod2.dot new file mode 100644 index 0000000..1565c59 --- /dev/null +++ b/test-output/switchMethod2.dot @@ -0,0 +1,24 @@ +digraph switchMethod2 { + label="switchMethod2"; + + node [shape=record] + e [shape=circle,label="e"] + x [shape=circle,label="x"] + bb0 [label="0|{0: // label|1: // line number information|2: ICONST_0 |3: ISTORE 2|4: // label|5: // line number information|6: ILOAD 1|7: LOOKUPSWITCH 0: 8, 1000: 14, 2000: 20, default: 26}"] + bb8 [label="8|{8: // label|9: // line number information|10: // stack frame map|11: ICONST_0 |12: ISTORE 2|13: GOTO 31}"] + bb14 [label="14|{14: // label|15: // line number information|16: // stack frame map|17: ICONST_1 |18: ISTORE 2|19: GOTO 31}"] + bb20 [label="20|{20: // label|21: // line number information|22: // stack frame map|23: ICONST_2 |24: ISTORE 2|25: GOTO 31}"] + bb26 [label="26|{26: // label|27: // line number information|28: // stack frame map|29: ICONST_M1 |30: ISTORE 2}"] + bb31 [label="31|{31: // label|32: // line number information|33: // stack frame map|34: ILOAD 2|35: IRETURN }"] + + e -> bb0 + bb26 -> bb31 + bb31 -> x + bb0 -> bb8 [label="0"] + bb0 -> bb14 [label="1000"] + bb0 -> bb20 [label="2000"] + bb0 -> bb26 [label="default"] + bb8 -> bb31 [label="T"] + bb14 -> bb31 [label="T"] + bb20 -> bb31 [label="T"] +} diff --git a/test-output/whileMethod.dot b/test-output/whileMethod.dot new file mode 100644 index 0000000..832221b --- /dev/null +++ b/test-output/whileMethod.dot @@ -0,0 +1,18 @@ +digraph whileMethod { + label="whileMethod"; + + node [shape=record] + e [shape=circle,label="e"] + x [shape=circle,label="x"] + bb0 [label="0|{0: // label|1: // line number information|2: ICONST_0 |3: ISTORE 2}"] + bb4 [label="4|{4: // label|5: // line number information|6: // stack frame map|7: ILOAD 1|8: IFLE 19}"] + bb9 [label="9|{9: // label|10: // line number information|11: ILOAD 2|12: ILOAD 1|13: IADD |14: ISTORE 2|15: // label|16: // line number information|17: IINC 1 -1|18: GOTO 4}"] + bb19 [label="19|{19: // label|20: // line number information|21: // stack frame map|22: ILOAD 2|23: IRETURN }"] + + e -> bb0 + bb0 -> bb4 + bb4 -> bb9 + bb19 -> x + bb9 -> bb4 [label="T"] + bb4 -> bb19 [label="T"] +} diff --git a/test-output/whileTrueMethod.dot b/test-output/whileTrueMethod.dot new file mode 100644 index 0000000..f0fb500 --- /dev/null +++ b/test-output/whileTrueMethod.dot @@ -0,0 +1,11 @@ +digraph whileTrueMethod { + label="whileTrueMethod"; + + node [shape=record] + e [shape=circle,label="e"] + e [shape=circle,label="e"] + bb0 [label="0|{0: // label|1: // line number information|2: // stack frame map|3: IINC 1 1|4: GOTO 0}"] + + e -> bb0 + bb0 -> bb0 [label="T"] +}