aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/c_type.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/c_type.h')
-rw-r--r--src/c_type.h177
1 files changed, 177 insertions, 0 deletions
diff --git a/src/c_type.h b/src/c_type.h
new file mode 100644
index 0000000..ad8e1b1
--- /dev/null
+++ b/src/c_type.h
@@ -0,0 +1,177 @@
+#ifndef TYPE_H_
+#define TYPE_H_
+#include "common.h"
+
+enum qualifier {
+ QCONST = 1<<0,
+ QVOLATILE = 1<<1,
+};
+
+enum typetag { /* ordering is important here! */
+ TYXXX,
+ TYENUM,
+ TYBOOL, TYCHAR, TYSCHAR, TYUCHAR, TYSHORT, TYUSHORT, TYINT, TYUINT, TYLONG, TYULONG, TYVLONG, TYUVLONG,
+ TYFLOAT, TYDOUBLE, TYLDOUBLE, TYCOMPLEXF, TYCOMPLEX, TYCOMPLEXL,
+ TYVOID,
+ TYPTR, TYARRAY, TYFUNC,
+ TYSTRUCT, TYUNION,
+ NTYPETAG,
+ TYSIGNEDSET_ = 1<<TYSCHAR | 1<<TYSHORT | 1<<TYINT | 1<<TYLONG | 1<<TYVLONG,
+ TYUNSIGNEDSET_ = 1<<TYUCHAR | 1<<TYUSHORT | 1<<TYUINT | 1<<TYULONG | 1<<TYUVLONG,
+ TYSCALARSET_ = ((1u << (TYCOMPLEXL - TYENUM + 1)) - 1) << TYENUM | 1<<TYPTR
+};
+
+enum typeflagmask {
+ TFCHLDQUAL = 3,
+ TFCHLDPRIM = 1<<2,
+ TFCHLDISDAT = 1<<3,
+};
+
+union type {
+ struct {
+ uchar t; /* type tag */
+ union {
+ uchar flag;
+ uchar backing; /* type tag for enum backing int */
+ };
+ union {
+ struct {
+ uchar child; /* prim type tag */
+ uchar arrlen; /* small array */
+ };
+ ushort dat; /* index into typedata */
+ };
+ };
+ uint bits;
+};
+static_assert(sizeof(union type) == 4);
+
+#define isprimt(t) in_range((t), TYBOOL, TYVOID)
+#define isintt(t) in_range((t), TYENUM, TYUVLONG)
+#define issignedt(t) ((TYSIGNEDSET_ | targ_charsigned << TYCHAR) >> (t) & 1)
+#define isunsignedt(t) ((TYUNSIGNEDSET_ | !targ_charsigned << TYCHAR) >> (t) & 1)
+#define isfltt(t) in_range((t), TYFLOAT, TYLDOUBLE)
+#define isaritht(t) in_range((t), TYENUM, TYCOMPLEXL)
+#define isscalart(t) (TYSCALARSET_ >> (t) & 1)
+#define isptrcvtt(t) in_range((t), TYPTR, TYFUNC)
+#define isaggt(t) in_range((t), TYSTRUCT, TYUNION)
+#define isprim(ty) isprimt((ty).t)
+#define isint(ty) isintt((ty).t)
+#define issigned(ty) issignedt(scalartypet(ty))
+#define isunsigned(ty) isunsignedt(scalartypet(ty))
+#define isflt(ty) isfltt((ty).t)
+#define isarith(ty) isaritht((ty).t)
+#define isscalar(ty) isscalart((ty).t)
+#define isptrcvt(ty) isptrcvtt((ty).t)
+#define isagg(ty) isaggt((ty).t)
+#define iscomplext(t) in_range((t), TYCOMPLEXF, TYCOMPLEXL)
+#define iscomplex(ty) iscomplext((ty).t)
+#define mktype(...) ((union type) {{ __VA_ARGS__ }})
+
+struct enumvar {
+ internstr name;
+ union { vlong i; uvlong u; };
+};
+
+struct fielddata {
+ union type t;
+ ushort off;
+ uchar bitsiz,
+ bitoff : 6,
+ qual : 2;
+};
+struct namedfield {
+ internstr name;
+ struct fielddata f;
+};
+
+struct typedata {
+ uchar t;
+ ushort id;
+ union {
+ union type child;
+ const union type *param; /* functions */
+ struct { /* aggregates */
+ struct namedfield *fld;
+ };
+ struct { /* enum */
+ uchar backing;
+ struct enumvar *var;
+ };
+ };
+ union {
+ uint arrlen; /* array */
+ struct {
+ short nmemb; /* functions, aggregates, enums */
+ uchar align;
+ union {
+ struct { /* function */
+ bool kandr : 1, variadic : 1;
+ };
+ struct { /* aggregate */
+ bool anyconst : 1, flexi : 1;
+ };
+ };
+ };
+ };
+ union {
+ uint siz; /* aggregate & array */
+ union type ret; /* function */
+ };
+};
+
+extern struct typedata typedata[];
+extern internstr ttypenames[/*id*/];
+
+bool isincomplete(union type);
+uint typesize(union type);
+uint typealign(union type);
+union type mkptrtype(union type, int qual);
+union type mkarrtype(union type t, int qual, uint n);
+union type mkfntype(union type ret, uint n, const union type *, bool kandr, bool variadic);
+union type mktagtype(internstr name, struct typedata *td);
+bool getfield(struct fielddata *res, union type, internstr);
+union type completetype(internstr name, int id, struct typedata *td);
+union type typedecay(union type);
+bool assigncompat(union type dst, union type src);
+enum typetag intpromote(enum typetag);
+union type cvtarith(union type a, union type b);
+static inline union type
+typechild(union type t)
+{
+ if (t.t == TYENUM) return mktype(t.backing ? t.backing : typedata[t.dat].backing);
+ if (t.flag & TFCHLDPRIM) return mktype(t.child);
+ if (t.flag & TFCHLDISDAT) {
+ union type chld = mktype(typedata[t.dat].t, .dat = t.dat);
+ if (chld.t == TYENUM) chld.backing = typedata[t.dat].backing;
+ return chld;
+ }
+ return typedata[t.dat].child;
+}
+static inline enum typetag
+scalartypet(union type t)
+{
+ if (t.t == TYENUM) return t.backing ? t.backing : typedata[t.dat].backing;
+ if (isptrcvt(t)) return TYPTR;
+ assert(!iscomplex(t));
+ return t.t;
+}
+static inline uint
+typearrlen(union type t)
+{
+ return (t.flag & TFCHLDPRIM) ? t.arrlen : typedata[t.dat].arrlen;
+}
+
+/**********/
+/* Target */
+/**********/
+
+extern uint targ_valistsize;
+extern uchar targ_primsizes[];
+extern uchar targ_primalign[];
+extern enum typetag targ_sizetype, targ_ptrdifftype, targ_wchartype;
+extern bool targ_charsigned, targ_bigendian, targ_64bit;
+
+#endif
+
+/* vim:set ts=3 sw=3 expandtab: */