diff options
Diffstat (limited to 'c')
| -rw-r--r-- | c/builtin.c | 66 | ||||
| -rw-r--r-- | c/c.c | 42 | ||||
| -rw-r--r-- | c/c.h | 1 |
3 files changed, 77 insertions, 32 deletions
diff --git a/c/builtin.c b/c/builtin.c index aabd750..5c59857 100644 --- a/c/builtin.c +++ b/c/builtin.c @@ -32,13 +32,13 @@ callcheck(const struct span *span, int nparam, const union type *param, int narg return callcheck(&ex->span, countof(par)-1, par+1, ex->narg, ex->sub+1); \ } +/* __builtin_va_start */ static bool va_start_sema(struct comp *cm, struct expr *ex) { ex->ty = mktype(TYVOID); return callcheck(&ex->span, 1, &cvalistty, ex->narg, ex->sub+1); } - static union ref va_start_comp(struct function *fn, struct expr *ex, bool discard) { @@ -50,8 +50,7 @@ va_start_comp(struct function *fn, struct expr *ex, bool discard) return NOREF; } -DEF_FNLIKE_SEMA(trap, mktype(TYVOID), ) - +/* __builtin_va_end */ static bool va_end_sema(struct comp *cm, struct expr *ex) { @@ -65,13 +64,13 @@ va_end_comp(struct function *fn, struct expr *ex, bool discard) return NOREF; } +/* __builtin_va_copy */ DEF_FNLIKE_SEMA(va_copy, mktype(TYVOID), cvalistty, cvalistty) - static union ref va_copy_comp(struct function *fn, struct expr *ex, bool discard) { union irtype typ = mkirtype(cvalistty.t == TYARRAY ? typechild(cvalistty) : cvalistty); - for (int i = 1; i < 2; ++i) + for (int i = 1; i <= 2; ++i) assert(typedecay(ex->sub[i].ty).bits == typedecay(cvalistty).bits); union ref dst = compileexpr(fn, &ex->sub[1], 0), src = compileexpr(fn, &ex->sub[2], 0); addinstr(fn, mkarginstr(typ, dst)); @@ -80,6 +79,8 @@ va_copy_comp(struct function *fn, struct expr *ex, bool discard) return NOREF; } +/* __builtin_trap */ +DEF_FNLIKE_SEMA(trap, mktype(TYVOID), ) static union ref trap_comp(struct function *fn, struct expr *ex, bool discard) { @@ -88,17 +89,51 @@ trap_comp(struct function *fn, struct expr *ex, bool discard) return NOREF; } -union ref -builtin_va_arg_comp(struct function *fn, const struct expr *ex, bool discard) +static inline union ref +cvtintref(struct function *fn, enum irclass dst, union ref src) { - assert(ex->t == EVAARG && ex->ty.t); - enum irclass k = isagg(ex->ty) ? KPTR : type2cls[scalartypet(ex->ty)]; - return addinstr(fn, mkinstr(Ovaarg, k, compileexpr(fn, ex->sub, 0), mktyperef(mkirtype(ex->ty)))); + if (src.t == RTMP) { + if (insrescls(instrtab[src.i]) != dst) + return addinstr(fn, mkinstr(Ocopy, dst, src)); + return src; + } else if (isintcon(src)) { + vlong x = intconval(src); + return mkintcon(dst, cls2siz[dst] == 4 ? (int)x : x); + } + assert(!"int ref?"); +} + +/* __builtin_bswap16 */ +DEF_FNLIKE_SEMA(bswap16, mktype(TYUSHORT), mktype(TYUSHORT)) +static union ref +bswap16_comp(struct function *fn, struct expr *ex, bool discard) +{ + assert(isint(ex->ty)); + return irunop(fn, Obswap16, KI32, scalarcvt(fn, ex->ty, ex->sub[1].ty, + compileexpr(fn, &ex->sub[1], 0))); +} +/* __builtin_bswap32 */ +DEF_FNLIKE_SEMA(bswap32, mktype(TYUINT), mktype(TYUINT)) +static union ref +bswap32_comp(struct function *fn, struct expr *ex, bool discard) +{ + assert(isint(ex->ty)); + return irunop(fn, Obswap32, KI32, scalarcvt(fn, ex->ty, ex->sub[1].ty, + compileexpr(fn, &ex->sub[1], 0))); +} +/* __builtin_bswap64 */ +DEF_FNLIKE_SEMA(bswap64, mktype(TYUVLONG), mktype(TYUVLONG)) +static union ref +bswap64_comp(struct function *fn, struct expr *ex, bool discard) +{ + assert(isint(ex->ty)); + return irunop(fn, Obswap64, KI64, scalarcvt(fn, ex->ty, ex->sub[1].ty, + compileexpr(fn, &ex->sub[1], 0))); } #define LIST_BUILTINS(_) \ _(va_start) _(va_copy) _(va_end) \ - _(trap) + _(trap) _(bswap16) _(bswap32) _(bswap64) static const struct { const char *name; @@ -121,6 +156,15 @@ putbuiltins(struct env *env) } } +/* this is separate because it's a keyword */ +union ref +builtin_va_arg_comp(struct function *fn, const struct expr *ex, bool discard) +{ + assert(ex->t == EVAARG && ex->ty.t); + enum irclass k = isagg(ex->ty) ? KPTR : type2cls[scalartypet(ex->ty)]; + return addinstr(fn, mkinstr(Ovaarg, k, compileexpr(fn, ex->sub, 0), mktyperef(mkirtype(ex->ty)))); +} + bool hasbuiltin(const char *name, uint len) { @@ -3146,8 +3146,8 @@ isboollike(struct function *fn, union ref r) return 0; } -static union ref -cvt(struct function *fn, union type to, union type from, union ref ref) +union ref +scalarcvt(struct function *fn, union type to, union type from, union ref ref) { enum irclass kto = type2cls[scalartypet(to)], kfrom = type2cls[scalartypet(from)]; enum op op; @@ -3172,7 +3172,7 @@ cvt(struct function *fn, union type to, union type from, union ref ref) if (to.t == TYBOOL) { if (from.t == TYBOOL) return ref; if (isboollike(fn, ref)) - return kfrom == KI32 ? ref : cvt(fn, mktype(TYINT), from, ref); + return kfrom == KI32 ? ref : scalarcvt(fn, mktype(TYINT), from, ref); return irbinop(fn, Oneq, kfrom, ref, ZEROREF); } else if (kfrom == KI32 && issigned(from)) op = Oexts32; @@ -3223,7 +3223,7 @@ genptroff(struct function *fn, enum op op, uint siz, union ref ptr, union ref off; assert(siz); - idx = cvt(fn, mktype(targ_sizetype), t, idx); + idx = scalarcvt(fn, mktype(targ_sizetype), t, idx); if (siz == 1) off = idx; else if (idx.t == RICON) { if (op == Osub) op = Oadd, idx.i = -idx.i; @@ -3340,7 +3340,7 @@ Recur: } else { union ref val = exprvalue(fn, ex); if (isscalar(phis->typ)) - val = cvt(fn, phis->typ, ex->ty, val); + val = scalarcvt(fn, phis->typ, ex->ty, val); else assert(ex->ty.bits == phis->typ.bits); vpush(&phis->ref, val); } @@ -3396,7 +3396,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, typedecay(arg->ty), exprvalue(fn, arg)); + union ref r = scalarcvt(fn, ty, typedecay(arg->ty), exprvalue(fn, arg)); vpush(&insns, mkarginstr(mkirtype(ty), r)); } for (int i = 0; i < insns.n; ++i) @@ -3541,7 +3541,7 @@ compileexpr(struct function *fn, const struct expr *ex, bool discard) case EPLUS: r = compileexpr(fn, sub, discard); if (discard) return NOREF; - r = cvt(fn, ex->ty, sub->ty, r); + r = scalarcvt(fn, ex->ty, sub->ty, r); if (isint(ex->ty) && (typesize(ex->ty) < typesize(sub->ty) || issigned(ex->ty) != issigned(sub->ty))) return narrow(fn, type2cls[scalartypet(ex->ty)], ex->ty, r, 0); return r; @@ -3553,7 +3553,7 @@ compileexpr(struct function *fn, const struct expr *ex, bool discard) Unary: l = compileexpr(fn, sub, discard); if (discard) return NOREF; - l = cvt(fn, ex->ty, sub->ty, l); + l = scalarcvt(fn, ex->ty, sub->ty, l); return irunop(fn, op, cls, l); case ELOGNOT: for (; sub->t == ELOGNOT; ex = sub, sub = sub->sub) @@ -3561,7 +3561,7 @@ compileexpr(struct function *fn, const struct expr *ex, bool discard) op = Oequ + swp; l = compileexpr(fn, sub, discard); if (discard) return NOREF; - l = cvt(fn, ex->ty, sub->ty, l); + l = scalarcvt(fn, ex->ty, sub->ty, l); r = mkintcon(cls, 0); return irbinop(fn, op, cls, l, r); case EDEREF: @@ -3609,8 +3609,8 @@ compileexpr(struct function *fn, const struct expr *ex, bool discard) return genptrdiff(fn, typesize(typechild(sub[0].ty)), l, r); } else if ((op != Oadd && op != Osub) || cls != KPTR) { /* num OP num */ - l = cvt(fn, ex->ty, sub[0].ty, l); - r = cvt(fn, ex->ty, sub[1].ty, r); + l = scalarcvt(fn, ex->ty, sub[0].ty, l); + r = scalarcvt(fn, ex->ty, sub[1].ty, r); } else { assert(isptrcvt(sub[0].ty)); /* ptr +/- num */ @@ -3680,13 +3680,13 @@ compileexpr(struct function *fn, const struct expr *ex, bool discard) l = compileexpr(fn, &sub[0], discard); r = compileexpr(fn, &sub[1], discard); if (discard) return NOREF; - l = cvt(fn, ty, sub[0].ty, l); - r = cvt(fn, ty, sub[1].ty, r); + l = scalarcvt(fn, ty, sub[0].ty, l); + r = scalarcvt(fn, ty, sub[1].ty, r); cls = type2cls[ty.t]; return irbinop(fn, op, cls, l, r); case ESET: assert(isscalar(ex->ty)); - q = cvt(fn, sub[0].ty, sub[1].ty, exprvalue(fn, &sub[1])); + q = scalarcvt(fn, sub[0].ty, sub[1].ty, exprvalue(fn, &sub[1])); if (sub[0].t == EGETF && (bitsiz = sub[0].fld.bitsiz)) { /* bit-field */ adr = expraddr(fn, &sub[0].sub[0]); @@ -3744,10 +3744,10 @@ compileexpr(struct function *fn, const struct expr *ex, bool discard) adr = expraddr(fn, &sub[0]); l = genload(fn, ex->ty, adr, ex->qual & QVOLATILE); if ((op != Oadd && op != Osub) || cls != KPTR) { - l = cvt(fn, ty, sub[0].ty, l); - r = cvt(fn, ty, sub[1].ty, r); + l = scalarcvt(fn, ty, sub[0].ty, l); + r = scalarcvt(fn, ty, sub[1].ty, r); q = irbinop(fn, op, type2cls[ty.t], l, r); - q = cvt(fn, ex->ty, ty, q); + q = scalarcvt(fn, ex->ty, ty, q); } else { q = genptroff(fn, op, typesize(typechild(ex->ty)), l, sub[1].ty, r); } @@ -3764,7 +3764,7 @@ compileexpr(struct function *fn, const struct expr *ex, bool discard) for (bool c; knowntruthy(&c, &ex->sub[0]);) { r = compileexpr(fn, &ex->sub[2-c], discard); if (discard) return NOREF; - return cvt(fn, ex->ty, ex->sub[2-c].ty, r); + return scalarcvt(fn, ex->ty, ex->sub[2-c].ty, r); } if (ex->ty.t == TYVOID || discard) { @@ -3789,7 +3789,7 @@ compileexpr(struct function *fn, const struct expr *ex, bool discard) c ^= ex->t == ELOGIOR; r = compileexpr(fn, &ex->sub[c], discard); if (discard) return NOREF; - return cvt(fn, mktype(TYBOOL), ex->sub[c].ty, r); + return scalarcvt(fn, mktype(TYBOOL), ex->sub[c].ty, r); } return condexprvalue(fn, ex, discard); case ESEQ: @@ -4314,7 +4314,7 @@ stmt(struct comp *cm, struct function *fn) } EMITS { if (isscalar(fn->retty)) - r = cvt(fn, fn->retty, ex.ty, exprvalue(fn, &ex)); + r = scalarcvt(fn, fn->retty, ex.ty, exprvalue(fn, &ex)); else if (fn->retty.t == TYVOID) r = (expreffects(fn, &ex), NOREF); else @@ -4424,7 +4424,7 @@ localdecl(struct comp *cm, struct function *fn, bool forini) structcopy(fn, ty, mkref(RTMP, decl.id), exprvalue(fn, &ini)); else { genstore(fn, ty, mkref(RTMP, decl.id), - cvt(fn, ty, ini.ty, exprvalue(fn, &ini))); + scalarcvt(fn, ty, ini.ty, exprvalue(fn, &ini))); } } } else if (decl.scls == SCEXTERN) { @@ -108,6 +108,7 @@ struct function; int envadddecl(struct env *env, const struct decl *d); bool assigncheck(union type t, const struct expr *src); union ref expraddr(struct function *, const struct expr *); +union ref scalarcvt(struct function *, union type to, union type from, union ref); union ref compileexpr(struct function *, const struct expr *, bool discard); /** builtin.c **/ |