aboutsummaryrefslogtreecommitdiffhomepage
path: root/type.c
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2026-03-17 13:22:00 +0100
committerlemon <lsof@mailbox.org>2026-03-17 13:22:00 +0100
commita8d6f8bf30c07edb775e56889f568ca20240bedf (patch)
treeb5a452b2675b2400f15013617291fe6061180bbf /type.c
parent24f14b7ad1af08d872971d72ce089a529911f657 (diff)
REFACTOR: move sources to src/
Diffstat (limited to 'type.c')
-rw-r--r--type.c311
1 files changed, 0 insertions, 311 deletions
diff --git a/type.c b/type.c
deleted file mode 100644
index e8a5b1e..0000000
--- a/type.c
+++ /dev/null
@@ -1,311 +0,0 @@
-#include "type.h"
-
-struct typedata typedata[1<<13];
-internstr ttypenames[1<<10];
-
-static ushort
-hashtd(const struct typedata *td)
-{
- uint h = td->t*33;
- bool t;
- switch (td->t) {
- case TYARRAY:
- h = hashb(h, &td->arrlen, sizeof td->arrlen);
- /* fallthru */
- case TYPTR:
- h = hashb(h, &td->child, sizeof td->child);
- break;
- case TYSTRUCT:
- case TYUNION:
- case TYENUM:
- h = hashb(h, &td->id, sizeof td->id);
- break;
- case TYFUNC:
- h = hashb(h, &td->ret, sizeof td->ret);
- h = hashb(h, &td->nmemb, sizeof td->nmemb);
- h = hashb(h, (t = td->kandr, &t), sizeof t);
- h = hashb(h, (t = td->variadic, &t), sizeof t);
- for (int i = 0; i < td->nmemb; ++i) {
- h = hashb(h, &td->param[i], sizeof *td->param);
- }
- break;
- default:
- assert(0 && "bad typedata tag");
- }
- return h ^ h>>16;
-}
-
-static bool
-tdequ(const struct typedata *a, const struct typedata *b)
-{
- if (a->t != b->t) return 0;
- switch (a->t) {
- case TYARRAY:
- return a->arrlen == b->arrlen && a->child.bits == b->child.bits;
- case TYPTR:
- return a->child.bits == b->child.bits;
- case TYSTRUCT:
- case TYUNION:
- case TYENUM:
- return a->id == b->id;
- case TYFUNC:
- if (a->ret.bits != b->ret.bits) return 0;
- if (a->nmemb != b->nmemb) return 0;
- if (a->variadic != b->variadic) return 0;
- if (a->kandr != b->kandr) return 0;
- for (int i = 0; i < a->nmemb; ++i) {
- if (a->param[i].bits != b->param[i].bits)
- return 0;
- }
- return 1;
- default:
- assert(0 && "bad typedata tag");
- }
-}
-
-static ushort
-interntd(const struct typedata *td)
-{
- uint h, i, n = countof(typedata);
- for (i = h = hashtd(td); n--; ++i) {
- struct typedata *slot = &typedata[i &= countof(typedata) - 1];
- if (!slot->t) {
- uint nmemb;
- static struct arena *datarena;
- if (!datarena) {
- enum { N = 1<<12 };
- static union { char m[sizeof(struct arena) + N]; struct arena *_align; } amem;
- datarena = (void *)amem.m, datarena->cap = N;
- }
-
- Copy:
- nmemb = td->nmemb;
- *slot = *td;
- switch (slot->t) {
- case TYENUM:
- if (slot->var)
- slot->var = alloccopy(&datarena, td->var, nmemb * sizeof *slot->var, 0);
- break;
- case TYSTRUCT:
- case TYUNION:
- if (slot->fld)
- slot->fld = alloccopy(&datarena, td->fld, nmemb * sizeof *slot->fld, 0);
- break;
- case TYFUNC:
- if (slot->param)
- slot->param = alloccopy(&datarena, td->param, nmemb * sizeof *slot->param, 0);
- }
- return i;
- } else if (tdequ(slot, td)) {
- if (td->t == TYSTRUCT || td->t == TYUNION || td->t == TYENUM)
- goto Copy;
- return i;
- }
- }
- assert(0 && "typedata[] full");
-}
-
-bool
-isincomplete(union type t)
-{
- switch (t.t) {
- case TYVOID: return 1;
- case TYARRAY: return !typearrlen(t);
- case TYSTRUCT:
- case TYUNION:
- return typedata[t.dat].nmemb == 0;
- case TYENUM:
- return !typedata[t.dat].backing;
- }
- return 0;
-}
-
-uint
-typesize(union type t)
-{
- if (isprim(t) || t.t == TYPTR) return targ_primsizes[t.t];
- switch (t.t) {
- case TYENUM:
- return targ_primsizes[typedata[t.dat].backing];
- case TYARRAY:
- if (t.flag & TFCHLDPRIM)
- return targ_primsizes[t.child] * t.arrlen;
- /* fallthru */
- case TYSTRUCT:
- case TYUNION:
- return typedata[t.dat].siz;
- }
- return 0;
-}
-
-uint
-typealign(union type t)
-{
- if (isprim(t) || t.t == TYPTR) return targ_primalign[t.t];
- switch (t.t) {
- case TYENUM:
- return targ_primalign[typedata[t.dat].backing];
- case TYARRAY:
- return typealign(typechild(t));
- case TYSTRUCT:
- case TYUNION:
- return typedata[t.dat].align;
- }
- return 0;
-}
-
-union type
-mkptrtype(union type t, int qual)
-{
- if (isprim(t))
- return mktype(TYPTR, .flag = TFCHLDPRIM | (qual & TFCHLDQUAL), .child = t.t);
- else if (t.t == TYENUM || t.t == TYFUNC || isagg(t))
- return mktype(TYPTR, .flag = TFCHLDISDAT | (qual & TFCHLDQUAL), .dat = t.dat);
- return mktype(TYPTR, .flag = qual & TFCHLDQUAL,
- .dat = interntd(&(struct typedata) { TYPTR, .child = t }));
-}
-
-union type
-mkarrtype(union type t, int qual, uint n)
-{
- if (isprim(t) && n < 256)
- return mktype(TYARRAY, .flag = TFCHLDPRIM | (qual & TFCHLDQUAL), .child = t.t, .arrlen = n);
- return mktype(TYARRAY, .flag = qual & TFCHLDQUAL,
- .dat = interntd(&(struct typedata) { TYARRAY, .child = t, .arrlen = n, .siz = n * typesize(t) }));
-}
-
-union type
-mkfntype(union type ret, uint n, const union type *par, bool kandr, bool variadic)
-{
- struct typedata td = { TYFUNC, .ret = ret, .nmemb = n, .param = par };
- td.kandr = kandr, td.variadic = variadic;
- return mktype(TYFUNC, .dat = interntd(&td));
-}
-
-union type
-completetype(internstr name, int id, struct typedata *td)
-{
- assert(td->t == TYENUM || td->t == TYSTRUCT || td->t == TYUNION);
- td->id = id;
- assert(id < countof(ttypenames) && "too many tag types");
- if (ttypenames[id])
- assert(ttypenames[id] == name && "bad redefn");
- else
- ttypenames[id] = name;
- return mktype(td->t, .dat = interntd(td), .backing = td->t == TYENUM ? td->backing : 0);
-}
-
-union type
-mktagtype(internstr name, struct typedata *td)
-{
- static int id;
- return completetype(name, id++, td);
-}
-
-static bool
-getfieldrec(struct fielddata *res, uint off, const struct typedata *td, internstr name)
-{
-Begin:
- for (int i = 0; i < td->nmemb; ++i) {
- struct namedfield *fld = &td->fld[i];
- if (fld->name == name) { /* match */
- *res = fld->f;
- res->off += off;
- return 1;
- } else if (!fld->name) { /* anonymous struct/union */
- const struct typedata *ftd = &typedata[fld->f.t.dat];
- assert(isagg(fld->f.t));
- if (i == td->nmemb - 1) { /* last field, tail recurse */
- off += fld->f.off;
- td = ftd;
- goto Begin;
- } else if (getfieldrec(res, off + fld->f.off, ftd, name))
- return 1;
- }
- }
- return 0;
-}
-
-bool
-getfield(struct fielddata *res, union type ty, internstr name)
-{
- assert(isagg(ty));
- return getfieldrec(res, 0, &typedata[ty.dat], name);
-}
-
-union type
-typedecay(union type t)
-{
- if (t.t == TYARRAY)
- return mkptrtype(typechild(t), t.flag & TFCHLDQUAL);
- if (t.t == TYFUNC)
- return mkptrtype(t, 0);
- return t;
-}
-
-bool /* 6.5.16.1 Simple assignment Constraints */
-assigncompat(union type dst, union type src)
-{
- if (dst.bits == src.bits) return 1;
- if (isarith(dst) && isarith(src)) return 1;
- if (dst.t == TYPTR && src.t == TYPTR) {
- union type ds = typechild(dst), ss = typechild(src);
- if (ds.bits == ss.bits) return 1; /* T* with different qualifiers */
- if (ss.t == TYVOID || ds.t == TYVOID) return 1; /* T* <-> void* */
- enum typetag dt = scalartypet(ds), /* handle enums */
- st = scalartypet(ss);
- if (!dt || !st) return 0; /* unequal incomplete enums */
- /* plain char exception */
- if (st == TYCHAR && in_range(dt, TYUCHAR, TYSCHAR)) return 1;
- if (dt == TYCHAR && in_range(st, TYUCHAR, TYSCHAR)) return 1;
- } else if (dst.t == TYBOOL && src.t == TYPTR)
- return 1;
- return 0;
-}
-
-enum typetag
-intpromote(enum typetag t)
-{
- static int intisshort = -1;
- if (intisshort < 0) intisshort = targ_primsizes[TYINT] == targ_primsizes[TYSHORT];
- if (intisshort && t == TYUSHORT) return TYUINT;
- return t < TYINT ? TYINT : t;
-}
-
-union type /* 6.3.1.8 Usual arithmetic conversions */
-cvtarith(union type a, union type b)
-{
- const union type none = {0};
-
- if (!isarith(a) || !isarith(b)) return none;
- if (a.t == TYENUM) a = typechild(a);
- if (b.t == TYENUM) b = typechild(b);
- if (isflt(a) || isflt(b)) {
- /* when one type is float, choose type with greatest rank */
- /* enumeration order of type tags reflects arithmetic type rank */
- return a.t > b.t ? a : b;
- }
- a.t = intpromote(a.t);
- b.t = intpromote(b.t);
- if (a.bits == b.bits) return a;
-
- if (issigned(a) == issigned(b)) {
- /* when both are integers with same signage, choose type with greatest rank */
- return a.t > b.t ? a : b;
- }
- /* if the signed type can represent all values of the unsigned type,
- * choose it, otherwise choose its corresponding unsigned type */
- /* so long long + unsigned = long long;
- * but long long + unsigned long = unsigned long long */
- if (issigned(a)) {
- if (targ_primsizes[a.t] <= targ_primsizes[b.t])
- a.t += 1; /* make unsigned */
- return a.t > b.t ? a : b;
- } else {
- if (targ_primsizes[b.t] <= targ_primsizes[a.t])
- b.t += 1; /* make unsigned */
- return b.t > a.t ? b : a;
- }
-}
-
-/* vim:set ts=3 sw=3 expandtab: */