aboutsummaryrefslogtreecommitdiff
path: root/src/prc1/cgen/qbe
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
parent4ce39e4fc1de9536de7dedfe91b6dee38dec76ae (diff)
downloadprc-master.tar.gz
WIP tripletHEADmaster
Diffstat (limited to 'src/prc1/cgen/qbe')
-rw-r--r--src/prc1/cgen/qbe/CMakeLists.txt1
-rw-r--r--src/prc1/cgen/qbe/from.c134
-rw-r--r--src/prc1/cgen/qbe/qbe.c1
-rw-r--r--src/prc1/cgen/qbe/qbe.h2
4 files changed, 138 insertions, 0 deletions
diff --git a/src/prc1/cgen/qbe/CMakeLists.txt b/src/prc1/cgen/qbe/CMakeLists.txt
index 5d0bd63..a9e7155 100644
--- a/src/prc1/cgen/qbe/CMakeLists.txt
+++ b/src/prc1/cgen/qbe/CMakeLists.txt
@@ -1,6 +1,7 @@
target_sources(prc1 PRIVATE
call.c
free.c
+ from.c
fn.c
gl.c
print.c
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);
+}
diff --git a/src/prc1/cgen/qbe/qbe.c b/src/prc1/cgen/qbe/qbe.c
index c27bad6..d727bc0 100644
--- a/src/prc1/cgen/qbe/qbe.c
+++ b/src/prc1/cgen/qbe/qbe.c
@@ -154,6 +154,7 @@ int cgen_qbe(const struct ast *ast, struct cgen *c)
.print = qbe_print,
.call = qbe_call,
.free = qbe_free,
+ .from = qbe_from,
.set = qbe_set,
.gl = qbe_gl,
.ws = qbe_ws,
diff --git a/src/prc1/cgen/qbe/qbe.h b/src/prc1/cgen/qbe/qbe.h
index b0e66f1..206cf32 100644
--- a/src/prc1/cgen/qbe/qbe.h
+++ b/src/prc1/cgen/qbe/qbe.h
@@ -3,6 +3,7 @@
#include "call.h"
#include "cgen.h"
+#include "from.h"
#include "print.h"
#include "set.h"
#include "storage.h"
@@ -20,6 +21,7 @@ int qbe_call(const struct call *m, struct cgen *c);
int qbe_set(const struct set *m, struct cgen *c);
int qbe_gl(const struct storage *gl, struct cgen *c);
int qbe_ws(const struct storage *s, struct cgen *c);
+int qbe_from(const struct from *fn, struct cgen *c);
int qbe_fn(const struct fn *fn, struct cgen *c);
void qbe_free(struct cgen_prv *p);