Merge branch '32-create-asm-class-structure' into 'master'
32: Create Meta ASM Structure Closes #32 See merge request mkais001/klang!23
This commit is contained in:
@@ -129,11 +129,8 @@ public class Klang {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Generate assembler code
|
// Generate assembler code
|
||||||
// System.out.println("\nPrinting the assembler code");
|
GenASM genasm = new GenASM(mainName, structs);
|
||||||
StringWriter wAsm = new StringWriter();
|
|
||||||
GenASM.ExWriter exAsm = new GenASM.ExWriter(wAsm);
|
|
||||||
GenASM genasm = new GenASM(exAsm, mainName, structs);
|
|
||||||
root.welcome(genasm);
|
root.welcome(genasm);
|
||||||
generateOutput(out, wAsm.toString());
|
generateOutput(out, genasm.toAsm());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
218
src/main/java/de/hsrm/compiler/Klang/asm/ASM.java
Normal file
218
src/main/java/de/hsrm/compiler/Klang/asm/ASM.java
Normal file
@@ -0,0 +1,218 @@
|
|||||||
|
package de.hsrm.compiler.Klang.asm;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import de.hsrm.compiler.Klang.asm.mnemonics.*;
|
||||||
|
|
||||||
|
public class ASM {
|
||||||
|
private List<Mnemonic> mnemonics;
|
||||||
|
|
||||||
|
public ASM() {
|
||||||
|
this.mnemonics = new ArrayList<Mnemonic>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void push(String dataType, int immediate) {
|
||||||
|
mnemonics.add(new Push(dataType, immediate));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void push(String dataType, String operand) {
|
||||||
|
mnemonics.add(new Push(dataType, operand));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void pop(String dataType, String operand) {
|
||||||
|
mnemonics.add(new Pop(dataType, operand));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void mov(String dataType, String src, String dst) {
|
||||||
|
mnemonics.add(new Mov(dataType, src, dst));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void mov(String dataType, String label, String src, String dst) {
|
||||||
|
mnemonics.add(new Mov(dataType, label, src, dst));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void mov(String dataType, int offset, String src, String dst) {
|
||||||
|
mnemonics.add(new Mov(dataType, offset, src, dst));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void mov(String dataType, String src, int offset, String dst) {
|
||||||
|
mnemonics.add(new Mov(dataType, src, offset, dst));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void mov(String dataType, int immediate, String dst) {
|
||||||
|
mnemonics.add(new Mov(dataType, immediate, dst));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ucomi(String dataType, String src, String dst) {
|
||||||
|
mnemonics.add(new Ucomi(dataType, src, dst));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void cmp(String dataType, String src, String dst) {
|
||||||
|
mnemonics.add(new Cmp(dataType, src, dst));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void cmp(String dataType, int immediate, String dst) {
|
||||||
|
mnemonics.add(new Cmp(dataType, immediate, dst));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void je(int label) {
|
||||||
|
mnemonics.add(new Je(label));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void je(String labelPrefix, int label) {
|
||||||
|
mnemonics.add(new Je(labelPrefix, label));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void jmp(int label) {
|
||||||
|
mnemonics.add(new Jmp(label));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void jmp(String labelPrefix, int label) {
|
||||||
|
mnemonics.add(new Jmp(labelPrefix, label));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void jne(int label) {
|
||||||
|
mnemonics.add(new Jne(label));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void jne(String labelPrefix, int label) {
|
||||||
|
mnemonics.add(new Jne(labelPrefix, label));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void jg(int label) {
|
||||||
|
mnemonics.add(new Jg(label));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void jg(String labelPrefix, int label) {
|
||||||
|
mnemonics.add(new Jg(labelPrefix, label));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void jge(int label) {
|
||||||
|
mnemonics.add(new Jge(label));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void jge(String labelPrefix, int label) {
|
||||||
|
mnemonics.add(new Jge(labelPrefix, label));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void jl(int label) {
|
||||||
|
mnemonics.add(new Jl(label));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void jl(String labelPrefix, int label) {
|
||||||
|
mnemonics.add(new Jl(labelPrefix, label));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void jle(int label) {
|
||||||
|
mnemonics.add(new Jle(label));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void jle(String labelPrefix, int label) {
|
||||||
|
mnemonics.add(new Jle(labelPrefix, label));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void jz(int label) {
|
||||||
|
mnemonics.add(new Jz(label));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void jz(String labelPrefix, int label) {
|
||||||
|
mnemonics.add(new Jz(labelPrefix, label));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void jnz(int label) {
|
||||||
|
mnemonics.add(new Jnz(label));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void jnz(String labelPrefix, int label) {
|
||||||
|
mnemonics.add(new Jnz(labelPrefix, label));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void label(int label) {
|
||||||
|
mnemonics.add(new Label(label));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void label(String labelPrefix, int label) {
|
||||||
|
mnemonics.add(new Label(labelPrefix, label));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void add(String dataType, String src, String dst) {
|
||||||
|
mnemonics.add(new Add(dataType, src, dst));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void add(String dataType, String src, int dstOffset, String dst) {
|
||||||
|
mnemonics.add(new Add(dataType, src, dstOffset, dst));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void add(String dataType, int immediate, String dst) {
|
||||||
|
mnemonics.add(new Add(dataType, immediate, dst));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sub(String dataType, String src, String dst) {
|
||||||
|
mnemonics.add(new Sub(dataType, src, dst));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void mul(String dataType, String src, String dst) {
|
||||||
|
mnemonics.add(new Mul(dataType, src, dst));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void div(String dataType, String src, String dst) {
|
||||||
|
mnemonics.add(new Div(dataType, src, dst));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void idiv(String dataType, String operand) {
|
||||||
|
mnemonics.add(new Idiv(dataType, operand));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void imul(String dataType, String src, String dst) {
|
||||||
|
mnemonics.add(new Imul(dataType, src, dst));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void cqto() {
|
||||||
|
mnemonics.add(new Cqto());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ret() {
|
||||||
|
mnemonics.add(new Ret());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void xor(String dataType, String src, String dst) {
|
||||||
|
mnemonics.add(new Xor(dataType, src, dst));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void neg(String operand) {
|
||||||
|
mnemonics.add(new Neg(operand));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void functionHead(String functionName) {
|
||||||
|
mnemonics.add(new FunctionHead(functionName));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void call(String operand) {
|
||||||
|
mnemonics.add(new Call(operand));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void text(String text) {
|
||||||
|
mnemonics.add(new Text(text));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void newline() {
|
||||||
|
mnemonics.add(new Newline());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void cvtsi2sd(String src, String dst) {
|
||||||
|
mnemonics.add(new Cvtsi2sd(src, dst));
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toAsm() {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
mnemonics.stream().forEach(x -> {
|
||||||
|
for (int i = 0; i < x.indentation; i++) {
|
||||||
|
sb.append("\t");
|
||||||
|
}
|
||||||
|
sb.append(x.toAsm());
|
||||||
|
sb.append("\n");
|
||||||
|
});
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
29
src/main/java/de/hsrm/compiler/Klang/asm/mnemonics/Add.java
Normal file
29
src/main/java/de/hsrm/compiler/Klang/asm/mnemonics/Add.java
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
package de.hsrm.compiler.Klang.asm.mnemonics;
|
||||||
|
|
||||||
|
public class Add extends TwoOperandMnemonic {
|
||||||
|
public String dataType;
|
||||||
|
|
||||||
|
public Add(String dataType, String src, String dst) {
|
||||||
|
this.dataType = dataType;
|
||||||
|
this.src = src;
|
||||||
|
this.dst = dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Add(String dataType, String src, int dstOffset, String dst) {
|
||||||
|
this.dataType = dataType;
|
||||||
|
this.src = src;
|
||||||
|
this.dst = dstOffset + "(" + dst + ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
public Add(String dataType, int immediate, String dst) {
|
||||||
|
this.dataType = dataType;
|
||||||
|
this.src = "$" + immediate;
|
||||||
|
this.dst = dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toAsm() {
|
||||||
|
return "add" + this.dataType + " " + this.src + ", " + this.dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
14
src/main/java/de/hsrm/compiler/Klang/asm/mnemonics/Call.java
Normal file
14
src/main/java/de/hsrm/compiler/Klang/asm/mnemonics/Call.java
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
package de.hsrm.compiler.Klang.asm.mnemonics;
|
||||||
|
|
||||||
|
public class Call extends OneOperandMnemonic {
|
||||||
|
|
||||||
|
public Call(String operand) {
|
||||||
|
this.operand = operand;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toAsm() {
|
||||||
|
return "call " + this.operand;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
22
src/main/java/de/hsrm/compiler/Klang/asm/mnemonics/Cmp.java
Normal file
22
src/main/java/de/hsrm/compiler/Klang/asm/mnemonics/Cmp.java
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
package de.hsrm.compiler.Klang.asm.mnemonics;
|
||||||
|
|
||||||
|
public class Cmp extends TwoOperandMnemonic {
|
||||||
|
public String dataType;
|
||||||
|
|
||||||
|
public Cmp(String dataType, String src, String dst) {
|
||||||
|
this.dataType = dataType;
|
||||||
|
this.src = src;
|
||||||
|
this.dst = dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Cmp(String dataType, int immediate, String dst) {
|
||||||
|
this.dataType = dataType;
|
||||||
|
this.src = "$" + immediate;
|
||||||
|
this.dst = dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toAsm() {
|
||||||
|
return "cmp" + this.dataType + " " + this.src + ", " + this.dst;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package de.hsrm.compiler.Klang.asm.mnemonics;
|
||||||
|
|
||||||
|
public class Cqto extends NoOperandMnemonic {
|
||||||
|
@Override
|
||||||
|
public String toAsm() {
|
||||||
|
return "cqto";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package de.hsrm.compiler.Klang.asm.mnemonics;
|
||||||
|
|
||||||
|
public class Cvtsi2sd extends TwoOperandMnemonic {
|
||||||
|
|
||||||
|
public Cvtsi2sd(String src, String dst) {
|
||||||
|
this.src = src;
|
||||||
|
this.dst = dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toAsm() {
|
||||||
|
return "cvtsi2sd " + this.src + ", " + this.dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
17
src/main/java/de/hsrm/compiler/Klang/asm/mnemonics/Div.java
Normal file
17
src/main/java/de/hsrm/compiler/Klang/asm/mnemonics/Div.java
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
package de.hsrm.compiler.Klang.asm.mnemonics;
|
||||||
|
|
||||||
|
public class Div extends TwoOperandMnemonic {
|
||||||
|
public String dataType;
|
||||||
|
|
||||||
|
public Div(String dataType, String src, String dst) {
|
||||||
|
this.dataType = dataType;
|
||||||
|
this.src = src;
|
||||||
|
this.dst = dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toAsm() {
|
||||||
|
return "div" + this.dataType + " " + this.src + ", " + this.dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package de.hsrm.compiler.Klang.asm.mnemonics;
|
||||||
|
|
||||||
|
public class FunctionHead extends NoOperandMnemonic {
|
||||||
|
|
||||||
|
public String functionName;
|
||||||
|
|
||||||
|
public FunctionHead(String functionName) {
|
||||||
|
this.functionName = functionName;
|
||||||
|
this.indentation = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toAsm() {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append(".globl ");
|
||||||
|
sb.append(this.functionName);
|
||||||
|
sb.append("\n");
|
||||||
|
sb.append(".type ");
|
||||||
|
sb.append(this.functionName);
|
||||||
|
sb.append(", @function\n");
|
||||||
|
sb.append(this.functionName);
|
||||||
|
sb.append(":");
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
16
src/main/java/de/hsrm/compiler/Klang/asm/mnemonics/Idiv.java
Normal file
16
src/main/java/de/hsrm/compiler/Klang/asm/mnemonics/Idiv.java
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
package de.hsrm.compiler.Klang.asm.mnemonics;
|
||||||
|
|
||||||
|
public class Idiv extends OneOperandMnemonic{
|
||||||
|
public String dataType;
|
||||||
|
|
||||||
|
public Idiv(String dataType, String operand) {
|
||||||
|
this.dataType = dataType;
|
||||||
|
this.operand = operand;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toAsm() {
|
||||||
|
return "idiv" + this.dataType + " " + this.operand;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
17
src/main/java/de/hsrm/compiler/Klang/asm/mnemonics/Imul.java
Normal file
17
src/main/java/de/hsrm/compiler/Klang/asm/mnemonics/Imul.java
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
package de.hsrm.compiler.Klang.asm.mnemonics;
|
||||||
|
|
||||||
|
public class Imul extends TwoOperandMnemonic {
|
||||||
|
public String dataType;
|
||||||
|
|
||||||
|
public Imul(String dataType, String src, String dst) {
|
||||||
|
this.dataType = dataType;
|
||||||
|
this.src = src;
|
||||||
|
this.dst = dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toAsm() {
|
||||||
|
return "imul" + this.dataType + " " + this.src + ", " + this.dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
12
src/main/java/de/hsrm/compiler/Klang/asm/mnemonics/Je.java
Normal file
12
src/main/java/de/hsrm/compiler/Klang/asm/mnemonics/Je.java
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
package de.hsrm.compiler.Klang.asm.mnemonics;
|
||||||
|
|
||||||
|
public class Je extends Jump {
|
||||||
|
|
||||||
|
public Je(int label) {
|
||||||
|
super("je", label);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Je(String labelPrefix, int label) {
|
||||||
|
super("je", labelPrefix, label);
|
||||||
|
}
|
||||||
|
}
|
||||||
11
src/main/java/de/hsrm/compiler/Klang/asm/mnemonics/Jg.java
Normal file
11
src/main/java/de/hsrm/compiler/Klang/asm/mnemonics/Jg.java
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
package de.hsrm.compiler.Klang.asm.mnemonics;
|
||||||
|
|
||||||
|
public class Jg extends Jump {
|
||||||
|
public Jg(int label) {
|
||||||
|
super("jg", label);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Jg(String labelPrefix, int label) {
|
||||||
|
super("jg", labelPrefix, label);
|
||||||
|
}
|
||||||
|
}
|
||||||
11
src/main/java/de/hsrm/compiler/Klang/asm/mnemonics/Jge.java
Normal file
11
src/main/java/de/hsrm/compiler/Klang/asm/mnemonics/Jge.java
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
package de.hsrm.compiler.Klang.asm.mnemonics;
|
||||||
|
|
||||||
|
public class Jge extends Jump {
|
||||||
|
public Jge(int label) {
|
||||||
|
super("jge", label);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Jge(String labelPrefix, int label) {
|
||||||
|
super("jge", labelPrefix, label);
|
||||||
|
}
|
||||||
|
}
|
||||||
11
src/main/java/de/hsrm/compiler/Klang/asm/mnemonics/Jl.java
Normal file
11
src/main/java/de/hsrm/compiler/Klang/asm/mnemonics/Jl.java
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
package de.hsrm.compiler.Klang.asm.mnemonics;
|
||||||
|
|
||||||
|
public class Jl extends Jump {
|
||||||
|
public Jl(int label) {
|
||||||
|
super("jl", label);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Jl(String labelPrefix, int label) {
|
||||||
|
super("jl", labelPrefix, label);
|
||||||
|
}
|
||||||
|
}
|
||||||
11
src/main/java/de/hsrm/compiler/Klang/asm/mnemonics/Jle.java
Normal file
11
src/main/java/de/hsrm/compiler/Klang/asm/mnemonics/Jle.java
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
package de.hsrm.compiler.Klang.asm.mnemonics;
|
||||||
|
|
||||||
|
public class Jle extends Jump {
|
||||||
|
public Jle(int label) {
|
||||||
|
super("jle", label);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Jle(String labelPrefix, int label) {
|
||||||
|
super("jle", labelPrefix, label);
|
||||||
|
}
|
||||||
|
}
|
||||||
11
src/main/java/de/hsrm/compiler/Klang/asm/mnemonics/Jmp.java
Normal file
11
src/main/java/de/hsrm/compiler/Klang/asm/mnemonics/Jmp.java
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
package de.hsrm.compiler.Klang.asm.mnemonics;
|
||||||
|
|
||||||
|
public class Jmp extends Jump {
|
||||||
|
public Jmp(String labelPrefix, int label) {
|
||||||
|
super("jmp", labelPrefix, label);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Jmp(int label) {
|
||||||
|
super("jmp", label);
|
||||||
|
}
|
||||||
|
}
|
||||||
11
src/main/java/de/hsrm/compiler/Klang/asm/mnemonics/Jne.java
Normal file
11
src/main/java/de/hsrm/compiler/Klang/asm/mnemonics/Jne.java
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
package de.hsrm.compiler.Klang.asm.mnemonics;
|
||||||
|
|
||||||
|
public class Jne extends Jump {
|
||||||
|
public Jne(int label) {
|
||||||
|
super("jne", label);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Jne(String labelPrefix, int label) {
|
||||||
|
super("jne", labelPrefix, label);
|
||||||
|
}
|
||||||
|
}
|
||||||
11
src/main/java/de/hsrm/compiler/Klang/asm/mnemonics/Jnz.java
Normal file
11
src/main/java/de/hsrm/compiler/Klang/asm/mnemonics/Jnz.java
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
package de.hsrm.compiler.Klang.asm.mnemonics;
|
||||||
|
|
||||||
|
public class Jnz extends Jump {
|
||||||
|
public Jnz(int label) {
|
||||||
|
super("jnz", label);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Jnz(String labelPrefix, int label) {
|
||||||
|
super("jnz", labelPrefix, label);
|
||||||
|
}
|
||||||
|
}
|
||||||
21
src/main/java/de/hsrm/compiler/Klang/asm/mnemonics/Jump.java
Normal file
21
src/main/java/de/hsrm/compiler/Klang/asm/mnemonics/Jump.java
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
package de.hsrm.compiler.Klang.asm.mnemonics;
|
||||||
|
|
||||||
|
public abstract class Jump extends Mnemonic {
|
||||||
|
protected String opcode;
|
||||||
|
public String labelPrefix = "L";
|
||||||
|
public int label;
|
||||||
|
public Jump(String opcode, String labelPrefix, int label) {
|
||||||
|
this.opcode = opcode;
|
||||||
|
this.labelPrefix = labelPrefix;
|
||||||
|
this.label = label;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Jump(String opcode, int label) {
|
||||||
|
this.opcode = opcode;
|
||||||
|
this.label = label;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public String toAsm() {
|
||||||
|
return this.opcode + " ." + this.labelPrefix + this.label;
|
||||||
|
}
|
||||||
|
}
|
||||||
11
src/main/java/de/hsrm/compiler/Klang/asm/mnemonics/Jz.java
Normal file
11
src/main/java/de/hsrm/compiler/Klang/asm/mnemonics/Jz.java
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
package de.hsrm.compiler.Klang.asm.mnemonics;
|
||||||
|
|
||||||
|
public class Jz extends Jump {
|
||||||
|
public Jz(int label) {
|
||||||
|
super("jz", label);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Jz(String labelPrefix, int label) {
|
||||||
|
super("jz", labelPrefix, label);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package de.hsrm.compiler.Klang.asm.mnemonics;
|
||||||
|
|
||||||
|
public class Label extends Mnemonic {
|
||||||
|
public String labelPrefix = "L";
|
||||||
|
public int label;
|
||||||
|
|
||||||
|
public Label(int label) {
|
||||||
|
this.label = label;
|
||||||
|
this.indentation = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Label(String labelPrefix, int label) {
|
||||||
|
this.labelPrefix = labelPrefix;
|
||||||
|
this.label = label;
|
||||||
|
this.indentation = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toAsm() {
|
||||||
|
return "." + this.labelPrefix + this.label + ":";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package de.hsrm.compiler.Klang.asm.mnemonics;
|
||||||
|
|
||||||
|
public abstract class Mnemonic {
|
||||||
|
public abstract String toAsm();
|
||||||
|
public int indentation = 2;
|
||||||
|
}
|
||||||
40
src/main/java/de/hsrm/compiler/Klang/asm/mnemonics/Mov.java
Normal file
40
src/main/java/de/hsrm/compiler/Klang/asm/mnemonics/Mov.java
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
package de.hsrm.compiler.Klang.asm.mnemonics;
|
||||||
|
|
||||||
|
public class Mov extends TwoOperandMnemonic{
|
||||||
|
public String dataType = "q";
|
||||||
|
|
||||||
|
public Mov(String dataType, String src, String dst) {
|
||||||
|
this.dataType = dataType;
|
||||||
|
this.src = src;
|
||||||
|
this.dst = dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Mov(String dataType, String label, String src, String dst) {
|
||||||
|
this.dataType = dataType;
|
||||||
|
this.src = label + "(" + src + ")";
|
||||||
|
this.dst = dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Mov(String dataType, int offset, String src, String dst) {
|
||||||
|
this.dataType = dataType;
|
||||||
|
this.src = offset + "(" + src + ")";
|
||||||
|
this.dst = dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Mov(String dataType, int immediate, String dst) {
|
||||||
|
this.dataType = dataType;
|
||||||
|
this.src = "$" + immediate;
|
||||||
|
this.dst = dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Mov(String dataType, String src, int offset, String dst) {
|
||||||
|
this.dataType = dataType;
|
||||||
|
this.src = src;
|
||||||
|
this.dst = offset + "(" + dst + ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toAsm() {
|
||||||
|
return "mov" + this.dataType + " " + this.src + ", " + this.dst;
|
||||||
|
}
|
||||||
|
}
|
||||||
17
src/main/java/de/hsrm/compiler/Klang/asm/mnemonics/Mul.java
Normal file
17
src/main/java/de/hsrm/compiler/Klang/asm/mnemonics/Mul.java
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
package de.hsrm.compiler.Klang.asm.mnemonics;
|
||||||
|
|
||||||
|
public class Mul extends TwoOperandMnemonic {
|
||||||
|
public String dataType;
|
||||||
|
|
||||||
|
public Mul(String dataType, String src, String dst) {
|
||||||
|
this.dataType = dataType;
|
||||||
|
this.src = src;
|
||||||
|
this.dst = dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toAsm() {
|
||||||
|
return "mul" + this.dataType + " " + this.src + ", " + this.dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
14
src/main/java/de/hsrm/compiler/Klang/asm/mnemonics/Neg.java
Normal file
14
src/main/java/de/hsrm/compiler/Klang/asm/mnemonics/Neg.java
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
package de.hsrm.compiler.Klang.asm.mnemonics;
|
||||||
|
|
||||||
|
public class Neg extends OneOperandMnemonic {
|
||||||
|
|
||||||
|
public Neg(String operand) {
|
||||||
|
this.operand = operand;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toAsm() {
|
||||||
|
return "neg " + this.operand;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package de.hsrm.compiler.Klang.asm.mnemonics;
|
||||||
|
|
||||||
|
public class Newline extends NoOperandMnemonic {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toAsm() {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package de.hsrm.compiler.Klang.asm.mnemonics;
|
||||||
|
|
||||||
|
public abstract class NoOperandMnemonic extends Mnemonic {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package de.hsrm.compiler.Klang.asm.mnemonics;
|
||||||
|
|
||||||
|
public abstract class OneOperandMnemonic extends Mnemonic {
|
||||||
|
public String operand;
|
||||||
|
}
|
||||||
16
src/main/java/de/hsrm/compiler/Klang/asm/mnemonics/Pop.java
Normal file
16
src/main/java/de/hsrm/compiler/Klang/asm/mnemonics/Pop.java
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
package de.hsrm.compiler.Klang.asm.mnemonics;
|
||||||
|
|
||||||
|
public class Pop extends OneOperandMnemonic {
|
||||||
|
public String dataType;
|
||||||
|
|
||||||
|
public Pop(String dataType, String operand) {
|
||||||
|
this.dataType = dataType;
|
||||||
|
this.operand = operand;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toAsm() {
|
||||||
|
return "pop" + this.dataType + " " + this.operand;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
21
src/main/java/de/hsrm/compiler/Klang/asm/mnemonics/Push.java
Normal file
21
src/main/java/de/hsrm/compiler/Klang/asm/mnemonics/Push.java
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
package de.hsrm.compiler.Klang.asm.mnemonics;
|
||||||
|
|
||||||
|
public class Push extends OneOperandMnemonic {
|
||||||
|
public String dataType;
|
||||||
|
|
||||||
|
public Push(String dataType, int immediate){
|
||||||
|
this.dataType = dataType;
|
||||||
|
this.operand = "$" + immediate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Push(String dataType, String operand) {
|
||||||
|
this.dataType = dataType;
|
||||||
|
this.operand = operand;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toAsm() {
|
||||||
|
return "push" + this.dataType + " " + this.operand;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package de.hsrm.compiler.Klang.asm.mnemonics;
|
||||||
|
|
||||||
|
public class Ret extends NoOperandMnemonic {
|
||||||
|
@Override
|
||||||
|
public String toAsm() {
|
||||||
|
return "ret";
|
||||||
|
}
|
||||||
|
}
|
||||||
17
src/main/java/de/hsrm/compiler/Klang/asm/mnemonics/Sub.java
Normal file
17
src/main/java/de/hsrm/compiler/Klang/asm/mnemonics/Sub.java
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
package de.hsrm.compiler.Klang.asm.mnemonics;
|
||||||
|
|
||||||
|
public class Sub extends TwoOperandMnemonic {
|
||||||
|
public String dataType;
|
||||||
|
|
||||||
|
public Sub(String dataType, String src, String dst) {
|
||||||
|
this.dataType = dataType;
|
||||||
|
this.src = src;
|
||||||
|
this.dst = dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toAsm() {
|
||||||
|
return "sub" + this.dataType + " " + this.src + ", " + this.dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
15
src/main/java/de/hsrm/compiler/Klang/asm/mnemonics/Text.java
Normal file
15
src/main/java/de/hsrm/compiler/Klang/asm/mnemonics/Text.java
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
package de.hsrm.compiler.Klang.asm.mnemonics;
|
||||||
|
|
||||||
|
public class Text extends NoOperandMnemonic {
|
||||||
|
public String text;
|
||||||
|
|
||||||
|
public Text(String text) {
|
||||||
|
this.text = text;
|
||||||
|
this.indentation = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toAsm() {
|
||||||
|
return this.text;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package de.hsrm.compiler.Klang.asm.mnemonics;
|
||||||
|
|
||||||
|
public abstract class TwoOperandMnemonic extends Mnemonic {
|
||||||
|
public String src;
|
||||||
|
public String dst;
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package de.hsrm.compiler.Klang.asm.mnemonics;
|
||||||
|
|
||||||
|
public class Ucomi extends TwoOperandMnemonic {
|
||||||
|
public String dataType;
|
||||||
|
|
||||||
|
public Ucomi(String dataType, String src, String dst) {
|
||||||
|
this.dataType = dataType;
|
||||||
|
this.src = src;
|
||||||
|
this.dst = dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toAsm() {
|
||||||
|
return "ucomi" + this.dataType + " " + this.src + ", " + this.dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
17
src/main/java/de/hsrm/compiler/Klang/asm/mnemonics/Xor.java
Normal file
17
src/main/java/de/hsrm/compiler/Klang/asm/mnemonics/Xor.java
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
package de.hsrm.compiler.Klang.asm.mnemonics;
|
||||||
|
|
||||||
|
public class Xor extends TwoOperandMnemonic {
|
||||||
|
public String dataType;
|
||||||
|
|
||||||
|
public Xor(String dataType, String src, String dst) {
|
||||||
|
this.dataType = dataType;
|
||||||
|
this.src = src;
|
||||||
|
this.dst = dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toAsm() {
|
||||||
|
return "xor" + this.dataType + " " + this.src + ", " + this.dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
package de.hsrm.compiler.Klang.visitors;
|
package de.hsrm.compiler.Klang.visitors;
|
||||||
|
|
||||||
import java.io.*;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
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.asm.ASM;
|
||||||
import de.hsrm.compiler.Klang.helper.Helper;
|
import de.hsrm.compiler.Klang.helper.Helper;
|
||||||
import de.hsrm.compiler.Klang.nodes.*;
|
import de.hsrm.compiler.Klang.nodes.*;
|
||||||
import de.hsrm.compiler.Klang.nodes.expressions.*;
|
import de.hsrm.compiler.Klang.nodes.expressions.*;
|
||||||
@@ -17,47 +17,6 @@ import de.hsrm.compiler.Klang.nodes.statements.*;
|
|||||||
import de.hsrm.compiler.Klang.types.Type;
|
import de.hsrm.compiler.Klang.types.Type;
|
||||||
|
|
||||||
public class GenASM implements Visitor<Void> {
|
public class GenASM implements Visitor<Void> {
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class FloatWriter {
|
private class FloatWriter {
|
||||||
private StringBuilder sb = new StringBuilder();
|
private StringBuilder sb = new StringBuilder();
|
||||||
private int id = -1;
|
private int id = -1;
|
||||||
@@ -104,7 +63,7 @@ public class GenASM implements Visitor<Void> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ExWriter ex;
|
private ASM asm;
|
||||||
private FloatWriter fw = new FloatWriter();
|
private FloatWriter fw = new FloatWriter();
|
||||||
private String mainName;
|
private String mainName;
|
||||||
Map<String, Integer> env = new HashMap<>();
|
Map<String, Integer> env = new HashMap<>();
|
||||||
@@ -112,81 +71,81 @@ public class GenASM implements Visitor<Void> {
|
|||||||
Set<String> vars;
|
Set<String> vars;
|
||||||
String[] registers = { "%rdi", "%rsi", "%rdx", "%rcx", "%r8", "%r9" };
|
String[] registers = { "%rdi", "%rsi", "%rdx", "%rcx", "%r8", "%r9" };
|
||||||
String[] floatRegisters = { "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7" };
|
String[] floatRegisters = { "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7" };
|
||||||
private int lCount = 0; // Invariante: lCount ist benutzt
|
private int lCount = 0; // Invariant: lCount is used
|
||||||
private int currentFunctionStartLabel = 0;
|
private int currentFunctionStartLabel = 0;
|
||||||
private Parameter[] currentFunctionParams;
|
private Parameter[] currentFunctionParams;
|
||||||
|
|
||||||
private void intToFloat(String src, String dst) {
|
|
||||||
this.ex.write(" cvtsi2sd " + src + ", " + dst + "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean prepareRegisters(Expression lhs, Expression rhs) {
|
private boolean prepareRegisters(Expression lhs, Expression rhs) {
|
||||||
boolean lhsIsFloat = lhs.type.equals(Type.getFloatType());
|
boolean lhsIsFloat = lhs.type.equals(Type.getFloatType());
|
||||||
boolean rhsIsFloat = rhs.type.equals(Type.getFloatType());
|
boolean rhsIsFloat = rhs.type.equals(Type.getFloatType());
|
||||||
if (lhsIsFloat && rhsIsFloat) {
|
if (lhsIsFloat && rhsIsFloat) {
|
||||||
lhs.welcome(this);
|
lhs.welcome(this);
|
||||||
this.ex.write(" movsd %xmm0, %xmm2\n");
|
asm.mov("sd", "%xmm0", "%xmm2");
|
||||||
rhs.welcome(this);
|
rhs.welcome(this);
|
||||||
this.ex.write(" movsd %xmm0, %xmm1\n");
|
asm.mov("sd", "%xmm2", "%xmm0");
|
||||||
this.ex.write(" movsd %xmm2, %xmm0\n");
|
asm.mov("sd", "%xmm2", "%xmm0");
|
||||||
return true;
|
return true;
|
||||||
} else if (lhsIsFloat && !rhsIsFloat) {
|
} else if (lhsIsFloat && !rhsIsFloat) {
|
||||||
lhs.welcome(this);
|
lhs.welcome(this);
|
||||||
rhs.welcome(this);
|
rhs.welcome(this);
|
||||||
this.intToFloat("%rax", "%xmm1");
|
asm.cvtsi2sd("%rax", "%xmm1");
|
||||||
return true;
|
return true;
|
||||||
} else if (!lhsIsFloat && rhsIsFloat) {
|
} else if (!lhsIsFloat && rhsIsFloat) {
|
||||||
lhs.welcome(this);
|
lhs.welcome(this);
|
||||||
this.intToFloat("%rax", "%xmm2");
|
asm.cvtsi2sd("%rax", "%xmm2");
|
||||||
rhs.welcome(this);
|
rhs.welcome(this);
|
||||||
this.ex.write(" movsd %xmm0, %xmm1\n");
|
asm.mov("sd", "%xmm0", "%xmm1");
|
||||||
this.ex.write(" movsd %xmm2, %xmm0\n");
|
asm.mov("sd", "%xmm2", "%xmm0");
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
lhs.welcome(this);
|
lhs.welcome(this);
|
||||||
this.ex.write(" pushq %rax\n");
|
asm.push("q", "%rax");
|
||||||
rhs.welcome(this);
|
rhs.welcome(this);
|
||||||
this.ex.write(" movq %rax, %rbx\n");
|
asm.mov("q", "%rax", "%rbx");
|
||||||
this.ex.write(" popq %rax\n");
|
asm.pop("q", "%rax");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public GenASM(ExWriter ex, String mainName, Map<String, StructDefinition> structs) {
|
public GenASM(String mainName, Map<String, StructDefinition> structs) {
|
||||||
this.ex = ex;
|
|
||||||
this.mainName = mainName;
|
this.mainName = mainName;
|
||||||
this.structs = structs;
|
this.structs = structs;
|
||||||
|
this.asm = new ASM();
|
||||||
}
|
}
|
||||||
|
|
||||||
public GenASM(ExWriter ex, Map<String, StructDefinition> structs) {
|
public GenASM(Map<String, StructDefinition> structs) {
|
||||||
this(ex, "main", structs);
|
this("main", structs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toAsm() {
|
||||||
|
return asm.toAsm();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Void visit(IntegerExpression e) {
|
public Void visit(IntegerExpression e) {
|
||||||
this.ex.write(" movq $" + e.value + ", %rax\n");
|
asm.mov("q", e.value, "%rax");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Void visit(FloatExpression e) {
|
public Void visit(FloatExpression e) {
|
||||||
String floatLabel = fw.getFloat(e.value);
|
String floatLabel = fw.getFloat(e.value);
|
||||||
this.ex.write(" movsd " + floatLabel + "(%rip), %xmm0\n");
|
asm.mov("sd", floatLabel, "%rip", "%xmm0");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Void visit(BooleanExpression e) {
|
public Void visit(BooleanExpression e) {
|
||||||
this.ex.write(" movq $" + (e.value ? 1 : 0) + ", %rax\n");
|
asm.mov("q", e.value ? 1 : 0, "%rax");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Void visit(Variable e) {
|
public Void visit(Variable e) {
|
||||||
if (e.type.equals(Type.getFloatType())) {
|
if (e.type.equals(Type.getFloatType())) {
|
||||||
this.ex.write(" movsd " + this.env.get(e.name) + "(%rbp), %xmm0\n");
|
asm.mov("sd", this.env.get(e.name), "%rbp", "%xmm0");
|
||||||
} else {
|
} else {
|
||||||
this.ex.write(" movq " + this.env.get(e.name) + "(%rbp), %rax\n");
|
asm.mov("q", this.env.get(e.name), "%rbp", "%rax");
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -198,18 +157,18 @@ public class GenASM implements Visitor<Void> {
|
|||||||
|
|
||||||
boolean isFloatOperation = this.prepareRegisters(e.lhs, e.rhs);
|
boolean isFloatOperation = this.prepareRegisters(e.lhs, e.rhs);
|
||||||
if (isFloatOperation) {
|
if (isFloatOperation) {
|
||||||
this.ex.write(" ucomisd %xmm1, %xmm0\n");
|
asm.ucomi("sd", "%xmm1", "xmm0");
|
||||||
} else {
|
} else {
|
||||||
this.ex.write(" cmp %rbx, %rax\n");
|
asm.cmp("q", "%rbx", "%rax");
|
||||||
}
|
}
|
||||||
this.ex.write(" je .L" + lblTrue + "\n");
|
asm.je(lblTrue);
|
||||||
// false
|
// false
|
||||||
this.ex.write(" movq $0, %rax\n");
|
asm.mov("q", 0, "%rax");
|
||||||
this.ex.write(" jmp .L" + lblEnd + "\n");
|
asm.jmp(lblEnd);
|
||||||
this.ex.write(".L" + lblTrue + ":\n");
|
asm.label(lblTrue);
|
||||||
// true
|
// true
|
||||||
this.ex.write(" movq $1, %rax\n");
|
asm.mov("q", 1, "%rax");
|
||||||
this.ex.write(".L" + lblEnd + ":\n");
|
asm.label(lblEnd);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -220,18 +179,18 @@ public class GenASM implements Visitor<Void> {
|
|||||||
|
|
||||||
boolean isFloatOperation = this.prepareRegisters(e.lhs, e.rhs);
|
boolean isFloatOperation = this.prepareRegisters(e.lhs, e.rhs);
|
||||||
if (isFloatOperation) {
|
if (isFloatOperation) {
|
||||||
this.ex.write(" ucomisd %xmm0, %xmm1\n");
|
asm.ucomi("sd", "%xmm0", "%xmm1");
|
||||||
} else {
|
} else {
|
||||||
this.ex.write(" cmp %rax, %rbx\n");
|
asm.cmp("q", "%rax", "%rbx");
|
||||||
}
|
}
|
||||||
this.ex.write(" jne .L" + lblTrue + "\n");
|
asm.jne(lblTrue);
|
||||||
// false
|
// false
|
||||||
this.ex.write(" movq $0, %rax\n");
|
asm.mov("q", 0, "%rax");
|
||||||
this.ex.write(" jmp .L" + lblEnd + "\n");
|
asm.jmp(lblEnd);
|
||||||
this.ex.write(".L" + lblTrue + ":\n");
|
asm.label(lblTrue);
|
||||||
// true
|
// true
|
||||||
this.ex.write(" movq $1, %rax\n");
|
asm.mov("q", 1, "%rax");
|
||||||
this.ex.write(".L" + lblEnd + ":\n");
|
asm.label(lblEnd);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -242,18 +201,18 @@ public class GenASM implements Visitor<Void> {
|
|||||||
|
|
||||||
boolean isFloatOperation = this.prepareRegisters(e.lhs, e.rhs);
|
boolean isFloatOperation = this.prepareRegisters(e.lhs, e.rhs);
|
||||||
if (isFloatOperation) {
|
if (isFloatOperation) {
|
||||||
this.ex.write(" ucomisd %xmm1, %xmm0\n");
|
asm.ucomi("sd", "%xmm1", "%xmm0");
|
||||||
} else {
|
} else {
|
||||||
this.ex.write(" cmp %rbx, %rax\n");
|
asm.cmp("q", "%rbx", "%rax");
|
||||||
}
|
}
|
||||||
this.ex.write(" jg .L" + lblTrue + "\n");
|
asm.jg(lblTrue);
|
||||||
// false
|
// false
|
||||||
this.ex.write(" movq $0, %rax\n");
|
asm.mov("q", 0, "%rax");
|
||||||
this.ex.write(" jmp .L" + lblEnd + "\n");
|
asm.jmp(lblEnd);
|
||||||
this.ex.write(".L" + lblTrue + ":\n");
|
asm.label(lblTrue);
|
||||||
// true
|
// true
|
||||||
this.ex.write(" movq $1, %rax\n");
|
asm.mov("q", 1, "%rax");
|
||||||
this.ex.write(".L" + lblEnd + ":\n");
|
asm.label(lblEnd);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -264,18 +223,18 @@ public class GenASM implements Visitor<Void> {
|
|||||||
|
|
||||||
boolean isFloatOperation = this.prepareRegisters(e.lhs, e.rhs);
|
boolean isFloatOperation = this.prepareRegisters(e.lhs, e.rhs);
|
||||||
if (isFloatOperation) {
|
if (isFloatOperation) {
|
||||||
this.ex.write(" ucomisd %xmm1, %xmm0\n");
|
asm.ucomi("sd", "%xmm1", "xmm0");
|
||||||
} else {
|
} else {
|
||||||
this.ex.write(" cmp %rbx, %rax\n");
|
asm.cmp("q", "%rbx", "%rax");
|
||||||
}
|
}
|
||||||
this.ex.write(" jge .L" + lblTrue + "\n");
|
asm.jge(lblTrue);
|
||||||
// false
|
// false
|
||||||
this.ex.write(" movq $0, %rax\n");
|
asm.mov("q", 0, "%rax");
|
||||||
this.ex.write(" jmp .L" + lblEnd + "\n");
|
asm.jmp(lblEnd);
|
||||||
this.ex.write(".L" + lblTrue + ":\n");
|
asm.label(lblTrue);
|
||||||
// true
|
// true
|
||||||
this.ex.write(" movq $1, %rax\n");
|
asm.mov("q", 1, "%rax");
|
||||||
this.ex.write(".L" + lblEnd + ":\n");
|
asm.label(lblEnd);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -286,18 +245,18 @@ public class GenASM implements Visitor<Void> {
|
|||||||
|
|
||||||
boolean isFloatOperation = this.prepareRegisters(e.lhs, e.rhs);
|
boolean isFloatOperation = this.prepareRegisters(e.lhs, e.rhs);
|
||||||
if (isFloatOperation) {
|
if (isFloatOperation) {
|
||||||
this.ex.write(" ucomisd %xmm1, %xmm0\n");
|
asm.ucomi("sd", "%xmm1", "%xmm0");
|
||||||
} else {
|
} else {
|
||||||
this.ex.write(" cmp %rbx, %rax\n");
|
asm.cmp("q", "%rbx", "%rax");
|
||||||
}
|
}
|
||||||
this.ex.write(" jl .L" + lblTrue + "\n");
|
asm.jl(lblTrue);
|
||||||
// false
|
// false
|
||||||
this.ex.write(" movq $0, %rax\n");
|
asm.mov("q", 0, "%rax");
|
||||||
this.ex.write(" jmp .L" + lblEnd + "\n");
|
asm.jmp(lblEnd);
|
||||||
this.ex.write(".L" + lblTrue + ":\n");
|
asm.label(lblTrue);
|
||||||
// true
|
// true
|
||||||
this.ex.write(" movq $1, %rax\n");
|
asm.mov("q", 1, "%rax");
|
||||||
this.ex.write(".L" + lblEnd + ":\n");
|
asm.label(lblEnd);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -308,18 +267,18 @@ public class GenASM implements Visitor<Void> {
|
|||||||
|
|
||||||
boolean isFloatOperation = this.prepareRegisters(e.lhs, e.rhs);
|
boolean isFloatOperation = this.prepareRegisters(e.lhs, e.rhs);
|
||||||
if (isFloatOperation) {
|
if (isFloatOperation) {
|
||||||
this.ex.write(" ucomisd %xmm1, %xmm0\n");
|
asm.ucomi("sd", "%xmm1", "%xmm0");
|
||||||
} else {
|
} else {
|
||||||
this.ex.write(" cmp %rbx, %rax\n");
|
asm.cmp("q", "%rbx", "%rax");
|
||||||
}
|
}
|
||||||
this.ex.write(" jle .L" + lblTrue + "\n");
|
asm.jle(lblTrue);
|
||||||
// false
|
// false
|
||||||
this.ex.write(" movq $0, %rax\n");
|
asm.mov("q", 0, "%rax");
|
||||||
this.ex.write(" jmp .L" + lblEnd + "\n");
|
asm.jmp(lblEnd);
|
||||||
this.ex.write(".L" + lblTrue + ":\n");
|
asm.label(lblTrue);
|
||||||
// true
|
// true
|
||||||
this.ex.write(" movq $1, %rax\n");
|
asm.mov("q", 1, "%rax");
|
||||||
this.ex.write(".L" + lblEnd + ":\n");
|
asm.label(lblEnd);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -327,9 +286,9 @@ public class GenASM implements Visitor<Void> {
|
|||||||
public Void visit(AdditionExpression e) {
|
public Void visit(AdditionExpression e) {
|
||||||
boolean isFloatOperation = this.prepareRegisters(e.lhs, e.rhs);
|
boolean isFloatOperation = this.prepareRegisters(e.lhs, e.rhs);
|
||||||
if (isFloatOperation) {
|
if (isFloatOperation) {
|
||||||
this.ex.write(" addsd %xmm1, %xmm0\n");
|
asm.add("sd", "%xmm1", "%xmm0");
|
||||||
} else {
|
} else {
|
||||||
this.ex.write(" addq %rbx, %rax\n");
|
asm.add("q", "%rbx", "%rax");
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -338,9 +297,9 @@ public class GenASM implements Visitor<Void> {
|
|||||||
public Void visit(SubstractionExpression e) {
|
public Void visit(SubstractionExpression e) {
|
||||||
boolean isFloatOperation = this.prepareRegisters(e.lhs, e.rhs);
|
boolean isFloatOperation = this.prepareRegisters(e.lhs, e.rhs);
|
||||||
if (isFloatOperation) {
|
if (isFloatOperation) {
|
||||||
this.ex.write(" subsd %xmm1, %xmm0\n");
|
asm.sub("sd", "%xmm1", "%xmm0");
|
||||||
} else {
|
} else {
|
||||||
this.ex.write(" subq %rbx, %rax\n");
|
asm.sub("q", "%rbx", "%rax");
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -349,9 +308,9 @@ public class GenASM implements Visitor<Void> {
|
|||||||
public Void visit(MultiplicationExpression e) {
|
public Void visit(MultiplicationExpression e) {
|
||||||
boolean isFloatOperation = this.prepareRegisters(e.lhs, e.rhs);
|
boolean isFloatOperation = this.prepareRegisters(e.lhs, e.rhs);
|
||||||
if (isFloatOperation) {
|
if (isFloatOperation) {
|
||||||
this.ex.write(" mulsd %xmm1, %xmm0\n");
|
asm.mul("sd", "%xmm1", "%xmm0");
|
||||||
} else {
|
} else {
|
||||||
this.ex.write(" imulq %rbx, %rax\n");
|
asm.imul("q", "%rbx", "%rax");
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -360,10 +319,10 @@ public class GenASM implements Visitor<Void> {
|
|||||||
public Void visit(DivisionExpression e) {
|
public Void visit(DivisionExpression e) {
|
||||||
boolean isFloatOperation = this.prepareRegisters(e.lhs, e.rhs);
|
boolean isFloatOperation = this.prepareRegisters(e.lhs, e.rhs);
|
||||||
if (isFloatOperation) {
|
if (isFloatOperation) {
|
||||||
this.ex.write(" divsd %xmm1, %xmm0\n");
|
asm.div("sd", "%xmm1", "%xmm0");
|
||||||
} else {
|
} else {
|
||||||
this.ex.write(" cqto\n"); // sign extend rax into rdx since we're dealing with signed values
|
asm.cqto();
|
||||||
this.ex.write(" idiv %rbx\n"); // %rax/%rbx, quotient now in %rax
|
asm.idiv("q", "%rbx");
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -371,13 +330,13 @@ public class GenASM implements Visitor<Void> {
|
|||||||
@Override
|
@Override
|
||||||
public Void visit(ModuloExpression e) {
|
public Void visit(ModuloExpression e) {
|
||||||
e.lhs.welcome(this);
|
e.lhs.welcome(this);
|
||||||
this.ex.write(" pushq %rax\n");
|
asm.push("q", "%rax");
|
||||||
e.rhs.welcome(this);
|
e.rhs.welcome(this);
|
||||||
this.ex.write(" movq %rax, %rbx\n");
|
asm.mov("q", "%rax", "%rbx");
|
||||||
this.ex.write(" popq %rax\n");
|
asm.pop("q", "%rax");
|
||||||
this.ex.write(" cqto\n"); // sign extend rax into rdx since we're dealing with signed values
|
asm.cqto();
|
||||||
this.ex.write(" idiv %rbx\n"); // %rax/%rbx, remainder now in %rdx
|
asm.idiv("q", "%rbx");
|
||||||
this.ex.write(" movq %rdx, %rax\n");
|
asm.mov("q", "%rdx", "%rax");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -386,10 +345,10 @@ public class GenASM implements Visitor<Void> {
|
|||||||
e.lhs.welcome(this);
|
e.lhs.welcome(this);
|
||||||
if (e.lhs.type.equals(Type.getFloatType())) {
|
if (e.lhs.type.equals(Type.getFloatType())) {
|
||||||
String floatLabel = fw.getNegateFloat();
|
String floatLabel = fw.getNegateFloat();
|
||||||
this.ex.write(" movsd " + floatLabel + "(%rip), %xmm1\n");
|
asm.mov("sd", floatLabel, "%rip", "%xmm1");
|
||||||
this.ex.write(" xorpd %xmm1, %xmm0\n");
|
asm.xor("pd", "%xmm1", "%xmm0");
|
||||||
} else {
|
} else {
|
||||||
this.ex.write(" neg %rax\n");
|
asm.neg("%rax");
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -404,28 +363,28 @@ public class GenASM implements Visitor<Void> {
|
|||||||
// Wenn LHS != 0 bedeutet das true
|
// Wenn LHS != 0 bedeutet das true
|
||||||
// also können wir direkt sagen dass das Ergebnis true ist
|
// also können wir direkt sagen dass das Ergebnis true ist
|
||||||
e.lhs.welcome(this);
|
e.lhs.welcome(this);
|
||||||
this.ex.write(" cmpq $0, %rax\n");
|
asm.cmp("q", 0, "%rax");
|
||||||
this.ex.write(" jne .L" + lblTrue + "\n");
|
asm.jne(lblTrue);
|
||||||
|
|
||||||
// LHS war false, also werte RHS aus
|
// LHS war false, also werte RHS aus
|
||||||
// Wenn RHS == 0 bedeutet das false,
|
// Wenn RHS == 0 bedeutet das false,
|
||||||
// also ist das Gesamtergebnis false
|
// also ist das Gesamtergebnis false
|
||||||
e.rhs.welcome(this);
|
e.rhs.welcome(this);
|
||||||
this.ex.write(" cmpq $0, %rax\n");
|
asm.cmp("q", 0, "%rax");
|
||||||
this.ex.write(" je .L" + lblFalse + "\n");
|
asm.je(lblFalse);
|
||||||
|
|
||||||
// Die Expression wertet zu true aus
|
// Die Expression wertet zu true aus
|
||||||
// Springe am false Teil vorbei
|
// Springe am false Teil vorbei
|
||||||
this.ex.write(".L" + lblTrue + ":\n");
|
asm.label(lblTrue);
|
||||||
this.ex.write(" movq $1, %rax\n");
|
asm.mov("q", 1, "%rax");
|
||||||
this.ex.write(" jmp .L" + lblEnd + "\n");
|
asm.jmp(lblEnd);
|
||||||
|
|
||||||
// Die Expressoin wertet zu false aus
|
// Die Expressoin wertet zu false aus
|
||||||
this.ex.write(".L" + lblFalse + ":\n");
|
asm.label(lblFalse);
|
||||||
this.ex.write(" movq $0, %rax\n");
|
asm.mov("q", 0, "%rax");
|
||||||
|
|
||||||
// Das hier ist das ende
|
// Das hier ist das ende
|
||||||
this.ex.write(".L" + lblEnd + ":\n");
|
asm.label(lblEnd);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -439,28 +398,28 @@ public class GenASM implements Visitor<Void> {
|
|||||||
// Wenn LHS == 0, bedeutet das false
|
// Wenn LHS == 0, bedeutet das false
|
||||||
// also können wir direkt sagen dass das Ergebnis false ist
|
// also können wir direkt sagen dass das Ergebnis false ist
|
||||||
e.lhs.welcome(this);
|
e.lhs.welcome(this);
|
||||||
this.ex.write(" cmpq $0, %rax\n");
|
asm.cmp("q", 0, "%rax");
|
||||||
this.ex.write(" je .L" + lblFalse + "\n");
|
asm.je(lblFalse);
|
||||||
|
|
||||||
// LHS war true, also werte RHS aus.
|
// LHS war true, also werte RHS aus.
|
||||||
// Wenn RHS == 0, bedeutet das false
|
// Wenn RHS == 0, bedeutet das false
|
||||||
// also ist das Gesamtergebnis false
|
// also ist das Gesamtergebnis false
|
||||||
e.rhs.welcome(this);
|
e.rhs.welcome(this);
|
||||||
this.ex.write(" cmpq $0, %rax\n");
|
asm.cmp("q", 0, "%rax");
|
||||||
this.ex.write(" je .L" + lblFalse + "\n");
|
asm.je(lblFalse);
|
||||||
|
|
||||||
// Die Expression wertet zu true aus
|
// Die Expression wertet zu true aus
|
||||||
// Springe am false Teil vorbei
|
// Springe am false Teil vorbei
|
||||||
this.ex.write(".L" + lblTrue + ":\n");
|
asm.label(lblTrue);
|
||||||
this.ex.write(" movq $1, %rax\n");
|
asm.mov("q", 1, "%rax");
|
||||||
this.ex.write(" jmp .L" + lblEnd + "\n");
|
asm.jmp(lblEnd);
|
||||||
|
|
||||||
// Die Expressoin wertet zu false aus
|
// Die Expressoin wertet zu false aus
|
||||||
this.ex.write(".L" + lblFalse + ":\n");
|
asm.label(lblFalse);
|
||||||
this.ex.write(" movq $0, %rax\n");
|
asm.mov("q", 0, "%rax");
|
||||||
|
|
||||||
// Das hier ist das ende
|
// Das hier ist das ende
|
||||||
this.ex.write(".L" + lblEnd + ":\n");
|
asm.label(lblEnd);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -473,21 +432,21 @@ public class GenASM implements Visitor<Void> {
|
|||||||
// Wenn LHS != 0 bedeutet das true, also jumpe zum false Teil
|
// Wenn LHS != 0 bedeutet das true, also jumpe zum false Teil
|
||||||
// Wenn nicht, falle durch zum true Teil
|
// Wenn nicht, falle durch zum true Teil
|
||||||
e.lhs.welcome(this);
|
e.lhs.welcome(this);
|
||||||
this.ex.write(" cmpq $0, %rax\n");
|
asm.cmp("q", 0, "%rax");
|
||||||
this.ex.write(" jne .L" + lblFalse + "\n");
|
asm.jne(lblFalse);
|
||||||
|
|
||||||
// Hier ist das Ergebnis true
|
// Hier ist das Ergebnis true
|
||||||
// Springe am false Teil vorbei
|
// Springe am false Teil vorbei
|
||||||
this.ex.write(" movq $1, %rax\n");
|
asm.mov("q", 1, "%rax");
|
||||||
this.ex.write(" jmp .L" + lblEnd + "\n");
|
asm.jmp(lblEnd);
|
||||||
|
|
||||||
// Hier ist das Ergebnis false
|
// Hier ist das Ergebnis false
|
||||||
// Falle zum Ende durch
|
// Falle zum Ende durch
|
||||||
this.ex.write(".L" + lblFalse + ":\n");
|
asm.label(lblFalse);
|
||||||
this.ex.write("movq $0, %rax\n");
|
asm.mov("q", 0, "%rax");
|
||||||
|
|
||||||
// Hier ist das Ende
|
// Hier ist das Ende
|
||||||
this.ex.write(".L" + lblEnd + ":\n");
|
asm.label(lblEnd);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -497,25 +456,25 @@ public class GenASM implements Visitor<Void> {
|
|||||||
int lblEnd = ++lCount;
|
int lblEnd = ++lCount;
|
||||||
boolean hasElse = e.alt != null || e.elif != null;
|
boolean hasElse = e.alt != null || e.elif != null;
|
||||||
e.cond.welcome(this);
|
e.cond.welcome(this);
|
||||||
this.ex.write(" cmp $0, %rax\n");
|
asm.cmp("", 0, "%rax");
|
||||||
// in case of cond evaluating to false, jump to else/elif
|
// in case of cond evaluating to false, jump to else/elif
|
||||||
// Jump to end if there is no else part, this saves a label declaration
|
// Jump to end if there is no else part, this saves a label declaration
|
||||||
if (hasElse) {
|
if (hasElse) {
|
||||||
this.ex.write(" jz .L" + lblElse + "\n");
|
asm.jz(lblElse);
|
||||||
} else {
|
} else {
|
||||||
this.ex.write(" jz .L" + lblEnd + "\n");
|
asm.jz(lblEnd);
|
||||||
}
|
}
|
||||||
e.then.welcome(this);
|
e.then.welcome(this);
|
||||||
if (hasElse) {
|
if (hasElse) {
|
||||||
this.ex.write(" jmp .L" + lblEnd + "\n");
|
asm.jmp(lblEnd);
|
||||||
this.ex.write(".L" + lblElse + ":\n");
|
asm.label(lblElse);
|
||||||
if (e.alt != null) {
|
if (e.alt != null) {
|
||||||
e.alt.welcome(this);
|
e.alt.welcome(this);
|
||||||
} else {
|
} else {
|
||||||
e.elif.welcome(this);
|
e.elif.welcome(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.ex.write(".L" + lblEnd + ":\n");
|
asm.label(lblEnd);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -523,24 +482,24 @@ public class GenASM implements Visitor<Void> {
|
|||||||
public Void visit(WhileLoop e) {
|
public Void visit(WhileLoop e) {
|
||||||
int lblCond = ++lCount;
|
int lblCond = ++lCount;
|
||||||
int lblEnd = ++lCount;
|
int lblEnd = ++lCount;
|
||||||
this.ex.write(".L" + lblCond + ":\n");
|
asm.label(lblCond);
|
||||||
e.cond.welcome(this);
|
e.cond.welcome(this);
|
||||||
this.ex.write(" cmp $0, %rax\n");
|
asm.cmp("", 0, "%rax");
|
||||||
this.ex.write(" jz .L" + lblEnd + "\n");
|
asm.jz(lblEnd);
|
||||||
e.block.welcome(this);
|
e.block.welcome(this);
|
||||||
this.ex.write(" jmp .L" + lblCond + "\n");
|
asm.jmp(lblCond);
|
||||||
this.ex.write(".L" + lblEnd + ":\n");
|
asm.label(lblEnd);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Void visit(DoWhileLoop e) {
|
public Void visit(DoWhileLoop e) {
|
||||||
int lblStart = ++lCount;
|
int lblStart = ++lCount;
|
||||||
this.ex.write(".L" + lblStart + ":\n");
|
asm.label(lblStart);
|
||||||
e.block.welcome(this);
|
e.block.welcome(this);
|
||||||
e.cond.welcome(this);
|
e.cond.welcome(this);
|
||||||
this.ex.write(" cmp $0, %rax\n");
|
asm.cmp("", 0, "%rax");
|
||||||
this.ex.write(" jnz .L" + lblStart + "\n");
|
asm.jnz(lblStart);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -549,15 +508,14 @@ public class GenASM implements Visitor<Void> {
|
|||||||
int lblStart = ++lCount;
|
int lblStart = ++lCount;
|
||||||
int lblEnd = ++lCount;
|
int lblEnd = ++lCount;
|
||||||
e.init.welcome(this);
|
e.init.welcome(this);
|
||||||
this.ex.write(".L" + lblStart + ":\n");
|
asm.label(lblStart);
|
||||||
e.condition.welcome(this);
|
e.condition.welcome(this);
|
||||||
this.ex.write(" cmp $0, %rax\n");
|
asm.cmp("", 0, "%rax");
|
||||||
this.ex.write(" jz .L" + lblEnd + "\n");
|
asm.jz(lblEnd);
|
||||||
e.block.welcome(this);
|
e.block.welcome(this);
|
||||||
e.step.welcome(this);
|
e.step.welcome(this);
|
||||||
this.ex.write(" jmp .L" + lblStart + "\n");
|
asm.jmp(lblStart);
|
||||||
this.ex.write(".L" + lblEnd + ":\n");
|
asm.label(lblEnd);
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -568,12 +526,12 @@ public class GenASM implements Visitor<Void> {
|
|||||||
if (e.expression != null) {
|
if (e.expression != null) {
|
||||||
e.expression.welcome(this);
|
e.expression.welcome(this);
|
||||||
int offset = this.env.get(e.name);
|
int offset = this.env.get(e.name);
|
||||||
|
|
||||||
if (e.expression.type.equals(Type.getFloatType())) {
|
if (e.expression.type.equals(Type.getFloatType())) {
|
||||||
this.ex.write(" movq %xmm0, %rax\n");
|
asm.mov("q", "%xmm0", "%rax");
|
||||||
}
|
}
|
||||||
|
|
||||||
this.ex.write(" movq %rax, " + offset + "(%rbp)\n");
|
asm.mov("q", "%rax", offset, "%rbp");
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -586,20 +544,20 @@ public class GenASM implements Visitor<Void> {
|
|||||||
// Determine where the result of this expression was placed into
|
// Determine where the result of this expression was placed into
|
||||||
// and move it onto the stack from there
|
// and move it onto the stack from there
|
||||||
if (e.expression.type.equals(Type.getFloatType())) {
|
if (e.expression.type.equals(Type.getFloatType())) {
|
||||||
this.ex.write(" movq %xmm0, " + offset + "(%rbp)\n");
|
asm.mov("q", "%xmm0", offset, "%rbp");
|
||||||
} else {
|
} else {
|
||||||
this.ex.write(" movq %rax, " + offset + "(%rbp)\n");
|
asm.mov("q", "%rax", offset, "%rbp");
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Void visit(ReturnStatement e) {
|
public Void visit(ReturnStatement e) {
|
||||||
e.expression.welcome(this);
|
e.expression.welcome(this);
|
||||||
this.ex.write(" movq %rbp, %rsp\n");
|
asm.mov("q", "%rbp", "%rsp");
|
||||||
this.ex.write(" popq %rbp\n");
|
asm.pop("q", "%rbp");
|
||||||
this.ex.write(" ret\n");
|
asm.ret();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -616,12 +574,10 @@ public class GenASM implements Visitor<Void> {
|
|||||||
int lblStart = ++lCount;
|
int lblStart = ++lCount;
|
||||||
this.currentFunctionStartLabel = lblStart;
|
this.currentFunctionStartLabel = lblStart;
|
||||||
this.currentFunctionParams = e.parameters;
|
this.currentFunctionParams = e.parameters;
|
||||||
this.ex.write(".globl " + e.name + "\n");
|
asm.functionHead(e.name);
|
||||||
this.ex.write(".type " + e.name + ", @function\n");
|
asm.push("q", "%rbp");
|
||||||
this.ex.write(e.name + ":\n");
|
asm.mov("q", "%rsp", "%rbp");
|
||||||
this.ex.write(" pushq %rbp\n");
|
asm.label(lblStart);
|
||||||
this.ex.write(" movq %rsp, %rbp\n");
|
|
||||||
this.ex.write(".L" + lblStart + ":\n");
|
|
||||||
|
|
||||||
// hole die anzahl der lokalen variablen
|
// hole die anzahl der lokalen variablen
|
||||||
this.vars = new TreeSet<String>();
|
this.vars = new TreeSet<String>();
|
||||||
@@ -661,19 +617,19 @@ public class GenASM implements Visitor<Void> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
offset = 0;
|
offset = 0;
|
||||||
ri = 0;
|
ri = 0;
|
||||||
fi = 0;
|
fi = 0;
|
||||||
for (var param: registerParameters) {
|
for (var param: registerParameters) {
|
||||||
if (param.type.equals(Type.getFloatType())) {
|
if (param.type.equals(Type.getFloatType())) {
|
||||||
this.ex.write(" movq "+ this.floatRegisters[fi] + ", %rax\n");
|
asm.mov("q", this.floatRegisters[fi], "%rax");
|
||||||
this.ex.write(" pushq %rax\n");
|
asm.push("q", "%rax");
|
||||||
offset -= 8;
|
offset -= 8;
|
||||||
this.env.put(param.name, offset); // negative, liegt unter aktuellem BP
|
this.env.put(param.name, offset); // negative, liegt unter aktuellem BP
|
||||||
fi++;
|
fi++;
|
||||||
} else {
|
} else {
|
||||||
this.ex.write(" pushq " + this.registers[ri] + "\n");
|
asm.push("q", this.registers[ri]);
|
||||||
offset -= 8;
|
offset -= 8;
|
||||||
this.env.put(param.name, offset); // negative, liegt unter aktuellem BP
|
this.env.put(param.name, offset); // negative, liegt unter aktuellem BP
|
||||||
ri++;
|
ri++;
|
||||||
@@ -683,7 +639,7 @@ public class GenASM implements Visitor<Void> {
|
|||||||
// Reserviere Platz auf dem Stack für jede lokale variable
|
// Reserviere Platz auf dem Stack für jede lokale variable
|
||||||
for (String lok_var : vars) {
|
for (String lok_var : vars) {
|
||||||
offset -= 8;
|
offset -= 8;
|
||||||
this.ex.write(" pushq $0\n");
|
asm.push("q", 0);
|
||||||
this.env.put(lok_var, offset);
|
this.env.put(lok_var, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -700,18 +656,18 @@ public class GenASM implements Visitor<Void> {
|
|||||||
e.arguments[i].welcome(this);
|
e.arguments[i].welcome(this);
|
||||||
|
|
||||||
if (e.arguments[i].type.equals(Type.getFloatType())) {
|
if (e.arguments[i].type.equals(Type.getFloatType())) {
|
||||||
this.ex.write(" movq %xmm0, %rax\n");
|
asm.mov("q", "%xmm0", "%rax0");
|
||||||
}
|
}
|
||||||
|
|
||||||
this.ex.write(" pushq %rax\n");
|
asm.push("q", "%rax");
|
||||||
}
|
}
|
||||||
|
|
||||||
// push args into local var locations, last arg is ontop of the stack
|
// push args into local var locations, last arg is ontop of the stack
|
||||||
for (int i = e.arguments.length - 1; i >= 0; i--) {
|
for (int i = e.arguments.length - 1; i >= 0; i--) {
|
||||||
this.ex.write(" popq " + this.env.get(this.currentFunctionParams[i].name) + "(%rbp)\n");
|
asm.pop("q", this.env.get(this.currentFunctionParams[i].name) + "(%rbp)");
|
||||||
}
|
}
|
||||||
|
|
||||||
this.ex.write(" jmp .L" + this.currentFunctionStartLabel + "\n");
|
asm.jmp(this.currentFunctionStartLabel);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -724,12 +680,12 @@ public class GenASM implements Visitor<Void> {
|
|||||||
// Mapping arguments index -> all purpose registers index
|
// Mapping arguments index -> all purpose registers index
|
||||||
int[] rIdxs = new int[this.registers.length];
|
int[] rIdxs = new int[this.registers.length];
|
||||||
int ri = -1;
|
int ri = -1;
|
||||||
|
|
||||||
// Mapping arguments index -> stack
|
// Mapping arguments index -> stack
|
||||||
ArrayList<Integer> stackIdxs = new ArrayList<Integer>();
|
ArrayList<Integer> stackIdxs = new ArrayList<Integer>();
|
||||||
|
|
||||||
// Go through arguments
|
// Go through arguments
|
||||||
// sort them into the memory regions they go when being passed to functions
|
// sort them into the memory regions they go when being passed to functions
|
||||||
for (int i = 0; i < e.arguments.length; i++) {
|
for (int i = 0; i < e.arguments.length; i++) {
|
||||||
var arg = e.arguments[i];
|
var arg = e.arguments[i];
|
||||||
if (arg.type.equals(Type.getFloatType())) {
|
if (arg.type.equals(Type.getFloatType())) {
|
||||||
@@ -757,10 +713,10 @@ public class GenASM implements Visitor<Void> {
|
|||||||
for (var arg : e.arguments) {
|
for (var arg : e.arguments) {
|
||||||
arg.welcome(this);
|
arg.welcome(this);
|
||||||
if (arg.type.equals(Type.getFloatType())) {
|
if (arg.type.equals(Type.getFloatType())) {
|
||||||
this.ex.write(" movq %xmm0, %rax\n");
|
asm.mov("q", "%xmm0", "%rax");
|
||||||
this.ex.write(" pushq %rax\n");
|
asm.push("q", "%rax");
|
||||||
} else {
|
} else {
|
||||||
this.ex.write(" pushq %rax\n");
|
asm.push("q", "%rax");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -768,14 +724,14 @@ public class GenASM implements Visitor<Void> {
|
|||||||
for (int i = 0; i <= fi; i++) {
|
for (int i = 0; i <= fi; i++) {
|
||||||
int indexInArguments = xmmIdxs[i];
|
int indexInArguments = xmmIdxs[i];
|
||||||
int rspOffset = (((e.arguments.length - indexInArguments) - 1) * 8);
|
int rspOffset = (((e.arguments.length - indexInArguments) - 1) * 8);
|
||||||
this.ex.write(" movsd " + rspOffset + "(%rsp), " + this.floatRegisters[i] + "\n");
|
asm.mov("sd", rspOffset, "%rsp", this.floatRegisters[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move primitives from stack to all purpose registers
|
// Move primitives from stack to all purpose registers
|
||||||
for (int i = 0; i <= ri; i++) {
|
for (int i = 0; i <= ri; i++) {
|
||||||
int indexInArguments = rIdxs[i];
|
int indexInArguments = rIdxs[i];
|
||||||
int rspOffset = (((e.arguments.length - indexInArguments) - 1) * 8);
|
int rspOffset = (((e.arguments.length - indexInArguments) - 1) * 8);
|
||||||
this.ex.write(" movq " + rspOffset + "(%rsp), " + this.registers[i] + "\n");
|
asm.mov("q", rspOffset, "%rsp", this.registers[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move everything else from a higher stack position to our stack frame start
|
// Move everything else from a higher stack position to our stack frame start
|
||||||
@@ -784,39 +740,34 @@ public class GenASM implements Visitor<Void> {
|
|||||||
stackStartOffset -= 8;
|
stackStartOffset -= 8;
|
||||||
int indexInArguments = stackIdxs.get(i);
|
int indexInArguments = stackIdxs.get(i);
|
||||||
int rspOffset = (((e.arguments.length - indexInArguments) - 1) * 8);
|
int rspOffset = (((e.arguments.length - indexInArguments) - 1) * 8);
|
||||||
this.ex.write(" movq " + rspOffset + "(%rsp), %rax\n");
|
asm.mov("q", rspOffset, "%rsp", "%rax");
|
||||||
this.ex.write(" movq %rax, " + stackStartOffset + "(%rsp)\n");
|
asm.mov("q", "%rax", stackStartOffset, "%rsp");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rescue RSP
|
// Rescue RSP
|
||||||
this.ex.write(" addq $" + stackStartOffset + ", %rsp\n");
|
asm.add("q", stackStartOffset, "%rsp");
|
||||||
}
|
}
|
||||||
|
|
||||||
this.ex.write(" call " + e.name + "\n");
|
asm.call(e.name);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Void visit(Program e) {
|
public Void visit(Program e) {
|
||||||
this.ex.write(".text\n");
|
asm.text(".text");
|
||||||
for (var func : e.funcs) {
|
for (var func : e.funcs) {
|
||||||
func.welcome(this);
|
func.welcome(this);
|
||||||
this.ex.write("\n");
|
asm.newline();
|
||||||
}
|
}
|
||||||
this.ex.write(".globl " + mainName + "\n");
|
asm.functionHead(mainName);
|
||||||
this.ex.write(".type " + mainName + ", @function\n");
|
asm.push("q", "%rbp");
|
||||||
this.ex.write(mainName + ":\n");
|
asm.mov("q", "%rsp", "%rbp");
|
||||||
this.ex.write(" pushq %rbp\n");
|
|
||||||
this.ex.write(" movq %rsp, %rbp\n");
|
|
||||||
e.expression.welcome(this);
|
e.expression.welcome(this);
|
||||||
|
asm.mov("q", "%rbp", "%rsp");
|
||||||
|
asm.pop("q", "%rbp");
|
||||||
|
asm.ret();
|
||||||
|
|
||||||
this.ex.write(" movq %rbp, %rsp\n");
|
asm.text(fw.getFloatSection());
|
||||||
this.ex.write(" popq %rbp\n");
|
|
||||||
this.ex.write(" ret\n");
|
|
||||||
|
|
||||||
// PRINT FLOATS HERE
|
|
||||||
this.ex.write("\n");
|
|
||||||
this.ex.write(fw.getFloatSection());
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -845,21 +796,21 @@ public class GenASM implements Visitor<Void> {
|
|||||||
int offset = this.env.get(e.varName);
|
int offset = this.env.get(e.varName);
|
||||||
|
|
||||||
// move struct address into rax
|
// move struct address into rax
|
||||||
this.ex.write(" movq " + offset + "(%rbp), %rax\n");
|
asm.mov("q", offset, "%rbp", "%rax");
|
||||||
|
|
||||||
// "follow" the first path element by moving the referenced value into rax
|
// "follow" the first path element by moving the referenced value into rax
|
||||||
this.ex.write(" movq " + Helper.getFieldOffset(structDef, e.path[0]) + "(%rax), %rax\n");
|
asm.mov("q", Helper.getFieldOffset(structDef, e.path[0]), "%rax", "%rax");
|
||||||
for (int i = 1; i < e.path.length; i++) {
|
for (int i = 1; i < e.path.length; i++) {
|
||||||
// "follow" the current path element
|
// "follow" the current path element
|
||||||
structDef = this.structs.get(structDef.fields[Helper.getFieldIndex(structDef, e.path[i - 1])].type.getName());
|
structDef = this.structs.get(structDef.fields[Helper.getFieldIndex(structDef, e.path[i - 1])].type.getName());
|
||||||
this.ex.write(" movq " + Helper.getFieldOffset(structDef, e.path[i]) + "(%rax), %rax\n");
|
asm.mov("q", Helper.getFieldOffset(structDef, e.path[i]), "%rax", "%rax");
|
||||||
}
|
}
|
||||||
|
|
||||||
// desired value now in rax
|
// desired value now in rax
|
||||||
|
|
||||||
// push rax to xmm0 if the result type is a float
|
// push rax to xmm0 if the result type is a float
|
||||||
if (e.type.equals(Type.getFloatType())) {
|
if (e.type.equals(Type.getFloatType())) {
|
||||||
this.ex.write(" movq %rax, %xmm0\n");
|
asm.mov("q", "%rax", "%xmm0");
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
@@ -873,20 +824,20 @@ public class GenASM implements Visitor<Void> {
|
|||||||
|
|
||||||
// move float values from xmm0 to rax first
|
// move float values from xmm0 to rax first
|
||||||
if (arg.type.equals(Type.getFloatType())) {
|
if (arg.type.equals(Type.getFloatType())) {
|
||||||
this.ex.write(" movq %xmm0, %rax\n");
|
asm.mov("q", "%xmm0", "%rax");
|
||||||
}
|
}
|
||||||
|
|
||||||
this.ex.write(" pushq %rax\n");
|
asm.push("q", "%rax");
|
||||||
}
|
}
|
||||||
|
|
||||||
// allocate heap memory by calling malloc
|
// allocate heap memory by calling malloc
|
||||||
var structDef = this.structs.get(e.structName);
|
var structDef = this.structs.get(e.structName);
|
||||||
this.ex.write(" movl $" + Helper.getFieldSizeBytes(structDef) + ", %edi\n");
|
asm.mov("l", Helper.getFieldSizeBytes(structDef), "%edi");
|
||||||
this.ex.write(" call malloc@PLT\n"); // struct address now in rax
|
asm.call("malloc@PLT");
|
||||||
|
|
||||||
// push args into struct memory, last arg is ontop of the stack
|
// push args into struct memory, last arg is ontop of the stack
|
||||||
for (int i = e.args.length - 1; i >= 0; i--) {
|
for (int i = e.args.length - 1; i >= 0; i--) {
|
||||||
this.ex.write(" popq " + Helper.getFieldOffset(structDef, i) + "(%rax)\n");
|
asm.pop("q", Helper.getFieldOffset(structDef, i) + "(%rax)");
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
@@ -894,14 +845,14 @@ public class GenASM implements Visitor<Void> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Void visit(NullExpression e) {
|
public Void visit(NullExpression e) {
|
||||||
this.ex.write(" movq $0, %rax\n");
|
asm.mov("q", 0 , "%rax");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Void visit(DestructorCall e) {
|
public Void visit(DestructorCall e) {
|
||||||
this.ex.write(" movq " +this.env.get(e.name) + "(%rbp), %rdi\n");
|
asm.mov("q", this.env.get(e.name), "%rbp", "%rdi");
|
||||||
this.ex.write(" call free@PLT\n");
|
asm.call("free@PLT");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -915,25 +866,25 @@ public class GenASM implements Visitor<Void> {
|
|||||||
|
|
||||||
// Move it from xmm0 rax if its a flaot
|
// Move it from xmm0 rax if its a flaot
|
||||||
if (e.expression.type.equals(Type.getFloatType())) {
|
if (e.expression.type.equals(Type.getFloatType())) {
|
||||||
this.ex.write(" movq %xmm0, %rax\n");
|
asm.mov("q", "%xmm0", "%rax");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Push the expression onto the stack
|
// Push the expression onto the stack
|
||||||
this.ex.write(" pushq %rax\n");
|
asm.push("q", "%rax");
|
||||||
|
|
||||||
// move struct address into rax
|
// move struct address into rax
|
||||||
this.ex.write(" movq " + offset + "(%rbp), %rax\n");
|
asm.mov("q", offset, "%rbp", "%rax");
|
||||||
|
|
||||||
// If there are at least two elements in the path,
|
// If there are at least two elements in the path,
|
||||||
// move the address of the next referenced struct into rax
|
// move the address of the next referenced struct into rax
|
||||||
for (int i = 1; i < e.path.length - 1; i++) {
|
for (int i = 1; i < e.path.length - 1; i++) {
|
||||||
structDef = this.structs.get(structDef.fields[Helper.getFieldIndex(structDef, e.path[i - 1])].type.getName());
|
structDef = this.structs.get(structDef.fields[Helper.getFieldIndex(structDef, e.path[i - 1])].type.getName());
|
||||||
this.ex.write(" movq " + Helper.getFieldOffset(structDef, e.path[i]) + "(%rax), %rax\n");
|
asm.mov("q", Helper.getFieldOffset(structDef, e.path[i]), "%rax", "%rax");
|
||||||
}
|
}
|
||||||
|
|
||||||
// pop the expression that is ontop of the stack into the field of the struct that has to be updated
|
// pop the expression that is ontop of the stack into the field of the struct that has to be updated
|
||||||
this.ex.write(" popq " + Helper.getFieldOffset(structDef, fieldNameToUpdate) + "(%rax)\n");
|
asm.pop("q", Helper.getFieldOffset(structDef, fieldNameToUpdate) + "(%rax)");
|
||||||
this.ex.write(" movq $0, %rax\n"); // clear rax sind an assignment has no result
|
asm.mov("q", 0 , "%rax"); // clear rax since an assignment has no result
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user