diff options
author | Michael Forney <mforney@mforney.org> | 2019-02-22 12:25:50 -0800 |
---|---|---|
committer | Michael Forney <mforney@mforney.org> | 2019-02-22 12:25:50 -0800 |
commit | 2cbd75bbab472b6861dc0ae806e41cf139518fe6 (patch) | |
tree | 15435cabe49771c07664df83824297cfa3d9f008 | |
parent | f2a079fa1a94b6a99e7ce432b6df17fdb4c9b554 (diff) |
Implement __builtin_alloca
-rw-r--r-- | decl.c | 1 | ||||
-rw-r--r-- | decl.h | 1 | ||||
-rw-r--r-- | expr.c | 10 | ||||
-rw-r--r-- | expr.h | 1 | ||||
-rw-r--r-- | main.c | 1 | ||||
-rw-r--r-- | qbe.c | 3 | ||||
-rw-r--r-- | tests/builtin-alloca.c | 3 | ||||
-rw-r--r-- | tests/builtin-alloca.qbe | 12 |
8 files changed, 27 insertions, 5 deletions
@@ -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}; @@ -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 *); @@ -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); @@ -81,6 +81,7 @@ struct expression { BUILTINVASTART, BUILTINVAARG, BUILTINVAEND, + BUILTINALLOCA, } kind; struct expression *arg; } builtin; @@ -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"); @@ -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 new file mode 100644 index 0000000..f086f19 --- /dev/null +++ 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 new file mode 100644 index 0000000..75a1fe1 --- /dev/null +++ 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 +} |