horrible messy liveness analysis, will be redone
This commit is contained in:
@ -1,4 +1,8 @@
|
||||
import codegen.CodeGenerator;
|
||||
import codegen.analysis.dataflow.DataFlowGraph;
|
||||
import codegen.analysis.liveness.LivenessAnalysis;
|
||||
import codegen.flowgraph.FlowGraph;
|
||||
import codegen.flowgraph.FlowGraphGenerator;
|
||||
import lexer.StupsLexer;
|
||||
import org.antlr.v4.runtime.CharStreams;
|
||||
import org.antlr.v4.runtime.Lexer;
|
||||
@ -102,5 +106,49 @@ public final class StupsCompiler {
|
||||
|
||||
private static void liveness(String filename) {
|
||||
System.out.println("Liveness-Analyse für " + filename);
|
||||
|
||||
// File opening + Lexing
|
||||
Lexer lexer;
|
||||
try {
|
||||
// Relativer Pfad
|
||||
|
||||
final Path programPath = Paths.get(System.getProperty("user.dir") + "/" + filename);
|
||||
lexer = new StupsLexer(CharStreams.fromPath(programPath));
|
||||
} catch (IOException e) {
|
||||
|
||||
try {
|
||||
// Absoluter Pfad
|
||||
|
||||
final Path programPath = Paths.get(filename);
|
||||
lexer = new StupsLexer(CharStreams.fromPath(programPath));
|
||||
} catch (IOException ee) {
|
||||
System.out.println("Das Programm konnte nicht gelesen werden.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Grammar parsing from file
|
||||
final Grammar grammar;
|
||||
try {
|
||||
final Path grammarFile = Paths.get(System.getProperty("user.dir") + "/stups.grammar");
|
||||
grammar = Grammar.fromFile(grammarFile);
|
||||
} catch (IOException e) {
|
||||
System.out.println("Die Grammatik konnte nicht geöffnet werden.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Parser from Grammar
|
||||
final StupsParser stupsParser = StupsParser.fromGrammar(grammar);
|
||||
|
||||
// Parsing + Typechecking of program
|
||||
final AST tree = stupsParser.parse(lexer.getAllTokens(), lexer.getVocabulary());
|
||||
tree.postprocess(grammar);
|
||||
final Map<ASTNode, String> nodeTable = TypeChecker.validate(tree);
|
||||
|
||||
final FlowGraphGenerator gen = FlowGraphGenerator.fromAST(tree, nodeTable, filename);
|
||||
final FlowGraph graph = gen.generateGraph();
|
||||
final DataFlowGraph dataFlowGraph = DataFlowGraph.fromSourceGraph(graph);
|
||||
|
||||
LivenessAnalysis.doLivenessAnalysis(dataFlowGraph, gen.getVarMap());
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,4 @@
|
||||
package codegen.analysis.liveness;
|
||||
|
||||
public class InterferenceGraph {
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
package codegen.analysis.liveness;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
public class InterferenceNode {
|
||||
|
||||
private final String symbol;
|
||||
private final Set<InterferenceNode> neighbours;
|
||||
private int color;
|
||||
|
||||
public InterferenceNode(String symbol) {
|
||||
this.symbol = symbol;
|
||||
this.color = 0;
|
||||
this.neighbours = new HashSet<>();
|
||||
}
|
||||
|
||||
public String getSymbol() {
|
||||
return this.symbol;
|
||||
}
|
||||
|
||||
public void addNeighbour(InterferenceNode node) {
|
||||
if (!node.equals(this)) {
|
||||
this.neighbours.add(node);
|
||||
}
|
||||
}
|
||||
|
||||
public Set<InterferenceNode> getNeighbours() {
|
||||
return this.neighbours;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(this.symbol);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || this.getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
final InterferenceNode that = (InterferenceNode) o;
|
||||
return this.symbol.equals(that.symbol);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.symbol;
|
||||
}
|
||||
|
||||
public Integer getColor() {
|
||||
return this.color;
|
||||
}
|
||||
|
||||
public void setColor(int color) {
|
||||
this.color = color;
|
||||
}
|
||||
}
|
178
src/main/java/codegen/analysis/liveness/LivenessAnalysis.java
Normal file
178
src/main/java/codegen/analysis/liveness/LivenessAnalysis.java
Normal file
@ -0,0 +1,178 @@
|
||||
package codegen.analysis.liveness;
|
||||
|
||||
import codegen.analysis.dataflow.DataFlowGraph;
|
||||
import codegen.analysis.dataflow.DataFlowNode;
|
||||
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.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
// TODO: This is just terrible
|
||||
public final class LivenessAnalysis {
|
||||
|
||||
private LivenessAnalysis() {}
|
||||
|
||||
public static void doLivenessAnalysis(DataFlowGraph graph, Map<String, Integer> varMap) {
|
||||
|
||||
// Calculate IN, OUT
|
||||
boolean change;
|
||||
do {
|
||||
change = false;
|
||||
|
||||
for (DataFlowNode node : graph.getNodes()) {
|
||||
if (graph.getNodes().indexOf(node) == graph.getNodes().size() - 1) {
|
||||
// Skip END
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
change = change || updateInOut(node);
|
||||
}
|
||||
} while (change);
|
||||
|
||||
Logger.log("IN, OUT Sets:");
|
||||
for (DataFlowNode node : graph.getNodes()) {
|
||||
Logger.log(graph.getNodes().indexOf(node) + ": " + node.getInst() + " IN: " + node.getIn());
|
||||
Logger.log(graph.getNodes().indexOf(node) + ": " + node.getInst() + " OUT: " + node.getOut());
|
||||
}
|
||||
Logger.log("\n");
|
||||
|
||||
doInterference(graph.getNodes(), varMap);
|
||||
}
|
||||
|
||||
private static boolean updateInOut(DataFlowNode node) {
|
||||
boolean change;
|
||||
|
||||
for (DataFlowNode succ : node.getSuccessors()) {
|
||||
node.addOut(succ.getIn());
|
||||
}
|
||||
|
||||
final Set<String> addIN = new HashSet<>(node.getOut()); // Copy important
|
||||
addIN.removeAll(node.getDef());
|
||||
|
||||
change = node.addIn(node.getUse());
|
||||
change = change || node.addIn(addIN);
|
||||
|
||||
return change;
|
||||
}
|
||||
|
||||
private static void doInterference(List<DataFlowNode> nodes, Map<String, Integer> varMap) {
|
||||
final List<InterferenceNode> interferenceGraph = new ArrayList<>();
|
||||
|
||||
// Init graph
|
||||
for (Map.Entry<String, Integer> var : varMap.entrySet()) {
|
||||
interferenceGraph.add(new InterferenceNode(var.getValue().toString()));
|
||||
}
|
||||
System.out.println("Interference nodes: " + interferenceGraph);
|
||||
|
||||
// Determine neighbours
|
||||
for (DataFlowNode node : nodes) {
|
||||
Logger.log("NODE " + node.getInst() + " - OUT: " + node.getOut());
|
||||
for (String left : node.getOut()) {
|
||||
if (left.isBlank()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (String right : node.getOut()) {
|
||||
if (right.isBlank()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Logger.log("LEFT: " + left + ", RIGHT: " + right);
|
||||
getNodeBySymbol(left, interferenceGraph).addNeighbour(getNodeBySymbol(right, interferenceGraph));
|
||||
Logger.log("Add interference neighbour: " + left + ": " + right);
|
||||
Logger.log("Neighbours of " + left + ": " + getNodeBySymbol(left, interferenceGraph).getNeighbours());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Color graph
|
||||
int colors = 0;
|
||||
int currentColor;
|
||||
Logger.log("\n");
|
||||
for (InterferenceNode node : interferenceGraph) {
|
||||
currentColor = 1;
|
||||
final Set<Integer> neighbourColors = new HashSet<>();
|
||||
Logger.log("Interference node " + node + ", Color = " + node.getColor() + ": Neighbours - "
|
||||
+ node.getNeighbours() + ", NColors - " + neighbourColors);
|
||||
for (InterferenceNode neighbour : node.getNeighbours()) {
|
||||
neighbourColors.add(neighbour.getColor());
|
||||
}
|
||||
|
||||
while (neighbourColors.contains(currentColor)) {
|
||||
currentColor++;
|
||||
}
|
||||
|
||||
node.setColor(currentColor);
|
||||
|
||||
if (currentColor > colors) {
|
||||
colors = currentColor;
|
||||
}
|
||||
}
|
||||
|
||||
printInterferenceGraphToPicture(interferenceGraph);
|
||||
|
||||
System.out.println("\nLiveness: " + colors + " register nötig.");
|
||||
}
|
||||
|
||||
// Printing
|
||||
|
||||
private static String printInterferenceGraphToPicture(List<InterferenceNode> graph) {
|
||||
final StringBuilder dot = new StringBuilder();
|
||||
|
||||
dot.append("digraph dfd {\n")
|
||||
.append("node[shape=Mrecord]\n");
|
||||
|
||||
for (InterferenceNode node : graph) {
|
||||
dot.append(node.getSymbol())
|
||||
.append(" [label=\"{<f0> Symbol: ")
|
||||
.append(node.getSymbol())
|
||||
.append("|<f1> Color: ")
|
||||
.append(node.getColor())
|
||||
.append("}\"];\n");
|
||||
}
|
||||
|
||||
for (InterferenceNode node : graph) {
|
||||
for (InterferenceNode neigh : node.getNeighbours()) {
|
||||
if (!dot.toString().contains(neigh.getSymbol() + " -> " + node.getSymbol())) { // No double lines
|
||||
dot.append(node.getSymbol()).append(" -> ").append(neigh.getSymbol()).append(" [arrowhead=\"none\"];\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dot.append("}");
|
||||
|
||||
final String dotOut = dot.toString();
|
||||
|
||||
final Path dotFile = Paths.get(System.getProperty("user.dir") + "/InterferenceGraph.dot");
|
||||
try {
|
||||
Files.writeString(dotFile, dotOut);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
final ProcessBuilder dotCompile = new ProcessBuilder("dot", "-Tsvg", "-oInterferenceGraph.svg", "InterferenceGraph.dot");
|
||||
try {
|
||||
dotCompile.start();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return "Finished.";
|
||||
}
|
||||
|
||||
private static InterferenceNode getNodeBySymbol(String symbol, List<InterferenceNode> interferenceGraph) {
|
||||
return interferenceGraph.stream()
|
||||
.filter(node -> node.getSymbol().equals(symbol))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user