aboutsummaryrefslogtreecommitdiff
path: root/ir.c
diff options
context:
space:
mode:
Diffstat (limited to 'ir.c')
-rw-r--r--ir.c66
1 files changed, 51 insertions, 15 deletions
diff --git a/ir.c b/ir.c
index e3a3171..4dca5b0 100644
--- a/ir.c
+++ b/ir.c
@@ -60,8 +60,15 @@ const char* condcode_show(enum condcode condcode) {
}
}
-void ref_show(struct ref ref, char *dest) {
+const char* ref_show(struct ref ref) {
static const char *special[8] = {"A", "B", "C", "D", "X", "Y", "SP", "BP"};
+ static char *buffer = NULL;
+ static int buffer_size = 0;
+
+ if (buffer == NULL) {
+ buffer_size = 40; // enough for all non-name refs
+ buffer = malloc(buffer_size + 1);
+ }
const char *suffix = NULL;
if (ref.type == REF_MEM) {
@@ -74,48 +81,70 @@ void ref_show(struct ref ref, char *dest) {
switch (ref.type) {
case REF_REG:
if (ref.reg == REG_UNUSED) {
- strcpy(dest, "<<UNUSED?>>");
+ strcpy(buffer, "<<UNUSED?>>");
} else if (ref.reg < 0) {
- strcpy(dest, special[-(ref.reg - REG_A)]);
+ strcpy(buffer, special[-(ref.reg - REG_A)]);
} else {
- sprintf(dest, "t%d", ref.reg);
+ sprintf(buffer, "t%d", ref.reg);
}
break;
case REF_MEM:
if (ref.reg == REG_UNUSED) {
- sprintf(dest, "[0x%x%s]", ref.offset, suffix);
+ sprintf(buffer, "[0x%x%s]", ref.offset, suffix);
} else if (ref.reg < 0) {
if (ref.offset < 0) {
- sprintf(dest, "[%s - %d%s]", special[-(ref.reg - REG_A)], -ref.offset, suffix);
+ sprintf(buffer, "[%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);
+ sprintf(buffer, "[%s + %d%s]", special[-(ref.reg - REG_A)], ref.offset, suffix);
}
} else {
if (ref.offset < 0) {
- sprintf(dest, "[t%d - %d%s]", ref.reg, -ref.offset, suffix);
+ sprintf(buffer, "[t%d - %d%s]", ref.reg, -ref.offset, suffix);
} else {
- sprintf(dest, "[t%d + %d%s]", ref.reg, ref.offset, suffix);
+ sprintf(buffer, "[t%d + %d%s]", ref.reg, ref.offset, suffix);
}
}
break;
case REF_IMM:
- sprintf(dest, "%d", ref.imm);
+ sprintf(buffer, "%d", ref.imm);
+ break;
+
+ case REF_VARNAME: {
+ int namelen = strlen(ref.name);
+ if (buffer_size < 1 + namelen) {
+ buffer_size = 1 + namelen;
+ buffer = realloc(buffer, 1 + namelen + 1);
+ }
+ buffer[0] = '@';
+ memcpy(buffer + 1, ref.name, namelen + 1);
break;
+ }
default:
assert(false);
}
+
+ return buffer;
}
static const char* ref_show_c(struct ref ref) {
- static char cbuf[3][40];
+ static char *cbuf[3] = {NULL, NULL, NULL};
+ static int cbufsize[3] = {-1, -1, -1};
static int cbufi = 0;
+ const char *sbuf = ref_show(ref);
+ int len = strlen(sbuf);
+ if (cbufsize[cbufi] < len) {
+ cbufsize[cbufi] = len;
+ if (cbuf[cbufi]) cbuf[cbufi] = realloc(cbuf[cbufi], len + 1);
+ else cbuf[cbufi] = malloc(len + 1);
+ }
+ memcpy(cbuf[cbufi], sbuf, len + 1);
+
char *buf = cbuf[cbufi];
cbufi = (cbufi + 1) % 3;
- ref_show(ref, buf);
return buf;
}
@@ -141,6 +170,7 @@ void irins_print(struct irins *ins, FILE *f) {
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;
+ case INS_HWI: fprintf(f, "\thwi %s\n", ref_show_c(ins->r1)); break;
default: assert(false);
}
}
@@ -245,6 +275,7 @@ void irins_which_refs(const struct irins *ins, bool have[3]) {
case INS_RETV: have[1] = true; break;
case INS_MOV: have[0] = true; have[1] = true; break;
case INS_BRK: break;
+ case INS_HWI: have[1] = true; break;
default: assert(false);
}
}
@@ -257,15 +288,19 @@ const char* gen_label_name(void) {
}
struct ref ref_reg(int reg) {
- return (struct ref){REF_REG, reg, 0, REFREL_ZERO, 0};
+ return (struct ref){REF_REG, reg, 0, REFREL_ZERO, 0, NULL};
}
struct ref ref_mem(int reg, int offset, enum refrel rel) {
- return (struct ref){REF_MEM, reg, offset, rel, 0};
+ return (struct ref){REF_MEM, reg, offset, rel, 0, NULL};
}
struct ref ref_imm(int imm) {
- return (struct ref){REF_IMM, REG_UNUSED, 0, REFREL_ZERO, imm};
+ return (struct ref){REF_IMM, REG_UNUSED, 0, REFREL_ZERO, imm, NULL};
+}
+
+struct ref ref_varname(const char *name) {
+ return (struct ref){REF_VARNAME, REG_UNUSED, 0, REFREL_ZERO, 0, ir_str(name)};
}
struct ref ref_next_register(void) {
@@ -279,6 +314,7 @@ bool ref_equal(struct ref r1, struct ref r2) {
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;
+ case REF_VARNAME: return strcmp(r1.name, r2.name) == 0;
default: assert(false);
}
}