diff options
79 files changed, 2352 insertions, 1524 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 7397346..2b31fa2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.5) +cmake_minimum_required(VERSION 3.13) project(prc C) cmake_policy(SET CMP0135 OLD) add_subdirectory(src) @@ -6,7 +6,7 @@ include(ExternalProject) ExternalProject_Add(musl URL https://musl.libc.org/releases/musl-1.2.6.tar.gz URL_HASH SHA256=d585fd3b613c66151fc3249e8ed44f77020cb5e6c1e635a616d3f9f82460512a - CONFIGURE_COMMAND <SOURCE_DIR>/configure --prefix=${CMAKE_INSTALL_PREFIX} + CONFIGURE_COMMAND CFLAGS=-g <SOURCE_DIR>/configure --prefix=${CMAKE_INSTALL_PREFIX} BUILD_COMMAND make - INSTALL_COMMAND make + INSTALL_COMMAND make install ) @@ -7,7 +7,7 @@ Prose is a new and small programming language that aims for readability and native interoperability with C. Its syntax, while a bit distant from ALGOL-like languages like C, should still be readable to most programmers. -Most remarkably, Prose avoids sigils such as `{}`, `$` or any other kind of +Most remarkably, Prose avoids tokens such as `{}`, `$` or any other kind of symbol, in favour of simple and readable English-like statements. The only exception is `*`, which is used for comments: diff --git a/examples/alias.prose b/examples/alias.prs index 0fae9a6..0fae9a6 100644 --- a/examples/alias.prose +++ b/examples/alias.prs diff --git a/examples/argcv.prose b/examples/argcv.prs index da50b59..da50b59 100644 --- a/examples/argcv.prose +++ b/examples/argcv.prs diff --git a/examples/c.prose b/examples/c.prs index 8224fb5..8224fb5 100644 --- a/examples/c.prose +++ b/examples/c.prs diff --git a/examples/call.prose b/examples/call.prose deleted file mode 100644 index d90ccff..0000000 --- a/examples/call.prose +++ /dev/null @@ -1,18 +0,0 @@ -* function calls -function foo - linkage - myparam word - ret word - procedure using myparam returning ret - display "myparam is " myparam - set ret to 0 - -public function main - linkage - status word - storage - myvar word - procedure returning status - set myvar to 123 - call foo using myvar returning status - display "status is " status diff --git a/examples/call.prs b/examples/call.prs new file mode 100644 index 0000000..3c7d9c4 --- /dev/null +++ b/examples/call.prs @@ -0,0 +1,17 @@ +* function calls +function foo + linkage + a word + b word + c word + d word + procedure using a b c returning d + +public function main + types + foo prototype + procedure + storage + myfoo foo + procedure + call foo using a b c returning d diff --git a/examples/from.prose b/examples/from.prs index 746371d..746371d 100644 --- a/examples/from.prose +++ b/examples/from.prs diff --git a/examples/hello.prose b/examples/hello.prose deleted file mode 100644 index 00c0fe1..0000000 --- a/examples/hello.prose +++ /dev/null @@ -1,7 +0,0 @@ -* hello world example -public function main - linkage - status word - procedure returning status - display "hello world" - set status to 0 diff --git a/examples/hello.prs b/examples/hello.prs new file mode 100644 index 0000000..4ba371a --- /dev/null +++ b/examples/hello.prs @@ -0,0 +1,20 @@ +* hello world example + +public function main + globals + myptr pointer to int + types + socket prototype + linkage + fd int + procedure returning fd + + vfprintf prototype + procedure + + myalias alias int + procedure + display "socket=" socket etc + display ", vfprintf=" vfprintf + display "this is a string" + display cast "this is a string" to pointer to void diff --git a/src/prc/posix.c b/src/prc/posix.c index 5510130..bce793e 100644 --- a/src/prc/posix.c +++ b/src/prc/posix.c @@ -11,11 +11,15 @@ struct spawn { + char *path; pid_t pid; }; void spawn_free(struct spawn *s) { + if (s) + free(s->path); + free(s); } @@ -31,6 +35,12 @@ int spawn_wait(struct spawn *s) } else if (WIFEXITED(stat) && WEXITSTATUS(stat) != EXIT_SUCCESS) return -1; + else if (WIFSIGNALED(stat)) + { + fprintf(stderr, "%s terminated by signal %d\n", s->path, + WTERMSIG(stat)); + return -1; + } else if (WIFSTOPPED(stat)) return -1; @@ -60,13 +70,21 @@ static int setupfd(FILE *f, int dst) struct spawn *spawnvi(const char *path, char *const argv[], FILE *in, FILE *out) { struct spawn *ret = malloc(sizeof *ret); + char *pathdup = strdup(path); - if (!ret) + if (!pathdup) + { + perror("strdup(3)"); + goto failure; + } + else if (!ret) { perror("malloc(3)"); goto failure; } + ret->path = pathdup; + switch ((ret->pid = fork())) { case -1: @@ -89,6 +107,7 @@ struct spawn *spawnvi(const char *path, char *const argv[], FILE *in, FILE *out) return ret; failure: + free(pathdup); free(ret); return NULL; } diff --git a/src/prc/prc.c b/src/prc/prc.c index cbdc2d2..3c90cde 100644 --- a/src/prc/prc.c +++ b/src/prc/prc.c @@ -332,7 +332,7 @@ static int prc1(struct state *s, const char *src) goto end; } else if (s->verbose) - printcmd(&path, args); + printcmd(&path, args + 1); /* HACK: struct dstr is ultimately syntax sugar for char *. */ if (!(proc = spawnv(path.s, (char **)args, out))) 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); |
