From 3272b5d83d2e2167eed24748557df88bd66584ee Mon Sep 17 00:00:00 2001 From: tomsmeding Date: Fri, 5 Jan 2018 23:42:24 +0100 Subject: There's actually a chance that, correctly stringified, this will work --- ir.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 67 insertions(+), 12 deletions(-) (limited to 'ir.c') diff --git a/ir.c b/ir.c index cf529dd..69a9d64 100644 --- a/ir.c +++ b/ir.c @@ -1,8 +1,29 @@ #include +#include #include #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) { -- cgit v1.2.3-54-g00ecf