diff options
author | Michael Forney <mforney@mforney.org> | 2019-02-22 13:46:07 -0800 |
---|---|---|
committer | Michael Forney <mforney@mforney.org> | 2019-02-22 13:50:49 -0800 |
commit | a056c878d1df67ff12e506d48653c48e9a1b001d (patch) | |
tree | 2b7d02df3e295155e94b1404fcad22ad10f2c569 /expr.c | |
parent | 430c38701375d7c3a8176218a8536fd83b52a446 (diff) |
Separate out built-in handling from postfixexpr
Diffstat (limited to 'expr.c')
-rw-r--r-- | expr.c | 119 |
1 files changed, 65 insertions, 54 deletions
@@ -398,13 +398,76 @@ primaryexpr(struct scope *s) } static struct expression * +builtinfunc(struct scope *s, enum builtinkind kind) +{ + struct expression *e; + struct type *t; + char *name; + uint64_t offset; + + switch (kind) { + case BUILTINVASTART: + e = mkexpr(EXPRBUILTIN, &typevoid, 0); + e->builtin.kind = BUILTINVASTART; + e->builtin.arg = exprconvert(assignexpr(s), &typevalistptr); + expect(TCOMMA, "after va_list"); + free(expect(TIDENT, "after ','")); + // XXX: check that this was actually a parameter name? + break; + case 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); + break; + case 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)); + e = exprconvert(e, &typevoid); + break; + case BUILTINVAEND: + e = mkexpr(EXPRBUILTIN, &typevoid, 0); + e->builtin.kind = BUILTINVAEND; + exprconvert(assignexpr(s), &typevalistptr); + break; + case BUILTINOFFSETOF: + t = typename(s); + expect(TCOMMA, "after type name"); + name = expect(TIDENT, "after ','"); + if (t->kind != TYPESTRUCT && t->kind != TYPEUNION) + error(&tok.loc, "type is not a struct/union type"); + offset = 0; + if (!typemember(t, name, &offset)) + error(&tok.loc, "struct/union has no member named '%s'", name); + e = mkconstexpr(&typeulong, offset); + free(name); + break; + case BUILTINALLOCA: + e = mkexpr(EXPRBUILTIN, mkpointertype(&typevoid), 0); + e->builtin.kind = BUILTINALLOCA; + e->builtin.arg = exprconvert(assignexpr(s), &typeulong); + break; + case BUILTININFF: + e = mkexpr(EXPRCONST, &typefloat, 0); + /* TODO: use INFINITY here when we can handle musl's math.h */ + e->constant.f = strtod("inf", NULL); + break; + default: + fatal("internal error; unknown builtin"); + } + return e; +} + +static struct expression * postfixexpr(struct scope *s, struct expression *r) { struct expression *e, *arr, *idx, *tmp, **end; struct type *t; enum typequalifier tq; struct parameter *p; - char *name; uint64_t offset; enum tokenkind op; bool lvalue; @@ -436,59 +499,7 @@ postfixexpr(struct scope *s, struct expression *r) case TLPAREN: /* function call */ next(); if (r->kind == EXPRIDENT && r->ident.decl->kind == DECLBUILTIN) { - switch (r->ident.decl->builtin) { - case BUILTINVASTART: - e = mkexpr(EXPRBUILTIN, &typevoid, 0); - e->builtin.kind = BUILTINVASTART; - e->builtin.arg = exprconvert(assignexpr(s), &typevalistptr); - expect(TCOMMA, "after va_list"); - free(expect(TIDENT, "after ','")); - // XXX: check that this was actually a parameter name? - break; - case 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); - break; - case 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)); - e = exprconvert(e, &typevoid); - break; - case BUILTINVAEND: - e = mkexpr(EXPRBUILTIN, &typevoid, 0); - e->builtin.kind = BUILTINVAEND; - exprconvert(assignexpr(s), &typevalistptr); - break; - case BUILTINOFFSETOF: - t = typename(s); - expect(TCOMMA, "after type name"); - name = expect(TIDENT, "after ','"); - if (t->kind != TYPESTRUCT && t->kind != TYPEUNION) - error(&tok.loc, "type is not a struct/union type"); - offset = 0; - if (!typemember(t, name, &offset)) - error(&tok.loc, "struct/union has no member named '%s'", name); - e = mkconstexpr(&typeulong, offset); - free(name); - break; - case BUILTINALLOCA: - e = mkexpr(EXPRBUILTIN, mkpointertype(&typevoid), 0); - e->builtin.kind = BUILTINALLOCA; - e->builtin.arg = exprconvert(assignexpr(s), &typeulong); - break; - case BUILTININFF: - e = mkexpr(EXPRCONST, &typefloat, 0); - /* TODO: use INFINITY here when we can handle musl's math.h */ - e->constant.f = strtod("inf", NULL); - break; - default: - fatal("internal error; unknown builtin"); - } + e = builtinfunc(s, r->ident.decl->builtin); expect(TRPAREN, "after builtin parameters"); break; } |