diff --git a/.gitignore b/.gitignore index 52a1170..e0fbaca 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,9 @@ src/main/antlr4/de/hsrm/compiler/Klang/.antlr # assembly files *.s + +# other sourcecode files +*.c + +# build output +out diff --git a/src/main/antlr4/de/hsrm/compiler/Klang/Klang.g4 b/src/main/antlr4/de/hsrm/compiler/Klang/Klang.g4 index 9263309..a6dbbb7 100644 --- a/src/main/antlr4/de/hsrm/compiler/Klang/Klang.g4 +++ b/src/main/antlr4/de/hsrm/compiler/Klang/Klang.g4 @@ -44,14 +44,21 @@ return_statement ; expression - : atom MULT atom #multiplicationExpression - | atom op=(ADD | SUB) atom #additiveExpression - | atom MOD atom #moduloExpression - | SUB atom #unaryNegateExpression - | atom #atomExpression + : atom #atomExpression + | OPAR lhs=expression ADD rhs=expression CPAR #additionExpression + | OPAR lhs=expression SUB rhs=expression CPAR #substractionExpression + | OPAR lhs=expression MUL rhs=expression CPAR #multiplicationExpression + | OPAR lhs=expression DIV rhs=expression CPAR #divisionExpression + | OPAR lhs=expression MOD rhs=expression CPAR #moduloExpression + | SUB expression #negateExpression | functionCall #functionCallExpression ; +atom + : INTEGER_LITERAL #intAtom + | IDENT # variable + ; + functionCall : IDENT OPAR arguments CPAR ; @@ -60,11 +67,6 @@ arguments : (expression (COMMA expression)*)? ; -atom - : INTEGER_LITERAL #intAtom - | IDENT # variable - ; - PRINT: 'print'; IF: 'if'; ELSE: 'else'; @@ -79,10 +81,11 @@ CPAR: ')'; COMMA: ','; EQUAL: '='; -MULT: '*'; +MUL: '*'; ADD: '+'; SUB: '-'; MOD: '%'; +DIV: '/'; INTEGER_LITERAL : [0-9]+ diff --git a/src/main/java/de/hsrm/compiler/Klang/ContextAnalysis.java b/src/main/java/de/hsrm/compiler/Klang/ContextAnalysis.java index 8cee8ee..a41643b 100644 --- a/src/main/java/de/hsrm/compiler/Klang/ContextAnalysis.java +++ b/src/main/java/de/hsrm/compiler/Klang/ContextAnalysis.java @@ -66,38 +66,33 @@ public class ContextAnalysis extends KlangBaseVisitor { } @Override - public Node visitMultiplicationExpression(KlangParser.MultiplicationExpressionContext ctx) { - Node left = this.visit(ctx.atom(0)); - Node right = this.visit(ctx.atom(1)); - Node result = new MultiplicativeExpression((Expression) left, (Expression) right); - result.type = left.type; // We have to actually compute this in the future - return result; + public Node visitAdditionExpression(KlangParser.AdditionExpressionContext ctx) { + return new AdditionExpression((Expression) this.visit(ctx.lhs), (Expression) this.visit(ctx.rhs)); } @Override - public Node visitAdditiveExpression(KlangParser.AdditiveExpressionContext ctx) { - Node left = this.visit(ctx.atom(0)); - Node right = this.visit(ctx.atom(1)); - Node result = new AdditiveExpression((Expression) left, (Expression) right); - result.type = left.type; // We have to actually compute this in the future - return result; + public Node visitSubstractionExpression(KlangParser.SubstractionExpressionContext ctx) { + return new SubstractionExpression((Expression) this.visit(ctx.lhs), (Expression) this.visit(ctx.rhs)); + } + + @Override + public Node visitMultiplicationExpression(KlangParser.MultiplicationExpressionContext ctx) { + return new MultiplicationExpression((Expression) this.visit(ctx.lhs), (Expression) this.visit(ctx.rhs)); + } + + @Override + public Node visitDivisionExpression(KlangParser.DivisionExpressionContext ctx) { + return new DivisionExpression((Expression) this.visit(ctx.lhs), (Expression) this.visit(ctx.rhs)); } @Override public Node visitModuloExpression(KlangParser.ModuloExpressionContext ctx) { - Node left = this.visit(ctx.atom(0)); - Node right = this.visit(ctx.atom(1)); - Node result = new ModuloExpression((Expression) left, (Expression) right); - result.type = left.type; // We have to actually compute this in the future - return result; + return new ModuloExpression((Expression) this.visit(ctx.lhs), (Expression) this.visit(ctx.rhs)); } @Override - public Node visitUnaryNegateExpression(KlangParser.UnaryNegateExpressionContext ctx) { - Node atom = this.visit(ctx.atom()); - Node result = new NegateExpression((Expression) atom); - result.type = atom.type; - return result; + public Node visitNegateExpression(KlangParser.NegateExpressionContext ctx) { + return new NegateExpression((Expression) this.visit(ctx.expression())); } @Override diff --git a/src/main/java/de/hsrm/compiler/Klang/JSVisitor.java b/src/main/java/de/hsrm/compiler/Klang/JSVisitor.java deleted file mode 100644 index a2054c7..0000000 --- a/src/main/java/de/hsrm/compiler/Klang/JSVisitor.java +++ /dev/null @@ -1,71 +0,0 @@ -package de.hsrm.compiler.Klang; - -public class JSVisitor extends KlangBaseVisitor { - private final StringBuilder sb; - - public JSVisitor(StringBuilder sb) { - this.sb = sb; - } - - @Override - public Void visitStatement(KlangParser.StatementContext ctx) { - for (int i = 0; i < ctx.children.size(); i++) { - this.visit(ctx.children.get(i)); - sb.append("\n"); - } - return null; - } - - @Override - public Void visitPrint(KlangParser.PrintContext ctx) { - sb.append("console.log("); - this.visit(ctx.expression()); - sb.append(");"); - return null; - } - - @Override - public Void visitMultiplicationExpression(KlangParser.MultiplicationExpressionContext ctx) { - this.visit(ctx.atom(0)); - sb.append(" * "); - this.visit(ctx.atom(1)); - return null; - } - - @Override - public Void visitAdditiveExpression(KlangParser.AdditiveExpressionContext ctx) { - this.visit(ctx.atom(0)); - - switch (ctx.op.getType()) { - case KlangParser.ADD: - sb.append(" + "); - break; - case KlangParser.SUB: - sb.append(" - "); - break; - } - this.visit(ctx.atom(1)); - return null; - } - - @Override - public Void visitModuloExpression(KlangParser.ModuloExpressionContext ctx) { - this.visit(ctx.atom(0)); - sb.append(" % "); - this.visit(ctx.atom(1)); - return null; - } - - @Override - public Void visitUnaryNegateExpression(KlangParser.UnaryNegateExpressionContext ctx) { - sb.append("-"); - this.visit(ctx.atom()); - return null; - } - - @Override - public Void visitIntAtom(KlangParser.IntAtomContext ctx) { - sb.append(ctx.getText()); - return null; - } -} \ No newline at end of file diff --git a/src/main/java/de/hsrm/compiler/Klang/nodes/expressions/AdditiveExpression.java b/src/main/java/de/hsrm/compiler/Klang/nodes/expressions/AdditionExpression.java similarity index 64% rename from src/main/java/de/hsrm/compiler/Klang/nodes/expressions/AdditiveExpression.java rename to src/main/java/de/hsrm/compiler/Klang/nodes/expressions/AdditionExpression.java index 0c81e60..34e840c 100644 --- a/src/main/java/de/hsrm/compiler/Klang/nodes/expressions/AdditiveExpression.java +++ b/src/main/java/de/hsrm/compiler/Klang/nodes/expressions/AdditionExpression.java @@ -2,9 +2,8 @@ package de.hsrm.compiler.Klang.nodes.expressions; import de.hsrm.compiler.Klang.visitors.Visitor; -public class AdditiveExpression extends BinaryExpression { - - public AdditiveExpression(Expression lhs, Expression rhs) { +public class AdditionExpression extends BinaryExpression { + public AdditionExpression(Expression lhs, Expression rhs) { super(lhs, rhs); } @@ -12,5 +11,4 @@ public class AdditiveExpression extends BinaryExpression { public R welcome(Visitor v) { return v.visit(this); } - } \ No newline at end of file diff --git a/src/main/java/de/hsrm/compiler/Klang/nodes/expressions/BinaryExpression.java b/src/main/java/de/hsrm/compiler/Klang/nodes/expressions/BinaryExpression.java index 2ac71e7..e7f06bc 100644 --- a/src/main/java/de/hsrm/compiler/Klang/nodes/expressions/BinaryExpression.java +++ b/src/main/java/de/hsrm/compiler/Klang/nodes/expressions/BinaryExpression.java @@ -1,7 +1,6 @@ package de.hsrm.compiler.Klang.nodes.expressions; public abstract class BinaryExpression extends Expression { - public Expression lhs; public Expression rhs; diff --git a/src/main/java/de/hsrm/compiler/Klang/nodes/expressions/DivisionExpression.java b/src/main/java/de/hsrm/compiler/Klang/nodes/expressions/DivisionExpression.java new file mode 100644 index 0000000..325c188 --- /dev/null +++ b/src/main/java/de/hsrm/compiler/Klang/nodes/expressions/DivisionExpression.java @@ -0,0 +1,14 @@ +package de.hsrm.compiler.Klang.nodes.expressions; + +import de.hsrm.compiler.Klang.visitors.Visitor; + +public class DivisionExpression extends BinaryExpression { + public DivisionExpression(Expression lhs, Expression rhs) { + super(lhs, rhs); + } + + @Override + public R welcome(Visitor v) { + return v.visit(this); + } +} \ No newline at end of file diff --git a/src/main/java/de/hsrm/compiler/Klang/nodes/expressions/ModuloExpression.java b/src/main/java/de/hsrm/compiler/Klang/nodes/expressions/ModuloExpression.java index ee613e1..89e99da 100644 --- a/src/main/java/de/hsrm/compiler/Klang/nodes/expressions/ModuloExpression.java +++ b/src/main/java/de/hsrm/compiler/Klang/nodes/expressions/ModuloExpression.java @@ -3,7 +3,6 @@ package de.hsrm.compiler.Klang.nodes.expressions; import de.hsrm.compiler.Klang.visitors.Visitor; public class ModuloExpression extends BinaryExpression { - public ModuloExpression(Expression lhs, Expression rhs) { super(lhs, rhs); } @@ -12,5 +11,4 @@ public class ModuloExpression extends BinaryExpression { public R welcome(Visitor v) { return v.visit(this); } - } \ No newline at end of file diff --git a/src/main/java/de/hsrm/compiler/Klang/nodes/expressions/MultiplicativeExpression.java b/src/main/java/de/hsrm/compiler/Klang/nodes/expressions/MultiplicationExpression.java similarity index 50% rename from src/main/java/de/hsrm/compiler/Klang/nodes/expressions/MultiplicativeExpression.java rename to src/main/java/de/hsrm/compiler/Klang/nodes/expressions/MultiplicationExpression.java index 3ddd060..e8719d9 100644 --- a/src/main/java/de/hsrm/compiler/Klang/nodes/expressions/MultiplicativeExpression.java +++ b/src/main/java/de/hsrm/compiler/Klang/nodes/expressions/MultiplicationExpression.java @@ -1,9 +1,9 @@ package de.hsrm.compiler.Klang.nodes.expressions; -import de.hsrm.compiler.Klang.visitors.Visitor;; +import de.hsrm.compiler.Klang.visitors.Visitor; -public class MultiplicativeExpression extends BinaryExpression { - public MultiplicativeExpression(Expression lhs, Expression rhs) { +public class MultiplicationExpression extends BinaryExpression { + public MultiplicationExpression(Expression lhs, Expression rhs) { super(lhs, rhs); } diff --git a/src/main/java/de/hsrm/compiler/Klang/nodes/expressions/SubstractionExpression.java b/src/main/java/de/hsrm/compiler/Klang/nodes/expressions/SubstractionExpression.java new file mode 100644 index 0000000..9bc48a4 --- /dev/null +++ b/src/main/java/de/hsrm/compiler/Klang/nodes/expressions/SubstractionExpression.java @@ -0,0 +1,14 @@ +package de.hsrm.compiler.Klang.nodes.expressions; + +import de.hsrm.compiler.Klang.visitors.Visitor; + +public class SubstractionExpression extends BinaryExpression { + public SubstractionExpression(Expression lhs, Expression rhs) { + super(lhs, rhs); + } + + @Override + public R welcome(Visitor v) { + return v.visit(this); + } +} \ No newline at end of file diff --git a/src/main/java/de/hsrm/compiler/Klang/visitors/EvalVisitor.java b/src/main/java/de/hsrm/compiler/Klang/visitors/EvalVisitor.java index 300360f..7142326 100644 --- a/src/main/java/de/hsrm/compiler/Klang/visitors/EvalVisitor.java +++ b/src/main/java/de/hsrm/compiler/Klang/visitors/EvalVisitor.java @@ -21,24 +21,38 @@ public class EvalVisitor implements Visitor { } @Override - public Value visit(MultiplicativeExpression e) { - Value a = e.lhs.welcome(this); - Value b = e.rhs.welcome(this); - return new Value(a.asInteger() * b.asInteger()); + public Value visit(AdditionExpression e) { + Value lhs = e.lhs.welcome(this); + Value rhs = e.rhs.welcome(this); + return new Value(lhs.asInteger() + rhs.asInteger()); } @Override - public Value visit(AdditiveExpression e) { - Value a = e.lhs.welcome(this); - Value b = e.rhs.welcome(this); - return new Value(a.asInteger() + b.asInteger()); + public Value visit(SubstractionExpression e) { + Value lhs = e.lhs.welcome(this); + Value rhs = e.rhs.welcome(this); + 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 public Value visit(ModuloExpression e) { - Value a = e.lhs.welcome(this); - Value b = e.rhs.welcome(this); - return new Value(a.asInteger() % b.asInteger()); + Value lhs = e.lhs.welcome(this); + Value rhs = e.rhs.welcome(this); + return new Value(lhs.asInteger() % rhs.asInteger()); } @Override @@ -52,7 +66,7 @@ public class EvalVisitor implements Visitor { Value result = this.env.get(e.name); 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; @@ -123,7 +137,7 @@ public class EvalVisitor implements Visitor { // Stelle sicher, dass die Länge der argumente und parameter übereinstimmen 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 @@ -147,7 +161,7 @@ public class EvalVisitor implements Visitor { public Value visit(Program e) { // Funktionsdefinitionen für die Auswertung // von Funktionsaufrufen speichern - for (var funcDef: e.funcs) { + for (var funcDef : e.funcs) { this.funcs.put(funcDef.name, funcDef); } diff --git a/src/main/java/de/hsrm/compiler/Klang/visitors/GenASM.java b/src/main/java/de/hsrm/compiler/Klang/visitors/GenASM.java index f82e50c..cc01a65 100644 --- a/src/main/java/de/hsrm/compiler/Klang/visitors/GenASM.java +++ b/src/main/java/de/hsrm/compiler/Klang/visitors/GenASM.java @@ -6,249 +6,263 @@ import java.util.Map; import java.util.Set; import java.util.TreeSet; -import de.hsrm.compiler.Klang.nodes.Block; -import de.hsrm.compiler.Klang.nodes.FunctionDefinition; -import de.hsrm.compiler.Klang.nodes.Program; -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; +import de.hsrm.compiler.Klang.nodes.*; +import de.hsrm.compiler.Klang.nodes.expressions.*; +import de.hsrm.compiler.Klang.nodes.statements.*; public class GenASM implements Visitor { - public static class ExWriter { - Writer w; - String indent = ""; + public static class ExWriter { + Writer w; + String indent = ""; - void addIndent() { - 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); - } - } + void addIndent() { + indent = indent + " "; } - public ExWriter ex; - Map env = new HashMap<>(); - Set vars; - String[] rs = { "%rdi", "%rsi", "%rdx", "%rcx", "%r8", "%r9" }; - private int lCount = 0; // Invariante: lCount ist benutzt - - public GenASM(ExWriter ex) { - this.ex = ex; + void subIndent() { + indent = indent.substring(2); } - @Override - public Void visit(IntegerExpression e) { - this.ex.write(" movq $" + e.value + ", %rax\n"); - return null; + void nl() { + write("\n" + indent); } - @Override - public Void visit(Variable e) { - this.ex.write(" movq " +this.env.get(e.name) +"(%rbp), %rax\n"); - return null; + int lbl = 0; + + int next() { + return lbl++; } - @Override - public Void visit(MultiplicativeExpression e) { - e.lhs.welcome(this); - this.ex.write(" movq %rax, %rbx\n"); - e.rhs.welcome(this); - this.ex.write(" imulq %rbx, %rax\n"); - return null; + public ExWriter(Writer w) { + this.w = w; } - @Override - public Void visit(AdditiveExpression e) { - e.lhs.welcome(this); - this.ex.write(" movq %rax, %rbx\n"); - e.rhs.welcome(this); - this.ex.write(" addq %rbx, %rax\n"); - return null; + void lnwrite(Object o) { + nl(); + write(o); } - @Override - public Void visit(NegateExpression e) { - e.lhs.welcome(this); - this.ex.write(" neg %rax\n"); - return null; + void write(Object o) { + try { + w.write(o + ""); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + } + + public ExWriter ex; + Map env = new HashMap<>(); + Set 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(); + GetVars getvars = new GetVars(vars); + getvars.visit(e); + + // Erzeuge ein environment + this.env = new HashMap(); + + // 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 - public Void visit(ModuloExpression e) { - e.rhs.welcome(this); - this.ex.write(" movq %rax, %rbx\n"); - e.lhs.welcome(this); - this.ex.write(" xor %rdx, %rdx\n"); // clear remainder register - this.ex.write(" idiv %ebx\n"); // %rax/%rbx, remainder now in %rdx - this.ex.write(" movq %rdx, %rax\n"); - return null; + // 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 } - @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; + // 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); } - @Override - public Void visit(PrintStatement e) { - throw new RuntimeException("Das machen wir mal nicht, ne?!"); + 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"); } - @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; + // Den Rest auf den stack pushen + for (int i = this.rs.length; i < e.arguments.length; i++) { + e.arguments[i].welcome(this); } - @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; + 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); - @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(); - GetVars getvars = new GetVars(vars); - getvars.visit(e); - - // Erzeuge ein environment - this.env = new HashMap(); - - // 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; - } + this.ex.write(" movq %rbp, %rsp\n"); + this.ex.write(" popq %rbp\n"); + this.ex.write(" ret\n"); + return null; + } } \ No newline at end of file diff --git a/src/main/java/de/hsrm/compiler/Klang/visitors/GetVars.java b/src/main/java/de/hsrm/compiler/Klang/visitors/GetVars.java index ebf004f..8c7444d 100644 --- a/src/main/java/de/hsrm/compiler/Klang/visitors/GetVars.java +++ b/src/main/java/de/hsrm/compiler/Klang/visitors/GetVars.java @@ -2,20 +2,9 @@ package de.hsrm.compiler.Klang.visitors; import java.util.Set; -import de.hsrm.compiler.Klang.nodes.Block; -import de.hsrm.compiler.Klang.nodes.FunctionDefinition; -import de.hsrm.compiler.Klang.nodes.Program; -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; +import de.hsrm.compiler.Klang.nodes.*; +import de.hsrm.compiler.Klang.nodes.expressions.*; +import de.hsrm.compiler.Klang.nodes.statements.*; class GetVars implements Visitor { @@ -36,14 +25,35 @@ class GetVars implements Visitor { } @Override - public Void visit(MultiplicativeExpression e) { + public Void visit(AdditionExpression e) { e.lhs.welcome(this); e.rhs.welcome(this); return null; } @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.rhs.welcome(this); return null; @@ -55,13 +65,6 @@ class GetVars implements Visitor { return null; } - @Override - public Void visit(ModuloExpression e) { - e.lhs.welcome(this); - e.rhs.welcome(this); - return null; - } - @Override public Void visit(IfStatement e) { e.cond.welcome(this); diff --git a/src/main/java/de/hsrm/compiler/Klang/visitors/PrettyPrintVisitor.java b/src/main/java/de/hsrm/compiler/Klang/visitors/PrettyPrintVisitor.java index fed3c01..0e74dc0 100644 --- a/src/main/java/de/hsrm/compiler/Klang/visitors/PrettyPrintVisitor.java +++ b/src/main/java/de/hsrm/compiler/Klang/visitors/PrettyPrintVisitor.java @@ -72,33 +72,60 @@ public class PrettyPrintVisitor implements Visitor { } @Override - public Void visit(MultiplicativeExpression e) { - e.lhs.welcome(this); - ex.write(" * "); - e.rhs.welcome(this); - return null; - } - - @Override - public Void visit(AdditiveExpression e) { + public Void visit(AdditionExpression e) { + ex.write("("); e.lhs.welcome(this); ex.write(" + "); e.rhs.welcome(this); + ex.write(")"); return null; } @Override - public Void visit(NegateExpression e) { - ex.write(" - "); + public Void visit(SubstractionExpression e) { + ex.write("("); 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; } @Override public Void visit(ModuloExpression e) { + ex.write("("); e.lhs.welcome(this); ex.write(" % "); e.rhs.welcome(this); + ex.write(")"); + return null; + } + + + @Override + public Void visit(NegateExpression e) { + ex.write(" - "); + e.lhs.welcome(this); return null; } diff --git a/src/main/java/de/hsrm/compiler/Klang/visitors/Visitor.java b/src/main/java/de/hsrm/compiler/Klang/visitors/Visitor.java index 456c8cd..662500d 100644 --- a/src/main/java/de/hsrm/compiler/Klang/visitors/Visitor.java +++ b/src/main/java/de/hsrm/compiler/Klang/visitors/Visitor.java @@ -9,10 +9,12 @@ import de.hsrm.compiler.Klang.nodes.statements.*; public interface Visitor { R visit(IntegerExpression e); R visit(Variable e); - R visit(MultiplicativeExpression e); - R visit(AdditiveExpression e); - R visit(NegateExpression e); + R visit(AdditionExpression e); + R visit(SubstractionExpression e); + R visit(MultiplicationExpression e); + R visit(DivisionExpression e); R visit(ModuloExpression e); + R visit(NegateExpression e); R visit(IfStatement e); R visit(PrintStatement e); R visit(VariableAssignment e);