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

View File

@ -4,7 +4,7 @@ import codegen.CodeGenerationException;
import codegen.analysis.StackSizeAnalyzer; import codegen.analysis.StackSizeAnalyzer;
import parser.ast.AST; import parser.ast.AST;
import parser.ast.ASTNode; import parser.ast.ASTNode;
import util.Logger; import typechecker.TypeChecker;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
@ -22,6 +22,9 @@ import static util.Logger.log;
*/ */
public final class FlowGraphGenerator { public final class FlowGraphGenerator {
/**
* Mappt die {@link ASTNode}-Namen auf entsprechende Methoden für die Codeerzeugung.
*/
private static final Map<String, Method> methodMap; private static final Map<String, Method> methodMap;
static { static {
@ -49,9 +52,20 @@ public final class FlowGraphGenerator {
} }
private final AST tree; 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; 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 final FlowGraph graph;
private int labelCounter; private int labelCounter;
private FlowGraphGenerator(Map<String, Integer> varMap, AST tree, Map<ASTNode, String> nodeTypeMap, FlowGraph graph) { 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; 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) { 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"); throw new CodeGenerationException("Empty File can't be compiled");
} }
final Map<String, Integer> varMap = initVarMap(tree); final Map<String, Integer> varMap = initVarMap(tree);
final FlowGraph graph = initFlowGraph(tree, varMap, 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;
final FlowGraph graph = new FlowGraph(bytecodeVersion, source, clazz, stackSize, localCount);
return new FlowGraphGenerator(varMap, tree, nodeTypeMap, graph); return new FlowGraphGenerator(varMap, tree, nodeTypeMap, graph);
} }
@ -80,19 +92,23 @@ public final class FlowGraphGenerator {
private static Map<String, Integer> initVarMap(AST tree) { private static Map<String, Integer> initVarMap(AST tree) {
final Map<String, Integer> varMap = new HashMap<>(); final Map<String, Integer> varMap = new HashMap<>();
// Assign variables to map: Symbol -> jasminLocalVarNr.
int varCount = 0;
final Deque<ASTNode> stack = new ArrayDeque<>(); final Deque<ASTNode> stack = new ArrayDeque<>();
stack.push(tree.getRoot()); stack.push(tree.getRoot());
int currentVarNumber = 0;
// Assign variables to map: Symbol -> jasminLocalVarNr.
while (!stack.isEmpty()) { while (!stack.isEmpty()) {
final ASTNode current = stack.pop(); final ASTNode current = stack.pop();
if ("declaration".equals(current.getName())) { if ("declaration".equals(current.getName())) {
varCount++; // New variables only come from declarations
varMap.put(current.getChildren().get(0).getValue(), varCount);
currentVarNumber++;
varMap.put(current.getChildren().get(0).getValue(), currentVarNumber);
log("New local " + current.getValue() + " variable " log("New local " + current.getValue() + " variable "
+ current.getChildren().get(0).getValue() + current.getChildren().get(0).getValue()
+ " assigned to slot " + varCount + "."); + " assigned to slot " + currentVarNumber + ".");
} }
current.getChildren().forEach(stack::push); current.getChildren().forEach(stack::push);
@ -101,6 +117,15 @@ public final class FlowGraphGenerator {
return Collections.unmodifiableMap(varMap); 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. * Erzeugt den Flussgraphen für den gespeicherten AST.
* Der Flussgraph ist dabei die Graphenform des generierten SourceCodes: * Der Flussgraph ist dabei die Graphenform des generierten SourceCodes:
@ -112,9 +137,8 @@ public final class FlowGraphGenerator {
// Skip the first 2 identifiers: ClassName, MainArgs // Skip the first 2 identifiers: ClassName, MainArgs
this.generateNode(this.tree.getRoot().getChildren().get(3).getChildren().get(11)); this.generateNode(this.tree.getRoot().getChildren().get(3).getChildren().get(11));
this.graph.purgeEmptyBlocks(); 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."); System.out.println("Graph-generation successful.");
return this.graph; 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. * Erzeugt den Teilbaum für einen If-Knoten.
*/ */

View File

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

View File

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