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