#include "from.h" #include "stmt.h" #include "cgen.h" #include "qbe.h" #include #include #include 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); }