summaryrefslogtreecommitdiff
path: root/set.c
diff options
context:
space:
mode:
authorXavier Del Campo Romero <xavi92@disroot.org>2026-05-09 02:56:07 +0200
committerXavier Del Campo Romero <xavi92@disroot.org>2026-05-17 11:13:23 +0200
commit527c23b73c8dae16f02cca6f450edb7d8225f60f (patch)
tree6b2bfd9e8d814026d6d2c1839d8cfe1bcadc825c /set.c
downloadslcob-master.tar.gz
Add project skeletonHEADmaster
Diffstat (limited to 'set.c')
-rw-r--r--set.c447
1 files changed, 447 insertions, 0 deletions
diff --git a/set.c b/set.c
new file mode 100644
index 0000000..389da7a
--- /dev/null
+++ b/set.c
@@ -0,0 +1,447 @@
+#include "set.h"
+#include "cgen.h"
+#include "errloc.h"
+#include "fn.h"
+#include "lex.h"
+#include "parse.h"
+#include "prv.h"
+#include "stmt.h"
+#include "storage.h"
+#include "type.h"
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+static int mv(const struct lex *l, struct prv *p);
+static int maddr(const struct lex *l, struct prv *p);
+static int msz(const struct lex *l, struct prv *p);
+static int mimb(const struct lex *l, struct prv *p);
+
+static const struct seq seqs[] =
+{
+ /* size of elementary data types */
+ {(const struct step[]){
+ {ID, NULL, 1},
+ {ID, "to"},
+ {ID, "size"},
+ {ID, "of"},
+ {ID, "void"},
+ {0}}, .fn = msz},
+ {(const struct step[]){
+ {ID, NULL, 1},
+ {ID, "to"},
+ {ID, "size"},
+ {ID, "of"},
+ {ID, "byte"},
+ {0}}, .fn = msz},
+ {(const struct step[]){
+ {ID, NULL, 1},
+ {ID, "to"},
+ {ID, "size"},
+ {ID, "of"},
+ {ID, "halfword"},
+ {0}}, .fn = msz},
+ {(const struct step[]){
+ {ID, NULL, 1},
+ {ID, "to"},
+ {ID, "size"},
+ {ID, "of"},
+ {ID, "word"},
+ {0}}, .fn = msz},
+ {(const struct step[]){
+ {ID, NULL, 1},
+ {ID, "to"},
+ {ID, "size"},
+ {ID, "of"},
+ {ID, "long"},
+ {0}}, .fn = msz},
+ {(const struct step[]){
+ {ID, NULL, 1},
+ {ID, "to"},
+ {ID, "size"},
+ {ID, "of"},
+ {ID, "ubyte"},
+ {0}}, .fn = msz},
+ {(const struct step[]){
+ {ID, NULL, 1},
+ {ID, "to"},
+ {ID, "size"},
+ {ID, "of"},
+ {ID, "uhalfword"},
+ {0}}, .fn = msz},
+ {(const struct step[]){
+ {ID, NULL, 1},
+ {ID, "to"},
+ {ID, "size"},
+ {ID, "of"},
+ {ID, "uword"},
+ {0}}, .fn = msz},
+ {(const struct step[]){
+ {ID, NULL, 1},
+ {ID, "to"},
+ {ID, "size"},
+ {ID, "of"},
+ {ID, "ulong"},
+ {0}}, .fn = msz},
+
+ /* address of variable */
+ {(const struct step[]){
+ {ID, NULL, 1},
+ {ID, "to"},
+ {ID, "address"},
+ {ID, "of"},
+ {ID},
+ {0}}, .fn = maddr},
+
+ /* size of variable or type alias */
+ {(const struct step[]){
+ {ID, NULL, 1},
+ {ID, "to"},
+ {ID, "size"},
+ {ID, "of"},
+ {ANY},
+ {0}}, .fn = msz},
+
+ /* array index or aggregate member */
+ {(const struct step[]){
+ {ID, NULL, 1},
+ {ID, "to"},
+ {ANY},
+ {ID, "of"},
+ {ID},
+ {0}}, .fn = mimb},
+
+ /* simple set */
+ {(const struct step[]){{ID, NULL, 1}, {ID, "to"}, {ANY}, {0}}, .fn = mv},
+ {0}
+};
+
+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 dst(const struct lex *l, const struct tk *tk, struct set *mv,
+ struct prv *p)
+{
+ const struct stentry *e = fn_var(fn_cur(p), tk);
+ size_t n = mv->ndsts + 1;
+ struct setdst *dsts;
+
+ if (!e)
+ return -1;
+ else if (!(dsts = realloc(mv->dsts, n * sizeof *dsts)))
+ {
+ perror("realloc(3)");
+ return -1;
+ }
+
+ mv->dsts = dsts;
+ mv->dsts[mv->ndsts++] = (struct setdst){.entry = e};
+ return 0;
+}
+
+static int mv(const struct lex *l, struct prv *p)
+{
+ const struct tk *tk = p->stk;
+ const struct stentry *e;
+ struct stmt *stmt = stmt_cur(p);
+ struct set *mv = &stmt->u.set;
+
+ while (!lex_eof(l, tk) && !kw((tk)->s))
+ if (dst(l, tk++, mv, p))
+ return -1;
+
+ /* skip "to" */
+ tk++;
+
+ fputs("\t\tadding set ", stderr);
+
+ for (size_t i = 0; i < mv->ndsts; i++)
+ fprintf(stderr, "%s ", mv->dsts[i].entry->tk->s);
+
+ if (tk->type == LIT)
+ {
+ /* this can only be applied to arrays of/pointers to chars */
+ fprintf(stderr, "%s: TODO\n", __func__);
+ return -1;
+ }
+ else if (tk->type == NUM)
+ {
+ mv->type = MV_VAL;
+ mv->srcv = tonum(tk->s);
+ }
+ else if (tk->type == ID)
+ {
+ const struct fn *fn = fn_cur(p);
+ const struct type *t = type_find(fn, tk->s);
+
+ if (t)
+ {
+ if (t->type != C)
+ {
+ errloc(tk, "type \"%s\" not a constant", tk->s);
+ return -1;
+ }
+
+ mv->type = MV_VAL;
+ mv->srcv = t->u.c.v;
+ }
+ else if ((e = fn_var(fn_cur(p), tk)))
+ {
+ mv->type = MV_ADDR;
+ mv->src = e;
+ }
+ else
+ {
+ errloc(tk, "undefined reference to \"%s\"", tk->s);
+ return -1;
+ }
+ }
+
+ fprintf(stderr, "to %s\n", tk->s);
+
+ if (pop(l, p))
+ return -1;
+
+ p->stk = ++tk;
+ return 1;
+}
+
+static int maddr(const struct lex *l, struct prv *p)
+{
+ const struct tk *tk = p->stk;
+ struct stmt *stmt = stmt_cur(p);
+ struct set *mv = &stmt->u.set;
+ const struct stentry *e;
+
+ while (!lex_eof(l, tk) && !kw((tk)->s))
+ if (dst(l, tk++, mv, p))
+ return -1;
+
+ /* skip "to address of" */
+ tk += 3;
+
+ if (!(e = fn_var(fn_cur(p), tk)))
+ {
+ errloc(tk, "undefined reference to \"%s\"", tk->s);
+ return -1;
+ }
+ else if (pop(l, p))
+ return -1;
+
+ mv->type = MV_ADDR;
+ mv->src = e;
+ p->stk = ++tk;
+ fputs("\t\tadding set ", stderr);
+
+ for (size_t i = 0; i < mv->ndsts; i++)
+ fprintf(stderr, "%s ", mv->dsts[i].entry->tk->s);
+
+ fprintf(stderr, "to address of %s\n", mv->src->tk->s);
+ return 1;
+}
+
+static int msz(const struct lex *l, struct prv *p)
+{
+ const struct tk *tk = p->stk;
+ const struct stentry *e;
+ struct stmt *stmt = stmt_cur(p);
+ struct set *mv = &stmt->u.set;
+ const struct fn *fn = fn_cur(p);
+ const struct type *t;
+
+ while (!lex_eof(l, tk) && !kw((tk)->s))
+ if (dst(l, tk++, mv, p))
+ return -1;
+
+ /* skip "to size of" */
+ tk += 3;
+
+ if (tk->type == NUM)
+ {
+ errloc(tk, "cannot compute size of a number");
+ return -1;
+ }
+ else if (tk->type == LIT)
+ mv->srcv = strlen(tk->s) + 1;
+ else if ((t = type_find(fn, tk->s)))
+ {
+ if (!t->sz)
+ {
+ errloc(tk, "type \"%s\" has no size", tk->s);
+ return-1;
+ }
+
+ mv->srcv = t->sz;
+ }
+ else if ((e = fn_var(fn, tk)))
+ mv->srcv = e->t->sz;
+ else
+ return-1;
+
+ if (pop(l, p))
+ return -1;
+
+ mv->type = MV_VAL;
+ p->stk = ++tk;
+ fputs("\t\tadding set ", stderr);
+
+ for (size_t i = 0; i < mv->ndsts; i++)
+ fprintf(stderr, "%s ", mv->dsts[i].entry->tk->s);
+
+ fprintf(stderr, "size=%llu\n", mv->srcv);
+ return 1;
+}
+
+static int mimb(const struct lex *l, struct prv *p)
+{
+ const struct tk *tk = p->stk;
+ const struct fn *fn = fn_cur(p);
+ struct stmt *stmt = stmt_cur(p);
+ struct set *mv = &stmt->u.set;
+ while (!lex_eof(l, tk) && !kw((tk)->s))
+ if (dst(l, tk++, mv, p))
+ return -1;
+
+ /* skip "to" */
+ tk++;
+
+ fputs("\t\tadding set ", stderr);
+
+ for (size_t i = 0; i < mv->ndsts; i++)
+ fprintf(stderr, "%s ", mv->dsts[i].entry->tk->s);
+
+ if (tk->type == LIT)
+ {
+ errloc(tk, "unexpected literal \"%s\"", tk->s);
+ return -1;
+ }
+ else if (tk->type == ID && !(mv->off = fn_var(fn, tk)))
+ {
+ errloc(tk, "undefined reference to \"%s\"", tk->s);
+ return -1;
+ }
+ else if (tk->type == NUM)
+ mv->srcv = tonum(tk->s);
+
+ fprintf(stderr, "to [%s] ", tk->s);
+
+ /* skip index and "of" */
+ tk += 2;
+
+ if (!(mv->src = fn_var(fn, tk)))
+ {
+ errloc(tk, "undefined reference to \"%s\"", tk->s);
+ return -1;
+ }
+ else if (pop(l, p))
+ return -1;
+
+ fprintf(stderr, " of %s\n", tk->s);
+ mv->type = MV_IMB;
+ p->stk = ++tk;
+ return 1;
+}
+
+void set_free(struct set *m)
+{
+ if (m)
+ free(m->dsts);
+}
+
+static int cg_val(const struct set *m, const struct stentry *dst,
+ struct cgen *c)
+{
+ const char *name = dst->tk->s;
+ size_t sz = dst->t->sz;
+ const char *szstr = cgen_sz(sz);
+ const struct pr *pr = c->fn->pr;
+ const struct param *ret = pr->ret;
+
+ if (ret && dst == ret->entry)
+ printf("%%__ret =%s add %llu, 0", cgen_abity(ret->entry->t), m->srcv);
+ else if (cgen_global(c->fn, dst))
+ printf("store%s %llu, $%s", szstr, m->srcv, name);
+ else
+ printf("%%%s_ =%s add %llu, 0", name, cgen_abity(dst->t), m->srcv);
+
+ putchar('\n');
+ return 0;
+}
+
+int set_cgen(const struct set *m, struct cgen *c)
+{
+ for (size_t i = 0; i < m->ndsts; i++)
+ {
+ const struct stentry *dst = m->dsts[i].entry;
+
+ switch (m->type)
+ {
+ case MV_VAL:
+ if (cg_val(m, dst, c))
+ return -1;
+
+ break;
+
+ case MV_ADDR:
+ case MV_VAR:
+ case MV_IMB:
+ fprintf(stderr, "%s: TODO\n", __func__);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+int set(const struct lex *l, struct prv *p)
+{
+ const struct tk *next = p->tk;
+ const char *ns = next->s;
+ struct fn *fn = fn_cur(p);
+ size_t n = fn->nstmts + 1;
+ struct stmt *stmts;
+
+ if (lex_eof(l, next))
+ {
+ errloc(next - 1, "incomplete set statement");
+ return -1;
+ }
+ else if (kw(ns))
+ {
+ errloc(next, "incomplete set statement");
+ return -1;
+ }
+ else if (!(stmts = realloc(fn->stmts, n * sizeof *stmts)))
+ {
+ perror("realloc(3)");
+ return -1;
+ }
+
+ fn->stmts = stmts;
+ fn->stmts[fn->nstmts++] = (struct stmt){.type = SET};
+
+ struct pos init =
+ {
+ .seq = seqs,
+ .stseq = seqs,
+ .step = seqs->steps
+ };
+
+ if (push(&init, p))
+ return -1;
+
+ p->stk = p->tk;
+ return 1;
+}