diff options
| author | 2025-10-15 19:40:06 +0200 | |
|---|---|---|
| committer | 2025-10-15 19:40:06 +0200 | |
| commit | 15d29261df4c92208754fe13bf289fb881084cb9 (patch) | |
| tree | 5ace2fdb4316810ebb2c696ce5e1f3d850697914 | |
| parent | 74145741f194f914ea479801a19d83708c8b72fd (diff) | |
be able to eval offsetof() macro
| -rw-r--r-- | c.c | 6 | ||||
| -rw-r--r-- | eval.c | 42 |
2 files changed, 36 insertions, 12 deletions
@@ -1245,7 +1245,7 @@ iniwrite(struct comp *cm, struct initparser *ip, uint off, union type ty, struct } else { union ref sym; vlong addend; - efmt("<<> %ty <- %ty\n", ty, ex->ty); + //efmt("<<> %ty <- %ty\n", ty, ex->ty); expr2reloc(&sym, &addend, ex); assert(sym.t == RXCON); if (!ip->dyn) { @@ -3179,7 +3179,7 @@ compileexpr(struct function *fn, const struct expr *ex, bool discard) genstore(fn, ex->ty, r, q); } if (discard) return NOREF; - return narrow(fn, cls, sub[0].ty, q, bitsiz); + return bitsiz ? narrow(fn, cls, sub[0].ty, q, bitsiz) : q; case ESETMUL: ins.op = isunsigned(ex->ty) ? Oumul : Omul; goto Compound; @@ -3234,7 +3234,7 @@ compileexpr(struct function *fn, const struct expr *ex, bool discard) genstore(fn, ex->ty, r, q); } if (discard) return NOREF; - return narrow(fn, cls, ex->ty, q, bitsiz); + return bitsiz ? narrow(fn, cls, ex->ty, q, bitsiz) : q; case ECALL: r = compilecall(fn, ex); if (isint(ex->ty)) @@ -3,6 +3,7 @@ static int targ2hosttype(enum typetag t) { + if (t == TYPTR) t = targ_64bit ? TYUVLONG : TYUINT; if (isintt(t)) { int siz = targ_primsizes[t]; int sgn = issignedt(t); @@ -23,10 +24,10 @@ targ2hosttype(enum typetag t) } static bool -numcast(enum typetag t, struct expr *dst, const struct expr *src) +numcast(union type ty, struct expr *dst, const struct expr *src) { struct expr tmp; - enum typetag td = targ2hosttype(t); + enum typetag td = targ2hosttype(ty.t); enum typetag ts = targ2hosttype(src->ty.t == TYENUM ? src->ty.backing : src->ty.t); if (src == dst) tmp = *src, src = &tmp; @@ -68,7 +69,7 @@ numcast(enum typetag t, struct expr *dst, const struct expr *src) #undef TF dst->t = ENUMLIT; - dst->ty = mktype(t); + dst->ty = ty; return 1; } @@ -101,9 +102,25 @@ unop(struct expr *ex, enum evalmode mode) ex->u = off == s.n ? 0 : s.p[off]; return 1; } + if (ex->t == EADDROF) { + assert(ex->ty.t == TYPTR); + /* oh boy */ + /* match &(*(T *)12345).fld */ + if (sub->t == EGETF && sub->sub->t == EDEREF && eval(sub->sub->sub, EVFOLD) && sub->sub->sub->t == ENUMLIT) { + ex->t = ENUMLIT; + ex->u = sub->sub->sub->u + sub->fld.off; + return 1; + } + } if (sub->t != ENUMLIT && !eval(sub, mode)) return 0; switch (ex->t) { case ECAST: + if (ex->ty.t == TYPTR) { + ex->t = ENUMLIT; + ex->u = sub->u; + return 1; + } + break; case EPLUS: break; case ENEG: @@ -121,7 +138,7 @@ unop(struct expr *ex, enum evalmode mode) default: return 0; } - if (!numcast(ex->ty.t, ex, sub)) return 0; + if (!numcast(ex->ty, ex, sub)) return 0; return 1; } @@ -160,14 +177,15 @@ binop(struct expr *ex, enum evalmode mode) int t; struct expr *lhs = &ex->sub[0], *rhs = &ex->sub[1]; + if (ex->ty.t == TYPTR) mode = EVFOLD; if (!eval(lhs, mode)) return 0; if (!eval(rhs, mode)) return 0; if (in_range(ex->t, EADD, ESHR)) oty = ex->ty; else oty = cvtarith(lhs->ty, rhs->ty); - if (!numcast(oty.t, lhs, lhs)) return 0; - if (!numcast(oty.t, rhs, rhs)) return 0; + if (!numcast(oty, lhs, lhs)) return 0; + if (!numcast(oty, rhs, rhs)) return 0; flt = isflt(oty); sgn = issigned(oty); switch (ex->t) { @@ -175,7 +193,12 @@ binop(struct expr *ex, enum evalmode mode) case EADD: if (flt) lhs->f += rhs->f; else lhs->u += rhs->u; break; - case ESUB: if (flt) lhs->f -= rhs->f; + case ESUB: if (oty.t == TYPTR) { + assert(lhs->t == ENUMLIT && rhs->t == ENUMLIT); + assert(!isincomplete(typechild(ex->ty))); + lhs->u = (lhs->u - rhs->u) / typesize(typechild(ex->ty)); + } + ef (flt) lhs->f -= rhs->f; else lhs->u -= rhs->u; break; case EMUL: if (flt) lhs->f *= rhs->f; @@ -245,7 +268,7 @@ binop(struct expr *ex, enum evalmode mode) #undef ef } - return numcast(ex->ty.t, ex, lhs); + return numcast(ex->ty, ex, lhs); } bool @@ -255,7 +278,7 @@ eval(struct expr *ex, enum evalmode mode) if (mode <= EVINTCONST) return isint(ex->ty); return 1; } - if (ex->t == ESTRLIT) return 1; + if (ex->t == ESTRLIT && mode > EVINTCONST) return 1; if (mode == EVSTATICINI && isaddrconst(ex)) { struct expr *e = ex; while (e->t == ECAST) e = e->sub; @@ -265,6 +288,7 @@ eval(struct expr *ex, enum evalmode mode) } return 1; } + mode += mode == EVINTCONST; if (isunop(ex->t)) return unop(ex, mode) && eval(ex, mode); if (isbinop(ex->t)) return binop(ex, mode) && eval(ex, mode); if (ex->t == ESEQ) { |