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
|
||||
// System.out.println("\nPrinting the assembler code");
|
||||
StringWriter wAsm = new StringWriter();
|
||||
GenASM.ExWriter exAsm = new GenASM.ExWriter(wAsm);
|
||||
GenASM genasm = new GenASM(exAsm, mainName, structs);
|
||||
GenASM genasm = new GenASM(mainName, structs);
|
||||
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;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import de.hsrm.compiler.Klang.asm.ASM;
|
||||
import de.hsrm.compiler.Klang.helper.Helper;
|
||||
import de.hsrm.compiler.Klang.nodes.*;
|
||||
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;
|
||||
|
||||
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 StringBuilder sb = new StringBuilder();
|
||||
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 String mainName;
|
||||
Map<String, Integer> env = new HashMap<>();
|
||||
@@ -112,81 +71,81 @@ public class GenASM implements Visitor<Void> {
|
||||
Set<String> vars;
|
||||
String[] registers = { "%rdi", "%rsi", "%rdx", "%rcx", "%r8", "%r9" };
|
||||
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 Parameter[] currentFunctionParams;
|
||||
|
||||
private void intToFloat(String src, String dst) {
|
||||
this.ex.write(" cvtsi2sd " + src + ", " + dst + "\n");
|
||||
}
|
||||
|
||||
private boolean prepareRegisters(Expression lhs, Expression rhs) {
|
||||
boolean lhsIsFloat = lhs.type.equals(Type.getFloatType());
|
||||
boolean rhsIsFloat = rhs.type.equals(Type.getFloatType());
|
||||
if (lhsIsFloat && rhsIsFloat) {
|
||||
lhs.welcome(this);
|
||||
this.ex.write(" movsd %xmm0, %xmm2\n");
|
||||
asm.mov("sd", "%xmm0", "%xmm2");
|
||||
rhs.welcome(this);
|
||||
this.ex.write(" movsd %xmm0, %xmm1\n");
|
||||
this.ex.write(" movsd %xmm2, %xmm0\n");
|
||||
asm.mov("sd", "%xmm2", "%xmm0");
|
||||
asm.mov("sd", "%xmm2", "%xmm0");
|
||||
return true;
|
||||
} else if (lhsIsFloat && !rhsIsFloat) {
|
||||
lhs.welcome(this);
|
||||
rhs.welcome(this);
|
||||
this.intToFloat("%rax", "%xmm1");
|
||||
asm.cvtsi2sd("%rax", "%xmm1");
|
||||
return true;
|
||||
} else if (!lhsIsFloat && rhsIsFloat) {
|
||||
lhs.welcome(this);
|
||||
this.intToFloat("%rax", "%xmm2");
|
||||
asm.cvtsi2sd("%rax", "%xmm2");
|
||||
rhs.welcome(this);
|
||||
this.ex.write(" movsd %xmm0, %xmm1\n");
|
||||
this.ex.write(" movsd %xmm2, %xmm0\n");
|
||||
asm.mov("sd", "%xmm0", "%xmm1");
|
||||
asm.mov("sd", "%xmm2", "%xmm0");
|
||||
return true;
|
||||
} else {
|
||||
lhs.welcome(this);
|
||||
this.ex.write(" pushq %rax\n");
|
||||
asm.push("q", "%rax");
|
||||
rhs.welcome(this);
|
||||
this.ex.write(" movq %rax, %rbx\n");
|
||||
this.ex.write(" popq %rax\n");
|
||||
asm.mov("q", "%rax", "%rbx");
|
||||
asm.pop("q", "%rax");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public GenASM(ExWriter ex, String mainName, Map<String, StructDefinition> structs) {
|
||||
this.ex = ex;
|
||||
public GenASM(String mainName, Map<String, StructDefinition> structs) {
|
||||
this.mainName = mainName;
|
||||
this.structs = structs;
|
||||
this.asm = new ASM();
|
||||
}
|
||||
|
||||
public GenASM(ExWriter ex, Map<String, StructDefinition> structs) {
|
||||
this(ex, "main", structs);
|
||||
public GenASM(Map<String, StructDefinition> structs) {
|
||||
this("main", structs);
|
||||
}
|
||||
|
||||
public String toAsm() {
|
||||
return asm.toAsm();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(IntegerExpression e) {
|
||||
this.ex.write(" movq $" + e.value + ", %rax\n");
|
||||
asm.mov("q", e.value, "%rax");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(FloatExpression e) {
|
||||
String floatLabel = fw.getFloat(e.value);
|
||||
this.ex.write(" movsd " + floatLabel + "(%rip), %xmm0\n");
|
||||
asm.mov("sd", floatLabel, "%rip", "%xmm0");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
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;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(Variable e) {
|
||||
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 {
|
||||
this.ex.write(" movq " + this.env.get(e.name) + "(%rbp), %rax\n");
|
||||
asm.mov("q", this.env.get(e.name), "%rbp", "%rax");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -198,18 +157,18 @@ public class GenASM implements Visitor<Void> {
|
||||
|
||||
boolean isFloatOperation = this.prepareRegisters(e.lhs, e.rhs);
|
||||
if (isFloatOperation) {
|
||||
this.ex.write(" ucomisd %xmm1, %xmm0\n");
|
||||
asm.ucomi("sd", "%xmm1", "xmm0");
|
||||
} else {
|
||||
this.ex.write(" cmp %rbx, %rax\n");
|
||||
asm.cmp("q", "%rbx", "%rax");
|
||||
}
|
||||
this.ex.write(" je .L" + lblTrue + "\n");
|
||||
asm.je(lblTrue);
|
||||
// false
|
||||
this.ex.write(" movq $0, %rax\n");
|
||||
this.ex.write(" jmp .L" + lblEnd + "\n");
|
||||
this.ex.write(".L" + lblTrue + ":\n");
|
||||
asm.mov("q", 0, "%rax");
|
||||
asm.jmp(lblEnd);
|
||||
asm.label(lblTrue);
|
||||
// true
|
||||
this.ex.write(" movq $1, %rax\n");
|
||||
this.ex.write(".L" + lblEnd + ":\n");
|
||||
asm.mov("q", 1, "%rax");
|
||||
asm.label(lblEnd);
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -220,18 +179,18 @@ public class GenASM implements Visitor<Void> {
|
||||
|
||||
boolean isFloatOperation = this.prepareRegisters(e.lhs, e.rhs);
|
||||
if (isFloatOperation) {
|
||||
this.ex.write(" ucomisd %xmm0, %xmm1\n");
|
||||
asm.ucomi("sd", "%xmm0", "%xmm1");
|
||||
} else {
|
||||
this.ex.write(" cmp %rax, %rbx\n");
|
||||
asm.cmp("q", "%rax", "%rbx");
|
||||
}
|
||||
this.ex.write(" jne .L" + lblTrue + "\n");
|
||||
asm.jne(lblTrue);
|
||||
// false
|
||||
this.ex.write(" movq $0, %rax\n");
|
||||
this.ex.write(" jmp .L" + lblEnd + "\n");
|
||||
this.ex.write(".L" + lblTrue + ":\n");
|
||||
asm.mov("q", 0, "%rax");
|
||||
asm.jmp(lblEnd);
|
||||
asm.label(lblTrue);
|
||||
// true
|
||||
this.ex.write(" movq $1, %rax\n");
|
||||
this.ex.write(".L" + lblEnd + ":\n");
|
||||
asm.mov("q", 1, "%rax");
|
||||
asm.label(lblEnd);
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -242,18 +201,18 @@ public class GenASM implements Visitor<Void> {
|
||||
|
||||
boolean isFloatOperation = this.prepareRegisters(e.lhs, e.rhs);
|
||||
if (isFloatOperation) {
|
||||
this.ex.write(" ucomisd %xmm1, %xmm0\n");
|
||||
asm.ucomi("sd", "%xmm1", "%xmm0");
|
||||
} else {
|
||||
this.ex.write(" cmp %rbx, %rax\n");
|
||||
asm.cmp("q", "%rbx", "%rax");
|
||||
}
|
||||
this.ex.write(" jg .L" + lblTrue + "\n");
|
||||
asm.jg(lblTrue);
|
||||
// false
|
||||
this.ex.write(" movq $0, %rax\n");
|
||||
this.ex.write(" jmp .L" + lblEnd + "\n");
|
||||
this.ex.write(".L" + lblTrue + ":\n");
|
||||
asm.mov("q", 0, "%rax");
|
||||
asm.jmp(lblEnd);
|
||||
asm.label(lblTrue);
|
||||
// true
|
||||
this.ex.write(" movq $1, %rax\n");
|
||||
this.ex.write(".L" + lblEnd + ":\n");
|
||||
asm.mov("q", 1, "%rax");
|
||||
asm.label(lblEnd);
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -264,18 +223,18 @@ public class GenASM implements Visitor<Void> {
|
||||
|
||||
boolean isFloatOperation = this.prepareRegisters(e.lhs, e.rhs);
|
||||
if (isFloatOperation) {
|
||||
this.ex.write(" ucomisd %xmm1, %xmm0\n");
|
||||
asm.ucomi("sd", "%xmm1", "xmm0");
|
||||
} else {
|
||||
this.ex.write(" cmp %rbx, %rax\n");
|
||||
asm.cmp("q", "%rbx", "%rax");
|
||||
}
|
||||
this.ex.write(" jge .L" + lblTrue + "\n");
|
||||
asm.jge(lblTrue);
|
||||
// false
|
||||
this.ex.write(" movq $0, %rax\n");
|
||||
this.ex.write(" jmp .L" + lblEnd + "\n");
|
||||
this.ex.write(".L" + lblTrue + ":\n");
|
||||
asm.mov("q", 0, "%rax");
|
||||
asm.jmp(lblEnd);
|
||||
asm.label(lblTrue);
|
||||
// true
|
||||
this.ex.write(" movq $1, %rax\n");
|
||||
this.ex.write(".L" + lblEnd + ":\n");
|
||||
asm.mov("q", 1, "%rax");
|
||||
asm.label(lblEnd);
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -286,18 +245,18 @@ public class GenASM implements Visitor<Void> {
|
||||
|
||||
boolean isFloatOperation = this.prepareRegisters(e.lhs, e.rhs);
|
||||
if (isFloatOperation) {
|
||||
this.ex.write(" ucomisd %xmm1, %xmm0\n");
|
||||
asm.ucomi("sd", "%xmm1", "%xmm0");
|
||||
} else {
|
||||
this.ex.write(" cmp %rbx, %rax\n");
|
||||
asm.cmp("q", "%rbx", "%rax");
|
||||
}
|
||||
this.ex.write(" jl .L" + lblTrue + "\n");
|
||||
asm.jl(lblTrue);
|
||||
// false
|
||||
this.ex.write(" movq $0, %rax\n");
|
||||
this.ex.write(" jmp .L" + lblEnd + "\n");
|
||||
this.ex.write(".L" + lblTrue + ":\n");
|
||||
asm.mov("q", 0, "%rax");
|
||||
asm.jmp(lblEnd);
|
||||
asm.label(lblTrue);
|
||||
// true
|
||||
this.ex.write(" movq $1, %rax\n");
|
||||
this.ex.write(".L" + lblEnd + ":\n");
|
||||
asm.mov("q", 1, "%rax");
|
||||
asm.label(lblEnd);
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -308,18 +267,18 @@ public class GenASM implements Visitor<Void> {
|
||||
|
||||
boolean isFloatOperation = this.prepareRegisters(e.lhs, e.rhs);
|
||||
if (isFloatOperation) {
|
||||
this.ex.write(" ucomisd %xmm1, %xmm0\n");
|
||||
asm.ucomi("sd", "%xmm1", "%xmm0");
|
||||
} else {
|
||||
this.ex.write(" cmp %rbx, %rax\n");
|
||||
asm.cmp("q", "%rbx", "%rax");
|
||||
}
|
||||
this.ex.write(" jle .L" + lblTrue + "\n");
|
||||
asm.jle(lblTrue);
|
||||
// false
|
||||
this.ex.write(" movq $0, %rax\n");
|
||||
this.ex.write(" jmp .L" + lblEnd + "\n");
|
||||
this.ex.write(".L" + lblTrue + ":\n");
|
||||
asm.mov("q", 0, "%rax");
|
||||
asm.jmp(lblEnd);
|
||||
asm.label(lblTrue);
|
||||
// true
|
||||
this.ex.write(" movq $1, %rax\n");
|
||||
this.ex.write(".L" + lblEnd + ":\n");
|
||||
asm.mov("q", 1, "%rax");
|
||||
asm.label(lblEnd);
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -327,9 +286,9 @@ public class GenASM implements Visitor<Void> {
|
||||
public Void visit(AdditionExpression e) {
|
||||
boolean isFloatOperation = this.prepareRegisters(e.lhs, e.rhs);
|
||||
if (isFloatOperation) {
|
||||
this.ex.write(" addsd %xmm1, %xmm0\n");
|
||||
asm.add("sd", "%xmm1", "%xmm0");
|
||||
} else {
|
||||
this.ex.write(" addq %rbx, %rax\n");
|
||||
asm.add("q", "%rbx", "%rax");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -338,9 +297,9 @@ public class GenASM implements Visitor<Void> {
|
||||
public Void visit(SubstractionExpression e) {
|
||||
boolean isFloatOperation = this.prepareRegisters(e.lhs, e.rhs);
|
||||
if (isFloatOperation) {
|
||||
this.ex.write(" subsd %xmm1, %xmm0\n");
|
||||
asm.sub("sd", "%xmm1", "%xmm0");
|
||||
} else {
|
||||
this.ex.write(" subq %rbx, %rax\n");
|
||||
asm.sub("q", "%rbx", "%rax");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -349,9 +308,9 @@ public class GenASM implements Visitor<Void> {
|
||||
public Void visit(MultiplicationExpression e) {
|
||||
boolean isFloatOperation = this.prepareRegisters(e.lhs, e.rhs);
|
||||
if (isFloatOperation) {
|
||||
this.ex.write(" mulsd %xmm1, %xmm0\n");
|
||||
asm.mul("sd", "%xmm1", "%xmm0");
|
||||
} else {
|
||||
this.ex.write(" imulq %rbx, %rax\n");
|
||||
asm.imul("q", "%rbx", "%rax");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -360,10 +319,10 @@ public class GenASM implements Visitor<Void> {
|
||||
public Void visit(DivisionExpression e) {
|
||||
boolean isFloatOperation = this.prepareRegisters(e.lhs, e.rhs);
|
||||
if (isFloatOperation) {
|
||||
this.ex.write(" divsd %xmm1, %xmm0\n");
|
||||
asm.div("sd", "%xmm1", "%xmm0");
|
||||
} else {
|
||||
this.ex.write(" cqto\n"); // sign extend rax into rdx since we're dealing with signed values
|
||||
this.ex.write(" idiv %rbx\n"); // %rax/%rbx, quotient now in %rax
|
||||
asm.cqto();
|
||||
asm.idiv("q", "%rbx");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -371,13 +330,13 @@ public class GenASM implements Visitor<Void> {
|
||||
@Override
|
||||
public Void visit(ModuloExpression e) {
|
||||
e.lhs.welcome(this);
|
||||
this.ex.write(" pushq %rax\n");
|
||||
asm.push("q", "%rax");
|
||||
e.rhs.welcome(this);
|
||||
this.ex.write(" movq %rax, %rbx\n");
|
||||
this.ex.write(" popq %rax\n");
|
||||
this.ex.write(" cqto\n"); // sign extend rax into rdx since we're dealing with signed values
|
||||
this.ex.write(" idiv %rbx\n"); // %rax/%rbx, remainder now in %rdx
|
||||
this.ex.write(" movq %rdx, %rax\n");
|
||||
asm.mov("q", "%rax", "%rbx");
|
||||
asm.pop("q", "%rax");
|
||||
asm.cqto();
|
||||
asm.idiv("q", "%rbx");
|
||||
asm.mov("q", "%rdx", "%rax");
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -386,10 +345,10 @@ public class GenASM implements Visitor<Void> {
|
||||
e.lhs.welcome(this);
|
||||
if (e.lhs.type.equals(Type.getFloatType())) {
|
||||
String floatLabel = fw.getNegateFloat();
|
||||
this.ex.write(" movsd " + floatLabel + "(%rip), %xmm1\n");
|
||||
this.ex.write(" xorpd %xmm1, %xmm0\n");
|
||||
asm.mov("sd", floatLabel, "%rip", "%xmm1");
|
||||
asm.xor("pd", "%xmm1", "%xmm0");
|
||||
} else {
|
||||
this.ex.write(" neg %rax\n");
|
||||
asm.neg("%rax");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -404,28 +363,28 @@ public class GenASM implements Visitor<Void> {
|
||||
// Wenn LHS != 0 bedeutet das true
|
||||
// also können wir direkt sagen dass das Ergebnis true ist
|
||||
e.lhs.welcome(this);
|
||||
this.ex.write(" cmpq $0, %rax\n");
|
||||
this.ex.write(" jne .L" + lblTrue + "\n");
|
||||
asm.cmp("q", 0, "%rax");
|
||||
asm.jne(lblTrue);
|
||||
|
||||
// LHS war false, also werte RHS aus
|
||||
// Wenn RHS == 0 bedeutet das false,
|
||||
// also ist das Gesamtergebnis false
|
||||
e.rhs.welcome(this);
|
||||
this.ex.write(" cmpq $0, %rax\n");
|
||||
this.ex.write(" je .L" + lblFalse + "\n");
|
||||
asm.cmp("q", 0, "%rax");
|
||||
asm.je(lblFalse);
|
||||
|
||||
// Die Expression wertet zu true aus
|
||||
// Springe am false Teil vorbei
|
||||
this.ex.write(".L" + lblTrue + ":\n");
|
||||
this.ex.write(" movq $1, %rax\n");
|
||||
this.ex.write(" jmp .L" + lblEnd + "\n");
|
||||
asm.label(lblTrue);
|
||||
asm.mov("q", 1, "%rax");
|
||||
asm.jmp(lblEnd);
|
||||
|
||||
// Die Expressoin wertet zu false aus
|
||||
this.ex.write(".L" + lblFalse + ":\n");
|
||||
this.ex.write(" movq $0, %rax\n");
|
||||
asm.label(lblFalse);
|
||||
asm.mov("q", 0, "%rax");
|
||||
|
||||
// Das hier ist das ende
|
||||
this.ex.write(".L" + lblEnd + ":\n");
|
||||
asm.label(lblEnd);
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -439,28 +398,28 @@ public class GenASM implements Visitor<Void> {
|
||||
// Wenn LHS == 0, bedeutet das false
|
||||
// also können wir direkt sagen dass das Ergebnis false ist
|
||||
e.lhs.welcome(this);
|
||||
this.ex.write(" cmpq $0, %rax\n");
|
||||
this.ex.write(" je .L" + lblFalse + "\n");
|
||||
asm.cmp("q", 0, "%rax");
|
||||
asm.je(lblFalse);
|
||||
|
||||
// LHS war true, also werte RHS aus.
|
||||
// Wenn RHS == 0, bedeutet das false
|
||||
// also ist das Gesamtergebnis false
|
||||
e.rhs.welcome(this);
|
||||
this.ex.write(" cmpq $0, %rax\n");
|
||||
this.ex.write(" je .L" + lblFalse + "\n");
|
||||
asm.cmp("q", 0, "%rax");
|
||||
asm.je(lblFalse);
|
||||
|
||||
// Die Expression wertet zu true aus
|
||||
// Springe am false Teil vorbei
|
||||
this.ex.write(".L" + lblTrue + ":\n");
|
||||
this.ex.write(" movq $1, %rax\n");
|
||||
this.ex.write(" jmp .L" + lblEnd + "\n");
|
||||
asm.label(lblTrue);
|
||||
asm.mov("q", 1, "%rax");
|
||||
asm.jmp(lblEnd);
|
||||
|
||||
// Die Expressoin wertet zu false aus
|
||||
this.ex.write(".L" + lblFalse + ":\n");
|
||||
this.ex.write(" movq $0, %rax\n");
|
||||
asm.label(lblFalse);
|
||||
asm.mov("q", 0, "%rax");
|
||||
|
||||
// Das hier ist das ende
|
||||
this.ex.write(".L" + lblEnd + ":\n");
|
||||
asm.label(lblEnd);
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -473,21 +432,21 @@ public class GenASM implements Visitor<Void> {
|
||||
// Wenn LHS != 0 bedeutet das true, also jumpe zum false Teil
|
||||
// Wenn nicht, falle durch zum true Teil
|
||||
e.lhs.welcome(this);
|
||||
this.ex.write(" cmpq $0, %rax\n");
|
||||
this.ex.write(" jne .L" + lblFalse + "\n");
|
||||
asm.cmp("q", 0, "%rax");
|
||||
asm.jne(lblFalse);
|
||||
|
||||
// Hier ist das Ergebnis true
|
||||
// Springe am false Teil vorbei
|
||||
this.ex.write(" movq $1, %rax\n");
|
||||
this.ex.write(" jmp .L" + lblEnd + "\n");
|
||||
asm.mov("q", 1, "%rax");
|
||||
asm.jmp(lblEnd);
|
||||
|
||||
// Hier ist das Ergebnis false
|
||||
// Falle zum Ende durch
|
||||
this.ex.write(".L" + lblFalse + ":\n");
|
||||
this.ex.write("movq $0, %rax\n");
|
||||
asm.label(lblFalse);
|
||||
asm.mov("q", 0, "%rax");
|
||||
|
||||
// Hier ist das Ende
|
||||
this.ex.write(".L" + lblEnd + ":\n");
|
||||
asm.label(lblEnd);
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -497,25 +456,25 @@ public class GenASM implements Visitor<Void> {
|
||||
int lblEnd = ++lCount;
|
||||
boolean hasElse = e.alt != null || e.elif != null;
|
||||
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
|
||||
// Jump to end if there is no else part, this saves a label declaration
|
||||
if (hasElse) {
|
||||
this.ex.write(" jz .L" + lblElse + "\n");
|
||||
asm.jz(lblElse);
|
||||
} else {
|
||||
this.ex.write(" jz .L" + lblEnd + "\n");
|
||||
asm.jz(lblEnd);
|
||||
}
|
||||
e.then.welcome(this);
|
||||
if (hasElse) {
|
||||
this.ex.write(" jmp .L" + lblEnd + "\n");
|
||||
this.ex.write(".L" + lblElse + ":\n");
|
||||
asm.jmp(lblEnd);
|
||||
asm.label(lblElse);
|
||||
if (e.alt != null) {
|
||||
e.alt.welcome(this);
|
||||
} else {
|
||||
e.elif.welcome(this);
|
||||
}
|
||||
}
|
||||
this.ex.write(".L" + lblEnd + ":\n");
|
||||
asm.label(lblEnd);
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -523,24 +482,24 @@ public class GenASM implements Visitor<Void> {
|
||||
public Void visit(WhileLoop e) {
|
||||
int lblCond = ++lCount;
|
||||
int lblEnd = ++lCount;
|
||||
this.ex.write(".L" + lblCond + ":\n");
|
||||
asm.label(lblCond);
|
||||
e.cond.welcome(this);
|
||||
this.ex.write(" cmp $0, %rax\n");
|
||||
this.ex.write(" jz .L" + lblEnd + "\n");
|
||||
asm.cmp("", 0, "%rax");
|
||||
asm.jz(lblEnd);
|
||||
e.block.welcome(this);
|
||||
this.ex.write(" jmp .L" + lblCond + "\n");
|
||||
this.ex.write(".L" + lblEnd + ":\n");
|
||||
asm.jmp(lblCond);
|
||||
asm.label(lblEnd);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(DoWhileLoop e) {
|
||||
int lblStart = ++lCount;
|
||||
this.ex.write(".L" + lblStart + ":\n");
|
||||
asm.label(lblStart);
|
||||
e.block.welcome(this);
|
||||
e.cond.welcome(this);
|
||||
this.ex.write(" cmp $0, %rax\n");
|
||||
this.ex.write(" jnz .L" + lblStart + "\n");
|
||||
asm.cmp("", 0, "%rax");
|
||||
asm.jnz(lblStart);
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -549,15 +508,14 @@ public class GenASM implements Visitor<Void> {
|
||||
int lblStart = ++lCount;
|
||||
int lblEnd = ++lCount;
|
||||
e.init.welcome(this);
|
||||
this.ex.write(".L" + lblStart + ":\n");
|
||||
asm.label(lblStart);
|
||||
e.condition.welcome(this);
|
||||
this.ex.write(" cmp $0, %rax\n");
|
||||
this.ex.write(" jz .L" + lblEnd + "\n");
|
||||
asm.cmp("", 0, "%rax");
|
||||
asm.jz(lblEnd);
|
||||
e.block.welcome(this);
|
||||
e.step.welcome(this);
|
||||
this.ex.write(" jmp .L" + lblStart + "\n");
|
||||
this.ex.write(".L" + lblEnd + ":\n");
|
||||
|
||||
asm.jmp(lblStart);
|
||||
asm.label(lblEnd);
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -570,10 +528,10 @@ public class GenASM implements Visitor<Void> {
|
||||
int offset = this.env.get(e.name);
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -586,9 +544,9 @@ public class GenASM implements Visitor<Void> {
|
||||
// Determine where the result of this expression was placed into
|
||||
// and move it onto the stack from there
|
||||
if (e.expression.type.equals(Type.getFloatType())) {
|
||||
this.ex.write(" movq %xmm0, " + offset + "(%rbp)\n");
|
||||
asm.mov("q", "%xmm0", offset, "%rbp");
|
||||
} else {
|
||||
this.ex.write(" movq %rax, " + offset + "(%rbp)\n");
|
||||
asm.mov("q", "%rax", offset, "%rbp");
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -597,9 +555,9 @@ public class GenASM implements Visitor<Void> {
|
||||
@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");
|
||||
asm.mov("q", "%rbp", "%rsp");
|
||||
asm.pop("q", "%rbp");
|
||||
asm.ret();
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -616,12 +574,10 @@ public class GenASM implements Visitor<Void> {
|
||||
int lblStart = ++lCount;
|
||||
this.currentFunctionStartLabel = lblStart;
|
||||
this.currentFunctionParams = e.parameters;
|
||||
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");
|
||||
this.ex.write(".L" + lblStart + ":\n");
|
||||
asm.functionHead(e.name);
|
||||
asm.push("q", "%rbp");
|
||||
asm.mov("q", "%rsp", "%rbp");
|
||||
asm.label(lblStart);
|
||||
|
||||
// hole die anzahl der lokalen variablen
|
||||
this.vars = new TreeSet<String>();
|
||||
@@ -667,13 +623,13 @@ public class GenASM implements Visitor<Void> {
|
||||
fi = 0;
|
||||
for (var param: registerParameters) {
|
||||
if (param.type.equals(Type.getFloatType())) {
|
||||
this.ex.write(" movq "+ this.floatRegisters[fi] + ", %rax\n");
|
||||
this.ex.write(" pushq %rax\n");
|
||||
asm.mov("q", this.floatRegisters[fi], "%rax");
|
||||
asm.push("q", "%rax");
|
||||
offset -= 8;
|
||||
this.env.put(param.name, offset); // negative, liegt unter aktuellem BP
|
||||
fi++;
|
||||
} else {
|
||||
this.ex.write(" pushq " + this.registers[ri] + "\n");
|
||||
asm.push("q", this.registers[ri]);
|
||||
offset -= 8;
|
||||
this.env.put(param.name, offset); // negative, liegt unter aktuellem BP
|
||||
ri++;
|
||||
@@ -683,7 +639,7 @@ public class GenASM implements Visitor<Void> {
|
||||
// Reserviere Platz auf dem Stack für jede lokale variable
|
||||
for (String lok_var : vars) {
|
||||
offset -= 8;
|
||||
this.ex.write(" pushq $0\n");
|
||||
asm.push("q", 0);
|
||||
this.env.put(lok_var, offset);
|
||||
}
|
||||
|
||||
@@ -700,18 +656,18 @@ public class GenASM implements Visitor<Void> {
|
||||
e.arguments[i].welcome(this);
|
||||
|
||||
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
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -757,10 +713,10 @@ public class GenASM implements Visitor<Void> {
|
||||
for (var arg : e.arguments) {
|
||||
arg.welcome(this);
|
||||
if (arg.type.equals(Type.getFloatType())) {
|
||||
this.ex.write(" movq %xmm0, %rax\n");
|
||||
this.ex.write(" pushq %rax\n");
|
||||
asm.mov("q", "%xmm0", "%rax");
|
||||
asm.push("q", "%rax");
|
||||
} 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++) {
|
||||
int indexInArguments = xmmIdxs[i];
|
||||
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
|
||||
for (int i = 0; i <= ri; i++) {
|
||||
int indexInArguments = rIdxs[i];
|
||||
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
|
||||
@@ -784,39 +740,34 @@ public class GenASM implements Visitor<Void> {
|
||||
stackStartOffset -= 8;
|
||||
int indexInArguments = stackIdxs.get(i);
|
||||
int rspOffset = (((e.arguments.length - indexInArguments) - 1) * 8);
|
||||
this.ex.write(" movq " + rspOffset + "(%rsp), %rax\n");
|
||||
this.ex.write(" movq %rax, " + stackStartOffset + "(%rsp)\n");
|
||||
asm.mov("q", rspOffset, "%rsp", "%rax");
|
||||
asm.mov("q", "%rax", stackStartOffset, "%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;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(Program e) {
|
||||
this.ex.write(".text\n");
|
||||
asm.text(".text");
|
||||
for (var func : e.funcs) {
|
||||
func.welcome(this);
|
||||
this.ex.write("\n");
|
||||
asm.newline();
|
||||
}
|
||||
this.ex.write(".globl " + mainName + "\n");
|
||||
this.ex.write(".type " + mainName + ", @function\n");
|
||||
this.ex.write(mainName + ":\n");
|
||||
this.ex.write(" pushq %rbp\n");
|
||||
this.ex.write(" movq %rsp, %rbp\n");
|
||||
asm.functionHead(mainName);
|
||||
asm.push("q", "%rbp");
|
||||
asm.mov("q", "%rsp", "%rbp");
|
||||
e.expression.welcome(this);
|
||||
asm.mov("q", "%rbp", "%rsp");
|
||||
asm.pop("q", "%rbp");
|
||||
asm.ret();
|
||||
|
||||
this.ex.write(" movq %rbp, %rsp\n");
|
||||
this.ex.write(" popq %rbp\n");
|
||||
this.ex.write(" ret\n");
|
||||
|
||||
// PRINT FLOATS HERE
|
||||
this.ex.write("\n");
|
||||
this.ex.write(fw.getFloatSection());
|
||||
asm.text(fw.getFloatSection());
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -845,21 +796,21 @@ public class GenASM implements Visitor<Void> {
|
||||
int offset = this.env.get(e.varName);
|
||||
|
||||
// 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
|
||||
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++) {
|
||||
// "follow" the current path element
|
||||
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
|
||||
|
||||
// push rax to xmm0 if the result type is a float
|
||||
if (e.type.equals(Type.getFloatType())) {
|
||||
this.ex.write(" movq %rax, %xmm0\n");
|
||||
asm.mov("q", "%rax", "%xmm0");
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -873,20 +824,20 @@ public class GenASM implements Visitor<Void> {
|
||||
|
||||
// move float values from xmm0 to rax first
|
||||
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
|
||||
var structDef = this.structs.get(e.structName);
|
||||
this.ex.write(" movl $" + Helper.getFieldSizeBytes(structDef) + ", %edi\n");
|
||||
this.ex.write(" call malloc@PLT\n"); // struct address now in rax
|
||||
asm.mov("l", Helper.getFieldSizeBytes(structDef), "%edi");
|
||||
asm.call("malloc@PLT");
|
||||
|
||||
// push args into struct memory, last arg is ontop of the stack
|
||||
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;
|
||||
@@ -894,14 +845,14 @@ public class GenASM implements Visitor<Void> {
|
||||
|
||||
@Override
|
||||
public Void visit(NullExpression e) {
|
||||
this.ex.write(" movq $0, %rax\n");
|
||||
asm.mov("q", 0 , "%rax");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(DestructorCall e) {
|
||||
this.ex.write(" movq " +this.env.get(e.name) + "(%rbp), %rdi\n");
|
||||
this.ex.write(" call free@PLT\n");
|
||||
asm.mov("q", this.env.get(e.name), "%rbp", "%rdi");
|
||||
asm.call("free@PLT");
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -915,25 +866,25 @@ public class GenASM implements Visitor<Void> {
|
||||
|
||||
// Move it from xmm0 rax if its a flaot
|
||||
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
|
||||
this.ex.write(" pushq %rax\n");
|
||||
asm.push("q", "%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,
|
||||
// move the address of the next referenced struct into rax
|
||||
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());
|
||||
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
|
||||
this.ex.write(" popq " + Helper.getFieldOffset(structDef, fieldNameToUpdate) + "(%rax)\n");
|
||||
this.ex.write(" movq $0, %rax\n"); // clear rax sind an assignment has no result
|
||||
asm.pop("q", Helper.getFieldOffset(structDef, fieldNameToUpdate) + "(%rax)");
|
||||
asm.mov("q", 0 , "%rax"); // clear rax since an assignment has no result
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user