diff options
| author | 2025-10-19 11:06:58 +0200 | |
|---|---|---|
| committer | 2025-10-19 11:06:58 +0200 | |
| commit | 9bf5c97d3b5391c6cf3757629d09a53403a64f45 (patch) | |
| tree | e8ca609e27d72b4011be6803a45d5d3773a05b05 /c | |
| parent | dea8fd171acb54b6d9685422d5e391fb55074008 (diff) | |
c irgen fixes
Diffstat (limited to 'c')
| -rw-r--r-- | c/c.c | 52 | ||||
| -rw-r--r-- | c/c.h | 9 | ||||
| -rw-r--r-- | c/eval.c | 20 |
3 files changed, 60 insertions, 21 deletions
@@ -1440,8 +1440,7 @@ aggdesignator(struct initparser *ip, union type ty, const char *name, const stru if (sub == -1) { --ip->sub; ip->sub->idx = save; - } - else return sub; + } else return sub; } } return -1; @@ -1501,7 +1500,8 @@ designators(struct initparser *ip, struct comp *cm) if (!isagg(ip->sub->ty)) error(&span, "member designator used with non-aggregate type '%ty'", ip->sub->ty); else if (tk.t == TKIDENT) { - do { + int idx; + for (;;) { idx = aggdesignator(ip, ip->sub->ty, tk.s, &span); if (idx >= 0) break; if (ip->sub != ip->cur && !ttypenames[typedata[ip->sub->ty.dat].id]) { @@ -1509,7 +1509,7 @@ designators(struct initparser *ip, struct comp *cm) --ip->sub; continue; } - } while (0); + } ip->sub->idx = idx; if (idx < 0) error(&span, "%ty has no such field: '%s'", ip->cur->ty, tk.s); @@ -2531,6 +2531,7 @@ mkhiddensym(const char *fnname, const char *name, int id) } static void geninit(struct function *fn, union type t, union ref dst, const struct expr *src); +static union ref condexprvalue(struct function *fn, const struct expr *ex, bool discard); static union ref expraddr(struct function *fn, const struct expr *ex) @@ -2576,9 +2577,6 @@ expraddr(struct function *fn, const struct expr *ex) r = expraddr(fn, &ex->sub[1]); structcopy(fn, ex->ty, expraddr(fn, &ex->sub[0]), r); return r; - case ESEQ: - expreffects(fn, &ex->sub[0]); - return expraddr(fn, &ex->sub[1]); case ECALL: assert(isagg(ex->ty)); return compilecall(fn, ex); @@ -2589,7 +2587,14 @@ expraddr(struct function *fn, const struct expr *ex) geninit(fn, ex->ty, r, ex); return r; } else { + assert(!"nyi"); } + case ESEQ: + expreffects(fn, &ex->sub[0]); + return expraddr(fn, &ex->sub[1]); + case ECOND: + assert(isagg(ex->ty)); + return condexprvalue(fn, ex, 0); default: assert(!"lvalue?>"); } @@ -2662,15 +2667,28 @@ geninit(struct function *fn, union type t, union ref dst, const struct expr *src uint off = val->off; struct expr *ex = &val->ex; adr = off == 0 ? dst : addinstr(fn, mkinstr(Oadd, KPTR, dst, mkref(RICON, off))); - genstore(fn, ex->ty, adr, exprvalue(fn, ex)); + if (ex->t == EINIT || ex->t == ESTRLIT) { + geninit(fn, ex->ty, adr, ex); + } else if (isagg(ex->ty)) { + structcopy(fn, ex->ty, dst, expraddr(fn, ex)); + } else { + genstore(fn, ex->ty, adr, exprvalue(fn, ex)); + } } } else if (src->t == ESTRLIT) { + union type ctyp = typechild(src->ty); + uint csiz = typesize(ctyp); adr = dst; for (uint i = 0; i < src->s.n; ++i) { - genstore(fn, mktype(TYCHAR), adr, mkref(RICON, src->s.p[i])); - adr = addinstr(fn, mkinstr(Oadd, KPTR, dst, mkref(RICON, i+1))); + if (csiz == 1) + genstore(fn, ctyp, adr, mkref(RICON, src->s.p[i])); + else if (csiz == 2) + genstore(fn, ctyp, adr, mkref(RICON, src->s.w16[i])); + else + genstore(fn, ctyp, adr, mkintcon(KI4, src->s.w32[i])); + adr = addinstr(fn, mkinstr(Oadd, KPTR, dst, mkref(RICON, (i+1)*csiz))); } - genstore(fn, mktype(TYCHAR), adr, ZEROREF); /* null term */ + genstore(fn, ctyp, adr, ZEROREF); /* null term */ } else assert(0); } @@ -2679,6 +2697,7 @@ cvt(struct function *fn, union type to, union type from, union ref ref) { enum irclass kto = type2cls[scalartypet(to)], kfrom = type2cls[scalartypet(from)]; struct instr ins = {0}; + if (to.bits == from.bits) return ref; assert(kto && kfrom); if (kto == kfrom && to.t != TYBOOL) return ref; if (ref.t == RICON && kto < KF4) return ref; @@ -2903,8 +2922,13 @@ condexprvalue(struct function *fn, const struct expr *ex, bool discard) condexprrec(fn, ex, discard ? NULL : &phis, -1, NULL, dst); useblk(fn, dst); if (discard) return NOREF; - k = type2cls[scalartypet(ex->ty)]; - assert(k); + if (isscalar(ex->ty)) { + k = type2cls[scalartypet(ex->ty)]; + assert(k); + } else { + assert(isagg(ex->ty) || isptrcvt(ex->ty)); + k = KPTR; + } r = addphi(fn, k, phis.ref.p); vfree(&phis.ref); return r; @@ -2931,7 +2955,7 @@ compilecall(struct function *fn, const struct expr *ex) for (int i = 0; i < ex->narg; ++i) { struct expr *arg = &sub[i+1]; union type ty = i < td->nmemb ? td->param[i] : argpromote(arg->ty); - union ref r = cvt(fn, ty, arg->ty, exprvalue(fn, arg)); + union ref r = cvt(fn, ty, typedecay(arg->ty), exprvalue(fn, arg)); vpush(&insns, mkarginstr(mkirtype(ty), r)); } for (int i = 0; i < insns.n; ++i) @@ -36,7 +36,14 @@ struct expr { } fld; /* EGETF */ }; uvlong u; vlong i; double f; /* ENUMLIT */ - struct bytes s; /* ESTRLIT */ + struct { + union { + uchar *p; + ushort *w16; + uint *w32; + }; + uint n; + } s; /* ESTRLIT */ struct decl *sym; /* ESYM */ struct init *init; /* EINIT */ }; @@ -80,26 +80,34 @@ unop(struct expr *ex, enum evalmode mode) if (mode >= EVSTATICINI && ex->t == EDEREF) { uvlong off; - struct bytes s; + uchar *p; + uint len; + uint csiz; if (sub->t == ESTRLIT) { /* *"s" */ off = 0; - s = sub->s; + p = sub->s.p, len = sub->s.n; + csiz = typesize(sub->ty); } else if (sub->t == EADD && sub->sub[0].t == ESTRLIT && eval(&sub->sub[1], EVINTCONST)) { /* "s"[0] */ assert(sub->sub[1].t == ENUMLIT && isint(sub->sub[1].ty)); off = sub->sub[1].u; - s = sub->sub[0].s; + p = sub->sub[0].s.p, len = sub->sub[0].s.n; + csiz = typesize(sub->sub[0].ty); } else if (sub->t == EADD && sub->sub[1].t == ESTRLIT && eval(&sub->sub[0], EVINTCONST)) { /* 0["s"] */ assert(sub->sub[0].t == ENUMLIT && isint(sub->sub[0].ty)); off = sub->sub[0].u; - s = sub->sub[1].s; + p = sub->sub[1].s.p, len = sub->sub[1].s.n; + csiz = typesize(sub->sub[1].ty); } else return 0; - if (off > s.n) return 0; + if (off > len) return 0; ex->t = ENUMLIT; ex->ty = mktype(TYINT); - ex->u = off == s.n ? 0 : s.p[off]; + if (off == len) ex->u = 0; + else if (csiz == 1) ex->u = p[off]; + else if (csiz == 2) ex->u = ((short *)p)[off]; + else if (csiz == 4) ex->u = ((int *)p)[off]; return 1; } if (ex->t == EADDROF) { |