aboutsummaryrefslogtreecommitdiff
path: root/bootstrap
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2022-08-12 11:20:43 +0200
committerlemon <lsof@mailbox.org>2022-08-12 11:20:43 +0200
commiteff929f0d323559f3b2e9272e3c1d4aa82fc5c80 (patch)
treec3dd54fe4ed4a3082f455c8fe37436f767760977 /bootstrap
parent19f1093f0929b989a06cdee2e7d175e6db15559c (diff)
va list, cont fix
Diffstat (limited to 'bootstrap')
-rw-r--r--bootstrap/all.h10
-rw-r--r--bootstrap/cgen.c40
-rw-r--r--bootstrap/dump.c2
-rw-r--r--bootstrap/parse.c25
-rw-r--r--bootstrap/types.c7
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
};