diff options
| author | 2026-03-17 13:43:05 +0100 | |
|---|---|---|
| committer | 2026-03-17 16:10:00 +0100 | |
| commit | 3eeb6f219e4d32160fa10895b57a8ddfefff5ff7 (patch) | |
| tree | febb6021a9e4a8593bd67402b25082b2f7109f72 /src/antcc.h | |
| parent | a8d6f8bf30c07edb775e56889f568ca20240bedf (diff) | |
REFACTOR: finish renaming
Diffstat (limited to 'src/antcc.h')
| -rw-r--r-- | src/antcc.h | 465 |
1 files changed, 465 insertions, 0 deletions
diff --git a/src/antcc.h b/src/antcc.h new file mode 100644 index 0000000..a24aa3d --- /dev/null +++ b/src/antcc.h @@ -0,0 +1,465 @@ +#ifndef COMMON_H_ +#define COMMON_H_ + +#include <stdarg.h> +#include <stddef.h> +#include <string.h> + +#ifdef __clang__ /* stop linter from complaining about "unused" inline functions */ +#pragma GCC diagnostic ignored "-Wunused-function" +#endif + +#define bool _Bool +typedef unsigned char uchar; +typedef signed char schar; +typedef unsigned short ushort; +typedef unsigned long long uvlong; +typedef signed long long vlong; +typedef unsigned uint; + +#if __STDC_VERSION__ >= 202311L +#define NORETURN [[noreturn]] +#elif __STDC_VERSION__ >= 201112L +#define NORETURN _Noreturn +#else +#define NORETURN +#endif + +#ifdef __has_builtin +#define HAS_BUILTIN(b) __has_builtin(__builtin_##b) +#else +#define HAS_BUILTIN(_) 0 +#endif + +#define static_assert(x) _Static_assert(x, #x) +#define in_range(x, Lo, Hi) ((uint) (x) - (Lo) <= (Hi) - (Lo)) /* lo <= x <= hi; lo > 0, hi > 0 */ +#define alignup(x, A) (((x) + ((A) - 1)) & -(A)) +#define countof(a) (sizeof(a) / sizeof 0[a]) + +enum { SPANFILEBITS = 10 }; +struct span { + struct span0 { + uint off; + uint len : 32-SPANFILEBITS, + file : SPANFILEBITS; + } sl, /* original source location */ + ex; /* the location after #include/macro expansion */ +}; + +void _assertfmt(const char *file, int line, const char *func, const char *expr); +#if HAS_BUILTIN(trap) +#define assert(x) (!(x) ? _assertfmt(__FILE__,__LINE__,__func__,#x), __builtin_trap() : (void)0) +#else +#define assert(x) (void)(!(x) ? _assertfmt(__FILE__,__LINE__,__func__,#x), *(volatile int *)0 : 0) +#endif + +static inline size_t +hashs(size_t h, const char *s) +{ + while (*s) h = (uchar)*s++ + h*65599; + return h; +} +static inline size_t +hashb(size_t h, const void *d, size_t n) +{ + const uchar *b = d; + while (n--) h = *b++ + h*65599; + return h; +} +static inline size_t +ptrhash(const void *p) { + return (size_t)p * 2654435761u; +} +static inline uint +popcnt(uvlong x) { +#if HAS_BUILTIN(popcountll) + return x ? __builtin_popcountll(x) : 0; +#else + uint n = 0; + while (x) n += x&1, x >>= 1; + return n; +#endif +} +static inline bool +ispo2(uvlong x) { + return (x != 0) & ((x & (x - 1)) == 0); +} +static inline uint +ilog2(uvlong x) { /* assumes x is a power of 2 */ +#if HAS_BUILTIN(ctzll) + return __builtin_ctzll(x); +#else + uint n = 0; + while (x >>= 1) ++n; + return n; +#endif +} +static inline uint +lowestsetbit(uvlong x) +{ +#if HAS_BUILTIN(ctzll) + return __builtin_ctzll(x); +#else + int i = 0; + for (uvlong mask = 1;; ++i, mask <<= 1) + if (x & mask) + break; + return i; +#endif +} + +#define aisprint(c) in_range(c, ' ', '~') +#define aisdigit(c) in_range(c, '0', '9') +#define aisodigit(c) in_range(c, '0', '7') +#define aisalpha(c) in_range((c)|0x20, 'a', 'z') +static inline bool aisspace(int c) { return c == ' ' || in_range(c, '\t', '\r'); } +static inline bool aisxdigit(int c) { return aisdigit(c) || in_range(c|0x20, 'a', 'f'); } + +/******************/ +/* COMPILER STATE */ +/******************/ + +enum cstd { + STDC89, + STDC99, + STDC11, + STDC23, +}; +struct option { + enum cstd cstd; + bool pedant; + bool trigraph; + bool nocolor; + bool pie, pic; + bool werror; + bool wnone; + enum optz { + OPT0 = -1, + OPT1 = 1, + OPT2 = 2, + } o; + union { + struct { + bool p : 1, /* after parsing */ + a : 1, /* after abi0 */ + m : 1, /* after mem */ + y : 1, /* after inline */ + o : 1, /* after optimizations */ + s : 1, /* after stack */ + i : 1, /* after isel */ + l : 1, /* after liveness fixup */ + r : 1; /* after regalloc */ + }; + uint any; + } dbg; + struct wbuf *dbgout; +}; +extern struct option ccopt; +extern struct cinclpaths { + struct inclpath { + struct inclpath *next; + const char *path; + } *list, **tail; +} cinclpaths[5]; +enum { /* GCC include directory search order: https://gcc.gnu.org/onlinedocs/gcc/Directory-Options.html#Options-for-Directory-Search */ + CINCL_iquote, + CINCL_I, + CINCL_isystem, + CINCLsys, + CINCL_idirafter, +}; + +/**********/ +/* Target */ +/**********/ + +struct targtriple { + enum mcarch { ISxxx, ISx86_64, ISaarch64 } arch; + enum mcos { OSunknown, OSlinux } os; + enum mcabi { ABInone, ABIgnu, ABImusl } abi; +}; +extern const struct mctarg *mctarg; +extern struct targtriple target; +void targ_init(const char *); + +/*********/ +/** MEM **/ +/*********/ + +/* libc *alloc wrappers */ +void *xmalloc(size_t n, const char *); +void *xcalloc(size_t n, const char *); +void *xrealloc(void *, size_t n, const char *); +void free(void *); +#define xmalloc(n) xmalloc(n, __func__) +#define xcalloc(n) xcalloc(n, __func__) +#define xrealloc(p,n) xrealloc(p, n, __func__) + +/* string interning */ +typedef const struct internstr {char c;} *internstr; +internstr intern_(const char *, uint len); +#define intern(s) intern_(s, 0) + +/* growable buffer that stores its capacity in the allocated memory */ +#define xbnew_(n) (void *)(1 + (size_t *)xcalloc(sizeof(size_t) + (n))) +#define xbcap_(p) ((size_t *)(p))[-1] +static inline void +xbgrow_(void **p, size_t n) +{ + if (!n) return; + if (!*p) { *p = xbnew_(n); xbcap_(*p) = n; assert(n>0); } + else if (xbcap_(*p) < n) { + size_t k = xbcap_(*p); + assert(k > 0); + do k *= 2; while (k < n); + *p = 1 + (size_t *)xrealloc(&xbcap_(*(p)), sizeof(size_t) + k); + xbcap_(*p) = k; + }; +} +#define xbgrow(p, n) xbgrow_((void **)(p), (n) * sizeof**(p)) +#define xbpush(p, n, x) (xbgrow(p, (*(n) + 1)), (*(p))[(*(n))++] = (x)) +#define xbfree(p) ((p) ? free(&xbcap_(p)) : (void)0) +#define xbcap(p) ((p) ? xbcap_(p) / sizeof*(p) : 0) +#define xbgrowz(p, n) do { \ + size_t tmp = *(p) ? xbcap_(*(p)) : 0; \ + xbgrow(p, n); \ + memset((char*)*(p)+tmp, 0, xbcap_(*(p))-tmp); \ +} while (0) + + +/** arenas **/ +struct arena { + uint cap : 31, + dyn : 1; + uint n; + struct arena *prev; + uchar mem[]; +}; + +extern struct arena *globarena; + +struct arena *newarena(uint chunksiz); +void *alloc(struct arena **, uint siz, uint align); +void *allocz(struct arena **, uint siz, uint align); +static inline void * +alloccopy(struct arena **arena, const void *src, uint siz, uint align) +{ + if (!siz) return NULL; + return memcpy(alloc(arena, siz, align), src, siz); +} +void freearena(struct arena **); + +/** vec **/ +struct vecbase { void *p; uint n; uint cap : 31, dyn : 1; }; +#define vec_of(T) union { \ + struct { T *p; uint n; }; \ + struct vecbase _vb; \ +} +void vinit_(struct vecbase *, void *inlbuf, uint cap, uint siz); +void vpush_(struct vecbase *, uint siz); +void *vpushn_(struct vecbase *, uint siz, const void *dat, uint ndat); +void vresize_(struct vecbase *, uint siz, uint N); +#define VINIT(inlbuf, Cap) { ._vb.p = (inlbuf), ._vb.cap = (Cap) } +#define vfree(v) ((v)->_vb.dyn ? free((v)->p) : (void)0, memset((v), 0, sizeof*(v))) +#define vinit(v, inlbuf, Cap) (vfree(v), vinit_(&(v)->_vb, inlbuf, (Cap), sizeof *(v)->p)) +#define vpush(v, x) (vpush_(&(v)->_vb, sizeof *(v)->p), (v)->p[(v)->n++] = (x)) +#define vpushn(v, xs, N) vpushn_(&(v)->_vb, sizeof *(v)->p, xs, N) +#define vresize(v, N) vresize_(&(v)->_vb, sizeof *(v)->p, N) + +/** map of short -> T **/ +#define imap_of(T) struct { T *v; int tmp; struct imapbase mb; } +struct imapbase { short *k; struct bitset *bs; uint n, N; }; + +void imap_init_(struct imapbase *, void **v, uint vsiz, uint N); +int imap_get_(struct imapbase *, short k); +int imap_set_(struct imapbase *, void **v, uint vsiz, short k); +#define imap_free(m) (free((m)->mb.k), memset((m), 0, sizeof *(m))) +#define imap_init(m, N) (imap_free(m), imap_init_(&(m)->mb, (void **)&(m)->v, sizeof*(m)->v, (N))) +#define imap_clear(m) ((m)->mb.bs ? bszero((m)->mb.bs, BSSIZE((m)->mb.N)) : (void)0, \ + (m)->mb.n = 0) +#define imap_get(m, k) ((m)->tmp = imap_get_(&(m)->mb, k), (m)->tmp < 0 ? NULL : &(m)->v[(m)->tmp]) +#define imap_set(m, k, ...) ((m)->tmp = imap_set_(&(m)->mb, (void **)&(m)->v, sizeof*(m)->v, k), \ + (m)->v[(m)->tmp] = (__VA_ARGS__), &(m)->v[(m)->tmp]) +#define imap_each(m,kx,pvx) \ + for (int _i = 0; _i < (m)->mb.N && ((kx) = (m)->mb.k[_i], (pvx) = &(m)->v[_i], 1); ++_i) \ + if (bstest((m)->mb.bs, _i)) +#define imap_copy(dst,src) do { \ + size_t N = (src)->mb.N; \ + if (!N) break; \ + (dst)->mb.n = (src)->mb.n; \ + imap_init((dst), N); \ + memcpy((dst)->mb.k, (src)->mb.k, \ + N*(sizeof*(src)->mb.k + sizeof*(src)->v) + BSSIZE(N)*sizeof(struct bitset)); \ +} while (0) + + +/** map of non-null ptr -> T **/ +#define pmap_of(T) struct { T *v; int tmp; struct pmapbase mb; } +struct pmapbase { void **k; uint n, N; }; + +void pmap_init_(struct pmapbase *, void **v, uint vsiz, uint N); +int pmap_get_(struct pmapbase *, const void *k); +int pmap_set_(struct pmapbase *, void **v, uint vsiz, const void *k); +void pmap_del_(struct pmapbase *, const void *k); +extern char pmap_tombstone_[]; +#define pmap_free(m) (free((m)->mb.k), memset((m), 0, sizeof *(m))) +#define pmap_init(m, N) (pmap_free(m), pmap_init_(&(m)->mb, (void **)&(m)->v, sizeof*(m)->v, (N))) +#define pmap_get(m, k) (((m)->tmp = pmap_get_(&(m)->mb, k)) < 0 ? NULL : &(m)->v[(m)->tmp]) +#define pmap_set(m, k, x) ((m)->tmp = pmap_set_(&(m)->mb, (void **)&(m)->v, sizeof*(m)->v, k), \ + (m)->v[(m)->tmp] = (x)) +#define pmap_del(m, k) pmap_del_(&(m)->mb, k) +#define pmap_each(m,kx,pvx) \ + for (size_t _i = 0; _i < (m)->mb.N && ((kx) = (m)->mb.k[_i], (pvx) = &(m)->v[_i], 1); ++_i) \ + if (kx && kx != pmap_tombstone_) + +/** bitset **/ +struct bitset { size_t u; }; +enum { BSNBIT = 8 * sizeof(struct bitset) }; +#define BSSIZE(nbit) ((nbit)/BSNBIT + ((nbit)%BSNBIT != 0)) + +static inline bool +bstest(const struct bitset *bs, uint i) +{ + return bs[i/BSNBIT].u >> i%BSNBIT & 1; +} + +static inline void +bsset(struct bitset *bs, uint i) +{ + bs[i/BSNBIT].u |= 1ull << i%BSNBIT; +} + +static inline void +bsclr(struct bitset *bs, uint i) +{ + bs[i/BSNBIT].u &= ~(1ull << i%BSNBIT); +} + +static inline void +bszero(struct bitset bs[/*siz*/], uint siz) +{ + memset(bs, 0, siz * sizeof *bs); +} + +static inline void +bscopy(struct bitset dst[/*siz*/], const struct bitset src[/*siz*/], uint siz) +{ + while (siz--) dst++->u = src++->u; +} + +static inline void +bsunion(struct bitset dst[/*siz*/], const struct bitset src[/*siz*/], uint siz) +{ + while (siz--) dst++->u |= src++->u; +} + +static inline uint +bscount(struct bitset bs[/*siz*/], uint siz) +{ + uint n = 0; + while (siz--) n += popcnt(bs++->u); + return n; +} + +static inline bool +bsiter(uint *i, struct bitset bs[/*siz*/], uint siz) +{ + uint k = *i/BSNBIT, j = *i%BSNBIT; + if (k >= siz) return 0; + size_t t = bs[k].u & ~(((size_t)1 << j) - 1); + while (!t) { + if (++k >= siz) return 0; + t = bs[k].u; + } + *i = k*BSNBIT + lowestsetbit(t); + return 1; +} +#define bs_each(T, var, bs, siz) for (T (var) = 0; bsiter(&(var), (bs), (siz)); ++(var)) + +static inline bool +bsiterzr(uint *i, struct bitset bs[/*siz*/], uint siz) +{ + uint k = *i/BSNBIT, j = *i%BSNBIT; + if (k >= siz) return 0; + size_t t = ~bs[k].u & ~(((size_t)1 << j) - 1); + while (!t) { + if (++k >= siz) return 0; + t = ~bs[k].u; + } + *i = k*BSNBIT + lowestsetbit(t); + return 1; +} + +/********/ +/** IO **/ +/********/ + +struct wbuf { + union { + struct { + char *buf; + uint cap; + uint len; + int fd; + }; + void *fp; + }; + bool err; + bool isfp; +}; + +/* read-only file mapping that is at least 1 page larger than the real file + * so it's legal to read a few bytes beyond it to avoid some bounds checks */ +struct memfile { + const uchar *p; + uint n; + bool statik; +}; + +struct embedfile { + const char *name; + const char *s; + size_t len; +}; + +#define MEMBUF(buf_, cap_) { .buf = (buf_), .cap = (cap_), .fd = -1 } +#define FDBUF(buf_, cap_, fd_) { .buf = (buf_), .cap = (cap_), .fd = (fd_) } +extern struct wbuf bstdout, bstderr; +void ioinit(void); +void iowrite(struct wbuf *, const void *src, int n); +void ioputc(struct wbuf *, uchar); +void ioflush(struct wbuf *); +int vbfmt(struct wbuf *, const char *, va_list ap); +int bfmt(struct wbuf *, const char *, ...); +#define pfmt(...) bfmt(&bstdout, __VA_ARGS__) +#define efmt(...) bfmt(&bstderr, __VA_ARGS__) +struct memfile mapopen(const char **err, const char *path); +void mapclose(struct memfile *); +void *mapzeros(uint); +int munmap(void *, size_t); +int getpredeffile(struct memfile **, const char *name); +int openfile(const char **err, struct memfile **, const char *path); +const char *getfilename(int id, uint atoff); +struct memfile *getfile(int id); +void addfileline(int id, uint off); +void setfileline(int id, uint off, int line, const char *file); +const char *getfilepos(int *line, int *col, int id, uint off); +bool isoncefile(int id, internstr *guard); +void markfileonce(int id, internstr guard); +void markfileseen(int id); +bool isfileseen(int id); +void closefile(int id); + +enum diagkind { DGERROR, DGWARN, DGNOTE, }; +void vdiag(const struct span *, enum diagkind, const char *, va_list); +NORETURN void fatal(const struct span *, const char *, ...); +void error(const struct span *, const char *, ...); +void warn(const struct span *, const char *, ...); +void note(const struct span *, const char *, ...); +ushort *utf8to16(uint *ulen, struct arena **, const uchar *s, size_t len); +uint *utf8to32(uint *ulen, struct arena **, const uchar *s, size_t len); +int utf8enc(char out[4], uint cp); + +#endif /* COMMON_H_ */ + +/* vim:set ts=3 sw=3 expandtab: */ |