add new node types to the visitors
This commit is contained in:
@@ -21,24 +21,38 @@ public class EvalVisitor implements Visitor<Value> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Value visit(MultiplicativeExpression e) {
|
public Value visit(AdditionExpression e) {
|
||||||
Value a = e.lhs.welcome(this);
|
Value lhs = e.lhs.welcome(this);
|
||||||
Value b = e.rhs.welcome(this);
|
Value rhs = e.rhs.welcome(this);
|
||||||
return new Value(a.asInteger() * b.asInteger());
|
return new Value(lhs.asInteger() + rhs.asInteger());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Value visit(AdditiveExpression e) {
|
public Value visit(SubstractionExpression e) {
|
||||||
Value a = e.lhs.welcome(this);
|
Value lhs = e.lhs.welcome(this);
|
||||||
Value b = e.rhs.welcome(this);
|
Value rhs = e.rhs.welcome(this);
|
||||||
return new Value(a.asInteger() + b.asInteger());
|
return new Value(lhs.asInteger() - rhs.asInteger());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Value visit(MultiplicationExpression e) {
|
||||||
|
Value lhs = e.lhs.welcome(this);
|
||||||
|
Value rhs = e.rhs.welcome(this);
|
||||||
|
return new Value(lhs.asInteger() * rhs.asInteger());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Value visit(DivisionExpression e) {
|
||||||
|
Value lhs = e.lhs.welcome(this);
|
||||||
|
Value rhs = e.rhs.welcome(this);
|
||||||
|
return new Value(lhs.asInteger() / rhs.asInteger());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Value visit(ModuloExpression e) {
|
public Value visit(ModuloExpression e) {
|
||||||
Value a = e.lhs.welcome(this);
|
Value lhs = e.lhs.welcome(this);
|
||||||
Value b = e.rhs.welcome(this);
|
Value rhs = e.rhs.welcome(this);
|
||||||
return new Value(a.asInteger() % b.asInteger());
|
return new Value(lhs.asInteger() % rhs.asInteger());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -52,7 +66,7 @@ public class EvalVisitor implements Visitor<Value> {
|
|||||||
Value result = this.env.get(e.name);
|
Value result = this.env.get(e.name);
|
||||||
|
|
||||||
if (result == null) {
|
if (result == null) {
|
||||||
throw new RuntimeException("Variable with name " +e.name + " not found.");
|
throw new RuntimeException("Variable with name " + e.name + " not found.");
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@@ -123,7 +137,7 @@ public class EvalVisitor implements Visitor<Value> {
|
|||||||
|
|
||||||
// Stelle sicher, dass die Länge der argumente und parameter übereinstimmen
|
// Stelle sicher, dass die Länge der argumente und parameter übereinstimmen
|
||||||
if (e.arguments.length != func.parameters.length) {
|
if (e.arguments.length != func.parameters.length) {
|
||||||
throw new RuntimeException("Error with function call " +e.name + ": Number of parameters wrong");
|
throw new RuntimeException("Error with function call " + e.name + ": Number of parameters wrong");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Baue ein neues environment
|
// Baue ein neues environment
|
||||||
@@ -147,7 +161,7 @@ public class EvalVisitor implements Visitor<Value> {
|
|||||||
public Value visit(Program e) {
|
public Value visit(Program e) {
|
||||||
// Funktionsdefinitionen für die Auswertung
|
// Funktionsdefinitionen für die Auswertung
|
||||||
// von Funktionsaufrufen speichern
|
// von Funktionsaufrufen speichern
|
||||||
for (var funcDef: e.funcs) {
|
for (var funcDef : e.funcs) {
|
||||||
this.funcs.put(funcDef.name, funcDef);
|
this.funcs.put(funcDef.name, funcDef);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,249 +6,263 @@ import java.util.Map;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.TreeSet;
|
import java.util.TreeSet;
|
||||||
|
|
||||||
import de.hsrm.compiler.Klang.nodes.Block;
|
import de.hsrm.compiler.Klang.nodes.*;
|
||||||
import de.hsrm.compiler.Klang.nodes.FunctionDefinition;
|
import de.hsrm.compiler.Klang.nodes.expressions.*;
|
||||||
import de.hsrm.compiler.Klang.nodes.Program;
|
import de.hsrm.compiler.Klang.nodes.statements.*;
|
||||||
import de.hsrm.compiler.Klang.nodes.expressions.AdditiveExpression;
|
|
||||||
import de.hsrm.compiler.Klang.nodes.expressions.FunctionCall;
|
|
||||||
import de.hsrm.compiler.Klang.nodes.expressions.IntegerExpression;
|
|
||||||
import de.hsrm.compiler.Klang.nodes.expressions.ModuloExpression;
|
|
||||||
import de.hsrm.compiler.Klang.nodes.expressions.MultiplicativeExpression;
|
|
||||||
import de.hsrm.compiler.Klang.nodes.expressions.NegateExpression;
|
|
||||||
import de.hsrm.compiler.Klang.nodes.expressions.Variable;
|
|
||||||
import de.hsrm.compiler.Klang.nodes.statements.IfStatement;
|
|
||||||
import de.hsrm.compiler.Klang.nodes.statements.PrintStatement;
|
|
||||||
import de.hsrm.compiler.Klang.nodes.statements.ReturnStatement;
|
|
||||||
import de.hsrm.compiler.Klang.nodes.statements.VariableAssignment;
|
|
||||||
|
|
||||||
public class GenASM implements Visitor<Void> {
|
public class GenASM implements Visitor<Void> {
|
||||||
|
|
||||||
public static class ExWriter {
|
public static class ExWriter {
|
||||||
Writer w;
|
Writer w;
|
||||||
String indent = "";
|
String indent = "";
|
||||||
|
|
||||||
void addIndent() {
|
void addIndent() {
|
||||||
indent = indent + " ";
|
indent = indent + " ";
|
||||||
}
|
|
||||||
|
|
||||||
void subIndent() {
|
|
||||||
indent = indent.substring(2);
|
|
||||||
}
|
|
||||||
|
|
||||||
void nl() {
|
|
||||||
write("\n" + indent);
|
|
||||||
}
|
|
||||||
|
|
||||||
int lbl = 0;
|
|
||||||
|
|
||||||
int next() {
|
|
||||||
return lbl++;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ExWriter(Writer w) {
|
|
||||||
this.w = w;
|
|
||||||
}
|
|
||||||
|
|
||||||
void lnwrite(Object o) {
|
|
||||||
nl();
|
|
||||||
write(o);
|
|
||||||
}
|
|
||||||
|
|
||||||
void write(Object o) {
|
|
||||||
try {
|
|
||||||
w.write(o + "");
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ExWriter ex;
|
void subIndent() {
|
||||||
Map<String, Integer> env = new HashMap<>();
|
indent = indent.substring(2);
|
||||||
Set<String> vars;
|
|
||||||
String[] rs = { "%rdi", "%rsi", "%rdx", "%rcx", "%r8", "%r9" };
|
|
||||||
private int lCount = 0; // Invariante: lCount ist benutzt
|
|
||||||
|
|
||||||
public GenASM(ExWriter ex) {
|
|
||||||
this.ex = ex;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
void nl() {
|
||||||
public Void visit(IntegerExpression e) {
|
write("\n" + indent);
|
||||||
this.ex.write(" movq $" + e.value + ", %rax\n");
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
int lbl = 0;
|
||||||
public Void visit(Variable e) {
|
|
||||||
this.ex.write(" movq " +this.env.get(e.name) +"(%rbp), %rax\n");
|
int next() {
|
||||||
return null;
|
return lbl++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public ExWriter(Writer w) {
|
||||||
public Void visit(MultiplicativeExpression e) {
|
this.w = w;
|
||||||
e.lhs.welcome(this);
|
|
||||||
this.ex.write(" movq %rax, %rbx\n");
|
|
||||||
e.rhs.welcome(this);
|
|
||||||
this.ex.write(" imulq %rbx, %rax\n");
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
void lnwrite(Object o) {
|
||||||
public Void visit(AdditiveExpression e) {
|
nl();
|
||||||
e.lhs.welcome(this);
|
write(o);
|
||||||
this.ex.write(" movq %rax, %rbx\n");
|
|
||||||
e.rhs.welcome(this);
|
|
||||||
this.ex.write(" addq %rbx, %rax\n");
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
void write(Object o) {
|
||||||
public Void visit(NegateExpression e) {
|
try {
|
||||||
e.lhs.welcome(this);
|
w.write(o + "");
|
||||||
this.ex.write(" neg %rax\n");
|
} catch (IOException e) {
|
||||||
return null;
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExWriter ex;
|
||||||
|
Map<String, Integer> env = new HashMap<>();
|
||||||
|
Set<String> vars;
|
||||||
|
String[] rs = { "%rdi", "%rsi", "%rdx", "%rcx", "%r8", "%r9" };
|
||||||
|
private int lCount = 0; // Invariante: lCount ist benutzt
|
||||||
|
|
||||||
|
public GenASM(ExWriter ex) {
|
||||||
|
this.ex = ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Void visit(IntegerExpression e) {
|
||||||
|
this.ex.write(" movq $" + e.value + ", %rax\n");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Void visit(Variable e) {
|
||||||
|
this.ex.write(" movq " + this.env.get(e.name) + "(%rbp), %rax\n");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Void visit(AdditionExpression e) {
|
||||||
|
e.lhs.welcome(this);
|
||||||
|
this.ex.write(" pushq %rax\n");
|
||||||
|
e.rhs.welcome(this);
|
||||||
|
this.ex.write(" popq %rbx\n");
|
||||||
|
this.ex.write(" addq %rbx, %rax\n");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Void visit(SubstractionExpression e) {
|
||||||
|
e.lhs.welcome(this);
|
||||||
|
this.ex.write(" pushq %rax\n");
|
||||||
|
e.rhs.welcome(this);
|
||||||
|
this.ex.write(" popq %rbx\n");
|
||||||
|
this.ex.write(" subq %rbx, %rax\n");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Void visit(MultiplicationExpression e) {
|
||||||
|
e.lhs.welcome(this);
|
||||||
|
this.ex.write(" pushq %rax\n");
|
||||||
|
e.rhs.welcome(this);
|
||||||
|
this.ex.write(" popq %rbx\n");
|
||||||
|
this.ex.write(" imulq %rbx, %rax\n");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Void visit(DivisionExpression e) {
|
||||||
|
e.lhs.welcome(this);
|
||||||
|
this.ex.write(" pushq %rax\n");
|
||||||
|
e.rhs.welcome(this);
|
||||||
|
this.ex.write(" movq %rax, %rbx\n");
|
||||||
|
this.ex.write(" popq %rax\n");
|
||||||
|
this.ex.write(" xor %rdx, %rdx\n"); // clear upper part of division
|
||||||
|
this.ex.write(" idiv %rbx\n"); // %rax/%rbx, quotient now in %rax
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Void visit(ModuloExpression e) {
|
||||||
|
this.ex.write(" pushq %rax\n");
|
||||||
|
e.rhs.welcome(this);
|
||||||
|
this.ex.write(" movq %rax, %rbx\n");
|
||||||
|
this.ex.write(" popq %rax\n");
|
||||||
|
this.ex.write(" xor %rdx, %rdx\n"); // clear upper part of division
|
||||||
|
this.ex.write(" idiv %rbx\n"); // %rax/%rbx, remainder now in %rdx
|
||||||
|
this.ex.write(" movq %rdx, %rax\n");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Void visit(NegateExpression e) {
|
||||||
|
e.lhs.welcome(this);
|
||||||
|
this.ex.write(" neg %rax\n");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Void visit(IfStatement e) {
|
||||||
|
int then = ++lCount;
|
||||||
|
int end = ++lCount;
|
||||||
|
|
||||||
|
e.cond.welcome(this);
|
||||||
|
this.ex.write(" cmp $0, %rax\n");
|
||||||
|
this.ex.write(" jz .L" + then + "\n");
|
||||||
|
// else Part
|
||||||
|
if (e.alt != null) {
|
||||||
|
e.alt.welcome(this);
|
||||||
|
} else if (e.elif != null) {
|
||||||
|
e.elif.welcome(this);
|
||||||
|
}
|
||||||
|
this.ex.write(" jmp .L" + end + "\n");
|
||||||
|
// then Part
|
||||||
|
this.ex.write(".L" + then + ":\n");
|
||||||
|
e.then.welcome(this);
|
||||||
|
this.ex.write(".L" + end + ":\n");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Void visit(PrintStatement e) {
|
||||||
|
throw new RuntimeException("Das machen wir mal nicht, ne?!");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Void visit(VariableAssignment e) {
|
||||||
|
e.expression.welcome(this);
|
||||||
|
int offset = this.env.get(e.name);
|
||||||
|
this.ex.write(" movq %rax, " + offset + "(%rbp)\n");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Void visit(ReturnStatement e) {
|
||||||
|
e.expression.welcome(this);
|
||||||
|
this.ex.write(" movq %rbp, %rsp\n");
|
||||||
|
this.ex.write(" popq %rbp\n");
|
||||||
|
this.ex.write(" ret\n");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Void visit(Block e) {
|
||||||
|
for (var statement : e.statements) {
|
||||||
|
statement.welcome(this);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Void visit(FunctionDefinition e) {
|
||||||
|
this.ex.write(".globl " + e.name + "\n");
|
||||||
|
this.ex.write(".type " + e.name + ", @function\n");
|
||||||
|
this.ex.write(e.name + ":\n");
|
||||||
|
this.ex.write(" pushq %rbp\n");
|
||||||
|
this.ex.write(" movq %rsp, %rbp\n");
|
||||||
|
|
||||||
|
// hole die anzahl der lokalen variablen
|
||||||
|
this.vars = new TreeSet<String>();
|
||||||
|
GetVars getvars = new GetVars(vars);
|
||||||
|
getvars.visit(e);
|
||||||
|
|
||||||
|
// Erzeuge ein environment
|
||||||
|
this.env = new HashMap<String, Integer>();
|
||||||
|
|
||||||
|
// Merke dir die offsets der parameter, die direkt auf den stack gelegt wurden
|
||||||
|
int m = e.parameters.length - this.rs.length;
|
||||||
|
for (int i = this.rs.length; i < e.parameters.length; i++) {
|
||||||
|
int j = i - this.rs.length;
|
||||||
|
this.env.put(e.parameters[i], ((m - j) * 8)); // positiv, liegt über unserem stack frame
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
// pushe die aufrufparameter aus den Registern wieder auf den Stack
|
||||||
public Void visit(ModuloExpression e) {
|
int offset = 0;
|
||||||
e.rhs.welcome(this);
|
for (int i = 0; i < Math.min(this.rs.length, e.parameters.length); i++) {
|
||||||
this.ex.write(" movq %rax, %rbx\n");
|
this.ex.write(" pushq " + this.rs[i] + "\n");
|
||||||
e.lhs.welcome(this);
|
offset -= 8;
|
||||||
this.ex.write(" xor %rdx, %rdx\n"); // clear remainder register
|
this.env.put(e.parameters[i], offset); // negative, liegt unter aktuellem BP
|
||||||
this.ex.write(" idiv %ebx\n"); // %rax/%rbx, remainder now in %rdx
|
|
||||||
this.ex.write(" movq %rdx, %rax\n");
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
// Reserviere Platz auf dem Stack für jede lokale variable
|
||||||
public Void visit(IfStatement e) {
|
for (String lok_var : vars) {
|
||||||
int then = ++lCount;
|
offset -= 8;
|
||||||
int end = ++lCount;
|
this.ex.write(" pushq $0\n");
|
||||||
|
this.env.put(lok_var, offset);
|
||||||
e.cond.welcome(this);
|
|
||||||
this.ex.write(" cmp $0, %rax\n");
|
|
||||||
this.ex.write(" jz .L" + then + "\n");
|
|
||||||
// else Part
|
|
||||||
if (e.alt != null) {
|
|
||||||
e.alt.welcome(this);
|
|
||||||
} else if (e.elif != null) {
|
|
||||||
e.elif.welcome(this);
|
|
||||||
}
|
|
||||||
this.ex.write(" jmp .L" + end + "\n");
|
|
||||||
// then Part
|
|
||||||
this.ex.write(".L" + then + ":\n");
|
|
||||||
e.then.welcome(this);
|
|
||||||
this.ex.write(".L" + end + ":\n");
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
e.block.welcome(this);
|
||||||
public Void visit(PrintStatement e) {
|
return null;
|
||||||
throw new RuntimeException("Das machen wir mal nicht, ne?!");
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Void visit(FunctionCall e) {
|
||||||
|
// Die ersten sechs params in die register schieben
|
||||||
|
for (int i = 0; i < Math.min(this.rs.length, e.arguments.length); i++) {
|
||||||
|
e.arguments[i].welcome(this);
|
||||||
|
this.ex.write(" movq %rax, " + this.rs[i] + "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
// Den Rest auf den stack pushen
|
||||||
public Void visit(VariableAssignment e) {
|
for (int i = this.rs.length; i < e.arguments.length; i++) {
|
||||||
e.expression.welcome(this);
|
e.arguments[i].welcome(this);
|
||||||
int offset = this.env.get(e.name);
|
|
||||||
this.ex.write(" movq %rax, " + offset + "(%rbp)\n");
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
this.ex.write(" call " + e.name + "\n");
|
||||||
public Void visit(ReturnStatement e) {
|
return null;
|
||||||
e.expression.welcome(this);
|
}
|
||||||
this.ex.write(" movq %rbp, %rsp\n");
|
|
||||||
this.ex.write(" popq %rbp\n");
|
@Override
|
||||||
this.ex.write(" ret\n");
|
public Void visit(Program e) {
|
||||||
return null;
|
this.ex.write(".text\n");
|
||||||
|
for (var func : e.funcs) {
|
||||||
|
func.welcome(this);
|
||||||
|
this.ex.write("\n");
|
||||||
}
|
}
|
||||||
|
this.ex.write(".globl start\n");
|
||||||
|
this.ex.write(".type start, @function\n");
|
||||||
|
this.ex.write("start:\n");
|
||||||
|
this.ex.write(" pushq %rbp\n");
|
||||||
|
this.ex.write(" movq %rsp, %rbp\n");
|
||||||
|
e.expression.welcome(this);
|
||||||
|
|
||||||
@Override
|
this.ex.write(" movq %rbp, %rsp\n");
|
||||||
public Void visit(Block e) {
|
this.ex.write(" popq %rbp\n");
|
||||||
for (var statement : e.statements) {
|
this.ex.write(" ret\n");
|
||||||
statement.welcome(this);
|
return null;
|
||||||
}
|
}
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Void visit(FunctionDefinition e) {
|
|
||||||
this.ex.write(".globl " + e.name + "\n");
|
|
||||||
this.ex.write(".type " + e.name + ", @function\n");
|
|
||||||
this.ex.write(e.name + ":\n");
|
|
||||||
this.ex.write(" pushq %rbp\n");
|
|
||||||
this.ex.write(" movq %rsp, %rbp\n");
|
|
||||||
|
|
||||||
// hole die anzahl der lokalen variablen
|
|
||||||
this.vars = new TreeSet<String>();
|
|
||||||
GetVars getvars = new GetVars(vars);
|
|
||||||
getvars.visit(e);
|
|
||||||
|
|
||||||
// Erzeuge ein environment
|
|
||||||
this.env = new HashMap<String, Integer>();
|
|
||||||
|
|
||||||
// Merke dir die offsets der parameter, die direkt auf den stack gelegt wurden
|
|
||||||
int m = e.parameters.length - this.rs.length;
|
|
||||||
for (int i = this.rs.length; i < e.parameters.length; i++) {
|
|
||||||
int j = i - this.rs.length;
|
|
||||||
this.env.put(e.parameters[i], ((m - j) * 8)); // positiv, liegt über unserem stack frame
|
|
||||||
}
|
|
||||||
|
|
||||||
// pushe die aufrufparameter aus den Registern wieder auf den Stack
|
|
||||||
int offset = 0;
|
|
||||||
for (int i = 0; i < Math.min(this.rs.length, e.parameters.length); i++) {
|
|
||||||
this.ex.write(" pushq " + this.rs[i] + "\n");
|
|
||||||
offset -= 8;
|
|
||||||
this.env.put(e.parameters[i], offset); // negative, liegt unter aktuellem BP
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reserviere Platz auf dem Stack für jede lokale variable
|
|
||||||
for (String lok_var: vars) {
|
|
||||||
offset -= 8;
|
|
||||||
this.ex.write(" pushq $0\n");
|
|
||||||
this.env.put(lok_var, offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
e.block.welcome(this);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Void visit(FunctionCall e) {
|
|
||||||
// Die ersten sechs params in die register schieben
|
|
||||||
for (int i = 0; i < Math.min(this.rs.length, e.arguments.length); i++) {
|
|
||||||
e.arguments[i].welcome(this);
|
|
||||||
this.ex.write(" movq %rax, " + this.rs[i] + "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Den Rest auf den stack pushen
|
|
||||||
for (int i = this.rs.length; i < e.arguments.length; i++) {
|
|
||||||
e.arguments[i].welcome(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.ex.write(" call " + e.name + "\n");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Void visit(Program e) {
|
|
||||||
this.ex.write(".text\n");
|
|
||||||
for (var func : e.funcs) {
|
|
||||||
func.welcome(this);
|
|
||||||
this.ex.write("\n");
|
|
||||||
}
|
|
||||||
this.ex.write(".globl start\n");
|
|
||||||
this.ex.write(".type start, @function\n");
|
|
||||||
this.ex.write("start:\n");
|
|
||||||
this.ex.write(" pushq %rbp\n");
|
|
||||||
this.ex.write(" movq %rsp, %rbp\n");
|
|
||||||
e.expression.welcome(this);
|
|
||||||
|
|
||||||
this.ex.write(" movq %rbp, %rsp\n");
|
|
||||||
this.ex.write(" popq %rbp\n");
|
|
||||||
this.ex.write(" ret\n");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -2,20 +2,9 @@ package de.hsrm.compiler.Klang.visitors;
|
|||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import de.hsrm.compiler.Klang.nodes.Block;
|
import de.hsrm.compiler.Klang.nodes.*;
|
||||||
import de.hsrm.compiler.Klang.nodes.FunctionDefinition;
|
import de.hsrm.compiler.Klang.nodes.expressions.*;
|
||||||
import de.hsrm.compiler.Klang.nodes.Program;
|
import de.hsrm.compiler.Klang.nodes.statements.*;
|
||||||
import de.hsrm.compiler.Klang.nodes.expressions.AdditiveExpression;
|
|
||||||
import de.hsrm.compiler.Klang.nodes.expressions.FunctionCall;
|
|
||||||
import de.hsrm.compiler.Klang.nodes.expressions.IntegerExpression;
|
|
||||||
import de.hsrm.compiler.Klang.nodes.expressions.ModuloExpression;
|
|
||||||
import de.hsrm.compiler.Klang.nodes.expressions.MultiplicativeExpression;
|
|
||||||
import de.hsrm.compiler.Klang.nodes.expressions.NegateExpression;
|
|
||||||
import de.hsrm.compiler.Klang.nodes.expressions.Variable;
|
|
||||||
import de.hsrm.compiler.Klang.nodes.statements.IfStatement;
|
|
||||||
import de.hsrm.compiler.Klang.nodes.statements.PrintStatement;
|
|
||||||
import de.hsrm.compiler.Klang.nodes.statements.ReturnStatement;
|
|
||||||
import de.hsrm.compiler.Klang.nodes.statements.VariableAssignment;
|
|
||||||
|
|
||||||
class GetVars implements Visitor<Void> {
|
class GetVars implements Visitor<Void> {
|
||||||
|
|
||||||
@@ -36,14 +25,35 @@ class GetVars implements Visitor<Void> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Void visit(MultiplicativeExpression e) {
|
public Void visit(AdditionExpression e) {
|
||||||
e.lhs.welcome(this);
|
e.lhs.welcome(this);
|
||||||
e.rhs.welcome(this);
|
e.rhs.welcome(this);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Void visit(AdditiveExpression e) {
|
public Void visit(SubstractionExpression e) {
|
||||||
|
e.lhs.welcome(this);
|
||||||
|
e.rhs.welcome(this);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Void visit(MultiplicationExpression e) {
|
||||||
|
e.lhs.welcome(this);
|
||||||
|
e.rhs.welcome(this);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Void visit(DivisionExpression e) {
|
||||||
|
e.lhs.welcome(this);
|
||||||
|
e.rhs.welcome(this);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Void visit(ModuloExpression e) {
|
||||||
e.lhs.welcome(this);
|
e.lhs.welcome(this);
|
||||||
e.rhs.welcome(this);
|
e.rhs.welcome(this);
|
||||||
return null;
|
return null;
|
||||||
@@ -55,13 +65,6 @@ class GetVars implements Visitor<Void> {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Void visit(ModuloExpression e) {
|
|
||||||
e.lhs.welcome(this);
|
|
||||||
e.rhs.welcome(this);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Void visit(IfStatement e) {
|
public Void visit(IfStatement e) {
|
||||||
e.cond.welcome(this);
|
e.cond.welcome(this);
|
||||||
|
|||||||
@@ -72,33 +72,60 @@ public class PrettyPrintVisitor implements Visitor<Void> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Void visit(MultiplicativeExpression e) {
|
public Void visit(AdditionExpression e) {
|
||||||
e.lhs.welcome(this);
|
ex.write("(");
|
||||||
ex.write(" * ");
|
|
||||||
e.rhs.welcome(this);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Void visit(AdditiveExpression e) {
|
|
||||||
e.lhs.welcome(this);
|
e.lhs.welcome(this);
|
||||||
ex.write(" + ");
|
ex.write(" + ");
|
||||||
e.rhs.welcome(this);
|
e.rhs.welcome(this);
|
||||||
|
ex.write(")");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Void visit(NegateExpression e) {
|
public Void visit(SubstractionExpression e) {
|
||||||
ex.write(" - ");
|
ex.write("(");
|
||||||
e.lhs.welcome(this);
|
e.lhs.welcome(this);
|
||||||
|
ex.write(" - ");
|
||||||
|
e.rhs.welcome(this);
|
||||||
|
ex.write(")");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Void visit(MultiplicationExpression e) {
|
||||||
|
ex.write("(");
|
||||||
|
e.lhs.welcome(this);
|
||||||
|
ex.write(" * ");
|
||||||
|
e.rhs.welcome(this);
|
||||||
|
ex.write(")");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Void visit(DivisionExpression e) {
|
||||||
|
ex.write("(");
|
||||||
|
e.lhs.welcome(this);
|
||||||
|
ex.write(" / ");
|
||||||
|
e.rhs.welcome(this);
|
||||||
|
ex.write(")");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Void visit(ModuloExpression e) {
|
public Void visit(ModuloExpression e) {
|
||||||
|
ex.write("(");
|
||||||
e.lhs.welcome(this);
|
e.lhs.welcome(this);
|
||||||
ex.write(" % ");
|
ex.write(" % ");
|
||||||
e.rhs.welcome(this);
|
e.rhs.welcome(this);
|
||||||
|
ex.write(")");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Void visit(NegateExpression e) {
|
||||||
|
ex.write(" - ");
|
||||||
|
e.lhs.welcome(this);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,10 +9,12 @@ import de.hsrm.compiler.Klang.nodes.statements.*;
|
|||||||
public interface Visitor<R> {
|
public interface Visitor<R> {
|
||||||
R visit(IntegerExpression e);
|
R visit(IntegerExpression e);
|
||||||
R visit(Variable e);
|
R visit(Variable e);
|
||||||
R visit(MultiplicativeExpression e);
|
R visit(AdditionExpression e);
|
||||||
R visit(AdditiveExpression e);
|
R visit(SubstractionExpression e);
|
||||||
R visit(NegateExpression e);
|
R visit(MultiplicationExpression e);
|
||||||
|
R visit(DivisionExpression e);
|
||||||
R visit(ModuloExpression e);
|
R visit(ModuloExpression e);
|
||||||
|
R visit(NegateExpression e);
|
||||||
R visit(IfStatement e);
|
R visit(IfStatement e);
|
||||||
R visit(PrintStatement e);
|
R visit(PrintStatement e);
|
||||||
R visit(VariableAssignment e);
|
R visit(VariableAssignment e);
|
||||||
|
|||||||
Reference in New Issue
Block a user