cproc

Unnamed repository; edit this file 'description' to name the repository.
git clone git://git.nihaljere.xyz/cproc
Log | Files | Refs | Submodules | README | LICENSE

commit 2cbd75bbab472b6861dc0ae806e41cf139518fe6
parent f2a079fa1a94b6a99e7ce432b6df17fdb4c9b554
Author: Michael Forney <mforney@mforney.org>
Date:   Fri, 22 Feb 2019 12:25:50 -0800

Implement __builtin_alloca

Diffstat:
Mdecl.c | 1+
Mdecl.h | 1+
Mexpr.c | 10+++++-----
Mexpr.h | 1+
Mmain.c | 1+
Mqbe.c | 3+++
Atests/builtin-alloca.c | 3+++
Atests/builtin-alloca.qbe | 12++++++++++++
8 files changed, 27 insertions(+), 5 deletions(-)

diff --git a/decl.c b/decl.c @@ -24,6 +24,7 @@ struct declaration builtinvaarg = {.kind = DECLBUILTIN}; struct declaration builtinvacopy = {.kind = DECLBUILTIN}; struct declaration builtinvaend = {.kind = DECLBUILTIN}; struct declaration builtinoffsetof = {.kind = DECLBUILTIN}; +struct declaration builtinalloca = {.kind = DECLBUILTIN}; static struct list tentativedefns = {&tentativedefns, &tentativedefns}; diff --git a/decl.h b/decl.h @@ -31,6 +31,7 @@ extern struct declaration builtinvaarg; extern struct declaration builtinvacopy; extern struct declaration builtinvaend; extern struct declaration builtinoffsetof; +extern struct declaration builtinalloca; struct declaration *mkdecl(enum declarationkind, struct type *, enum linkage); _Bool decl(struct scope *, struct function *); diff --git a/expr.c b/expr.c @@ -443,26 +443,22 @@ postfixexpr(struct scope *s, struct expression *r) expect(TCOMMA, "after va_list"); free(expect(TIDENT, "after ','")); // XXX: check that this was actually a parameter name? - expect(TRPAREN, "after parameter identifier"); } else if (r->ident.decl == &builtinvaarg) { e = mkexpr(EXPRBUILTIN, NULL, 0); e->builtin.kind = BUILTINVAARG; e->builtin.arg = exprconvert(assignexpr(s), &typevalistptr); expect(TCOMMA, "after va_list"); e->type = typename(s); - expect(TRPAREN, "after typename"); } else if (r->ident.decl == &builtinvacopy) { e = mkexpr(EXPRASSIGN, typevalist.base, 0); e->assign.l = mkunaryexpr(TMUL, exprconvert(assignexpr(s), &typevalistptr)); expect(TCOMMA, "after target va_list"); e->assign.r = mkunaryexpr(TMUL, exprconvert(assignexpr(s), &typevalistptr)); - expect(TRPAREN, "after source va_list"); e = exprconvert(e, &typevoid); } else if (r->ident.decl == &builtinvaend) { e = mkexpr(EXPRBUILTIN, &typevoid, 0); e->builtin.kind = BUILTINVAEND; exprconvert(assignexpr(s), &typevalistptr); - expect(TRPAREN, "after va_list"); } else if (r->ident.decl == &builtinoffsetof) { t = typename(s); expect(TCOMMA, "after type name"); @@ -474,10 +470,14 @@ postfixexpr(struct scope *s, struct expression *r) error(&tok.loc, "struct/union has no member named '%s'", name); e = mkconstexpr(&typeulong, offset); free(name); - expect(TRPAREN, "after member name"); + } else if (r->ident.decl == &builtinalloca) { + e = mkexpr(EXPRBUILTIN, mkpointertype(&typevoid), 0); + e->builtin.kind = BUILTINALLOCA; + e->builtin.arg = exprconvert(assignexpr(s), &typeulong); } else { fatal("internal error; unknown builtin"); } + expect(TRPAREN, "after builtin parameters"); break; } lvalueconvert(r); diff --git a/expr.h b/expr.h @@ -81,6 +81,7 @@ struct expression { BUILTINVASTART, BUILTINVAARG, BUILTINVAEND, + BUILTINALLOCA, } kind; struct expression *arg; } builtin; diff --git a/main.c b/main.c @@ -59,6 +59,7 @@ main(int argc, char *argv[]) scopeputdecl(&filescope, "__builtin_va_arg", &builtinvaarg); scopeputdecl(&filescope, "__builtin_va_end", &builtinvaend); scopeputdecl(&filescope, "__builtin_offsetof", &builtinoffsetof); + scopeputdecl(&filescope, "__builtin_alloca", &builtinalloca); while (tok.kind != TEOF) { if (!decl(&filescope, NULL)) error(&tok.loc, "expected declaration or function definition"); diff --git a/qbe.c b/qbe.c @@ -830,6 +830,9 @@ funcexpr(struct function *f, struct expression *e) case BUILTINVAEND: /* no-op */ break; + case BUILTINALLOCA: + l = funcexpr(f, e->builtin.arg); + return funcinst(f, IALLOC16, &iptr, (struct value *[]){l}); default: fatal("internal error: unimplemented builtin"); } diff --git a/tests/builtin-alloca.c b/tests/builtin-alloca.c @@ -0,0 +1,3 @@ +void f(void) { + int *x = __builtin_alloca(32); +} diff --git a/tests/builtin-alloca.qbe b/tests/builtin-alloca.qbe @@ -0,0 +1,12 @@ +export +function $f() { +@start.1 + %.1 =l alloc8 8 +@body.2 + %.2 =l add %.1, 0 + %.3 =l extsw 32 + %.4 =l alloc16 %.3 + %.5 =l copy %.4 + storel %.5, %.2 + ret +}