commit 201c8f0da021884364993e891a9bb09ec10c05ad
parent 3021470e7878a91d1960a1d19527d941d7803b8c
Author: Ryan Sepassi <rsepassi@gmail.com>
Date: Thu, 14 May 2026 10:49:27 -0700
Expose frontend support API for C
Diffstat:
38 files changed, 1709 insertions(+), 1533 deletions(-)
diff --git a/include/abi/abi.h b/include/abi/abi.h
@@ -1,126 +0,0 @@
-#ifndef CFREE_ABI_H
-#define CFREE_ABI_H
-
-#include <cfree/cg.h>
-
-#include "core/core.h"
-
-/* TargetABI is the single authority for target-dependent storage layout and
- * calling convention decisions. Frontends lower source-language types to
- * CfreeCgTypeId before entering this generic ABI layer. */
-typedef struct TargetABI TargetABI;
-
-typedef enum ABIScalarKind {
- ABI_SC_VOID,
- ABI_SC_BOOL,
- ABI_SC_INT,
- ABI_SC_FLOAT,
- ABI_SC_PTR,
-} ABIScalarKind;
-
-typedef struct ABITypeInfo {
- u32 size;
- u32 align;
- u8 scalar_kind; /* ABIScalarKind; ABI_SC_VOID for aggregates/void */
- u8 signed_;
- u8 atomic;
- u8 pad;
-} ABITypeInfo;
-
-typedef struct ABIFieldLayout {
- u32 offset; /* byte offset from record base */
- u16 bit_offset; /* bit offset within storage unit for bitfields */
- u16 bit_width; /* 0 for non-bitfield */
- u32 storage_size; /* bytes in the bitfield storage unit; 0 otherwise */
-} ABIFieldLayout;
-
-typedef struct ABIRecordLayout {
- u32 size;
- u32 align;
- u32 nfields;
- const ABIFieldLayout* fields;
-} ABIRecordLayout;
-
-typedef enum ABIArgKind {
- ABI_ARG_IGNORE,
- ABI_ARG_DIRECT, /* one or more inspectable parts */
- ABI_ARG_INDIRECT, /* caller passes address */
- ABI_ARG_EXPAND, /* aggregate split into parts below */
-} ABIArgKind;
-
-typedef enum ABIArgClass {
- ABI_CLASS_NONE,
- ABI_CLASS_INT,
- ABI_CLASS_FP,
- ABI_CLASS_VEC,
- ABI_CLASS_MEM,
-} ABIArgClass;
-
-typedef enum ABIArgLoc {
- ABI_LOC_NONE,
- ABI_LOC_REG,
- ABI_LOC_STACK,
- ABI_LOC_EITHER,
-} ABIArgLoc;
-
-typedef enum ABIArgFlag {
- ABI_AF_NONE = 0,
- ABI_AF_SRET = 1u << 0, /* hidden structure-return pointer */
- ABI_AF_BYVAL = 1u << 1, /* caller passes an address to a copy */
- ABI_AF_SIGN_EXT = 1u << 2,
- ABI_AF_ZERO_EXT = 1u << 3,
- ABI_AF_VARARG = 1u << 4, /* placement affected by variadic rules */
- ABI_AF_SPLIT = 1u << 5, /* source value is split across parts */
-} ABIArgFlag;
-
-typedef struct ABIArgPart {
- u8 cls; /* ABIArgClass */
- u8 loc; /* ABIArgLoc preference */
- u16 flags; /* ABIArgFlag */
- u32 src_offset; /* byte offset within source object */
- u32 size; /* bytes carried by this part */
- u32 align; /* part alignment */
- u32 stack_align; /* required stack alignment if stack-passed */
-} ABIArgPart;
-
-typedef struct ABIArgInfo {
- u8 kind; /* ABIArgKind */
- u8 flags; /* ABIArgFlag applying to the whole argument */
- u16 nparts;
- u32 indirect_align; /* required alignment for ABI_ARG_INDIRECT/byval copy */
- const ABIArgPart* parts;
-} ABIArgInfo;
-
-typedef struct ABIFuncInfo {
- ABIArgInfo ret;
- const ABIArgInfo* params;
- u16 nparams;
- u8 variadic;
- u8 has_sret;
- /* True when the trailing `...` portion of a variadic call must be
- * routed to the stack exclusively, bypassing the GPR/FPR arg pools.
- * Apple ARM64 sets this; AAPCS64 / SysV-x64 leave it 0 (variadics
- * use the same register routing as fixed args). */
- u8 vararg_on_stack;
- u32 vararg_gp_offset;
- u32 vararg_fp_offset;
- u32 vararg_overflow_offset;
-} ABIFuncInfo;
-
-void abi_init(TargetABI*, Compiler*);
-void abi_fini(TargetABI*);
-
-/* Heap-allocating wrappers around abi_init/abi_fini, used by compiler_init.
- * The returned pointer is valid until abi_free returns. */
-TargetABI* abi_new(Compiler*);
-void abi_free(TargetABI*);
-Compiler* abi_compiler(TargetABI*);
-
-ABITypeInfo abi_cg_type_info(TargetABI*, CfreeCgTypeId);
-u32 abi_cg_sizeof(TargetABI*, CfreeCgTypeId);
-u32 abi_cg_alignof(TargetABI*, CfreeCgTypeId);
-const ABIRecordLayout* abi_cg_record_layout(TargetABI*, CfreeCgTypeId);
-const ABIFuncInfo* abi_cg_func_info(TargetABI*, CfreeCgTypeId fn_type);
-ABITypeInfo abi_va_list_info(TargetABI*);
-
-#endif
diff --git a/include/cfree/frontend.h b/include/cfree/frontend.h
@@ -0,0 +1,72 @@
+#ifndef CFREE_FRONTEND_H
+#define CFREE_FRONTEND_H
+
+#include <cfree.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdint.h>
+
+typedef struct CfreeArena CfreeArena;
+
+/* Arena storage for frontends. The arena is opaque; allocation is bump-style
+ * and released wholesale by reset/free. */
+CfreeArena* cfree_arena_new(CfreeHeap*, size_t block_size);
+void cfree_arena_free(CfreeArena*);
+void cfree_arena_reset(CfreeArena*);
+void* cfree_arena_alloc(CfreeArena*, size_t size, size_t align);
+void* cfree_arena_zalloc(CfreeArena*, size_t size, size_t align);
+char* cfree_arena_strdup(CfreeArena*, const char* s, size_t len);
+
+#define cfree_arena_new_obj(a, T) \
+ ((T*)cfree_arena_alloc((a), sizeof(T), _Alignof(T)))
+#define cfree_arena_znew_obj(a, T) \
+ ((T*)cfree_arena_zalloc((a), sizeof(T), _Alignof(T)))
+#define cfree_arena_array(a, T, n) \
+ ((T*)cfree_arena_alloc((a), sizeof(T) * (size_t)(n), _Alignof(T)))
+#define cfree_arena_zarray(a, T, n) \
+ ((T*)cfree_arena_zalloc((a), sizeof(T) * (size_t)(n), _Alignof(T)))
+
+/* Compiler-attached host services. These expose the vtables already present
+ * in CfreeEnv without exposing CfreeCompiler's internal layout. */
+CfreeHeap* cfree_compiler_heap(CfreeCompiler*);
+const CfreeFileIO* cfree_compiler_file_io(CfreeCompiler*);
+int64_t cfree_compiler_now(CfreeCompiler*);
+
+/* Symbol pool helpers. cfree_sym_intern is the c-string convenience in
+ * <cfree.h>; the length-taking form is needed by lexers and preprocessors. */
+CfreeSym cfree_sym_intern_len(CfreeCompiler*, const char* str, size_t len);
+const char* cfree_sym_str(CfreeCompiler*, CfreeSym, size_t* len_out);
+
+/* Source-file registration and include-edge recording. */
+uint32_t cfree_source_add_file(CfreeCompiler*, const char* path,
+ int system_header);
+uint32_t cfree_source_add_memory(CfreeCompiler*, const char* name);
+uint32_t cfree_source_add_builtin(CfreeCompiler*, const char* name);
+void cfree_source_add_include(CfreeCompiler*, uint32_t includer_file_id,
+ uint32_t included_file_id, CfreeSrcLoc loc,
+ int system);
+
+typedef struct CfreeSourceFile {
+ uint32_t id;
+ CfreeSym name;
+ CfreeSym path;
+ uint8_t kind;
+ uint8_t system_header;
+ uint16_t pad;
+} CfreeSourceFile;
+
+int cfree_source_file(CfreeCompiler*, uint32_t file_id, CfreeSourceFile* out);
+
+/* Frontend panic boundary. Frontend entry points called by cfree_compile_obj*
+ * already run under libcfree's top-level boundary; standalone frontend helpers
+ * such as preprocess/token-dump can use cfree_frontend_run to get the same
+ * behavior without seeing jmp_buf or CfreeCompiler internals. */
+typedef int (*CfreeFrontendRunFn)(CfreeCompiler*, void* user);
+int cfree_frontend_run(CfreeCompiler*, CfreeFrontendRunFn, void* user);
+
+_Noreturn void cfree_frontend_fatal(CfreeCompiler*, CfreeSrcLoc,
+ const char* fmt, ...);
+_Noreturn void cfree_frontend_vfatal(CfreeCompiler*, CfreeSrcLoc,
+ const char* fmt, va_list);
+
+#endif
diff --git a/include/cfree/hashmap.h b/include/cfree/hashmap.h
@@ -0,0 +1,170 @@
+#ifndef CFREE_HASHMAP_H
+#define CFREE_HASHMAP_H
+
+#include <cfree.h>
+#include <stdint.h>
+#include <string.h>
+
+static inline uint32_t cfree_hash_u32(uint32_t x) {
+ x += 0x9e3779b9u;
+ x ^= x >> 16;
+ x *= 0x7feb352du;
+ x ^= x >> 15;
+ x *= 0x846ca68bu;
+ x ^= x >> 16;
+ return x;
+}
+
+static inline uint32_t cfree_hash_u64(uint64_t x) {
+ x ^= x >> 33;
+ x *= 0xff51afd7ed558ccdULL;
+ x ^= x >> 33;
+ x *= 0xc4ceb9fe1a85ec53ULL;
+ x ^= x >> 33;
+ return (uint32_t)x;
+}
+
+#define CFREE_HASHMAP_LOAD_NUM 3u
+#define CFREE_HASHMAP_LOAD_DEN 4u
+#define CFREE_HASHMAP_INIT_CAP 16u
+
+#define CFREE_HASHMAP_DEFINE(NAME, KT, VT, HASH_FN) \
+ typedef struct NAME##Slot { \
+ KT k; \
+ VT v; \
+ } NAME##Slot; \
+ typedef struct NAME { \
+ CfreeHeap* heap; \
+ NAME##Slot* slots; \
+ uint32_t cap; \
+ uint32_t used; \
+ } NAME; \
+ \
+ __attribute__((unused)) static void NAME##_resize(NAME* m, \
+ uint32_t new_cap) { \
+ NAME##Slot* fresh; \
+ uint32_t i, mask; \
+ fresh = (NAME##Slot*)m->heap->alloc(m->heap, sizeof(*fresh) * new_cap, \
+ _Alignof(NAME##Slot)); \
+ if (!fresh) return; \
+ memset(fresh, 0, sizeof(*fresh) * new_cap); \
+ mask = new_cap - 1u; \
+ for (i = 0; i < m->cap; ++i) { \
+ KT k = m->slots[i].k; \
+ uint32_t j; \
+ if (!(k)) continue; \
+ j = HASH_FN(k) & mask; \
+ while (fresh[j].k) j = (j + 1u) & mask; \
+ fresh[j] = m->slots[i]; \
+ } \
+ if (m->slots) \
+ m->heap->free(m->heap, m->slots, sizeof(*m->slots) * m->cap); \
+ m->slots = fresh; \
+ m->cap = new_cap; \
+ } \
+ \
+ __attribute__((unused)) static inline void NAME##_init_cap( \
+ NAME* m, CfreeHeap* h, uint32_t cap) { \
+ m->heap = h; \
+ m->slots = NULL; \
+ m->cap = 0; \
+ m->used = 0; \
+ if (cap) NAME##_resize(m, cap); \
+ } \
+ \
+ __attribute__((unused)) static inline void NAME##_init(NAME* m, \
+ CfreeHeap* h) { \
+ NAME##_init_cap(m, h, CFREE_HASHMAP_INIT_CAP); \
+ } \
+ \
+ __attribute__((unused)) static inline void NAME##_fini(NAME* m) { \
+ if (m->slots) \
+ m->heap->free(m->heap, m->slots, sizeof(*m->slots) * m->cap); \
+ m->slots = NULL; \
+ m->cap = m->used = 0; \
+ } \
+ \
+ __attribute__((unused)) static inline VT* NAME##_get(const NAME* m, KT k) { \
+ uint32_t mask, j; \
+ if (m->cap == 0 || !(k)) return NULL; \
+ mask = m->cap - 1u; \
+ j = HASH_FN(k) & mask; \
+ while (m->slots[j].k) { \
+ if (m->slots[j].k == (k)) return &m->slots[j].v; \
+ j = (j + 1u) & mask; \
+ } \
+ return NULL; \
+ } \
+ \
+ __attribute__((unused)) static inline int NAME##_set(NAME* m, KT k, VT v) { \
+ uint32_t mask, j; \
+ if (m->cap == 0 || \
+ m->used * CFREE_HASHMAP_LOAD_DEN >= m->cap * CFREE_HASHMAP_LOAD_NUM) \
+ NAME##_resize(m, m->cap ? m->cap * 2u : CFREE_HASHMAP_INIT_CAP); \
+ mask = m->cap - 1u; \
+ j = HASH_FN(k) & mask; \
+ while (m->slots[j].k) { \
+ if (m->slots[j].k == (k)) { \
+ m->slots[j].v = (v); \
+ return 0; \
+ } \
+ j = (j + 1u) & mask; \
+ } \
+ m->slots[j].k = (k); \
+ m->slots[j].v = (v); \
+ m->used++; \
+ return 1; \
+ } \
+ \
+ __attribute__((unused)) static inline int NAME##_try_insert( \
+ NAME* m, KT k, VT v, VT* existing_out) { \
+ uint32_t mask, j; \
+ if (m->cap == 0 || \
+ m->used * CFREE_HASHMAP_LOAD_DEN >= m->cap * CFREE_HASHMAP_LOAD_NUM) \
+ NAME##_resize(m, m->cap ? m->cap * 2u : CFREE_HASHMAP_INIT_CAP); \
+ mask = m->cap - 1u; \
+ j = HASH_FN(k) & mask; \
+ while (m->slots[j].k) { \
+ if (m->slots[j].k == (k)) { \
+ if (existing_out) *existing_out = m->slots[j].v; \
+ return 0; \
+ } \
+ j = (j + 1u) & mask; \
+ } \
+ m->slots[j].k = (k); \
+ m->slots[j].v = (v); \
+ m->used++; \
+ return 1; \
+ } \
+ \
+ __attribute__((unused)) static inline void NAME##_del(NAME* m, KT k) { \
+ uint32_t mask, j; \
+ if (m->cap == 0 || !(k)) return; \
+ mask = m->cap - 1u; \
+ j = HASH_FN(k) & mask; \
+ while (m->slots[j].k) { \
+ if (m->slots[j].k == (k)) { \
+ uint32_t i = (j + 1u) & mask; \
+ m->slots[j].k = 0; \
+ m->used--; \
+ while (m->slots[i].k) { \
+ KT rk = m->slots[i].k; \
+ VT rv = m->slots[i].v; \
+ uint32_t nh; \
+ m->slots[i].k = 0; \
+ m->used--; \
+ nh = HASH_FN(rk) & mask; \
+ while (m->slots[nh].k) nh = (nh + 1u) & mask; \
+ m->slots[nh].k = rk; \
+ m->slots[nh].v = rv; \
+ m->used++; \
+ i = (i + 1u) & mask; \
+ } \
+ return; \
+ } \
+ j = (j + 1u) & mask; \
+ } \
+ } \
+ struct NAME
+
+#endif
diff --git a/include/core/arena.h b/include/core/arena.h
@@ -1,31 +0,0 @@
-#ifndef CFREE_ARENA_H
-#define CFREE_ARENA_H
-
-#include "core/core.h"
-#include "core/heap.h"
-
-typedef struct ArenaBlock ArenaBlock;
-
-struct Arena {
- Heap* heap;
- ArenaBlock* head;
- u8* cur; /* points into head's buffer */
- u8* end; /* end of head's buffer */
- size_t block_size;
-};
-
-void arena_init(Arena*, Heap*, size_t block_size);
-void arena_fini(Arena*);
-void arena_reset(Arena*);
-void* arena_alloc(Arena*, size_t size, size_t align);
-void* arena_zalloc(Arena*, size_t size, size_t align); /* zeroed; NULL on OOM */
-char* arena_strdup(Arena*, const char* s, size_t len);
-
-#define arena_new(a, T) ((T*)arena_alloc((a), sizeof(T), _Alignof(T)))
-#define arena_znew(a, T) ((T*)arena_zalloc((a), sizeof(T), _Alignof(T)))
-#define arena_array(a, T, n) \
- ((T*)arena_alloc((a), sizeof(T) * (size_t)(n), _Alignof(T)))
-#define arena_zarray(a, T, n) \
- ((T*)arena_zalloc((a), sizeof(T) * (size_t)(n), _Alignof(T)))
-
-#endif
diff --git a/include/core/core.h b/include/core/core.h
@@ -1,160 +0,0 @@
-#ifndef CFREE_INTERNAL_CORE_H
-#define CFREE_INTERNAL_CORE_H
-
-#include <cfree.h>
-#include <setjmp.h>
-#include <stdarg.h>
-#include <stddef.h>
-#include <stdint.h>
-
-/* Short integer aliases used throughout libcfree's internal headers. */
-typedef int8_t i8;
-typedef int16_t i16;
-typedef int32_t i32;
-typedef int64_t i64;
-typedef uint8_t u8;
-typedef uint16_t u16;
-typedef uint32_t u32;
-typedef uint64_t u64;
-
-/* Internal aliases for types that also have a public Cfree-prefixed name.
- * <cfree.h> is the single source of truth for those types' identities;
- * src/ keeps its terser, plain names so the internal call sites don't
- * change. Both names refer to the same struct. */
-typedef CfreeCompiler Compiler;
-typedef CfreeHeap Heap;
-typedef CfreeDiagSink DiagSink;
-typedef CfreeWriter Writer;
-typedef CfreeTarget Target;
-typedef CfreeObjBuilder ObjBuilder;
-typedef enum CfreeArchKind ArchKind;
-typedef enum CfreeOSKind OSKind;
-typedef enum CfreeObjFmt ObjFmt;
-
-/* Internal-only forward declarations. */
-typedef struct Arena Arena;
-typedef struct Pool Pool;
-typedef struct TargetABI TargetABI;
-typedef struct SourceManager SourceManager;
-
-/* Interned string ids. 0 reserved as "none". Object and linker symbols are
- * intentionally not intern-pool concepts; see obj/obj.h and link/link.h. */
-typedef u32 Sym;
-
-/* Binary-blob handle into the same Pool. Shares the numeric value space with
- * Sym but is a distinct typedef so callers don't accidentally mix interned
- * strings with decoded literal bytes. */
-typedef u32 BytesId;
-#define BYTES_NONE 0u
-
-/* SrcLoc is the public CfreeSrcLoc; the alias keeps internal call sites
- * terse. */
-typedef CfreeSrcLoc SrcLoc;
-
-typedef struct SrcRange {
- SrcLoc begin;
- SrcLoc end;
-} SrcRange;
-
-typedef enum SourceFileKind {
- SRC_FILE_REAL,
- SRC_FILE_MEMORY,
- SRC_FILE_BUILTIN,
- SRC_FILE_MACRO,
-} SourceFileKind;
-
-typedef struct SourceFile {
- u32 id;
- Sym name; /* spelling used in diagnostics */
- Sym path; /* normalized path, 0 for memory/builtin-only input */
- u8 kind; /* SourceFileKind */
- u8 system_header;
- u16 pad;
-} SourceFile;
-
-typedef struct SourceInclude {
- u32 includer_file_id;
- u32 included_file_id;
- SrcLoc include_loc;
- u8 system;
- u8 pad[3];
-} SourceInclude;
-
-typedef struct SourceExpansion {
- SrcLoc spelling_loc; /* where the token text came from */
- SrcLoc expansion_loc; /* where the macro expansion was requested */
- Sym macro_name;
-} SourceExpansion;
-
-typedef struct SourceDepIter SourceDepIter;
-
-SourceManager* source_new(Compiler*);
-void source_free(SourceManager*);
-
-u32 source_add_file(SourceManager*, const char* path, int system_header);
-u32 source_add_memory(SourceManager*, const char* name);
-u32 source_add_builtin(SourceManager*, const char* name);
-void source_add_include(SourceManager*, u32 includer_file_id,
- u32 included_file_id, SrcLoc include_loc, int system);
-u32 source_add_macro_expansion(SourceManager*, Sym macro_name,
- SrcLoc spelling_loc, SrcLoc expansion_loc);
-
-const SourceFile* source_file(SourceManager*, u32 file_id);
-const SourceExpansion* source_expansion(SourceManager*, u32 expansion_file_id);
-SrcLoc source_spelling_loc(SourceManager*, SrcLoc);
-SrcLoc source_expansion_loc(SourceManager*, SrcLoc);
-
-SourceDepIter* source_depiter_new(SourceManager*);
-const SourceInclude* source_depiter_next(SourceDepIter*);
-void source_depiter_free(SourceDepIter*);
-
-/* compiler_defer registers a cleanup that runs LIFO from cfree_run's panic
- * boundary (or any caller that establishes its own setjmp). Each subsystem
- * _new registers its matching _free; the matched _free calls compiler_undefer
- * with the returned handle. The cleanup stack lives in scratch arena and is
- * bounded by pipeline depth (~10 entries). */
-typedef struct CompilerCleanup CompilerCleanup;
-
-struct CfreeCompiler {
- jmp_buf panic;
- const CfreeEnv* env;
- Pool* global;
- Arena* tu;
- Arena* scratch;
- SourceManager* sources;
- TargetABI* abi;
- Target target;
- CompilerCleanup* cleanup; /* top of LIFO cleanup stack */
- CfreeCompileFn frontends[CFREE_LANG_COUNT];
- void* cg_api; /* public cfree/cg.h adapter state */
- void (*cg_api_free)(Compiler*);
-};
-
-void compiler_init(Compiler*, Target, const CfreeEnv*);
-void compiler_fini(Compiler*);
-
-/* Cleanup stack. compiler_defer returns an opaque handle; compiler_undefer
- * removes the entry without running it (use after a successful _free).
- * compiler_run_cleanups runs everything LIFO, used by the panic handler. */
-CompilerCleanup* compiler_defer(Compiler*, void (*fn)(void*), void* arg);
-void compiler_undefer(Compiler*, CompilerCleanup*);
-void compiler_run_cleanups(Compiler*);
-
-/* Emits a diagnostic and longjmps c->panic. Used by parse/cg/arch fatal paths.
- */
-_Noreturn void compiler_panic(Compiler*, SrcLoc, const char* fmt, ...);
-_Noreturn void compiler_panicv(Compiler*, SrcLoc, const char* fmt, va_list);
-
-/* Save/restore the panic jmp_buf so layered APIs can nest. Each top-level
- * driver function (cfree_compile_obj, cfree_link_*, ...) saves c->panic,
- * installs its own setjmp, and restores on every exit path — both the
- * panic-return path (after compiler_run_cleanups) and the success path.
- * Without this, an inner setjmp clobbers an outer setjmp's jmp_buf, and a
- * subsequent compiler_panic by the outer caller longjmps to a dead frame. */
-typedef struct PanicSave {
- jmp_buf buf;
-} PanicSave;
-void compiler_panic_save(Compiler*, PanicSave* out);
-void compiler_panic_restore(Compiler*, const PanicSave* saved);
-
-#endif
diff --git a/include/core/diag.h b/include/core/diag.h
@@ -1,19 +0,0 @@
-#ifndef CFREE_DIAG_H
-#define CFREE_DIAG_H
-
-#include "core/core.h"
-
-/* DiagKind / DiagSink struct are public (see <cfree.h>). The internal
- * aliases below keep terse names; the unprefixed enum constants below
- * are the names libcfree's source uses internally. */
-typedef CfreeDiagKind DiagKind;
-#define DIAG_NOTE CFREE_DIAG_NOTE
-#define DIAG_WARN CFREE_DIAG_WARN
-#define DIAG_ERROR CFREE_DIAG_ERROR
-#define DIAG_FATAL CFREE_DIAG_FATAL
-
-/* Convenience varargs wrappers around `sink->emit`. Internal use only. */
-void diag_emit(DiagSink*, DiagKind, SrcLoc, const char* fmt, ...);
-void diag_emitv(DiagSink*, DiagKind, SrcLoc, const char* fmt, va_list);
-
-#endif
diff --git a/include/core/hashmap.h b/include/core/hashmap.h
@@ -1,202 +0,0 @@
-#ifndef CFREE_HASHMAP_H
-#define CFREE_HASHMAP_H
-
-/* Generic open-addressed hashmap as a typed-macro template.
- *
- * Linear probing; doubling rehash at 75% load. Tombstoneless deletion
- * via cluster rehash. Empty-key sentinel is 0 — slots are zero-initialized
- * by allocation, and callers must never insert a key whose value compares
- * equal to 0. (Sym=0 already means "none" per core.h:42; OBJ_SEC_NONE=0;
- * pointer keys avoid 0 by construction.)
- *
- * HASHMAP_DEFINE(NAME, KT, VT, HASH_FN)
- * NAME — struct typedef name for this instance.
- * KT — key type (must support `== 0` and `==` against another KT).
- * VT — value type (any assignable type).
- * HASH_FN — function-like expression mapping KT -> u32.
- *
- * Emits typedef NAME, NAME##Slot, and these static functions:
- * void NAME##_init (NAME*, Heap*) — default initial cap
- * void NAME##_init_cap(NAME*, Heap*, u32 cap) — caller picks initial
- * cap void NAME##_fini (NAME*) VT* NAME##_get (const NAME*, KT) —
- * NULL if absent int NAME##_set (NAME*, KT, VT) — 1
- * inserted, 0 updated void NAME##_del (NAME*, KT) — no-op
- * if absent
- *
- * Equality is `==` on KT. That covers all keys we use (Sym which is u32,
- * u64 guest_pc). A string-keyed instance would need a small extension.
- *
- * Built-in mixers below cover u32 (hash_u32) and u64 (hash_u64) keys. */
-
-#include <string.h>
-
-#include "core/core.h"
-#include "core/heap.h"
-
-/* xorshift mixer suitable for dense u32 keys (interned Sym ids etc.). */
-static inline u32 hash_u32(u32 x) {
- x += 0x9e3779b9u;
- x ^= x >> 16;
- x *= 0x7feb352du;
- x ^= x >> 15;
- x *= 0x846ca68bu;
- x ^= x >> 16;
- return x;
-}
-
-/* SplitMix-style mixer for u64 keys (e.g. guest PC). */
-static inline u32 hash_u64(u64 x) {
- x ^= x >> 33;
- x *= 0xff51afd7ed558ccdULL;
- x ^= x >> 33;
- x *= 0xc4ceb9fe1a85ec53ULL;
- x ^= x >> 33;
- return (u32)x;
-}
-
-#define HASHMAP_LOAD_NUM 3u
-#define HASHMAP_LOAD_DEN 4u
-#define HASHMAP_INIT_CAP 16u
-
-#define HASHMAP_DEFINE(NAME, KT, VT, HASH_FN) \
- typedef struct NAME##Slot { \
- KT k; \
- VT v; \
- } NAME##Slot; \
- typedef struct NAME { \
- Heap* heap; \
- NAME##Slot* slots; \
- u32 cap; \
- u32 used; \
- } NAME; \
- \
- __attribute__((unused)) static void NAME##_resize(NAME* m, u32 new_cap) { \
- NAME##Slot* fresh; \
- u32 i, mask; \
- fresh = (NAME##Slot*)m->heap->alloc(m->heap, sizeof(*fresh) * new_cap, \
- _Alignof(NAME##Slot)); \
- if (!fresh) return; \
- memset(fresh, 0, sizeof(*fresh) * new_cap); \
- mask = new_cap - 1u; \
- for (i = 0; i < m->cap; ++i) { \
- KT k = m->slots[i].k; \
- u32 j; \
- if (!(k)) continue; \
- j = HASH_FN(k) & mask; \
- while (fresh[j].k) j = (j + 1u) & mask; \
- fresh[j] = m->slots[i]; \
- } \
- if (m->slots) \
- m->heap->free(m->heap, m->slots, sizeof(*m->slots) * m->cap); \
- m->slots = fresh; \
- m->cap = new_cap; \
- } \
- \
- __attribute__((unused)) static inline void NAME##_init_cap(NAME* m, Heap* h, \
- u32 cap) { \
- m->heap = h; \
- m->slots = NULL; \
- m->cap = 0; \
- m->used = 0; \
- if (cap) NAME##_resize(m, cap); \
- } \
- \
- __attribute__((unused)) static inline void NAME##_init(NAME* m, Heap* h) { \
- NAME##_init_cap(m, h, HASHMAP_INIT_CAP); \
- } \
- \
- __attribute__((unused)) static inline void NAME##_fini(NAME* m) { \
- if (m->slots) \
- m->heap->free(m->heap, m->slots, sizeof(*m->slots) * m->cap); \
- m->slots = NULL; \
- m->cap = m->used = 0; \
- } \
- \
- __attribute__((unused)) static inline VT* NAME##_get(const NAME* m, KT k) { \
- u32 mask, j; \
- if (m->cap == 0 || !(k)) return NULL; \
- mask = m->cap - 1u; \
- j = HASH_FN(k) & mask; \
- while (m->slots[j].k) { \
- if (m->slots[j].k == (k)) return &m->slots[j].v; \
- j = (j + 1u) & mask; \
- } \
- return NULL; \
- } \
- \
- __attribute__((unused)) static inline int NAME##_set(NAME* m, KT k, VT v) { \
- u32 mask, j; \
- if (m->cap == 0 || \
- m->used * HASHMAP_LOAD_DEN >= m->cap * HASHMAP_LOAD_NUM) \
- NAME##_resize(m, m->cap ? m->cap * 2u : HASHMAP_INIT_CAP); \
- mask = m->cap - 1u; \
- j = HASH_FN(k) & mask; \
- while (m->slots[j].k) { \
- if (m->slots[j].k == (k)) { \
- m->slots[j].v = (v); \
- return 0; \
- } \
- j = (j + 1u) & mask; \
- } \
- m->slots[j].k = (k); \
- m->slots[j].v = (v); \
- m->used++; \
- return 1; \
- } \
- \
- /* Insert if absent. Returns 1 if newly inserted; 0 if k was present \
- * (in that case writes the existing value to *existing_out when \
- * existing_out is non-NULL). */ \
- __attribute__((unused)) static inline int NAME##_try_insert( \
- NAME* m, KT k, VT v, VT* existing_out) { \
- u32 mask, j; \
- if (m->cap == 0 || \
- m->used * HASHMAP_LOAD_DEN >= m->cap * HASHMAP_LOAD_NUM) \
- NAME##_resize(m, m->cap ? m->cap * 2u : HASHMAP_INIT_CAP); \
- mask = m->cap - 1u; \
- j = HASH_FN(k) & mask; \
- while (m->slots[j].k) { \
- if (m->slots[j].k == (k)) { \
- if (existing_out) *existing_out = m->slots[j].v; \
- return 0; \
- } \
- j = (j + 1u) & mask; \
- } \
- m->slots[j].k = (k); \
- m->slots[j].v = (v); \
- m->used++; \
- return 1; \
- } \
- \
- __attribute__((unused)) static inline void NAME##_del(NAME* m, KT k) { \
- u32 mask, j; \
- if (m->cap == 0 || !(k)) return; \
- mask = m->cap - 1u; \
- j = HASH_FN(k) & mask; \
- while (m->slots[j].k) { \
- if (m->slots[j].k == (k)) { \
- u32 i = (j + 1u) & mask; \
- m->slots[j].k = 0; \
- m->used--; \
- while (m->slots[i].k) { \
- KT rk = m->slots[i].k; \
- VT rv = m->slots[i].v; \
- u32 nh; \
- m->slots[i].k = 0; \
- m->used--; \
- nh = HASH_FN(rk) & mask; \
- while (m->slots[nh].k) nh = (nh + 1u) & mask; \
- m->slots[nh].k = rk; \
- m->slots[nh].v = rv; \
- m->used++; \
- i = (i + 1u) & mask; \
- } \
- return; \
- } \
- j = (j + 1u) & mask; \
- } \
- } \
- /* trailing struct decl swallows the macro-call's semicolon */ \
- struct NAME
-
-#endif
diff --git a/include/core/heap.h b/include/core/heap.h
@@ -1,16 +0,0 @@
-#ifndef CFREE_HEAP_H
-#define CFREE_HEAP_H
-
-#include "core/core.h"
-
-/* CfreeHeap struct definition is in <cfree.h> (public). The host
- * implements `alloc`/`realloc`/`free` and passes the heap in via
- * CfreeEnv.heap.
- *
- * heap_mmap_exec is a libcfree-internal helper used only by the JIT path
- * (mapped pages with PROT_EXEC available on flip). It is the one place
- * inside libcfree that genuinely depends on host memory mapping; for now
- * it stays internal until the JIT is wired up. */
-Heap* heap_mmap_exec(void);
-
-#endif
diff --git a/include/core/pool.h b/include/core/pool.h
@@ -1,40 +0,0 @@
-#ifndef CFREE_POOL_H
-#define CFREE_POOL_H
-
-#include "core/arena.h"
-#include "core/core.h"
-#include "core/heap.h"
-
-typedef struct PoolEntry {
- const char* data;
- u32 len;
- u32 hash;
-} PoolEntry;
-
-struct Pool {
- Heap* heap;
- Arena arena; /* string storage */
-
- /* Hash table: 0 means empty. Otherwise it's a Sym id (1-based). */
- Sym* table;
- u32 cap; /* always a power of two */
- u32 used;
-
- /* Sym → string mapping. Index 0 reserved as Sym = 0 ("none"). */
- PoolEntry* entries;
- u32 nentries;
- u32 entries_cap;
-
- /* Frontends may hang language-specific interning state here. */
- void* type_cache;
-};
-
-void pool_init(Pool*, Heap*);
-void pool_fini(Pool*);
-
-/* Strings. Returns canonical id; equal strings → equal ids. */
-Sym pool_intern(Pool*, const char* s, size_t len);
-Sym pool_intern_cstr(Pool*, const char* s);
-const char* pool_str(Pool*, Sym, size_t* len_out);
-
-#endif
diff --git a/lang/c/abi/c_abi.c b/lang/c/abi/c_abi.c
@@ -1,6 +1,6 @@
#include "abi/c_abi.h"
-#include "core/pool.h"
+#include <string.h>
static int c_type_is_signed_integer(const Type* t) {
if (!t) return 0;
@@ -20,8 +20,33 @@ static int c_type_is_signed_integer(const Type* t) {
}
ABITypeInfo c_abi_type_info(TargetABI* a, const Type* t) {
- Compiler* c = abi_compiler(a);
- ABITypeInfo r = abi_cg_type_info(a, type_cg_id(c, t));
+ CfreeCgTypeId id = type_cg_id(a, t);
+ CfreeCgTypeKind kind = cfree_cg_type_kind(a, id);
+ ABITypeInfo r;
+ memset(&r, 0, sizeof(r));
+ r.size = (u32)cfree_cg_type_size(a, id);
+ r.align = cfree_cg_type_align(a, id);
+ switch (kind) {
+ case CFREE_CG_TYPE_VOID:
+ r.scalar_kind = ABI_SC_VOID;
+ break;
+ case CFREE_CG_TYPE_BOOL:
+ r.scalar_kind = ABI_SC_BOOL;
+ break;
+ case CFREE_CG_TYPE_INT:
+ case CFREE_CG_TYPE_ENUM:
+ r.scalar_kind = ABI_SC_INT;
+ break;
+ case CFREE_CG_TYPE_FLOAT:
+ r.scalar_kind = ABI_SC_FLOAT;
+ break;
+ case CFREE_CG_TYPE_PTR:
+ r.scalar_kind = ABI_SC_PTR;
+ break;
+ default:
+ r.scalar_kind = ABI_SC_VOID;
+ break;
+ }
r.signed_ = c_type_is_signed_integer(t);
return r;
}
@@ -34,18 +59,57 @@ u32 c_abi_alignof(TargetABI* a, const Type* t) {
return c_abi_type_info(a, t).align;
}
-const ABIRecordLayout* c_abi_record_layout(TargetABI* a, const Type* t) {
- return abi_cg_record_layout(a, type_cg_id(abi_compiler(a), t));
+const ABIRecordLayout* c_abi_record_layout(TargetABI* a, Pool* p,
+ const Type* t) {
+ CfreeCgTypeId id = type_cg_id_in_pool(a, p, t);
+ ABIRecordLayout* L;
+ ABIFieldLayout* fl = NULL;
+ u32 nfields;
+ if (cfree_cg_type_kind(a, id) != CFREE_CG_TYPE_RECORD) return NULL;
+ nfields = cfree_cg_type_record_nfields(a, id);
+ L = arena_znew(p->arena, ABIRecordLayout);
+ if (!L) return NULL;
+ if (nfields) {
+ fl = arena_zarray(p->arena, ABIFieldLayout, nfields);
+ if (!fl) return NULL;
+ for (u32 i = 0; i < nfields; ++i) {
+ CfreeCgField f;
+ uint64_t off = 0;
+ memset(&f, 0, sizeof(f));
+ if (cfree_cg_type_record_field(a, id, i, &f, &off) != 0) return NULL;
+ fl[i].offset = (u32)off;
+ fl[i].storage_size = (u32)cfree_cg_type_size(a, f.type);
+ if (t->rec.fields[i].flags & FIELD_BITFIELD) {
+ fl[i].bit_width = t->rec.fields[i].bitfield_width;
+ }
+ }
+ }
+ L->size = (u32)cfree_cg_type_size(a, id);
+ L->align = cfree_cg_type_align(a, id);
+ L->nfields = nfields;
+ L->fields = fl;
+ return L;
}
-const ABIFuncInfo* c_abi_func_info(TargetABI* a, const Type* fn_type) {
- return abi_cg_func_info(a, type_cg_id(abi_compiler(a), fn_type));
+const ABIFuncInfo* c_abi_func_info(TargetABI* a, Pool* p, const Type* fn_type) {
+ CfreeCgTypeId id = type_cg_id_in_pool(a, p, fn_type);
+ ABIFuncInfo* info;
+ uint32_t nparams;
+ if (cfree_cg_type_kind(a, id) != CFREE_CG_TYPE_FUNC) return NULL;
+ nparams = cfree_cg_type_func_nparams(a, id);
+ info = arena_znew(p->arena, ABIFuncInfo);
+ if (!info) return NULL;
+ info->nparams = (u16)nparams;
+ if (nparams) {
+ info->params = arena_zarray(p->arena, ABIArgInfo, nparams);
+ if (!info->params) return NULL;
+ }
+ return info;
}
static const Type* c_size_or_uintptr(TargetABI* a, Pool* p) {
- Compiler* c = abi_compiler(a);
- return c->target.ptr_size == 8 ? type_prim(p, TY_ULLONG)
- : type_prim(p, TY_UINT);
+ CfreeTarget target = cfree_compiler_target(a);
+ return target.ptr_size == 8 ? type_prim(p, TY_ULLONG) : type_prim(p, TY_UINT);
}
const Type* c_abi_size_type(TargetABI* a, Pool* p) {
@@ -53,9 +117,8 @@ const Type* c_abi_size_type(TargetABI* a, Pool* p) {
}
const Type* c_abi_ptrdiff_type(TargetABI* a, Pool* p) {
- Compiler* c = abi_compiler(a);
- return c->target.ptr_size == 8 ? type_prim(p, TY_LLONG)
- : type_prim(p, TY_INT);
+ CfreeTarget target = cfree_compiler_target(a);
+ return target.ptr_size == 8 ? type_prim(p, TY_LLONG) : type_prim(p, TY_INT);
}
const Type* c_abi_intptr_type(TargetABI* a, Pool* p) {
@@ -67,8 +130,8 @@ const Type* c_abi_uintptr_type(TargetABI* a, Pool* p) {
}
const Type* c_abi_va_list_type(TargetABI* a, Pool* p) {
- Compiler* c = abi_compiler(a);
- switch (c->target.arch) {
+ CfreeTarget target = cfree_compiler_target(a);
+ switch (target.arch) {
case CFREE_ARCH_X86_64: {
const Type* vp = type_ptr(p, type_void(p));
const Type* uit = type_prim(p, TY_UINT);
@@ -81,14 +144,14 @@ const Type* c_abi_va_list_type(TargetABI* a, Pool* p) {
type_record_field(
b, (Field){.name = pool_intern_cstr(p, "fp_offset"), .type = uit});
type_record_field(
- b,
- (Field){.name = pool_intern_cstr(p, "overflow_arg_area"), .type = vp});
+ b, (Field){.name = pool_intern_cstr(p, "overflow_arg_area"),
+ .type = vp});
type_record_field(
b, (Field){.name = pool_intern_cstr(p, "reg_save_area"), .type = vp});
return type_record_end(p, b);
}
case CFREE_ARCH_ARM_64:
- if (c->target.os == CFREE_OS_MACOS) {
+ if (target.os == CFREE_OS_MACOS) {
return type_ptr(p, type_prim(p, TY_CHAR));
} else {
const Type* vp = type_ptr(p, type_void(p));
diff --git a/lang/c/abi/c_abi.h b/lang/c/abi/c_abi.h
@@ -1,14 +1,54 @@
#ifndef CFREE_LANG_C_ABI_H
#define CFREE_LANG_C_ABI_H
-#include "abi/abi.h"
+#include "c_support.h"
#include "type/type.h"
+typedef enum ABIScalarKind {
+ ABI_SC_VOID,
+ ABI_SC_BOOL,
+ ABI_SC_INT,
+ ABI_SC_FLOAT,
+ ABI_SC_PTR,
+} ABIScalarKind;
+
+typedef struct ABITypeInfo {
+ u32 size;
+ u32 align;
+ u8 scalar_kind;
+ u8 signed_;
+ u8 atomic;
+ u8 pad;
+} ABITypeInfo;
+
+typedef struct ABIFieldLayout {
+ u32 offset;
+ u16 bit_offset;
+ u16 bit_width;
+ u32 storage_size;
+} ABIFieldLayout;
+
+typedef struct ABIRecordLayout {
+ u32 size;
+ u32 align;
+ u32 nfields;
+ const ABIFieldLayout* fields;
+} ABIRecordLayout;
+
+typedef struct ABIArgInfo {
+ u8 dummy;
+} ABIArgInfo;
+
+typedef struct ABIFuncInfo {
+ ABIArgInfo* params;
+ u16 nparams;
+} ABIFuncInfo;
+
ABITypeInfo c_abi_type_info(TargetABI*, const Type*);
u32 c_abi_sizeof(TargetABI*, const Type*);
u32 c_abi_alignof(TargetABI*, const Type*);
-const ABIRecordLayout* c_abi_record_layout(TargetABI*, const Type*);
-const ABIFuncInfo* c_abi_func_info(TargetABI*, const Type*);
+const ABIRecordLayout* c_abi_record_layout(TargetABI*, Pool*, const Type*);
+const ABIFuncInfo* c_abi_func_info(TargetABI*, Pool*, const Type*);
const Type* c_abi_size_type(TargetABI*, Pool*);
const Type* c_abi_ptrdiff_type(TargetABI*, Pool*);
diff --git a/lang/c/c.c b/lang/c/c.c
@@ -2,7 +2,6 @@
#include <cfree/cg.h>
-#include "core/pool.h"
#include "decl/decl.h"
#include "lex/lex.h"
#include "parse/parse.h"
@@ -38,18 +37,21 @@ static void c_apply_pp_options(Pp* pp, const CfreePpOptions* opts) {
}
}
-int cfree_c_preprocess(CfreeCompiler* c, const CfreePpOptions* opts,
- const CfreeBytesInput* input, CfreeWriter* out) {
- PanicSave saved;
+typedef struct CPreprocessRun {
+ const CfreePpOptions* opts;
+ const CfreeBytesInput* input;
+ CfreeWriter* out;
+} CPreprocessRun;
+
+static int c_preprocess_body(CfreeCompiler* c, void* user) {
+ CPreprocessRun* r = (CPreprocessRun*)user;
Lexer* lex;
Pp* pp;
- compiler_panic_save(c, &saved);
- if (setjmp(c->panic)) {
- compiler_run_cleanups(c);
- compiler_panic_restore(c, &saved);
- return 1;
- }
+ const CfreePpOptions* opts = r->opts;
+ const CfreeBytesInput* input = r->input;
+ CfreeWriter* out = r->out;
+
if (!opts || !input || !out) {
c_bad_options(c, "preprocess args missing");
}
@@ -60,27 +62,37 @@ int cfree_c_preprocess(CfreeCompiler* c, const CfreePpOptions* opts,
lex = lex_open_mem(c, input->name, (const char*)input->data, input->len);
pp = pp_new(c);
+ if (!lex || !pp)
+ compiler_panic(c, c_no_loc(), "C preprocessor out of memory");
c_apply_pp_options(pp, opts);
pp_push_input(pp, lex);
pp_emit_text(pp, out);
pp_free(pp);
- compiler_panic_restore(c, &saved);
return 0;
}
+int cfree_c_preprocess(CfreeCompiler* c, const CfreePpOptions* opts,
+ const CfreeBytesInput* input, CfreeWriter* out) {
+ CPreprocessRun r;
+ r.opts = opts;
+ r.input = input;
+ r.out = out;
+ return cfree_frontend_run(c, c_preprocess_body, &r);
+}
+
static void dump_write_str(CfreeWriter* w, const char* s) {
size_t n = 0;
while (s[n]) ++n;
w->write(w, s, n);
}
-static void dump_write_sym(CfreeWriter* w, Pool* p, Sym sym) {
+static void dump_write_sym(CfreeWriter* w, Compiler* c, Sym sym) {
size_t len = 0;
- const char* s = sym ? pool_str(p, sym, &len) : NULL;
+ const char* s = sym ? compiler_sym_str(c, sym, &len) : NULL;
if (s && len) w->write(w, s, len);
}
-static void dump_emit(CfreeWriter* w, Pool* p, const Tok* t) {
+static void dump_emit(CfreeWriter* w, Compiler* c, const Tok* t) {
switch (t->kind) {
case TOK_EOF:
dump_write_str(w, "(eof)\n");
@@ -119,22 +131,22 @@ static void dump_emit(CfreeWriter* w, Pool* p, const Tok* t) {
dump_write_str(w, "(unknown ");
break;
}
- dump_write_sym(w, p, t->spelling);
+ dump_write_sym(w, c, t->spelling);
dump_write_str(w, ")\n");
}
-int cfree_c_dump_tokens(CfreeCompiler* c, const CfreeBytesInput* input,
- CfreeWriter* out) {
- PanicSave saved;
+typedef struct CDumpTokensRun {
+ const CfreeBytesInput* input;
+ CfreeWriter* out;
+} CDumpTokensRun;
+
+static int c_dump_tokens_body(CfreeCompiler* c, void* user) {
+ CDumpTokensRun* r = (CDumpTokensRun*)user;
+ const CfreeBytesInput* input = r->input;
+ CfreeWriter* out = r->out;
Lexer* lex;
Tok t;
- compiler_panic_save(c, &saved);
- if (setjmp(c->panic)) {
- compiler_run_cleanups(c);
- compiler_panic_restore(c, &saved);
- return 1;
- }
if (!input || !out) {
c_bad_options(c, "dump_tokens args missing");
}
@@ -144,37 +156,51 @@ int cfree_c_dump_tokens(CfreeCompiler* c, const CfreeBytesInput* input,
}
lex = lex_open_mem(c, input->name, (const char*)input->data, input->len);
+ if (!lex) compiler_panic(c, c_no_loc(), "C lexer out of memory");
for (;;) {
t = lex_next(lex);
- dump_emit(out, c->global, &t);
+ dump_emit(out, c, &t);
if (t.kind == TOK_EOF) break;
}
lex_close(lex);
- compiler_panic_restore(c, &saved);
return 0;
}
+int cfree_c_dump_tokens(CfreeCompiler* c, const CfreeBytesInput* input,
+ CfreeWriter* out) {
+ CDumpTokensRun r;
+ r.input = input;
+ r.out = out;
+ return cfree_frontend_run(c, c_dump_tokens_body, &r);
+}
+
int cfree_c_compile(CfreeCompiler* c, const CfreeCompileOptions* opts,
const CfreeBytesInput* input, CfreeObjBuilder* out) {
+ Pool* pool;
Lexer* lex;
Pp* pp;
DeclTable* decls;
CfreeCg* cg;
+ pool = c_pool_new(c);
+ if (!pool) compiler_panic(c, c_no_loc(), "C compiler out of memory");
lex = lex_open_mem(c, input->name, (const char*)input->data, input->len);
pp = pp_new(c);
- cg = cfree_cg_new(c, out);
+ cg = cfree_cg_new(c, out, opts);
+ if (!lex || !pp || !cg)
+ compiler_panic(c, c_no_loc(), "C compiler out of memory");
(void)out;
decls = decl_new(c, cg);
c_apply_pp_options(pp, &opts->pp);
pp_push_input(pp, lex);
- parse_c(c, pp, decls, cg);
+ parse_c(c, pool, pp, decls, cg);
cfree_cg_free(cg);
decl_free(decls);
pp_free(pp);
+ c_pool_free(pool);
return 0;
}
diff --git a/lang/c/c_support.h b/lang/c/c_support.h
@@ -0,0 +1,97 @@
+#ifndef CFREE_LANG_C_SUPPORT_H
+#define CFREE_LANG_C_SUPPORT_H
+
+#include <cfree/frontend.h>
+#include <cfree/hashmap.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdint.h>
+
+typedef int8_t i8;
+typedef int16_t i16;
+typedef int32_t i32;
+typedef int64_t i64;
+typedef uint8_t u8;
+typedef uint16_t u16;
+typedef uint32_t u32;
+typedef uint64_t u64;
+
+typedef CfreeCompiler Compiler;
+typedef CfreeHeap Heap;
+typedef CfreeWriter Writer;
+typedef CfreeSym Sym;
+typedef CfreeSrcLoc SrcLoc;
+typedef CfreeCompiler TargetABI;
+typedef u32 BytesId;
+
+typedef struct SrcRange {
+ SrcLoc begin;
+ SrcLoc end;
+} SrcRange;
+
+typedef struct Pool {
+ Compiler* c;
+ CfreeArena* arena;
+ void* type_cache;
+} Pool;
+
+static inline Pool* c_pool_new(Compiler* c) {
+ Heap* h = cfree_compiler_heap(c);
+ Pool* p = h ? (Pool*)h->alloc(h, sizeof(*p), _Alignof(Pool)) : NULL;
+ if (!p) return NULL;
+ p->c = c;
+ p->arena = cfree_arena_new(h, 0);
+ p->type_cache = NULL;
+ if (!p->arena) {
+ h->free(h, p, sizeof(*p));
+ return NULL;
+ }
+ return p;
+}
+
+static inline void c_pool_free(Pool* p) {
+ Heap* h;
+ if (!p) return;
+ h = cfree_compiler_heap(p->c);
+ cfree_arena_free(p->arena);
+ if (h) h->free(h, p, sizeof(*p));
+}
+
+static inline Sym pool_intern(Pool* p, const char* s, size_t len) {
+ return cfree_sym_intern_len(p->c, s, len);
+}
+
+static inline Sym pool_intern_cstr(Pool* p, const char* s) {
+ return cfree_sym_intern(p->c, s);
+}
+
+static inline const char* pool_str(Pool* p, Sym sym, size_t* len_out) {
+ return cfree_sym_str(p->c, sym, len_out);
+}
+
+static inline const char* compiler_sym_str(Compiler* c, Sym sym,
+ size_t* len_out) {
+ return cfree_sym_str(c, sym, len_out);
+}
+
+#define arena_alloc(a, size, align) cfree_arena_alloc((a), (size), (align))
+#define arena_zalloc(a, size, align) cfree_arena_zalloc((a), (size), (align))
+#define arena_strdup(a, s, len) cfree_arena_strdup((a), (s), (len))
+#define arena_new(a, T) cfree_arena_new_obj((a), T)
+#define arena_znew(a, T) cfree_arena_znew_obj((a), T)
+#define arena_array(a, T, n) cfree_arena_array((a), T, n)
+#define arena_zarray(a, T, n) cfree_arena_zarray((a), T, n)
+
+_Noreturn static inline void compiler_panic(Compiler* c, SrcLoc loc,
+ const char* fmt, ...) {
+ va_list ap;
+ va_start(ap, fmt);
+ cfree_frontend_vfatal(c, loc, fmt, ap);
+}
+
+_Noreturn static inline void compiler_panicv(Compiler* c, SrcLoc loc,
+ const char* fmt, va_list ap) {
+ cfree_frontend_vfatal(c, loc, fmt, ap);
+}
+
+#endif
diff --git a/lang/c/decl/decl.c b/lang/c/decl/decl.c
@@ -18,10 +18,6 @@
#include <string.h>
-#include "core/arena.h"
-#include "core/core.h"
-#include "core/heap.h"
-#include "core/pool.h"
#include "parse/cg_public_compat.h"
struct DeclTable {
@@ -35,7 +31,7 @@ struct DeclTable {
#define DECL_INITIAL_CAP 16u
static void decls_grow(DeclTable* t, u32 want) {
- Heap* h = t->c->env->heap;
+ Heap* h = cfree_compiler_heap(t->c);
u32 cap = t->cap;
Decl* nb;
if (cap >= want) return;
@@ -50,7 +46,7 @@ static void decls_grow(DeclTable* t, u32 want) {
}
DeclTable* decl_new(Compiler* c, CfreeCg* cg) {
- Heap* h = c->env->heap;
+ Heap* h = cfree_compiler_heap(c);
DeclTable* t =
(DeclTable*)h->alloc(h, sizeof(DeclTable), _Alignof(DeclTable));
memset(t, 0, sizeof *t);
@@ -65,7 +61,7 @@ DeclTable* decl_new(Compiler* c, CfreeCg* cg) {
void decl_free(DeclTable* t) {
Heap* h;
if (!t) return;
- h = t->c->env->heap;
+ h = cfree_compiler_heap(t->c);
if (t->slots) h->free(h, t->slots, sizeof(Decl) * t->cap);
h->free(h, t, sizeof(*t));
}
@@ -106,7 +102,8 @@ DeclId decl_declare(DeclTable* t, const Decl* in) {
decl.type = pcg_tid(t->c, slot->type);
decl.sym = decl_sym_attrs(slot);
if (decl.kind == CFREE_CG_DECL_FUNC) {
- if (slot->flags & DF_NORETURN) decl.as.func.flags |= CFREE_CG_FUNC_NORETURN;
+ if (slot->flags & DF_NORETURN)
+ decl.as.func.flags |= CFREE_CG_FUNC_NORETURN;
decl.as.func.section = slot->section_id;
} else {
if (slot->flags & DF_THREAD) decl.as.object.flags |= CFREE_CG_OBJ_TLS;
diff --git a/lang/c/decl/decl.h b/lang/c/decl/decl.h
@@ -3,7 +3,7 @@
#include <cfree/cg.h>
-#include "core/core.h"
+#include "c_support.h"
#include "type/type.h"
#ifndef CFREE_OBJ_H
@@ -74,7 +74,7 @@ typedef struct Decl {
u8 pad;
u32 flags; /* DeclFlag */
/* Phase 2 attribute carriers — populated by attr_list_to_decl. */
- u32 align; /* explicit alignment from _Alignas or aligned(N); 0=natural */
+ u32 align; /* explicit alignment from _Alignas or aligned(N); 0=natural */
Sym alias_target; /* target name for __attribute__((alias("..."))); 0=none */
} Decl;
diff --git a/lang/c/decl/decl_attrs.c b/lang/c/decl/decl_attrs.c
@@ -2,8 +2,6 @@
#include <string.h>
-#include "core/pool.h"
-
/* Bare `__attribute__((aligned))` (no argument) means "biggest scalar
* alignment". cfree's targets all have `_Alignof(long double) == 16`
* (x86_64 SysV, AArch64 AAPCS, RISC-V LP64D), so 16 is a valid v1
@@ -21,7 +19,7 @@ static void apply_visibility(Compiler* c, const Attr* a, Decl* out) {
compiler_panic(c, a->loc, "visibility attribute missing argument");
}
size_t n = 0;
- const char* s = pool_str(c->global, a->v.sym, &n);
+ const char* s = compiler_sym_str(c, a->v.sym, &n);
if (s && strcmp(s, "default") == 0) {
out->visibility = SV_DEFAULT;
} else if (s && strcmp(s, "hidden") == 0) {
diff --git a/lang/c/decl/decl_attrs.h b/lang/c/decl/decl_attrs.h
@@ -1,7 +1,6 @@
#ifndef CFREE_DECL_ATTRS_H
#define CFREE_DECL_ATTRS_H
-#include "core/core.h"
#include "decl/decl.h"
#include "parse/attr.h"
diff --git a/lang/c/lex/lex.c b/lang/c/lex/lex.c
@@ -16,9 +16,6 @@
#include <string.h>
-#include "core/heap.h"
-#include "core/pool.h"
-
struct Lexer {
Compiler* c;
Pool* pool;
@@ -126,17 +123,21 @@ static SrcLoc lex_here(const Lexer* l) {
Lexer* lex_open_mem(Compiler* c, const char* name, const char* src,
size_t len) {
- Heap* h = (Heap*)c->env->heap;
+ Heap* h = (Heap*)cfree_compiler_heap(c);
Lexer* l = (Lexer*)h->alloc(h, sizeof(*l), _Alignof(Lexer));
if (!l) return NULL;
memset(l, 0, sizeof(*l));
l->c = c;
- l->pool = c->global;
+ l->pool = c_pool_new(c);
+ if (!l->pool) {
+ h->free(h, l, sizeof(*l));
+ return NULL;
+ }
l->heap = h;
l->src = src ? src : "";
l->len = src ? len : 0;
l->pos = 0;
- l->file_id = source_add_memory(c->sources, name);
+ l->file_id = cfree_source_add_memory(c, name);
l->line = 1;
l->col = 1;
l->at_bol = 1;
@@ -146,6 +147,7 @@ Lexer* lex_open_mem(Compiler* c, const char* name, const char* src,
void lex_close(Lexer* l) {
if (!l) return;
+ c_pool_free(l->pool);
l->heap->free(l->heap, l, sizeof(*l));
}
@@ -488,15 +490,27 @@ Tok lex_next(Lexer* l) {
size_t j = k;
while (j > 0) {
char c = pbuf[j - 1];
- if (c == 'f' || c == 'F') { t.flags |= TF_FLT_F; --j; continue; }
- if (c == 'l' || c == 'L') { t.flags |= TF_FLT_L; --j; continue; }
+ if (c == 'f' || c == 'F') {
+ t.flags |= TF_FLT_F;
+ --j;
+ continue;
+ }
+ if (c == 'l' || c == 'L') {
+ t.flags |= TF_FLT_L;
+ --j;
+ continue;
+ }
break;
}
} else {
size_t j = k;
while (j > 0) {
char c = pbuf[j - 1];
- if (c == 'u' || c == 'U') { t.flags |= TF_INT_U; --j; continue; }
+ if (c == 'u' || c == 'U') {
+ t.flags |= TF_INT_U;
+ --j;
+ continue;
+ }
if (c == 'l' || c == 'L') {
if (j >= 2 && (pbuf[j - 2] == 'l' || pbuf[j - 2] == 'L')) {
t.flags |= TF_INT_LL;
diff --git a/lang/c/lex/lex.h b/lang/c/lex/lex.h
@@ -1,7 +1,7 @@
#ifndef CFREE_LEX_H
#define CFREE_LEX_H
-#include "core/core.h"
+#include "c_support.h"
typedef enum TokKind {
TOK_EOF = 0,
diff --git a/lang/c/parse/attr.h b/lang/c/parse/attr.h
@@ -1,7 +1,7 @@
#ifndef CFREE_PARSE_ATTR_H
#define CFREE_PARSE_ATTR_H
-#include "core/core.h"
+#include "c_support.h"
/* GNU __attribute__((...)) AST node, shared between the parser (producer)
* and the declaration-attribute consumers. The parser builds
diff --git a/lang/c/parse/cg_adapter.c b/lang/c/parse/cg_adapter.c
@@ -1,7 +1,7 @@
-#include "parse/parse_priv.h"
-
#include <string.h>
+#include "parse/parse_priv.h"
+
CfreeCgTypeId pcg_tid(Compiler* c, const Type* ty) { return type_cg_id(c, ty); }
static u32 pcg_sizeof(Parser* p, const Type* ty) {
@@ -27,7 +27,7 @@ static void pcg_stack_grow(Parser* p, u32 want) {
if (p->cg_type_cap >= want) return;
nc = p->cg_type_cap ? p->cg_type_cap * 2u : 64u;
while (nc < want) nc *= 2u;
- ns = arena_array(p->c->tu, const Type*, nc);
+ ns = arena_array(p->pool->arena, const Type*, nc);
if (!ns) perr(p, "out of memory in CG type stack");
if (p->cg_type_stack && p->cg_type_sp) {
memcpy(ns, p->cg_type_stack, sizeof(*ns) * p->cg_type_sp);
@@ -53,8 +53,7 @@ void pcg_dup_type(Parser* p) {
void pcg_swap_type(Parser* p) {
if (p->cg_type_sp >= 2) {
const Type* a = p->cg_type_stack[p->cg_type_sp - 1u];
- p->cg_type_stack[p->cg_type_sp - 1u] =
- p->cg_type_stack[p->cg_type_sp - 2u];
+ p->cg_type_stack[p->cg_type_sp - 1u] = p->cg_type_stack[p->cg_type_sp - 2u];
p->cg_type_stack[p->cg_type_sp - 2u] = a;
}
}
@@ -62,10 +61,8 @@ void pcg_swap_type(Parser* p) {
void pcg_rot3_type(Parser* p) {
if (p->cg_type_sp >= 3) {
const Type* a = p->cg_type_stack[p->cg_type_sp - 3u];
- p->cg_type_stack[p->cg_type_sp - 3u] =
- p->cg_type_stack[p->cg_type_sp - 2u];
- p->cg_type_stack[p->cg_type_sp - 2u] =
- p->cg_type_stack[p->cg_type_sp - 1u];
+ p->cg_type_stack[p->cg_type_sp - 3u] = p->cg_type_stack[p->cg_type_sp - 2u];
+ p->cg_type_stack[p->cg_type_sp - 2u] = p->cg_type_stack[p->cg_type_sp - 1u];
p->cg_type_stack[p->cg_type_sp - 1u] = a;
}
}
@@ -106,70 +103,114 @@ int pcg_type_is_signed(const Type* ty) {
CfreeCgIntBinOp pcg_int_binop(BinOp op) {
switch (op) {
- case BO_IADD: return CFREE_CG_INT_ADD;
- case BO_ISUB: return CFREE_CG_INT_SUB;
- case BO_IMUL: return CFREE_CG_INT_MUL;
- case BO_SDIV: return CFREE_CG_INT_SDIV;
- case BO_UDIV: return CFREE_CG_INT_UDIV;
- case BO_SREM: return CFREE_CG_INT_SREM;
- case BO_UREM: return CFREE_CG_INT_UREM;
- case BO_AND: return CFREE_CG_INT_AND;
- case BO_OR: return CFREE_CG_INT_OR;
- case BO_XOR: return CFREE_CG_INT_XOR;
- case BO_SHL: return CFREE_CG_INT_SHL;
- case BO_SHR_S: return CFREE_CG_INT_ASHR;
- case BO_SHR_U: return CFREE_CG_INT_LSHR;
- default: return CFREE_CG_INT_ADD;
+ case BO_IADD:
+ return CFREE_CG_INT_ADD;
+ case BO_ISUB:
+ return CFREE_CG_INT_SUB;
+ case BO_IMUL:
+ return CFREE_CG_INT_MUL;
+ case BO_SDIV:
+ return CFREE_CG_INT_SDIV;
+ case BO_UDIV:
+ return CFREE_CG_INT_UDIV;
+ case BO_SREM:
+ return CFREE_CG_INT_SREM;
+ case BO_UREM:
+ return CFREE_CG_INT_UREM;
+ case BO_AND:
+ return CFREE_CG_INT_AND;
+ case BO_OR:
+ return CFREE_CG_INT_OR;
+ case BO_XOR:
+ return CFREE_CG_INT_XOR;
+ case BO_SHL:
+ return CFREE_CG_INT_SHL;
+ case BO_SHR_S:
+ return CFREE_CG_INT_ASHR;
+ case BO_SHR_U:
+ return CFREE_CG_INT_LSHR;
+ default:
+ return CFREE_CG_INT_ADD;
}
}
CfreeCgFpBinOp pcg_fp_binop(BinOp op) {
switch (op) {
- case BO_FADD: return CFREE_CG_FP_ADD;
- case BO_FSUB: return CFREE_CG_FP_SUB;
- case BO_FMUL: return CFREE_CG_FP_MUL;
- case BO_FDIV: return CFREE_CG_FP_DIV;
- default: return CFREE_CG_FP_ADD;
+ case BO_FADD:
+ return CFREE_CG_FP_ADD;
+ case BO_FSUB:
+ return CFREE_CG_FP_SUB;
+ case BO_FMUL:
+ return CFREE_CG_FP_MUL;
+ case BO_FDIV:
+ return CFREE_CG_FP_DIV;
+ default:
+ return CFREE_CG_FP_ADD;
}
}
CfreeCgIntCmpOp pcg_int_cmp(CmpOp op) {
switch (op) {
- case CMP_EQ: return CFREE_CG_INT_EQ;
- case CMP_NE: return CFREE_CG_INT_NE;
- case CMP_LT_S: return CFREE_CG_INT_LT_S;
- case CMP_LE_S: return CFREE_CG_INT_LE_S;
- case CMP_GT_S: return CFREE_CG_INT_GT_S;
- case CMP_GE_S: return CFREE_CG_INT_GE_S;
- case CMP_LT_U: return CFREE_CG_INT_LT_U;
- case CMP_LE_U: return CFREE_CG_INT_LE_U;
- case CMP_GT_U: return CFREE_CG_INT_GT_U;
- case CMP_GE_U: return CFREE_CG_INT_GE_U;
- default: return CFREE_CG_INT_EQ;
+ case CMP_EQ:
+ return CFREE_CG_INT_EQ;
+ case CMP_NE:
+ return CFREE_CG_INT_NE;
+ case CMP_LT_S:
+ return CFREE_CG_INT_LT_S;
+ case CMP_LE_S:
+ return CFREE_CG_INT_LE_S;
+ case CMP_GT_S:
+ return CFREE_CG_INT_GT_S;
+ case CMP_GE_S:
+ return CFREE_CG_INT_GE_S;
+ case CMP_LT_U:
+ return CFREE_CG_INT_LT_U;
+ case CMP_LE_U:
+ return CFREE_CG_INT_LE_U;
+ case CMP_GT_U:
+ return CFREE_CG_INT_GT_U;
+ case CMP_GE_U:
+ return CFREE_CG_INT_GE_U;
+ default:
+ return CFREE_CG_INT_EQ;
}
}
CfreeCgFpCmpOp pcg_fp_cmp(CmpOp op) {
switch (op) {
- case CMP_EQ: return CFREE_CG_FP_OEQ;
- case CMP_NE: return CFREE_CG_FP_ONE;
- case CMP_LT_F: return CFREE_CG_FP_OLT;
- case CMP_LE_F: return CFREE_CG_FP_OLE;
- case CMP_GT_F: return CFREE_CG_FP_OGT;
- case CMP_GE_F: return CFREE_CG_FP_OGE;
- default: return CFREE_CG_FP_OEQ;
+ case CMP_EQ:
+ return CFREE_CG_FP_OEQ;
+ case CMP_NE:
+ return CFREE_CG_FP_ONE;
+ case CMP_LT_F:
+ return CFREE_CG_FP_OLT;
+ case CMP_LE_F:
+ return CFREE_CG_FP_OLE;
+ case CMP_GT_F:
+ return CFREE_CG_FP_OGT;
+ case CMP_GE_F:
+ return CFREE_CG_FP_OGE;
+ default:
+ return CFREE_CG_FP_OEQ;
}
}
CfreeCgAtomicOp pcg_atomic_op(AtomicOp op) {
switch (op) {
- case AO_XCHG: return CFREE_CG_ATOMIC_XCHG;
- case AO_ADD: return CFREE_CG_ATOMIC_ADD;
- case AO_SUB: return CFREE_CG_ATOMIC_SUB;
- case AO_AND: return CFREE_CG_ATOMIC_AND;
- case AO_OR: return CFREE_CG_ATOMIC_OR;
- case AO_XOR: return CFREE_CG_ATOMIC_XOR;
- case AO_NAND: return CFREE_CG_ATOMIC_NAND;
+ case AO_XCHG:
+ return CFREE_CG_ATOMIC_XCHG;
+ case AO_ADD:
+ return CFREE_CG_ATOMIC_ADD;
+ case AO_SUB:
+ return CFREE_CG_ATOMIC_SUB;
+ case AO_AND:
+ return CFREE_CG_ATOMIC_AND;
+ case AO_OR:
+ return CFREE_CG_ATOMIC_OR;
+ case AO_XOR:
+ return CFREE_CG_ATOMIC_XOR;
+ case AO_NAND:
+ return CFREE_CG_ATOMIC_NAND;
}
return CFREE_CG_ATOMIC_XCHG;
}
@@ -301,10 +342,12 @@ void pcg_convert(Parser* p, const Type* dst) {
return;
}
if (si && di) {
- if (ds < ss) cfree_cg_trunc(p->cg, id);
+ if (ds < ss)
+ cfree_cg_trunc(p->cg, id);
else if (ds > ss && type_is_int(src) && pcg_type_is_signed(src))
cfree_cg_sext(p->cg, id);
- else if (ds > ss) cfree_cg_zext(p->cg, id);
+ else if (ds > ss)
+ cfree_cg_zext(p->cg, id);
} else if (type_is_int(src) && df) {
if (pcg_type_is_signed(src))
cfree_cg_sint_to_float(p->cg, id, CFREE_CG_ROUND_DEFAULT);
@@ -316,8 +359,10 @@ void pcg_convert(Parser* p, const Type* dst) {
else
cfree_cg_float_to_uint(p->cg, id, CFREE_CG_ROUND_DEFAULT);
} else if (sf && df) {
- if (ds > ss) cfree_cg_fpext(p->cg, id);
- else if (ds < ss) cfree_cg_fptrunc(p->cg, id);
+ if (ds > ss)
+ cfree_cg_fpext(p->cg, id);
+ else if (ds < ss)
+ cfree_cg_fptrunc(p->cg, id);
} else {
cfree_cg_bitcast(p->cg, id);
}
@@ -396,17 +441,19 @@ void pcg_fence(Parser* p, MemOrder ord) {
}
void pcg_intrinsic_unary_to_int(Parser* p, IntrinKind k) {
- CfreeCgIntrinsic ck = k == INTRIN_CLZ ? CFREE_CG_INTRIN_CLZ
- : k == INTRIN_CTZ ? CFREE_CG_INTRIN_CTZ
- : CFREE_CG_INTRIN_POPCOUNT;
+ CfreeCgIntrinsic ck = k == INTRIN_CLZ ? CFREE_CG_INTRIN_CLZ
+ : k == INTRIN_CTZ ? CFREE_CG_INTRIN_CTZ
+ : CFREE_CG_INTRIN_POPCOUNT;
const Type* ity = type_prim(p->pool, TY_INT);
cfree_cg_intrinsic(p->cg, ck, 1, pcg_tid(p->c, ity));
pcg_retag_top(p, ity);
}
void pcg_intrinsic_void(Parser* p, IntrinKind k) {
- if (k == INTRIN_UNREACHABLE) cfree_cg_unreachable(p->cg);
- else cfree_cg_intrinsic(p->cg, CFREE_CG_INTRIN_TRAP, 0, CFREE_CG_TYPE_NONE);
+ if (k == INTRIN_UNREACHABLE)
+ cfree_cg_unreachable(p->cg);
+ else
+ cfree_cg_intrinsic(p->cg, CFREE_CG_INTRIN_TRAP, 0, CFREE_CG_TYPE_NONE);
}
void pcg_inline_asm(Parser* p, const char* tmpl, const AsmConstraint* outs,
@@ -419,7 +466,7 @@ void pcg_inline_asm(Parser* p, const char* tmpl, const AsmConstraint* outs,
memset(&a, 0, sizeof a);
a.tmpl = cfree_sym_intern(p->c, tmpl ? tmpl : "");
if (nout) {
- o = arena_zarray(p->c->tu, CfreeCgAsmOperand, nout);
+ o = arena_zarray(p->pool->arena, CfreeCgAsmOperand, nout);
for (u32 i = 0; i < nout; ++i) {
o[i].constraint = cfree_sym_intern(p->c, outs[i].str ? outs[i].str : "");
o[i].name = outs[i].name;
@@ -428,17 +475,17 @@ void pcg_inline_asm(Parser* p, const char* tmpl, const AsmConstraint* outs,
}
}
if (nin) {
- in = arena_zarray(p->c->tu, CfreeCgAsmOperand, nin);
+ in = arena_zarray(p->pool->arena, CfreeCgAsmOperand, nin);
for (u32 i = 0; i < nin; ++i) {
in[i].constraint = cfree_sym_intern(p->c, ins[i].str ? ins[i].str : "");
in[i].name = ins[i].name;
in[i].type = pcg_tid(p->c, ins[i].type);
- in[i].dir = (ins[i].dir == ASM_INOUT) ? CFREE_CG_ASM_INOUT
- : CFREE_CG_ASM_IN;
+ in[i].dir =
+ (ins[i].dir == ASM_INOUT) ? CFREE_CG_ASM_INOUT : CFREE_CG_ASM_IN;
}
}
if (nclob) {
- cl = arena_array(p->c->tu, CfreeSym, nclob);
+ cl = arena_array(p->pool->arena, CfreeSym, nclob);
for (u32 i = 0; i < nclob; ++i) cl[i] = clobbers[i];
}
a.outputs = o;
diff --git a/lang/c/parse/cg_public_compat.h b/lang/c/parse/cg_public_compat.h
@@ -3,7 +3,7 @@
#include <cfree/cg.h>
-#include "core/core.h"
+#include "c_support.h"
#include "type/type.h"
typedef CfreeCg CG;
@@ -226,20 +226,20 @@ void pcg_inline_asm(Parser*, const char*, const AsmConstraint*, u32,
#define cg_push_global(g, sym, ty) pcg_push_global(p, (sym), (ty))
#define cg_load(g) pcg_load(p)
#define cg_addr(g) pcg_addr(p)
-#define cg_dup(g) \
- do { \
- cfree_cg_dup((g)); \
- pcg_dup_type(p); \
+#define cg_dup(g) \
+ do { \
+ cfree_cg_dup((g)); \
+ pcg_dup_type(p); \
} while (0)
-#define cg_swap(g) \
- do { \
- cfree_cg_swap((g)); \
- pcg_swap_type(p); \
+#define cg_swap(g) \
+ do { \
+ cfree_cg_swap((g)); \
+ pcg_swap_type(p); \
} while (0)
-#define cg_drop(g) \
- do { \
- cfree_cg_drop((g)); \
- pcg_drop_type(p); \
+#define cg_drop(g) \
+ do { \
+ cfree_cg_drop((g)); \
+ pcg_drop_type(p); \
} while (0)
#define cg_store(g) pcg_store(p)
#define cg_deref(g, ty) pcg_deref(p, (ty))
@@ -268,15 +268,15 @@ void pcg_inline_asm(Parser*, const char*, const AsmConstraint*, u32,
#define cg_label_new(g) cfree_cg_label_new((g))
#define cg_label_place(g, l) cfree_cg_label_place((g), (l))
#define cg_jump(g, l) cfree_cg_jump((g), (l))
-#define cg_branch_true(g, l) \
- do { \
+#define cg_branch_true(g, l) \
+ do { \
cfree_cg_branch_true((g), (l)); \
- pcg_drop_type(p); \
+ pcg_drop_type(p); \
} while (0)
-#define cg_branch_false(g, l) \
- do { \
+#define cg_branch_false(g, l) \
+ do { \
cfree_cg_branch_false((g), (l)); \
- pcg_drop_type(p); \
+ pcg_drop_type(p); \
} while (0)
#define cg_inline_asm(g, tmpl, outs, nout, ins, nin, clob, nclob) \
pcg_inline_asm(p, (tmpl), (outs), (nout), (ins), (nin), (clob), (nclob))
diff --git a/lang/c/parse/parse.c b/lang/c/parse/parse.c
@@ -15,26 +15,63 @@
* All expression, type, initializer, and statement code lives in
* parse_expr.c, parse_type.c, parse_init.c, and parse_stmt.c. */
-#include "parse/parse_priv.h"
-
#include <stdarg.h>
#include <string.h>
+#include "parse/parse_priv.h"
+
/* ============================================================
* Keywords
* ============================================================ */
static const char* const kw_names[KW_COUNT] = {
- NULL, "auto", "break", "case", "char",
- "const", "continue", "default", "do", "double",
- "else", "enum", "extern", "float", "for",
- "goto", "if", "inline", "int", "long",
- "register", "restrict", "return", "short", "signed",
- "sizeof", "static", "struct", "switch", "typedef",
- "union", "unsigned", "void", "volatile", "while",
- "_Bool", "_Complex", "_Imaginary","_Alignas", "_Alignof",
- "_Atomic", "_Generic", "_Noreturn", "_Static_assert", "_Thread_local",
- "asm", "__asm__",
+ NULL,
+ "auto",
+ "break",
+ "case",
+ "char",
+ "const",
+ "continue",
+ "default",
+ "do",
+ "double",
+ "else",
+ "enum",
+ "extern",
+ "float",
+ "for",
+ "goto",
+ "if",
+ "inline",
+ "int",
+ "long",
+ "register",
+ "restrict",
+ "return",
+ "short",
+ "signed",
+ "sizeof",
+ "static",
+ "struct",
+ "switch",
+ "typedef",
+ "union",
+ "unsigned",
+ "void",
+ "volatile",
+ "while",
+ "_Bool",
+ "_Complex",
+ "_Imaginary",
+ "_Alignas",
+ "_Alignof",
+ "_Atomic",
+ "_Generic",
+ "_Noreturn",
+ "_Static_assert",
+ "_Thread_local",
+ "asm",
+ "__asm__",
};
/* ============================================================
@@ -62,8 +99,7 @@ static size_t str_prefix_len(u16 flags) {
return 0;
}
-#define STR_ENC_MASK \
- (TF_STR_WIDE | TF_STR_U8 | TF_STR_U16 | TF_STR_U32)
+#define STR_ENC_MASK (TF_STR_WIDE | TF_STR_U8 | TF_STR_U16 | TF_STR_U32)
/* Fuse two adjacent TOK_STR tokens into one per C11 §6.4.5 ¶5. */
static Tok fuse_string_lits(Parser* p, Tok a, Tok b) {
@@ -77,14 +113,15 @@ static Tok fuse_string_lits(Parser* p, Tok a, Tok b) {
size_t a_content_len, b_content_len;
size_t out_pfx_len;
size_t out_len;
- Heap* h = p->c->env->heap;
+ Heap* h = cfree_compiler_heap(p->c);
char* buf;
size_t k = 0;
Tok out;
if (!as || !bs) perr(p, "bad string literal in concatenation");
if (ae != 0 && be != 0 && ae != be) {
- perr(p, "concatenating string literals with incompatible "
- "encoding prefixes");
+ perr(p,
+ "concatenating string literals with incompatible "
+ "encoding prefixes");
}
fused_enc = ae ? ae : be;
apfx = str_prefix_len(a.flags);
@@ -193,7 +230,7 @@ void record_braced_block(Parser* p) {
for (;;) {
if (p->replay_len == p->replay_cap) {
u32 new_cap = p->replay_cap ? p->replay_cap * 2 : 32;
- Tok* nv = arena_array(p->c->tu, Tok, new_cap);
+ Tok* nv = arena_array(p->pool->arena, Tok, new_cap);
if (!nv) perr(p, "out of memory in record_braced_block");
if (p->replay && p->replay_len) {
memcpy(nv, p->replay, p->replay_len * sizeof(Tok));
@@ -233,9 +270,12 @@ u32 count_recorded_top_level_items(const Tok* vec, u32 len) {
count = 1;
for (i = 1; i < len - 1; ++i) {
const Tok* t = &vec[i];
- if (is_punct(t, '{') || is_punct(t, '(') || is_punct(t, '[')) ++depth;
- else if (is_punct(t, '}') || is_punct(t, ')') || is_punct(t, ']')) --depth;
- else if (depth == 0 && is_punct(t, ',')) ++count;
+ if (is_punct(t, '{') || is_punct(t, '(') || is_punct(t, '['))
+ ++depth;
+ else if (is_punct(t, '}') || is_punct(t, ')') || is_punct(t, ']'))
+ --depth;
+ else if (depth == 0 && is_punct(t, ','))
+ ++count;
}
if (is_punct(&vec[len - 2], ',')) --count;
return count;
@@ -246,7 +286,7 @@ u32 count_recorded_top_level_items(const Tok* vec, u32 len) {
* ============================================================ */
Scope* scope_new(Parser* p, Scope* parent) {
- Scope* s = arena_new(p->c->tu, Scope);
+ Scope* s = arena_new(p->pool->arena, Scope);
if (!s) perr(p, "out of memory in scope_new");
s->entries = NULL;
s->tags = NULL;
@@ -262,7 +302,7 @@ void scope_pop(Parser* p) {
SymEntry* scope_define(Parser* p, Sym name, SymEntryKind kind,
const Type* type) {
- SymEntry* e = arena_new(p->c->tu, SymEntry);
+ SymEntry* e = arena_new(p->pool->arena, SymEntry);
if (!e) perr(p, "out of memory in scope_define");
memset(e, 0, sizeof *e);
e->name = name;
@@ -286,7 +326,7 @@ SymEntry* scope_lookup(Parser* p, Sym name) {
TagEntry* tag_define(Parser* p, Sym name, TagDeclKind kind, Type* type,
int complete) {
- TagEntry* e = arena_new(p->c->tu, TagEntry);
+ TagEntry* e = arena_new(p->pool->arena, TagEntry);
if (!e) perr(p, "out of memory in tag_define");
memset(e, 0, sizeof *e);
e->name = name;
@@ -329,8 +369,8 @@ static const Type* ty_size_t(Parser* p) {
* Local-variable slot allocation
* ============================================================ */
-FrameSlot make_local_aligned(Parser* p, Sym name, const Type* type,
- SrcLoc loc, u32 align_override) {
+FrameSlot make_local_aligned(Parser* p, Sym name, const Type* type, SrcLoc loc,
+ u32 align_override) {
FrameSlotDesc fsd;
FrameSlot s;
SymEntry* e;
@@ -454,7 +494,8 @@ static void parse_init_declarator(Parser* p, const DeclSpecs* specs) {
e = scope_define(p, name, SEK_GLOBAL, var_ty);
e->v.sym = sym;
has_init = accept_punct(p, '=');
- if (has_init && var_ty && var_ty->kind == TY_ARRAY && var_ty->arr.incomplete) {
+ if (has_init && var_ty && var_ty->kind == TY_ARRAY &&
+ var_ty->arr.incomplete) {
const Type* completed = complete_incomplete_array(p, var_ty);
if (completed != var_ty) {
var_ty = completed;
@@ -553,7 +594,8 @@ static void parse_init_declarator(Parser* p, const DeclSpecs* specs) {
{
int has_init = is_punct(&p->cur, '=');
FrameSlot s;
- if (has_init && var_ty && var_ty->kind == TY_ARRAY && var_ty->arr.incomplete) {
+ if (has_init && var_ty && var_ty->kind == TY_ARRAY &&
+ var_ty->arr.incomplete) {
advance(p); /* '=' */
var_ty = complete_incomplete_array(p, var_ty);
s = make_local_aligned(p, name, var_ty, loc, specs->align);
@@ -569,7 +611,7 @@ static void parse_init_declarator(Parser* p, const DeclSpecs* specs) {
parse_assign_expr(p);
emit_struct_copy_into_slot(p, s, var_ty, 0, var_ty);
} else if (var_ty->kind == TY_ARRAY || var_ty->kind == TY_STRUCT ||
- var_ty->kind == TY_UNION) {
+ var_ty->kind == TY_UNION) {
init_at(p, s, var_ty, 0, var_ty);
} else {
cg_push_local_typed(p->cg, s, var_ty);
@@ -616,7 +658,7 @@ void parse_param_list(Parser* p, ParamInfo** infos_out, u16* nparams_out,
}
}
- infos = (ParamInfo*)arena_array(p->c->tu, ParamInfo, cap);
+ infos = (ParamInfo*)arena_array(p->pool->arena, ParamInfo, cap);
for (;;) {
DeclSpecs specs;
Sym pname = 0;
@@ -640,7 +682,7 @@ void parse_param_list(Parser* p, ParamInfo** infos_out, u16* nparams_out,
}
if (n == cap) {
cap *= 2;
- ParamInfo* nbuf = (ParamInfo*)arena_array(p->c->tu, ParamInfo, cap);
+ ParamInfo* nbuf = (ParamInfo*)arena_array(p->pool->arena, ParamInfo, cap);
memcpy(nbuf, infos, sizeof(ParamInfo) * n);
infos = nbuf;
}
@@ -656,10 +698,8 @@ void parse_param_list(Parser* p, ParamInfo** infos_out, u16* nparams_out,
static SymEntry* declare_function(Parser* p, Sym fname, const Type* fn_ty,
const DeclSpecs* specs, SrcLoc fname_loc,
- const Attr* dattrs,
- ObjSecId* out_section_id,
- u32* out_decl_flags,
- Sym* out_alias_target) {
+ const Attr* dattrs, ObjSecId* out_section_id,
+ u32* out_decl_flags, Sym* out_alias_target) {
if (out_section_id) *out_section_id = OBJ_SEC_NONE;
if (out_decl_flags) *out_decl_flags = 0;
if (out_alias_target) *out_alias_target = 0;
@@ -684,8 +724,7 @@ static SymEntry* declare_function(Parser* p, Sym fname, const Type* fn_ty,
decl_in.type = fn_ty;
decl_in.loc = fname_loc;
decl_in.storage = (specs->storage == DS_STATIC) ? DS_STATIC : DS_EXTERN;
- decl_in.linkage =
- (specs->storage == DS_STATIC) ? DL_INTERNAL : DL_EXTERNAL;
+ decl_in.linkage = (specs->storage == DS_STATIC) ? DL_INTERNAL : DL_EXTERNAL;
decl_in.visibility = SV_DEFAULT;
attr_list_to_decl(p->c, p->decls, specs->attrs, &decl_in);
attr_list_to_decl(p->c, p->decls, dattrs, &decl_in);
@@ -719,7 +758,7 @@ static void parse_function_body(Parser* p, ObjSymId fsym, const Type* fn_ty,
if (decl_flags & DF_NORETURN) fd.flags |= CGFD_NORETURN;
if (nparams) {
- pds = (CGParamDesc*)arena_array(p->c->tu, CGParamDesc, nparams);
+ pds = (CGParamDesc*)arena_array(p->pool->arena, CGParamDesc, nparams);
memset(pds, 0, sizeof(CGParamDesc) * nparams);
for (u16 i = 0; i < nparams; ++i) {
pds[i].index = i;
@@ -798,9 +837,9 @@ static void parse_external_decl(Parser* p) {
for (;;) {
Sym tname = 0;
SrcLoc tloc = {0, 0, 0};
- const Type* tty = parse_declarator_full(p, specs.type,
- /*allow_abstract=*/0,
- &tname, &tloc);
+ const Type* tty =
+ parse_declarator_full(p, specs.type,
+ /*allow_abstract=*/0, &tname, &tloc);
if (is_punct(&p->cur, '=')) {
perr(p, "typedef declarator cannot have initializer");
}
@@ -813,7 +852,8 @@ static void parse_external_decl(Parser* p) {
}
base_ty = parse_pointer_layer(p, specs.type);
- if (p->cur.kind != TOK_IDENT || ident_kw_inline(p, p->cur.v.ident) != KW_NONE) {
+ if (p->cur.kind != TOK_IDENT ||
+ ident_kw_inline(p, p->cur.v.ident) != KW_NONE) {
perr(p, "expected declarator");
}
name = p->cur.v.ident;
@@ -846,18 +886,17 @@ static void parse_external_decl(Parser* p) {
parse_attrs_into(p, &dattrs);
if (nparams) {
- ptypes = (const Type**)arena_array(p->c->tu, const Type*, nparams);
+ ptypes = (const Type**)arena_array(p->pool->arena, const Type*, nparams);
for (u16 i = 0; i < nparams; ++i) ptypes[i] = infos[i].type;
}
fn_ty = type_func(p->pool, base_ty, ptypes, nparams, (int)variadic);
- abi = c_abi_func_info(p->abi, fn_ty);
+ abi = c_abi_func_info(p->abi, p->pool, fn_ty);
ObjSecId fn_section_id;
u32 fn_decl_flags;
Sym fn_alias_target;
- fent = declare_function(p, name, fn_ty, &specs, loc, dattrs,
- &fn_section_id, &fn_decl_flags,
- &fn_alias_target);
+ fent = declare_function(p, name, fn_ty, &specs, loc, dattrs, &fn_section_id,
+ &fn_decl_flags, &fn_alias_target);
attr_list_append(&fent->attrs, dattrs);
if (is_punct(&p->cur, '{')) {
@@ -874,8 +913,7 @@ static void parse_external_decl(Parser* p) {
if (!te) {
size_t nl = 0;
const char* nm = pool_str(p->pool, fn_alias_target, &nl);
- compiler_panic(p->c, loc,
- "alias target '%s' is undefined",
+ compiler_panic(p->c, loc, "alias target '%s' is undefined",
nm ? nm : "?");
}
CfreeCgAlias alias;
@@ -883,14 +921,13 @@ static void parse_external_decl(Parser* p) {
alias.display_name = name;
alias.linkage_name = cfree_cg_c_linkage_name(p->c, name);
alias.target = te->v.sym;
- alias.sym.bind = (fn_decl_flags & DF_WEAK) ? CFREE_SB_WEAK
- : CFREE_SB_GLOBAL;
+ alias.sym.bind =
+ (fn_decl_flags & DF_WEAK) ? CFREE_SB_WEAK : CFREE_SB_GLOBAL;
alias.sym.visibility = CFREE_CG_VIS_DEFAULT;
if (cfree_cg_alias(p->cg, alias) == CFREE_CG_SYM_NONE) {
size_t nl = 0;
const char* nm = pool_str(p->pool, fn_alias_target, &nl);
- compiler_panic(p->c, loc,
- "alias target '%s' is undefined",
+ compiler_panic(p->c, loc, "alias target '%s' is undefined",
nm ? nm : "?");
}
}
@@ -960,17 +997,16 @@ static void parse_external_decl(Parser* p) {
}
}
define_static_object(p, sym, section_id, base_ty, specs.quals,
- /*has_init=*/1, loc,
- align_eff);
+ /*has_init=*/1, loc, align_eff);
} else if (!is_pure_extern) {
define_static_object(p, sym, section_id, base_ty, specs.quals,
- /*has_init=*/0, loc,
- align_eff);
+ /*has_init=*/0, loc, align_eff);
}
if (!accept_punct(p, ',')) break;
base_ty = parse_pointer_layer(p, specs.type);
- if (p->cur.kind != TOK_IDENT || ident_kw_inline(p, p->cur.v.ident) != KW_NONE) {
+ if (p->cur.kind != TOK_IDENT ||
+ ident_kw_inline(p, p->cur.v.ident) != KW_NONE) {
perr(p, "expected declarator after ','");
}
name = p->cur.v.ident;
@@ -1033,7 +1069,7 @@ static void parse_translation_unit(Parser* p) {
* Entry point
* ============================================================ */
-void parse_c(Compiler* c, Pp* pp, DeclTable* decls, CG* cg) {
+void parse_c(Compiler* c, Pool* pool, Pp* pp, DeclTable* decls, CG* cg) {
Parser p;
CKw i;
@@ -1042,51 +1078,51 @@ void parse_c(Compiler* c, Pp* pp, DeclTable* decls, CG* cg) {
p.pp = pp;
p.decls = decls;
p.cg = cg;
- p.abi = c->abi;
- p.pool = c->global;
+ p.abi = c;
+ p.pool = pool;
for (i = (CKw)1; i < KW_COUNT; ++i) {
p.kw_sym[i] = pool_intern_cstr(p.pool, kw_names[i]);
}
- p.sym_b_alloca = pool_intern_cstr(p.pool, "__builtin_alloca");
- p.sym_b_ctz = pool_intern_cstr(p.pool, "__builtin_ctz");
- p.sym_b_clz = pool_intern_cstr(p.pool, "__builtin_clz");
- p.sym_b_clzl = pool_intern_cstr(p.pool, "__builtin_clzl");
- p.sym_b_clzll = pool_intern_cstr(p.pool, "__builtin_clzll");
- p.sym_b_trap = pool_intern_cstr(p.pool, "__builtin_trap");
+ p.sym_b_alloca = pool_intern_cstr(p.pool, "__builtin_alloca");
+ p.sym_b_ctz = pool_intern_cstr(p.pool, "__builtin_ctz");
+ p.sym_b_clz = pool_intern_cstr(p.pool, "__builtin_clz");
+ p.sym_b_clzl = pool_intern_cstr(p.pool, "__builtin_clzl");
+ p.sym_b_clzll = pool_intern_cstr(p.pool, "__builtin_clzll");
+ p.sym_b_trap = pool_intern_cstr(p.pool, "__builtin_trap");
p.sym_b_unreachable = pool_intern_cstr(p.pool, "__builtin_unreachable");
- p.sym_b_memcpy = pool_intern_cstr(p.pool, "__builtin_memcpy");
- p.sym_b_memmove = pool_intern_cstr(p.pool, "__builtin_memmove");
- p.sym_b_memcmp = pool_intern_cstr(p.pool, "__builtin_memcmp");
- p.sym_b_memset = pool_intern_cstr(p.pool, "__builtin_memset");
- p.sym_func = pool_intern_cstr(p.pool, "__func__");
- p.sym_func_gcc = pool_intern_cstr(p.pool, "__FUNCTION__");
+ p.sym_b_memcpy = pool_intern_cstr(p.pool, "__builtin_memcpy");
+ p.sym_b_memmove = pool_intern_cstr(p.pool, "__builtin_memmove");
+ p.sym_b_memcmp = pool_intern_cstr(p.pool, "__builtin_memcmp");
+ p.sym_b_memset = pool_intern_cstr(p.pool, "__builtin_memset");
+ p.sym_func = pool_intern_cstr(p.pool, "__func__");
+ p.sym_func_gcc = pool_intern_cstr(p.pool, "__FUNCTION__");
p.sym_pretty_func_gcc = pool_intern_cstr(p.pool, "__PRETTY_FUNCTION__");
- p.sym_b_expect = pool_intern_cstr(p.pool, "__builtin_expect");
- p.sym_b_offsetof = pool_intern_cstr(p.pool, "__builtin_offsetof");
- p.sym_b_va_list = pool_intern_cstr(p.pool, "__builtin_va_list");
- p.sym_b_va_start = pool_intern_cstr(p.pool, "__builtin_va_start");
- p.sym_b_va_arg = pool_intern_cstr(p.pool, "__builtin_va_arg");
- p.sym_b_va_end = pool_intern_cstr(p.pool, "__builtin_va_end");
- p.sym_b_va_copy = pool_intern_cstr(p.pool, "__builtin_va_copy");
- p.sym_attribute = pool_intern_cstr(p.pool, "__attribute__");
+ p.sym_b_expect = pool_intern_cstr(p.pool, "__builtin_expect");
+ p.sym_b_offsetof = pool_intern_cstr(p.pool, "__builtin_offsetof");
+ p.sym_b_va_list = pool_intern_cstr(p.pool, "__builtin_va_list");
+ p.sym_b_va_start = pool_intern_cstr(p.pool, "__builtin_va_start");
+ p.sym_b_va_arg = pool_intern_cstr(p.pool, "__builtin_va_arg");
+ p.sym_b_va_end = pool_intern_cstr(p.pool, "__builtin_va_end");
+ p.sym_b_va_copy = pool_intern_cstr(p.pool, "__builtin_va_copy");
+ p.sym_attribute = pool_intern_cstr(p.pool, "__attribute__");
p.sym_volatile_alias = pool_intern_cstr(p.pool, "__volatile__");
- p.sym_alignof_alias = pool_intern_cstr(p.pool, "__alignof__");
- p.sym_int128 = pool_intern_cstr(p.pool, "__int128");
- p.sym_int128_t = pool_intern_cstr(p.pool, "__int128_t");
- p.sym_uint128_t = pool_intern_cstr(p.pool, "__uint128_t");
- p.sym_a_load_n = pool_intern_cstr(p.pool, "__atomic_load_n");
- p.sym_a_store_n = pool_intern_cstr(p.pool, "__atomic_store_n");
+ p.sym_alignof_alias = pool_intern_cstr(p.pool, "__alignof__");
+ p.sym_int128 = pool_intern_cstr(p.pool, "__int128");
+ p.sym_int128_t = pool_intern_cstr(p.pool, "__int128_t");
+ p.sym_uint128_t = pool_intern_cstr(p.pool, "__uint128_t");
+ p.sym_a_load_n = pool_intern_cstr(p.pool, "__atomic_load_n");
+ p.sym_a_store_n = pool_intern_cstr(p.pool, "__atomic_store_n");
p.sym_a_exchange_n = pool_intern_cstr(p.pool, "__atomic_exchange_n");
- p.sym_a_fetch_add = pool_intern_cstr(p.pool, "__atomic_fetch_add");
- p.sym_a_fetch_sub = pool_intern_cstr(p.pool, "__atomic_fetch_sub");
- p.sym_a_fetch_and = pool_intern_cstr(p.pool, "__atomic_fetch_and");
- p.sym_a_fetch_or = pool_intern_cstr(p.pool, "__atomic_fetch_or");
- p.sym_a_fetch_xor = pool_intern_cstr(p.pool, "__atomic_fetch_xor");
- p.sym_a_cas_n = pool_intern_cstr(p.pool, "__atomic_compare_exchange_n");
- p.sym_a_thread_fence = pool_intern_cstr(p.pool, "__atomic_thread_fence");
- p.sym_a_signal_fence = pool_intern_cstr(p.pool, "__atomic_signal_fence");
+ p.sym_a_fetch_add = pool_intern_cstr(p.pool, "__atomic_fetch_add");
+ p.sym_a_fetch_sub = pool_intern_cstr(p.pool, "__atomic_fetch_sub");
+ p.sym_a_fetch_and = pool_intern_cstr(p.pool, "__atomic_fetch_and");
+ p.sym_a_fetch_or = pool_intern_cstr(p.pool, "__atomic_fetch_or");
+ p.sym_a_fetch_xor = pool_intern_cstr(p.pool, "__atomic_fetch_xor");
+ p.sym_a_cas_n = pool_intern_cstr(p.pool, "__atomic_compare_exchange_n");
+ p.sym_a_thread_fence = pool_intern_cstr(p.pool, "__atomic_thread_fence");
+ p.sym_a_signal_fence = pool_intern_cstr(p.pool, "__atomic_signal_fence");
p.scope = scope_new(&p, NULL);
diff --git a/lang/c/parse/parse.h b/lang/c/parse/parse.h
@@ -7,6 +7,6 @@
/* C11 frontend. Reads preprocessed tokens, records C declarations, and drives
* the public CG API for executable code and object data. */
-void parse_c(Compiler*, Pp*, DeclTable*, CG*);
+void parse_c(Compiler*, Pool*, Pp*, DeclTable*, CG*);
#endif
diff --git a/lang/c/parse/parse_expr.c b/lang/c/parse/parse_expr.c
@@ -8,7 +8,6 @@ static const Type* ty_size_t(Parser* p) {
return c_abi_size_type(p->abi, p->pool);
}
-
static CKw ident_kw(const Parser* p, Sym name) {
return ident_kw_inline(p, name);
}
@@ -65,10 +64,14 @@ static const Type* int_literal_type(Parser* p, const Tok* t) {
int l = (t->flags & TF_INT_L) != 0;
int ll = (t->flags & TF_INT_LL) != 0;
TypeKind k;
- if (ll) k = u ? TY_ULLONG : TY_LLONG;
- else if (l) k = u ? TY_ULONG : TY_LONG;
- else if (u) k = TY_UINT;
- else k = TY_INT;
+ if (ll)
+ k = u ? TY_ULLONG : TY_LLONG;
+ else if (l)
+ k = u ? TY_ULONG : TY_LONG;
+ else if (u)
+ k = TY_UINT;
+ else
+ k = TY_INT;
return type_prim(p->pool, k);
}
@@ -89,13 +92,17 @@ static double parse_float_literal(Parser* p, const Tok* t) {
while (i < len) {
int c = (unsigned char)s[i];
int dv;
- if (c == '.' || c == 'e' || c == 'E' || c == 'p' || c == 'P' ||
- c == 'f' || c == 'F' || c == 'l' || c == 'L')
+ if (c == '.' || c == 'e' || c == 'E' || c == 'p' || c == 'P' || c == 'f' ||
+ c == 'F' || c == 'l' || c == 'L')
break;
- if (c >= '0' && c <= '9') dv = c - '0';
- else if (is_hex && c >= 'a' && c <= 'f') dv = c - 'a' + 10;
- else if (is_hex && c >= 'A' && c <= 'F') dv = c - 'A' + 10;
- else perr(p, "bad digit in float literal");
+ if (c >= '0' && c <= '9')
+ dv = c - '0';
+ else if (is_hex && c >= 'a' && c <= 'f')
+ dv = c - 'a' + 10;
+ else if (is_hex && c >= 'A' && c <= 'F')
+ dv = c - 'A' + 10;
+ else
+ perr(p, "bad digit in float literal");
v = v * (is_hex ? 16.0 : 10.0) + (double)dv;
i++;
}
@@ -104,13 +111,17 @@ static double parse_float_literal(Parser* p, const Tok* t) {
while (i < len) {
int c = (unsigned char)s[i];
int dv;
- if (c == 'e' || c == 'E' || c == 'p' || c == 'P' ||
- c == 'f' || c == 'F' || c == 'l' || c == 'L')
+ if (c == 'e' || c == 'E' || c == 'p' || c == 'P' || c == 'f' ||
+ c == 'F' || c == 'l' || c == 'L')
break;
- if (c >= '0' && c <= '9') dv = c - '0';
- else if (is_hex && c >= 'a' && c <= 'f') dv = c - 'a' + 10;
- else if (is_hex && c >= 'A' && c <= 'F') dv = c - 'A' + 10;
- else perr(p, "bad digit in float literal");
+ if (c >= '0' && c <= '9')
+ dv = c - '0';
+ else if (is_hex && c >= 'a' && c <= 'f')
+ dv = c - 'a' + 10;
+ else if (is_hex && c >= 'A' && c <= 'F')
+ dv = c - 'A' + 10;
+ else
+ perr(p, "bad digit in float literal");
v = v * (is_hex ? 16.0 : 10.0) + (double)dv;
exp -= 1;
frac_seen = 1;
@@ -139,14 +150,32 @@ static double parse_float_literal(Parser* p, const Tok* t) {
exp = 0;
}
}
- while (exp < 0) { v /= (is_hex ? 16.0 : 10.0); exp++; }
- while (exp > 0) { v *= (is_hex ? 16.0 : 10.0); exp--; }
+ while (exp < 0) {
+ v /= (is_hex ? 16.0 : 10.0);
+ exp++;
+ }
+ while (exp > 0) {
+ v *= (is_hex ? 16.0 : 10.0);
+ exp--;
+ }
if (is_hex) {
- while (dec_exp < 0) { v /= 2.0; dec_exp++; }
- while (dec_exp > 0) { v *= 2.0; dec_exp--; }
+ while (dec_exp < 0) {
+ v /= 2.0;
+ dec_exp++;
+ }
+ while (dec_exp > 0) {
+ v *= 2.0;
+ dec_exp--;
+ }
} else {
- while (dec_exp < 0) { v /= 10.0; dec_exp++; }
- while (dec_exp > 0) { v *= 10.0; dec_exp--; }
+ while (dec_exp < 0) {
+ v /= 10.0;
+ dec_exp++;
+ }
+ while (dec_exp > 0) {
+ v *= 10.0;
+ dec_exp--;
+ }
}
return v;
}
@@ -172,27 +201,53 @@ static i64 decode_one_char(Parser* p, const char* s, size_t len, size_t* pi,
if (i >= len) compiler_panic(p->c, loc, "trailing '\\' in literal");
c = (unsigned char)s[i++];
switch (c) {
- case 'n': v = '\n'; break;
- case 't': v = '\t'; break;
- case 'r': v = '\r'; break;
- case 'b': v = '\b'; break;
- case 'f': v = '\f'; break;
- case 'v': v = '\v'; break;
- case 'a': v = '\a'; break;
- case '\\': v = '\\'; break;
- case '\'': v = '\''; break;
- case '"': v = '"'; break;
- case '?': v = '?'; break;
+ case 'n':
+ v = '\n';
+ break;
+ case 't':
+ v = '\t';
+ break;
+ case 'r':
+ v = '\r';
+ break;
+ case 'b':
+ v = '\b';
+ break;
+ case 'f':
+ v = '\f';
+ break;
+ case 'v':
+ v = '\v';
+ break;
+ case 'a':
+ v = '\a';
+ break;
+ case '\\':
+ v = '\\';
+ break;
+ case '\'':
+ v = '\'';
+ break;
+ case '"':
+ v = '"';
+ break;
+ case '?':
+ v = '?';
+ break;
case 'x': {
i64 hex = 0;
int any = 0;
while (i < len) {
int d = (unsigned char)s[i];
int dv;
- if (d >= '0' && d <= '9') dv = d - '0';
- else if (d >= 'a' && d <= 'f') dv = d - 'a' + 10;
- else if (d >= 'A' && d <= 'F') dv = d - 'A' + 10;
- else break;
+ if (d >= '0' && d <= '9')
+ dv = d - '0';
+ else if (d >= 'a' && d <= 'f')
+ dv = d - 'a' + 10;
+ else if (d >= 'A' && d <= 'F')
+ dv = d - 'A' + 10;
+ else
+ break;
hex = hex * 16 + dv;
any = 1;
i++;
@@ -226,8 +281,10 @@ i64 decode_char_literal(Parser* p, const Tok* t) {
size_t i = 0;
i64 v;
if (!s) perr(p, "bad char literal");
- if (t->flags & TF_STR_U8) i = 2;
- else if (t->flags & (TF_STR_WIDE | TF_STR_U16 | TF_STR_U32)) i = 1;
+ if (t->flags & TF_STR_U8)
+ i = 2;
+ else if (t->flags & (TF_STR_WIDE | TF_STR_U16 | TF_STR_U32))
+ i = 1;
if (i >= len || s[i] != '\'') perr(p, "malformed character literal");
i++;
if (i >= len || s[i] == '\'') perr(p, "empty character literal");
@@ -242,12 +299,14 @@ u8* decode_string_literal(Parser* p, const Tok* t, size_t* nlen_out) {
size_t len = 0;
const char* s = pool_str(p->pool, t->spelling, &len);
size_t i = 0;
- Heap* h = p->c->env->heap;
+ Heap* h = cfree_compiler_heap(p->c);
u8* buf;
size_t k = 0;
if (!s) perr(p, "bad string literal");
- if (t->flags & TF_STR_U8) i = 2;
- else if (t->flags & (TF_STR_WIDE | TF_STR_U16 | TF_STR_U32)) i = 1;
+ if (t->flags & TF_STR_U8)
+ i = 2;
+ else if (t->flags & (TF_STR_WIDE | TF_STR_U16 | TF_STR_U32))
+ i = 1;
if (i >= len || s[i] != '"') perr(p, "malformed string literal");
i++;
buf = (u8*)h->alloc(h, len + 1, 1);
@@ -262,7 +321,8 @@ u8* decode_string_literal(Parser* p, const Tok* t, size_t* nlen_out) {
}
CfreeCgSym emit_string_to_rodata(Parser* p, const u8* bytes, size_t n) {
- const Type* arr_ty = type_array(p->pool, type_prim(p->pool, TY_CHAR), (u32)n, 0);
+ const Type* arr_ty =
+ type_array(p->pool, type_prim(p->pool, TY_CHAR), (u32)n, 0);
return cfree_cg_const_data(p->cg, bytes, n, 1u, pcg_tid(p->c, arr_ty));
}
@@ -276,7 +336,8 @@ static const Type* offsetof_designator(Parser* p, const Type* base, u32* off);
static i64 cexpr_mul(Parser* p, SrcLoc loc) {
i64 v = cexpr_unary(p, loc);
for (;;) {
- if (accept_punct(p, '*')) v = v * cexpr_unary(p, loc);
+ if (accept_punct(p, '*'))
+ v = v * cexpr_unary(p, loc);
else if (accept_punct(p, '/')) {
i64 r = cexpr_unary(p, loc);
if (r == 0) compiler_panic(p->c, loc, "division by zero in constant");
@@ -285,47 +346,62 @@ static i64 cexpr_mul(Parser* p, SrcLoc loc) {
i64 r = cexpr_unary(p, loc);
if (r == 0) compiler_panic(p->c, loc, "modulo by zero in constant");
v = v % r;
- } else break;
+ } else
+ break;
}
return v;
}
static i64 cexpr_add(Parser* p, SrcLoc loc) {
i64 v = cexpr_mul(p, loc);
for (;;) {
- if (accept_punct(p, '+')) v = v + cexpr_mul(p, loc);
- else if (accept_punct(p, '-')) v = v - cexpr_mul(p, loc);
- else break;
+ if (accept_punct(p, '+'))
+ v = v + cexpr_mul(p, loc);
+ else if (accept_punct(p, '-'))
+ v = v - cexpr_mul(p, loc);
+ else
+ break;
}
return v;
}
static i64 cexpr_shift(Parser* p, SrcLoc loc) {
i64 v = cexpr_add(p, loc);
for (;;) {
- if (accept_punct(p, P_SHL)) v = v << cexpr_add(p, loc);
- else if (accept_punct(p, P_SHR)) v = v >> cexpr_add(p, loc);
- else break;
+ if (accept_punct(p, P_SHL))
+ v = v << cexpr_add(p, loc);
+ else if (accept_punct(p, P_SHR))
+ v = v >> cexpr_add(p, loc);
+ else
+ break;
}
return v;
}
static i64 cexpr_rel(Parser* p, SrcLoc loc) {
i64 v = cexpr_shift(p, loc);
for (;;) {
- if (accept_punct(p, P_LE)) v = v <= cexpr_shift(p, loc);
- else if (accept_punct(p, P_GE)) v = v >= cexpr_shift(p, loc);
+ if (accept_punct(p, P_LE))
+ v = v <= cexpr_shift(p, loc);
+ else if (accept_punct(p, P_GE))
+ v = v >= cexpr_shift(p, loc);
else if (is_punct(&p->cur, '<')) {
- advance(p); v = v < cexpr_shift(p, loc);
+ advance(p);
+ v = v < cexpr_shift(p, loc);
} else if (is_punct(&p->cur, '>')) {
- advance(p); v = v > cexpr_shift(p, loc);
- } else break;
+ advance(p);
+ v = v > cexpr_shift(p, loc);
+ } else
+ break;
}
return v;
}
static i64 cexpr_eq(Parser* p, SrcLoc loc) {
i64 v = cexpr_rel(p, loc);
for (;;) {
- if (accept_punct(p, P_EQ)) v = (v == cexpr_rel(p, loc));
- else if (accept_punct(p, P_NE)) v = (v != cexpr_rel(p, loc));
- else break;
+ if (accept_punct(p, P_EQ))
+ v = (v == cexpr_rel(p, loc));
+ else if (accept_punct(p, P_NE))
+ v = (v != cexpr_rel(p, loc));
+ else
+ break;
}
return v;
}
@@ -511,7 +587,7 @@ static const Type* offsetof_designator(Parser* p, const Type* base, u32* off) {
const Field* mf = NULL;
/* find_field is static in parse_type.c; we need it here.
* We call c_abi_record_layout directly inline. */
- const ABIRecordLayout* L = c_abi_record_layout(p->abi, cur);
+ const ABIRecordLayout* L = c_abi_record_layout(p->abi, p->pool, cur);
if (!L) perr(p, "no such member in __builtin_offsetof");
int found = 0;
for (u16 i = 0; i < cur->rec.nfields; ++i) {
@@ -570,27 +646,26 @@ static int try_parse_builtin_call(Parser* p) {
* forgot to declare the underlying libc function. */
if (name == p->sym_b_memcpy || name == p->sym_b_memmove ||
name == p->sym_b_memcmp || name == p->sym_b_memset) {
- const char* libname = (name == p->sym_b_memcpy) ? "memcpy"
- : (name == p->sym_b_memmove) ? "memmove"
- : (name == p->sym_b_memcmp) ? "memcmp"
- : "memset";
+ const char* libname = (name == p->sym_b_memcpy) ? "memcpy"
+ : (name == p->sym_b_memmove) ? "memmove"
+ : (name == p->sym_b_memcmp) ? "memcmp"
+ : "memset";
p->cur.v.ident = pool_intern_cstr(p->pool, libname);
return 0;
}
- if (name != p->sym_b_alloca && name != p->sym_b_ctz &&
- name != p->sym_b_clz && name != p->sym_b_clzl &&
- name != p->sym_b_clzll && name != p->sym_b_trap &&
- name != p->sym_b_unreachable &&
- name != p->sym_b_expect &&
- name != p->sym_b_offsetof && name != p->sym_b_va_start &&
- name != p->sym_b_va_arg && name != p->sym_b_va_end &&
- name != p->sym_b_va_copy && name != p->sym_a_load_n &&
- name != p->sym_a_store_n && name != p->sym_a_exchange_n &&
- name != p->sym_a_fetch_add && name != p->sym_a_fetch_sub &&
- name != p->sym_a_fetch_and && name != p->sym_a_fetch_or &&
- name != p->sym_a_fetch_xor && name != p->sym_a_cas_n &&
- name != p->sym_a_thread_fence && name != p->sym_a_signal_fence) {
+ if (name != p->sym_b_alloca && name != p->sym_b_ctz && name != p->sym_b_clz &&
+ name != p->sym_b_clzl && name != p->sym_b_clzll &&
+ name != p->sym_b_trap && name != p->sym_b_unreachable &&
+ name != p->sym_b_expect && name != p->sym_b_offsetof &&
+ name != p->sym_b_va_start && name != p->sym_b_va_arg &&
+ name != p->sym_b_va_end && name != p->sym_b_va_copy &&
+ name != p->sym_a_load_n && name != p->sym_a_store_n &&
+ name != p->sym_a_exchange_n && name != p->sym_a_fetch_add &&
+ name != p->sym_a_fetch_sub && name != p->sym_a_fetch_and &&
+ name != p->sym_a_fetch_or && name != p->sym_a_fetch_xor &&
+ name != p->sym_a_cas_n && name != p->sym_a_thread_fence &&
+ name != p->sym_a_signal_fence) {
return 0;
}
advance(p); /* IDENT */
@@ -634,8 +709,7 @@ static int try_parse_builtin_call(Parser* p) {
return 1;
}
- if (name == p->sym_b_clz || name == p->sym_b_clzl ||
- name == p->sym_b_clzll) {
+ if (name == p->sym_b_clz || name == p->sym_b_clzl || name == p->sym_b_clzll) {
parse_assign_expr(p);
to_rvalue(p);
expect_punct(p, ')', "')' after __builtin_clz");
@@ -743,22 +817,29 @@ static int try_parse_builtin_call(Parser* p) {
}
if (name == p->sym_a_cas_n) {
- parse_assign_expr(p); to_rvalue(p); /* ptr */
+ parse_assign_expr(p);
+ to_rvalue(p); /* ptr */
expect_punct(p, ',', "',' in __atomic_compare_exchange_n");
- parse_assign_expr(p); to_rvalue(p); /* &expected */
+ parse_assign_expr(p);
+ to_rvalue(p); /* &expected */
const Type* eptr_ty = cg_top_type(p->cg);
if (!eptr_ty || eptr_ty->kind != TY_PTR) {
perr(p, "__atomic_compare_exchange_n: arg 2 must be a pointer");
}
const Type* val_ty = eptr_ty->ptr.pointee;
- FrameSlotDesc fsd; memset(&fsd, 0, sizeof fsd);
- fsd.type = eptr_ty; fsd.size = 8; fsd.align = 8; fsd.kind = FS_LOCAL;
+ FrameSlotDesc fsd;
+ memset(&fsd, 0, sizeof fsd);
+ fsd.type = eptr_ty;
+ fsd.size = 8;
+ fsd.align = 8;
+ fsd.kind = FS_LOCAL;
FrameSlot eslot = cg_local(p->cg, &fsd);
cg_push_local_typed(p->cg, eslot, eptr_ty);
cg_swap(p->cg);
- cg_store(p->cg); cg_drop(p->cg);
+ cg_store(p->cg);
+ cg_drop(p->cg);
cg_push_local_typed(p->cg, eslot, eptr_ty);
cg_load(p->cg);
@@ -766,10 +847,11 @@ static int try_parse_builtin_call(Parser* p) {
cg_load(p->cg);
expect_punct(p, ',', "',' in __atomic_compare_exchange_n");
- parse_assign_expr(p); to_rvalue(p); /* desired */
+ parse_assign_expr(p);
+ to_rvalue(p); /* desired */
expect_punct(p, ',', "',' in __atomic_compare_exchange_n");
- (void)eval_const_int(p, p->cur.loc); /* weak */
+ (void)eval_const_int(p, p->cur.loc); /* weak */
expect_punct(p, ',', "',' in __atomic_compare_exchange_n");
i64 succ = eval_const_int(p, p->cur.loc);
expect_punct(p, ',', "',' in __atomic_compare_exchange_n");
@@ -780,20 +862,29 @@ static int try_parse_builtin_call(Parser* p) {
cg_atomic_cas(p->cg, (MemOrder)succ, (MemOrder)fail);
const Type* ok_ty = cg_top_type(p->cg);
- FrameSlotDesc okd; memset(&okd, 0, sizeof okd);
- okd.type = ok_ty; okd.size = 4; okd.align = 4; okd.kind = FS_LOCAL;
+ FrameSlotDesc okd;
+ memset(&okd, 0, sizeof okd);
+ okd.type = ok_ty;
+ okd.size = 4;
+ okd.align = 4;
+ okd.kind = FS_LOCAL;
FrameSlot okslot = cg_local(p->cg, &okd);
cg_push_local_typed(p->cg, okslot, ok_ty);
- cg_swap(p->cg); cg_store(p->cg); cg_drop(p->cg);
+ cg_swap(p->cg);
+ cg_store(p->cg);
+ cg_drop(p->cg);
- FrameSlotDesc pd; memset(&pd, 0, sizeof pd);
+ FrameSlotDesc pd;
+ memset(&pd, 0, sizeof pd);
pd.type = val_ty;
pd.size = c_abi_sizeof(p->abi, val_ty);
pd.align = c_abi_alignof(p->abi, val_ty);
pd.kind = FS_LOCAL;
FrameSlot pslot = cg_local(p->cg, &pd);
cg_push_local_typed(p->cg, pslot, val_ty);
- cg_swap(p->cg); cg_store(p->cg); cg_drop(p->cg);
+ cg_swap(p->cg);
+ cg_store(p->cg);
+ cg_drop(p->cg);
cg_push_local_typed(p->cg, okslot, ok_ty);
cg_load(p->cg);
@@ -804,7 +895,8 @@ static int try_parse_builtin_call(Parser* p) {
cg_deref(p->cg, val_ty);
cg_push_local_typed(p->cg, pslot, val_ty);
cg_load(p->cg);
- cg_store(p->cg); cg_drop(p->cg);
+ cg_store(p->cg);
+ cg_drop(p->cg);
cg_label_place(p->cg, L_done);
cg_push_local_typed(p->cg, okslot, ok_ty);
@@ -813,13 +905,21 @@ static int try_parse_builtin_call(Parser* p) {
}
AtomicOp op;
- if (name == p->sym_a_exchange_n) op = AO_XCHG;
- else if (name == p->sym_a_fetch_add) op = AO_ADD;
- else if (name == p->sym_a_fetch_sub) op = AO_SUB;
- else if (name == p->sym_a_fetch_and) op = AO_AND;
- else if (name == p->sym_a_fetch_or) op = AO_OR;
- else if (name == p->sym_a_fetch_xor) op = AO_XOR;
- else { perr(p, "internal: unhandled builtin"); }
+ if (name == p->sym_a_exchange_n)
+ op = AO_XCHG;
+ else if (name == p->sym_a_fetch_add)
+ op = AO_ADD;
+ else if (name == p->sym_a_fetch_sub)
+ op = AO_SUB;
+ else if (name == p->sym_a_fetch_and)
+ op = AO_AND;
+ else if (name == p->sym_a_fetch_or)
+ op = AO_OR;
+ else if (name == p->sym_a_fetch_xor)
+ op = AO_XOR;
+ else {
+ perr(p, "internal: unhandled builtin");
+ }
parse_assign_expr(p);
to_rvalue(p);
@@ -883,13 +983,13 @@ static void parse_primary(Parser* p) {
t.v.ident == p->sym_pretty_func_gcc) {
if (p->cur_func_name == 0) {
compiler_panic(p->c, t.loc, "'%s' used outside a function",
- t.v.ident == p->sym_func ? "__func__"
+ t.v.ident == p->sym_func ? "__func__"
: t.v.ident == p->sym_func_gcc ? "__FUNCTION__"
- : "__PRETTY_FUNCTION__");
+ : "__PRETTY_FUNCTION__");
}
size_t nlen = 0;
const char* fn_name = pool_str(p->pool, p->cur_func_name, &nlen);
- Heap* h = p->c->env->heap;
+ Heap* h = cfree_compiler_heap(p->c);
u8* bytes = (u8*)h->alloc(h, nlen + 1u, 1u);
for (size_t i = 0; i < nlen; ++i) bytes[i] = (u8)fn_name[i];
bytes[nlen] = 0;
@@ -938,7 +1038,7 @@ static void parse_primary(Parser* p) {
size_t n = 0;
u8* bytes = decode_string_literal(p, &t, &n);
ObjSymId sym = emit_string_to_rodata(p, bytes, n);
- p->c->env->heap->free(p->c->env->heap, bytes, 0);
+ cfree_compiler_heap(p->c)->free(cfree_compiler_heap(p->c), bytes, 0);
advance(p);
{
const Type* char_ty = type_prim(p->pool, TY_CHAR);
@@ -1050,7 +1150,8 @@ static void parse_postfix(Parser* p) {
const Field* mf = NULL;
advance(p); /* '.' */
if (!lt || (lt->kind != TY_STRUCT && lt->kind != TY_UNION)) {
- perr(p, "request for member in something that is not a struct or union");
+ perr(p,
+ "request for member in something that is not a struct or union");
}
if (p->cur.kind != TOK_IDENT || ident_kw(p, p->cur.v.ident) != KW_NONE) {
perr(p, "expected member name after '.'");
@@ -1058,7 +1159,7 @@ static void parse_postfix(Parser* p) {
mname = p->cur.v.ident;
advance(p);
{
- const ABIRecordLayout* L = c_abi_record_layout(p->abi, lt);
+ const ABIRecordLayout* L = c_abi_record_layout(p->abi, p->pool, lt);
if (!L) perr(p, "no such member");
int found = 0;
for (u16 i = 0; i < lt->rec.nfields; ++i) {
@@ -1071,12 +1172,13 @@ static void parse_postfix(Parser* p) {
break;
}
/* anonymous member flattening */
- if ((f->flags & FIELD_ANON) && (f->type->kind == TY_STRUCT ||
- f->type->kind == TY_UNION)) {
+ if ((f->flags & FIELD_ANON) &&
+ (f->type->kind == TY_STRUCT || f->type->kind == TY_UNION)) {
const Type* inner_ty = NULL;
u32 inner_off = 0;
const Field* inner_f = NULL;
- const ABIRecordLayout* IL = c_abi_record_layout(p->abi, f->type);
+ const ABIRecordLayout* IL =
+ c_abi_record_layout(p->abi, p->pool, f->type);
if (IL) {
for (u16 j = 0; j < f->type->rec.nfields; ++j) {
const Field* ff = &f->type->rec.fields[j];
@@ -1132,7 +1234,7 @@ static void parse_postfix(Parser* p) {
mname = p->cur.v.ident;
advance(p);
{
- const ABIRecordLayout* L = c_abi_record_layout(p->abi, rec_ty);
+ const ABIRecordLayout* L = c_abi_record_layout(p->abi, p->pool, rec_ty);
if (!L) perr(p, "no such member");
int found = 0;
for (u16 i = 0; i < rec_ty->rec.nfields; ++i) {
@@ -1144,9 +1246,10 @@ static void parse_postfix(Parser* p) {
found = 1;
break;
}
- if ((f->flags & FIELD_ANON) && (f->type->kind == TY_STRUCT ||
- f->type->kind == TY_UNION)) {
- const ABIRecordLayout* IL = c_abi_record_layout(p->abi, f->type);
+ if ((f->flags & FIELD_ANON) &&
+ (f->type->kind == TY_STRUCT || f->type->kind == TY_UNION)) {
+ const ABIRecordLayout* IL =
+ c_abi_record_layout(p->abi, p->pool, f->type);
if (IL) {
for (u16 j = 0; j < f->type->rec.nfields; ++j) {
const Field* ff = &f->type->rec.fields[j];
@@ -1346,7 +1449,7 @@ void parse_unary(Parser* p) {
emitted = 1;
} else if (is_default && !default_buf) {
u32 cap = 16;
- Tok* buf = arena_array(p->c->tu, Tok, cap);
+ Tok* buf = arena_array(p->pool->arena, Tok, cap);
u32 len = 0;
int paren_depth = 0, brack_depth = 0, brace_depth = 0;
while (p->cur.kind != TOK_EOF) {
@@ -1355,24 +1458,30 @@ void parse_unary(Parser* p) {
}
if (len == cap) {
u32 new_cap = cap * 2;
- Tok* nv = arena_array(p->c->tu, Tok, new_cap);
+ Tok* nv = arena_array(p->pool->arena, Tok, new_cap);
if (!nv) perr(p, "out of memory recording _Generic default");
memcpy(nv, buf, len * sizeof(Tok));
buf = nv;
cap = new_cap;
}
buf[len++] = p->cur;
- if (is_punct(&p->cur, '(')) ++paren_depth;
- else if (is_punct(&p->cur, ')')) --paren_depth;
- else if (is_punct(&p->cur, '[')) ++brack_depth;
- else if (is_punct(&p->cur, ']')) --brack_depth;
- else if (is_punct(&p->cur, '{')) ++brace_depth;
- else if (is_punct(&p->cur, '}')) --brace_depth;
+ if (is_punct(&p->cur, '('))
+ ++paren_depth;
+ else if (is_punct(&p->cur, ')'))
+ --paren_depth;
+ else if (is_punct(&p->cur, '['))
+ ++brack_depth;
+ else if (is_punct(&p->cur, ']'))
+ --brack_depth;
+ else if (is_punct(&p->cur, '{'))
+ ++brace_depth;
+ else if (is_punct(&p->cur, '}'))
+ --brace_depth;
advance(p);
}
if (len == cap) {
u32 new_cap = cap + 1;
- Tok* nv = arena_array(p->c->tu, Tok, new_cap);
+ Tok* nv = arena_array(p->pool->arena, Tok, new_cap);
if (!nv) perr(p, "out of memory recording _Generic default");
memcpy(nv, buf, len * sizeof(Tok));
buf = nv;
@@ -1392,12 +1501,18 @@ void parse_unary(Parser* p) {
if (paren_depth == 0 && brack_depth == 0 && brace_depth == 0) {
if (is_punct(&p->cur, ',') || is_punct(&p->cur, ')')) break;
}
- if (is_punct(&p->cur, '(')) ++paren_depth;
- else if (is_punct(&p->cur, ')')) --paren_depth;
- else if (is_punct(&p->cur, '[')) ++brack_depth;
- else if (is_punct(&p->cur, ']')) --brack_depth;
- else if (is_punct(&p->cur, '{')) ++brace_depth;
- else if (is_punct(&p->cur, '}')) --brace_depth;
+ if (is_punct(&p->cur, '('))
+ ++paren_depth;
+ else if (is_punct(&p->cur, ')'))
+ --paren_depth;
+ else if (is_punct(&p->cur, '['))
+ ++brack_depth;
+ else if (is_punct(&p->cur, ']'))
+ --brack_depth;
+ else if (is_punct(&p->cur, '{'))
+ ++brace_depth;
+ else if (is_punct(&p->cur, '}'))
+ --brace_depth;
advance(p);
}
}
@@ -1457,8 +1572,8 @@ void parse_unary(Parser* p) {
* ============================================================ */
static int type_is_fp(const Type* t) {
- return t && (t->kind == TY_FLOAT || t->kind == TY_DOUBLE ||
- t->kind == TY_LDOUBLE);
+ return t &&
+ (t->kind == TY_FLOAT || t->kind == TY_DOUBLE || t->kind == TY_LDOUBLE);
}
static const Type* common_fp_type(Parser* p, const Type* a, const Type* b) {
@@ -1479,10 +1594,18 @@ static void emit_fp_binop(Parser* p, BinOp bop, const Type* common) {
cg_swap(p->cg);
BinOp fop;
switch (bop) {
- case BO_IADD: fop = BO_FADD; break;
- case BO_ISUB: fop = BO_FSUB; break;
- case BO_IMUL: fop = BO_FMUL; break;
- case BO_SDIV: fop = BO_FDIV; break;
+ case BO_IADD:
+ fop = BO_FADD;
+ break;
+ case BO_ISUB:
+ fop = BO_FSUB;
+ break;
+ case BO_IMUL:
+ fop = BO_FMUL;
+ break;
+ case BO_SDIV:
+ fop = BO_FDIV;
+ break;
default:
perr(p, "operator does not apply to floating types");
return;
@@ -1826,25 +1949,35 @@ void parse_assign_expr(Parser* p) {
is_simple_assign = 1;
compound = (BinOp)0;
} else if (is_punct(&t, P_ADD_ASSIGN)) {
- is_simple_assign = 0; compound = BO_IADD;
+ is_simple_assign = 0;
+ compound = BO_IADD;
} else if (is_punct(&t, P_SUB_ASSIGN)) {
- is_simple_assign = 0; compound = BO_ISUB;
+ is_simple_assign = 0;
+ compound = BO_ISUB;
} else if (is_punct(&t, P_MUL_ASSIGN)) {
- is_simple_assign = 0; compound = BO_IMUL;
+ is_simple_assign = 0;
+ compound = BO_IMUL;
} else if (is_punct(&t, P_DIV_ASSIGN)) {
- is_simple_assign = 0; compound = BO_SDIV;
+ is_simple_assign = 0;
+ compound = BO_SDIV;
} else if (is_punct(&t, P_MOD_ASSIGN)) {
- is_simple_assign = 0; compound = BO_SREM;
+ is_simple_assign = 0;
+ compound = BO_SREM;
} else if (is_punct(&t, P_AND_ASSIGN)) {
- is_simple_assign = 0; compound = BO_AND;
+ is_simple_assign = 0;
+ compound = BO_AND;
} else if (is_punct(&t, P_OR_ASSIGN)) {
- is_simple_assign = 0; compound = BO_OR;
+ is_simple_assign = 0;
+ compound = BO_OR;
} else if (is_punct(&t, P_XOR_ASSIGN)) {
- is_simple_assign = 0; compound = BO_XOR;
+ is_simple_assign = 0;
+ compound = BO_XOR;
} else if (is_punct(&t, P_SHL_ASSIGN)) {
- is_simple_assign = 0; compound = BO_SHL;
+ is_simple_assign = 0;
+ compound = BO_SHL;
} else if (is_punct(&t, P_SHR_ASSIGN)) {
- is_simple_assign = 0; compound = BO_SHR_S;
+ is_simple_assign = 0;
+ compound = BO_SHR_S;
} else {
return;
}
@@ -1878,6 +2011,4 @@ void parse_expr(Parser* p) {
}
/* parse_cond_expr is the ternary level, provided for completeness */
-void parse_cond_expr(Parser* p) {
- parse_ternary(p);
-}
+void parse_cond_expr(Parser* p) { parse_ternary(p); }
diff --git a/lang/c/parse/parse_init.c b/lang/c/parse/parse_init.c
@@ -47,7 +47,7 @@ static u8* peek_string_bytes(Parser* p, size_t* nlen_out) {
/* Forward declaration for mutual recursion. */
void init_at(Parser* p, FrameSlot slot, const Type* arr_ty, u32 offset,
- const Type* ty);
+ const Type* ty);
static u32 init_elided(Parser* p, FrameSlot slot, const Type* arr_ty,
u32 offset, const Type* ty);
@@ -66,10 +66,10 @@ void push_subobject_lv(Parser* p, FrameSlot slot, const Type* arr_ty,
}
/* Emit a load+store for one scalar leaf. */
-static void emit_copy_leaf(Parser* p, FrameSlot dst_slot, const Type* dst_arr_ty,
- u32 dst_off, FrameSlot src_ptr_slot,
- const Type* src_ptr_ty, u32 src_off,
- const Type* leaf_ty) {
+static void emit_copy_leaf(Parser* p, FrameSlot dst_slot,
+ const Type* dst_arr_ty, u32 dst_off,
+ FrameSlot src_ptr_slot, const Type* src_ptr_ty,
+ u32 src_off, const Type* leaf_ty) {
push_subobject_lv(p, dst_slot, dst_arr_ty, dst_off, leaf_ty);
cg_push_local_typed(p->cg, src_ptr_slot, src_ptr_ty);
cg_load(p->cg);
@@ -91,22 +91,21 @@ static void emit_walk_copy(Parser* p, FrameSlot dst_slot,
FrameSlot src_ptr_slot, const Type* src_ptr_ty,
u32 src_off, const Type* ty) {
if (ty->kind == TY_STRUCT) {
- const ABIRecordLayout* L = c_abi_record_layout(p->abi, ty);
+ const ABIRecordLayout* L = c_abi_record_layout(p->abi, p->pool, ty);
for (u16 i = 0; i < ty->rec.nfields; ++i) {
const Field* f = &ty->rec.fields[i];
if (f->flags & FIELD_BITFIELD) continue;
u32 foff = L->fields[i].offset;
- emit_walk_copy(p, dst_slot, dst_arr_ty, dst_off + foff,
- src_ptr_slot, src_ptr_ty, src_off + foff, f->type);
+ emit_walk_copy(p, dst_slot, dst_arr_ty, dst_off + foff, src_ptr_slot,
+ src_ptr_ty, src_off + foff, f->type);
}
return;
}
if (ty->kind == TY_ARRAY) {
u32 esz = c_abi_sizeof(p->abi, ty->arr.elem);
for (u32 i = 0; i < ty->arr.count; ++i) {
- emit_walk_copy(p, dst_slot, dst_arr_ty, dst_off + i * esz,
- src_ptr_slot, src_ptr_ty, src_off + i * esz,
- ty->arr.elem);
+ emit_walk_copy(p, dst_slot, dst_arr_ty, dst_off + i * esz, src_ptr_slot,
+ src_ptr_ty, src_off + i * esz, ty->arr.elem);
}
return;
}
@@ -114,8 +113,8 @@ static void emit_walk_copy(Parser* p, FrameSlot dst_slot,
u32 sz = c_abi_sizeof(p->abi, ty);
const Type* uchar_ty = type_prim(p->pool, TY_UCHAR);
for (u32 i = 0; i < sz; ++i) {
- emit_copy_leaf(p, dst_slot, dst_arr_ty, dst_off + i,
- src_ptr_slot, src_ptr_ty, src_off + i, uchar_ty);
+ emit_copy_leaf(p, dst_slot, dst_arr_ty, dst_off + i, src_ptr_slot,
+ src_ptr_ty, src_off + i, uchar_ty);
}
return;
}
@@ -158,7 +157,7 @@ static void zero_init_at(Parser* p, FrameSlot slot, const Type* arr_ty,
return;
}
if (ty->kind == TY_STRUCT) {
- const ABIRecordLayout* L = c_abi_record_layout(p->abi, ty);
+ const ABIRecordLayout* L = c_abi_record_layout(p->abi, p->pool, ty);
for (u16 i = 0; i < ty->rec.nfields; ++i) {
const Field* f = &ty->rec.fields[i];
zero_init_at(p, slot, arr_ty, offset + L->fields[i].offset, f->type);
@@ -180,7 +179,8 @@ static void zero_init_at(Parser* p, FrameSlot slot, const Type* arr_ty,
cg_drop(p->cg);
}
-/* Emit byte stores for a string literal initializing a char-array sub-object. */
+/* Emit byte stores for a string literal initializing a char-array sub-object.
+ */
static void init_string_at(Parser* p, FrameSlot slot, const Type* arr_ty,
u32 offset, const Type* elem_ty, u32 count) {
size_t n = 0;
@@ -200,7 +200,7 @@ static void init_string_at(Parser* p, FrameSlot slot, const Type* arr_ty,
cg_store(p->cg);
cg_drop(p->cg);
}
- p->c->env->heap->free(p->c->env->heap, bytes, 0);
+ cfree_compiler_heap(p->c)->free(cfree_compiler_heap(p->c), bytes, 0);
advance(p); /* consume TOK_STR */
}
@@ -237,16 +237,16 @@ static void parse_designator_chain(Parser* p, const Type* outer_ty,
const Field* ff;
u16 fi;
advance(p);
- if (p->cur.kind != TOK_IDENT || ident_kw_init(p, p->cur.v.ident) != KW_NONE) {
+ if (p->cur.kind != TOK_IDENT ||
+ ident_kw_init(p, p->cur.v.ident) != KW_NONE) {
perr(p, "expected field name after '.'");
}
fname = p->cur.v.ident;
advance(p);
- if (!cur_ty ||
- (cur_ty->kind != TY_STRUCT && cur_ty->kind != TY_UNION)) {
+ if (!cur_ty || (cur_ty->kind != TY_STRUCT && cur_ty->kind != TY_UNION)) {
perr(p, "field designator on non-record type");
}
- if (!find_field(p->abi, cur_ty, fname, &fty, &foff, &ff)) {
+ if (!find_field(p->abi, p->pool, cur_ty, fname, &fty, &foff, &ff)) {
perr(p, "no such field in designator");
}
cur_off += foff;
@@ -262,7 +262,7 @@ static void parse_designator_chain(Parser* p, const Type* outer_ty,
const Type* tmp_ty;
u32 tmp_off;
const Field* tmp_f;
- if (find_field(p->abi, g->type, fname, &tmp_ty, &tmp_off,
+ if (find_field(p->abi, p->pool, g->type, fname, &tmp_ty, &tmp_off,
&tmp_f)) {
*top_index_out = fi;
break;
@@ -285,7 +285,7 @@ static void parse_designator_chain(Parser* p, const Type* outer_ty,
static u32 init_struct_fields(Parser* p, FrameSlot slot, const Type* arr_ty,
u32 offset, const Type* ty, u32 start_field,
int braced) {
- const ABIRecordLayout* L = c_abi_record_layout(p->abi, ty);
+ const ABIRecordLayout* L = c_abi_record_layout(p->abi, p->pool, ty);
u32 i = start_field;
u32 zero_lo = start_field;
for (; i < ty->rec.nfields; ++i) {
@@ -314,7 +314,7 @@ static u32 init_struct_fields(Parser* p, FrameSlot slot, const Type* arr_ty,
++i;
break;
}
- next_item_struct:
+ next_item_struct:
if (!accept_punct(p, ',')) {
++i;
break;
@@ -393,8 +393,7 @@ void init_at(Parser* p, FrameSlot slot, const Type* arr_ty, u32 offset,
const Type* sub_ty;
u32 sub_off;
u32 top_idx = 0;
- parse_designator_chain(p, ty, offset, &sub_ty, &sub_off,
- &top_idx);
+ parse_designator_chain(p, ty, offset, &sub_ty, &sub_off, &top_idx);
while (zero_lo < top_idx) {
zero_init_at(p, slot, arr_ty, offset + zero_lo * esz, elem_ty);
++zero_lo;
@@ -489,9 +488,10 @@ static void parse_static_string_at(Parser* p, u8* buf, u32 buflen, u32 offset,
u8* bytes = peek_string_bytes(p, &n);
size_t copy = n;
if (copy > count) copy = count;
- if (offset + (u32)copy > buflen) perr(p, "string initializer overflows object");
+ if (offset + (u32)copy > buflen)
+ perr(p, "string initializer overflows object");
memcpy(buf + offset, bytes, copy);
- p->c->env->heap->free(p->c->env->heap, bytes, 0);
+ cfree_compiler_heap(p->c)->free(cfree_compiler_heap(p->c), bytes, 0);
advance(p);
}
@@ -499,8 +499,8 @@ static void parse_static_string_at(Parser* p, u8* buf, u32 buflen, u32 offset,
void srl_push(Parser* p, u32 offset, u32 size, ObjSymId target, i64 addend) {
if (p->static_relocs_len == p->static_relocs_cap) {
u32 nc = p->static_relocs_cap ? p->static_relocs_cap * 2u : 4u;
- void* nb = arena_array(p->c->tu, char,
- nc * sizeof(*p->static_relocs));
+ void* nb =
+ arena_array(p->pool->arena, char, nc * sizeof(*p->static_relocs));
if (!nb) perr(p, "out of memory recording static relocs");
if (p->static_relocs && p->static_relocs_len) {
memcpy(nb, p->static_relocs,
@@ -517,8 +517,8 @@ void srl_push(Parser* p, u32 offset, u32 size, ObjSymId target, i64 addend) {
}
/* Try to parse the current expression as an address constant. */
-static int try_parse_addr_const(Parser* p, const Type* ty, u8* buf,
- u32 offset, u32 sz) {
+static int try_parse_addr_const(Parser* p, const Type* ty, u8* buf, u32 offset,
+ u32 sz) {
Tok t = p->cur;
Sym name = 0;
SrcLoc nloc = tok_loc_init(&p->cur);
@@ -532,7 +532,7 @@ static int try_parse_addr_const(Parser* p, const Type* ty, u8* buf,
size_t n = 0;
u8* bytes = decode_string_literal(p, &t, &n);
ObjSymId str_sym = emit_string_to_rodata(p, bytes, n);
- p->c->env->heap->free(p->c->env->heap, bytes, 0);
+ cfree_compiler_heap(p->c)->free(cfree_compiler_heap(p->c), bytes, 0);
advance(p);
(void)ty;
(void)buf;
@@ -542,7 +542,8 @@ static int try_parse_addr_const(Parser* p, const Type* ty, u8* buf,
if (is_punct(&t, '&')) {
saw_amp = 1;
advance(p);
- if (p->cur.kind != TOK_IDENT || ident_kw_init(p, p->cur.v.ident) != KW_NONE) {
+ if (p->cur.kind != TOK_IDENT ||
+ ident_kw_init(p, p->cur.v.ident) != KW_NONE) {
perr(p, "expected identifier after '&' in static initializer");
}
name = p->cur.v.ident;
@@ -647,7 +648,7 @@ void parse_static_init_at(Parser* p, u8* buf, u32 buflen, u32 offset,
}
if (ty->kind == TY_STRUCT) {
int had_brace = accept_punct(p, '{');
- const ABIRecordLayout* L = c_abi_record_layout(p->abi, ty);
+ const ABIRecordLayout* L = c_abi_record_layout(p->abi, p->pool, ty);
u32 i = 0;
if (!had_brace) {
perr(p, "expected '{' for static-storage struct initializer");
@@ -747,12 +748,15 @@ void define_static_object(Parser* p, ObjSymId sym, ObjSecId section_id,
int has_nonzero = 0;
if (has_init) {
- buf = (u8*)arena_array(p->c->tu, u8, size ? size : 1u);
+ buf = (u8*)arena_array(p->pool->arena, u8, size ? size : 1u);
memset(buf, 0, size);
p->static_relocs_len = 0;
parse_static_init_at(p, buf, size, 0, var_ty);
for (u32 i = 0; i < size; ++i) {
- if (buf[i]) { has_nonzero = 1; break; }
+ if (buf[i]) {
+ has_nonzero = 1;
+ break;
+ }
}
if (p->static_relocs_len) has_nonzero = 1;
}
diff --git a/lang/c/parse/parse_priv.h b/lang/c/parse/parse_priv.h
@@ -6,20 +6,15 @@
#pragma once
-#include "parse/parse.h"
-
#include <stdarg.h>
#include <string.h>
#include "abi/c_abi.h"
-#include "core/arena.h"
-#include "core/core.h"
-#include "core/heap.h"
-#include "core/pool.h"
#include "decl/decl.h"
#include "decl/decl_attrs.h"
#include "lex/lex.h"
#include "parse/attr.h"
+#include "parse/parse.h"
#include "pp/pp.h"
#include "type/type.h"
@@ -62,16 +57,16 @@ typedef enum CKw {
KW_VOID,
KW_VOLATILE,
KW_WHILE,
- KW_BOOL, /* _Bool */
- KW_COMPLEX, /* _Complex */
- KW_IMAGINARY, /* _Imaginary */
- KW_ALIGNAS, /* _Alignas */
- KW_ALIGNOF, /* _Alignof */
- KW_ATOMIC, /* _Atomic */
- KW_GENERIC, /* _Generic */
- KW_NORETURN, /* _Noreturn */
+ KW_BOOL, /* _Bool */
+ KW_COMPLEX, /* _Complex */
+ KW_IMAGINARY, /* _Imaginary */
+ KW_ALIGNAS, /* _Alignas */
+ KW_ALIGNOF, /* _Alignof */
+ KW_ATOMIC, /* _Atomic */
+ KW_GENERIC, /* _Generic */
+ KW_NORETURN, /* _Noreturn */
KW_STATIC_ASSERT, /* _Static_assert */
- KW_THREAD_LOCAL, /* _Thread_local */
+ KW_THREAD_LOCAL, /* _Thread_local */
KW_ASM, /* GNU `asm` */
KW_BUILTIN_ASM, /* GNU `__asm__` */
KW_COUNT
@@ -189,11 +184,11 @@ typedef struct Parser {
Sym sym_b_memmove;
Sym sym_b_memcmp;
Sym sym_b_memset;
- Sym sym_func; /* __func__ */
- Sym sym_func_gcc; /* __FUNCTION__ */
- Sym sym_pretty_func_gcc; /* __PRETTY_FUNCTION__ */
- Sym cur_func_name; /* name of the function whose body we're in,
- * 0 at file scope */
+ Sym sym_func; /* __func__ */
+ Sym sym_func_gcc; /* __FUNCTION__ */
+ Sym sym_pretty_func_gcc; /* __PRETTY_FUNCTION__ */
+ Sym cur_func_name; /* name of the function whose body we're in,
+ * 0 at file scope */
Sym sym_b_expect;
Sym sym_b_offsetof;
Sym sym_b_va_list;
@@ -204,9 +199,9 @@ typedef struct Parser {
Sym sym_attribute;
Sym sym_volatile_alias;
Sym sym_alignof_alias;
- Sym sym_int128; /* __int128 */
- Sym sym_int128_t; /* __int128_t */
- Sym sym_uint128_t; /* __uint128_t */
+ Sym sym_int128; /* __int128 */
+ Sym sym_int128_t; /* __int128_t */
+ Sym sym_uint128_t; /* __uint128_t */
Sym sym_a_load_n;
Sym sym_a_store_n;
Sym sym_a_exchange_n;
@@ -250,7 +245,7 @@ typedef struct Parser {
u32 size;
ObjSymId target;
i64 addend;
- } *static_relocs;
+ }* static_relocs;
u32 static_relocs_len;
u32 static_relocs_cap;
} Parser;
@@ -280,7 +275,7 @@ typedef struct TypeSpecAccum {
u8 saw_bool;
u8 saw_float;
u8 saw_double;
- u8 saw_int128; /* __int128 / __int128_t / __uint128_t */
+ u8 saw_int128; /* __int128 / __int128_t / __uint128_t */
u8 saw_explicit_type;
} TypeSpecAccum;
@@ -301,9 +296,11 @@ int accept_punct(Parser* p, u32 punct);
Scope* scope_new(Parser* p, Scope* parent);
void scope_push(Parser* p);
void scope_pop(Parser* p);
-SymEntry* scope_define(Parser* p, Sym name, SymEntryKind kind, const Type* type);
+SymEntry* scope_define(Parser* p, Sym name, SymEntryKind kind,
+ const Type* type);
SymEntry* scope_lookup(Parser* p, Sym name);
-TagEntry* tag_define(Parser* p, Sym name, TagDeclKind kind, Type* type, int complete);
+TagEntry* tag_define(Parser* p, Sym name, TagDeclKind kind, Type* type,
+ int complete);
TagEntry* tag_lookup(Parser* p, Sym name);
TagEntry* tag_lookup_local(Parser* p, Sym name);
@@ -367,22 +364,26 @@ typedef struct DeclSuffix {
/* parse_type.c */
int parse_decl_specs(Parser* p, DeclSpecs* out);
-const Type* parse_struct_or_union(Parser* p, TypeKind kind, Attr** anon_attrs_out);
+const Type* parse_struct_or_union(Parser* p, TypeKind kind,
+ Attr** anon_attrs_out);
const Type* parse_enum(Parser* p, Attr** anon_attrs_out);
const Type* resolve_type_specs(Parser* p, const TypeSpecAccum* a, SrcLoc loc);
const Type* parse_type_name(Parser* p);
const Type* parse_pointer_layer(Parser* p, const Type* base);
-const Type* parse_declarator_full(Parser* p, const Type* base, int allow_abstract,
- Sym* name_out, SrcLoc* loc_out);
-const Type* parse_declarator_full_ex(Parser* p, const Type* base, int allow_abstract,
- Sym* name_out, SrcLoc* loc_out, Attr** attrs_out);
-const Type* parse_declarator(Parser* p, const Type* base, Sym* name_out, SrcLoc* loc_out);
+const Type* parse_declarator_full(Parser* p, const Type* base,
+ int allow_abstract, Sym* name_out,
+ SrcLoc* loc_out);
+const Type* parse_declarator_full_ex(Parser* p, const Type* base,
+ int allow_abstract, Sym* name_out,
+ SrcLoc* loc_out, Attr** attrs_out);
+const Type* parse_declarator(Parser* p, const Type* base, Sym* name_out,
+ SrcLoc* loc_out);
const Type* complete_incomplete_array(Parser* p, const Type* ty);
int starts_type_name(const Parser* p, const Tok* t);
int starts_attr(const Parser* p);
Attr* parse_attribute_spec_list(Parser* p);
void parse_and_discard_attributes(Parser* p);
-int find_field(TargetABI* abi, const Type* rec, Sym name,
+int find_field(TargetABI* abi, Pool* pool, const Type* rec, Sym name,
const Type** out_type, u32* out_offset, const Field** out_field);
u32 attrs_pick_aligned(const Attr* a);
void attr_list_append(Attr** head, Attr* add);
@@ -404,8 +405,10 @@ void coerce_top_to_lvalue(Parser* p);
CfreeCgSym emit_string_to_rodata(Parser* p, const u8* bytes, size_t n);
/* parse_init.c */
-void init_at(Parser* p, FrameSlot slot, const Type* arr_ty, u32 offset, const Type* ty);
-void parse_static_init_at(Parser* p, u8* buf, u32 buflen, u32 offset, const Type* ty);
+void init_at(Parser* p, FrameSlot slot, const Type* arr_ty, u32 offset,
+ const Type* ty);
+void parse_static_init_at(Parser* p, u8* buf, u32 buflen, u32 offset,
+ const Type* ty);
void define_static_object(Parser* p, ObjSymId sym, ObjSecId section_id,
const Type* var_ty, u16 quals, int has_init,
SrcLoc loc, u32 align_override);
@@ -429,7 +432,7 @@ void parse_param_list(Parser* p, ParamInfo** infos_out, u16* nparams_out,
void parse_local_decl(Parser* p, const DeclSpecs* specs);
FrameSlot make_local(Parser* p, Sym name, const Type* type, SrcLoc loc);
FrameSlot make_local_aligned(Parser* p, Sym name, const Type* type, SrcLoc loc,
- u32 align_override);
+ u32 align_override);
Sym mint_static_local_sym(Parser* p, Sym orig);
void record_braced_block(Parser* p);
void replay_rewind(Parser* p);
diff --git a/lang/c/parse/parse_stmt.c b/lang/c/parse/parse_stmt.c
@@ -172,7 +172,7 @@ static GotoLabel* label_get_or_create(Parser* p, Sym name, SrcLoc loc) {
for (gl = p->goto_labels; gl; gl = gl->next) {
if (gl->name == name) return gl;
}
- gl = arena_new(p->c->tu, GotoLabel);
+ gl = arena_new(p->pool->arena, GotoLabel);
if (!gl) perr(p, "out of memory in label_get_or_create");
memset(gl, 0, sizeof *gl);
gl->name = name;
@@ -222,7 +222,7 @@ static void parse_case_stmt(Parser* p) {
expect_punct(p, ':', "':' after case constant");
L = cg_label_new(p->cg);
cg_label_place(p->cg, L);
- ce = arena_new(p->c->tu, CaseEntry);
+ ce = arena_new(p->pool->arena, CaseEntry);
if (!ce) perr(p, "out of memory in parse_case_stmt");
ce->value = v;
ce->label = L;
@@ -328,8 +328,8 @@ void parse_static_assert(Parser* p) {
if (!v) {
size_t mlen = 0;
const char* mstr = pool_str(p->pool, msg.spelling, &mlen);
- compiler_panic(p->c, loc, "static assertion failed: %.*s",
- (int)mlen, mstr ? mstr : "");
+ compiler_panic(p->c, loc, "static assertion failed: %.*s", (int)mlen,
+ mstr ? mstr : "");
}
}
}
@@ -368,7 +368,7 @@ static const char* parse_asm_str(Parser* p, const char* what) {
bytes = decode_string_literal(p, &t, &nlen);
if (nlen > 0) nlen -= 1;
s = pool_intern(p->pool, (const char*)bytes, nlen);
- p->c->env->heap->free(p->c->env->heap, bytes, 0);
+ cfree_compiler_heap(p->c)->free(cfree_compiler_heap(p->c), bytes, 0);
return pool_str(p->pool, s, NULL);
}
@@ -399,8 +399,10 @@ static void parse_asm_stmt(Parser* p) {
if (accept_punct(p, ':')) {
if (!is_punct(&p->cur, ':') && !is_punct(&p->cur, ')')) {
cap_out = 4;
- outs = (AsmConstraint*)arena_array(p->c->tu, AsmConstraint, cap_out);
- out_lvs = (AsmOutLValue*)arena_array(p->c->tu, AsmOutLValue, cap_out);
+ outs =
+ (AsmConstraint*)arena_array(p->pool->arena, AsmConstraint, cap_out);
+ out_lvs =
+ (AsmOutLValue*)arena_array(p->pool->arena, AsmOutLValue, cap_out);
for (;;) {
AsmConstraint c;
AsmOutLValue lv;
@@ -412,8 +414,10 @@ static void parse_asm_stmt(Parser* p) {
memset(&lv, 0, sizeof lv);
c.name = parse_asm_operand_name(p);
c.str = parse_asm_str(p, "asm output constraint");
- if (c.str && c.str[0] == '+') c.dir = ASM_INOUT;
- else c.dir = ASM_OUT;
+ if (c.str && c.str[0] == '+')
+ c.dir = ASM_INOUT;
+ else
+ c.dir = ASM_OUT;
expect_punct(p, '(', "'(' before asm output lvalue");
parse_assign_expr(p);
val_ty = cg_top_type(p->cg);
@@ -439,9 +443,9 @@ static void parse_asm_stmt(Parser* p) {
if (nout == cap_out) {
u32 nc = cap_out * 2;
AsmConstraint* nb =
- (AsmConstraint*)arena_array(p->c->tu, AsmConstraint, nc);
+ (AsmConstraint*)arena_array(p->pool->arena, AsmConstraint, nc);
AsmOutLValue* nlv =
- (AsmOutLValue*)arena_array(p->c->tu, AsmOutLValue, nc);
+ (AsmOutLValue*)arena_array(p->pool->arena, AsmOutLValue, nc);
memcpy(nb, outs, sizeof(AsmConstraint) * nout);
memcpy(nlv, out_lvs, sizeof(AsmOutLValue) * nout);
outs = nb;
@@ -458,7 +462,8 @@ static void parse_asm_stmt(Parser* p) {
if (accept_punct(p, ':')) {
if (!is_punct(&p->cur, ':') && !is_punct(&p->cur, ')')) {
cap_in = 4;
- ins = (AsmConstraint*)arena_array(p->c->tu, AsmConstraint, cap_in);
+ ins =
+ (AsmConstraint*)arena_array(p->pool->arena, AsmConstraint, cap_in);
for (;;) {
AsmConstraint c;
memset(&c, 0, sizeof c);
@@ -473,7 +478,7 @@ static void parse_asm_stmt(Parser* p) {
if (nin == cap_in) {
u32 nc = cap_in * 2;
AsmConstraint* nb =
- (AsmConstraint*)arena_array(p->c->tu, AsmConstraint, nc);
+ (AsmConstraint*)arena_array(p->pool->arena, AsmConstraint, nc);
memcpy(nb, ins, sizeof(AsmConstraint) * nin);
ins = nb;
cap_in = nc;
@@ -486,7 +491,7 @@ static void parse_asm_stmt(Parser* p) {
if (accept_punct(p, ':')) {
if (!is_punct(&p->cur, ':') && !is_punct(&p->cur, ')')) {
cap_clob = 4;
- clobbers = (Sym*)arena_array(p->c->tu, Sym, cap_clob);
+ clobbers = (Sym*)arena_array(p->pool->arena, Sym, cap_clob);
for (;;) {
const char* cstr;
Sym cs;
@@ -494,7 +499,7 @@ static void parse_asm_stmt(Parser* p) {
cs = pool_intern_cstr(p->pool, cstr);
if (nclob == cap_clob) {
u32 nc = cap_clob * 2;
- Sym* nb = (Sym*)arena_array(p->c->tu, Sym, nc);
+ Sym* nb = (Sym*)arena_array(p->pool->arena, Sym, nc);
memcpy(nb, clobbers, sizeof(Sym) * nclob);
clobbers = nb;
cap_clob = nc;
@@ -529,14 +534,14 @@ static void parse_asm_stmt(Parser* p) {
if (outs[i].dir == ASM_INOUT) ninout++;
}
if (ninout > 0) {
- static const char* const k_match_strs[10] = {
- "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"};
+ static const char* const k_match_strs[10] = {"0", "1", "2", "3", "4",
+ "5", "6", "7", "8", "9"};
u32 need = nin + ninout;
if (need > cap_in) {
u32 nc = cap_in ? cap_in : 4;
while (nc < need) nc *= 2;
AsmConstraint* nb =
- (AsmConstraint*)arena_array(p->c->tu, AsmConstraint, nc);
+ (AsmConstraint*)arena_array(p->pool->arena, AsmConstraint, nc);
if (nin) memcpy(nb, ins, sizeof(AsmConstraint) * nin);
ins = nb;
cap_in = nc;
@@ -544,8 +549,9 @@ static void parse_asm_stmt(Parser* p) {
for (u32 i = 0; i < nout; ++i) {
if (outs[i].dir != ASM_INOUT) continue;
if (i >= 10) {
- perr(p, "asm: '+r' constraint at output index >9 exceeds "
- "matching-digit syntax");
+ perr(p,
+ "asm: '+r' constraint at output index >9 exceeds "
+ "matching-digit syntax");
}
AsmOutLValue* lv = &out_lvs[i];
cg_push_local_typed(p->cg, lv->addr_slot, lv->ptr_ty);
diff --git a/lang/c/parse/parse_type.c b/lang/c/parse/parse_type.c
@@ -21,40 +21,40 @@ static const struct {
AttrKind kind;
AttrArgShape shape;
} kAttrTable[] = {
- {"packed", ATTR_PACKED, AS_NONE},
- {"aligned", ATTR_ALIGNED, AS_INT_OPT},
- {"section", ATTR_SECTION, AS_STRING},
- {"used", ATTR_USED, AS_NONE},
- {"noreturn", ATTR_NORETURN, AS_NONE},
- {"alias", ATTR_ALIAS, AS_STRING},
- {"weak", ATTR_WEAK, AS_NONE},
- {"visibility", ATTR_VISIBILITY, AS_STRING},
- {"always_inline", ATTR_ALWAYS_INLINE, AS_NONE},
- {"noinline", ATTR_NOINLINE, AS_NONE},
- {"unused", ATTR_UNUSED, AS_NONE},
- {"deprecated", ATTR_DEPRECATED, AS_OPAQUE},
- {"warn_unused_result", ATTR_WARN_UNUSED_RESULT, AS_NONE},
- {"format", ATTR_FORMAT, AS_FORMAT},
- {"nonnull", ATTR_NONNULL, AS_OPAQUE},
- {"returns_nonnull", ATTR_RETURNS_NONNULL, AS_NONE},
- {"pure", ATTR_PURE, AS_NONE},
- {"const", ATTR_CONST, AS_NONE},
- {"malloc", ATTR_MALLOC, AS_OPAQUE},
- {"nothrow", ATTR_NOTHROW, AS_NONE},
- {"leaf", ATTR_LEAF, AS_NONE},
- {"cold", ATTR_COLD, AS_NONE},
- {"hot", ATTR_HOT, AS_NONE},
- {"constructor", ATTR_CONSTRUCTOR, AS_INT_OPT},
- {"destructor", ATTR_DESTRUCTOR, AS_INT_OPT},
- {"cleanup", ATTR_CLEANUP, AS_IDENT},
- {"mode", ATTR_MODE, AS_IDENT},
- {"vector_size", ATTR_VECTOR_SIZE, AS_INT},
- {"transparent_union", ATTR_TRANSPARENT_UNION, AS_NONE},
- {"gnu_inline", ATTR_GNU_INLINE, AS_NONE},
- {"fallthrough", ATTR_FALLTHROUGH, AS_NONE},
- {"sentinel", ATTR_SENTINEL, AS_OPAQUE},
- {"no_instrument_function", ATTR_NO_INSTRUMENT_FUNCTION, AS_NONE},
- {"no_sanitize", ATTR_NO_SANITIZE, AS_OPAQUE},
+ {"packed", ATTR_PACKED, AS_NONE},
+ {"aligned", ATTR_ALIGNED, AS_INT_OPT},
+ {"section", ATTR_SECTION, AS_STRING},
+ {"used", ATTR_USED, AS_NONE},
+ {"noreturn", ATTR_NORETURN, AS_NONE},
+ {"alias", ATTR_ALIAS, AS_STRING},
+ {"weak", ATTR_WEAK, AS_NONE},
+ {"visibility", ATTR_VISIBILITY, AS_STRING},
+ {"always_inline", ATTR_ALWAYS_INLINE, AS_NONE},
+ {"noinline", ATTR_NOINLINE, AS_NONE},
+ {"unused", ATTR_UNUSED, AS_NONE},
+ {"deprecated", ATTR_DEPRECATED, AS_OPAQUE},
+ {"warn_unused_result", ATTR_WARN_UNUSED_RESULT, AS_NONE},
+ {"format", ATTR_FORMAT, AS_FORMAT},
+ {"nonnull", ATTR_NONNULL, AS_OPAQUE},
+ {"returns_nonnull", ATTR_RETURNS_NONNULL, AS_NONE},
+ {"pure", ATTR_PURE, AS_NONE},
+ {"const", ATTR_CONST, AS_NONE},
+ {"malloc", ATTR_MALLOC, AS_OPAQUE},
+ {"nothrow", ATTR_NOTHROW, AS_NONE},
+ {"leaf", ATTR_LEAF, AS_NONE},
+ {"cold", ATTR_COLD, AS_NONE},
+ {"hot", ATTR_HOT, AS_NONE},
+ {"constructor", ATTR_CONSTRUCTOR, AS_INT_OPT},
+ {"destructor", ATTR_DESTRUCTOR, AS_INT_OPT},
+ {"cleanup", ATTR_CLEANUP, AS_IDENT},
+ {"mode", ATTR_MODE, AS_IDENT},
+ {"vector_size", ATTR_VECTOR_SIZE, AS_INT},
+ {"transparent_union", ATTR_TRANSPARENT_UNION, AS_NONE},
+ {"gnu_inline", ATTR_GNU_INLINE, AS_NONE},
+ {"fallthrough", ATTR_FALLTHROUGH, AS_NONE},
+ {"sentinel", ATTR_SENTINEL, AS_OPAQUE},
+ {"no_instrument_function", ATTR_NO_INSTRUMENT_FUNCTION, AS_NONE},
+ {"no_sanitize", ATTR_NO_SANITIZE, AS_OPAQUE},
};
static SrcLoc tok_loc(const Tok* t) { return t->loc; }
@@ -75,10 +75,10 @@ int starts_attr(const Parser* p) {
return p->cur.kind == TOK_IDENT && p->cur.v.ident == p->sym_attribute;
}
-static void attr_canon_range(const char* s, size_t len,
- const char** out_p, size_t* out_len) {
- if (len >= 4 && s[0] == '_' && s[1] == '_' &&
- s[len - 1] == '_' && s[len - 2] == '_') {
+static void attr_canon_range(const char* s, size_t len, const char** out_p,
+ size_t* out_len) {
+ if (len >= 4 && s[0] == '_' && s[1] == '_' && s[len - 1] == '_' &&
+ s[len - 2] == '_') {
*out_p = s + 2;
*out_len = len - 4;
return;
@@ -119,10 +119,14 @@ static void skip_balanced_parens(Parser* p) {
if (p->cur.kind == TOK_EOF) {
perr(p, "unexpected EOF inside attribute arguments");
}
- if (is_punct(&p->cur, '(')) ++depth;
+ if (is_punct(&p->cur, '('))
+ ++depth;
else if (is_punct(&p->cur, ')')) {
--depth;
- if (depth == 0) { advance(p); return; }
+ if (depth == 0) {
+ advance(p);
+ return;
+ }
}
advance(p);
}
@@ -155,8 +159,7 @@ static void parse_attr_args(Parser* p, Attr* a, AttrArgShape shape,
advance(p); /* '(' */
if (is_punct(&p->cur, ')')) {
if (shape == AS_INT) {
- perr(p, "attribute '%s' expects an integer argument",
- attr_diag_name);
+ perr(p, "attribute '%s' expects an integer argument", attr_diag_name);
}
advance(p);
return;
@@ -177,8 +180,8 @@ static void parse_attr_args(Parser* p, Attr* a, AttrArgShape shape,
size_t nlen = 0;
u8* bytes = decode_string_literal(p, &t, &nlen);
u32 ilen = (nlen > 0) ? (u32)(nlen - 1) : 0;
- a->v.sym = pool_intern(p->c->global, (const char*)bytes, ilen);
- p->c->env->heap->free(p->c->env->heap, bytes, 0);
+ a->v.sym = pool_intern(p->pool, (const char*)bytes, ilen);
+ cfree_compiler_heap(p->c)->free(cfree_compiler_heap(p->c), bytes, 0);
}
a->nargs = 1;
advance(p);
@@ -243,13 +246,14 @@ Attr* parse_attribute_spec_list(Parser* p) {
size_t diag_len;
const char* canon;
size_t canon_len;
- while (accept_punct(p, ',')) { /* skip */ }
+ while (accept_punct(p, ',')) { /* skip */
+ }
if (is_punct(&p->cur, ')')) break;
if (p->cur.kind != TOK_IDENT) {
perr(p, "expected attribute name");
}
aname = p->cur.v.ident;
- a = arena_new(p->c->tu, Attr);
+ a = arena_new(p->pool->arena, Attr);
if (!a) perr(p, "out of memory in parse_attribute_spec_list");
memset(a, 0, sizeof *a);
a->loc = tok_loc(&p->cur);
@@ -258,9 +262,13 @@ Attr* parse_attribute_spec_list(Parser* p) {
advance(p);
diag_name = pool_str(p->pool, aname, &diag_len);
attr_canon_range(diag_name, diag_len, &canon, &canon_len);
- (void)canon; (void)canon_len;
+ (void)canon;
+ (void)canon_len;
parse_attr_args(p, a, shape, diag_name ? diag_name : "<unknown>");
- if (tail) tail->next = a; else head = a;
+ if (tail)
+ tail->next = a;
+ else
+ head = a;
tail = a;
if (!accept_punct(p, ',')) break;
}
@@ -278,7 +286,10 @@ void parse_and_discard_attributes(Parser* p) {
/* Append `add` to the end of `*head` (linked via Attr.next). */
void attr_list_append(Attr** head, Attr* add) {
if (!add) return;
- if (!*head) { *head = add; return; }
+ if (!*head) {
+ *head = add;
+ return;
+ }
Attr* tail = *head;
while (tail->next) tail = tail->next;
tail->next = add;
@@ -424,43 +435,92 @@ int parse_decl_specs(Parser* p, DeclSpecs* out) {
continue;
}
if (is_kw(p, &t, KW_VOID)) {
- acc.saw_void = 1; acc.saw_explicit_type = 1; advance(p); seen = 1;
+ acc.saw_void = 1;
+ acc.saw_explicit_type = 1;
+ advance(p);
+ seen = 1;
} else if (is_kw(p, &t, KW_CHAR)) {
- acc.saw_char = 1; acc.saw_explicit_type = 1; advance(p); seen = 1;
+ acc.saw_char = 1;
+ acc.saw_explicit_type = 1;
+ advance(p);
+ seen = 1;
} else if (is_kw(p, &t, KW_INT)) {
- acc.saw_int = 1; acc.saw_explicit_type = 1; advance(p); seen = 1;
+ acc.saw_int = 1;
+ acc.saw_explicit_type = 1;
+ advance(p);
+ seen = 1;
} else if (is_kw(p, &t, KW_SHORT)) {
- acc.saw_short = 1; acc.saw_explicit_type = 1; advance(p); seen = 1;
+ acc.saw_short = 1;
+ acc.saw_explicit_type = 1;
+ advance(p);
+ seen = 1;
} else if (is_kw(p, &t, KW_LONG)) {
- acc.long_count++; acc.saw_explicit_type = 1; advance(p); seen = 1;
+ acc.long_count++;
+ acc.saw_explicit_type = 1;
+ advance(p);
+ seen = 1;
} else if (is_kw(p, &t, KW_SIGNED)) {
- acc.saw_signed = 1; acc.saw_explicit_type = 1; advance(p); seen = 1;
+ acc.saw_signed = 1;
+ acc.saw_explicit_type = 1;
+ advance(p);
+ seen = 1;
} else if (is_kw(p, &t, KW_UNSIGNED)) {
- acc.saw_unsigned = 1; acc.saw_explicit_type = 1; advance(p); seen = 1;
+ acc.saw_unsigned = 1;
+ acc.saw_explicit_type = 1;
+ advance(p);
+ seen = 1;
} else if (is_kw(p, &t, KW_BOOL)) {
- acc.saw_bool = 1; acc.saw_explicit_type = 1; advance(p); seen = 1;
+ acc.saw_bool = 1;
+ acc.saw_explicit_type = 1;
+ advance(p);
+ seen = 1;
} else if (is_kw(p, &t, KW_FLOAT)) {
- acc.saw_float = 1; acc.saw_explicit_type = 1; advance(p); seen = 1;
+ acc.saw_float = 1;
+ acc.saw_explicit_type = 1;
+ advance(p);
+ seen = 1;
} else if (is_kw(p, &t, KW_DOUBLE)) {
- acc.saw_double = 1; acc.saw_explicit_type = 1; advance(p); seen = 1;
+ acc.saw_double = 1;
+ acc.saw_explicit_type = 1;
+ advance(p);
+ seen = 1;
} else if (t.kind == TOK_IDENT && t.v.ident == p->sym_int128) {
- acc.saw_int128 = 1; acc.saw_explicit_type = 1; advance(p); seen = 1;
+ acc.saw_int128 = 1;
+ acc.saw_explicit_type = 1;
+ advance(p);
+ seen = 1;
} else if (t.kind == TOK_IDENT && t.v.ident == p->sym_int128_t) {
- acc.saw_int128 = 1; acc.saw_signed = 1; acc.saw_explicit_type = 1;
- advance(p); seen = 1;
+ acc.saw_int128 = 1;
+ acc.saw_signed = 1;
+ acc.saw_explicit_type = 1;
+ advance(p);
+ seen = 1;
} else if (t.kind == TOK_IDENT && t.v.ident == p->sym_uint128_t) {
- acc.saw_int128 = 1; acc.saw_unsigned = 1; acc.saw_explicit_type = 1;
- advance(p); seen = 1;
+ acc.saw_int128 = 1;
+ acc.saw_unsigned = 1;
+ acc.saw_explicit_type = 1;
+ advance(p);
+ seen = 1;
} else if (is_kw(p, &t, KW_STATIC)) {
- out->storage = DS_STATIC; advance(p); seen = 1;
+ out->storage = DS_STATIC;
+ advance(p);
+ seen = 1;
} else if (is_kw(p, &t, KW_EXTERN)) {
- out->storage = DS_EXTERN; advance(p); seen = 1;
+ out->storage = DS_EXTERN;
+ advance(p);
+ seen = 1;
} else if (is_kw(p, &t, KW_CONST)) {
- out->quals |= Q_CONST; advance(p); seen = 1;
+ out->quals |= Q_CONST;
+ advance(p);
+ seen = 1;
} else if (is_kw(p, &t, KW_VOLATILE)) {
- out->quals |= Q_VOLATILE; advance(p); seen = 1;
+ out->quals |= Q_VOLATILE;
+ advance(p);
+ seen = 1;
} else if (is_kw(p, &t, KW_RESTRICT)) {
- out->quals |= Q_RESTRICT; advance(p); seen = 1;
+ out->quals |= Q_RESTRICT;
+ advance(p);
+ seen = 1;
} else if (is_kw(p, &t, KW_ATOMIC)) {
Tok n = peek1(p);
if (is_punct(&n, '(')) {
@@ -477,9 +537,13 @@ int parse_decl_specs(Parser* p, DeclSpecs* out) {
seen = 1;
continue;
}
- out->quals |= Q_ATOMIC; advance(p); seen = 1;
+ out->quals |= Q_ATOMIC;
+ advance(p);
+ seen = 1;
} else if (is_kw(p, &t, KW_TYPEDEF)) {
- out->storage = DS_TYPEDEF; advance(p); seen = 1;
+ out->storage = DS_TYPEDEF;
+ advance(p);
+ seen = 1;
} else if (is_kw(p, &t, KW_ALIGNAS)) {
u32 a = 0;
advance(p); /* `_Alignas` */
@@ -496,14 +560,19 @@ int parse_decl_specs(Parser* p, DeclSpecs* out) {
if (a > out->align) out->align = a;
seen = 1;
} else if (is_kw(p, &t, KW_INLINE)) {
- out->flags |= DF_INLINE; advance(p); seen = 1;
+ out->flags |= DF_INLINE;
+ advance(p);
+ seen = 1;
} else if (is_kw(p, &t, KW_THREAD_LOCAL)) {
- out->flags |= DF_THREAD; advance(p); seen = 1;
+ out->flags |= DF_THREAD;
+ advance(p);
+ seen = 1;
} else if (is_kw(p, &t, KW_NORETURN) || is_kw(p, &t, KW_REGISTER) ||
is_kw(p, &t, KW_AUTO)) {
- advance(p); seen = 1;
- } else if (!acc.saw_explicit_type && !tagged_ty &&
- t.kind == TOK_IDENT && ident_kw(p, t.v.ident) == KW_NONE) {
+ advance(p);
+ seen = 1;
+ } else if (!acc.saw_explicit_type && !tagged_ty && t.kind == TOK_IDENT &&
+ ident_kw(p, t.v.ident) == KW_NONE) {
if (t.v.ident == p->sym_b_va_list) {
tagged_ty = c_abi_va_list_type(p->abi, p->pool);
acc.saw_explicit_type = 1;
@@ -544,11 +613,11 @@ int parse_decl_specs(Parser* p, DeclSpecs* out) {
* struct / union / enum
* ============================================================ */
-int find_field(TargetABI* abi, const Type* rec, Sym name,
+int find_field(TargetABI* abi, Pool* pool, const Type* rec, Sym name,
const Type** out_type, u32* out_offset,
const Field** out_field) {
if (!rec || (rec->kind != TY_STRUCT && rec->kind != TY_UNION)) return 0;
- const ABIRecordLayout* L = c_abi_record_layout(abi, rec);
+ const ABIRecordLayout* L = c_abi_record_layout(abi, pool, rec);
if (!L) return 0;
for (u16 i = 0; i < rec->rec.nfields; ++i) {
const Field* f = &rec->rec.fields[i];
@@ -558,12 +627,13 @@ int find_field(TargetABI* abi, const Type* rec, Sym name,
*out_field = f;
return 1;
}
- if ((f->flags & FIELD_ANON) && (f->type->kind == TY_STRUCT ||
- f->type->kind == TY_UNION)) {
+ if ((f->flags & FIELD_ANON) &&
+ (f->type->kind == TY_STRUCT || f->type->kind == TY_UNION)) {
const Type* inner_ty = NULL;
u32 inner_off = 0;
const Field* inner_f = NULL;
- if (find_field(abi, f->type, name, &inner_ty, &inner_off, &inner_f)) {
+ if (find_field(abi, pool, f->type, name, &inner_ty, &inner_off,
+ &inner_f)) {
*out_type = inner_ty;
*out_offset = L->fields[i].offset + inner_off;
*out_field = inner_f;
@@ -581,8 +651,8 @@ static void parse_member_decls(Parser* p, TypeRecordBuilder* b) {
perr(p, "expected member declaration");
}
if (is_punct(&p->cur, ';')) {
- if (specs.type && (specs.type->kind == TY_STRUCT ||
- specs.type->kind == TY_UNION)) {
+ if (specs.type &&
+ (specs.type->kind == TY_STRUCT || specs.type->kind == TY_UNION)) {
Field f;
memset(&f, 0, sizeof f);
f.name = 0;
@@ -709,8 +779,7 @@ const Type* parse_struct_or_union(Parser* p, TypeKind kind,
}
{
const Type* fresh = type_record_end(p->pool, b);
- type_record_install(target, (Field*)fresh->rec.fields,
- fresh->rec.nfields);
+ type_record_install(target, (Field*)fresh->rec.fields, fresh->rec.nfields);
}
{
TypeRecordOpts opts;
@@ -837,7 +906,8 @@ int starts_type_name(const Parser* p, const Tok* t) {
case KW_NONE: {
if (t->v.ident == p->sym_b_va_list) return 1;
if (t->v.ident == p->sym_int128 || t->v.ident == p->sym_int128_t ||
- t->v.ident == p->sym_uint128_t) return 1;
+ t->v.ident == p->sym_uint128_t)
+ return 1;
SymEntry* e = scope_lookup((Parser*)p, t->v.ident);
return e && e->kind == SEK_TYPEDEF;
}
@@ -851,11 +921,26 @@ const Type* parse_pointer_layer(Parser* p, const Type* base) {
u16 q = 0;
base = type_ptr(p->pool, base);
for (;;) {
- if (accept_kw(p, KW_CONST)) { q |= Q_CONST; continue; }
- if (accept_kw(p, KW_VOLATILE)) { q |= Q_VOLATILE; continue; }
- if (accept_kw(p, KW_RESTRICT)) { q |= Q_RESTRICT; continue; }
- if (accept_kw(p, KW_ATOMIC)) { q |= Q_ATOMIC; continue; }
- if (starts_attr(p)) { parse_and_discard_attributes(p); continue; }
+ if (accept_kw(p, KW_CONST)) {
+ q |= Q_CONST;
+ continue;
+ }
+ if (accept_kw(p, KW_VOLATILE)) {
+ q |= Q_VOLATILE;
+ continue;
+ }
+ if (accept_kw(p, KW_RESTRICT)) {
+ q |= Q_RESTRICT;
+ continue;
+ }
+ if (accept_kw(p, KW_ATOMIC)) {
+ q |= Q_ATOMIC;
+ continue;
+ }
+ if (starts_attr(p)) {
+ parse_and_discard_attributes(p);
+ continue;
+ }
break;
}
if (q) base = type_qualified(p->pool, base, q);
@@ -870,8 +955,8 @@ const Type* parse_type_name(Parser* p) {
if (!parse_decl_specs(p, &specs)) {
perr(p, "expected type-name");
}
- return parse_declarator_full(p, specs.type, /*allow_abstract=*/1,
- &dummy_name, &dummy_loc);
+ return parse_declarator_full(p, specs.type, /*allow_abstract=*/1, &dummy_name,
+ &dummy_loc);
}
/* ============================================================
@@ -903,7 +988,8 @@ int parse_decl_suffix(Parser* p, DeclSuffix* out) {
if (p->cur.kind == TOK_EOF) {
perr(p, "unexpected EOF in parameter array bound");
}
- if (is_punct(&p->cur, '[')) ++depth;
+ if (is_punct(&p->cur, '['))
+ ++depth;
else if (is_punct(&p->cur, ']')) {
--depth;
if (depth == 0) break;
@@ -968,14 +1054,15 @@ int parse_decl_suffix(Parser* p, DeclSuffix* out) {
}
const Type* apply_decl_suffix(Parser* p, const Type* base,
- const DeclSuffix* s) {
+ const DeclSuffix* s) {
if (s->kind == DS_ARRAY) {
return type_array(p->pool, base, s->count, s->incomplete || s->vla);
}
{
const Type** ptypes = NULL;
if (s->nparams) {
- ptypes = (const Type**)arena_array(p->c->tu, const Type*, s->nparams);
+ ptypes =
+ (const Type**)arena_array(p->pool->arena, const Type*, s->nparams);
for (u16 i = 0; i < s->nparams; ++i) ptypes[i] = s->params[i].type;
}
return type_func(p->pool, base, ptypes, s->nparams, (int)s->variadic);
@@ -995,8 +1082,7 @@ const Type* parse_declarator_full(Parser* p, const Type* base,
const Type* parse_declarator_full_ex(Parser* p, const Type* base,
int allow_abstract, Sym* name_out,
- SrcLoc* loc_out,
- Attr** attrs_out) {
+ SrcLoc* loc_out, Attr** attrs_out) {
base = parse_pointer_layer(p, base);
Sym name = 0;
@@ -1023,11 +1109,26 @@ const Type* parse_declarator_full_ex(Parser* p, const Type* base,
u16 q = 0;
if (nptrs_inner >= 8) perr(p, "too many pointer levels");
for (;;) {
- if (accept_kw(p, KW_CONST)) { q |= Q_CONST; continue; }
- if (accept_kw(p, KW_VOLATILE)) { q |= Q_VOLATILE; continue; }
- if (accept_kw(p, KW_RESTRICT)) { q |= Q_RESTRICT; continue; }
- if (accept_kw(p, KW_ATOMIC)) { q |= Q_ATOMIC; continue; }
- if (starts_attr(p)) { parse_and_discard_attributes(p); continue; }
+ if (accept_kw(p, KW_CONST)) {
+ q |= Q_CONST;
+ continue;
+ }
+ if (accept_kw(p, KW_VOLATILE)) {
+ q |= Q_VOLATILE;
+ continue;
+ }
+ if (accept_kw(p, KW_RESTRICT)) {
+ q |= Q_RESTRICT;
+ continue;
+ }
+ if (accept_kw(p, KW_ATOMIC)) {
+ q |= Q_ATOMIC;
+ continue;
+ }
+ if (starts_attr(p)) {
+ parse_and_discard_attributes(p);
+ continue;
+ }
break;
}
inner_quals[nptrs_inner++] = q;
@@ -1060,8 +1161,10 @@ const Type* parse_declarator_full_ex(Parser* p, const Type* base,
}
if (starts_attr(p)) {
- if (attrs_out) parse_attrs_into(p, attrs_out);
- else parse_and_discard_attributes(p);
+ if (attrs_out)
+ parse_attrs_into(p, attrs_out);
+ else
+ parse_and_discard_attributes(p);
}
DeclSuffix suffs[8];
@@ -1070,8 +1173,10 @@ const Type* parse_declarator_full_ex(Parser* p, const Type* base,
if (!parse_decl_suffix(p, &suffs[nsuffs])) break;
++nsuffs;
if (starts_attr(p)) {
- if (attrs_out) parse_attrs_into(p, attrs_out);
- else parse_and_discard_attributes(p);
+ if (attrs_out)
+ parse_attrs_into(p, attrs_out);
+ else
+ parse_and_discard_attributes(p);
}
}
if (nsuffs == 8 && (is_punct(&p->cur, '[') || is_punct(&p->cur, '('))) {
@@ -1098,8 +1203,9 @@ const Type* parse_declarator_full_ex(Parser* p, const Type* base,
}
const Type* parse_declarator(Parser* p, const Type* base, Sym* name_out,
- SrcLoc* loc_out) {
- return parse_declarator_full(p, base, /*allow_abstract=*/0, name_out, loc_out);
+ SrcLoc* loc_out) {
+ return parse_declarator_full(p, base, /*allow_abstract=*/0, name_out,
+ loc_out);
}
/* ============================================================
@@ -1114,7 +1220,7 @@ const Type* complete_incomplete_array(Parser* p, const Type* ty) {
Tok t = p->cur;
size_t n = 0;
u8* bytes = decode_string_literal(p, &t, &n);
- p->c->env->heap->free(p->c->env->heap, bytes, 0);
+ cfree_compiler_heap(p->c)->free(cfree_compiler_heap(p->c), bytes, 0);
return type_array(p->pool, elem, (u32)n, /*incomplete=*/0);
}
if (is_punct(&p->cur, '{')) {
@@ -1126,7 +1232,7 @@ const Type* complete_incomplete_array(Parser* p, const Type* ty) {
Tok t = p->replay[1];
size_t n = 0;
u8* bytes = decode_string_literal(p, &t, &n);
- p->c->env->heap->free(p->c->env->heap, bytes, 0);
+ cfree_compiler_heap(p->c)->free(cfree_compiler_heap(p->c), bytes, 0);
cnt = (u32)n;
}
replay_rewind(p);
diff --git a/lang/c/pp/pp.c b/lang/c/pp/pp.c
@@ -142,8 +142,8 @@ Tok pp_next(Pp* pp) {
}
/* Not a pragma — push the peeked token back as a 1-element buffer
* so the next pp_next_raw returns it, and surface the hash now. */
- Tok* keep = arena_array(&pp->arena, Tok, 1);
- HidesetId* hs = arena_array(&pp->arena, HidesetId, 1);
+ Tok* keep = arena_array(pp->arena, Tok, 1);
+ HidesetId* hs = arena_array(pp->arena, HidesetId, 1);
keep[0] = t2;
hs[0] = HS_EMPTY;
push_buf(pp, keep, hs, 1);
@@ -180,7 +180,7 @@ void pp_emit_text(Pp* pp, Writer* out) {
}
if (t.spelling) {
size_t slen = 0;
- const char* s = pool_str(pp->c->global, t.spelling, &slen);
+ const char* s = pool_str(pp->pool, t.spelling, &slen);
w_str(out, s, slen);
}
at_bol = 0;
@@ -192,7 +192,7 @@ void pp_emit_text(Pp* pp, Writer* out) {
* ============================================================ */
static void pp_intern_keywords(Pp* pp) {
- Pool* p = pp->c->global;
+ Pool* p = pp->pool;
pp->sym_define = pool_intern_cstr(p, "define");
pp->sym_undef = pool_intern_cstr(p, "undef");
pp->sym_include = pool_intern_cstr(p, "include");
@@ -269,11 +269,11 @@ static void compute_date_time(Pp* pp) {
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
char date[24];
char tm[16];
- int64_t t = pp->c->env->now;
+ int64_t t = cfree_compiler_now(pp->c);
PpYMD ymd;
if (t < 0) {
- pp->val_date_str = pool_intern_cstr(pp->c->global, "\"??? ?? ????\"");
- pp->val_time_str = pool_intern_cstr(pp->c->global, "\"??:??:??\"");
+ pp->val_date_str = pool_intern_cstr(pp->pool, "\"??? ?? ????\"");
+ pp->val_time_str = pool_intern_cstr(pp->pool, "\"??:??:??\"");
return;
}
pp_break_time(t, &ymd);
@@ -292,7 +292,7 @@ static void compute_date_time(Pp* pp) {
date[p++] = (char)('0' + (yyyy / 10) % 10);
date[p++] = (char)('0' + (yyyy) % 10);
date[p++] = '"';
- pp->val_date_str = pool_intern(pp->c->global, date, (size_t)p);
+ pp->val_date_str = pool_intern(pp->pool, date, (size_t)p);
}
{
int hh = ymd.h, mm = ymd.m, ss = ymd.s;
@@ -307,7 +307,7 @@ static void compute_date_time(Pp* pp) {
tm[p++] = (char)('0' + (ss / 10) % 10);
tm[p++] = (char)('0' + ss % 10);
tm[p++] = '"';
- pp->val_time_str = pool_intern(pp->c->global, tm, (size_t)p);
+ pp->val_time_str = pool_intern(pp->pool, tm, (size_t)p);
}
}
@@ -333,10 +333,11 @@ static void pp_register_static_predefined(Pp* pp) {
* cfree supports), ptr_size == 4 picks ILP32. LLP64 (Windows x86-64) is
* not yet a supported target, so `long` always tracks pointer width here. */
static void pp_register_target_predefined(Pp* pp) {
- int lp64 = (pp->c->target.ptr_size == 8);
+ CfreeTarget target = cfree_compiler_target(pp->c);
+ int lp64 = (target.ptr_size == 8);
pp_define(pp, "__USER_LABEL_PREFIX__",
- pp->c->target.obj == CFREE_OBJ_MACHO ? "_" : "");
+ target.obj == CFREE_OBJ_MACHO ? "_" : "");
/* stddef.h base aliases */
pp_define(pp, "__SIZE_TYPE__", lp64 ? "unsigned long" : "unsigned int");
@@ -447,12 +448,19 @@ static void pp_register_target_predefined(Pp* pp) {
}
Pp* pp_new(Compiler* c) {
- Heap* h = (Heap*)c->env->heap;
+ Heap* h = (Heap*)cfree_compiler_heap(c);
Pp* pp = (Pp*)h->alloc(h, sizeof(*pp), _Alignof(Pp));
if (!pp) return NULL;
memset(pp, 0, sizeof(*pp));
pp->c = c;
- arena_init(&pp->arena, h, 64 * 1024);
+ pp->pool = c_pool_new(c);
+ pp->arena = cfree_arena_new(h, 64 * 1024);
+ if (!pp->pool || !pp->arena) {
+ c_pool_free(pp->pool);
+ cfree_arena_free(pp->arena);
+ h->free(h, pp, sizeof(*pp));
+ return NULL;
+ }
/* Reserve hideset slot 0 for HS_EMPTY. The slot is unused but the
* indexing convention costs only a pointer. */
pp->hsets_cap = 8;
@@ -469,7 +477,9 @@ Pp* pp_new(Compiler* c) {
}
void pp_free(Pp* pp) {
+ Heap* h;
if (!pp) return;
+ h = pp_heap(pp);
/* Pop / close any remaining lex sources. */
while (pp->nsources) src_pop(pp);
pp_xfree(pp, pp->sources, sizeof(TokSrc) * pp->sources_cap);
@@ -477,8 +487,9 @@ void pp_free(Pp* pp) {
pp_xfree(pp, pp->hsets, sizeof(Hideset*) * pp->hsets_cap);
pp_xfree(pp, pp->ifstk, sizeof(IfFrame) * pp->ifstk_cap);
pp_xfree(pp, pp->inc_dirs, sizeof(*pp->inc_dirs) * pp->inc_dirs_cap);
- arena_fini(&pp->arena);
- pp_heap(pp)->free((Heap*)pp->c->env->heap, pp, sizeof(*pp));
+ c_pool_free(pp->pool);
+ cfree_arena_free(pp->arena);
+ h->free(h, pp, sizeof(*pp));
}
void pp_push_input(Pp* pp, Lexer* lex) {
@@ -546,13 +557,13 @@ void pp_define(Pp* pp, const char* name, const char* body) {
void pp_undef(Pp* pp, const char* name) {
Sym s;
if (!name || !*name) return;
- s = pool_intern_cstr(pp->c->global, name);
+ s = pool_intern_cstr(pp->pool, name);
mt_del(pp, s);
}
void pp_add_include_edge(Pp* pp, u32 includer, u32 included, SrcLoc include_loc,
int system) {
- source_add_include(pp->c->sources, includer, included, include_loc, system);
+ cfree_source_add_include(pp->c, includer, included, include_loc, system);
}
const LitInfo* pp_lit(const Pp* pp, LitId id) {
diff --git a/lang/c/pp/pp.h b/lang/c/pp/pp.h
@@ -5,8 +5,8 @@
typedef struct Pp Pp;
-/* PP reads file_io from c->env for include search. If include search is
- * configured but c->env->file_io is missing, include resolution panics. */
+/* PP reads the compiler file-IO service for include search. If include search
+ * is configured but file_io is missing, include resolution panics. */
Pp* pp_new(Compiler*);
void pp_free(Pp*);
diff --git a/lang/c/pp/pp_directive.c b/lang/c/pp/pp_directive.c
@@ -42,7 +42,7 @@ void read_directive_line(Pp* pp, Tok** out_toks, u32* out_n) {
if (t.kind == TOK_NEWLINE || t.kind == TOK_EOF) break;
if (n == cap) {
u32 nc = cap ? cap * 2 : 8;
- Tok* nb = (Tok*)arena_alloc(&pp->arena, sizeof(Tok) * nc, _Alignof(Tok));
+ Tok* nb = (Tok*)arena_alloc(pp->arena, sizeof(Tok) * nc, _Alignof(Tok));
if (cap) memcpy(nb, buf, sizeof(Tok) * cap);
buf = nb;
cap = nc;
@@ -120,8 +120,7 @@ static void prepass_defined(Pp* pp, const Tok* in, u32 nin, TokVec* out) {
t.kind = TOK_NUM;
t.flags = in[i].flags & (TF_AT_BOL | TF_HAS_SPACE);
t.loc = in[i].loc;
- t.spelling =
- pool_intern_cstr(pp->c->global, mt_get(pp, ident) ? "1" : "0");
+ t.spelling = pool_intern_cstr(pp->pool, mt_get(pp, ident) ? "1" : "0");
tv_push(pp, out, t);
}
i = j - 1;
@@ -137,13 +136,13 @@ static void prepass_defined(Pp* pp, const Tok* in, u32 nin, TokVec* out) {
static void expand_for_if(Pp* pp, const Tok* in, u32 nin, TokVec* out) {
Tok* slice;
if (nin == 0) return;
- slice = arena_array(&pp->arena, Tok, nin);
+ slice = arena_array(pp->arena, Tok, nin);
memcpy(slice, in, sizeof(Tok) * nin);
expand_arg_to_eof(pp, slice, nin, out);
/* Replace remaining identifiers with `0`. */
{
u32 i;
- Sym zero = pool_intern_cstr(pp->c->global, "0");
+ Sym zero = pool_intern_cstr(pp->pool, "0");
for (i = 0; i < out->n; ++i) {
if (out->data[i].kind == TOK_IDENT) {
out->data[i].kind = TOK_NUM;
@@ -182,7 +181,7 @@ static i64 ee_primary(EE* e) {
if (!t) compiler_panic(e->pp->c, e->loc, "#if: missing operand");
if (t->kind == TOK_NUM) {
size_t slen;
- const char* s = pool_str(e->pp->c->global, t->spelling, &slen);
+ const char* s = pool_str(e->pp->pool, t->spelling, &slen);
++e->pos;
return parse_pp_int(s, slen);
}
@@ -191,7 +190,7 @@ static i64 ee_primary(EE* e) {
* not implemented; cover the common case of a single ASCII
* char). */
size_t slen;
- const char* s = pool_str(e->pp->c->global, t->spelling, &slen);
+ const char* s = pool_str(e->pp->pool, t->spelling, &slen);
++e->pos;
if (slen >= 3 && s[0] == '\'') return (unsigned char)s[1];
return 0;
@@ -585,7 +584,7 @@ static int try_open_include(Pp* pp, const char* path, const u8** data_out,
u8* buf;
memset(&fd, 0, sizeof(fd));
- io = pp->c->env->file_io;
+ io = cfree_compiler_file_io(pp->c);
if (!io || !io->read_all) {
compiler_panic(pp->c, (SrcLoc){0, 0, 0},
"#include: env.file_io is not configured");
@@ -593,7 +592,7 @@ static int try_open_include(Pp* pp, const char* path, const u8** data_out,
if (!io->read_all(io->user, path, &fd)) return 0;
{
size_t sz = fd.size;
- buf = (u8*)arena_alloc(&pp->arena, sz ? sz : 1, 1);
+ buf = (u8*)arena_alloc(pp->arena, sz ? sz : 1, 1);
if (sz && fd.data) memcpy(buf, fd.data, sz);
if (io->release) io->release(io->user, &fd); /* zeros fd */
*data_out = buf;
@@ -606,12 +605,15 @@ static int try_open_include(Pp* pp, const char* path, const u8** data_out,
* for in-memory/builtin sources (where CWD is the natural fallback, like
* gcc treats stdin). `dir_out` must point to a buffer of size >= cap. */
static int includer_dir(Pp* pp, SrcLoc loc, char* dir_out, size_t cap) {
- const SourceFile* sf = source_file(pp->c->sources, loc.file_id);
+ CfreeSourceFile sf;
const char* p = NULL;
size_t plen = 0;
const char* slash;
size_t dlen;
- if (sf && sf->name) p = pool_str(pp->c->global, sf->name, &plen);
+ memset(&sf, 0, sizeof(sf));
+ if (cfree_source_file(pp->c, loc.file_id, &sf) == 0 && sf.name) {
+ p = pool_str(pp->pool, sf.name, &plen);
+ }
if (!p || plen == 0 || p[0] == '<') {
if (cap < 2) return 0;
dir_out[0] = '.';
@@ -706,7 +708,7 @@ static void parse_include_path(Pp* pp, const Tok* line, u32 n, SrcLoc loc,
if (line[0].kind == TOK_HEADER) {
size_t slen = 0;
- const char* s = pool_str(pp->c->global, line[0].spelling, &slen);
+ const char* s = pool_str(pp->pool, line[0].spelling, &slen);
if (slen < 2) compiler_panic(pp->c, loc, "#include: malformed header name");
if (s[0] == '<' && s[slen - 1] == '>')
*system_out = 1;
@@ -724,7 +726,7 @@ static void parse_include_path(Pp* pp, const Tok* line, u32 n, SrcLoc loc,
/* Macro-replaced form. */
{
TokVec exp = {0};
- Tok* slice = arena_array(&pp->arena, Tok, n);
+ Tok* slice = arena_array(pp->arena, Tok, n);
memcpy(slice, line, sizeof(Tok) * n);
expand_arg_to_eof(pp, slice, n, &exp);
@@ -733,7 +735,7 @@ static void parse_include_path(Pp* pp, const Tok* line, u32 n, SrcLoc loc,
}
if (exp.data[0].kind == TOK_STR) {
size_t slen = 0;
- const char* s = pool_str(pp->c->global, exp.data[0].spelling, &slen);
+ const char* s = pool_str(pp->pool, exp.data[0].spelling, &slen);
if (slen < 2 || s[0] != '"' || s[slen - 1] != '"') {
compiler_panic(pp->c, loc, "#include: malformed string");
}
@@ -755,7 +757,7 @@ static void parse_include_path(Pp* pp, const Tok* line, u32 n, SrcLoc loc,
break;
}
if (exp.data[i].spelling) {
- s = pool_str(pp->c->global, exp.data[i].spelling, &slen);
+ s = pool_str(pp->pool, exp.data[i].spelling, &slen);
}
if (s && pos + slen + 1 <= cap) {
memcpy(path_out + pos, s, slen);
@@ -807,8 +809,7 @@ static void do_include(Pp* pp, const Tok* line, u32 n, SrcLoc loc) {
s.lex = lex;
src_push(pp, s);
- source_add_include(pp->c->sources, includer_id, included_id, loc,
- system_form);
+ cfree_source_add_include(pp->c, includer_id, included_id, loc, system_form);
}
/* ============================================================
@@ -835,7 +836,7 @@ static void do_line(Pp* pp, const Tok* line, u32 n, SrcLoc loc) {
Sym target_file = 0;
if (n == 0) compiler_panic(pp->c, loc, "#line: missing arguments");
- slice = arena_array(&pp->arena, Tok, n);
+ slice = arena_array(pp->arena, Tok, n);
memcpy(slice, line, sizeof(Tok) * n);
expand_arg_to_eof(pp, slice, n, &exp);
@@ -844,7 +845,7 @@ static void do_line(Pp* pp, const Tok* line, u32 n, SrcLoc loc) {
}
{
size_t sl = 0;
- const char* s = pool_str(pp->c->global, exp.data[0].spelling, &sl);
+ const char* s = pool_str(pp->pool, exp.data[0].spelling, &sl);
target_line = parse_pp_int(s, sl);
}
if (exp.n >= 2) {
@@ -853,9 +854,9 @@ static void do_line(Pp* pp, const Tok* line, u32 n, SrcLoc loc) {
}
{
size_t sl = 0;
- const char* s = pool_str(pp->c->global, exp.data[1].spelling, &sl);
+ const char* s = pool_str(pp->pool, exp.data[1].spelling, &sl);
if (sl >= 2 && s[0] == '"' && s[sl - 1] == '"') {
- target_file = pool_intern(pp->c->global, s + 1, sl - 2);
+ target_file = pool_intern(pp->pool, s + 1, sl - 2);
}
}
}
@@ -889,7 +890,7 @@ void emit_pragma_line(Pp* pp, const Tok* line, u32 n, SrcLoc loc) {
hash.kind = TOK_PP_HASH;
hash.flags = TF_AT_BOL;
hash.loc = loc;
- hash.spelling = pool_intern_cstr(pp->c->global, "#");
+ hash.spelling = pool_intern_cstr(pp->pool, "#");
tv_push(pp, &out, hash);
memset(&ident, 0, sizeof(ident));
@@ -915,7 +916,7 @@ void emit_pragma_line(Pp* pp, const Tok* line, u32 n, SrcLoc loc) {
nl.loc = loc;
tv_push(pp, &out, nl);
- hids = arena_array(&pp->arena, HidesetId, out.n ? out.n : 1);
+ hids = arena_array(pp->arena, HidesetId, out.n ? out.n : 1);
for (i = 0; i < out.n; ++i) hids[i] = HS_EMPTY;
push_buf(pp, out.data, hids, out.n);
}
@@ -933,7 +934,7 @@ static void do_pragma(Pp* pp, const Tok* line, u32 n, SrcLoc loc) {
static void destringize(Pp* pp, const Tok* str_tok, char* out, size_t cap,
size_t* out_len) {
size_t slen = 0;
- const char* s = pool_str(pp->c->global, str_tok->spelling, &slen);
+ const char* s = pool_str(pp->pool, str_tok->spelling, &slen);
size_t i, w = 0;
if (slen < 2 || s[0] != '"' || s[slen - 1] != '"') {
compiler_panic(pp->c, str_tok->loc,
@@ -997,7 +998,7 @@ int try_expand_pragma_op(Pp* pp, const Tok* invoke) {
/* Re-lex into args. Bytes need to live until lex_close; copy into
* arena. */
{
- char* arena_buf = (char*)arena_alloc(&pp->arena, buf_n + 1, 1);
+ char* arena_buf = (char*)arena_alloc(pp->arena, buf_n + 1, 1);
memcpy(arena_buf, buf, buf_n + 1);
lex = lex_open_mem(pp->c, "<_Pragma>", arena_buf, buf_n);
}
@@ -1022,9 +1023,8 @@ static void do_error(Pp* pp, const Tok* line, u32 n, SrcLoc loc) {
u32 i;
for (i = 0; i < n; ++i) {
size_t sl = 0;
- const char* s = line[i].spelling
- ? pool_str(pp->c->global, line[i].spelling, &sl)
- : NULL;
+ const char* s =
+ line[i].spelling ? pool_str(pp->pool, line[i].spelling, &sl) : NULL;
if (i > 0) cb_putc(pp, &cb, ' ');
if (s && sl) cb_append(pp, &cb, s, (u32)sl);
}
@@ -1054,7 +1054,7 @@ static void do_embed(Pp* pp, const Tok* line, u32 n, SrcLoc loc) {
if (line[0].kind == TOK_HEADER) {
size_t sl = 0;
- const char* s = pool_str(pp->c->global, line[0].spelling, &sl);
+ const char* s = pool_str(pp->pool, line[0].spelling, &sl);
if (sl < 2) compiler_panic(pp->c, loc, "#embed: malformed header name");
if (s[0] == '<' && s[sl - 1] == '>')
system_form = 1;
@@ -1074,7 +1074,7 @@ static void do_embed(Pp* pp, const Tok* line, u32 n, SrcLoc loc) {
while (j < n) {
if (line[j].kind == TOK_IDENT) {
size_t sl = 0;
- const char* s = pool_str(pp->c->global, line[j].v.ident, &sl);
+ const char* s = pool_str(pp->pool, line[j].v.ident, &sl);
if (sl == 5 && memcmp(s, "limit", 5) == 0) {
if (j + 1 >= n || line[j + 1].kind != TOK_PUNCT ||
line[j + 1].v.punct != '(') {
@@ -1086,7 +1086,7 @@ static void do_embed(Pp* pp, const Tok* line, u32 n, SrcLoc loc) {
}
{
size_t sl2 = 0;
- const char* s2 = pool_str(pp->c->global, line[j].spelling, &sl2);
+ const char* s2 = pool_str(pp->pool, line[j].spelling, &sl2);
limit_n = parse_pp_int(s2, sl2);
}
++j;
@@ -1119,7 +1119,7 @@ static void do_embed(Pp* pp, const Tok* line, u32 n, SrcLoc loc) {
if (j >= n) {
compiler_panic(pp->c, loc, "#embed: unterminated if_empty");
}
- if_empty_toks = arena_array(&pp->arena, Tok, j - start ? j - start : 1);
+ if_empty_toks = arena_array(pp->arena, Tok, j - start ? j - start : 1);
if_empty_n = j - start;
memcpy(if_empty_toks, line + start, sizeof(Tok) * if_empty_n);
++j; /* skip ')' */
@@ -1141,7 +1141,7 @@ static void do_embed(Pp* pp, const Tok* line, u32 n, SrcLoc loc) {
if (emit_n == 0) {
/* Empty: emit if_empty payload (or nothing). */
if (if_empty_toks && if_empty_n) {
- HidesetId* hids = arena_array(&pp->arena, HidesetId, if_empty_n);
+ HidesetId* hids = arena_array(pp->arena, HidesetId, if_empty_n);
u32 i;
for (i = 0; i < if_empty_n; ++i) hids[i] = HS_EMPTY;
push_buf(pp, if_empty_toks, hids, if_empty_n);
@@ -1174,7 +1174,7 @@ static void do_embed(Pp* pp, const Tok* line, u32 n, SrcLoc loc) {
memset(&t, 0, sizeof(t));
t.kind = TOK_NUM;
t.loc = loc;
- t.spelling = pool_intern(pp->c->global, numbuf, (size_t)nl);
+ t.spelling = pool_intern(pp->pool, numbuf, (size_t)nl);
if (i == 0) t.flags = TF_AT_BOL;
/* Bytes after a comma get a leading space to match
* clang's `, ` separator format. */
@@ -1188,11 +1188,11 @@ static void do_embed(Pp* pp, const Tok* line, u32 n, SrcLoc loc) {
comma.kind = TOK_PUNCT;
comma.v.punct = ',';
comma.loc = loc;
- comma.spelling = pool_intern_cstr(pp->c->global, ",");
+ comma.spelling = pool_intern_cstr(pp->pool, ",");
tv_push(pp, &out, comma);
}
}
- hids = arena_array(&pp->arena, HidesetId, out.n ? out.n : 1);
+ hids = arena_array(pp->arena, HidesetId, out.n ? out.n : 1);
{
u32 k;
for (k = 0; k < out.n; ++k) hids[k] = HS_EMPTY;
diff --git a/lang/c/pp/pp_expand.c b/lang/c/pp/pp_expand.c
@@ -41,7 +41,7 @@ static HidesetId hs_register(Pp* pp, const Sym* names, u32 n) {
sizeof(Hideset*) * nc, _Alignof(Hideset*));
pp->hsets_cap = nc;
}
- h = (Hideset*)arena_alloc(&pp->arena,
+ h = (Hideset*)arena_alloc(pp->arena,
sizeof(Hideset) + sizeof(Sym) * (n ? n - 1 : 0),
_Alignof(Hideset));
h->n = n;
@@ -149,7 +149,7 @@ void do_define(Pp* pp, const Tok* line, u32 n) {
def_loc = line[i].loc;
++i;
- m = arena_znew(&pp->arena, Macro);
+ m = arena_znew(pp->arena, Macro);
m->name = name;
m->def_loc = def_loc;
@@ -174,7 +174,7 @@ void do_define(Pp* pp, const Tok* line, u32 n) {
* matches the standard identifier directly. */
if (pn == pcap) {
u32 nc = pcap ? pcap * 2 : 4;
- Sym* nb = arena_array(&pp->arena, Sym, nc);
+ Sym* nb = arena_array(pp->arena, Sym, nc);
if (pcap) memcpy(nb, params, sizeof(Sym) * pcap);
params = nb;
pcap = nc;
@@ -185,7 +185,7 @@ void do_define(Pp* pp, const Tok* line, u32 n) {
} else if (line[i].kind == TOK_IDENT) {
if (pn == pcap) {
u32 nc = pcap ? pcap * 2 : 4;
- Sym* nb = arena_array(&pp->arena, Sym, nc);
+ Sym* nb = arena_array(pp->arena, Sym, nc);
if (pcap) memcpy(nb, params, sizeof(Sym) * pcap);
params = nb;
pcap = nc;
@@ -246,7 +246,7 @@ void do_define(Pp* pp, const Tok* line, u32 n) {
{
u32 body_n = n - i;
u32 j;
- m->body = body_n ? arena_array(&pp->arena, Tok, body_n) : NULL;
+ m->body = body_n ? arena_array(pp->arena, Tok, body_n) : NULL;
m->body_len = body_n;
for (j = 0; j < body_n; ++j) {
Tok t = line[i + j];
@@ -361,7 +361,7 @@ static void expand_object_macro(Pp* pp, const Macro* m, const Tok* invoke,
}
/* Run the body through the paste phase: object-like macros may use
* `##`. There are no parameters, so phase 1 reduces to a copy. */
- tmp = arena_array(&pp->arena, Tok, m->body_len);
+ tmp = arena_array(pp->arena, Tok, m->body_len);
for (i = 0; i < m->body_len; ++i) tmp[i] = m->body[i];
subst_phase2(pp, tmp, m->body_len, invoke, &body);
@@ -374,7 +374,7 @@ static void expand_object_macro(Pp* pp, const Macro* m, const Tok* invoke,
for (i = 0; i < body.n; ++i) body.data[i].loc = invoke->loc;
hs = hs_add(pp, invoke_hs, m->name);
- hids = arena_array(&pp->arena, HidesetId, body.n);
+ hids = arena_array(pp->arena, HidesetId, body.n);
for (i = 0; i < body.n; ++i) hids[i] = hs;
push_buf(pp, body.data, hids, body.n);
}
@@ -483,7 +483,7 @@ static Tok read_invocation_args(Pp* pp, const Macro* m, SrcLoc invoke_loc,
Tok close_tok;
memset(out, 0, sizeof(*out));
- starts = arena_array(&pp->arena, u32, 8);
+ starts = arena_array(pp->arena, u32, 8);
starts_cap = 8;
starts[0] = 0;
@@ -534,7 +534,7 @@ static Tok read_invocation_args(Pp* pp, const Macro* m, SrcLoc invoke_loc,
if (want_slot) {
if (n_args + 1 >= starts_cap) {
u32 nc = starts_cap * 2;
- u32* nb = arena_array(&pp->arena, u32, nc);
+ u32* nb = arena_array(pp->arena, u32, nc);
memcpy(nb, starts, sizeof(u32) * starts_cap);
starts = nb;
starts_cap = nc;
@@ -558,7 +558,7 @@ static Tok read_invocation_args(Pp* pp, const Macro* m, SrcLoc invoke_loc,
/* Close current arg, start next. */
if (n_args + 1 >= starts_cap) {
u32 nc = starts_cap * 2;
- u32* nb = arena_array(&pp->arena, u32, nc);
+ u32* nb = arena_array(pp->arena, u32, nc);
memcpy(nb, starts, sizeof(u32) * starts_cap);
starts = nb;
starts_cap = nc;
@@ -594,7 +594,7 @@ done:
if (n_args + 1 == expected) {
if (n_args + 1 >= starts_cap) {
u32 nc = starts_cap * 2;
- u32* nb = arena_array(&pp->arena, u32, nc);
+ u32* nb = arena_array(pp->arena, u32, nc);
memcpy(nb, starts, sizeof(u32) * starts_cap);
starts = nb;
starts_cap = nc;
@@ -623,7 +623,7 @@ static void preexpand_args(Pp* pp, ArgList* a) {
TokVec exp = {0};
u32* exp_start;
u32 i;
- exp_start = arena_array(&pp->arena, u32, a->n_args + 1);
+ exp_start = arena_array(pp->arena, u32, a->n_args + 1);
exp_start[0] = 0;
for (i = 0; i < a->n_args; ++i) {
u32 lo = a->raw_start[i];
@@ -631,7 +631,7 @@ static void preexpand_args(Pp* pp, ArgList* a) {
if (hi > lo) {
/* Copy the slice into a fresh buffer so expand_arg_to_eof can
* own it without aliasing. */
- Tok* slice = arena_array(&pp->arena, Tok, hi - lo);
+ Tok* slice = arena_array(pp->arena, Tok, hi - lo);
memcpy(slice, &a->raw[lo], sizeof(Tok) * (hi - lo));
expand_arg_to_eof(pp, slice, hi - lo, &exp);
}
@@ -657,7 +657,7 @@ static Tok make_stringize(Pp* pp, const Tok* arg, u32 lo, u32 hi, SrcLoc loc) {
const Tok* at = &arg[i];
size_t slen = 0;
const char* s =
- at->spelling ? pool_str(pp->c->global, at->spelling, &slen) : NULL;
+ at->spelling ? pool_str(pp->pool, at->spelling, &slen) : NULL;
if (i > lo && (at->flags & TF_HAS_SPACE)) cb_putc(pp, &b, ' ');
if (s && slen) {
int esc = (at->kind == TOK_STR || at->kind == TOK_CHR);
@@ -671,7 +671,7 @@ static Tok make_stringize(Pp* pp, const Tok* arg, u32 lo, u32 hi, SrcLoc loc) {
}
cb_putc(pp, &b, '"');
- sp = pool_intern(pp->c->global, b.data, b.len);
+ sp = pool_intern(pp->pool, b.data, b.len);
memset(&t, 0, sizeof(t));
t.kind = TOK_STR;
t.loc = loc;
@@ -693,8 +693,8 @@ static Tok paste_tokens(Pp* pp, Tok lhs, Tok rhs, SrcLoc loc) {
if (lhs.kind == TOK_PP_PLACEMARKER) return rhs;
if (rhs.kind == TOK_PP_PLACEMARKER) return lhs;
- a = lhs.spelling ? pool_str(pp->c->global, lhs.spelling, &alen) : "";
- b = rhs.spelling ? pool_str(pp->c->global, rhs.spelling, &blen) : "";
+ a = lhs.spelling ? pool_str(pp->pool, lhs.spelling, &alen) : "";
+ b = rhs.spelling ? pool_str(pp->pool, rhs.spelling, &blen) : "";
if (alen + blen + 2 > sizeof(buf)) {
compiler_panic(pp->c, loc, "token paste: spelling too long");
}
@@ -892,7 +892,7 @@ static int try_expand_func_macro(Pp* pp, const Macro* m, const Tok* invoke,
{
u32 i;
- HidesetId* hids = arena_array(&pp->arena, HidesetId, body.n ? body.n : 1);
+ HidesetId* hids = arena_array(pp->arena, HidesetId, body.n ? body.n : 1);
for (i = 0; i < body.n; ++i) {
hids[i] = (HidesetId)hsvec.data[i].spelling;
}
@@ -946,7 +946,7 @@ Tok pp_next_raw(Pp* pp) {
while (j > 0) buf[k++] = tmp[--j];
}
t.kind = TOK_NUM;
- t.spelling = pool_intern(pp->c->global, buf, (size_t)k);
+ t.spelling = pool_intern(pp->pool, buf, (size_t)k);
return t;
}
if (id == pp->sym_file__) {
@@ -958,17 +958,19 @@ Tok pp_next_raw(Pp* pp) {
if (ls && ls->file_override) {
name = ls->file_override;
} else if (ls) {
- const SourceFile* sf =
- source_file(pp->c->sources, lex_file_id(ls->lex));
- if (sf) name = sf->name;
+ CfreeSourceFile sf;
+ memset(&sf, 0, sizeof(sf));
+ if (cfree_source_file(pp->c, lex_file_id(ls->lex), &sf) == 0) {
+ name = sf.name;
+ }
}
- if (name) nstr = pool_str(pp->c->global, name, &nlen);
- buf = (char*)arena_alloc(&pp->arena, nlen + 2, 1);
+ if (name) nstr = pool_str(pp->pool, name, &nlen);
+ buf = (char*)arena_alloc(pp->arena, nlen + 2, 1);
buf[0] = '"';
if (nlen) memcpy(buf + 1, nstr, nlen);
buf[nlen + 1] = '"';
t.kind = TOK_STR;
- t.spelling = pool_intern(pp->c->global, buf, nlen + 2);
+ t.spelling = pool_intern(pp->pool, buf, nlen + 2);
t.v.str = t.spelling;
return t;
}
diff --git a/lang/c/pp/pp_priv.h b/lang/c/pp/pp_priv.h
@@ -5,22 +5,18 @@
#ifndef CFREE_PP_PRIV_H
#define CFREE_PP_PRIV_H
-#include "pp/pp.h"
-
#include <stdlib.h>
#include <string.h>
-#include "core/arena.h"
-#include "core/diag.h"
-#include "core/heap.h"
-#include "core/pool.h"
+#include "c_support.h"
+#include "pp/pp.h"
/* ============================================================
* Internal token kinds
* ============================================================ */
/* Outside the range used by the lexer (TOK_KW_LAST = 0x1000). */
-#define TOK_PP_PARAM ((u16)0x1100)
+#define TOK_PP_PARAM ((u16)0x1100)
#define TOK_PP_PLACEMARKER ((u16)0x1101) /* empty-arg substitution marker */
/* ============================================================
@@ -73,9 +69,9 @@ typedef struct TokSrc {
} TokSrc;
typedef enum IfState {
- IF_INCLUDE = 1, /* group active, emit code */
+ IF_INCLUDE = 1, /* group active, emit code */
IF_SEEK_TRUE = 2, /* skip, looking for the first true elif/else */
- IF_DONE = 3, /* skip, already had a true branch */
+ IF_DONE = 3, /* skip, already had a true branch */
} IfState;
typedef struct IfFrame {
@@ -87,9 +83,9 @@ typedef struct IfFrame {
/* MacroMap = Sym -> Macro*. Generated open-addressed hashmap with
* deletion (#undef). See core/hashmap.h. */
-#include "core/hashmap.h"
-static inline u32 macro_hash_(Sym s) { return hash_u32((u32)s); }
-HASHMAP_DEFINE(MacroMap, Sym, Macro*, macro_hash_);
+#include <cfree/hashmap.h>
+static inline u32 macro_hash_(Sym s) { return cfree_hash_u32((u32)s); }
+CFREE_HASHMAP_DEFINE(MacroMap, Sym, Macro*, macro_hash_);
/* ============================================================
* Pp struct (definition shared across all three TUs)
@@ -97,6 +93,7 @@ HASHMAP_DEFINE(MacroMap, Sym, Macro*, macro_hash_);
struct Pp {
Compiler* c;
+ Pool* pool;
/* Source stack — top of stack is sources[nsources-1]. */
TokSrc* sources;
@@ -126,7 +123,7 @@ struct Pp {
/* Internal arena: macro bodies, hidesets, expansion buffers, file
* data for #include. Lives until pp_free. */
- Arena arena;
+ CfreeArena* arena;
/* Cached interned identifiers used for directive recognition. */
Sym sym_define;
@@ -165,10 +162,10 @@ struct Pp {
* Allocation helpers (defined in pp.c, used everywhere)
* ============================================================ */
-static inline Heap* pp_heap(Pp* pp) { return (Heap*)pp->c->env->heap; }
+static inline Heap* pp_heap(Pp* pp) { return cfree_compiler_heap(pp->c); }
static inline void* pp_xrealloc(Pp* pp, void* p, size_t old_n, size_t new_n,
- size_t align) {
+ size_t align) {
Heap* h = pp_heap(pp);
void* q = h->realloc(h, p, old_n, new_n, align);
if (!q) compiler_panic(pp->c, (SrcLoc){0, 0, 0}, "pp: out of memory");
@@ -195,7 +192,7 @@ static inline void tv_grow(Pp* pp, TokVec* v, u32 want) {
nc = v->cap ? v->cap * 2 : 8;
while (nc < want) nc *= 2;
{
- Tok* nb = arena_array(&pp->arena, Tok, nc);
+ Tok* nb = arena_array(pp->arena, Tok, nc);
if (v->n) memcpy(nb, v->data, sizeof(Tok) * v->n);
v->data = nb;
v->cap = nc;
@@ -219,7 +216,7 @@ static inline void cb_append(Pp* pp, CharBuf* b, const char* s, u32 n) {
u32 nc = b->cap ? b->cap * 2 : 64;
while (nc < b->len + n) nc *= 2;
{
- char* nb = (char*)arena_alloc(&pp->arena, nc, 1);
+ char* nb = (char*)arena_alloc(pp->arena, nc, 1);
if (b->len) memcpy(nb, b->data, b->len);
b->data = nb;
b->cap = nc;
@@ -250,11 +247,11 @@ Tok pp_next_raw(Pp* pp);
/* --- pp_expand.c → pp.c, pp_directive.c --- */
HidesetId hs_add(Pp* pp, HidesetId id, Sym s);
-int hs_contains(Pp* pp, HidesetId id, Sym s);
-Macro* mt_get(Pp* pp, Sym name);
-void mt_put(Pp* pp, Sym name, Macro* m);
-void mt_del(Pp* pp, Sym name);
-void expand_arg_to_eof(Pp* pp, Tok* in, u32 nin, TokVec* out);
+int hs_contains(Pp* pp, HidesetId id, Sym s);
+Macro* mt_get(Pp* pp, Sym name);
+void mt_put(Pp* pp, Sym name, Macro* m);
+void mt_del(Pp* pp, Sym name);
+void expand_arg_to_eof(Pp* pp, Tok* in, u32 nin, TokVec* out);
/* --- pp_directive.c → pp_expand.c --- */
i64 eval_if_expr(Pp* pp, const Tok* line, u32 n, SrcLoc loc);
@@ -262,8 +259,8 @@ void process_directive(Pp* pp, SrcLoc hash_loc);
/* --- pp_directive.c internal helpers called from pp_expand.c --- */
void emit_pragma_line(Pp* pp, const Tok* line, u32 n, SrcLoc loc);
-int peek_for_invoke_paren(Pp* pp, int* ws_has_space_out);
-int try_expand_pragma_op(Pp* pp, const Tok* invoke);
+int peek_for_invoke_paren(Pp* pp, int* ws_has_space_out);
+int try_expand_pragma_op(Pp* pp, const Tok* invoke);
/* --- pp_directive.c: read_directive_line (used by pp.c/pp_define) --- */
void read_directive_line(Pp* pp, Tok** out_toks, u32* out_n);
diff --git a/lang/c/type/type.c b/lang/c/type/type.c
@@ -21,9 +21,6 @@
#include <stdint.h>
#include <string.h>
-#include "core/arena.h"
-#include "core/pool.h"
-
#define NUM_PRIM_KINDS ((unsigned)TY_LDOUBLE + 1u)
typedef struct TypeListNode TypeListNode;
@@ -44,7 +41,7 @@ typedef struct PoolTypeCache {
static PoolTypeCache* cache_get(Pool* p) {
PoolTypeCache* c = (PoolTypeCache*)p->type_cache;
if (c) return c;
- c = arena_new(&p->arena, PoolTypeCache);
+ c = arena_new(p->arena, PoolTypeCache);
if (!c) return NULL;
memset(c, 0, sizeof *c);
c->next_tag = 1;
@@ -53,7 +50,7 @@ static PoolTypeCache* cache_get(Pool* p) {
}
static Type* alloc_type_node(Pool* p, PoolTypeCache* c) {
- TypeListNode* n = arena_new(&p->arena, TypeListNode);
+ TypeListNode* n = arena_new(p->arena, TypeListNode);
if (!n) return NULL;
memset(n, 0, sizeof *n);
n->next = c->derived;
@@ -140,7 +137,7 @@ const Type* type_func(Pool* p, const Type* ret, const Type** params, u16 n,
t->fn.nparams = n;
t->fn.variadic = (u8)(variadic ? 1 : 0);
if (n) {
- const Type** dst = arena_array(&p->arena, const Type*, n);
+ const Type** dst = arena_array(p->arena, const Type*, n);
if (!dst) return NULL;
for (u16 i = 0; i < n; ++i) dst[i] = params[i];
t->fn.params = dst;
@@ -207,7 +204,7 @@ TypeRecordBuilder* type_record_begin(Pool* p, TypeKind kind, TagId tag_id,
TypeRecordBuilder* type_record_begin_ex(Pool* p, TypeKind kind, TagId tag_id,
Sym tag, TypeRecordOpts opts) {
- TypeRecordBuilder* b = arena_new(&p->arena, TypeRecordBuilder);
+ TypeRecordBuilder* b = arena_new(p->arena, TypeRecordBuilder);
if (!b) return NULL;
memset(b, 0, sizeof *b);
b->pool = p;
@@ -221,7 +218,7 @@ TypeRecordBuilder* type_record_begin_ex(Pool* p, TypeKind kind, TagId tag_id,
void type_record_field(TypeRecordBuilder* b, Field f) {
if (b->nfields == b->cap) {
u32 nc = b->cap ? b->cap * 2 : 4;
- Field* nf = arena_array(&b->pool->arena, Field, nc);
+ Field* nf = arena_array(b->pool->arena, Field, nc);
if (!nf) return;
if (b->fields) memcpy(nf, b->fields, sizeof(Field) * b->nfields);
b->fields = nf;
@@ -350,8 +347,10 @@ int type_is_ptr(const Type* t) { return t && t->kind == TY_PTR; }
static CfreeCgTypeId type_cg_builtin(CfreeCompiler* c, TypeKind kind) {
CfreeCgBuiltinTypes b = cfree_cg_builtin_types(c);
switch (kind) {
- case TY_VOID: return b.id[CFREE_CG_BUILTIN_VOID];
- case TY_BOOL: return b.id[CFREE_CG_BUILTIN_BOOL];
+ case TY_VOID:
+ return b.id[CFREE_CG_BUILTIN_VOID];
+ case TY_BOOL:
+ return b.id[CFREE_CG_BUILTIN_BOOL];
case TY_CHAR:
case TY_SCHAR:
case TY_UCHAR:
@@ -370,7 +369,8 @@ static CfreeCgTypeId type_cg_builtin(CfreeCompiler* c, TypeKind kind) {
case TY_INT128:
case TY_UINT128:
return b.id[CFREE_CG_BUILTIN_I128];
- case TY_FLOAT: return b.id[CFREE_CG_BUILTIN_F32];
+ case TY_FLOAT:
+ return b.id[CFREE_CG_BUILTIN_F32];
case TY_DOUBLE:
case TY_LDOUBLE:
return b.id[CFREE_CG_BUILTIN_F64];
@@ -380,7 +380,7 @@ static CfreeCgTypeId type_cg_builtin(CfreeCompiler* c, TypeKind kind) {
return CFREE_CG_TYPE_NONE;
}
-static CfreeCgTypeId type_cg_id_walk(CfreeCompiler* c, const Type* t,
+static CfreeCgTypeId type_cg_id_walk(CfreeCompiler* c, Pool* p, const Type* t,
const Type* pending_record) {
CfreeCgTypeId id;
if (!c || !t) return CFREE_CG_TYPE_NONE;
@@ -390,28 +390,27 @@ static CfreeCgTypeId type_cg_id_walk(CfreeCompiler* c, const Type* t,
case TY_PTR: {
const Type* pointee = t->ptr.pointee;
if (pointee == pending_record) {
- pointee = type_void(c->global);
+ pointee = type_void(p);
}
- return cfree_cg_type_ptr(c, type_cg_id_walk(c, pointee, pending_record),
- 0);
+ return cfree_cg_type_ptr(
+ c, type_cg_id_walk(c, p, pointee, pending_record), 0);
}
case TY_ARRAY:
- return cfree_cg_type_array(c, type_cg_id_walk(c, t->arr.elem,
- pending_record),
- t->arr.count);
+ return cfree_cg_type_array(
+ c, type_cg_id_walk(c, p, t->arr.elem, pending_record), t->arr.count);
case TY_FUNC: {
CfreeCgParam* params = NULL;
CfreeCgFuncSig sig;
memset(&sig, 0, sizeof sig);
- sig.ret = type_cg_id_walk(c, t->fn.ret, pending_record);
+ sig.ret = type_cg_id_walk(c, p, t->fn.ret, pending_record);
sig.nparams = t->fn.nparams;
sig.abi_variadic = t->fn.variadic;
sig.call_conv = CFREE_CG_CC_TARGET_C;
if (t->fn.nparams) {
- params = arena_zarray(c->tu, CfreeCgParam, t->fn.nparams);
+ params = arena_zarray(p->arena, CfreeCgParam, t->fn.nparams);
for (u32 i = 0; i < t->fn.nparams; ++i) {
params[i].type =
- type_cg_id_walk(c, t->fn.params[i], pending_record);
+ type_cg_id_walk(c, p, t->fn.params[i], pending_record);
}
}
sig.params = params;
@@ -422,10 +421,10 @@ static CfreeCgTypeId type_cg_id_walk(CfreeCompiler* c, const Type* t,
CfreeCgField* fields = NULL;
CfreeCgRecordDesc desc;
if (t->rec.nfields) {
- fields = arena_zarray(c->tu, CfreeCgField, t->rec.nfields);
+ fields = arena_zarray(p->arena, CfreeCgField, t->rec.nfields);
for (u32 i = 0; i < t->rec.nfields; ++i) {
fields[i].name = t->rec.fields[i].name;
- fields[i].type = type_cg_id_walk(c, t->rec.fields[i].type, t);
+ fields[i].type = type_cg_id_walk(c, p, t->rec.fields[i].type, t);
fields[i].align_override = t->rec.fields[i].align_override;
if (t->rec.fields[i].packed && fields[i].align_override == 0) {
fields[i].align_override = 1;
@@ -444,10 +443,9 @@ static CfreeCgTypeId type_cg_id_walk(CfreeCompiler* c, const Type* t,
return cfree_cg_type_record_ex(c, &desc);
}
case TY_ENUM:
- return cfree_cg_type_enum(c, t->enm.tag,
- type_cg_id_walk(c, t->enm.base,
- pending_record),
- NULL, 0);
+ return cfree_cg_type_enum(
+ c, t->enm.tag, type_cg_id_walk(c, p, t->enm.base, pending_record),
+ NULL, 0);
default:
if (id != CFREE_CG_TYPE_NONE) {
return cfree_cg_type_alias(c, 0, id);
@@ -456,6 +454,16 @@ static CfreeCgTypeId type_cg_id_walk(CfreeCompiler* c, const Type* t,
}
}
+CfreeCgTypeId type_cg_id_in_pool(CfreeCompiler* c, Pool* p, const Type* t) {
+ if (!p) return CFREE_CG_TYPE_NONE;
+ return type_cg_id_walk(c, p, t, NULL);
+}
+
CfreeCgTypeId type_cg_id(CfreeCompiler* c, const Type* t) {
- return type_cg_id_walk(c, t, NULL);
+ CfreeCgTypeId id;
+ Pool* p = c_pool_new(c);
+ if (!p) return CFREE_CG_TYPE_NONE;
+ id = type_cg_id_in_pool(c, p, t);
+ c_pool_free(p);
+ return id;
}
diff --git a/lang/c/type/type.h b/lang/c/type/type.h
@@ -3,8 +3,7 @@
#include <cfree/cg.h>
-#include "core/core.h"
-#include "core/pool.h"
+#include "c_support.h"
typedef enum TypeKind {
TY_VOID,
@@ -151,8 +150,8 @@ typedef struct TypeRecordOpts {
* options on the builder; type_record_end copies them to Type.rec. The
* plain type_record_begin is equivalent to passing a zeroed
* TypeRecordOpts. */
-TypeRecordBuilder* type_record_begin_ex(Pool*, TypeKind kind, TagId,
- Sym tag, TypeRecordOpts);
+TypeRecordBuilder* type_record_begin_ex(Pool*, TypeKind kind, TagId, Sym tag,
+ TypeRecordOpts);
void type_record_field(TypeRecordBuilder*, Field);
const Type* type_record_end(Pool*, TypeRecordBuilder*);
/* Forward-declared struct/union: returns a mutable, incomplete Type with the
@@ -170,6 +169,7 @@ int type_is_arith(const Type*);
int type_is_int(const Type*);
int type_is_ptr(const Type*);
+CfreeCgTypeId type_cg_id_in_pool(CfreeCompiler*, Pool*, const Type*);
CfreeCgTypeId type_cg_id(CfreeCompiler*, const Type*);
#endif
diff --git a/src/api/frontend.c b/src/api/frontend.c
@@ -0,0 +1,133 @@
+#include <cfree/frontend.h>
+#include <setjmp.h>
+#include <stdarg.h>
+#include <string.h>
+
+#include "core/arena.h"
+#include "core/core.h"
+#include "core/pool.h"
+
+struct CfreeArena {
+ Arena inner;
+};
+
+CfreeArena* cfree_arena_new(CfreeHeap* h, size_t block_size) {
+ CfreeArena* a;
+ if (!h) return NULL;
+ a = (CfreeArena*)h->alloc(h, sizeof(*a), _Alignof(CfreeArena));
+ if (!a) return NULL;
+ arena_init(&a->inner, (Heap*)h, block_size);
+ return a;
+}
+
+void cfree_arena_free(CfreeArena* a) {
+ CfreeHeap* h;
+ if (!a) return;
+ h = a->inner.heap;
+ arena_fini(&a->inner);
+ h->free(h, a, sizeof(*a));
+}
+
+void cfree_arena_reset(CfreeArena* a) {
+ if (a) arena_reset(&a->inner);
+}
+
+void* cfree_arena_alloc(CfreeArena* a, size_t size, size_t align) {
+ return a ? arena_alloc(&a->inner, size, align) : NULL;
+}
+
+void* cfree_arena_zalloc(CfreeArena* a, size_t size, size_t align) {
+ return a ? arena_zalloc(&a->inner, size, align) : NULL;
+}
+
+char* cfree_arena_strdup(CfreeArena* a, const char* s, size_t len) {
+ return a ? arena_strdup(&a->inner, s, len) : NULL;
+}
+
+CfreeHeap* cfree_compiler_heap(CfreeCompiler* c) {
+ return (c && c->env) ? (CfreeHeap*)c->env->heap : NULL;
+}
+
+const CfreeFileIO* cfree_compiler_file_io(CfreeCompiler* c) {
+ return (c && c->env) ? c->env->file_io : NULL;
+}
+
+int64_t cfree_compiler_now(CfreeCompiler* c) {
+ return (c && c->env) ? c->env->now : -1;
+}
+
+CfreeSym cfree_sym_intern_len(CfreeCompiler* c, const char* str, size_t len) {
+ if (!c || !str || len == 0) return 0;
+ return pool_intern(c->global, str, len);
+}
+
+const char* cfree_sym_str(CfreeCompiler* c, CfreeSym sym, size_t* len_out) {
+ if (!c) {
+ if (len_out) *len_out = 0;
+ return NULL;
+ }
+ return pool_str(c->global, (Sym)sym, len_out);
+}
+
+uint32_t cfree_source_add_file(CfreeCompiler* c, const char* path,
+ int system_header) {
+ return c ? source_add_file(c->sources, path, system_header) : 0;
+}
+
+uint32_t cfree_source_add_memory(CfreeCompiler* c, const char* name) {
+ return c ? source_add_memory(c->sources, name) : 0;
+}
+
+uint32_t cfree_source_add_builtin(CfreeCompiler* c, const char* name) {
+ return c ? source_add_builtin(c->sources, name) : 0;
+}
+
+void cfree_source_add_include(CfreeCompiler* c, uint32_t includer_file_id,
+ uint32_t included_file_id, CfreeSrcLoc loc,
+ int system) {
+ if (!c) return;
+ source_add_include(c->sources, includer_file_id, included_file_id, loc,
+ system);
+}
+
+int cfree_source_file(CfreeCompiler* c, uint32_t file_id,
+ CfreeSourceFile* out) {
+ const SourceFile* f;
+ if (!c || !out) return 1;
+ f = source_file(c->sources, file_id);
+ if (!f) return 1;
+ memset(out, 0, sizeof *out);
+ out->id = f->id;
+ out->name = f->name;
+ out->path = f->path;
+ out->kind = f->kind;
+ out->system_header = f->system_header;
+ return 0;
+}
+
+int cfree_frontend_run(CfreeCompiler* c, CfreeFrontendRunFn fn, void* user) {
+ PanicSave saved;
+ int rc;
+ if (!c || !fn) return 1;
+ compiler_panic_save(c, &saved);
+ if (setjmp(c->panic)) {
+ compiler_run_cleanups(c);
+ compiler_panic_restore(c, &saved);
+ return 1;
+ }
+ rc = fn(c, user);
+ compiler_panic_restore(c, &saved);
+ return rc;
+}
+
+void cfree_frontend_fatal(CfreeCompiler* c, CfreeSrcLoc loc, const char* fmt,
+ ...) {
+ va_list ap;
+ va_start(ap, fmt);
+ cfree_frontend_vfatal(c, loc, fmt, ap);
+}
+
+void cfree_frontend_vfatal(CfreeCompiler* c, CfreeSrcLoc loc, const char* fmt,
+ va_list ap) {
+ compiler_panicv((Compiler*)c, loc, fmt, ap);
+}
diff --git a/src/core/hashmap.h b/src/core/hashmap.h
@@ -1,202 +1,12 @@
-#ifndef CFREE_HASHMAP_H
-#define CFREE_HASHMAP_H
+#ifndef CFREE_INTERNAL_HASHMAP_H
+#define CFREE_INTERNAL_HASHMAP_H
-/* Generic open-addressed hashmap as a typed-macro template.
- *
- * Linear probing; doubling rehash at 75% load. Tombstoneless deletion
- * via cluster rehash. Empty-key sentinel is 0 — slots are zero-initialized
- * by allocation, and callers must never insert a key whose value compares
- * equal to 0. (Sym=0 already means "none" per core.h:42; OBJ_SEC_NONE=0;
- * pointer keys avoid 0 by construction.)
- *
- * HASHMAP_DEFINE(NAME, KT, VT, HASH_FN)
- * NAME — struct typedef name for this instance.
- * KT — key type (must support `== 0` and `==` against another KT).
- * VT — value type (any assignable type).
- * HASH_FN — function-like expression mapping KT -> u32.
- *
- * Emits typedef NAME, NAME##Slot, and these static functions:
- * void NAME##_init (NAME*, Heap*) — default initial cap
- * void NAME##_init_cap(NAME*, Heap*, u32 cap) — caller picks initial
- * cap void NAME##_fini (NAME*) VT* NAME##_get (const NAME*, KT) —
- * NULL if absent int NAME##_set (NAME*, KT, VT) — 1
- * inserted, 0 updated void NAME##_del (NAME*, KT) — no-op
- * if absent
- *
- * Equality is `==` on KT. That covers all keys we use (Sym which is u32,
- * u64 guest_pc). A string-keyed instance would need a small extension.
- *
- * Built-in mixers below cover u32 (hash_u32) and u64 (hash_u64) keys. */
-
-#include <string.h>
+#include <cfree/hashmap.h>
#include "core/core.h"
-#include "core/heap.h"
-
-/* xorshift mixer suitable for dense u32 keys (interned Sym ids etc.). */
-static inline u32 hash_u32(u32 x) {
- x += 0x9e3779b9u;
- x ^= x >> 16;
- x *= 0x7feb352du;
- x ^= x >> 15;
- x *= 0x846ca68bu;
- x ^= x >> 16;
- return x;
-}
-
-/* SplitMix-style mixer for u64 keys (e.g. guest PC). */
-static inline u32 hash_u64(u64 x) {
- x ^= x >> 33;
- x *= 0xff51afd7ed558ccdULL;
- x ^= x >> 33;
- x *= 0xc4ceb9fe1a85ec53ULL;
- x ^= x >> 33;
- return (u32)x;
-}
-
-#define HASHMAP_LOAD_NUM 3u
-#define HASHMAP_LOAD_DEN 4u
-#define HASHMAP_INIT_CAP 16u
-#define HASHMAP_DEFINE(NAME, KT, VT, HASH_FN) \
- typedef struct NAME##Slot { \
- KT k; \
- VT v; \
- } NAME##Slot; \
- typedef struct NAME { \
- Heap* heap; \
- NAME##Slot* slots; \
- u32 cap; \
- u32 used; \
- } NAME; \
- \
- __attribute__((unused)) static void NAME##_resize(NAME* m, u32 new_cap) { \
- NAME##Slot* fresh; \
- u32 i, mask; \
- fresh = (NAME##Slot*)m->heap->alloc(m->heap, sizeof(*fresh) * new_cap, \
- _Alignof(NAME##Slot)); \
- if (!fresh) return; \
- memset(fresh, 0, sizeof(*fresh) * new_cap); \
- mask = new_cap - 1u; \
- for (i = 0; i < m->cap; ++i) { \
- KT k = m->slots[i].k; \
- u32 j; \
- if (!(k)) continue; \
- j = HASH_FN(k) & mask; \
- while (fresh[j].k) j = (j + 1u) & mask; \
- fresh[j] = m->slots[i]; \
- } \
- if (m->slots) \
- m->heap->free(m->heap, m->slots, sizeof(*m->slots) * m->cap); \
- m->slots = fresh; \
- m->cap = new_cap; \
- } \
- \
- __attribute__((unused)) static inline void NAME##_init_cap(NAME* m, Heap* h, \
- u32 cap) { \
- m->heap = h; \
- m->slots = NULL; \
- m->cap = 0; \
- m->used = 0; \
- if (cap) NAME##_resize(m, cap); \
- } \
- \
- __attribute__((unused)) static inline void NAME##_init(NAME* m, Heap* h) { \
- NAME##_init_cap(m, h, HASHMAP_INIT_CAP); \
- } \
- \
- __attribute__((unused)) static inline void NAME##_fini(NAME* m) { \
- if (m->slots) \
- m->heap->free(m->heap, m->slots, sizeof(*m->slots) * m->cap); \
- m->slots = NULL; \
- m->cap = m->used = 0; \
- } \
- \
- __attribute__((unused)) static inline VT* NAME##_get(const NAME* m, KT k) { \
- u32 mask, j; \
- if (m->cap == 0 || !(k)) return NULL; \
- mask = m->cap - 1u; \
- j = HASH_FN(k) & mask; \
- while (m->slots[j].k) { \
- if (m->slots[j].k == (k)) return &m->slots[j].v; \
- j = (j + 1u) & mask; \
- } \
- return NULL; \
- } \
- \
- __attribute__((unused)) static inline int NAME##_set(NAME* m, KT k, VT v) { \
- u32 mask, j; \
- if (m->cap == 0 || \
- m->used * HASHMAP_LOAD_DEN >= m->cap * HASHMAP_LOAD_NUM) \
- NAME##_resize(m, m->cap ? m->cap * 2u : HASHMAP_INIT_CAP); \
- mask = m->cap - 1u; \
- j = HASH_FN(k) & mask; \
- while (m->slots[j].k) { \
- if (m->slots[j].k == (k)) { \
- m->slots[j].v = (v); \
- return 0; \
- } \
- j = (j + 1u) & mask; \
- } \
- m->slots[j].k = (k); \
- m->slots[j].v = (v); \
- m->used++; \
- return 1; \
- } \
- \
- /* Insert if absent. Returns 1 if newly inserted; 0 if k was present \
- * (in that case writes the existing value to *existing_out when \
- * existing_out is non-NULL). */ \
- __attribute__((unused)) static inline int NAME##_try_insert( \
- NAME* m, KT k, VT v, VT* existing_out) { \
- u32 mask, j; \
- if (m->cap == 0 || \
- m->used * HASHMAP_LOAD_DEN >= m->cap * HASHMAP_LOAD_NUM) \
- NAME##_resize(m, m->cap ? m->cap * 2u : HASHMAP_INIT_CAP); \
- mask = m->cap - 1u; \
- j = HASH_FN(k) & mask; \
- while (m->slots[j].k) { \
- if (m->slots[j].k == (k)) { \
- if (existing_out) *existing_out = m->slots[j].v; \
- return 0; \
- } \
- j = (j + 1u) & mask; \
- } \
- m->slots[j].k = (k); \
- m->slots[j].v = (v); \
- m->used++; \
- return 1; \
- } \
- \
- __attribute__((unused)) static inline void NAME##_del(NAME* m, KT k) { \
- u32 mask, j; \
- if (m->cap == 0 || !(k)) return; \
- mask = m->cap - 1u; \
- j = HASH_FN(k) & mask; \
- while (m->slots[j].k) { \
- if (m->slots[j].k == (k)) { \
- u32 i = (j + 1u) & mask; \
- m->slots[j].k = 0; \
- m->used--; \
- while (m->slots[i].k) { \
- KT rk = m->slots[i].k; \
- VT rv = m->slots[i].v; \
- u32 nh; \
- m->slots[i].k = 0; \
- m->used--; \
- nh = HASH_FN(rk) & mask; \
- while (m->slots[nh].k) nh = (nh + 1u) & mask; \
- m->slots[nh].k = rk; \
- m->slots[nh].v = rv; \
- m->used++; \
- i = (i + 1u) & mask; \
- } \
- return; \
- } \
- j = (j + 1u) & mask; \
- } \
- } \
- /* trailing struct decl swallows the macro-call's semicolon */ \
- struct NAME
+#define hash_u32 cfree_hash_u32
+#define hash_u64 cfree_hash_u64
+#define HASHMAP_DEFINE CFREE_HASHMAP_DEFINE
#endif