pretty shitty dataflow graph, will be redone

This commit is contained in:
ChUrl
2021-01-29 21:54:07 +01:00
parent 525f021add
commit 96fc8cc654
2 changed files with 243 additions and 0 deletions

View 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.";
}
}

View 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);
}
}