aboutsummaryrefslogtreecommitdiff
path: root/ir.c
diff options
context:
space:
mode:
authortomsmeding <tom.smeding@gmail.com>2018-01-05 23:42:24 +0100
committertomsmeding <tom.smeding@gmail.com>2018-01-05 23:42:24 +0100
commit3272b5d83d2e2167eed24748557df88bd66584ee (patch)
tree6b8f1574f6d6a44e11b74903516286f6249cb0b7 /ir.c
parenta298cb75c4f586b83b304c7dc66cb555693ea1b8 (diff)
There's actually a chance that, correctly stringified, this will work
Diffstat (limited to 'ir.c')
-rw-r--r--ir.c79
1 files changed, 67 insertions, 12 deletions
diff --git a/ir.c b/ir.c
index cf529dd..69a9d64 100644
--- a/ir.c
+++ b/ir.c
@@ -1,8 +1,29 @@
#include <stdlib.h>
+#include <string.h>
#include <assert.h>
#include "ir.h"
+static int cap_interned = 32;
+static int num_interned = 0;
+static char **interned_strings = NULL;
+
+const char* ir_str(const char *str) {
+ if (interned_strings == NULL) {
+ interned_strings = malloc(cap_interned * sizeof(char*));
+ }
+ for (int i = 0; i < num_interned; i++) {
+ if (strcmp(interned_strings[i], str) == 0) return interned_strings[i];
+ }
+ if (num_interned == cap_interned) {
+ cap_interned *= 2;
+ interned_strings = realloc(interned_strings, cap_interned * sizeof(char*));
+ }
+ interned_strings[num_interned++] = strdup(str);
+ return interned_strings[num_interned - 1];
+}
+
+
struct ir* ir_make(void) {
struct ir *ir = malloc(sizeof(struct ir));
ir->cap = 32;
@@ -90,7 +111,7 @@ void irins_print(struct irins *ins, FILE *f) {
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_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_LBL: fprintf(f, "%s:\n", ins->name); break;
case INS_JMP: fprintf(f, "\tjmp %s\n", ins->name); break;
@@ -100,6 +121,7 @@ void irins_print(struct irins *ins, FILE *f) {
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_BRK: fprintf(f, "\tbrk\n"); break;
default: assert(false);
}
}
@@ -110,12 +132,19 @@ struct ref ir_reserve_global(struct ir *ir, int size) {
return ref_mem(REG_UNUSED, offset, REFREL_DATA);
}
-void ir_append(struct ir *ir, struct irins *ins) {
+void ir_insert_before(struct ir *ir, int pos, struct irins *ins) {
+ assert(pos >= 0 && pos <= ir->len);
if (ir->len == ir->cap) {
ir->cap *= 2;
ir->inss = realloc(ir->inss, ir->cap * sizeof(struct irins*));
}
- ir->inss[ir->len++] = ins;
+ memmove(ir->inss + pos + 1, ir->inss + pos, (ir->len - pos) * sizeof(struct irins*));
+ ir->inss[pos] = ins;
+ ir->len++;
+}
+
+void ir_append(struct ir *ir, struct irins *ins) {
+ ir_insert_before(ir, ir->len, ins);
}
struct irins* irins_make(enum instype type) {
@@ -125,9 +154,9 @@ struct irins* irins_make(enum instype type) {
return ins;
}
-struct irins* irins_make_name(enum instype type, char *name) {
+struct irins* irins_make_name(enum instype type, const char *name) {
struct irins *ins = irins_make(type);
- ins->name = name;
+ ins->name = ir_str(name);
return ins;
}
@@ -163,23 +192,49 @@ struct irins* irins_make_12(enum instype type, struct ref r1, struct ref r2) {
return ins;
}
-struct irins* irins_make_jcc(char *name, enum condcode condcode) {
+struct irins* irins_make_jcc(const char *name, enum condcode condcode) {
struct irins *ins = irins_make(INS_JCC);
- ins->name = name;
+ ins->name = ir_str(name);
ins->condcode = condcode;
return ins;
}
void irins_delete(struct irins *ins) {
- if (ins->name) free(ins->name);
free(ins);
}
-char* gen_label_name(void) {
+void irins_which_refs(const struct irins *ins, bool have[3]) {
+ have[0] = false; have[1] = false; have[2] = false;
+ switch (ins->type) {
+ case INS_ADD: have[0] = true; have[1] = true; have[2] = true; break;
+ case INS_SUB: have[0] = true; have[1] = true; have[2] = true; break;
+ case INS_MUL: have[0] = true; have[1] = true; have[2] = true; break;
+ case INS_DIV: have[0] = true; have[1] = true; have[2] = true; break;
+ case INS_MOD: have[0] = true; have[1] = true; have[2] = true; break;
+ case INS_NEG: have[0] = true; have[1] = true; break;
+ case INS_NOT: have[0] = true; have[1] = true; break;
+ case INS_TEST: have[1] = true; have[2] = true; break;
+ case INS_PUSH: have[1] = true; break;
+ case INS_POP: have[0] = true; break;
+ case INS_CMP: have[1] = true; have[2] = true; break;
+ case INS_LBL: break;
+ case INS_JMP: break;
+ case INS_JCC: break;
+ case INS_CALL: break;
+ case INS_CALLV: have[0] = true; break;
+ case INS_RET: break;
+ case INS_RETV: have[1] = true; break;
+ case INS_MOV: have[0] = true; have[1] = true; break;
+ case INS_BRK: break;
+ default: assert(false);
+ }
+}
+
+const char* gen_label_name(void) {
static int next = 0;
- char *buf = malloc(16);
- sprintf(buf, "L%d", next++);
- return buf;
+ static char buf[16];
+ sprintf(buf, "__L%d", next++);
+ return ir_str(buf);
}
struct ref ref_reg(int reg) {