aboutsummaryrefslogtreecommitdiff
path: root/src/prc1
diff options
context:
space:
mode:
authorXavier Del Campo Romero <xavi92@disroot.org>2026-10-01 01:04:30 +0200
committerXavier Del Campo Romero <xavi92@disroot.org>2026-10-11 00:14:35 +0200
commit4ce39e4fc1de9536de7dedfe91b6dee38dec76ae (patch)
treef9820f96b8eab624430c3700f32a2878a7036ee2 /src/prc1
parent9140988be4e5bb028b7140aca1a67af1370c72a7 (diff)
downloadprc-4ce39e4fc1de9536de7dedfe91b6dee38dec76ae.tar.gz
WIP sym + cgen
Diffstat (limited to 'src/prc1')
-rw-r--r--src/prc1/CMakeLists.txt4
-rw-r--r--src/prc1/arg.c17
-rw-r--r--src/prc1/arg.h1
-rw-r--r--src/prc1/call.c486
-rw-r--r--src/prc1/call.h15
-rw-r--r--src/prc1/cgen.c195
-rw-r--r--src/prc1/cgen.h9
-rw-r--r--src/prc1/cgen/CMakeLists.txt12
-rw-r--r--src/prc1/cgen/call.c8
-rw-r--r--src/prc1/cgen/fn.c8
-rw-r--r--src/prc1/cgen/free.c8
-rw-r--r--src/prc1/cgen/gl.c8
-rw-r--r--src/prc1/cgen/global.c32
-rw-r--r--src/prc1/cgen/param.c15
-rw-r--r--src/prc1/cgen/print.c8
-rw-r--r--src/prc1/cgen/prv.h23
-rw-r--r--src/prc1/cgen/qbe/CMakeLists.txt10
-rw-r--r--src/prc1/cgen/qbe/call.c163
-rw-r--r--src/prc1/cgen/qbe/fn.c94
-rw-r--r--src/prc1/cgen/qbe/free.c7
-rw-r--r--src/prc1/cgen/qbe/gl.c16
-rw-r--r--src/prc1/cgen/qbe/print.c95
-rw-r--r--src/prc1/cgen/qbe/qbe.c187
-rw-r--r--src/prc1/cgen/qbe/qbe.h26
-rw-r--r--src/prc1/cgen/qbe/set.c11
-rw-r--r--src/prc1/cgen/qbe/ws.c23
-rw-r--r--src/prc1/cgen/set.c8
-rw-r--r--src/prc1/cgen/ws.c8
-rw-r--r--src/prc1/dbg.c14
-rw-r--r--src/prc1/dbg.h1
-rw-r--r--src/prc1/display.c135
-rw-r--r--src/prc1/display.h9
-rw-r--r--src/prc1/div.c33
-rw-r--r--src/prc1/end.c4
-rw-r--r--src/prc1/fn.c115
-rw-r--r--src/prc1/fn.h2
-rw-r--r--src/prc1/from.c8
-rw-r--r--src/prc1/gl.c12
-rw-r--r--src/prc1/im.c144
-rw-r--r--src/prc1/kw.c10
-rw-r--r--src/prc1/lex.c3
-rw-r--r--src/prc1/lex.h2
-rw-r--r--src/prc1/lit.c2
-rw-r--r--src/prc1/parse.c101
-rw-r--r--src/prc1/parse.h38
-rw-r--r--src/prc1/pop.c30
-rw-r--r--src/prc1/pr.c350
-rw-r--r--src/prc1/prc1.c9
-rw-r--r--src/prc1/print.c178
-rw-r--r--src/prc1/print.h25
-rw-r--r--src/prc1/prv.h9
-rw-r--r--src/prc1/push.c15
-rw-r--r--src/prc1/reset.c10
-rw-r--r--src/prc1/set.c131
-rw-r--r--src/prc1/set.h1
-rw-r--r--src/prc1/stmt.c22
-rw-r--r--src/prc1/stmt.h6
-rw-r--r--src/prc1/storage.c17
-rw-r--r--src/prc1/sym.c478
-rw-r--r--src/prc1/sym.h15
-rw-r--r--src/prc1/td.c178
-rw-r--r--src/prc1/tmp.c12
-rw-r--r--src/prc1/type.c115
-rw-r--r--src/prc1/type.h1
-rw-r--r--src/prc1/warn.c25
-rw-r--r--src/prc1/warn.h9
-rw-r--r--src/prc1/ws.c17
67 files changed, 2290 insertions, 1493 deletions
diff --git a/src/prc1/CMakeLists.txt b/src/prc1/CMakeLists.txt
index f5dfa86..82d670d 100644
--- a/src/prc1/CMakeLists.txt
+++ b/src/prc1/CMakeLists.txt
@@ -17,7 +17,9 @@ add_executable(prc1
lit.c
lk.c
prc1.c
+ reset.c
set.c
+ sym.c
parse.c
pop.c
pr.c
@@ -33,10 +35,12 @@ add_executable(prc1
ws.c
)
+target_include_directories(prc1 PRIVATE ${CMAKE_CURRENT_LIST_DIR})
target_compile_options(prc1 PRIVATE -g -Wall -pedantic)
set_target_properties(prc1 PROPERTIES C_STANDARD 99 C_EXTENSIONS OFF)
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
target_compile_options(prc1 PRIVATE -Og)
endif()
+add_subdirectory(cgen)
include(GNUInstallDirs)
install(TARGETS prc1 DESTINATION ${CMAKE_INSTALL_LIBEXECDIR}/${PROJECT_NAME})
diff --git a/src/prc1/arg.c b/src/prc1/arg.c
index f61bca7..f55d322 100644
--- a/src/prc1/arg.c
+++ b/src/prc1/arg.c
@@ -20,7 +20,20 @@ struct arg
static int debug(struct args *a, const char *arg)
{
- dbgen = 1;
+ dbgen++;
+ return 0;
+}
+
+static int target(struct args *a, const char *arg)
+{
+ if (!strcmp(arg, "qbe"))
+ a->tgt = QBE;
+ else
+ {
+ fprintf(stderr, "invalid or unsupported target \"%s\"", arg);
+ return -1;
+ }
+
return 0;
}
@@ -77,6 +90,7 @@ int arg(struct args *a, const char *value)
static const struct arg args[] =
{
{"-d", debug},
+ {"-t", target},
{"-I", inc, SPACEVAL | JOINVAL}
};
@@ -110,6 +124,7 @@ int arg(struct args *a, const char *value)
void arg_defaults(struct args *a)
{
+ a->tgt = QBE;
}
static void free_input(struct arg_input *i)
diff --git a/src/prc1/arg.h b/src/prc1/arg.h
index efa623f..0e9a7ab 100644
--- a/src/prc1/arg.h
+++ b/src/prc1/arg.h
@@ -11,6 +11,7 @@ struct arg_input
struct args
{
+ enum target {QBE} tgt;
const char *name, *src;
const struct arg *arg;
struct arg_input incs;
diff --git a/src/prc1/call.c b/src/prc1/call.c
index 21ef4de..f06f25b 100644
--- a/src/prc1/call.c
+++ b/src/prc1/call.c
@@ -5,263 +5,171 @@
#include "lex.h"
#include "lit.h"
#include "parse.h"
+#include "pr.h"
#include "prv.h"
#include "stmt.h"
+#include "sym.h"
#include "type.h"
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-static int callpr(const struct lex *l, struct prv *p);
-static int callp(const struct lex *l, struct prv *p);
-static int callr(const struct lex *l, struct prv *p);
-static int callv(const struct lex *l, struct prv *p);
+static int using(const struct lex *, struct prv *);
+static int s_returning(const struct lex *, struct prv *);
+
+static const struct seq returning =
+ {(struct step[]){{ID, "returning"}, {0}}, .fn = s_returning};
static const struct seq seqs[] =
{
- {(struct step[]){
- {ID},
- {ID, "using"},
- {ANY, NULL, 1},
- {ID, "returning"},
- {ID},
- {0}}, .fn = callpr},
- {(struct step[]){
- {ID},
- {ID, "using"},
- {ANY, NULL, 1},
- {0}}, .fn = callp},
- {(struct step[]){
- {ID},
- {ID, "returning"},
- {ID},
- {0}}, .fn = callr},
- {(struct step[]){
- {ID},
- {0}}, .fn = callv},
+ {(struct step[]){{ID, "using"}, {0}}, .fn = using},
+ returning,
{0}
};
-static int param(const struct lex *l, struct prv *p, const struct tk *tk,
- struct call *c)
+static const struct seq useqs[] =
{
- const struct fn *fn = fn_cur(p);
+ returning,
+ {0}
+};
+
+static int param(const struct lex *l, struct prv *p, const struct sym *s)
+{
+ struct stmt *stmt = stmt_cur(p);
+ struct call *c = &stmt->u.call;
size_t n = c->nparams + 1;
- struct callparam *params;
- const struct lit *lit = NULL;
- const struct stentry *e = NULL;
- const struct type *t = NULL;
- int sign = 0;
- union callv u = {0};
-
- if (tk->type == LIT)
- {
- if (!(lit = lit_push(tk, p)))
- return -1;
- }
- else if (tk->type == NUM)
- {
- if ((sign = *tk->s == '-'))
- u.v = strtoll(tk->s, NULL, 0);
- else
- u.uv = strtoull(tk->s, NULL, 0);
- }
- else if ((t = type_find(fn, tk->s)))
- {
- if (t->type != C)
- {
- errloc(tk, "type \"%s\" not a constant", tk->s);
- return -1;
- }
- }
- else if (!(e = fn_var(fn, tk)))
- {
- errloc(tk, "undefined reference to parameter \"%s\"", tk->s);
- return -1;
- }
+ struct callparam *params = realloc(c->params, n * sizeof *params);
- if (!(params = realloc(c->params, n * sizeof *params)))
+ if (!params)
{
perror("realloc(3)");
return -1;
}
+ params[c->nparams++] = (struct callparam){.s = s};
c->params = params;
- c->params[c->nparams++] = (struct callparam)
- {
- .entry = e,
- .lit = lit,
- .t = t,
- .u = u
- };
-
return 0;
}
-static int callpr(const struct lex *l, struct prv *p)
+static int using(const struct lex *l, struct prv *p)
{
- const struct tk *tk = p->stk + 2;
- struct call *c = &stmt_cur(p)->u.call;
- const struct pr *pr = c->pr;
- const struct stentry *e;
- size_t n = 0;
+ struct pos init =
+ {
+ .name = __func__,
+ .seq = useqs
+ };
- while (!lex_eof(l, tk) && !kw((tk++)->s))
- n++;
+ struct stmt *stmt = stmt_cur(p);
+ struct call *c = &stmt->u.call;
+ const struct tk *tk = c->pr->tk, *u = c->using;
- if (pr->variadic)
+ if (u)
{
- if (n < pr->nparams)
- {
- errloc(tk, "function \"%s\" expects at least %zu parameters, "
- "but %zu were given", c->tk->s, pr->nparams, n);
- return -1;
- }
- }
- else if (n != pr->nparams)
- {
- tk -= 2;
- errloc(tk, "function \"%s\" expects %zu parameters, "
- "but %zu were given", c->tk->s, pr->nparams, n);
- return -1;
- }
+ const struct loc *loc = &u->loc;
- if (!pr->ret)
- {
- errloc(tk, "function \"%s\" does not expect any return variable",
- c->tk->s);
+ errloc(p->stk, "\"using\" for \"%s\" already set at %d:%d", tk->s,
+ loc->line, loc->col);
return -1;
}
+ else if (push(&init, p))
+ return -1;
- tk = p->stk + 2;
+ c->using = p->stk;
+ return sym(p, param);
+}
- for (size_t i = 0; i < n; i++)
- if (param(l, p, tk++, c))
- return -1;
+static int setret(const struct lex *l, struct prv *p, const struct sym *s)
+{
+ struct stmt *stmt = stmt_cur(p);
+ struct call *c = &stmt->u.call;
- if (!(e = fn_var(fn_cur(p), ++tk)))
+ c->ret = s;
+ return pop(l, p);
+}
+
+static int s_returning(const struct lex *l, struct prv *p)
+{
+ struct pos init =
{
- errloc(tk, "undefined reference to return variable \"%s\"",
- tk->s);
+ .name = __func__,
+ .seq = useqs
+ };
+
+ struct stmt *stmt = stmt_cur(p);
+ struct call *c = &stmt->u.call;
+ const struct tk *tk = c->pr->tk, *r = c->returning;
+
+ if (r)
+ {
+ const struct loc *loc = &r->loc;
+
+ errloc(p->stk, "\"returning\" for \"%s\" already set at %d:%d",
+ tk->s, loc->line, loc->col);
return -1;
}
- else if (pop(l, p))
+
+ if (push(&init, p))
return -1;
- dbg("\t\tadding call to %s using %zu params and %s as return variable\n",
- c->tk->s, n, tk->s);
- c->ret = e;
- c->nparams = n;
- p->stk = ++tk;
- return 1;
+ c->returning = p->stk;
+ return sym(p, setret);
}
-static int callr(const struct lex *l, struct prv *p)
+static int endcall(const struct lex *l, struct prv *p)
{
- const struct tk *tk = p->stk + 2;
- const struct fn *fn = fn_cur(p);
- const struct stentry *e;
- struct call *c = &stmt_cur(p)->u.call;
+ const struct stmt *stmt = stmt_cur(p);
+ const struct call *c = &stmt->u.call;
const struct pr *pr = c->pr;
+ const struct tk *tk = c->id->tk;
+ size_t n = c->nparams;
- if (!pr->ret)
+ if (!pr)
{
- errloc(tk, "function \"%s\" does not expect any return variable",
- c->tk->s);
+ errloc(p->stk - 1, "incomplete \"call\" statement");
return -1;
}
- else if (pr->nparams)
+ else if (c->using && !n)
{
- errloc(tk, "function \"%s\" expects %zu parameters, "
- "but none were given", c->tk->s, pr->nparams);
+ errloc(c->using, "\"using\" without arguments");
return -1;
}
- else if (!(e = fn_var(fn, tk)))
+ else if (c->returning && !c->ret)
{
- errloc(tk, "undefined reference to return variable \"%s\"", tk->s);
+ errloc(c->using, "\"returning\" without return variable");
return -1;
}
- else if (pop(l, p))
- return -1;
-
- dbg("\t\tadding call to %s with %s as return variable\n", c->tk->s, tk->s);
- c->ret = e;
- p->stk = ++tk;
- return 1;
-}
-
-static int callp(const struct lex *l, struct prv *p)
-{
- const struct tk *tk = p->stk + 2;
- struct call *c = &stmt_cur(p)->u.call;
- const struct pr *pr = c->pr;
- size_t n = 0;
-
- while (!lex_eof(l, tk) && !kw((tk++)->s))
- n++;
-
- if (lex_eof(l, tk))
- tk--;
-
- if (pr->variadic)
+ else if (pr->variadic)
{
if (n < pr->nparams)
{
- errloc(tk, "function \"%s\" expects at least %zu parameters, "
- "but %zu were given", c->tk->s, pr->nparams, n);
+ errloc(tk, "\"%s\" expects at least %zu parameters, "
+ "but %zu were given", tk->s, pr->nparams, n);
return -1;
}
}
- else if (pr->nparams != n)
+ else if (n != pr->nparams)
{
- errloc(tk, "function \"%s\" expects %zu parameters, "
- "but %zu were given", c->tk->s, pr->nparams, n);
+ errloc(tk, "\"%s\" expects %zu parameters, but %zu were given",
+ tk->s, pr->nparams, n);
return -1;
}
- tk = p->stk + 2;
-
- for (size_t i = 0; i < n; i++)
- if (param(l, p, tk++, c))
- return -1;
-
- if (pop(l, p))
- return -1;
-
- dbg("\t\tadding call to %s with 1 param\n", c->tk->s);
- p->stk = tk;
- return 1;
-}
-
-static int callv(const struct lex *l, struct prv *p)
-{
- const struct tk *tk = p->stk;
- struct call *c = &stmt_cur(p)->u.call;
- const struct pr *pr = c->pr;
-
- if (pr->nparams)
+ if (!pr->ret && c->ret)
{
- errloc(tk, "function \"%s\" expects %zu parameters, "
- "but none were given", c->tk->s, pr->nparams);
+ errloc(tk, "function \"%s\" does not expect any return variable",
+ tk->s);
return -1;
}
- else if (pop(l, p))
- return -1;
- dbg("\t\tadding call to %s with %s as return variable\n", c->tk->s, tk->s);
- p->stk = ++tk;
- return 1;
+ fprintf(stderr, "%s: TODO\n", __func__);
+ return -1;
}
-static const struct pr *find_proto(const struct fn *fn, const char *s)
+void call_free(struct call *c)
{
- const struct type *t = type_find(fn, s);
-
- if (t && t->type == P)
- return t->u.p.fn->pr;
-
- return NULL;
+ if (c)
+ free(c->params);
}
static const struct pr *find(const struct ast *ast, const char *s)
@@ -269,219 +177,71 @@ static const struct pr *find(const struct ast *ast, const char *s)
for (size_t i = 0; i < ast->nfns; i++)
{
const struct fn *fn = &ast->fns[i];
- const struct pr *pr;
- if ((pr = find_proto(fn, s)))
- return pr;
- else if (!strcmp(fn->tk->s, s))
+ if (!strcmp(fn->tk->s, s))
return fn->pr;
}
return NULL;
}
-static int gettmp(char *tmp, size_t n)
-{
- size_t j;
-
- for (j = 0; j < n; j++)
- {
- char c = tmp[j];
-
- if (!c)
- return tmp[j] = 'a';
- else if (c != 'z')
- return ++(tmp[j]);
- }
-
- return EOF;
-}
-
-static int param_lit(const struct lit *lit, struct cgen *c)
-{
- printf("l $%s", lit->name);
- return 0;
-}
-
-static int param_id(const struct stentry *e, struct cgen *c, char *tmp,
- size_t n)
-{
- const char *name = e->tk->s;
- const struct type *t = e->t;
-
- printf("%s ", cgen_sz(t->sz));
-
- if (cgen_global(c->fn, e))
- printf("$%s", name);
- else if (cgen_abity(t))
- {
- if (gettmp(tmp, n) == EOF)
- return -1;
-
- printf("%%%s", tmp);
- }
- else
- printf("%%%s_", name);
-
- return 0;
-}
-
-static int param_c(const struct type *t, struct cgen *cg)
-{
- const union c *c = &t->u.c;
-
- /* TODO: adapt type to expected param size */
- fputs("l ", stdout);
-
- if (t->sign)
- printf("%lld", c->v);
- else
- printf("%llu", c->uv);
-
- return 0;
-}
-
-static int param_num(const struct callparam *cp, struct cgen *c)
-{
- const union callv *u = &cp->u;
-
- /* TODO: adapt type to expected param size */
- fputs("w ", stdout);
-
- if (cp->sign)
- printf("%lld", u->v);
- else
- printf("%llu", u->uv);
-
- return 0;
-}
-
-static int param_load(const struct call *m, struct cgen *c)
+static int onsym(const struct lex *l, struct prv *p, const struct sym *s)
{
- char tmp[sizeof "abcdefghijklmnopqrstuvwxyz"] = {0};
+ const struct fn *fn = fn_cur(p);
+ struct stmt *stmt = stmt_cur(p);
+ struct call *c = &stmt->u.call;
+ const struct tk *tk = s->tk;
+ const struct pr *pr = find(p->ast, tk->s);
+ const struct stentry *e;
- for (size_t i = 0; i < m->nparams; i++)
+ if (pr)
+ c->pr = pr;
+ else if (!(e = fn_var(fn, tk)))
{
- const struct callparam *cp = &m->params[i];
- const struct stentry *e = cp->entry;
-
- if (!e || cgen_global(c->fn, e) || !cgen_abity(e->t))
- continue;
- else if (gettmp(tmp, sizeof tmp - 1) == EOF)
- {
- fprintf(stderr, "%s: exhausted temporaries\n", __func__);
- return -1;
- }
-
- printf("%%%s =%s load%s %%%s_\n", tmp, cgen_sz(e->t->sz),
- cgen_load(e->t), e->tk->s);
- }
-
- return 0;
-}
-
-int call_cgen(const struct call *m, struct cgen *c)
-{
- char tmps[sizeof "abcdefghijklmnopqrstuvwxyz"] = {0};
- const struct stentry *ret = m->ret;
- const char *tmp;
- size_t sz;
-
- if (param_load(m, c))
+ errloc(tk, "undefined reference to \"%s\"", tk->s);
return -1;
- else if (ret)
- {
- tmp = cgen_tmp((sz = ret->t->sz));
- printf("%%%s =%s ", tmp, cgen_sz(sz));
}
-
- printf("call $%s(", m->tk->s);
-
- for (size_t i = 0; i < m->nparams; i++)
+ else if (e->t->type != P)
{
- const struct callparam *cp = &m->params[i];
- int var = m->pr->variadic;
-
- if (cp->lit)
- param_lit(cp->lit, c);
- else if (cp->entry)
- param_id(cp->entry, c, tmps, sizeof tmps - 1);
- else if (cp->t)
- param_c(cp->t, c);
- else
- param_num(cp, c);
-
- if (var && i + 1 == var - 1)
- fputs(", ...", stdout);
-
- if (i + 1 < m->nparams)
- fputs(", ", stdout);
- }
+ char *tn = type_name(e->t);
- puts(")");
+ if (tn)
+ errloc(tk, "cannot call \"%s\" with type \"%s\"", tk->s, tn);
- if (ret)
- {
- printf("store%s %%%s, ", cgen_sz(sz), tmp);
- cgen_printvar(c->fn, ret);
- putchar('\n');
+ free(tn);
+ return -1;
}
+ else
+ c->pr = e->t->u.p.fn->pr;
- return 0;
-}
-
-void call_free(struct call *c)
-{
- if (c)
- free(c->params);
+ c->id = s;
+ return pop(l, p);
}
int call(const struct lex *l, struct prv *p)
{
- const struct tk *tk = p->tk;
- const struct pr *pr;
- struct fn *fn = fn_cur(p);
- size_t n = fn->nstmts +1;
- struct stmt *stmts;
struct pos init =
{
+ .name = __func__,
.seq = seqs,
- .stseq = seqs,
- .step = seqs->steps
+ .end = endcall,
};
- /* TODO: function pointers */
+ struct fn *fn = fn_cur(p);
+ size_t n = fn->nstmts + 1;
+ struct stmt *stmts = realloc(fn->stmts, n * sizeof *stmts);
- if (lex_eof(l, tk))
- {
- errloc(tk - 1, "incomplete call statement");
- return -1;
- }
- else if (!(pr = find(p->ast, tk->s)))
- {
- errloc(tk, "undefined reference to function \"%s\"", tk->s);
- return -1;
- }
- else if (!(stmts = realloc(fn->stmts, n * sizeof *stmts)))
+ if (!stmts)
{
perror("realloc(3)");
return -1;
}
+ stmts[fn->nstmts++] = (struct stmt){.type = CALL, .u.call.tk = p->stk};
fn->stmts = stmts;
- fn->stmts[fn->nstmts++] = (struct stmt)
- {
- .type = CALL,
- .u.call =
- {
- .tk = tk,
- .pr = pr
- }
- };
if (push(&init, p))
return -1;
- p->stk = p->tk;
- return 1;
+ return sym(p, onsym);
}
diff --git a/src/prc1/call.h b/src/prc1/call.h
index 0126e7f..d1b534c 100644
--- a/src/prc1/call.h
+++ b/src/prc1/call.h
@@ -9,23 +9,14 @@
struct callparam
{
- const struct lit *lit;
- const struct type *t;
- const struct stentry *entry;
- int sign;
-
- union callv
- {
- long long v;
- unsigned long long uv;
- } u;
+ const struct sym *s;
};
struct call
{
- const struct tk *tk;
+ const struct tk *tk, *using, *returning;
const struct pr *pr;
- const struct stentry *ret;
+ const struct sym *id, *ret;
struct callparam *params;
size_t nparams;
};
diff --git a/src/prc1/cgen.c b/src/prc1/cgen.c
index 44e9d24..c394f44 100644
--- a/src/prc1/cgen.c
+++ b/src/prc1/cgen.c
@@ -1,195 +1,16 @@
#include "cgen.h"
-#include "fn.h"
-#include "lex.h"
-#include "lit.h"
-#include "parse.h"
-#include "storage.h"
-#include <stddef.h>
-#include <stdlib.h>
-#include <string.h>
+#include "cgen/prv.h"
-void cgen_free(struct cgen *c)
-{
-}
-
-const char *cgen_sz(const size_t sz)
-{
- switch (sz)
- {
- case 1:
- return "b";
- case 2:
- return "h";
- case 4:
- return "w";
- case 8:
- return "l";
- default:
- break;
- }
-
- return NULL;
-}
-
-const char *cgen_tmp(const size_t sz)
-{
- switch (sz)
- {
- case 1:
- return "vb";
- case 2:
- return "vh";
- case 4:
- return "vw";
- case 8:
- return "vl";
- default:
- break;
- }
-
- return "v";
-}
-
-const char *cgen_type(const struct type *t)
+int cgen(const struct ast *ast, struct cgen *c)
{
- switch (t->sz)
- {
- case 1:
- return t->sign ? "b" : "ub";
- case 2:
- return t->sign ? "h" : "uh";
- case 4:
- return t->sign ? "w" : "uw";
- case 8:
- return t->sign ? "l" : "ul";
-
- default:
- break;
- }
+ const struct args *args = ast->args;
- return NULL;
-}
-
-const char *cgen_abity(const struct type *t)
-{
- switch (t->sz)
+ switch (args->tgt)
{
- case 1:
- return t->sign ? "b" : "ub";
- case 2:
- return t->sign ? "h" : "uh";
- case 4:
- return "w";
- case 8:
- return "l";
-
- default:
- break;
+ case QBE:
+ return cgen_qbe(ast, c);
}
- return NULL;
-}
-
-const char *cgen_load(const struct type *t)
-{
- switch (t->sz)
- {
- case 1:
- return t->sign ? "sb" : "ub";
- case 2:
- return t->sign ? "sh" : "uh";
- case 4:
- return t->sign ? "sw" : "uw";
- case 8:
- return "l";
-
- default:
- break;
- }
-
- return NULL;
-}
-
-int cgen_param(const struct fn *fn, const struct stentry *e)
-{
- const struct pr *pr = fn->pr;
- const char *name = e->tk->s;
-
- for (size_t i = 0; i < pr->nparams; i++)
- if (!strcmp(pr->params[i].tk->s, name))
- return 1;
-
- return 0;
-}
-
-void cgen_printvar(const struct fn *fn, const struct stentry *e)
-{
- const char *name = e->tk->s;
-
- if (cgen_global(fn, e))
- printf("$%s", name);
- else
- printf("%%%s_", name);
-}
-
-int cgen_global(const struct fn *fn, const struct stentry *e)
-{
- const struct storage *ws = fn->ws, *gl = fn->gl;
- const struct pr *pr = fn->pr;
- const struct param *ret = pr->ret;
- const char *name = e->tk->s;
-
- /* A variable is only global if it is defined inside the global
- * variables section ("gl"), or if it is not listed on the working
- * storage section ("ws"), as a function parameter or a return value. */
-
- if (gl)
- for (size_t i = 0; i < gl->nentries; i++)
- if (!strcmp(gl->entries[i].tk->s, name))
- return 1;
-
- if (cgen_param(fn, e) || (ret && !strcmp(ret->tk->s, name)))
- return 0;
- else if (ws)
- for (size_t i = 0; i < ws->nentries; i++)
- if (!strcmp(ws->entries[i].tk->s, name))
- return 0;
-
- for (const struct tmp *t = fn->tmps; t; t = t->next)
- if (!strcmp(t->tk.s, name))
- return 0;
-
- return 1;
-}
-
-static void pushfmt(const char *type, const char *fmt)
-{
- printf("data $____fmt%s = { b \"%s\" , b 0 }\n", type, fmt);
-}
-
-int cgen(const struct ast *ast, struct cgen *c)
-{
- /* generate literals to use with printf(3) */
- pushfmt("b", "%hhd");
- pushfmt("h", "%hd");
- pushfmt("w", "%d");
- pushfmt("l", "%ld");
- pushfmt("ub", "%hhu");
- pushfmt("uh", "%hu");
- pushfmt("uw", "%u");
- pushfmt("ul", "%lu");
- pushfmt("bx", "%#hhx");
- pushfmt("hx", "%#hx");
- pushfmt("wx", "%#x");
- pushfmt("lx", "%#lx");
-
- for (const struct lit *l = ast->lits; l; l = l->next)
- if (lit_cgen(l))
- return-1;
-
- for (size_t i = 0; i < ast->nfns; i++)
- if (fn_cgen((c->fn = &ast->fns[i]), c))
- return -1;
-
- return 0;
+ fprintf(stderr, "%s: unreachable\n", __func__);
+ return -1;
}
diff --git a/src/prc1/cgen.h b/src/prc1/cgen.h
index 0a30138..e8d48e1 100644
--- a/src/prc1/cgen.h
+++ b/src/prc1/cgen.h
@@ -6,18 +6,15 @@
struct cgen
{
+ const struct cgen_drv *drv;
const struct fn *fn;
+ struct fn_cgen *fnc;
+ struct cgen_prv *p;
};
int cgen(const struct ast *ast, struct cgen *c);
int cgen_param(const struct fn *fn, const struct stentry *e);
int cgen_global(const struct fn *fn, const struct stentry *e);
-void cgen_printvar(const struct fn *fn, const struct stentry *e);
-const char *cgen_sz(const size_t sz);
-const char *cgen_tmp(const size_t sz);
-const char *cgen_type(const struct type *t);
-const char *cgen_abity(const struct type *t);
-const char *cgen_load(const struct type *t);
void cgen_free(struct cgen *c);
#endif
diff --git a/src/prc1/cgen/CMakeLists.txt b/src/prc1/cgen/CMakeLists.txt
new file mode 100644
index 0000000..77aa786
--- /dev/null
+++ b/src/prc1/cgen/CMakeLists.txt
@@ -0,0 +1,12 @@
+add_subdirectory(qbe)
+target_sources(prc1 PRIVATE
+ call.c
+ fn.c
+ free.c
+ gl.c
+ global.c
+ param.c
+ print.c
+ set.c
+ ws.c
+)
diff --git a/src/prc1/cgen/call.c b/src/prc1/cgen/call.c
new file mode 100644
index 0000000..dc3545b
--- /dev/null
+++ b/src/prc1/cgen/call.c
@@ -0,0 +1,8 @@
+#include "call.h"
+#include "cgen.h"
+#include "cgen/prv.h"
+
+int call_cgen(const struct call *m, struct cgen *c)
+{
+ return c->drv->call(m, c);
+}
diff --git a/src/prc1/cgen/fn.c b/src/prc1/cgen/fn.c
new file mode 100644
index 0000000..0a79a1d
--- /dev/null
+++ b/src/prc1/cgen/fn.c
@@ -0,0 +1,8 @@
+#include "cgen.h"
+#include "cgen/prv.h"
+#include "fn.h"
+
+int fn_cgen(const struct fn *fn, struct cgen *c)
+{
+ return c->drv->fn(fn, c);
+}
diff --git a/src/prc1/cgen/free.c b/src/prc1/cgen/free.c
new file mode 100644
index 0000000..a7b88bb
--- /dev/null
+++ b/src/prc1/cgen/free.c
@@ -0,0 +1,8 @@
+#include "cgen.h"
+#include "cgen/prv.h"
+
+void cgen_free(struct cgen *c)
+{
+ if (c->drv)
+ c->drv->free(c->p);
+}
diff --git a/src/prc1/cgen/gl.c b/src/prc1/cgen/gl.c
new file mode 100644
index 0000000..8b436b8
--- /dev/null
+++ b/src/prc1/cgen/gl.c
@@ -0,0 +1,8 @@
+#include "cgen.h"
+#include "cgen/prv.h"
+#include "gl.h"
+
+int gl_cgen(const struct storage *gl, struct cgen *c)
+{
+ return c->drv->gl(gl, c);
+}
diff --git a/src/prc1/cgen/global.c b/src/prc1/cgen/global.c
new file mode 100644
index 0000000..6371b96
--- /dev/null
+++ b/src/prc1/cgen/global.c
@@ -0,0 +1,32 @@
+#include "cgen.h"
+#include <string.h>
+
+int cgen_global(const struct fn *fn, const struct stentry *e)
+{
+ const struct storage *ws = fn->ws, *gl = fn->gl;
+ const struct pr *pr = fn->pr;
+ const struct param *ret = pr->ret;
+ const char *name = e->tk->s;
+
+ /* A variable is only global if it is defined inside the global
+ * variables section ("gl"), or if it is not listed on the working
+ * storage section ("ws"), as a function parameter or a return value. */
+
+ if (gl)
+ for (size_t i = 0; i < gl->nentries; i++)
+ if (!strcmp(gl->entries[i].tk->s, name))
+ return 1;
+
+ if (cgen_param(fn, e) || (ret && !strcmp(ret->tk->s, name)))
+ return 0;
+ else if (ws)
+ for (size_t i = 0; i < ws->nentries; i++)
+ if (!strcmp(ws->entries[i].tk->s, name))
+ return 0;
+
+ for (const struct tmp *t = fn->tmps; t; t = t->next)
+ if (!strcmp(t->tk.s, name))
+ return 0;
+
+ return 1;
+}
diff --git a/src/prc1/cgen/param.c b/src/prc1/cgen/param.c
new file mode 100644
index 0000000..e31f1f1
--- /dev/null
+++ b/src/prc1/cgen/param.c
@@ -0,0 +1,15 @@
+#include "cgen.h"
+#include <stddef.h>
+#include <string.h>
+
+int cgen_param(const struct fn *fn, const struct stentry *e)
+{
+ const struct pr *pr = fn->pr;
+ const char *name = e->tk->s;
+
+ for (size_t i = 0; i < pr->nparams; i++)
+ if (!strcmp(pr->params[i].tk->s, name))
+ return 1;
+
+ return 0;
+}
diff --git a/src/prc1/cgen/print.c b/src/prc1/cgen/print.c
new file mode 100644
index 0000000..32c01f3
--- /dev/null
+++ b/src/prc1/cgen/print.c
@@ -0,0 +1,8 @@
+#include "cgen.h"
+#include "cgen/prv.h"
+#include "print.h"
+
+int print_cgen(const struct print *p, struct cgen *c, const char *f)
+{
+ return c->drv->print(p, c, f);
+}
diff --git a/src/prc1/cgen/prv.h b/src/prc1/cgen/prv.h
new file mode 100644
index 0000000..dc99404
--- /dev/null
+++ b/src/prc1/cgen/prv.h
@@ -0,0 +1,23 @@
+#ifndef CGEN_PRV_H
+#define CGEN_PRV_H
+
+#include "cgen.h"
+#include "call.h"
+#include "print.h"
+#include "set.h"
+#include "storage.h"
+
+struct cgen_drv
+{
+ int (*print)(const struct print *, struct cgen *, const char *);
+ int (*gl)(const struct storage *, struct cgen *);
+ int (*ws)(const struct storage *, struct cgen *);
+ int (*call)(const struct call *, struct cgen *);
+ int (*set)(const struct set *, struct cgen *);
+ int (*fn)(const struct fn *, struct cgen *);
+ void (*free)(struct cgen_prv *);
+};
+
+int cgen_qbe(const struct ast *ast, struct cgen *c);
+
+#endif
diff --git a/src/prc1/cgen/qbe/CMakeLists.txt b/src/prc1/cgen/qbe/CMakeLists.txt
new file mode 100644
index 0000000..5d0bd63
--- /dev/null
+++ b/src/prc1/cgen/qbe/CMakeLists.txt
@@ -0,0 +1,10 @@
+target_sources(prc1 PRIVATE
+ call.c
+ free.c
+ fn.c
+ gl.c
+ print.c
+ set.c
+ qbe.c
+ ws.c
+)
diff --git a/src/prc1/cgen/qbe/call.c b/src/prc1/cgen/qbe/call.c
new file mode 100644
index 0000000..0f49d76
--- /dev/null
+++ b/src/prc1/cgen/qbe/call.c
@@ -0,0 +1,163 @@
+#include "call.h"
+#include "cgen.h"
+#include "cgen/prv.h"
+#include "qbe.h"
+#include <stdio.h>
+
+#if 0
+static int gettmp(char *tmp, size_t n)
+{
+ size_t j;
+
+ for (j = 0; j < n; j++)
+ {
+ char c = tmp[j];
+
+ if (!c)
+ return tmp[j] = 'a';
+ else if (c != 'z')
+ return ++(tmp[j]);
+ }
+
+ return EOF;
+}
+
+static int param_lit(const struct lit *lit, struct cgen *c)
+{
+ printf("l $%s", lit->name);
+ return 0;
+}
+
+static int param_id(const struct stentry *e, struct cgen *c, char *tmp,
+ size_t n)
+{
+ const char *name = e->tk->s;
+ const struct type *t = e->t;
+
+ printf("%s ", cgen_sz(t->sz));
+
+ if (cgen_global(c->fn, e))
+ printf("$%s", name);
+ else if (cgen_abity(t))
+ {
+ if (gettmp(tmp, n) == EOF)
+ return -1;
+
+ printf("%%%s", tmp);
+ }
+ else
+ printf("%%%s_", name);
+
+ return 0;
+}
+
+static int param_c(const struct type *t, struct cgen *cg)
+{
+ const union c *c = &t->u.c;
+
+ /* TODO: adapt type to expected param size */
+ fputs("l ", stdout);
+
+ if (t->sign)
+ printf("%lld", c->v);
+ else
+ printf("%llu", c->uv);
+
+ return 0;
+}
+
+static int param_num(const struct callparam *cp, struct cgen *c)
+{
+ const union callv *u = &cp->u;
+
+ /* TODO: adapt type to expected param size */
+ fputs("w ", stdout);
+
+ if (cp->sign)
+ printf("%lld", u->v);
+ else
+ printf("%llu", u->uv);
+
+ return 0;
+}
+
+static int param_load(const struct call *m, struct cgen *c)
+{
+ char tmp[sizeof "abcdefghijklmnopqrstuvwxyz"] = {0};
+
+ for (size_t i = 0; i < m->nparams; i++)
+ {
+ const struct callparam *cp = &m->params[i];
+ const struct stentry *e = cp->entry;
+
+ if (!e || cgen_global(c->fn, e) || !cgen_abity(e->t))
+ continue;
+ else if (gettmp(tmp, sizeof tmp - 1) == EOF)
+ {
+ fprintf(stderr, "%s: exhausted temporaries\n", __func__);
+ return -1;
+ }
+
+ printf("%%%s =%s load%s %%%s_\n", tmp, cgen_sz(e->t->sz),
+ cgen_load(e->t), e->tk->s);
+ }
+
+ return 0;
+}
+
+int call_cgen(const struct call *m, struct cgen *c)
+{
+ char tmps[sizeof "abcdefghijklmnopqrstuvwxyz"] = {0};
+ const struct stentry *ret = m->ret;
+ const char *tmp;
+ size_t sz;
+
+ if (param_load(m, c))
+ return -1;
+ else if (ret)
+ {
+ tmp = cgen_tmp((sz = ret->t->sz));
+ printf("%%%s =%s ", tmp, cgen_sz(sz));
+ }
+
+ printf("call $%s(", m->tk->s);
+
+ for (size_t i = 0; i < m->nparams; i++)
+ {
+ const struct callparam *cp = &m->params[i];
+ int var = m->pr->variadic;
+
+ if (cp->lit)
+ param_lit(cp->lit, c);
+ else if (cp->entry)
+ param_id(cp->entry, c, tmps, sizeof tmps - 1);
+ else if (cp->t)
+ param_c(cp->t, c);
+ else
+ param_num(cp, c);
+
+ if (var && i + 1 == var - 1)
+ fputs(", ...", stdout);
+
+ if (i + 1 < m->nparams)
+ fputs(", ", stdout);
+ }
+
+ puts(")");
+
+ if (ret)
+ {
+ printf("store%s %%%s, ", cgen_sz(sz), tmp);
+ cgen_printvar(c->fn, ret);
+ putchar('\n');
+ }
+
+ return 0;
+}
+#endif
+
+int qbe_call(const struct call *m, struct cgen *c)
+{
+ fprintf(stderr, "%s: TODO\n", __func__);
+ return -1;
+}
diff --git a/src/prc1/cgen/qbe/fn.c b/src/prc1/cgen/qbe/fn.c
new file mode 100644
index 0000000..61b0bf0
--- /dev/null
+++ b/src/prc1/cgen/qbe/fn.c
@@ -0,0 +1,94 @@
+#include "cgen.h"
+#include "fn.h"
+#include "gl.h"
+#include "stmt.h"
+#include "qbe.h"
+#include "ws.h"
+#include <stdio.h>
+
+int qbe_fn(const struct fn *fn, struct cgen *c)
+{
+ const struct pr *pr = fn->pr;
+ const struct param *ret = pr->ret;
+ const struct type *rt = NULL;
+ const char *s = NULL;
+ struct fn_cgen fnc = {0};
+
+ c->fnc = &fnc;
+
+ if (fn->gl && gl_cgen(fn->gl, c))
+ return -1;
+
+ switch (fn->linkage)
+ {
+ case STATIC:
+ printf("function ");
+ break;
+ case EXTERNAL:
+ printf("export function ");
+ break;
+ }
+
+ if (ret)
+ {
+ rt = ret->entry->t;
+ s = ret->entry->tk->s;
+ printf("%s ", cgen_abity(ret->entry->t));
+ }
+
+ printf("$%s(", fn->tk->s);
+
+ for (size_t i = 0; i < pr->nparams; i++)
+ {
+ const struct param *p = &pr->params[i];
+
+ printf(" %s", cgen_abity(p->entry->t));
+ printf(" %%__param_%s ", p->tk->s);
+
+ if (i + 1 < pr->nparams)
+ fputs(", ", stdout);
+ }
+
+ puts(") {\n@start");
+
+ for (size_t i = 0; i < pr->nparams; i++)
+ {
+ const struct param *p = &pr->params[i];
+ const struct type *t = p->entry->t;
+ const char *s = p->tk->s;
+
+ printf("%%%s_ =l alloc%zu %zu\n", s, t->align, t->sz);
+ printf("store%s %%__param_%s, %%%s_\n", cgen_sz(t->sz), s, s);
+ }
+
+ if (ret)
+ printf("%%%s_ =l alloc%zu %zu\n", s, rt->align, rt->sz);
+
+ if (fn->ws && ws_cgen(fn->ws, c))
+ return -1;
+
+ for (const struct tmp *tmp = fn->tmps; tmp; tmp = tmp->next)
+ {
+ const struct stentry *e = &tmp->e;
+ const struct type *t = tmp->e.t;
+
+ printf("%%%s_ =l alloc%zu %zu\n", e->tk->s, t->align, t->sz);
+ }
+
+ for (size_t i = 0; i < fn->nstmts; i++)
+ if (stmt_cgen(&fn->stmts[i], c))
+ return -1;
+
+ if (ret)
+ {
+ const char *t = cgen_tmp(rt->sz);
+
+ printf("%%%s =%s load%s %%%s_\n", t, cgen_sz(rt->sz), cgen_load(rt), s);
+ printf("ret %%%s", t);
+ }
+ else
+ fputs("ret", stdout);
+
+ puts("\n}");
+ return 0;
+}
diff --git a/src/prc1/cgen/qbe/free.c b/src/prc1/cgen/qbe/free.c
new file mode 100644
index 0000000..c05e72d
--- /dev/null
+++ b/src/prc1/cgen/qbe/free.c
@@ -0,0 +1,7 @@
+#include "cgen.h"
+#include "cgen/prv.h"
+#include "qbe.h"
+
+void qbe_free(struct cgen_prv *p)
+{
+}
diff --git a/src/prc1/cgen/qbe/gl.c b/src/prc1/cgen/qbe/gl.c
new file mode 100644
index 0000000..61e9d7a
--- /dev/null
+++ b/src/prc1/cgen/qbe/gl.c
@@ -0,0 +1,16 @@
+#include "cgen.h"
+#include "qbe.h"
+#include <stddef.h>
+#include <stdio.h>
+
+int qbe_gl(const struct storage *gl, struct cgen *c)
+{
+ for (size_t i = 0; i < gl->nentries; i++)
+ {
+ const struct stentry *e = &gl->entries[i];
+
+ printf("export data $%s = { z %zu }\n", e->tk->s, e->t->sz);
+ }
+
+ return 0;
+}
diff --git a/src/prc1/cgen/qbe/print.c b/src/prc1/cgen/qbe/print.c
new file mode 100644
index 0000000..2890eb8
--- /dev/null
+++ b/src/prc1/cgen/qbe/print.c
@@ -0,0 +1,95 @@
+#include "cgen.h"
+#include "cgen/prv.h"
+#include "print.h"
+#include "qbe.h"
+#include <stdio.h>
+
+static int cg_str(const struct prisym *s, struct cgen *c, const char *f)
+{
+ fprintf(stderr, "%s: TODO\n", __func__);
+ return -1;
+}
+
+static int cg_ptr(const struct prisym *s, struct cgen *c, const char *f)
+{
+ const char *tmpf = cgen_tmp2(c), *tmpv = cgen_tmp2(c),
+ *name = s->s->tk->s;
+
+ if (!tmpf || !tmpv)
+ return -1;
+
+ printf("%%%s =l loadl ", tmpv);
+
+ if (cgen_global(c->fn, s->u.e))
+ printf("$%s", name);
+ else
+ printf("%%%s_", name);
+
+ fputc('\n', stdout);
+ printf("%%%s =l loadl $%s\n", tmpf, f);
+ printf("call $fprintf(w %%%s, l $____fmtlx, ..., l %%%s)\n", tmpf, tmpv);
+ return 0;
+}
+
+static int cg_num(const struct prisym *s, struct cgen *c, const char *f)
+{
+ fprintf(stderr, "%s: TODO\n", __func__);
+ return -1;
+}
+
+static int cg_nam(const struct prisym *ps, struct cgen *c, const char *f)
+{
+ const char *tmpf = cgen_tmp2(c), *name = ps->u.name;
+
+ if (!tmpf)
+ return -1;
+
+ printf("%%%s =l loadl $%s\n", tmpf, f);
+ printf("call $fprintf(w %%%s, l $____fmtlx, ..., l $%s)\n", tmpf, name);
+ return 0;
+}
+
+static int cg_lit(const struct prisym *s, struct cgen *c, const char *f)
+{
+ const struct lit *l = s->u.lit;
+ const char *tmp;
+
+ if (!l)
+ {
+ fprintf(stderr, "%s: unexpected null literal\n", __func__);
+ return -1;
+ }
+
+ /* TODO: ask target for sizeof (void *) */
+ tmp = cgen_tmp(sizeof (void *));
+ printf("%%%s =l loadl $%s\n", tmp, f);
+ printf("call $fputs(l $%s, w %%%s)\n", l->name, tmp);
+ return 0;
+}
+
+int qbe_print(const struct print *pr, struct cgen *c, const char *f)
+{
+ for (size_t i = 0; i < pr->nsyms; i++)
+ {
+ const struct prisym *ps = &pr->syms[i];
+ static int (*fn[])(const struct prisym *, struct cgen *, const char *) =
+ {
+ [PRS_LIT] = cg_lit,
+ [PRS_STR] = cg_str,
+ [PRS_NAM] = cg_nam,
+ [PRS_PTR] = cg_ptr,
+ [PRS_NUM] = cg_num
+ };
+
+ if (fn[ps->type](ps, c, f))
+ return -1;
+ }
+
+ if (!pr->skipln)
+ {
+ printf("%%v =l loadl $%s\n", f);
+ puts("call $fputc(l 10 , w %v)");
+ }
+
+ return 0;
+}
diff --git a/src/prc1/cgen/qbe/qbe.c b/src/prc1/cgen/qbe/qbe.c
new file mode 100644
index 0000000..c27bad6
--- /dev/null
+++ b/src/prc1/cgen/qbe/qbe.c
@@ -0,0 +1,187 @@
+#include "cgen.h"
+#include "cgen/prv.h"
+#include "fn.h"
+#include "lex.h"
+#include "lit.h"
+#include "parse.h"
+#include "qbe.h"
+#include "storage.h"
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+const char *cgen_sz(const size_t sz)
+{
+ switch (sz)
+ {
+ case 1:
+ return "b";
+ case 2:
+ return "h";
+ case 4:
+ return "w";
+ case 8:
+ return "l";
+ default:
+ break;
+ }
+
+ return NULL;
+}
+
+const char *cgen_tmp2(struct cgen *c)
+{
+ struct fn_cgen *fnc = c->fnc;
+
+ for (size_t i = 0; i < sizeof fnc->tmp - 1; i++)
+ {
+ char *s = &fnc->tmp[i];
+
+ if (!*s)
+ *s = 'a';
+ else if (*s >= 'z')
+ *s = 'A';
+ else if (*s >= 'Z')
+ continue;
+ else
+ (*s)++;
+
+ return s;
+ }
+
+ fprintf(stderr, "%s: ran out of temporaries\n", __func__);
+ return NULL;
+}
+
+const char *cgen_tmp(const size_t sz)
+{
+ switch (sz)
+ {
+ case 1:
+ return "vb";
+ case 2:
+ return "vh";
+ case 4:
+ return "vw";
+ case 8:
+ return "vl";
+ default:
+ break;
+ }
+
+ return "v";
+}
+
+const char *cgen_type(const struct type *t)
+{
+ switch (t->sz)
+ {
+ case 1:
+ return t->sign ? "b" : "ub";
+ case 2:
+ return t->sign ? "h" : "uh";
+ case 4:
+ return t->sign ? "w" : "uw";
+ case 8:
+ return t->sign ? "l" : "ul";
+
+ default:
+ break;
+ }
+
+ return NULL;
+}
+
+const char *cgen_abity(const struct type *t)
+{
+ switch (t->sz)
+ {
+ case 1:
+ return t->sign ? "b" : "ub";
+ case 2:
+ return t->sign ? "h" : "uh";
+ case 4:
+ return "w";
+ case 8:
+ return "l";
+
+ default:
+ break;
+ }
+
+ return NULL;
+}
+
+const char *cgen_load(const struct type *t)
+{
+ switch (t->sz)
+ {
+ case 1:
+ return t->sign ? "sb" : "ub";
+ case 2:
+ return t->sign ? "sh" : "uh";
+ case 4:
+ return t->sign ? "sw" : "uw";
+ case 8:
+ return "l";
+
+ default:
+ break;
+ }
+
+ return NULL;
+}
+
+void cgen_printvar(const struct fn *fn, const struct stentry *e)
+{
+ const char *name = e->tk->s;
+
+ if (cgen_global(fn, e))
+ printf("$%s", name);
+ else
+ printf("%%%s_", name);
+}
+
+static void pushfmt(const char *type, const char *fmt)
+{
+ printf("data $____fmt%s = { b \"%s\" , b 0 }\n", type, fmt);
+}
+
+int cgen_qbe(const struct ast *ast, struct cgen *c)
+{
+ static const struct cgen_drv drv =
+ {
+ .print = qbe_print,
+ .call = qbe_call,
+ .free = qbe_free,
+ .set = qbe_set,
+ .gl = qbe_gl,
+ .ws = qbe_ws,
+ .fn = qbe_fn
+ };
+
+ c->drv = &drv;
+ /* generate literals to use with printf(3) */
+ pushfmt("b", "%hhd");
+ pushfmt("h", "%hd");
+ pushfmt("w", "%d");
+ pushfmt("l", "%ld");
+ pushfmt("ub", "%hhu");
+ pushfmt("uh", "%hu");
+ pushfmt("uw", "%u");
+ pushfmt("ul", "%lu");
+ pushfmt("bx", "%#hhx");
+ pushfmt("hx", "%#hx");
+ pushfmt("wx", "%#x");
+ pushfmt("lx", "%#lx");
+
+ for (const struct lit *l = ast->lits; l; l = l->next)
+ if (lit_cgen(l))
+ return-1;
+
+ for (size_t i = 0; i < ast->nfns; i++)
+ if (fn_cgen((c->fn = &ast->fns[i]), c))
+ return -1;
+
+ return 0;
+}
diff --git a/src/prc1/cgen/qbe/qbe.h b/src/prc1/cgen/qbe/qbe.h
new file mode 100644
index 0000000..b0e66f1
--- /dev/null
+++ b/src/prc1/cgen/qbe/qbe.h
@@ -0,0 +1,26 @@
+#ifndef QBE_H
+#define QBE_H
+
+#include "call.h"
+#include "cgen.h"
+#include "print.h"
+#include "set.h"
+#include "storage.h"
+#include <stddef.h>
+
+const char *cgen_sz(const size_t sz);
+const char *cgen_tmp(const size_t sz);
+const char *cgen_tmp2(struct cgen *c);
+const char *cgen_type(const struct type *t);
+const char *cgen_abity(const struct type *t);
+const char *cgen_load(const struct type *t);
+int qbe_print(const struct print *m, struct cgen *c, const char *f);
+void cgen_printvar(const struct fn *fn, const struct stentry *e);
+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_fn(const struct fn *fn, struct cgen *c);
+void qbe_free(struct cgen_prv *p);
+
+#endif
diff --git a/src/prc1/cgen/qbe/set.c b/src/prc1/cgen/qbe/set.c
new file mode 100644
index 0000000..5dad08f
--- /dev/null
+++ b/src/prc1/cgen/qbe/set.c
@@ -0,0 +1,11 @@
+#include "call.h"
+#include "cgen.h"
+#include "cgen/prv.h"
+#include "qbe.h"
+#include <stdio.h>
+
+int qbe_set(const struct set *s, struct cgen *c)
+{
+ fprintf(stderr, "%s: TODO\n", __func__);
+ return -1;
+}
diff --git a/src/prc1/cgen/qbe/ws.c b/src/prc1/cgen/qbe/ws.c
new file mode 100644
index 0000000..4f4a6df
--- /dev/null
+++ b/src/prc1/cgen/qbe/ws.c
@@ -0,0 +1,23 @@
+#include "cgen.h"
+#include "storage.h"
+#include "type.h"
+#include "qbe.h"
+#include <stddef.h>
+#include <stdio.h>
+
+static int wspush(const struct stentry *e, struct cgen *c)
+{
+ const struct type *t = e->t;
+
+ printf("%%%s_ =l alloc%zu %zu\n", e->tk->s, t->align, t->sz);
+ return 0;
+}
+
+int qbe_ws(const struct storage *s, struct cgen *c)
+{
+ for (size_t i = 0; i < s->nentries; i++)
+ if (wspush(&s->entries[i], c))
+ return -1;
+
+ return 0;
+}
diff --git a/src/prc1/cgen/set.c b/src/prc1/cgen/set.c
new file mode 100644
index 0000000..07e654e
--- /dev/null
+++ b/src/prc1/cgen/set.c
@@ -0,0 +1,8 @@
+#include "cgen.h"
+#include "cgen/prv.h"
+#include "set.h"
+
+int set_cgen(const struct set *s, struct cgen *c)
+{
+ return c->drv->set(s, c);
+}
diff --git a/src/prc1/cgen/ws.c b/src/prc1/cgen/ws.c
new file mode 100644
index 0000000..a836e21
--- /dev/null
+++ b/src/prc1/cgen/ws.c
@@ -0,0 +1,8 @@
+#include "cgen.h"
+#include "cgen/prv.h"
+#include "ws.h"
+
+int ws_cgen(const struct storage *s, struct cgen *c)
+{
+ return c->drv->ws(s, c);
+}
diff --git a/src/prc1/dbg.c b/src/prc1/dbg.c
index cf2d18c..becb3e5 100644
--- a/src/prc1/dbg.c
+++ b/src/prc1/dbg.c
@@ -17,3 +17,17 @@ int dbg(const char *fmt, ...)
va_end(ap);
return n;
}
+
+int ddbg(const char *fmt, ...)
+{
+ int n;
+ va_list ap;
+
+ if (dbgen < 2)
+ return 0;
+
+ va_start(ap, fmt);
+ n = vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ return n;
+}
diff --git a/src/prc1/dbg.h b/src/prc1/dbg.h
index 956187e..aecbd78 100644
--- a/src/prc1/dbg.h
+++ b/src/prc1/dbg.h
@@ -2,6 +2,7 @@
#define DBG_H
int dbg(const char *fmt, ...);
+int ddbg(const char *fmt, ...);
extern int dbgen;
diff --git a/src/prc1/display.c b/src/prc1/display.c
index 2fbf331..70fac93 100644
--- a/src/prc1/display.c
+++ b/src/prc1/display.c
@@ -1,19 +1,21 @@
#include "display.h"
#include "cgen.h"
#include "dbg.h"
+#include "fn.h"
#include "parse.h"
#include "prv.h"
#include "stmt.h"
-#include "storage.h"
-#include <errno.h>
+#include <stddef.h>
#include <stdlib.h>
-#include <string.h>
-static int finalize(const struct lex *l, const struct prv *p,
- const struct print *pr)
+int display_cgen(const struct print *pr, struct cgen *c)
{
- const struct ast *ast = p->ast;
- struct fn *fn = &ast->fns[ast->nfns - 1];
+ return print_cgen(pr, c, "stdout");
+}
+
+int display(const struct lex *l, struct prv *p)
+{
+ struct fn *fn = fn_cur(p);
size_t n = fn->nstmts + 1;
struct stmt *stmts = realloc(fn->stmts, n * sizeof *stmts);
@@ -23,121 +25,8 @@ static int finalize(const struct lex *l, const struct prv *p,
return -1;
}
+ dbg("\t\tadd display statement\n");
+ stmts[fn->nstmts++] = (struct stmt){.type = DISPLAY, .u.print = {0}};
fn->stmts = stmts;
- fn->stmts[fn->nstmts++] = (struct stmt)
- {
- .type = DISPLAY,
- .u.display.p = *pr
- };
-
- dbg("\t\tadding display statement with %zu entries%s\n", pr->nentries,
- pr->println ? "" : ", no lf");
- return 0;
-}
-
-static int cg_val(const struct tk *tk)
-{
- const char *num = tk->s;
- int neg = *num == '-';
- unsigned long long uv;
- char *end;
-
- fputs("call $printf(l $____fmt", stdout);
- errno = 0;
- uv = strtoull(num, &end, 16);
-
- if (!neg && !errno && !*end)
- printf("lx, ..., l %llu )\n", uv);
- else
- {
- errno = 0;
- uv = strtoull(num, &end, 0);
-
- if (neg || errno || *end)
- {
- long long v = strtoll(num, NULL, 0);
- printf("l, ..., l %lld )\n", v);
- }
- else
- printf("l, ..., l %llu )\n", uv);
- }
-
- return 0;
-}
-
-static int cg_lit(const struct prientry *e)
-{
- const struct lit *l = e->lit;
- const char *tmp;
-
- if (!l)
- {
- fprintf(stderr, "%s: unexpected null literal\n", __func__);
- return -1;
- }
-
- printf("%%%s =l loadl $stdout\n", (tmp = cgen_tmp(sizeof (void *))));
- printf("call $fputs(l $%s, w %%%s)\n", l->name, tmp);
- return 0;
-}
-
-static int cg_id(const struct prientry *de, const struct fn *fn)
-{
- const struct stentry *e = de->entry;
- const struct type *t = e->t;
- const char *id = e->tk->s;
- int global = cgen_global(fn, e);
- size_t sz = t->sz;
- const char *asz = cgen_sz(sz < 4 ? 4 : sz), *tmp = cgen_tmp(sz);
-
- if (global)
- printf("%%%s =%s load%s $%s\n", tmp, asz, cgen_load(t), id);
- else
- printf("%%%s =%s load%s %%%s_\n", tmp, asz, cgen_load(t), id);
-
- fputs("call $printf(l $____fmt", stdout);
-
- if (t->type == PTR)
- fputs("lx, ..., l ", stdout);
- else
- printf("%s, ..., %s ", cgen_type(t), asz);
-
- printf("%%%s)\n", tmp);
-
- return 0;
-}
-
-int display_cgen(const struct display *d, struct cgen *c)
-{
- const struct print *p = &d->p;
-
- for (size_t i = 0; i < p->nentries; i++)
- {
- const struct prientry *e = &p->entries[i];
- const struct tk *tk = e->tk;
-
- if (tk->type == LIT && cg_lit(e))
- return -1;
- else if (tk->type == NUM && cg_val(tk))
- return -1;
- else if (tk->type == ID && e->entry && cg_id(e, c->fn))
- return -1;
- else if (tk->type == ID && e->lit && cg_lit(e))
- return -1;
- }
-
- if (p->println)
- puts("call $putchar(l 10)");
-
- return 0;
-}
-
-void display_free(struct display *d)
-{
- print_free(&d->p);
-}
-
-int display(const struct lex *l, struct prv *p)
-{
- return print(l, p, finalize);
+ return print(l, p);
}
diff --git a/src/prc1/display.h b/src/prc1/display.h
index 9b073b1..4367032 100644
--- a/src/prc1/display.h
+++ b/src/prc1/display.h
@@ -1,17 +1,12 @@
#ifndef DISPLAY_H
#define DISPLAY_H
+#include "cgen.h"
#include "lex.h"
#include "print.h"
#include "prv.h"
-struct display
-{
- struct print p;
-};
-
int display(const struct lex *l, struct prv *p);
-int display_cgen(const struct display *d, struct cgen *c);
-void display_free(struct display *d);
+int display_cgen(const struct print *pr, struct cgen *c);
#endif
diff --git a/src/prc1/div.c b/src/prc1/div.c
index 9061ac6..7236a71 100644
--- a/src/prc1/div.c
+++ b/src/prc1/div.c
@@ -1,4 +1,5 @@
#include "div.h"
+#include "fn.h"
#include "gl.h"
#include "im.h"
#include "lk.h"
@@ -6,8 +7,8 @@
#include "td.h"
#include "ws.h"
-static const struct seq linkage =
- {(struct step[]){{ID, "linkage"}, {0}}, .fn = lk},
+static const struct seq
+ linkage = {(struct step[]){{ID, "linkage"}, {0}}, .fn = lk},
types = {(struct step[]){{ID, "types"}, {0}}, .fn = td},
imports = {(struct step[]){{ID, "imports"}, {0}}, .fn = im},
procedure = {(struct step[]){{ID, "procedure"}, {0}}, .fn = pr};
@@ -42,9 +43,9 @@ int div_fn(const struct lex *l, struct prv *p)
{
struct pos init =
{
+ .name = __func__,
.seq = fnseq,
- .stseq = fnseq,
- .step = fnseq->steps
+ .end = fn_end
};
if (push(&init, p))
@@ -58,32 +59,38 @@ int div_im(const struct lex *l, struct prv *p)
{
struct pos init =
{
+ .name = __func__,
.seq = imseq,
- .stseq = imseq,
- .step = imseq->steps
};
- if (lex_eof(l, p->stk))
- return 0;
- else if (push(&init, p))
+ if (push(&init, p))
return -1;
p->stk = p->tk;
- return 1;
+ return 0;
+}
+
+static int endp(const struct lex *l, struct prv *p)
+{
+ if (fn_end(l, p))
+ return -1;
+
+ p->proto = NULL;
+ return 0;
}
int div_p(const struct lex *l, struct prv *p)
{
struct pos init =
{
+ .name = __func__,
.seq = pseq,
- .stseq = pseq,
- .step = pseq->steps
+ .end = endp
};
if (push(&init, p))
return -1;
p->stk = p->tk;
- return 1;
+ return 0;
}
diff --git a/src/prc1/end.c b/src/prc1/end.c
index 561c981..021142c 100644
--- a/src/prc1/end.c
+++ b/src/prc1/end.c
@@ -76,6 +76,6 @@ int end(const struct lex *l, struct prv *p)
pos->seq = pos->stseq = stmts;
pos->step = stmts->steps;
p->stk = p->tk;
- dbg("\t\tadding end statement, block index %zu\n", bl_i);
- return 1;
+ dbg("\t\tadd end statement, block index %zu\n", bl_i);
+ return 0;
}
diff --git a/src/prc1/fn.c b/src/prc1/fn.c
index 03aa11e..affa4be 100644
--- a/src/prc1/fn.c
+++ b/src/prc1/fn.c
@@ -9,6 +9,7 @@
#include "pr.h"
#include "stmt.h"
#include "storage.h"
+#include "sym.h"
#include "td.h"
#include "ws.h"
#include <stdlib.h>
@@ -20,11 +21,8 @@ static int prvfn(const struct lex *l, struct prv *p);
static const struct seq fnseq[] =
{
- {(struct step[])
- {{ID, "public"}, {ID, "function"}, {ID}, {0}}, .fn = pubfn,
- .end = fn_end},
- {(struct step[])
- {{ID, "function"}, {ID}, {0}}, .fn = prvfn, .end = fn_end},
+ {(struct step[]){{ID, "public"}, {ID, "function"}, {ID}, {0}}, .fn = pubfn},
+ {(struct step[]){{ID, "function"}, {ID}, {0}}, .fn = prvfn},
{0}
};
@@ -92,8 +90,8 @@ static int pushfn(const struct tk *tk, const struct lex *lex, struct prv *p,
if (div_fn(lex, p))
return -1;
- dbg("adding %s function %s\n", l == STATIC ? "private" : "public", tk->s);
- return 1;
+ dbg("add %s function %s\n", l == STATIC ? "private" : "public", tk->s);
+ return 0;
}
static int pubfn(const struct lex *l, struct prv *p)
@@ -123,90 +121,6 @@ const struct stentry *fn_var(const struct fn *fn, const struct tk *tk)
return NULL;
}
-int fn_cgen(const struct fn *fn, struct cgen *c)
-{
- const struct pr *pr = fn->pr;
- const struct param *ret = pr->ret;
- const struct type *rt = NULL;
- const char *s = NULL;
-
- if (fn->gl && gl_cgen(fn->gl, c))
- return -1;
-
- switch (fn->linkage)
- {
- case STATIC:
- printf("function ");
- break;
- case EXTERNAL:
- printf("export function ");
- break;
- }
-
- if (ret)
- {
- rt = ret->entry->t;
- s = ret->entry->tk->s;
- printf("%s ", cgen_abity(ret->entry->t));
- }
-
- printf("$%s(", fn->tk->s);
-
- for (size_t i = 0; i < pr->nparams; i++)
- {
- const struct param *p = &pr->params[i];
-
- printf(" %s", cgen_abity(p->entry->t));
- printf(" %%__param_%s ", p->tk->s);
-
- if (i + 1 < pr->nparams)
- fputs(", ", stdout);
- }
-
- puts(") {\n@start");
-
- for (size_t i = 0; i < pr->nparams; i++)
- {
- const struct param *p = &pr->params[i];
- const struct type *t = p->entry->t;
- const char *s = p->tk->s;
-
- printf("%%%s_ =l alloc%zu %zu\n", s, t->align, t->sz);
- printf("store%s %%__param_%s, %%%s_\n", cgen_sz(t->sz), s, s);
- }
-
- if (ret)
- printf("%%%s_ =l alloc%zu %zu\n", s, rt->align, rt->sz);
-
- if (fn->ws && ws_cgen(fn->ws, c))
- return -1;
-
- for (const struct tmp *tmp = fn->tmps; tmp; tmp = tmp->next)
- {
- const struct stentry *e = &tmp->e;
- const struct type *t = tmp->e.t;
-
- printf("%%%s_ =l alloc%zu %zu\n", e->tk->s, t->align, t->sz);
- }
-
- for (size_t i = 0; i < fn->nstmts; i++)
- if (stmt_cgen(&fn->stmts[i], c))
- return -1;
-
- if (ret)
- {
- const char *t = cgen_tmp(rt->sz);
-
- printf("%%%s =%s load%s %%%s_\n", t, cgen_sz(rt->sz), cgen_load(rt), s);
- printf("ret %%%s", t);
- }
- else
- fputs("ret", stdout);
-
- puts("\n}");
- return 0;
-}
-
void fn_cgen_free(struct fn_cgen *c)
{
free(c);
@@ -229,6 +143,14 @@ void fn_free(struct fn *fn)
t = next;
}
+ for (struct sym *s = fn->syms; s;)
+ {
+ struct sym *next = s->next;
+
+ sym_free(s);
+ s = next;
+ }
+
storage_free(fn->lk);
storage_free(fn->ws);
storage_free(fn->gl);
@@ -253,14 +175,11 @@ int fn(const struct lex *l, struct prv *p)
{
struct pos init =
{
- .seq = fnseq,
- .stseq = fnseq,
- .step = fnseq->steps
+ .name = __func__,
+ .seq = fnseq
};
- if (lex_eof(l, p->stk))
- return 0;
- else if (lex_eof(l, p->stk + 1))
+ if (lex_eof(l, p->stk + 1))
{
errloc(p->stk, "incomplete function statement");
return -1;
@@ -269,5 +188,5 @@ int fn(const struct lex *l, struct prv *p)
return -1;
p->stk = p->tk;
- return 1;
+ return 0;
}
diff --git a/src/prc1/fn.h b/src/prc1/fn.h
index 6c65ae5..f762ab9 100644
--- a/src/prc1/fn.h
+++ b/src/prc1/fn.h
@@ -8,7 +8,7 @@
struct fn_cgen
{
- int dummy;
+ char tmp[sizeof "abcdefghijklmopqrstuvwyxz"];
};
int fn(const struct lex *l, struct prv *p);
diff --git a/src/prc1/from.c b/src/prc1/from.c
index 838d1de..83f9b71 100644
--- a/src/prc1/from.c
+++ b/src/prc1/from.c
@@ -297,13 +297,13 @@ int from(const struct lex *l, struct prv *p)
|| !(fr.var = tmp_create(fn, t)))
return -1;
- dbg("\t\tadding from statement [%s, %s]", start->s, end->s);
+ dbg("\t\tadd from statement [%s, %s]", start->s, end->s);
if (finalize(p, fn, &fr))
return -1;
p->stk = ++end;
- return 1;
+ return 0;
}
static int checkvar(const struct fn *fn, const struct tk *tk, struct from *fr)
@@ -341,14 +341,14 @@ int from_id(const struct lex *l, struct prv *p)
|| checkvar(fn, var, &fr))
return -1;
- dbg("\t\tadding from statement [%s, %s] using %s", start->s, end->s,
+ dbg("\t\tadd from statement [%s, %s] using %s", start->s, end->s,
var->s);
if (finalize(p, fn, &fr))
return -1;
p->stk = ++var;
- return 1;
+ return 0;
}
int from_by(const struct lex *l, struct prv *p)
diff --git a/src/prc1/gl.c b/src/prc1/gl.c
index de0293f..c72db70 100644
--- a/src/prc1/gl.c
+++ b/src/prc1/gl.c
@@ -4,18 +4,6 @@
#include "parse.h"
#include "storage.h"
-int gl_cgen(const struct storage *gl, struct cgen *c)
-{
- for (size_t i = 0; i < gl->nentries; i++)
- {
- const struct stentry *e = &gl->entries[i];
-
- printf("export data $%s = { z %zu }\n", e->tk->s, e->t->sz);
- }
-
- return 0;
-}
-
int gl(const struct lex *l, struct prv *p)
{
struct fn *fn = fn_cur(p);
diff --git a/src/prc1/im.c b/src/prc1/im.c
index e9a208c..68ff9f3 100644
--- a/src/prc1/im.c
+++ b/src/prc1/im.c
@@ -1,77 +1,143 @@
#include "im.h"
+#include "dbg.h"
#include "errloc.h"
#include "fn.h"
#include "prv.h"
#include "parse.h"
+#include "sym.h"
#include <errno.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-static int imlit(const struct lex *, struct prv *);
-
-static const struct seq seqs[] =
-{
- {(struct step[]){{LIT, NULL, 1}, {0}}, .fn = imlit},
- {0}
-};
-
void im_free(struct im *im)
{
ast_free(&im->ast);
lex_free(&im->l);
}
+static FILE *tryinc(const char *dir, const char *path, char **fullpath)
+{
+ FILE *ret = NULL;
+ size_t n = strlen(dir) + strlen(path) + 2;
+ char *fp = malloc(n);
+
+ if (!fp)
+ {
+ perror("malloc(3)");
+ goto end;
+ }
+ else if (snprintf(fp, n, "%s/%s", dir, path) < 0)
+ {
+ fprintf(stderr, "%s: snprintf(3) failed\n", __func__);
+ goto end;
+ }
+ else if ((ret = fopen(fp, "rb")))
+ *fullpath = fp;
+
+end:
+ if (!ret)
+ free(fp);
+
+ return ret;
+}
+
+static char *fpath(const char *cur, const char *path)
+{
+ const char *sl = strrchr(cur, '/');
+ char *ret;
+ /* '/' + '\0' */
+ size_t n = 2;
+ int curlen;
+
+ if (!sl)
+ {
+ cur = ".";
+ curlen = 1;
+ }
+ else
+ curlen = sl - cur;
+
+ n += curlen + strlen(path);
+
+ if ((ret = malloc(n)))
+ snprintf(ret, n, "%.*s/%s", curlen, cur, path);
+ else
+ perror("malloc(3)");
+
+ return ret;
+}
+
static int doim(const struct lex *l, const struct tk *tk, struct prv *p)
{
int ret = -1;
FILE *f = NULL;
struct im *im;
- struct fn *fn = fn_cur(p);
+ struct fn *fn = fn_cur(p), *fns = NULL;
struct ast *ast;
- size_t n = fn->nimps + 1;
const char *path = tk->s;
+ size_t n = fn->nimps + 1;
+ char *fp = NULL, *incfp;
+ const struct loc *loc = &tk->loc;
- if (!strcmp(l->loc.f, path))
- {
- errloc(tk, "detected recursive import \"%s\"", path);
+ /* TODO: no protection against recursive imports */
+ if (!(fp = fpath(l->loc.f, path)))
goto end;
+ else if (!(f = fopen(fp, "rb")))
+ {
+ const struct arg_input *incs = &l->args->incs;
+
+ for (size_t i = 0; i < incs->n; i++)
+ if ((f = tryinc(incs->v[i], path, &incfp)))
+ {
+ free(fp);
+ fp = incfp;
+ break;
+ }
}
- /* TODO: honor -I flags */
- if (!(f = fopen(path, "rb")))
+
+ if (!f)
{
- errloc(tk, "failed to open import \"%s\": %s", path, strerror(errno));
+ errloc(tk, "failed to open import \"%s\"", path);
goto end;
}
- else if (!(im = realloc(fn->imps, n * sizeof *im)))
+ else if (!(fns = malloc(sizeof *fns)))
{
- perror("realloc(3)");
+ perror("malloc(3)");
goto end;
}
- fn->imps = im;
- im = &fn->imps[fn->nimps++];
- *im = (struct im){.l.loc.f = path};
- ast = &im->ast;
+ *fns = (struct fn){.tk = tk};
- if (!(ast->fns = malloc(sizeof *ast->fns)))
+ if (!(im = realloc(fn->imps, n * sizeof *im)))
{
- perror("malloc(3)");
+ perror("realloc(3)");
goto end;
}
- *ast->fns = (struct fn){.tk = tk};
+ fn->imps = im;
+ im = &fn->imps[fn->nimps++];
+ *im = (struct im){.l = {.loc.f = fp, .args = l->args}};
+ ast = &im->ast;
+ ast->fns = fns;
/* hack: treat imports as a function */
ast->nfns = 1;
+ fp = NULL;
+ dbg("start import %s (from %s:%d:%d)\n", im->l.loc.f, loc->f, loc->line,
+ loc->col);
if (lex(&im->l, f) || parse_im(&im->l, ast))
goto end;
+ dbg("end import %s\n", im->l.loc.f);
ret = 0;
end:
+ if (ret)
+ free(fp);
+
if (f && fclose(f))
{
fprintf(stderr, "fclose(3) %s: %s\n", path, strerror(errno));
@@ -81,30 +147,19 @@ end:
return ret;
}
-static int imlit(const struct lex *l, struct prv *p)
+static int onsym(const struct lex *l, struct prv *p, const struct sym *s)
{
- const struct tk *tk = p->stk;
-
- while (!lex_eof(l, tk) && !kw(tk->s))
- if (doim(l, tk++, p))
- return -1;
-
- if (pop(l, p))
+ if (s->type != SYM_LIT)
+ {
+ errloc(s->tk, "expected literal");
return -1;
+ }
- p->stk = p->tk;
- return 1;
+ return doim(l, s->tk, p);
}
int im(const struct lex *l, struct prv *p)
{
- struct pos init =
- {
- .seq = seqs,
- .stseq = seqs,
- .step = seqs->steps
- };
-
struct fn *fn = fn_cur(p);
if (fn->im)
@@ -116,10 +171,7 @@ int im(const struct lex *l, struct prv *p)
return -1;
}
- if (push(&init, p))
- return -1;
-
fn->im = p->stk;
p->stk = p->tk;
- return 1;
+ return sym(p, onsym);
}
diff --git a/src/prc1/kw.c b/src/prc1/kw.c
index c72ac97..0f4ca9f 100644
--- a/src/prc1/kw.c
+++ b/src/prc1/kw.c
@@ -11,8 +11,10 @@ static const char *kws[] =
/* types */
"union", "struct", "constant", "alias", "prototype",
/* operators */
- "add", "subtract", "multiply", "divide", "xor", "bitor", "bitand",
- "leftshift", "rightshift", "address", "size", "call", "set",
+ "add", "subtract", "multiply", "divide", "negate", "xor", "bitor", "bitand",
+ "leftshift", "rightshift", "call", "set",
+ /* expressions */
+ "address", "cast", "contents", "offset", "size",
/* procedures */
"using", "returning",
/* built-in functions */
@@ -26,9 +28,9 @@ static const char *kws[] =
/* built-in types */
"void", "array", "pointer",
/* built-in signed types */
- "byte", "halfword", "word", "long",
+ "char", "schar", "short", "int", "long", "longlong",
/* built-in unsigned types */
- "ubyte", "uhalfword", "uword", "ulong"
+ "uchar", "ushort", "uint", "ulong", "ulonglong"
};
int kw(const char *s)
diff --git a/src/prc1/lex.c b/src/prc1/lex.c
index 736ebdd..ad7a084 100644
--- a/src/prc1/lex.c
+++ b/src/prc1/lex.c
@@ -223,6 +223,7 @@ void lex_free(struct lex *lex)
free_tk(&lex->tokens[i]);
free(lex->tokens);
+ free(lex->loc.f);
free_tk(&lex->tk);
}
@@ -240,7 +241,7 @@ int lex(struct lex *l, FILE *f)
int c = fgetc(f);
if (c == EOF)
- break;
+ return fintok(l);
else if (clex(c, l))
return -1;
}
diff --git a/src/prc1/lex.h b/src/prc1/lex.h
index 4ab3e70..758ad1d 100644
--- a/src/prc1/lex.h
+++ b/src/prc1/lex.h
@@ -9,7 +9,7 @@ enum tktype {UNDEF, ID, LIT, NUM, ANY};
struct loc
{
- const char *f;
+ char *f;
int line, col;
};
diff --git a/src/prc1/lit.c b/src/prc1/lit.c
index 1faf247..065101b 100644
--- a/src/prc1/lit.c
+++ b/src/prc1/lit.c
@@ -93,7 +93,7 @@ const struct lit *lit_push(const struct tk *tk, struct prv *p)
else if (ast->lastlit)
ast->lastlit->next = l;
- dbg("adding literal \"%s\"\n", name);
+ dbg("add literal \"%s\"\n", name);
ast->lastlit = l;
return l;
diff --git a/src/prc1/parse.c b/src/prc1/parse.c
index 1c3aba2..db4bdcc 100644
--- a/src/prc1/parse.c
+++ b/src/prc1/parse.c
@@ -4,6 +4,7 @@
#include "fn.h"
#include "lex.h"
#include "lit.h"
+#include "sym.h"
#include "prv.h"
#include "type.h"
#include <stddef.h>
@@ -45,6 +46,29 @@ static const char *expected(const struct step *s)
return s->id ? s->id : tmap[s->type];
}
+static int unexpected(const struct tk *tk)
+{
+ switch (tk->type)
+ {
+ case LIT:
+ errloc(tk, "unexpected literal \"%s\"", tk->s);
+ break;
+ case NUM:
+ errloc(tk, "unexpected number %s", tk->s);
+ break;
+ case ID:
+ errloc(tk, "unexpected %s \"%s\"", kw(tk->s) ?
+ "keyword" : "identifier", tk->s);
+ break;
+ case ANY:
+ case UNDEF:
+ errloc(tk, "%s: unreachable", __func__);
+ break;
+ }
+
+ return -1;
+}
+
static int iter(const struct lex *l, struct prv *p)
{
struct pos *pos = p->pos;
@@ -52,41 +76,28 @@ static int iter(const struct lex *l, struct prv *p)
const struct tk *tk = p->tk;
if (!pos)
- return p->entry(l, p);
+ {
+ if (lex_eof(l, p->stk))
+ return 0;
+
+ return p->entry(l, p) ? -1 : 1;
+ }
pos = &p->pos[p->i];
+ /* no rules have matched the current token */
if (!(s = pos->step))
{
- if (lex_eof(l, tk))
- return 0;
- else if (p->n > 1)
+ if (p->n > 1)
return pop(l, p) ? -1 : 1;
+ else if (lex_eof(l, tk))
+ return 0;
else
- {
- switch (tk->type)
- {
- case LIT:
- errloc(tk, "unexpected literal \"%s\"", tk->s);
- break;
- case NUM:
- errloc(tk, "unexpected number %s", tk->s);
- break;
- case ID:
- errloc(tk, "unexpected %s %s", kw(tk->s) ?
- "keyword" : "identifier", tk->s);
- break;
- case ANY:
- case UNDEF:
- errloc(tk, "%s: unreachable", __func__);
- break;
- }
-
- return -1;
- }
+ return unexpected(tk);
}
else if (lex_eof(l, tk))
{
+ /* pop all remaining rules */
if (p->stk == p->tk)
return pop(l, p) ? -1 : 1;
else if (s->type)
@@ -101,41 +112,26 @@ static int iter(const struct lex *l, struct prv *p)
}
}
+ /* rule has been completely parsed, execute */
if (!s->type)
- return pos->seq->fn(l, p);
- else if ((s->type == ID || s->type == ANY) && !s->id && kw(tk->s)
- && !s->chain)
- {
- if (tk != p->stk || !p->n)
- {
- errloc(tk, "unexpected keyword %s", tk->s);
- return -1;
- }
- else if (pop(l, p))
- return -1;
-
- pos = &p->pos[p->i];
- }
- else if ((s->type != tk->type && s->type != ANY)
+ return pos->seq->fn(l, p) ? -1 : 1;
+ /* skip if: */
+ else if (
+ /* rule type does not match */
+ s->type != tk->type
+ /* ID does not match */
|| (s->type == ID && s->id && strcmp(s->id, tk->s))
- || (s->type == ID && kw(tk->s) && s->chain))
+ /* rule does not expect a keyword */
+ || (s->type == ID && !s->id && kw(tk->s)))
{
+ /* move to next rule on no match */
pos->step = (++pos->seq)->steps;
p->tk = p->stk;
}
+ /* move to next step */
else
{
- const struct tk *next = tk + 1;
-
- if (!s->chain)
- pos->step++;
- else if (!lex_eof(l, next))
- {
- if (s->chain && kw(next->s))
- pos->step++;
- }
- else
- pos->step++;
+ pos->step++;
if (!lex_eof(l, p->tk))
p->tk++;
@@ -146,6 +142,7 @@ static int iter(const struct lex *l, struct prv *p)
static void free_prv(struct prv *p)
{
+ sym_free(p->s);
free(p->tdc);
free(p->pos);
}
diff --git a/src/prc1/parse.h b/src/prc1/parse.h
index 5d3d25a..74380ed 100644
--- a/src/prc1/parse.h
+++ b/src/prc1/parse.h
@@ -49,7 +49,7 @@ struct builtin
struct type
{
- enum {U, S, C, P, T, PTR, ARY, BUILTIN} type;
+ enum ttype {U, S, C, P, T, PTR, ARY, BUILTIN} type;
const struct tk *tk;
size_t sz, align;
int sign;
@@ -68,6 +68,37 @@ struct type
} u;
};
+struct sym
+{
+ enum symtype
+ {
+ SYM_ID,
+ SYM_TMP,
+ SYM_LIT,
+ SYM_CAST,
+ SYM_NUM,
+ SYM_ADDR,
+ SYM_SZ,
+ SYM_CNT,
+ SYM_OFF
+ } type;
+
+ struct sym *child, *next, *parent;
+ const struct tk *tk;
+
+ union
+ {
+ const struct tmp *tmp;
+ const struct type *t;
+
+ struct
+ {
+ int sign;
+ union c c;
+ } num;
+ } u;
+};
+
struct param
{
const struct tk *tk;
@@ -76,7 +107,7 @@ struct param
struct pr
{
- const struct tk *tk;
+ const struct tk *tk, *using, *returning;
struct param *params, *ret;
size_t nparams;
int variadic;
@@ -86,7 +117,6 @@ struct td
{
const struct tk *tk;
struct type *types;
- size_t ntypes;
};
struct tmp
@@ -103,6 +133,7 @@ struct fn
enum linkage {EXTERNAL, STATIC} linkage;
struct storage *lk, *ws, *gl;
struct stmt *stmts;
+ struct sym *syms;
struct tmp *tmps;
struct im *imps;
struct pr *pr;
@@ -121,6 +152,7 @@ struct lit
struct ast
{
const struct args *args;
+ const struct type *littype;
struct fn *fns;
struct lit *lits, *lastlit;
struct type *types;
diff --git a/src/prc1/pop.c b/src/prc1/pop.c
index ba2f3a1..977129e 100644
--- a/src/prc1/pop.c
+++ b/src/prc1/pop.c
@@ -1,20 +1,28 @@
#include "prv.h"
+#include "dbg.h"
#include <stdlib.h>
int pop(const struct lex *l, struct prv *p)
{
size_t n;
- struct pos *pos = NULL;
+ struct pos *pos;
+ int (*end)(const struct lex *, struct prv *);
+ const char *name;
if (!p->n)
{
fprintf(stderr, "%s: underflow\n", __func__);
return -1;
}
- else if (!(n = p->n - 1))
+
+ pos = &p->pos[p->i];
+ end = pos->end;
+ name = pos->name;
+
+ if (!(n = p->n - 1))
{
free(p->pos);
- p->pos = NULL;
+ p->pos = pos = NULL;
}
else if (!(pos = realloc(p->pos, n * sizeof *pos)))
{
@@ -22,16 +30,18 @@ int pop(const struct lex *l, struct prv *p)
return -1;
}
+ ddbg("pop rule %s [%zu]", name, p->i);
+
+ if (end)
+ ddbg(", end=%p", end);
+
+ ddbg("\n");
p->pos = pos;
p->n = n;
+ p->i--;
- if (p->n)
- {
- const struct pos *old = &p->pos[--p->i];
-
- if (old->end && old->end(l, p))
- return -1;
- }
+ if (end)
+ return end(l, p);
return 0;
}
diff --git a/src/prc1/pr.c b/src/prc1/pr.c
index 3a4221a..325617e 100644
--- a/src/prc1/pr.c
+++ b/src/prc1/pr.c
@@ -6,82 +6,29 @@
#include "parse.h"
#include "stmt.h"
#include "storage.h"
+#include "sym.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-static int prey(const struct lex *l, struct prv *p);
-static int pren(const struct lex *l, struct prv *p);
-static int pryy(const struct lex *l, struct prv *p);
-static int pryn(const struct lex *l, struct prv *p);
-static int prny(const struct lex *l, struct prv *p);
-static int prnn(const struct lex *l, struct prv *p);
+static int etc(const struct lex *, struct prv *);
+static int using(const struct lex *, struct prv *);
+static int s_returning(const struct lex *, struct prv *);
+
+static const struct seq returning =
+ {(struct step[]){{ID, "returning"}, {0}}, .fn = s_returning};
static const struct seq seqs[] =
{
- /* function definition with variadic parameters and return variable */
- {
- (struct step[])
- {
- {ID, "using"},
- {ID, NULL, 1},
- {ID, "etc",},
- {ID, "returning"},
- {ID},
- {0}
- },
- .fn = prey
- },
-
- /* function definition with variadic parameters and no return variable */
- {
- (struct step[])
- {
- {ID, "using"},
- {ID, NULL, 1},
- {ID, "etc",},
- {0}
- },
- .fn = pren
- },
-
- /* function definition with parameters and return variable */
- {
- (struct step[])
- {
- {ID, "using"},
- {ID, NULL, 1},
- {ID, "returning"},
- {ID},
- {0}
- },
- .fn = pryy
- },
-
- /* function definition with parameters, no return variable */
- {
- (struct step[])
- {
- {ID, "using"},
- {ID, NULL, 1},
- {0}
- },
-
- .fn = pryn
- },
-
- /* function definition with no parameters, with return variable */
- {
- (struct step[])
- {
- {ID, "returning"},
- {ID},
- {0}
- },
-
- .fn = prny
- },
+ {(struct step[]){{ID, "using"}, {0}}, .fn = using},
+ returning,
+ {0}
+};
+static const struct seq useqs[] =
+{
+ {(struct step[]){{ID, "etc"}, {0}}, .fn = etc},
+ returning,
{0}
};
@@ -117,7 +64,17 @@ static int param(const struct tk *tk, const struct stentry *e, struct pr *pr)
static int setret(const struct tk *tk, const struct stentry *e, struct pr *pr)
{
- if (!(pr->ret = malloc(sizeof *pr->ret)))
+ const struct tk *prm = findparam(tk->s, pr);
+
+ if (prm)
+ {
+ const struct loc *loc = &prm->loc;
+
+ errloc(tk, "return value \"%s\" already listed as "
+ "parameter at %s:%d:%d", tk->s, loc->f, loc->line, loc->col);
+ return -1;
+ }
+ else if (!(pr->ret = malloc(sizeof *pr->ret)))
{
perror("malloc(3)");
return -1;
@@ -133,196 +90,171 @@ static int finalize(const struct lex *l, struct prv *p)
const struct pr *pr = fn->pr;
struct pos init =
{
- .seq = stmts,
- .stseq = stmts,
- .step = stmts->steps
+ .name = __func__,
+ .seq = stmts
};
- if (p->proto)
+ if (pr->using && !pr->params)
+ {
+ errloc(p->stk, "missing parameters");
+ return -1;
+ }
+ else if (pr->returning && !pr->ret)
+ {
+ errloc(p->stk, "missing return variable");
+ return -1;
+ }
+ else if (p->proto)
{
if (pop(l, p))
return -1;
- fputc('\t', stderr);
+ dbg("\t");
}
else if (push(&init, p))
return -1;
- dbg("\tadding procedure using %zu%s parameters and%s return value\n",
- pr->nparams, pr->variadic ? " variadic" : "", pr->ret ? "" : " no");
+ dbg("\tadd procedure to %s using %zu%s parameters and%s return value\n",
+ fn->tk->s, pr->nparams, pr->variadic ? " variadic" : "",
+ pr->ret ? "" : " no");
p->stk = p->tk;
- return 1;
+ return 0;
}
-static int prret(const struct lex *l, const struct tk *tk, struct prv *p)
+static int check(const struct lex *l, struct prv *p, const struct sym *s,
+ int param, const struct stentry **out)
{
const struct fn *fn = fn_cur(p);
- struct pr *pr = fn->pr;
- const char *s = tk->s;
- const struct storage *lk = fn->lk, *gl = fn->gl;
+ const struct tk *tk = s->tk;
const struct stentry *e, *gle;
- const struct tk *prm;
+ const struct storage *lk = fn->lk, *gl = fn->gl;
- if (!lk || !(e = storage_find(s, lk)))
+ if (s->type != SYM_ID)
{
- errloc(tk, "return value \"%s\" not in %s", s, tk->s);
+ errloc(tk, "expected identifier");
return -1;
}
- else if (gl && (gle = storage_find(s, gl)))
+ else if (!lk || !(e = storage_find(tk->s, lk)))
{
- const struct loc *loc = &gle->tk->loc;
-
- errloc(tk, "return value \"%s\" also in %s at %s:%d:%d", s, gl->name,
- loc->f, loc->line, loc->col);
- return -1;
+ if (param && p->proto)
+ {
+ /* ambiguous syntax: param might be confused
+ * with next custom type. */
+ p->stk = s->tk;
+ return pop(l, p);
+ }
+ else
+ {
+ errloc(tk, "\"%s\" not in linkage section", tk->s);
+ return -1;
+ }
}
- else if ((prm = findparam(s, pr)))
+ else if (gl && (gle = storage_find(tk->s, gl)))
{
- const struct loc *loc = &prm->loc;
+ const struct loc *loc = &gle->tk->loc;
- errloc(tk, "return value \"%s\" already listed as "
- "parameter at %s:%d:%d", tk->s, loc->f, loc->line, loc->col);
+ errloc(tk, "\"%s\" also in %s at %d:%d", s, gl->name,
+ loc->line, loc->col);
return -1;
}
- else if (setret(tk, e, pr))
- return -1;
- return finalize(l, p);
+ *out = e;
+ return 0;
}
-static const struct tk *prparams(const struct lex *l, struct prv *p, int *ret)
+static int usym(const struct lex *l, struct prv *p, const struct sym *s)
{
- const struct tk *tk = p->stk + 1;
+ const struct tk *tk = s->tk;
const struct fn *fn = fn_cur(p);
- struct pr *pr = fn->pr;
-
- if (ret)
- *ret = 0;
-
- for (;;)
- {
- const struct storage *lk = fn->lk, *gl = fn->gl;
- const struct stentry *e, *gle;
- const struct tk *prm;
- const char *s;
+ const struct stentry *e = NULL;
- if (lex_eof(l, tk))
- return tk;
- else if (!strcmp((s = tk->s), "returning") && ret)
- {
- *ret = 1;
- return ++tk;
- }
- else if (!strcmp(s, "etc"))
- {
- if (pr->variadic)
- {
- errloc(tk, "keyword \"etc\" may only appear once as a "
- "parameter");
- return NULL;
- }
-
- pr->variadic = tk++ - p->stk;
- }
- else if (kw(s))
- return tk;
- else if (pr->variadic)
- {
- errloc(tk, "keyword \"etc\" must appear as the last parameter");
- return NULL;
- }
- else if ((prm = findparam(s, pr)))
- {
- const struct loc *loc = &prm->loc;
-
- errloc(tk, "parameter \"%s\" already listed at %d:%d", s,
- loc->line, loc->col);
- return NULL;
- }
- else if (!lk || !(e = storage_find(s, lk)))
- {
- if (p->proto)
- {
- /* ambiguous syntax: param might be confused
- * with next custom type. */
- p->tk = p->stk + pr->nparams + 1;
- return tk;
- }
- else
- {
- errloc(tk, "parameter \"%s\" not in %s", s, tk->s);
- return NULL;
- }
- }
- else if (gl && (gle = storage_find(s, gl)))
- {
- const struct loc *loc = &gle->tk->loc;
-
- errloc(tk, "parameter \"%s\" also in %s at %d:%d", s, gl->name,
- loc->line, loc->col);
- return NULL;
- }
- else if (param(tk, e, pr))
- return NULL;
- else
- tk++;
- }
+ if (check(l, p, s, 1, &e))
+ return -1;
+ else if (e)
+ return param(tk, e, fn->pr);
- return tk;
+ return 0;
}
-static int prey(const struct lex *l, struct prv *p)
+static int etc(const struct lex *l, struct prv *p)
{
- int ret;
- const struct tk *tk = prparams(l, p, &ret);
+ const struct fn *fn = fn_cur(p);
+ struct pr *pr = fn->pr;
- if (!tk)
+ if (pr->variadic)
+ {
+ errloc(p->stk, "procedure for \"%s\" already set as variadic",
+ fn->tk->s);
return -1;
- else if (ret)
- return prret(l, tk, p);
+ }
- return finalize(l, p);
+ pr->variadic = 1;
+ reset(p);
+ return 0;
}
-static int pren(const struct lex *l, struct prv *p)
+static int rsym(const struct lex *l, struct prv *p, const struct sym *s)
{
- const struct tk *tk = prparams(l, p, NULL);
+ const struct tk *tk = s->tk;
+ const struct fn *fn = fn_cur(p);
+ const struct stentry *e = NULL;
- if (!tk)
+ if (check(l, p, s, 0, &e))
return -1;
+ else if (e)
+ {
+ if (setret(tk, e, fn->pr))
+ return -1;
+
+ return pop(l, p);
+ }
- return finalize(l, p);
+ return 0;
}
-static int pryy(const struct lex *l, struct prv *p)
+static int s_returning(const struct lex *l, struct prv *p)
{
- int ret;
- const struct tk *tk = prparams(l, p, &ret);
+ const struct fn *fn = fn_cur(p);
+ struct pr *pr = fn->pr;
+ const struct tk *r = pr->returning;
- if (!tk)
+ if (r)
+ {
+ const struct loc *loc = &r->loc;
+
+ errloc(p->stk, "\"returning\" for \"%s\" already set at %d:%d",
+ fn->tk->s, loc->line, loc->col);
return -1;
- else if (ret)
- return prret(l, tk, p);
+ }
- return finalize(l, p);
+ pr->returning = p->stk;
+ return sym(p, rsym);
}
-static int pryn(const struct lex *l, struct prv *p)
+static int using(const struct lex *l, struct prv *p)
{
- if (!prparams(l, p, NULL))
- return -1;
+ const struct fn *fn = fn_cur(p);
+ struct pr *pr = fn->pr;
+ const struct tk *u = pr->using;
+ struct pos init =
+ {
+ .name = __func__,
+ .seq = useqs
+ };
- return finalize(l, p);
-}
+ if (u)
+ {
+ const struct loc *loc = &u->loc;
-static int prny(const struct lex *l, struct prv *p)
-{
- return prret(l, p->stk + 1, p);
-}
+ errloc(p->stk, "\"using\" for \"%s\" already set at %d:%d", fn->tk->s,
+ loc->line, loc->col);
+ return -1;
+ }
+ else if (push(&init, p))
+ return -1;
-static int prnn(const struct lex *l, struct prv *p)
-{
- return finalize(l, p);
+ pr->using = p->stk;
+ return sym(p, usym);
}
void pr_free(struct pr *pr)
@@ -338,13 +270,13 @@ void pr_free(struct pr *pr)
int pr(const struct lex *l, struct prv *p)
{
- const struct tk *tk = p->tk - 1, *next = p->tk;
+ const struct tk *tk = p->stk;
struct fn *fn = fn_cur(p);
struct pos init =
{
+ .name = __func__,
.seq = seqs,
- .stseq = seqs,
- .step = seqs->steps
+ .end = finalize
};
if (fn->pr)
@@ -363,13 +295,9 @@ int pr(const struct lex *l, struct prv *p)
*fn->pr = (struct pr){.tk = tk};
- /* on no parameters or return values, go directly to next sequences list. */
- if (lex_eof(l, next)
- || (strcmp(next->s, "using") && strcmp(next->s, "returning")))
- return prnn(l, p);
- else if (push(&init, p))
+ if (push(&init, p))
return -1;
p->stk = p->tk;
- return 1;
+ return 0;
}
diff --git a/src/prc1/prc1.c b/src/prc1/prc1.c
index 2822cc5..634608b 100644
--- a/src/prc1/prc1.c
+++ b/src/prc1/prc1.c
@@ -41,7 +41,14 @@ int main(int argc, char *argv[])
fname = args.src;
}
- l.loc.f = fname;
+ if (!(l.loc.f = malloc(strlen(fname) + 1)))
+ {
+ perror("malloc(3)");
+ goto end;
+ }
+ else
+ strcpy(l.loc.f, fname);
+
l.args = a.args = &args;
if (lex(&l, f) || parse(&l, &a) || cgen(&a, &c))
diff --git a/src/prc1/print.c b/src/prc1/print.c
index abdb149..604c2a3 100644
--- a/src/prc1/print.c
+++ b/src/prc1/print.c
@@ -5,99 +5,149 @@
#include "parse.h"
#include "prv.h"
#include "stmt.h"
-#include "storage.h"
+#include "sym.h"
#include "type.h"
#include <stdlib.h>
-#include <string.h>
-static int entry(const struct lex *l, const struct tk *tk, struct print *pr,
- struct prv *p)
+static int etc(const struct lex *, struct prv *);
+
+static const struct seq seqs[] =
+{
+ {(struct step[]){{ID, "etc"}, {0}}, .fn = etc},
+ {0}
+};
+
+static int invalid(const struct sym *s, const struct type *t)
+{
+ char *tn = type_name(t);
+
+ if (tn)
+ errloc(s->tk, "cannot print type \"%s\"", tn);
+
+ free(tn);
+ return -1;
+}
+
+static const struct sym *inner(const struct sym *s)
+{
+ for (; s; s = s->child)
+ if (!s->child)
+ break;
+
+ return s;
+}
+
+static int setptr(struct prv *p, const struct sym *s, struct prisym *ps,
+ const struct type *t)
{
- size_t n = pr->nentries + 1;
- struct prientry *entries;
- const struct stentry *stentry = NULL;
const struct fn *fn = fn_cur(p);
- const struct lit *lit = NULL;
+ const struct stentry *e = fn_var(fn, s->tk);
- if (tk->type == ID)
+ if (!e)
{
- const struct type *t = NULL;
+ errloc(s->tk, "undefined reference to \"%s\"", s->tk->s);
+ return -1;
+ }
+
+ ps->type = PRS_PTR;
+ ps->u.e = e;
+ return 0;
+}
+
+static int settype(struct prv *p, const struct sym *s, struct prisym *ps)
+{
+ const struct type *t = sym_type(p, s);
+ const struct tk *tk = s->tk;
- if ((t = type_find(fn, tk->s)))
+ if (!t)
+ {
+ errloc(tk, "undefined reference to \"%s\"", tk->s);
+ return -1;
+ }
+ else if (inner(s)->type == SYM_LIT)
+ {
+ const struct lit *l = lit_push(tk, p);
+
+ if (!l)
+ return -1;
+ else if (t == p->ast->littype)
{
- if (t->type != C)
- {
- errloc(tk, "type \"%s\" not a constant", tk->s);
- return -1;
- }
- else if (!(lit = lit_push(t->tk, p)))
- return -1;
+ ps->type = PRS_LIT;
+ ps->u.lit = l;
}
- else if (!(stentry = fn_var(fn, tk)))
+ else
{
- errloc(tk, "undefined reference to \"%s\"", tk->s);
- return -1;
+ ps->type = PRS_NAM;
+ ps->u.name = l->name;
}
}
- else if (tk->type == LIT && !(lit = lit_push(tk, p)))
- return -1;
+ else
+ switch (t->type)
+ {
+ case U:
+ case S:
+ case T:
+ case ARY:
+ return invalid(s, t);
+ case C:
+ case BUILTIN:
+ fprintf(stderr, "%s: TODO\n", __func__);
+ return -1;
+ case P:
+ ps->type = PRS_NAM;
+ ps->u.name = s->tk->s;
+ break;
+ case PTR:
+ return setptr(p, s, ps, t);
+ }
- if (!(entries = realloc(pr->entries, n * sizeof *entries)))
+ return 0;
+}
+
+static int onsym(const struct lex *l, struct prv *p, const struct sym *s)
+{
+ struct stmt *stmt = stmt_cur(p);
+ struct print *pr = &stmt->u.print;
+ size_t n = pr->nsyms + 1;
+ struct prisym *syms, *nsym;
+
+ if (!(syms = realloc(pr->syms, n * sizeof *syms)))
{
perror("realloc(3)");
return -1;
}
- pr->entries = entries;
- pr->entries[pr->nentries++] = (struct prientry)
- {
- .tk = tk,
- .lit = lit,
- .entry = stentry
- };
+ pr->syms = syms;
+ nsym = &syms[pr->nsyms++];
+ *nsym = (struct prisym){.s = s};
+ return settype(p, s, nsym);
+}
+
+static int etc(const struct lex *l, struct prv *p)
+{
+ struct stmt *stmt = stmt_cur(p);
+ struct print *pr = &stmt->u.print;
+ pr->skipln = 1;
+ reset(p);
return 0;
}
void print_free(struct print *pr)
{
- free(pr->entries);
+ free(pr->syms);
}
-int print(const struct lex *l, struct prv *p,
- int (*fn)(const struct lex *, const struct prv *, const struct print *))
+int print(const struct lex *l, struct prv *p)
{
- const struct tk *tk = p->stk + 1;
- struct print pr = {0};
- struct pos *pos = &p->pos[p->i];
- int eof;
-
- if (lex_eof(l, tk))
+ struct pos init =
{
- errloc(tk - 1, "incomplete %s statement", p->stk->s);
- return -1;
- }
-
- for (;;)
- if (entry(l, tk, &pr, p))
- goto failure;
- else if ((eof = lex_eof(l, ++tk)) || kw(tk->s))
- break;
-
- if (eof || strcmp(tk->s, "etc"))
- pr.println = 1;
- else if (!eof)
- tk++;
-
- if (fn(l, p, &pr))
- goto failure;
+ .name = __func__,
+ .seq = seqs
+ };
- pos->seq = pos->stseq = stmts;
- pos->step = stmts->steps;
- p->stk = tk;
- return 1;
+ if (push(&init, p))
+ return -1;
-failure:
- print_free(&pr);
- return -1;
+ return sym(p, onsym);
}
diff --git a/src/prc1/print.h b/src/prc1/print.h
index 950e0bc..061ead4 100644
--- a/src/prc1/print.h
+++ b/src/prc1/print.h
@@ -3,24 +3,31 @@
#include "cgen.h"
#include "lex.h"
+#include "prv.h"
#include <stddef.h>
-struct prientry
+struct prisym
{
- const struct tk *tk;
- const struct lit *lit;
- const struct stentry *entry;
+ enum {PRS_LIT, PRS_NAM, PRS_STR, PRS_PTR, PRS_NUM} type;
+ const struct sym *s;
+
+ union
+ {
+ const struct lit *lit;
+ const struct stentry *e;
+ const char *name;
+ } u;
};
struct print
{
- struct prientry *entries;
- size_t nentries;
- int println;
+ struct prisym *syms;
+ size_t nsyms;
+ int skipln;
};
-int print(const struct lex *l, struct prv *p,
- int (*fn)(const struct lex *, const struct prv *, const struct print *));
+int print(const struct lex *l, struct prv *p);
+int print_cgen(const struct print *pr, struct cgen *c, const char *f);
void print_free(struct print *p);
#endif
diff --git a/src/prc1/prv.h b/src/prc1/prv.h
index c0c8930..e3658bc 100644
--- a/src/prc1/prv.h
+++ b/src/prc1/prv.h
@@ -10,11 +10,11 @@ struct step
{
enum tktype type;
const char *id;
- int chain;
};
struct pos
{
+ const char *name;
const struct seq *seq, *stseq;
const struct step *step;
int (*end)(const struct lex *, struct prv *);
@@ -29,23 +29,24 @@ struct prv
struct ast *ast;
struct type *ag, *t;
struct fn *proto;
- size_t n, i, block;
+ size_t n, i, block, cast;
+ struct sym *s;
int (*entry)(const struct lex *, struct prv *);
int (*type)(const struct lex *, struct prv *p, const struct type *t);
+ int (*sym)(const struct lex *, struct prv *, const struct sym *);
};
struct seq
{
const struct step *steps;
int (*fn)(const struct lex *l, struct prv *p);
- int (*end)(const struct lex *l, struct prv *p);
- const char *chain;
};
int kw(const char *s);
int prev(const struct prv *p);
int push(const struct pos *pos, struct prv *p);
int pop(const struct lex *l, struct prv *p);
+void reset(struct prv *p);
char *sdup(const char *s);
#endif
diff --git a/src/prc1/push.c b/src/prc1/push.c
index 1a9056d..2354305 100644
--- a/src/prc1/push.c
+++ b/src/prc1/push.c
@@ -1,10 +1,11 @@
#include "prv.h"
+#include "dbg.h"
#include <stdlib.h>
int push(const struct pos *pos, struct prv *p)
{
size_t n = p->n + 1;
- struct pos *npos = realloc(p->pos, n * sizeof *npos);
+ struct pos *npos = realloc(p->pos, n * sizeof *npos), *pp;
if (!npos)
{
@@ -15,13 +16,21 @@ int push(const struct pos *pos, struct prv *p)
{
struct pos *prev = &npos[p->n - 1];
- prev->end = prev->seq->end;
prev->seq = prev->stseq;
prev->step = prev->seq->steps;
p->i++;
}
- npos[p->n++] = *pos;
+ ddbg("push rule %s [%zu]", pos->name, p->n);
+
+ if (pos->end)
+ ddbg(", end=%p", pos->end);
+
+ ddbg("\n");
+ pp = &npos[p->n++];
+ *pp = *pos;
+ pp->stseq = pp->seq;
+ pp->step = pp->seq->steps;
p->pos = npos;
return 0;
}
diff --git a/src/prc1/reset.c b/src/prc1/reset.c
new file mode 100644
index 0000000..53145f1
--- /dev/null
+++ b/src/prc1/reset.c
@@ -0,0 +1,10 @@
+#include "prv.h"
+
+void reset(struct prv *p)
+{
+ struct pos *pos = &p->pos[p->i];
+
+ pos->seq = pos->stseq;
+ pos->step = pos->seq->steps;
+ p->stk = p->tk;
+}
diff --git a/src/prc1/set.c b/src/prc1/set.c
index 3b83fc9..bac787e 100644
--- a/src/prc1/set.c
+++ b/src/prc1/set.c
@@ -8,12 +8,23 @@
#include "prv.h"
#include "stmt.h"
#include "storage.h"
+#include "sym.h"
#include "type.h"
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
+static int to(const struct lex *, struct prv *);
+
+static const struct seq seqs[] =
+{
+ {(struct step[]){{ID, "to"}, {0}}, .fn = to},
+ {0}
+};
+
+#if 0
+
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);
@@ -132,29 +143,6 @@ static unsigned long long tonum(const char *s)
return v;
}
-static int dst(const struct lex *l, const struct tk *tk, struct set *s,
- struct prv *p)
-{
- const struct stentry *e = fn_var(fn_cur(p), tk);
- size_t n = s->ndsts + 1;
- struct setdst *dsts;
-
- if (!e)
- {
- errloc(tk, "undefined reference to \"%s\"", tk->s);
- return -1;
- }
- else if (!(dsts = realloc(s->dsts, n * sizeof *dsts)))
- {
- perror("realloc(3)");
- return -1;
- }
-
- s->dsts = dsts;
- s->dsts[s->ndsts++] = (struct setdst){.entry = e};
- return 0;
-}
-
static int checkzero(const struct tk *tk, const struct set *s,
unsigned long long v)
{
@@ -260,7 +248,7 @@ static int mv(const struct lex *l, struct prv *p)
}
}
- dbg("\t\tadding set ");
+ dbg("\t\tadd set ");
for (size_t i = 0; i < s->ndsts; i++)
dbg("%s ", s->dsts[i].entry->tk->s);
@@ -308,7 +296,7 @@ static int maddr(const struct lex *l, struct prv *p)
s->type = SET_ADDR;
s->src = e;
p->stk = ++tk;
- dbg("\t\tadding set ");
+ dbg("\t\tadd set ");
for (size_t i = 0; i < s->ndsts; i++)
dbg("%s ", s->dsts[i].entry->tk->s);
@@ -369,7 +357,7 @@ static int msz(const struct lex *l, struct prv *p)
s->type = SET_VAL;
p->stk = ++tk;
- dbg("\t\tadding set ");
+ dbg("\t\tadd set ");
for (size_t i = 0; i < s->ndsts; i++)
dbg("%s ", s->dsts[i].entry->tk->s);
@@ -392,7 +380,7 @@ static int mimb(const struct lex *l, struct prv *p)
/* skip "to" */
tk++;
- dbg("\t\tadding set ");
+ dbg("\t\tadd set ");
for (size_t i = 0; i < s->ndsts; i++)
dbg("%s ", s->dsts[i].entry->tk->s);
@@ -429,12 +417,6 @@ static int mimb(const struct lex *l, struct prv *p)
return 1;
}
-void set_free(struct set *m)
-{
- if (m)
- free(m->dsts);
-}
-
static int cg_val(const struct set *s, const struct stentry *dst,
struct cgen *c)
{
@@ -511,43 +493,92 @@ int set_cgen(const struct set *s, struct cgen *c)
return 0;
}
-int set(const struct lex *l, struct prv *p)
+static int to(const struct lex *l, struct prv *p)
{
- const struct tk *next = p->tk;
- const char *ns;
- struct fn *fn = fn_cur(p);
- size_t n = fn->nstmts + 1;
- struct stmt *stmts;
+ fprintf(stderr, "%s: TODO\n", __func__);
+ return -1;
+}
- if (lex_eof(l, next))
+static int dst(const struct lex *l, struct prv *p, const struct sym *s)
+{
+ const struct fn *fn = fn = fn_cur(p);
+ struct stmt *stmt = stmt_cur(p);
+
+ if (sym_rval(s))
{
- errloc(next - 1, "incomplete set statement");
+ errloc(p->stk, "expression is not assignable");
return -1;
}
- else if (kw((ns = next->s)))
+
+ fprintf(stderr, "%s: TODO\n", __func__);
+ return -1;
+#if 0
+ const struct stentry *e;
+ size_t n = s->ndsts + 1;
+ struct setdst *dsts;
+
+ if (rval())
+
+ if (!(e = fn_var(fn, )))
{
- errloc(next, "incomplete set statement");
+ errloc(tk, "undefined reference to \"%s\"", tk->s);
return -1;
}
- else if (!(stmts = realloc(fn->stmts, n * sizeof *stmts)))
+ else if (!(dsts = realloc(s->dsts, n * sizeof *dsts)))
{
perror("realloc(3)");
return -1;
}
- fn->stmts = stmts;
- fn->stmts[fn->nstmts++] = (struct stmt){.type = SET};
+ s->dsts = dsts;
+ s->dsts[s->ndsts++] = (struct setdst){.entry = e};
+ return 0;
+#endif
+}
+#endif
+
+static int to(const struct lex *l, struct prv *p)
+{
+ fprintf(stderr, "%s: TODO\n", __func__);
+ return -1;
+}
+
+static int finalize(const struct lex *l, struct prv *p)
+{
+ fprintf(stderr, "%s: TODO\n", __func__);
+ return -1;
+}
+void set_free(struct set *m)
+{
+ if (m)
+ free(m->dsts);
+}
+
+int set(const struct lex *l, struct prv *p)
+{
+ struct fn *fn = fn_cur(p);
+ size_t n = fn->nstmts + 1;
+ struct stmt *stmts;
struct pos init =
{
+ .name = __func__,
.seq = seqs,
- .stseq = seqs,
- .step = seqs->steps
+ .end = finalize
};
+ if (!(stmts = realloc(fn->stmts, n * sizeof *stmts)))
+ {
+ perror("realloc(3)");
+ return -1;
+ }
+
+ fn->stmts = stmts;
+ fn->stmts[fn->nstmts++] = (struct stmt){.type = SET};
+
if (push(&init, p))
return -1;
- p->stk = p->tk;
- return 1;
+ /* TODO */
+ return sym(p, NULL);
}
diff --git a/src/prc1/set.h b/src/prc1/set.h
index fdd067a..985f28b 100644
--- a/src/prc1/set.h
+++ b/src/prc1/set.h
@@ -3,7 +3,6 @@
#include "cgen.h"
#include "lex.h"
-#include "parse.h"
#include "prv.h"
#include "storage.h"
#include <stddef.h>
diff --git a/src/prc1/stmt.c b/src/prc1/stmt.c
index 8d2fdd4..babe5a8 100644
--- a/src/prc1/stmt.c
+++ b/src/prc1/stmt.c
@@ -14,7 +14,8 @@ void stmt_free(struct stmt *s)
switch (s->type)
{
case DISPLAY:
- display_free(&s->u.display);
+ case WARN:
+ print_free(&s->u.print);
break;
case SET:
set_free(&s->u.set);
@@ -22,9 +23,6 @@ void stmt_free(struct stmt *s)
case CALL:
call_free(&s->u.call);
break;
- case WARN:
- warn_free(&s->u.warn);
- break;
case FROM:
from_free(&s->u.from);
break;
@@ -39,13 +37,13 @@ int stmt_cgen(const struct stmt *s, struct cgen *c)
switch (s->type)
{
case DISPLAY:
- return display_cgen(&s->u.display, c);
+ return display_cgen(&s->u.print, c);
case SET:
return set_cgen(&s->u.set, c);
case CALL:
return call_cgen(&s->u.call, c);
case WARN:
- return warn_cgen(&s->u.warn, c);
+ return warn_cgen(&s->u.print, c);
case FROM:
return from_cgen(&s->u.from, c);
case END:
@@ -65,14 +63,8 @@ struct stmt *stmt_cur(const struct prv *p)
const struct seq stmts[] =
{
- {(struct step[]){
- {ID, "display"}, {ANY, NULL, 1}, {ID, "etc"}, {0}}, .fn = display},
- {(struct step[])
- {{ID, "display"}, {ANY, NULL, 1}, {0}}, .fn = display},
- {(struct step[]){
- {ID, "warn"}, {ANY, NULL, 1}, {ID, "etc"}, {0}}, .fn = warn},
- {(struct step[])
- {{ID, "warn"}, {ANY, NULL, 1}, {0}}, .fn = warn},
+ {(struct step[]){{ID, "display"}, {0}}, .fn = display},
+ {(struct step[]){{ID, "warn"}, {0}}, .fn = warn},
{(struct step[])
{{ID, "from"}, {ANY}, {ID, "to"}, {ANY}, {ID, "using"}, {ID},
{ID, "by"}, {ANY}, {0}}, .fn = from_idby},
@@ -84,9 +76,9 @@ const struct seq stmts[] =
.fn = from_id},
{(struct step[])
{{ID, "from"}, {ANY}, {ID, "to"}, {ANY}, {0}}, .fn = from},
+ {(struct step[]){{ID, "call"}, {0}}, .fn = call},
{(struct step[]){{ID, "exit"}, {0}}, .fn = s_exit},
{(struct step[]){{ID, "set"}, {0}}, .fn = set},
- {(struct step[]){{ID, "call"}, {0}}, .fn = call},
{(struct step[]){{ID, "end"}, {0}}, .fn = end},
{0}
};
diff --git a/src/prc1/stmt.h b/src/prc1/stmt.h
index 5cc650d..c23239d 100644
--- a/src/prc1/stmt.h
+++ b/src/prc1/stmt.h
@@ -2,13 +2,12 @@
#define STMTS_H
#include "cgen.h"
+#include "print.h"
#include "prv.h"
#include "call.h"
-#include "display.h"
#include "end.h"
#include "from.h"
#include "set.h"
-#include "warn.h"
struct stmt
{
@@ -26,10 +25,9 @@ struct stmt
union
{
- struct display display;
+ struct print print;
struct set set;
struct call call;
- struct warn warn;
struct from from;
struct end end;
} u;
diff --git a/src/prc1/storage.c b/src/prc1/storage.c
index 828ca1b..5ffff92 100644
--- a/src/prc1/storage.c
+++ b/src/prc1/storage.c
@@ -116,9 +116,7 @@ static int stpush(const struct lex *l, struct prv *p, const struct tk *name,
}
}
- if (pop(l, p))
- goto end;
- else if (!(entries = realloc(st->entries, n * sizeof *entries)))
+ if (!(entries = realloc(st->entries, n * sizeof *entries)))
{
perror("realloc(3)");
goto end;
@@ -139,12 +137,12 @@ static int stpush(const struct lex *l, struct prv *p, const struct tk *name,
p->stk = p->tk;
if (p->proto)
- fputc('\t', stderr);
+ dbg("\t");
- dbg("\tadding %s (%d:%d) to %s, type %s, offset %zu, size %zu\n",
+ dbg("\tadd %s (%d:%d) to %s, type %s, offset %zu, size %zu\n",
name->s, loc->line, loc->col, st->name, tname,
entries[st->nentries - 1].offset, t->sz);
- ret = 1;
+ ret = 0;
end:
free(tname);
return ret;
@@ -188,9 +186,8 @@ int storage(const struct lex *l, struct prv *p, const char *name, int check,
struct storage *st = NULL;
struct pos init =
{
- .seq = seqs,
- .stseq = seqs,
- .step = seqs->steps
+ .name = __func__,
+ .seq = seqs
};
if (*out)
@@ -212,7 +209,7 @@ int storage(const struct lex *l, struct prv *p, const char *name, int check,
*st = (struct storage){.name = name, .tk = p->stk, .check = check};
*out = p->st = st;
p->stk = p->tk;
- return 1;
+ return 0;
failure:
free(st);
diff --git a/src/prc1/sym.c b/src/prc1/sym.c
new file mode 100644
index 0000000..fb67f14
--- /dev/null
+++ b/src/prc1/sym.c
@@ -0,0 +1,478 @@
+#include "sym.h"
+#include "errloc.h"
+#include "fn.h"
+#include "lex.h"
+#include "parse.h"
+#include "prv.h"
+#include "storage.h"
+#include "type.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+static int addr(const struct lex *, struct prv *);
+static int cnt(const struct lex *, struct prv *);
+static int off(const struct lex *, struct prv *);
+static int szof(const struct lex *, struct prv *);
+static int idof(const struct lex *, struct prv *);
+static int numof(const struct lex *, struct prv *);
+static int cast(const struct lex *, struct prv *);
+static int to(const struct lex *, struct prv *);
+static int lit(const struct lex *, struct prv *);
+static int num(const struct lex *, struct prv *);
+static int id(const struct lex *, struct prv *);
+static int push_to(struct prv *);
+
+static const struct seq seqs[] =
+{
+ {(struct step[]){{ID, "address"}, {ID, "of"}, {0}}, .fn = addr},
+ {(struct step[]){{ID, "contents"}, {ID, "of"}, {0}}, .fn = cnt},
+ {(struct step[]){{ID, "offset"}, {ID, "of"}, {0}}, .fn = off},
+ {(struct step[]){{ID, "size"}, {ID, "of"}, {0}}, .fn = szof},
+ {(struct step[]){{ID, "cast"}, {0}}, .fn = cast},
+ {(struct step[]){{ID}, {ID, "of"}, {0}}, .fn = idof},
+ {(struct step[]){{NUM}, {ID, "of"}, {0}}, .fn = numof},
+ {(struct step[]){{LIT}, {0}}, .fn = lit},
+ {(struct step[]){{NUM}, {0}}, .fn = num},
+ {(struct step[]){{ID}, {0}}, .fn = id},
+ {0}
+};
+
+static const struct seq cast_seqs[] =
+{
+ {(struct step[]){{ID, "to"}, {0}}, .fn = to},
+ {0}
+};
+
+static void queue(struct prv *p, struct sym *s)
+{
+ struct sym *ss = p->s;
+
+ if (!ss)
+ p->s = s;
+ else
+ {
+ while (ss->child)
+ ss = ss->child;
+
+ ss->child = s;
+ s->parent = ss;
+ }
+
+ reset(p);
+}
+
+static int pushsym(struct prv *p, enum symtype t)
+{
+ struct sym *s = malloc(sizeof *s);
+
+ if (!s)
+ {
+ perror("malloc(3)");
+ return -1;
+ }
+
+ *s = (struct sym){.type = t, .tk = p->stk};
+ queue(p, s);
+ return 0;
+}
+
+static int addr(const struct lex *l, struct prv *p)
+{
+ return pushsym(p, SYM_ADDR);
+}
+
+static int cnt(const struct lex *l, struct prv *p)
+{
+ return pushsym(p, SYM_CNT);
+}
+
+static int off(const struct lex *l, struct prv *p)
+{
+ return pushsym(p, SYM_OFF);
+}
+
+static int szof(const struct lex *l, struct prv *p)
+{
+ return pushsym(p, SYM_SZ);
+}
+
+static void insert(struct fn *fn, struct sym *s)
+{
+ struct sym *ss = fn->syms;
+
+ while (ss && ss->next)
+ ss = ss->next;
+
+ if (!ss)
+ fn->syms = s;
+ else
+ ss->next = s;
+}
+
+static int symbol(const struct sym *s)
+{
+ switch (s->type)
+ {
+ case SYM_ID:
+ case SYM_TMP:
+ case SYM_LIT:
+ case SYM_NUM:
+ return 1;
+
+ case SYM_CAST:
+ case SYM_ADDR:
+ case SYM_SZ:
+ case SYM_CNT:
+ case SYM_OFF:
+ break;
+ }
+
+ return 0;
+}
+
+static struct sym *getsym(struct sym *s)
+{
+ for (struct sym *ss = s; ss; ss = ss->child)
+ if (symbol(ss))
+ return ss;
+
+ return NULL;
+}
+
+static int idof(const struct lex *l, struct prv *p)
+{
+ fprintf(stderr, "%s: TODO\n", __func__);
+ reset(p);
+ return -1;
+}
+
+static int numof(const struct lex *l, struct prv *p)
+{
+ fprintf(stderr, "%s: TODO\n", __func__);
+ reset(p);
+ return -1;
+}
+
+static struct sym *inner(struct sym *s)
+{
+ struct sym *ret = NULL;
+
+ for (; s; s = s->child)
+ if (s->type == SYM_CAST && !s->u.t)
+ ret = s;
+
+ return ret;
+}
+
+static struct sym *resolve(const struct sym *s)
+{
+ fprintf(stderr, "%s: TODO\n", __func__);
+ return NULL;
+}
+
+static int run(const struct lex *l, struct prv *p)
+{
+ struct fn *fn = fn_cur(p);
+ struct sym *s = p->s;
+
+ insert(fn, s);
+ p->s = NULL;
+
+ if (getsym(s))
+ return p->sym(l, p, s);
+
+ errloc(p->stk - 1, "expected identifier, literal or number");
+ return -1;
+}
+
+static int totype(const struct lex *l, struct prv *p, const struct type *t)
+{
+ struct sym *s = inner(p->s);
+
+ if (!s || s->u.t)
+ {
+ errloc(p->tk - 1, "incomplete cast");
+ return -1;
+ }
+
+ s->u.t = t;
+
+ if (pop(l, p))
+ return -1;
+
+ return !inner(p->s) && getsym(p->s) ? run(l, p) : 0;
+}
+
+static int to(const struct lex *l, struct prv *p)
+{
+ return type(l, p, totype);
+}
+
+static int endcast(const struct lex *l, struct prv *p)
+{
+ struct sym *s = inner(p->s);
+
+ if (!p->cast--)
+ {
+ errloc(p->tk - 1, "incomplete cast");
+ return -1;
+ }
+ else if (s)
+ {
+ if (lex_eof(l, p->tk))
+ {
+ errloc(p->tk - 1, "incomplete cast");
+ return -1;
+ }
+
+ return push_to(p);
+ }
+
+ return 0;
+}
+
+static int cast(const struct lex *l, struct prv *p)
+{
+ p->cast++;
+ return pushsym(p, SYM_CAST);
+}
+
+static int push_to(struct prv *p)
+{
+ struct pos init =
+ {
+ .name = __func__,
+ .seq = cast_seqs,
+ .end = endcast
+ };
+
+ return push(&init, p);
+}
+
+static int lit(const struct lex *l, struct prv *p)
+{
+ struct sym *cs = inner(p->s);
+
+ if (pushsym(p, SYM_LIT))
+ return -1;
+
+ return cs ? push_to(p) : run(l, p);
+}
+
+static int num(const struct lex *l, struct prv *p)
+{
+ fprintf(stderr, "%s: TODO\n", __func__);
+ reset(p);
+ return -1;
+}
+
+static int id(const struct lex *l, struct prv *p)
+{
+ struct sym *cs = inner(p->s);
+
+ if (pushsym(p, SYM_ID))
+ return -1;
+ else if (cs)
+ return push_to(p);
+
+ p->stk = p->tk;
+ return run(l, p);
+}
+
+void sym_free(struct sym *s)
+{
+ struct sym *ss = s;
+
+ while (ss)
+ {
+ struct sym *child = ss->child;
+
+ free(ss);
+ ss = child;
+ }
+}
+
+int sym_lval(const struct sym *s)
+{
+ int ret = 1;
+
+ while (s)
+ {
+ switch (s->type)
+ {
+ case SYM_OFF:
+ case SYM_SZ:
+ case SYM_LIT:
+ case SYM_NUM:
+ case SYM_TMP:
+ ret = 0;
+ break;
+
+ case SYM_ADDR:
+ if (!s->parent || s->parent->type != SYM_CNT)
+ ret = 0;
+ case SYM_ID:
+ case SYM_CNT:
+ case SYM_CAST:
+ break;
+ }
+
+ s = s->child;
+ }
+
+ return ret;
+}
+
+static int endsym(const struct lex *l, struct prv *p)
+{
+ return p->s ? run(l, p) : 0;
+}
+
+static int invalid(const struct tk *tk, const struct type *a,
+ const struct type *b)
+{
+ static int t[BUILTIN + 1][BUILTIN + 1] =
+ {
+ /* U S C P T PTR ARY BUILTIN */
+ /* U */ {1, 0, 0, 0, 0, 0, 0, 0},
+ /* S */ {0, 1, 0, 0, 0, 0, 0, 0},
+ /* C */ {0, 0, 1, 0, 0, 0, 0, 0},
+ /* P */ {0, 0, 0, 1, 0, 1, 0, 0},
+ /* T */ {0, 0, 0, 0, 1, 0, 0, 0},
+ /* PTR */ {0, 0, 0, 0, 0, 1, 1, 0},
+ /* ARY */ {0, 0, 0, 0, 0, 0, 1, 0},
+ /* BUILTIN */ {0, 0, 0, 0, 0, 0, 0, 1}
+ };
+
+ int valid = t[a->type][b->type];
+
+ if (!valid)
+ {
+ char *s1 = type_name(b), *s2 = type_name(a);
+
+ if (s1 && s2)
+ errloc(tk, "cannot convert \"%s\" to \"%s\"", s1, s2);
+
+ free(s1);
+ free(s2);
+ }
+
+ return !valid;
+}
+
+static const struct type *genlittype(struct prv *p)
+{
+ const struct fn *fn = fn_cur(p);
+ const struct type *byte = type_find(fn, "char");
+ struct type *bytedup = NULL, *t = NULL;
+
+ if (!byte)
+ return NULL;
+ else if (!(bytedup = malloc(sizeof *bytedup))
+ || !(t = malloc(sizeof *t)))
+ {
+ perror("malloc(3)");
+ goto failure;
+ }
+
+ *bytedup = *byte;
+ *t = (struct type)
+ {
+ .type = ARY,
+ .u.ary.etc = 1,
+ .child = bytedup
+ };
+
+ return p->ast->littype = type_insert(p, t);
+
+failure:
+ free(t);
+ free(bytedup);
+ return NULL;
+}
+
+static const struct type *littype(struct prv *p)
+{
+ const struct type *t = p->ast->littype;
+
+ return t ? t : genlittype(p);
+}
+
+const struct type *sym_type(struct prv *p, const struct sym *s)
+{
+ const struct fn *fn = fn_cur(p);
+ const struct type *ret = NULL;
+
+ for (; s; s = s->child)
+ {
+ const struct tk *tk = s->tk;
+
+ switch (s->type)
+ {
+ case SYM_CAST:
+ if (!ret)
+ ret = s->u.t;
+ else if (invalid(tk, ret, s->u.t))
+ return NULL;
+
+ break;
+
+ case SYM_ID:
+ {
+ const struct stentry *e = fn_var(fn, tk);
+ const struct type *t;
+
+ if (!e && !(t = type_ufind(fn, tk->s)))
+ return NULL;
+ else if (e)
+ t = e->t;
+
+ if (!ret)
+ ret = t;
+ else if (invalid(tk, ret, t))
+ return NULL;
+ }
+ break;
+
+ case SYM_LIT:
+ {
+ const struct type *lt = littype(p);
+
+ if (!ret)
+ ret = lt;
+ else if (invalid(tk, ret, lt))
+ return NULL;
+ }
+ break;
+
+ case SYM_ADDR:
+ case SYM_TMP:
+ case SYM_NUM:
+ case SYM_SZ:
+ case SYM_CNT:
+ case SYM_OFF:
+ break;
+ }
+ }
+
+ return ret;
+}
+
+int sym_rval(const struct sym *s)
+{
+ return !sym_lval(s);
+}
+
+int sym(struct prv *p, sym_fn fn)
+{
+ struct pos init =
+ {
+ .name = __func__,
+ .seq = seqs,
+ .end = endsym
+ };
+
+ p->stk = p->tk;
+ p->sym = fn;
+ return push(&init, p);
+}
diff --git a/src/prc1/sym.h b/src/prc1/sym.h
new file mode 100644
index 0000000..17a54b3
--- /dev/null
+++ b/src/prc1/sym.h
@@ -0,0 +1,15 @@
+#ifndef SYM_H
+#define SYM_H
+
+#include "lex.h"
+#include "prv.h"
+
+typedef int (*sym_fn)(const struct lex *, struct prv *, const struct sym *);
+
+int sym(struct prv *p, sym_fn fn);
+int sym_lval(const struct sym *s);
+int sym_rval(const struct sym *s);
+void sym_free(struct sym *s);
+const struct type *sym_type(struct prv *p, const struct sym *s);
+
+#endif
diff --git a/src/prc1/td.c b/src/prc1/td.c
index 06572e7..af88af8 100644
--- a/src/prc1/td.c
+++ b/src/prc1/td.c
@@ -18,7 +18,6 @@
static int cid(const struct lex *, struct prv *);
static int cnum(const struct lex *, struct prv *);
static int end(const struct lex *, struct prv *);
-static int endp(const struct lex *, struct prv *);
static int u(const struct lex *, struct prv *);
static int s(const struct lex *, struct prv *);
static int c(const struct lex *, struct prv *);
@@ -34,19 +33,10 @@ static const struct seq seqs[] =
{(struct step[]){{ID}, {ID, "union"}, {0}}, .fn = u},
{(struct step[]){{ID}, {ID, "struct"}, {0}}, .fn = s},
{(struct step[]){{ID}, {ID, "constant"}, {0}}, .fn = c},
- {(struct step[]){{ID}, {ID, "prototype"}, {0}}, .fn = p, .end = endp},
+ {(struct step[]){{ID}, {ID, "prototype"}, {0}}, .fn = p},
{0}
};
-static void reset(struct prv *p)
-{
- struct pos *pos = &p->pos[p->i];
-
- pos->seq = seqs;
- pos->step = seqs->steps;
- p->stk = p->tk;
-}
-
static int bump(const struct tk *tk, const struct type *t, struct prv *p)
{
struct tdconstant *tdc = p->tdc;
@@ -90,6 +80,21 @@ static int bump(const struct tk *tk, const struct type *t, struct prv *p)
return 0;
}
+static void insert(struct td *td, struct type *t)
+{
+ struct type *tt = td->types;
+
+ if (!tt)
+ td->types = t;
+ else
+ for (; tt; tt = tt->next)
+ if (!tt->next)
+ {
+ tt->next = t;
+ break;
+ }
+}
+
static int cid(const struct lex *l, struct prv *p)
{
const struct fn *fn = fn_cur(p);
@@ -98,29 +103,26 @@ static int cid(const struct lex *l, struct prv *p)
const struct type *t = type_find(fn, id->s);
struct tdconstant *tdc = p->tdc;
struct td *td = fn->td;
- size_t n = td->ntypes + 1;
- struct type *types, *nt;
+ struct type *nt;
+ const struct loc *loc;
if (t)
{
- const struct loc *loc = &t->tk->loc;
-
+ loc = &t->tk->loc;
errloc(id, "type \"%s\" already defined at %s:%d:%d", id->s, loc->f,
loc->line, loc->col);
return -1;
}
else if ((e = fn_var(fn, id)))
{
- const struct loc *loc = &e->tk->loc;
-
+ loc = &e->tk->loc;
errloc(id, "\"%s\" already defined as a variable at %s:%d:%d", id->s,
loc->f, loc->line, loc->col);
return -1;
}
else if ((e = fn_var(fn, v)))
{
- const struct loc *loc = &e->tk->loc;
-
+ loc = &e->tk->loc;
errloc(id, "value \"%s\" (defined at %s:%d:%d) is not a constant",
v->s, loc->f, loc->line, loc->col);
return -1;
@@ -132,20 +134,17 @@ static int cid(const struct lex *l, struct prv *p)
}
else if (t->type != C)
{
- const struct loc *loc = &t->tk->loc;
-
+ loc = &t->tk->loc;
errloc(id, "value \"%s\" (defined at %s:%d:%d) is not a constant",
v->s, loc->f, loc->line, loc->col);
return -1;
}
- else if (!(types = realloc(td->types, n * sizeof *types)))
+ else if (!(nt = malloc(sizeof *nt)))
{
- perror("realloc(3)");
+ perror("malloc(3)");
return -1;
}
- td->types = types;
- nt = &td->types[td->ntypes++];
*nt = (struct type)
{
.type = C,
@@ -154,6 +153,7 @@ static int cid(const struct lex *l, struct prv *p)
.u.c = t->u.c
};
+ insert(td, nt);
tdc->neg = t->sign;
if (bump(id, t, p))
@@ -162,9 +162,11 @@ static int cid(const struct lex *l, struct prv *p)
for (size_t i = 0; i < p->block; i++)
dbg("\t");
- dbg("\tadding constant %s to %s (%lld)\n", id->s, v->s, t->u.c.v);
+ loc = &id->loc;
+ dbg("\tadd constant %s (%d:%d) to %s (%lld)\n", id->s, loc->line,
+ loc->col, v->s, t->u.c.v);
reset(p);
- return 1;
+ return 0;
}
static int cnum(const struct lex *l, struct prv *p)
@@ -174,12 +176,12 @@ static int cnum(const struct lex *l, struct prv *p)
const char *name = id->s;
const struct stentry *e;
struct td *td = fn->td;
- size_t n = td->ntypes + 1;
- struct type *types, *nt;
+ struct type *nt;
struct tdconstant *tdc = p->tdc;
const struct type *t = type_find(fn, name);
int sign = *num->s == '-';
unsigned long long uv = 0;
+ const struct loc *loc;
long long v;
char *end;
@@ -194,28 +196,24 @@ static int cnum(const struct lex *l, struct prv *p)
if (t)
{
- const struct loc *loc = &t->tk->loc;
-
+ loc = &t->tk->loc;
errloc(id, "type \"%s\" already defined at %s:%d:%d", name, loc->f,
loc->line, loc->col);
return -1;
}
else if ((e = fn_var(fn, id)))
{
- const struct loc *loc = &e->tk->loc;
-
+ loc = &e->tk->loc;
errloc(id, "\"%s\" already defined as a variable at %s:%d:%d", id->s,
loc->f, loc->line, loc->col);
return -1;
}
- else if (!(types = realloc(td->types, n * sizeof *types)))
+ else if (!(nt = malloc(sizeof *nt)))
{
- perror("realloc(3)");
+ perror("malloc(3)");
return -1;
}
- td->types = types;
- nt = &td->types[td->ntypes++];
*nt = (struct type)
{
.type = C,
@@ -228,18 +226,21 @@ static int cnum(const struct lex *l, struct prv *p)
else
tdc->u.uv = nt->u.c.uv = uv;
+ insert(td, nt);
tdc->neg = sign;
for (size_t i = 0; i < p->block; i++)
dbg("\t");
- dbg("\tadding constant %s to %s\n", id->s, num->s);
+ loc = &id->loc;
+ dbg("\tadd constant %s (%d:%d) to %s\n", id->s, loc->line, loc->col,
+ num->s);
if (bump(id, nt, p))
return -1;
reset(p);
- return 1;
+ return 0;
}
static int c(const struct lex *l, struct prv *p)
@@ -249,34 +250,30 @@ static int c(const struct lex *l, struct prv *p)
const struct stentry *e;
const struct type *t = type_find(fn, id->s);
struct td *td = fn->td;
- size_t n = td->ntypes + 1;
- struct type *types, *nt;
+ struct type *nt;
const struct tdconstant *tdc = p->tdc;
+ const struct loc *loc;
if (t)
{
- const struct loc *loc = &t->tk->loc;
-
+ loc = &t->tk->loc;
errloc(id, "type \"%s\" already defined at %s:%d:%d", id->s, loc->f,
loc->line, loc->col);
return -1;
}
else if ((e = fn_var(fn, id)))
{
- const struct loc *loc = &e->tk->loc;
-
+ loc = &e->tk->loc;
errloc(id, "\"%s\" already defined as a variable at %s:%d:%d", id->s,
loc->f, loc->line, loc->col);
return -1;
}
- else if (!(types = realloc(td->types, n * sizeof *types)))
+ else if (!(nt = malloc(sizeof *nt)))
{
- perror("realloc(3)");
+ perror("malloc(3)");
return -1;
}
- td->types = types;
- nt = &td->types[td->ntypes];
*nt = (struct type)
{
.type = C,
@@ -289,31 +286,33 @@ static int c(const struct lex *l, struct prv *p)
else
nt->u.c.uv = tdc->u.uv;
+ insert(td, nt);
+
for (size_t i = 0; i < p->block; i++)
dbg("\t");
- dbg("\tadding constant %s to ", id->s);
+ loc = &id->loc;
+ dbg("\tadd constant %s (%d:%d) to ", id->s, loc->line, loc->col);
if (tdc->neg)
dbg("%lld", tdc->u.v);
else
dbg("%llu", tdc->u.uv);
- dbg("\n", stderr);
+ dbg("\n");
- if (bump(id, &td->types[td->ntypes++], p))
+ if (bump(id, nt, p))
return -1;
reset(p);
- return 1;
+ return 0;
}
static int p(const struct lex *l, struct prv *p)
{
struct fn *fn = fn_cur(p), *pt = NULL;
struct td *td = fn->td;
- size_t n = td->ntypes + 1;
- struct type *types;
+ struct type *nt = NULL;
if (!(pt = malloc(sizeof *pt)))
{
@@ -323,28 +322,30 @@ static int p(const struct lex *l, struct prv *p)
*pt = (struct fn){.tk = p->stk, .parent = fn};
- if (!(types = realloc(td->types, n * sizeof *types)))
+ if (!(nt = malloc(sizeof *nt)))
{
- perror("realloc(3)");
+ perror("malloc(3)");
goto failure;
}
- types[td->ntypes++] = (struct type)
+ *nt = (struct type)
{
.type = P,
.tk = p->stk,
+ /* TODO: use frontend-specific pointer size */
.sz = sizeof (void *),
.align = sizeof (void *),
.u.p.fn = pt
};
- td->types = types;
+ insert(td, nt);
p->proto = pt;
- dbg("\tadding prototype %s\n", p->stk->s);
+ dbg("\tadd prototype %s\n", p->stk->s);
return div_p(l, p);
failure:
free(pt);
+ type_free(nt);
return -1;
}
@@ -364,7 +365,7 @@ static int ends(struct type *t)
t->align = st->entries->t->align;
t->sz = e->offset + e->t->sz;
t->sz += t->align - (t->sz % t->align);
- dbg("\tadding struct %s, size %zu, align %zu\n", t->tk->s, t->sz, t->align);
+ dbg("\tadd struct %s, size %zu, align %zu\n", t->tk->s, t->sz, t->align);
return 0;
}
@@ -419,15 +420,6 @@ static int end(const struct lex *l, struct prv *p)
p->ag = NULL;
p->block--;
reset(p);
- return 1;
-}
-
-static int endp(const struct lex *l, struct prv *p)
-{
- if (fn_end(l, p))
- return -1;
-
- p->proto = NULL;
return 0;
}
@@ -436,8 +428,7 @@ static int s(const struct lex *l, struct prv *p)
const struct tk *id = p->stk;
struct fn *fn = fn_cur(p);
struct td *td = fn->td;
- size_t nt = td->ntypes + 1;
- struct type *types, *newt;
+ struct type *nt;
const struct type *t = type_find(fn, id->s);
if (t)
@@ -448,23 +439,22 @@ static int s(const struct lex *l, struct prv *p)
loc->line, loc->col);
return -1;
}
- else if (!(types = realloc(td->types, nt * sizeof *types)))
+ else if (!(nt = malloc(sizeof *nt)))
{
perror("realloc(3)");
return -1;
}
- td->types = types;
- newt = &td->types[td->ntypes++];
- *newt = (struct type)
+ *nt = (struct type)
{
.type = S,
.tk = id
};
- p->ag = newt;
+ p->ag = nt;
p->block++;
- return storage(l, p, id->s, 0, &newt->u.s.storage);
+ insert(td, nt);
+ return storage(l, p, id->s, 0, &nt->u.s.storage);
}
static int u(const struct lex *l, struct prv *p)
@@ -481,8 +471,7 @@ static int tt(const struct lex *l, struct prv *p, const struct type *t)
const struct type *tp = type_ufind(fn, id->s);
const struct loc *loc = &id->loc;
struct td *td = fn->td;
- size_t n = td->ntypes + 1;
- struct type *types, *nt;
+ struct type *nt;
char *s = type_name(t);
if (!s)
@@ -495,16 +484,12 @@ static int tt(const struct lex *l, struct prv *p, const struct type *t)
loc->line, loc->col);
goto end;
}
- else if (pop(l, p))
- return -1;
- else if (!(types = realloc(td->types, n * sizeof *types)))
+ else if (!(nt = malloc(sizeof *nt)))
{
perror("realloc(3)");
goto end;
}
- td->types = types;
- nt = &td->types[td->ntypes++];
*nt = (struct type)
{
.type = T,
@@ -512,10 +497,11 @@ static int tt(const struct lex *l, struct prv *p, const struct type *t)
.u.t.alias = t
};
- dbg("\tadding %s (%d:%d) alias %s\n", id->s, loc->line, loc->col, s);
+ dbg("\tadd %s (%d:%d) alias %s\n", id->s, loc->line, loc->col, s);
+ insert(td, nt);
reset(p);
p->id = NULL;
- ret = 1;
+ ret = 0;
end:
free(s);
return ret;
@@ -530,12 +516,11 @@ static int a(const struct lex *l, struct prv *p)
void td_free(struct td *td)
{
if (td)
- {
- for (size_t i = 0; i < td->ntypes; i++)
- type_free(&td->types[i]);
-
- free(td->types);
- }
+ for (struct type *t = td->types, *next; t; t = next)
+ {
+ next = t->next;
+ type_lfree(t);
+ }
free(td);
}
@@ -548,9 +533,8 @@ int td(const struct lex *l, struct prv *p)
struct tdconstant *tdc = NULL;
struct pos init =
{
- .seq = seqs,
- .stseq = seqs,
- .step = seqs->steps
+ .name = __func__,
+ .seq = seqs
};
if (prev)
@@ -575,7 +559,7 @@ int td(const struct lex *l, struct prv *p)
fn->td = td;
p->tdc = tdc;
p->stk = p->tk;
- return 1;
+ return 0;
failure:
free(tdc);
diff --git a/src/prc1/tmp.c b/src/prc1/tmp.c
index a08716b..96b2208 100644
--- a/src/prc1/tmp.c
+++ b/src/prc1/tmp.c
@@ -4,12 +4,13 @@
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
const struct stentry *tmp_create(struct fn *fn, const struct type *t)
{
- static const char fmt[] = "__tmp%zu";
+ static const char fmt[] = "__tmp%zu", path[] = "(temporary)";
int r = snprintf(NULL, 0, fmt, fn->ntmps);
- char *s = NULL, *tname = NULL;
+ char *s = NULL, *tname = NULL, *pathdup = NULL;
struct tmp *tmp;
if (!(tname = type_name(t)))
@@ -19,13 +20,15 @@ const struct stentry *tmp_create(struct fn *fn, const struct type *t)
fprintf(stderr, "%s: snprintf(3) failed\n", __func__);
goto failure;
}
- else if (!(s = malloc(r + 1)))
+ else if (!(s = malloc(r + 1))
+ || !(pathdup = malloc(strlen(path) + 1)))
{
perror("malloc(3)");
goto failure;
}
snprintf(s, r + 1, fmt, fn->ntmps++);
+ strcpy(pathdup, path);
if (!(tmp = malloc(sizeof *tmp)))
{
@@ -39,7 +42,7 @@ const struct stentry *tmp_create(struct fn *fn, const struct type *t)
{
.type = ID,
.s = s,
- .loc.f = "(temporary)"
+ .loc.f = pathdup
},
.e =
@@ -66,5 +69,6 @@ const struct stentry *tmp_create(struct fn *fn, const struct type *t)
failure:
free(s);
free(tname);
+ free(pathdup);
return NULL;
}
diff --git a/src/prc1/type.c b/src/prc1/type.c
index c7e43d0..92cc53f 100644
--- a/src/prc1/type.c
+++ b/src/prc1/type.c
@@ -17,20 +17,22 @@ static int t(const struct lex *l, struct prv *p);
static const struct seq seqs[] =
{
- {(struct step[])
- {{ID, "array"}, {ID, "of"}, {ID, "etc"}, {0}}, .fn = aetc},
+ {(struct step[]){{ID, "array"}, {ID, "of"}, {ID, "etc"}, {0}}, .fn = aetc},
{(struct step[]){{ID, "array"}, {ID, "of"}, {NUM}, {0}}, .fn = anum},
{(struct step[]){{ID, "array"}, {ID, "of"}, {ID}, {0}}, .fn = aid},
{(struct step[]){{ID, "pointer"}, {ID, "to"}, {0}}, .fn = p},
{(struct step[]){{ID, "void"}, {0}}, .fn = t},
- {(struct step[]){{ID, "byte"}, {0}}, .fn = t},
- {(struct step[]){{ID, "halfword"}, {0}}, .fn = t},
- {(struct step[]){{ID, "word"}, {0}}, .fn = t},
+ {(struct step[]){{ID, "char"}, {0}}, .fn = t},
+ {(struct step[]){{ID, "schar"}, {0}}, .fn = t},
+ {(struct step[]){{ID, "short"}, {0}}, .fn = t},
+ {(struct step[]){{ID, "int"}, {0}}, .fn = t},
{(struct step[]){{ID, "long"}, {0}}, .fn = t},
- {(struct step[]){{ID, "ubyte"}, {0}}, .fn = t},
- {(struct step[]){{ID, "uhalfword"}, {0}}, .fn = t},
- {(struct step[]){{ID, "uword"}, {0}}, .fn = t},
+ {(struct step[]){{ID, "longlong"}, {0}}, .fn = t},
+ {(struct step[]){{ID, "uchar"}, {0}}, .fn = t},
+ {(struct step[]){{ID, "ushort"}, {0}}, .fn = t},
+ {(struct step[]){{ID, "uint"}, {0}}, .fn = t},
{(struct step[]){{ID, "ulong"}, {0}}, .fn = t},
+ {(struct step[]){{ID, "ulonglong"}, {0}}, .fn = t},
{(struct step[]){{ID}, {0}}, .fn = t},
{0}
};
@@ -77,8 +79,13 @@ void type_free(struct type *t)
void type_lfree(struct type *t)
{
- if (t->child)
- type_lfree(t->child);
+ if (t)
+ {
+ if (t->child)
+ type_lfree(t->child);
+
+ type_free(t);
+ }
free(t);
}
@@ -156,15 +163,18 @@ const struct type *type_ufind(const struct fn *fn, const char *s)
{
static const struct type builtins[] =
{
- {.type = BUILTIN, .u.b.name = "void"},
- {.type = BUILTIN, .u.b.name = "byte", .sz = 1, .sign = 1, .align = 1},
- {.type = BUILTIN, .u.b.name = "halfword", .sz = 2, .sign = 1, .align = 2},
- {.type = BUILTIN, .u.b.name = "word", .sz = 4, .sign = 1, .align = 4},
- {.type = BUILTIN, .u.b.name = "long", .sz = 8, .sign = 1, .align = 8},
- {.type = BUILTIN, .u.b.name = "ubyte", .sz = 1, .align = 1},
- {.type = BUILTIN, .u.b.name = "uhalfword", .sz = 2, .align = 2},
- {.type = BUILTIN, .u.b.name = "uword", .sz = 4, .align = 4},
- {.type = BUILTIN, .u.b.name = "ulong", .sz = 8, .align = 8}
+ {.type = BUILTIN, .u.b = {"void"}},
+ {.type = BUILTIN, .u.b = {"char"}, .sz = 1, .sign = 1, .align = 1},
+ {.type = BUILTIN, .u.b = {"schar"}, .sz = 1, .sign = 1, .align = 1},
+ {.type = BUILTIN, .u.b = {"short"}, .sz = 2, .sign = 1, .align = 2},
+ {.type = BUILTIN, .u.b = {"int"}, .sz = 4, .sign = 1, .align = 4},
+ {.type = BUILTIN, .u.b = {"long"}, .sz = 8, .sign = 1, .align = 8},
+ {.type = BUILTIN, .u.b = {"longlong"}, .sz = 8, .sign = 1, .align = 8},
+ {.type = BUILTIN, .u.b = {"uchar"}, .sz = 1, .align = 1},
+ {.type = BUILTIN, .u.b = {"ushort"}, .sz = 2, .align = 2},
+ {.type = BUILTIN, .u.b = {"uint"}, .sz = 4, .align = 4},
+ {.type = BUILTIN, .u.b = {"ulong"}, .sz = 8, .align = 8},
+ {.type = BUILTIN, .u.b = {"ulonglong"}, .sz = 8, .align = 8}
};
const struct td *td = fn->td;
@@ -186,13 +196,9 @@ const struct type *type_ufind(const struct fn *fn, const char *s)
}
if (td)
- for (size_t i = 0; i < td->ntypes; i++)
- {
- const struct type *t = &td->types[i];
-
+ for (const struct type *t = td->types; t; t = t->next)
if (!strcmp(t->tk->s, s))
return t;
- }
for (size_t i = 0; i < fn->nimps; i++)
{
@@ -215,10 +221,9 @@ const struct type *type_find(const struct fn *fn, const char *s)
return t;
}
-static int queue(struct prv *p, struct type *t)
+static void queue(struct prv *p, struct type *t)
{
struct type *tt;
- struct pos *pos = &p->pos[p->i];
if (!(tt = p->t))
p->t = t;
@@ -230,10 +235,8 @@ static int queue(struct prv *p, struct type *t)
tt->child = t;
}
- pos->seq = pos->stseq;
- pos->step = pos->seq->steps;
p->stk = p->tk;
- return 1;
+ reset(p);
}
static int aetc(const struct lex *l, struct prv *p)
@@ -255,12 +258,13 @@ static int aetc(const struct lex *l, struct prv *p)
if (!(t = malloc(sizeof *t)))
{
- perror("malloc");
+ perror("malloc(3)");
return -1;
}
*t = (struct type){.type = ARY, .u.ary.etc = 1};
- return queue(p, t);
+ queue(p, t);
+ return 0;
}
static int aid(const struct lex *l, struct prv *p)
@@ -294,12 +298,13 @@ static int aid(const struct lex *l, struct prv *p)
}
else if (!(t = malloc(sizeof *t)))
{
- perror("malloc");
+ perror("malloc(3)");
return -1;
}
*t = (struct type){.type = ARY, .u.ary.n = v};
- return queue(p, t);
+ queue(p, t);
+ return 0;
}
static int anum(const struct lex *l, struct prv *p)
@@ -320,12 +325,13 @@ static int anum(const struct lex *l, struct prv *p)
}
else if (!(t = malloc(sizeof *t)))
{
- perror("malloc");
+ perror("malloc(3)");
return -1;
}
*t = (struct type){.type = ARY, .u.ary.n = n};
- return queue(p, t);
+ queue(p, t);
+ return 0;
}
static int p(const struct lex *l, struct prv *p)
@@ -334,24 +340,27 @@ static int p(const struct lex *l, struct prv *p)
if (!t)
{
- perror("malloc");
+ perror("malloc(3)");
return -1;
}
*t = (struct type)
{
.type = PTR,
+ /* TODO: ask target for sizeof (void *) */
.sz = sizeof (void *),
.align = sizeof (void *)
};
if ((tt = p->t) && tt->type == ARY)
{
+ /* TODO: ask target for sizeof (void *) */
tt->sz = tt->u.ary.n * sizeof (void *);
tt->align = sizeof (void *);
}
- return queue(p, t);
+ queue(p, t);
+ return 0;
}
static int aryeq(const struct type *a, const struct type *b)
@@ -372,10 +381,10 @@ static int eq(const struct type *a, const struct type *b)
return !a && !b;
}
-static const struct type *insert(struct prv *p)
+const struct type *type_insert(struct prv *p, struct type *a)
{
struct ast *ast = p->ast;
- struct type *a = p->t, *tt = ast->types;
+ struct type *tt = ast->types;
for (const struct type *b = ast->types; b; b = b->next)
if (eq(a, b))
@@ -434,26 +443,42 @@ static int t(const struct lex *l, struct prv *p)
tt->align = t->align;
}
- if (!(t = insert(p)))
+ if (!(t = type_insert(p, p->t)))
return -1;
-
- p->t = NULL;
}
+ else
+ p->t = (struct type *)t;
+ if (pop(l, p))
+ return -1;
+
+ p->stk = p->tk;
+ p->t = NULL;
return p->type(l, p, t);
}
+static int endtype(const struct lex *l, struct prv *p)
+{
+ if (!p->t)
+ {
+ errloc(p->stk - 1, "expected type");
+ return -1;
+ }
+
+ return 0;
+}
+
int type(const struct lex *l, struct prv *p,
int (*fn)(const struct lex *, struct prv *, const struct type *))
{
struct pos init =
{
+ .name = __func__,
.seq = seqs,
- .stseq = seqs,
- .step = seqs->steps
+ .end = endtype
};
p->stk = p->tk;
p->type = fn;
- return push(&init, p) ? -1 : 1;
+ return push(&init, p);
}
diff --git a/src/prc1/type.h b/src/prc1/type.h
index 7de6c28..455f243 100644
--- a/src/prc1/type.h
+++ b/src/prc1/type.h
@@ -7,6 +7,7 @@
const struct type *type_ufind(const struct fn *fn, const char *s);
const struct type *type_find(const struct fn *fn, const char *s);
+const struct type *type_insert(struct prv *p, struct type *a);
char *type_name(const struct type *t);
int type(const struct lex *l, struct prv *p,
int (*fn)(const struct lex *, struct prv *p, const struct type *t));
diff --git a/src/prc1/warn.c b/src/prc1/warn.c
index 93635db..9fb535e 100644
--- a/src/prc1/warn.c
+++ b/src/prc1/warn.c
@@ -1,6 +1,7 @@
#include "warn.h"
#include "cgen.h"
#include "dbg.h"
+#include "fn.h"
#include "parse.h"
#include "prv.h"
#include "stmt.h"
@@ -9,6 +10,8 @@
#include <stdlib.h>
#include <string.h>
+#if 0
+
static int finalize(const struct lex *l, const struct prv *p,
const struct print *pr)
{
@@ -30,7 +33,7 @@ static int finalize(const struct lex *l, const struct prv *p,
.u.warn.p = *pr
};
- dbg("\t\tadding warn statement with %zu entries%s\n", pr->nentries,
+ dbg("\t\tadd warn statement with %zu entries%s\n", pr->nentries,
pr->println ? "" : ", no lf");
return 0;
}
@@ -135,13 +138,27 @@ int warn_cgen(const struct warn *w, struct cgen *c)
return 0;
}
+#endif
-void warn_free(struct warn *w)
+int warn_cgen(const struct print *pr, struct cgen *c)
{
- print_free(&w->p);
+ return print_cgen(pr, c, "stderr");
}
int warn(const struct lex *l, struct prv *p)
{
- return print(l, p, finalize);
+ struct fn *fn = fn_cur(p);
+ size_t n = fn->nstmts + 1;
+ struct stmt *stmts = realloc(fn->stmts, n * sizeof *stmts);
+
+ if (!stmts)
+ {
+ perror("realloc(3)");
+ return -1;
+ }
+
+ dbg("\t\tadd warn statement\n");
+ stmts[fn->nstmts++] = (struct stmt){.type = WARN, .u.print = {0}};
+ fn->stmts = stmts;
+ return print(l, p);
}
diff --git a/src/prc1/warn.h b/src/prc1/warn.h
index 5327592..9a50857 100644
--- a/src/prc1/warn.h
+++ b/src/prc1/warn.h
@@ -1,17 +1,12 @@
#ifndef WARN_H
#define WARN_H
+#include "cgen.h"
#include "lex.h"
#include "print.h"
#include "prv.h"
-struct warn
-{
- struct print p;
-};
-
int warn(const struct lex *l, struct prv *p);
-int warn_cgen(const struct warn *w, struct cgen *c);
-void warn_free(struct warn *w);
+int warn_cgen(const struct print *pr, struct cgen *c);
#endif
diff --git a/src/prc1/ws.c b/src/prc1/ws.c
index 59e1aec..94014ce 100644
--- a/src/prc1/ws.c
+++ b/src/prc1/ws.c
@@ -4,23 +4,6 @@
#include "parse.h"
#include "storage.h"
-static int wspush(const struct stentry *e, struct cgen *c)
-{
- const struct type *t = e->t;
-
- printf("%%%s_ =l alloc%zu %zu\n", e->tk->s, t->align, t->sz);
- return 0;
-}
-
-int ws_cgen(const struct storage *s, struct cgen *c)
-{
- for (size_t i = 0; i < s->nentries; i++)
- if (wspush(&s->entries[i], c))
- return -1;
-
- return 0;
-}
-
int ws(const struct lex *l, struct prv *p)
{
struct fn *fn = fn_cur(p);