aboutsummaryrefslogtreecommitdiff
path: root/src/prc1/cgen/qbe/from.c
diff options
context:
space:
mode:
authorXavier Del Campo Romero <xavi92@disroot.org>2026-10-11 01:26:41 +0200
committerXavier Del Campo Romero <xavi92@disroot.org>2026-10-20 01:03:47 +0200
commitcab0135f57ca1c7e448e11f866b0adb8a1328d48 (patch)
treefcc24dc0b2d350524c33f07dc8b71f491431e832 /src/prc1/cgen/qbe/from.c
parent4ce39e4fc1de9536de7dedfe91b6dee38dec76ae (diff)
downloadprc-master.tar.gz
WIP tripletHEADmaster
Diffstat (limited to 'src/prc1/cgen/qbe/from.c')
-rw-r--r--src/prc1/cgen/qbe/from.c134
1 files changed, 134 insertions, 0 deletions
diff --git a/src/prc1/cgen/qbe/from.c b/src/prc1/cgen/qbe/from.c
new file mode 100644
index 0000000..40b2724
--- /dev/null
+++ b/src/prc1/cgen/qbe/from.c
@@ -0,0 +1,134 @@
+#include "from.h"
+#include "stmt.h"
+#include "cgen.h"
+#include "qbe.h"
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+static int loadvar(const struct from_it *st, struct cgen *c)
+{
+ const struct stentry *e = st->u.e;
+ size_t sz = e->t->sz;
+ const char *tmp = cgen_tmp(sz);
+
+ printf("%%%s =%s load%s ", tmp, cgen_sz(sz), cgen_load(e->t));
+ cgen_printvar(c->fn, e);
+ putchar('\n');
+ return 0;
+}
+
+/* TODO: de-duplicate function */
+static unsigned long long tonum(const char *s)
+{
+ unsigned long long v;
+ char *end;
+
+ errno = 0;
+ v = strtoull(s, &end, 0);
+
+ if (*s == '-' || errno || *end)
+ return strtoll(s, NULL, 0);
+
+ return v;
+}
+
+static int loadval(const struct from *fr, struct cgen *c)
+{
+ const struct stentry *dst = fr->var;
+ const struct from_it *st = &fr->start;
+ unsigned long long v = tonum(st->u.tk->s);
+
+ printf("store%s %llu, ", cgen_sz(dst->t->sz), v);
+ cgen_printvar(c->fn, dst);
+ putchar('\n');
+ return 0;
+}
+
+static int endvar(const struct from *fr, struct cgen *c)
+{
+ fprintf(stderr, "%s: TODO\n", __func__);
+ return -1;
+}
+
+static int endval(const struct from *fr, struct cgen *c)
+{
+ const struct stentry *src = fr->var;
+ size_t sz = src->t->sz;
+ const char *tmp = cgen_tmp(sz);
+ const struct from_it *end = &fr->end;
+ const struct tk *tk = end->u.tk;
+ int neg = *tk->s == '-';
+ size_t bl = fr->block_i;
+
+ printf("%%%s =%s load%s ", tmp, cgen_sz(sz), cgen_load(src->t));
+ cgen_printvar(c->fn, src);
+ putchar('\n');
+ printf("%%%s =%s c", tmp, cgen_sz(sz));
+ fputs(neg ? "sge" : "uge", stdout);
+ printf("%s ", cgen_sz(sz));
+ printf("%%%s, %s\n", tmp, tk->s);
+ printf("jnz %%%s, @__end%zu, @__blockbody%zu\n", tmp, bl, bl);
+ printf("@__blockbody%zu\n", bl);
+ return 0;
+}
+
+static int from_var(const struct from *fr, struct cgen *c)
+{
+ const struct from_it *st = &fr->start;
+
+ switch (st->type)
+ {
+ case FR_VAR:
+ if (loadvar(st, c))
+ return -1;
+ break;
+
+ case FR_VAL:
+ if (loadval(fr, c))
+ return -1;
+ break;
+ }
+
+ printf("@__block%zu\n", fr->block_i);
+
+ switch (fr->end.type)
+ {
+ case FR_VAR:
+ if (endvar(fr, c))
+ return -1;
+ break;
+
+ case FR_VAL:
+ if (endval(fr, c))
+ return -1;
+ break;
+ }
+
+ return 0;
+}
+
+int from_end(const struct stmt *s, struct cgen *c)
+{
+ const struct from *fr = &s->u.from;
+ const struct stentry *src = fr->var;
+ const struct type *t = src->t;
+ size_t sz = t->sz;
+ const char *tmp = cgen_tmp(sz);
+ const struct fn *fn = c->fn;
+
+ printf("%%%s =%s load%s ", tmp, cgen_sz(sz), cgen_load(t));
+ cgen_printvar(fn, src);
+ putchar('\n');
+ printf("%%%s =%s add %%%s, 1\n", tmp, cgen_sz(sz), tmp);
+ printf("store%s %%%s, ", cgen_sz(sz), tmp);
+ cgen_printvar(fn, src);
+ putchar('\n');
+ printf("jmp @__block%zu\n", fr->block_i);
+ return 0;
+}
+
+int qbe_from(const struct from *fr, struct cgen *c)
+{
+ return from_var(fr, c);
+}