This commit is contained in:
ChUrl
2021-01-31 18:11:56 +01:00
parent 9536e09f1c
commit d8f5142e5e
4 changed files with 59 additions and 20 deletions

View File

@ -10,6 +10,7 @@ import parser.ast.AST;
import parser.ast.ASTNode;
import parser.grammar.Grammar;
import typechecker.TypeChecker;
import util.Logger;
import java.io.IOException;
import java.nio.file.Files;
@ -44,6 +45,8 @@ public final class StupsCompiler {
final FlowGraphGenerator gen = getFlowGraphGen(filename);
final FlowGraph graph = gen.generateGraph();
Logger.call(graph::printToImage);
// Codegeneration + Output
final String outputName = filename.replaceFirst("\\.stups", ".j");
final String sourceCode = graph.toString();
@ -73,7 +76,12 @@ public final class StupsCompiler {
final FlowGraphGenerator gen = getFlowGraphGen(filename);
final FlowGraph graph = gen.generateGraph();
final DataFlowGraph dataFlowGraph = DataFlowGraph.fromSourceGraph(graph);
Logger.call(graph::printToImage);
final DataFlowGraph dataFlowGraph = DataFlowGraph.fromFlowGraph(graph);
Logger.call(dataFlowGraph::printToImage);
final LivenessAnalysis liveness = LivenessAnalysis.fromDataFlowGraph(dataFlowGraph, gen.getVarMap());
liveness.doLivenessAnalysis();

View File

@ -4,7 +4,7 @@ import codegen.CodeGenerationException;
import codegen.analysis.StackSizeAnalyzer;
import parser.ast.AST;
import parser.ast.ASTNode;
import util.Logger;
import typechecker.TypeChecker;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
@ -22,6 +22,9 @@ import static util.Logger.log;
*/
public final class FlowGraphGenerator {
/**
* Mappt die {@link ASTNode}-Namen auf entsprechende Methoden für die Codeerzeugung.
*/
private static final Map<String, Method> methodMap;
static {
@ -49,9 +52,20 @@ public final class FlowGraphGenerator {
}
private final AST tree;
private final Map<String, Integer> varMap;
/**
* Enthält den Rückgabetypen von jedem Expression-Node.
* Wird erstellt im {@link TypeChecker}.
*/
private final Map<ASTNode, String> nodeTypeMap;
/**
* Enthält die Mappings vom Symbol/Variablennamen auf die Position in der JVM-Locals-Tabelle.
*/
private final Map<String, Integer> varMap;
private final FlowGraph graph;
private int labelCounter;
private FlowGraphGenerator(Map<String, Integer> varMap, AST tree, Map<ASTNode, String> nodeTypeMap, FlowGraph graph) {
@ -61,18 +75,16 @@ public final class FlowGraphGenerator {
this.graph = graph;
}
/**
* @param source Das Source-File, welches compiliert wird (Optionaler Jasmin-Parameter)
*/
public static FlowGraphGenerator fromAST(AST tree, Map<ASTNode, String> nodeTypeMap, String source) {
if (!tree.getRoot().hasChildren()) {
if (tree.isEmpty()) {
throw new CodeGenerationException("Empty File can't be compiled");
}
final Map<String, Integer> varMap = initVarMap(tree);
final String bytecodeVersion = "49.0";
final String clazz = tree.getRoot().getChildren().get(1).getValue();
final int stackSize = StackSizeAnalyzer.runStackModel(tree);
final int localCount = varMap.size() + 1;
final FlowGraph graph = new FlowGraph(bytecodeVersion, source, clazz, stackSize, localCount);
final FlowGraph graph = initFlowGraph(tree, varMap, source);
return new FlowGraphGenerator(varMap, tree, nodeTypeMap, graph);
}
@ -80,19 +92,23 @@ public final class FlowGraphGenerator {
private static Map<String, Integer> initVarMap(AST tree) {
final Map<String, Integer> varMap = new HashMap<>();
// Assign variables to map: Symbol -> jasminLocalVarNr.
int varCount = 0;
final Deque<ASTNode> stack = new ArrayDeque<>();
stack.push(tree.getRoot());
int currentVarNumber = 0;
// Assign variables to map: Symbol -> jasminLocalVarNr.
while (!stack.isEmpty()) {
final ASTNode current = stack.pop();
if ("declaration".equals(current.getName())) {
varCount++;
varMap.put(current.getChildren().get(0).getValue(), varCount);
// New variables only come from declarations
currentVarNumber++;
varMap.put(current.getChildren().get(0).getValue(), currentVarNumber);
log("New local " + current.getValue() + " variable "
+ current.getChildren().get(0).getValue()
+ " assigned to slot " + varCount + ".");
+ " assigned to slot " + currentVarNumber + ".");
}
current.getChildren().forEach(stack::push);
@ -101,6 +117,15 @@ public final class FlowGraphGenerator {
return Collections.unmodifiableMap(varMap);
}
private static FlowGraph initFlowGraph(AST tree, Map<String, Integer> varMap, String source) {
final String bytecodeVersion = "49.0";
final String clazz = tree.getRoot().getChildren().get(1).getValue();
final int stackSize = StackSizeAnalyzer.runStackModel(tree);
final int localCount = varMap.size() + 1;
return new FlowGraph(bytecodeVersion, source, clazz, stackSize, localCount);
}
/**
* Erzeugt den Flussgraphen für den gespeicherten AST.
* Der Flussgraph ist dabei die Graphenform des generierten SourceCodes:
@ -112,9 +137,8 @@ public final class FlowGraphGenerator {
// Skip the first 2 identifiers: ClassName, MainArgs
this.generateNode(this.tree.getRoot().getChildren().get(3).getChildren().get(11));
this.graph.purgeEmptyBlocks();
Logger.call(this.graph::printToImage);
log("\n\nSourceGraph print:\n" + "-".repeat(100) + "\n" + this.graph.print() + "-".repeat(100));
log("\n\nSourceGraph print:\n" + "-".repeat(100) + "\n" + this.graph + "-".repeat(100));
System.out.println("Graph-generation successful.");
return this.graph;
@ -137,9 +161,6 @@ public final class FlowGraphGenerator {
}
}
// ifeq - if value is 0
// ifne - if value is not 0
/**
* Erzeugt den Teilbaum für einen If-Knoten.
*/

View File

@ -20,6 +20,10 @@ public class AST {
return this.root.size();
}
public boolean isEmpty() {
return this.root.isEmpty();
}
public void postprocess(Grammar grammar) {
ASTCompacter.clean(this, grammar);
ASTBalancer.balance(this);
@ -30,6 +34,8 @@ public class AST {
return new AST(this.root.deepCopy());
}
// Overrides
@Override
public boolean equals(Object obj) {
if (obj instanceof AST) {

View File

@ -119,4 +119,8 @@ public class ASTNode {
return newNode;
}
public boolean isEmpty() {
return this.children.isEmpty();
}
}