diff options
| author | 2022-08-19 06:50:12 +0200 | |
|---|---|---|
| committer | 2022-08-19 06:50:12 +0200 | |
| commit | 01969818aec859611ca1989783b6e0d7f81bdf9e (patch) | |
| tree | 80324a21b5b4647107d6596eaabd741e9f824f39 /bootstrap | |
| parent | eb48600f4da4e52dd2cb46a284474c4cba8fe237 (diff) | |
alignof, offsetof
Diffstat (limited to 'bootstrap')
| -rw-r--r-- | bootstrap/all.h | 2 | ||||
| -rw-r--r-- | bootstrap/parse.c | 46 | ||||
| -rw-r--r-- | bootstrap/test.cff | 1 |
3 files changed, 44 insertions, 5 deletions
diff --git a/bootstrap/all.h b/bootstrap/all.h index 34bab40..1bfe919 100644 --- a/bootstrap/all.h +++ b/bootstrap/all.h @@ -30,6 +30,7 @@ struct span { /* must be alpha sorted */ #define LIST_KEYWORDS(_) \ + _(alignof) \ _(and) \ _(as) \ _(break) \ @@ -47,6 +48,7 @@ struct span { _(if) \ _(import) \ _(let) \ + _(offsetof) \ _(or) \ _(return) \ _(sizeof) \ diff --git a/bootstrap/parse.c b/bootstrap/parse.c index 0abaf45..31469df 100644 --- a/bootstrap/parse.c +++ b/bootstrap/parse.c @@ -907,8 +907,10 @@ structidx2fld(const struct type *ty, int idx) { } static int -structfldnam2idx(const struct type *ty, const char *name) { +aggfldnam2idx(const struct type *ty, const char *name) { assert(name); + if (ty->t != TYunion && ty->t != TYstruct && ty->t != TYeunion) + return -1; for (int i = 0; i < ty->agg.flds.n; ++i) if (!strcmp(name, ty->agg.flds.d[i].name)) return i; @@ -917,7 +919,7 @@ structfldnam2idx(const struct type *ty, const char *name) { static struct aggfield * findaggfield(const struct type *ty, const char *name) { - int i = structfldnam2idx(ty, name); + int i = aggfldnam2idx(ty, name); return i < 0 ? NULL : &ty->agg.flds.d[i]; } @@ -957,7 +959,7 @@ parsestructini(struct parser *P, const struct type *ty) { if (lexmatch(P, &tok, '.')) { const char *fnam = (tok = lexexpect(P, TKident)).str; lexexpect(P, ':'); - idx = structfldnam2idx(ty, fnam); + idx = aggfldnam2idx(ty, fnam); if (idx < 0) fatal(P, tok.span, "%s %t has no field `%s'", kind, ty, fnam); } @@ -1225,7 +1227,7 @@ pexprimary(struct parser *P) { ex.span = tok.span; } else if (lexmatch(P, &tok, TKkw_sizeof)) { ex.t = Eintlit; - ex.ty = ty_isize; + ex.ty = ty_usize; if (lexmatch(P, &tok, '(')) { struct expr exp = parseexpr(P); ex.i = exp.ty->size; @@ -1234,6 +1236,40 @@ pexprimary(struct parser *P) { const struct type *ty = parsetype(P); ex.i = ty->size; } + } else if (lexmatch(P, &tok, TKkw_alignof)) { + ex.t = Eintlit; + ex.ty = ty_usize; + if (lexmatch(P, &tok, '(')) { + struct expr exp = parseexpr(P); + ex.i = exp.ty->align; + lexexpect(P, ')'); + } else { + const struct type *ty = parsetype(P); + ex.i = ty->align; + } + } else if (lexmatch(P, &tok, TKkw_offsetof)) { + lexexpect(P, '('); + const struct type *ty = parsetype(P); + lexexpect(P, ','); + size_t off = 0; + for (;;) { + const char *name = (tok = lexexpect(P, TKident)).str; + struct aggfield *fld = findaggfield(ty, name); + if (!fld) { + fatal(P, tok.span, "%t has no such field %T", ty, tok); + } + off += fld->off; + ty = fld->ty; + if (!lexmatch(P, &tok, '.')) { + lexmatch(P, &tok, ','); + lexexpect(P, ')'); + break; + } + } + ex.t = Eintlit; + ex.ty = ty_usize; + ex.u = off; + } else { experr: fatal(P, tok.span, "expected expression (near %s)", tok2str(tok)); @@ -1424,7 +1460,7 @@ pexpostfix(struct parser *P) { bool konst = ty->konst; ty = unconstify(ty); if (ty->t == TYstruct || ty->t == TYunion || ty->t == TYeunion) { - int idx = structfldnam2idx(ty, fnam); + int idx = aggfldnam2idx(ty, fnam); struct aggfield *fld = &ty->agg.flds.d[idx]; if (idx < 0) fatal(P, tok.span, "%t has no such field `%s'", ty, fnam); diff --git a/bootstrap/test.cff b/bootstrap/test.cff index 5e384af..ef0bbfb 100644 --- a/bootstrap/test.cff +++ b/bootstrap/test.cff @@ -107,6 +107,7 @@ extern fn main (argc int, argv **u8) int { printf("sizeof(is) = %zu\n", sizeof(is)); printf("sizeof *void = %zu\n", sizeof *void); + printf("alignof f64= %zu\n", alignof f64); printf("1.2 -> %#.8x\n", transmute(u32, 1.2f)); switch is.#len { |