aboutsummaryrefslogtreecommitdiff
path: root/ir.c
diff options
context:
space:
mode:
authortomsmeding <tom.smeding@gmail.com>2018-01-06 21:38:40 +0100
committertomsmeding <tom.smeding@gmail.com>2018-01-06 21:38:40 +0100
commitf4b60f43cf636d48f8857676b072371f1575a5b2 (patch)
treed185ecd5d15b379e64474030bad8a2ab386c4284 /ir.c
parentc4a376d1c7263993f13e9cf276ebd9e530fd419c (diff)
Working compiler
Diffstat (limited to 'ir.c')
-rw-r--r--ir.c101
1 files changed, 65 insertions, 36 deletions
diff --git a/ir.c b/ir.c
index 54f1259..e3a3171 100644
--- a/ir.c
+++ b/ir.c
@@ -48,7 +48,7 @@ void ir_print(struct ir *ir, FILE *f) {
}
}
-static const char* condcode_show(enum condcode condcode) {
+const char* condcode_show(enum condcode condcode) {
switch (condcode) {
case CCZ: return "z";
case CCNZ: return "nz";
@@ -60,67 +60,86 @@ static const char* condcode_show(enum condcode condcode) {
}
}
-static const char* ref_show(struct ref ref) {
- static char cbuf[3][16];
- static int cbufi = 0;
+void ref_show(struct ref ref, char *dest) {
static const char *special[8] = {"A", "B", "C", "D", "X", "Y", "SP", "BP"};
- const char *suffix;
- if (ref.rel == REFREL_ZERO) suffix = "";
- else if (ref.rel == REFREL_DATA) suffix = ":data";
- else if (ref.rel == REFREL_HEAP) suffix = ":heap";
- else assert(false);
+ const char *suffix = NULL;
+ if (ref.type == REF_MEM) {
+ if (ref.rel == REFREL_ZERO) suffix = "";
+ else if (ref.rel == REFREL_DATA) suffix = ":data";
+ else if (ref.rel == REFREL_HEAP) suffix = ":heap";
+ else assert(false);
+ }
switch (ref.type) {
case REF_REG:
- if (ref.reg == REG_UNUSED) return "<<UNUSED?>>";
- if (ref.reg < 0) return special[-(ref.reg - REG_A)];
- cbufi = (cbufi + 1) % 3;
- sprintf(cbuf[cbufi], "t%d", ref.reg);
- return cbuf[cbufi];
+ if (ref.reg == REG_UNUSED) {
+ strcpy(dest, "<<UNUSED?>>");
+ } else if (ref.reg < 0) {
+ strcpy(dest, special[-(ref.reg - REG_A)]);
+ } else {
+ sprintf(dest, "t%d", ref.reg);
+ }
+ break;
case REF_MEM:
- cbufi = (cbufi + 1) % 3;
if (ref.reg == REG_UNUSED) {
- sprintf(cbuf[cbufi], "[%d%s]", ref.offset, suffix);
+ sprintf(dest, "[0x%x%s]", ref.offset, suffix);
} else if (ref.reg < 0) {
- sprintf(cbuf[cbufi], "[%s + %d%s]", special[-(ref.reg - REG_A)], ref.offset, suffix);
+ if (ref.offset < 0) {
+ sprintf(dest, "[%s - %d%s]", special[-(ref.reg - REG_A)], -ref.offset, suffix);
+ } else {
+ sprintf(dest, "[%s + %d%s]", special[-(ref.reg - REG_A)], ref.offset, suffix);
+ }
} else {
- sprintf(cbuf[cbufi], "[t%d + %d%s]", ref.reg, ref.offset, suffix);
+ if (ref.offset < 0) {
+ sprintf(dest, "[t%d - %d%s]", ref.reg, -ref.offset, suffix);
+ } else {
+ sprintf(dest, "[t%d + %d%s]", ref.reg, ref.offset, suffix);
+ }
}
- return cbuf[cbufi];
+ break;
case REF_IMM:
- cbufi = (cbufi + 1) % 3;
- sprintf(cbuf[cbufi], "%d", ref.imm);
- return cbuf[cbufi];
+ sprintf(dest, "%d", ref.imm);
+ break;
default:
assert(false);
}
}
+static const char* ref_show_c(struct ref ref) {
+ static char cbuf[3][40];
+ static int cbufi = 0;
+
+ char *buf = cbuf[cbufi];
+ cbufi = (cbufi + 1) % 3;
+ ref_show(ref, buf);
+ return buf;
+}
+
void irins_print(struct irins *ins, FILE *f) {
switch (ins->type) {
- case INS_ADD: fprintf(f, "\t%s <- %s + %s\n", ref_show(ins->r0), ref_show(ins->r1), ref_show(ins->r2)); break;
- case INS_SUB: fprintf(f, "\t%s <- %s - %s\n", ref_show(ins->r0), ref_show(ins->r1), ref_show(ins->r2)); break;
- case INS_MUL: fprintf(f, "\t%s <- %s * %s\n", ref_show(ins->r0), ref_show(ins->r1), ref_show(ins->r2)); break;
- case INS_DIV: fprintf(f, "\t%s <- %s / %s\n", ref_show(ins->r0), ref_show(ins->r1), ref_show(ins->r2)); break;
- case INS_MOD: fprintf(f, "\t%s <- %s %% %s\n", ref_show(ins->r0), ref_show(ins->r1), ref_show(ins->r2)); break;
- case INS_NEG: fprintf(f, "\t%s <- -%s\n", ref_show(ins->r0), ref_show(ins->r1)); break;
- case INS_NOT: fprintf(f, "\t%s <- ~%s\n", ref_show(ins->r0), ref_show(ins->r1)); break;
- case INS_TEST: fprintf(f, "\ttest %s, %s\n", ref_show(ins->r1), ref_show(ins->r2)); break;
- case INS_PUSH: fprintf(f, "\tpush %s\n", ref_show(ins->r1)); break;
- case INS_POP: fprintf(f, "\t%s <- pop\n", ref_show(ins->r0)); break;
- case INS_CMP: fprintf(f, "\tcmp %s, %s\n", ref_show(ins->r1), ref_show(ins->r2)); break;
+ case INS_ADD: fprintf(f, "\t%s <- %s + %s\n", ref_show_c(ins->r0), ref_show_c(ins->r1), ref_show_c(ins->r2)); break;
+ case INS_SUB: fprintf(f, "\t%s <- %s - %s\n", ref_show_c(ins->r0), ref_show_c(ins->r1), ref_show_c(ins->r2)); break;
+ case INS_MUL: fprintf(f, "\t%s <- %s * %s\n", ref_show_c(ins->r0), ref_show_c(ins->r1), ref_show_c(ins->r2)); break;
+ case INS_DIV: fprintf(f, "\t%s <- %s / %s\n", ref_show_c(ins->r0), ref_show_c(ins->r1), ref_show_c(ins->r2)); break;
+ case INS_MOD: fprintf(f, "\t%s <- %s %% %s\n", ref_show_c(ins->r0), ref_show_c(ins->r1), ref_show_c(ins->r2)); break;
+ case INS_NEG: fprintf(f, "\t%s <- -%s\n", ref_show_c(ins->r0), ref_show_c(ins->r1)); break;
+ case INS_NOT: fprintf(f, "\t%s <- ~%s\n", ref_show_c(ins->r0), ref_show_c(ins->r1)); break;
+ case INS_TEST: fprintf(f, "\ttest %s, %s\n", ref_show_c(ins->r1), ref_show_c(ins->r2)); break;
+ case INS_PUSH: fprintf(f, "\tpush %s\n", ref_show_c(ins->r1)); break;
+ case INS_POP: fprintf(f, "\t%s <- pop\n", ref_show_c(ins->r0)); break;
+ case INS_CMP: fprintf(f, "\tcmp %s, %s\n", ref_show_c(ins->r1), ref_show_c(ins->r2)); break;
case INS_LBL: fprintf(f, "%s:\n", ins->name); break;
case INS_JMP: fprintf(f, "\tjmp %s\n", ins->name); break;
case INS_JCC: fprintf(f, "\tj%s %s\n", condcode_show(ins->condcode), ins->name); break;
case INS_CALL: fprintf(f, "\tcall %s\n", ins->name); break;
- case INS_CALLV: fprintf(f, "\t%s <- call %s\n", ref_show(ins->r0), ins->name); break;
+ case INS_CALLV: fprintf(f, "\t%s <- call %s\n", ref_show_c(ins->r0), ins->name); break;
case INS_RET: fprintf(f, "\tret\n"); break;
- case INS_RETV: fprintf(f, "\tret %s\n", ref_show(ins->r1)); break;
- case INS_MOV: fprintf(f, "\t%s <- %s\n", ref_show(ins->r0), ref_show(ins->r1)); break;
+ case INS_RETV: fprintf(f, "\tret %s\n", ref_show_c(ins->r1)); break;
+ case INS_MOV: fprintf(f, "\t%s <- %s\n", ref_show_c(ins->r0), ref_show_c(ins->r1)); break;
case INS_BRK: fprintf(f, "\tbrk\n"); break;
default: assert(false);
}
@@ -253,3 +272,13 @@ struct ref ref_next_register(void) {
static int next = 0;
return ref_reg(next++);
}
+
+bool ref_equal(struct ref r1, struct ref r2) {
+ if (r1.type != r2.type) return false;
+ switch (r1.type) {
+ case REF_REG: return r1.reg == r2.reg;
+ case REF_MEM: return r1.reg == r2.reg && r1.offset == r2.offset && r1.rel == r2.rel;
+ case REF_IMM: return r1.imm == r2.imm;
+ default: assert(false);
+ }
+}