diff options
| author | 2022-08-12 11:20:43 +0200 | |
|---|---|---|
| committer | 2022-08-12 11:20:43 +0200 | |
| commit | eff929f0d323559f3b2e9272e3c1d4aa82fc5c80 (patch) | |
| tree | c3dd54fe4ed4a3082f455c8fe37436f767760977 /bootstrap | |
| parent | 19f1093f0929b989a06cdee2e7d175e6db15559c (diff) | |
va list, cont fix
Diffstat (limited to 'bootstrap')
| -rw-r--r-- | bootstrap/all.h | 10 | ||||
| -rw-r--r-- | bootstrap/cgen.c | 40 | ||||
| -rw-r--r-- | bootstrap/dump.c | 2 | ||||
| -rw-r--r-- | bootstrap/parse.c | 25 | ||||
| -rw-r--r-- | bootstrap/types.c | 7 |
5 files changed, 71 insertions, 13 deletions
diff --git a/bootstrap/all.h b/bootstrap/all.h index 6a0de81..f8eb769 100644 --- a/bootstrap/all.h +++ b/bootstrap/all.h @@ -157,6 +157,7 @@ enum typetype { TYstruct, TYunion, TYeunion, + TYvalist, }; struct type { @@ -327,6 +328,9 @@ enum exprtype { Elen, Eeuini, Eeutag, + Evastart, + Evaarg, + Evaend, }; struct blockstmt { @@ -488,7 +492,9 @@ static const struct targ { llongsize, sizesize, f32align, - f64align; + f64align, + valistsize, + valistalign; bool charsigned; } g_targ = { .ptrsize = sizeof(void *), @@ -499,6 +505,8 @@ static const struct targ { .sizesize = sizeof(size_t), .f32align = alignof(float), .f64align = alignof(double), + .valistsize = sizeof(va_list), + .valistalign = alignof(va_list), .charsigned = CHAR_MIN < 0, }; diff --git a/bootstrap/cgen.c b/bootstrap/cgen.c index 1629151..6321e92 100644 --- a/bootstrap/cgen.c +++ b/bootstrap/cgen.c @@ -37,6 +37,9 @@ gentype(const struct type *ty) { case TYenum: gentype(ty->enu.intty); break; + case TYvalist: + pri("__builtin_va_list"); + break; } if (ty->konst) pri(" const"); @@ -168,6 +171,7 @@ geneuiniex(struct expr *ex) { static void genexpr(struct expr *ex) { + assert(ex); const struct type *ty = unconstify(ex->ty); struct decl *decl; @@ -284,6 +288,15 @@ genexpr(struct expr *ex) { geneuiniex(ex); pri(")"); break; + case Evastart: + pri("__builtin_va_start(%e, %e)", ex->binop.lhs, ex->binop.rhs); + break; + case Evaarg: + pri("__builtin_va_arg(%e, %t)", ex->child, ex->ty); + break; + case Evaend: + pri("__builtin_va_end(%e)", ex->child); + break; } } @@ -343,15 +356,15 @@ genstmt(struct stmt *stmt) { } break; case Swhile: - pri("while (%e) {", &stmt->loop.test); + pri("while (%e) {_cont%d:;", &stmt->loop.test, stmt->loop.id); genblock(stmt->loop.body); - pri("_cont%d:;} _brk%d:;\n", stmt->loop.id, stmt->loop.id); + pri("} _brk%d:;\n", stmt->loop.id); break; case Sdowhile: - pri("do {"); + pri("do {_cont%d:;",stmt->loop.id); genblock(stmt->loop.body); - pri("_cont%d:;} while (%e); _brk%d:;\n", - stmt->loop.id, &stmt->loop.test, stmt->loop.id); + pri("} while (%e); _brk%d:;\n", + &stmt->loop.test, stmt->loop.id); break; case Sfor: pri("{\n"); @@ -361,10 +374,12 @@ genstmt(struct stmt *stmt) { pri("%e;", &stmt->loop.test); if (stmt->loop.next) pri(" %e", stmt->loop.next); - pri(") {"); + pri(") {goto _skip%d; _cont%d:", stmt->loop.id, stmt->loop.id); + if (stmt->loop.next) + pri(" %e;", stmt->loop.next); + pri("_skip%d:;", stmt->loop.id); genblock(stmt->loop.body); - pri("_cont%d:; }", stmt->loop.id); - pri("} _brk%d:;\n", stmt->loop.id); + pri("}} _brk%d:;\n", stmt->loop.id); break; case Siswitch: pri("switch (%e) {", &stmt->iswitch.test); @@ -505,6 +520,13 @@ liftnestedex(struct expr *ex) { case Eeuini: liftnestedex(ex->euini.ini); break; + case Evastart: + liftnestedex(ex->binop.lhs); + liftnestedex(ex->binop.rhs); + break; + case Evaarg: case Evaend: + liftnestedex(ex->child); + break; } } @@ -676,7 +698,7 @@ defctype(const struct type *ty, void *_) { if (!ty->_cname) switch (ty->t) { - case TYvoid: case TYbool: + case TYvoid: case TYbool: case TYvalist: case TYenum: case TYint: case TYfloat: break; case TYptr: diff --git a/bootstrap/dump.c b/bootstrap/dump.c index 3bd915f..bf63d22 100644 --- a/bootstrap/dump.c +++ b/bootstrap/dump.c @@ -66,6 +66,8 @@ pritype(const struct type *ty) { epri("%bc", '>'); } break; + case TYvalist: + epri("va_list"); } } diff --git a/bootstrap/parse.c b/bootstrap/parse.c index d0bea8e..7c31ce1 100644 --- a/bootstrap/parse.c +++ b/bootstrap/parse.c @@ -1416,7 +1416,32 @@ pexpostfix(struct parser *P) { if (lexpeek(P).t != '(') lexexpect(P, '('); + } else if (ex.ty->t == TYvalist) { + if (!strcmp(fnam, "start")) { + lexexpect(P, '('); + struct expr ex2 = parseexpr(P); + lexexpect(P, ')'); + ex = (struct expr) { + Evastart, ex.span, ty_void, + .binop.lhs = exprdup(ex), + .binop.rhs = exprdup(ex2) + }; + } else if (!strcmp(fnam, "arg")) { + lexexpect(P, '('); + ty = parsetype(P); + lexexpect(P, ')'); + ex = (struct expr) { + Evaarg, ex.span, ty, .child = exprdup(ex) + }; + } else if (!strcmp(fnam, "end")) { + lexexpect(P, '('); + lexexpect(P, ')'); + ex = (struct expr) { + Evaend, ex.span, ty_void, .child = exprdup(ex) + }; + } else goto badmet; } else { + badmet: fatal(P, tok.span, "cannot call `->%s': left-hand-side is not an aggregate (%t)", fnam, ex.ty); } diff --git a/bootstrap/types.c b/bootstrap/types.c index 9118392..66ae840 100644 --- a/bootstrap/types.c +++ b/bootstrap/types.c @@ -36,7 +36,7 @@ hashtype(const struct type *ty) { epri(""); switch (ty->t) { - case TYvoid: case TYbool: + case TYvoid: case TYbool: case TYvalist: break; case TYint: case TYfloat: h = fnv1az(h, ty->size); @@ -75,7 +75,7 @@ typeeql(const struct type *lhs, const struct type *rhs) { if (lhs->t != rhs->t || lhs->konst != rhs->konst) return 0; switch (lhs->t) { - case TYvoid: case TYbool: + case TYvoid: case TYbool: case TYvalist: return 1; case TYfloat: return lhs->size == rhs->size; @@ -206,7 +206,7 @@ const struct type *ty_iptrint, *ty_uptrint, *ty_c_int, *ty_c_uint, *ty_c_char, *ty_c_schar, *ty_c_uchar, *ty_c_short, *ty_c_ushort, *ty_c_long, *ty_c_ulong, *ty_c_llong, - *ty_c_ullong; + *ty_c_ullong, *ty_valist; void putprimtypes(struct env *env) { @@ -248,6 +248,7 @@ putprimtypes(struct env *env) { {"c_ulong", &ty_c_ulong, {TYint, t.longsize, IU}}, {"c_llong", &ty_c_llong, {TYint, t.llongsize, IS}}, {"c_ullong", &ty_c_ullong, {TYint, t.llongsize, IU}}, + {"va_list", &ty_valist, {TYvalist, t.valistsize, t.valistalign}}, #undef IS #undef IU }; |