pretty shitty dataflow graph, will be redone
This commit is contained in:
122
src/main/java/codegen/analysis/dataflow/DataFlowGraph.java
Normal file
122
src/main/java/codegen/analysis/dataflow/DataFlowGraph.java
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
package codegen.analysis.dataflow;
|
||||||
|
|
||||||
|
import codegen.flowgraph.FlowBasicBlock;
|
||||||
|
import codegen.flowgraph.FlowGraph;
|
||||||
|
import codegen.flowgraph.FlowInstruction;
|
||||||
|
import util.Logger;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public final class DataFlowGraph {
|
||||||
|
|
||||||
|
private final List<DataFlowNode> graph;
|
||||||
|
|
||||||
|
private DataFlowGraph(List<DataFlowNode> graph) {
|
||||||
|
this.graph = Collections.unmodifiableList(graph);
|
||||||
|
Logger.call(this::printToImage);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DataFlowGraph fromSourceGraph(FlowGraph srcGraph) {
|
||||||
|
final List<DataFlowNode> graph = new LinkedList<>();
|
||||||
|
|
||||||
|
for (FlowBasicBlock block : srcGraph.getBlocks()) {
|
||||||
|
for (FlowInstruction inst : block.getInstructions()) {
|
||||||
|
graph.add(DataFlowNode.fromFlowNode(inst, block));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
initSuccPred(srcGraph, graph);
|
||||||
|
|
||||||
|
return new DataFlowGraph(graph);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void initSuccPred(FlowGraph srcGraph, List<DataFlowNode> graph) {
|
||||||
|
for (FlowBasicBlock block : srcGraph.getBlocks()) {
|
||||||
|
for (FlowInstruction inst : block.getInstructions()) {
|
||||||
|
final DataFlowNode current = getNodeByInstruction(inst, graph);
|
||||||
|
|
||||||
|
for (FlowInstruction pred : block.getPredecessors(inst)) {
|
||||||
|
final DataFlowNode currentPred = getNodeByInstruction(pred, graph);
|
||||||
|
|
||||||
|
current.addPredecessor(currentPred);
|
||||||
|
currentPred.addSuccessor(current);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (FlowInstruction succ : block.getSuccessors(inst)) {
|
||||||
|
final DataFlowNode currentSucc = getNodeByInstruction(succ, graph);
|
||||||
|
|
||||||
|
Logger.log("INST: " + current.getInst() + ", SUCC: " + currentSucc.getInst());
|
||||||
|
current.addSuccessor(currentSucc);
|
||||||
|
currentSucc.addPredecessor(current);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static DataFlowNode getNodeByInstruction(FlowInstruction inst, List<DataFlowNode> graph) {
|
||||||
|
return graph.stream()
|
||||||
|
.filter(node -> node.getId().equals(inst.getId()))
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<DataFlowNode> getNodes() {
|
||||||
|
return this.graph;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Printing
|
||||||
|
|
||||||
|
public String printToImage() {
|
||||||
|
final StringBuilder dot = new StringBuilder();
|
||||||
|
|
||||||
|
dot.append("digraph dfd {\n")
|
||||||
|
.append("node[shape=Mrecord]\n");
|
||||||
|
|
||||||
|
for (DataFlowNode node : this.graph) {
|
||||||
|
dot.append(node.getId())
|
||||||
|
.append(" [label=\"{<f0> ")
|
||||||
|
.append(this.graph.indexOf(node))
|
||||||
|
.append("|<f1> ")
|
||||||
|
.append(node.getInst())
|
||||||
|
.append("}\"];\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
dot.append("START[label=\"START\"];\n")
|
||||||
|
.append("END[label=\"END\"];\n");
|
||||||
|
|
||||||
|
dot.append("START -> ").append(this.graph.get(0).getId()).append(";\n");
|
||||||
|
dot.append(this.graph.get(this.graph.size() - 1).getId()).append(" -> END;\n");
|
||||||
|
|
||||||
|
for (DataFlowNode node : this.graph) {
|
||||||
|
for (DataFlowNode succ : node.getSuccessors()) {
|
||||||
|
dot.append(node.getId()).append(" -> ").append(succ.getId()).append(";\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dot.append("}");
|
||||||
|
|
||||||
|
final String dotOut = dot.toString();
|
||||||
|
|
||||||
|
final Path dotFile = Paths.get(System.getProperty("user.dir") + "/DataFlowGraph.dot");
|
||||||
|
try {
|
||||||
|
Files.writeString(dotFile, dotOut);
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
final ProcessBuilder dotCompile = new ProcessBuilder("dot", "-Tsvg", "-oDataFlowGraph.svg", "DataFlowGraph.dot");
|
||||||
|
try {
|
||||||
|
dotCompile.start();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
return "Finished.";
|
||||||
|
}
|
||||||
|
}
|
121
src/main/java/codegen/analysis/dataflow/DataFlowNode.java
Normal file
121
src/main/java/codegen/analysis/dataflow/DataFlowNode.java
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
package codegen.analysis.dataflow;
|
||||||
|
|
||||||
|
import codegen.flowgraph.FlowBasicBlock;
|
||||||
|
import codegen.flowgraph.FlowInstruction;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public final class DataFlowNode {
|
||||||
|
|
||||||
|
private final String id;
|
||||||
|
private final String blockId;
|
||||||
|
private final String inst;
|
||||||
|
private final String use;
|
||||||
|
private final String def;
|
||||||
|
private final Set<String> in;
|
||||||
|
private final Set<String> out;
|
||||||
|
private final Set<DataFlowNode> predecessors;
|
||||||
|
private final Set<DataFlowNode> successors;
|
||||||
|
|
||||||
|
private DataFlowNode(String id, String blockId, String inst, String use, String def) {
|
||||||
|
this.id = id;
|
||||||
|
this.blockId = blockId;
|
||||||
|
this.inst = inst;
|
||||||
|
this.use = use;
|
||||||
|
this.def = def;
|
||||||
|
this.in = new HashSet<>();
|
||||||
|
this.out = new HashSet<>();
|
||||||
|
this.predecessors = new HashSet<>();
|
||||||
|
this.successors = new HashSet<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DataFlowNode fromFlowNode(FlowInstruction srcInst, FlowBasicBlock block) {
|
||||||
|
final String instType = switch (srcInst.getInstruction()) {
|
||||||
|
case "aload", "iload" -> "use";
|
||||||
|
case "astore", "istore" -> "def";
|
||||||
|
case "goto", "ifeq",
|
||||||
|
"if_icmpeq", "if_acmpeq", "if_icmpne", "if_acmpne",
|
||||||
|
"if_icmplt", "if_icmple", "if_icmpgt", "if_icmpge" -> "jmp";
|
||||||
|
default -> "";
|
||||||
|
};
|
||||||
|
|
||||||
|
String use = "";
|
||||||
|
String def = "";
|
||||||
|
if ("use".equals(instType)) {
|
||||||
|
use = srcInst.getArgs()[0];
|
||||||
|
} else if ("def".equals(instType)) {
|
||||||
|
def = srcInst.getArgs()[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
return new DataFlowNode(srcInst.getId(), block.getId(), srcInst.getInstruction(), use, def);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return this.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getBlockId() {
|
||||||
|
return this.blockId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<String> getUse() {
|
||||||
|
return Set.of(this.use);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<String> getDef() {
|
||||||
|
return Set.of(this.def);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<String> getIn() {
|
||||||
|
return this.in;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<String> getOut() {
|
||||||
|
return this.out;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getInst() {
|
||||||
|
return this.inst;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addPredecessor(DataFlowNode node) {
|
||||||
|
this.predecessors.add(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<DataFlowNode> getPredecessors() {
|
||||||
|
return this.predecessors;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<DataFlowNode> getSuccessors() {
|
||||||
|
return this.successors;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addSuccessor(DataFlowNode node) {
|
||||||
|
this.successors.add(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addOut(Set<String> out) {
|
||||||
|
if (out.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (out.stream().allMatch(String::isEmpty)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.out.addAll(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean addIn(Set<String> in) {
|
||||||
|
if (in.isEmpty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (in.stream().allMatch(String::isEmpty)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.in.addAll(in);
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user