168 lines
3.6 KiB
Java
168 lines
3.6 KiB
Java
package cd.backend.codegen;
|
|
|
|
import cd.Config;
|
|
import cd.backend.codegen.RegisterManager.Register;
|
|
|
|
import java.io.IOException;
|
|
import java.io.Writer;
|
|
|
|
public class AssemblyEmitter {
|
|
public Writer out;
|
|
public StringBuilder indent = new StringBuilder();
|
|
public int counter = 0;
|
|
|
|
public AssemblyEmitter(Writer out) {
|
|
this.out = out;
|
|
}
|
|
|
|
/**
|
|
* Creates an constant operand.
|
|
*/
|
|
static String constant(int i) {
|
|
return "$" + i;
|
|
}
|
|
|
|
/**
|
|
* Creates an constant operand with the address of a label.
|
|
*/
|
|
static String labelAddress(String lbl) {
|
|
return "$" + lbl;
|
|
}
|
|
|
|
/**
|
|
* Creates an operand relative to another operand.
|
|
*/
|
|
static String registerOffset(int offset, Register reg) {
|
|
return String.format("%d(%s)", offset, reg);
|
|
}
|
|
|
|
/**
|
|
* Creates an operand addressing an item in an array
|
|
*/
|
|
static String arrayAddress(Register arrReg, Register idxReg) {
|
|
final int offset = Config.SIZEOF_PTR * 2; // one word each in front for
|
|
// vptr and length
|
|
final int mul = Config.SIZEOF_PTR; // assume all arrays of 4-byte elem
|
|
return String.format("%d(%s,%s,%d)", offset, arrReg, idxReg, mul);
|
|
}
|
|
|
|
void increaseIndent(String comment) {
|
|
indent.append(" ");
|
|
if (comment != null)
|
|
emitComment(comment);
|
|
}
|
|
|
|
void decreaseIndent() {
|
|
indent.setLength(indent.length() - 2);
|
|
}
|
|
|
|
void emitCommentSection(String name) {
|
|
int indentLen = indent.length();
|
|
int breakLen = 68 - indentLen - name.length();
|
|
StringBuffer sb = new StringBuffer();
|
|
sb.append(Config.COMMENT_SEP).append(" ");
|
|
for (int i = 0; i < indentLen; i++)
|
|
sb.append("_");
|
|
sb.append(name);
|
|
for (int i = 0; i < breakLen; i++)
|
|
sb.append("_");
|
|
|
|
try {
|
|
out.write(sb.toString());
|
|
out.write("\n");
|
|
} catch (IOException e) {
|
|
}
|
|
}
|
|
|
|
void emitComment(String comment) {
|
|
emitRaw(Config.COMMENT_SEP + " " + comment);
|
|
}
|
|
|
|
void emit(String op, Register src, String dest) {
|
|
emit(op, src.repr, dest);
|
|
}
|
|
|
|
void emit(String op, String src, Register dest) {
|
|
emit(op, src, dest.repr);
|
|
}
|
|
|
|
void emit(String op, Register src, Register dest) {
|
|
emit(op, src.repr, dest.repr);
|
|
}
|
|
|
|
void emit(String op, String src, String dest) {
|
|
emitRaw(String.format("%s %s, %s", op, src, dest));
|
|
}
|
|
|
|
void emit(String op, int src, Register dest) {
|
|
emit(op, constant(src), dest);
|
|
}
|
|
|
|
void emit(String op, String dest) {
|
|
emitRaw(op + " " + dest);
|
|
}
|
|
|
|
void emit(String op, Register reg) {
|
|
emit(op, reg.repr);
|
|
}
|
|
|
|
void emit(String op, int dest) {
|
|
emit(op, constant(dest));
|
|
}
|
|
|
|
void emitMove(Register src, String dest) {
|
|
emitMove(src.repr, dest);
|
|
}
|
|
|
|
void emitMove(Register src, Register dest) {
|
|
emitMove(src.repr, dest.repr);
|
|
}
|
|
|
|
void emitMove(String src, Register dest) {
|
|
emitMove(src, dest.repr);
|
|
}
|
|
|
|
void emitMove(String src, String dest) {
|
|
if (!src.equals(dest))
|
|
emit("movl", src, dest);
|
|
}
|
|
|
|
void emitLoad(int srcOffset, Register src, Register dest) {
|
|
emitMove(registerOffset(srcOffset, src), dest.repr);
|
|
}
|
|
|
|
void emitStore(Register src, int destOffset, Register dest) {
|
|
emitStore(src.repr, destOffset, dest);
|
|
}
|
|
|
|
void emitStore(String src, int destOffset, Register dest) {
|
|
emitMove(src, registerOffset(destOffset, dest));
|
|
}
|
|
|
|
void emitConstantData(String data) {
|
|
emitRaw(String.format("%s %s", Config.DOT_INT, data));
|
|
}
|
|
|
|
String uniqueLabel() {
|
|
String labelName = "label" + counter++;
|
|
return labelName;
|
|
}
|
|
|
|
void emitLabel(String label) {
|
|
try {
|
|
out.write(label + ":" + "\n");
|
|
} catch (IOException e) {
|
|
throw new RuntimeException(e);
|
|
}
|
|
}
|
|
|
|
void emitRaw(String op) {
|
|
try {
|
|
out.write(indent.toString());
|
|
out.write(op);
|
|
out.write("\n");
|
|
} catch (IOException e) {
|
|
throw new RuntimeException(e);
|
|
}
|
|
}
|
|
} |