kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

parse_priv.h (24044B)


      1 /* parse_priv.h — private header shared across parse_*.c modules.
      2  *
      3  * Declares: Parser struct, shared types (Scope, SymEntry, TagEntry,
      4  * DeclSpecs, TypeSpecAccum, CKw, TagDeclKind), forward decls of
      5  * cross-module functions, and inline/shared helpers. */
      6 
      7 #pragma once
      8 
      9 #include <kit/support/hashmap.h>
     10 #include <kit/support/symtab.h>
     11 #include <stdarg.h>
     12 #include <string.h>
     13 
     14 #include "abi/c_abi.h"
     15 #include "decl/decl.h"
     16 #include "decl/decl_attrs.h"
     17 #include "lex/lex.h"
     18 #include "parse/attr.h"
     19 #include "parse/parse.h"
     20 #include "pp/pp.h"
     21 #include "sem/sem.h"
     22 #include "type/type.h"
     23 
     24 /* ============================================================
     25  * Keywords
     26  * ============================================================ */
     27 typedef enum CKw {
     28   KW_NONE = 0,
     29   KW_AUTO,
     30   KW_BREAK,
     31   KW_CASE,
     32   KW_CHAR,
     33   KW_CONST,
     34   KW_CONTINUE,
     35   KW_DEFAULT,
     36   KW_DO,
     37   KW_DOUBLE,
     38   KW_ELSE,
     39   KW_ENUM,
     40   KW_EXTERN,
     41   KW_FLOAT,
     42   KW_FLOAT16, /* _Float16 */
     43   KW_FOR,
     44   KW_GOTO,
     45   KW_IF,
     46   KW_INLINE,
     47   KW_INT,
     48   KW_LONG,
     49   KW_REGISTER,
     50   KW_RESTRICT,
     51   KW_RETURN,
     52   KW_SHORT,
     53   KW_SIGNED,
     54   KW_SIZEOF,
     55   KW_STATIC,
     56   KW_STRUCT,
     57   KW_SWITCH,
     58   KW_TYPEDEF,
     59   KW_UNION,
     60   KW_UNSIGNED,
     61   KW_VOID,
     62   KW_VOLATILE,
     63   KW_WHILE,
     64   KW_BOOL,          /* _Bool */
     65   KW_COMPLEX,       /* _Complex */
     66   KW_IMAGINARY,     /* _Imaginary */
     67   KW_ALIGNAS,       /* _Alignas */
     68   KW_ALIGNOF,       /* _Alignof */
     69   KW_ATOMIC,        /* _Atomic */
     70   KW_GENERIC,       /* _Generic */
     71   KW_NORETURN,      /* _Noreturn */
     72   KW_STATIC_ASSERT, /* _Static_assert */
     73   KW_THREAD_LOCAL,  /* _Thread_local */
     74   KW_ASM,           /* GNU `asm` */
     75   KW_BUILTIN_ASM,   /* GNU `__asm__` */
     76   KW_COUNT
     77 } CKw;
     78 
     79 /* ============================================================
     80  * Scope stack types
     81  * ============================================================ */
     82 
     83 typedef enum SymEntryKind {
     84   SEK_LOCAL,    /* local variable or parameter source handle */
     85   SEK_GLOBAL,   /* global var, OPK_GLOBAL via ObjSymId */
     86   SEK_FUNC,     /* function decl, OPK_GLOBAL via ObjSymId */
     87   SEK_TYPEDEF,  /* typedef name */
     88   SEK_ENUM_CST, /* enumeration constant */
     89 } SymEntryKind;
     90 
     91 typedef struct SymEntry SymEntry;
     92 typedef struct VLABound VLABound;
     93 typedef struct StaticReloc StaticReloc;
     94 struct VLABound {
     95   const Type* array_ty;
     96   FrameSlot byte_slot;
     97   FrameSlot count_slot;
     98   VLABound* next;
     99 };
    100 
    101 typedef struct ParamVLABoundExpr ParamVLABoundExpr;
    102 struct ParamVLABoundExpr {
    103   Tok* toks;
    104   u32 ntoks;
    105   u8 has_expr;
    106   u8 pad[3];
    107 };
    108 
    109 struct StaticReloc {
    110   u32 offset;
    111   u32 size;
    112   ObjSymId target; /* symbol target when is_label == 0 */
    113   i64 addend;
    114   CGLabel label; /* label target when is_label != 0 */
    115   u8 is_label;   /* 1 -> label-address reloc (&&label), 0 -> symbol reloc */
    116   u8 pad[3];
    117 };
    118 
    119 struct SymEntry {
    120   Sym name;
    121   u8 kind;    /* SymEntryKind */
    122   u8 defined; /* compatibility alias for decl_state >= DSTATE_DEFINED */
    123   u8 decl_state;
    124   u8 storage; /* DeclStorage */
    125   u8 linkage; /* DeclLinkage */
    126   u8 pad[3];
    127   DeclId decl_id;
    128   u32 decl_flags;
    129   const Type* type;
    130   union {
    131     FrameSlot slot;
    132     ObjSymId sym;
    133     i64 enum_value;
    134   } v;
    135   FrameSlot vla_byte_slot;
    136   VLABound* vla_bounds;
    137   struct Attr* attrs;
    138   /* For a `register T x __asm__("reg")` local: the interned hard-register name
    139    * ("r10", "x8", ...) the variable is bound to. Pins x to that register when
    140    * used as an inline-asm operand (GNU explicit register variables). 0 = none.
    141    */
    142   Sym reg_asm_name;
    143   SymEntry* next;
    144   /* The binding that was current for this entry's name (in the innermost
    145    * visible scope) at the moment this entry was defined; 0 = none. The
    146    * Sym-keyed BindingTab cache on Parser restores bind[name] = shadowed when
    147    * this entry's scope is popped, so scope_lookup is one array load instead of
    148    * a scope-chain walk. memset-0 by scope_define/_checked, so default is NULL.
    149    */
    150   SymEntry* shadowed;
    151 };
    152 
    153 typedef struct TagEntry TagEntry;
    154 struct TagEntry {
    155   Sym name;
    156   u8 kind; /* TagDeclKind */
    157   u8 complete;
    158   u16 pad;
    159   Type* type;
    160   struct Attr* attrs;
    161   TagEntry* next;
    162 };
    163 
    164 /* Name -> entry indexes, keyed on the interned Sym (Sym 0 = "none" doubles as
    165  * the hashmap empty sentinel). Each scope keeps its LIFO list as the source of
    166  * truth and ordering, and lazily builds an index once it grows past
    167  * SCOPE_INDEX_THRESHOLD, so the O(n^2) "scan the whole scope per declaration"
    168  * cost (file scopes with thousands of globals/typedefs, functions with
    169  * thousands of locals) collapses to O(1) average lookups while tiny block
    170  * scopes stay on the cheap linear list. The maps allocate through the pool's
    171  * shared arena-heap facade (Pool.arena_heap) so there is nothing to free. */
    172 KIT_HASHMAP_DEFINE(SymEntryMap, Sym, SymEntry*, kit_hash_u32);
    173 KIT_HASHMAP_DEFINE(TagEntryMap, Sym, TagEntry*, kit_hash_u32);
    174 KIT_HASHMAP_DEFINE(ExternalFuncMap, Sym, SymEntry*, kit_hash_u32);
    175 
    176 /* Interned keyword/alias Sym -> CKw (stored as u8), built once in parse_c.
    177  * Sym-indexed dense table: classifying an identifier is one in-range load,
    178  * no hashing. Most identifiers in a body are interned after the keyword set
    179  * (higher Sym than kw_cap), so they classify as KW_NONE without even a load.
    180  * Storage comes from the pool's shared arena-heap facade (Pool.arena_heap). */
    181 KIT_SYMTAB_DEFINE(KwTab, u8);
    182 
    183 /* Interned identifier Sym -> the SymEntry currently visible for that name (the
    184  * innermost binding a scope-chain walk would return), or NULL when unbound.
    185  * scope_define/_checked maintain it (newest define wins, prior saved in
    186  * SymEntry.shadowed); scope_pop unwinds it. Lets scope_lookup be a single
    187  * in-range load instead of a per-nesting-level scope_entries_find walk. Storage
    188  * comes from the pool's shared arena-heap facade (Pool.arena_heap). */
    189 KIT_SYMTAB_DEFINE(BindingTab, SymEntry*);
    190 
    191 typedef struct Scope Scope;
    192 struct Scope {
    193   SymEntry* entries; /* LIFO */
    194   TagEntry* tags;    /* LIFO */
    195   Scope* parent;
    196   u32 saved_vla_mark;
    197   u32 nentries; /* count in `entries`; index built once it exceeds threshold */
    198   u32 ntags;    /* count in `tags`; index built once it exceeds threshold */
    199   SymEntryMap emap; /* name -> entry; active (cap != 0) once built */
    200   TagEntryMap tmap; /* name -> tag;   active (cap != 0) once built */
    201 };
    202 
    203 /* ============================================================
    204  * Switch/goto control-flow types
    205  * ============================================================ */
    206 
    207 typedef struct CaseEntry CaseEntry;
    208 struct CaseEntry {
    209   i64 value;
    210   CGLabel label;
    211   CaseEntry* next;
    212 };
    213 
    214 typedef struct SwitchCtx SwitchCtx;
    215 struct SwitchCtx {
    216   CaseEntry* cases;
    217   CGLabel default_label;
    218   FrameSlot value_slot;
    219   const Type* value_type;
    220   SwitchCtx* parent;
    221 };
    222 
    223 typedef struct GotoLabel GotoLabel;
    224 struct GotoLabel {
    225   Sym name;
    226   CGLabel label;
    227   u8 placed;
    228   u8 addr_taken; /* set when &&label is used (labels-as-values) */
    229   u8 pad[2];
    230   SrcLoc first_use;
    231   u32 min_forward_vla_mark;
    232   u32 label_vla_mark;
    233   GotoLabel* next;
    234 };
    235 
    236 /* ============================================================
    237  * Parser context
    238  * ============================================================ */
    239 
    240 typedef struct Parser {
    241   Compiler* c;
    242   Pp* pp;
    243   DeclTable* decls;
    244   CG* cg;
    245   KitCompiler* abi;
    246   Pool* pool;
    247   u8 default_visibility; /* SymVis */
    248   u8 auto_var_init;      /* KitAutoVarInit: implicit init for uninit locals */
    249   u8 general_regs_only;  /* -mgeneral-regs-only: reject C FP constructs */
    250   u8 stack_protector_mode;    /* KitStackProtectorMode */
    251   u8 stack_protector_enabled; /* selected current function */
    252   u8 stack_protector_scan;    /* semantic selection-only body pass */
    253   u8 stack_protector_scan_selected;
    254   u8 stack_protector_preselected;
    255 
    256   Tok cur;
    257   Tok next;
    258   int has_next;
    259 
    260   Tok pending;
    261   int has_pending;
    262 
    263   Sym kw_sym[KW_COUNT];
    264   KwTab kw_map; /* keyword/alias Sym -> CKw; built once, see ident_kw_inline */
    265 
    266   Sym sym_b_alloca;
    267   Sym sym_b_ctz;
    268   Sym sym_b_ctzl;
    269   Sym sym_b_ctzll;
    270   Sym sym_b_clz;
    271   Sym sym_b_clzl;
    272   Sym sym_b_clzll;
    273   Sym sym_b_trap;
    274   Sym sym_b_unreachable;
    275   Sym sym_b_memcpy;
    276   Sym sym_b_memmove;
    277   Sym sym_b_memcmp;
    278   Sym sym_b_memset;
    279   Sym sym_b_clear_cache;
    280   Sym sym_b_isnan;
    281   Sym sym_b_fabs;
    282   Sym sym_b_fabsf;
    283   Sym sym_b_fabsl;
    284   Sym sym_b_inf;
    285   Sym sym_b_inff;
    286   Sym sym_b_infl;
    287   Sym sym_b_huge_val;
    288   Sym sym_b_huge_valf;
    289   Sym sym_b_huge_vall;
    290   Sym sym_b_nan;            /* __builtin_nan  */
    291   Sym sym_b_nanf;           /* __builtin_nanf */
    292   Sym sym_b_nanl;           /* __builtin_nanl */
    293   Sym sym_b_isless;         /* __builtin_isless */
    294   Sym sym_b_islessequal;    /* __builtin_islessequal */
    295   Sym sym_b_isgreater;      /* __builtin_isgreater */
    296   Sym sym_b_isgreaterequal; /* __builtin_isgreaterequal */
    297   Sym sym_b_islessgreater;  /* __builtin_islessgreater */
    298   Sym sym_b_isunordered;    /* __builtin_isunordered */
    299   Sym sym_func;             /* __func__ */
    300   Sym sym_func_gcc;         /* __FUNCTION__ */
    301   Sym sym_pretty_func_gcc;  /* __PRETTY_FUNCTION__ */
    302   Sym cur_func_name;        /* name of the function whose body we're in,
    303                              * 0 at file scope */
    304   u8 cur_func_emits;        /* the current function body is being emitted (a CG
    305                              * func was begun); 0 for whole-body-suppressed
    306                              * `extern inline` definitions. Distinct from the
    307                              * momentary `suppress_codegen` counter: goto labels
    308                              * persist across the whole body, so their CG-label
    309                              * ids must be real whenever the function emits, even
    310                              * if the first reference is in a transiently
    311                              * suppressed (constant-false) region. */
    312   const Type* cur_func_ret;
    313   Sym sym_b_expect;
    314   Sym sym_b_offsetof;
    315   Sym sym_b_constant_p; /* __builtin_constant_p */
    316   Sym sym_b_va_list;
    317   /* Cached singleton for __builtin_va_list — built lazily on first
    318    * mention so every occurrence resolves to the same Type* (and the
    319    * same TagId where applicable).  Without the cache, c_abi_va_list_type
    320    * mints a fresh struct type per occurrence and headers that pass
    321    * locally-declared __builtin_va_list values to functions taking
    322    * va_list (e.g. mingw's sec_api/stdio_s.h) fail type-equality. */
    323   const Type* type_b_va_list;
    324   Sym sym_b_va_start;
    325   Sym sym_b_va_arg;
    326   Sym sym_b_va_end;
    327   Sym sym_b_va_copy;
    328   Sym sym_b_return_address;   /* __builtin_return_address */
    329   Sym sym_b_frame_address;    /* __builtin_frame_address */
    330   Sym sym_b_readcyclecounter; /* __builtin_readcyclecounter */
    331   Sym sym_kit_syscall[7];     /* __kit_syscall0 .. __kit_syscall6 */
    332   Sym sym_attribute;
    333   Sym sym_volatile_alias;
    334   Sym sym_alignof_alias;
    335   Sym sym_typeof_alias;  /* __typeof */
    336   Sym sym_typeof_alias2; /* __typeof__ */
    337   Sym sym_asm_alias;
    338   Sym sym_inline_alias;
    339   Sym sym_inline_alias2;
    340   Sym sym_restrict_alias;
    341   Sym sym_restrict_alias2;
    342   Sym sym_thread_alias;
    343   Sym sym_int128;    /* __int128 */
    344   Sym sym_int128_t;  /* __int128_t */
    345   Sym sym_uint128_t; /* __uint128_t */
    346   Sym sym_a_load_n;
    347   Sym sym_a_store_n;
    348   Sym sym_a_exchange_n;
    349   Sym sym_a_fetch_add;
    350   Sym sym_a_fetch_sub;
    351   Sym sym_a_fetch_and;
    352   Sym sym_a_fetch_or;
    353   Sym sym_a_fetch_xor;
    354   Sym sym_a_fetch_nand;
    355   Sym sym_a_cas_n;
    356   Sym sym_a_always_lock_free;
    357   Sym sym_a_is_lock_free;
    358   Sym sym_a_thread_fence;
    359   Sym sym_a_signal_fence;
    360   Sym sym_sync_synchronize; /* __sync_synchronize (legacy full barrier) */
    361 
    362   Scope* scope;
    363   /* Sym -> innermost-visible binding cache; the O(1) read side of scope_lookup.
    364    * Maintained by scope_define/_checked (write) and scope_pop (restore). */
    365   BindingTab bind;
    366   /* name -> current file-scope function entry. Replaces what was an O(n) linear
    367    * list walked on every function declaration/reference. Storage comes from the
    368    * pool's shared arena-heap facade (Pool.arena_heap). */
    369   ExternalFuncMap external_funcs;
    370 
    371   CGLabel cur_break;
    372   CGLabel cur_continue;
    373 
    374   SwitchCtx* cur_switch;
    375 
    376   GotoLabel* goto_labels;
    377   /* Set once a computed `goto *expr;` has been emitted in the current
    378    * function. After this point taking a new label's address with `&&label`
    379    * is rejected, because each computed goto's target set is finalized when
    380    * it is emitted and a later address-taken label would not be in it. */
    381   u8 computed_goto_emitted;
    382 
    383   u8 vla_pending;
    384   FrameSlot vla_pending_count_slot;
    385   FrameSlot vla_pending_count_slots[8];
    386   u8 vla_pending_count_len;
    387   u32 vla_mark;
    388 
    389   FrameSlot last_pushed_vla_slot;
    390   VLABound* last_pushed_vla_bounds;
    391 
    392   u8 in_param_decl;
    393   ParamVLABoundExpr param_vla_bounds[8];
    394   u8 param_vla_bound_len;
    395   u32 suppress_codegen;
    396 
    397   u32 const_guard_depth;
    398   u32 const_guard_not_eval;
    399   const char* const_guard_error;
    400   SrcLoc const_guard_error_loc;
    401 
    402   u32 static_local_counter;
    403 
    404   u32 compound_literal_counter;
    405 
    406   Tok* replay;
    407   u32 replay_cap;
    408   u32 replay_len;
    409   u32 replay_pos;
    410   u8 replay_active;
    411 
    412   /* A function body is buffered once for the stack-protector selection pass
    413    * and replayed through the ordinary parser.  This is distinct from `replay`,
    414    * which initializer/type parsing may nest while consuming the body. */
    415   Tok* function_replay;
    416   u32 function_replay_len;
    417   u32 function_replay_pos;
    418   u8 function_replay_active;
    419   u8 function_replay_hold;
    420 
    421   StaticReloc* static_relocs;
    422   u32 static_relocs_len;
    423   u32 static_relocs_cap;
    424 } Parser;
    425 
    426 /* ============================================================
    427  * DeclSpecs and TypeSpecAccum
    428  * ============================================================ */
    429 
    430 typedef struct DeclSpecs {
    431   const Type* type;
    432   DeclStorage storage;
    433   u32 flags; /* DeclFlag */
    434   u16 quals;
    435   u8 storage_explicit;
    436   u8 pad;
    437   u32 align;
    438   FrameSlot vla_byte_slot;
    439   VLABound* vla_bounds;
    440   Attr* attrs;
    441 } DeclSpecs;
    442 
    443 typedef struct TypeSpecAccum {
    444   u8 saw_void;
    445   u8 saw_char;
    446   u8 saw_int;
    447   u8 saw_short;
    448   u8 long_count;
    449   u8 saw_signed;
    450   u8 saw_unsigned;
    451   u8 saw_bool;
    452   u8 saw_float;
    453   u8 saw_double;
    454   u8 saw_int128; /* __int128 / __int128_t / __uint128_t */
    455   u8 saw_explicit_type;
    456 } TypeSpecAccum;
    457 
    458 /* ============================================================
    459  * Shared token/diagnostic helpers (defined in parse.c)
    460  * ============================================================ */
    461 
    462 _Noreturn void perr(Parser* p, const char* fmt, ...);
    463 void reject_general_regs_only_fp(Parser* p, const char* what);
    464 void advance(Parser* p);
    465 Tok peek1(Parser* p);
    466 void expect_punct(Parser* p, u32 punct, const char* what);
    467 int accept_punct(Parser* p, u32 punct);
    468 
    469 /* ============================================================
    470  * Scope/tag ops (defined in parse.c)
    471  * ============================================================ */
    472 
    473 Scope* scope_new(Parser* p, Scope* parent);
    474 void scope_push(Parser* p);
    475 void scope_pop(Parser* p);
    476 SymEntry* scope_define(Parser* p, Sym name, SymEntryKind kind,
    477                        const Type* type);
    478 SymEntry* scope_lookup_current(Parser* p, Sym name);
    479 SymEntry* scope_lookup(Parser* p, Sym name);
    480 TagEntry* tag_define(Parser* p, Sym name, TagDeclKind kind, Type* type,
    481                      int complete);
    482 TagEntry* tag_lookup(Parser* p, Sym name);
    483 TagEntry* tag_lookup_local(Parser* p, Sym name);
    484 
    485 /* ============================================================
    486  * Token predicate helpers (defined in parse.c — file-scope static,
    487  * exposed here as inline equivalents; each .c file sees its own copy)
    488  * ============================================================ */
    489 
    490 static inline int is_punct(const Tok* t, u32 punct) {
    491   return t->kind == TOK_PUNCT && tok_punct(t) == punct;
    492 }
    493 
    494 static inline int is_pp_hash(const Tok* t) { return t->kind == TOK_PP_HASH; }
    495 
    496 /* THE keyword classifier — the single canonical way keywordness is decided.
    497  * Interned Sym -> CKw via kw_map; KW_NONE if the Sym is not a keyword. The map
    498  * holds the canonical keyword spellings AND the GNU alias spellings
    499  * (`__inline__` etc.), each mapping to its CKw, registered once in the kw_map
    500  * population in parse_c — so aliases are classified identically to their
    501  * canonical keyword, with no separate "alias-aware" path. Everything below (and
    502  * the per-token classify_kw / is_kw adapters) routes through this. */
    503 static inline CKw ident_kw_inline(const Parser* p, Sym name) {
    504   return name ? (CKw)KwTab_get(&p->kw_map, name) : KW_NONE;
    505 }
    506 
    507 /* A token's keyword identity (KW_NONE for a non-identifier or non-keyword). The
    508  * one place to classify a Tok: classify once, then compare CKw. */
    509 static inline CKw classify_kw(const Parser* p, const Tok* t) {
    510   return t->kind == TOK_IDENT ? ident_kw_inline(p, tok_ident(t)) : KW_NONE;
    511 }
    512 
    513 /* Is token t the keyword k? Thin boolean shape-adapter over classify_kw. */
    514 static inline int is_kw(const Parser* p, const Tok* t, CKw k) {
    515   return classify_kw(p, t) == k;
    516 }
    517 
    518 static inline int c_type_is_scalar(const Type* ty) {
    519   return type_is_arith(ty) || type_is_ptr(ty);
    520 }
    521 
    522 /* ============================================================
    523  * Shared types (needed across multiple modules)
    524  * ============================================================ */
    525 
    526 typedef struct ParamInfo {
    527   Sym name;
    528   const Type* type;
    529   const Type* declared_type;
    530   SrcLoc loc;
    531   ParamVLABoundExpr* vla_bounds;
    532   u8 vla_bound_len;
    533 } ParamInfo;
    534 
    535 /* ============================================================
    536  * Declarator suffix types (defined in parse_type.c, shared here)
    537  * ============================================================ */
    538 
    539 typedef enum DSuffKind { DS_ARRAY, DS_FUNC } DSuffKind;
    540 typedef struct DeclSuffix {
    541   u8 kind;       /* DSuffKind */
    542   u32 count;     /* element count; meaningful when !vla and !incomplete */
    543   u8 incomplete; /* true for `[]` (no size given) */
    544   u8 vla;        /* true for `[expr]` with a non-constant size */
    545   FrameSlot vla_count_slot;
    546   ParamInfo* params;
    547   u16 nparams;
    548   u8 variadic;
    549 } DeclSuffix;
    550 
    551 typedef struct DeclaratorInfo {
    552   ParamInfo* fn_params;
    553   u16 fn_nparams;
    554   u8 fn_variadic;
    555   Sym asm_label;
    556 } DeclaratorInfo;
    557 
    558 /* ============================================================
    559  * Cross-module forward declarations
    560  * ============================================================ */
    561 
    562 /* parse_type.c */
    563 
    564 int parse_decl_specs(Parser* p, DeclSpecs* out);
    565 const Type* parse_struct_or_union(Parser* p, TypeKind kind,
    566                                   Attr** anon_attrs_out);
    567 const Type* parse_enum(Parser* p, Attr** anon_attrs_out);
    568 const Type* resolve_type_specs(Parser* p, const TypeSpecAccum* a, SrcLoc loc);
    569 const Type* parse_type_name(Parser* p);
    570 const Type* parse_pointer_layer(Parser* p, const Type* base);
    571 const Type* parse_declarator_full(Parser* p, const Type* base,
    572                                   int allow_abstract, Sym* name_out,
    573                                   SrcLoc* loc_out);
    574 const Type* parse_declarator_full_ex(Parser* p, const Type* base,
    575                                      int allow_abstract, Sym* name_out,
    576                                      SrcLoc* loc_out, Attr** attrs_out);
    577 const Type* parse_declarator_full_info(Parser* p, const Type* base,
    578                                        int allow_abstract, Sym* name_out,
    579                                        SrcLoc* loc_out, Attr** attrs_out,
    580                                        DeclaratorInfo* info_out);
    581 const Type* parse_declarator(Parser* p, const Type* base, Sym* name_out,
    582                              SrcLoc* loc_out);
    583 const Type* complete_incomplete_array(Parser* p, const Type* ty);
    584 int starts_type_name(const Parser* p, const Tok* t);
    585 int starts_attr(const Parser* p);
    586 Attr* parse_attribute_spec_list(Parser* p);
    587 void parse_and_discard_attributes(Parser* p);
    588 int find_field(KitCompiler* abi, Pool* pool, const Type* rec, Sym name,
    589                const Type** out_type, u32* out_offset, const Field** out_field);
    590 u32 attrs_pick_aligned(const Attr* a);
    591 void attr_list_append(Attr** head, Attr* add);
    592 void parse_attrs_into(Parser* p, Attr** sink);
    593 int parse_decl_suffix(Parser* p, DeclSuffix* out);
    594 const Type* apply_decl_suffix(Parser* p, const Type* base, const DeclSuffix* s);
    595 void validate_decl_type_constraints(Parser* p, const DeclSpecs* specs,
    596                                     const Type* ty, int is_function,
    597                                     int is_member);
    598 
    599 /* parse_expr.c */
    600 void parse_expr(Parser* p);
    601 void parse_assign_expr(Parser* p);
    602 void parse_cond_expr(Parser* p);
    603 void parse_unary(Parser* p);
    604 void c_const_guard_not_eval_push(Parser* p);
    605 void c_const_guard_not_eval_pop(Parser* p);
    606 typedef struct CConstInt {
    607   const Type* type;
    608   u64 lo;
    609   u64 hi;
    610 } CConstInt;
    611 CConstInt eval_const_int_typed(Parser* p, SrcLoc loc);
    612 i64 eval_const_int(Parser* p, SrcLoc loc);
    613 i64 const_int_as_i64(Parser* p, CConstInt v);
    614 i64 parse_int_literal(Parser* p, const Tok* t);
    615 double parse_float_literal(Parser* p, const Tok* t);
    616 i64 decode_char_literal(Parser* p, const Tok* t);
    617 const Type* char_literal_type(Parser* p, const Tok* t);
    618 const Type* string_literal_elem_type(Parser* p, const Tok* t);
    619 int string_literal_initializes_array(Parser* p, const Type* elem, const Tok* t);
    620 u8* decode_string_literal(Parser* p, const Tok* t, size_t* nlen_out);
    621 void to_rvalue(Parser* p);
    622 void coerce_top_to_lvalue(Parser* p);
    623 void coerce_top_to_type(Parser* p, const Type* dst);
    624 KitCgSym emit_string_to_rodata(Parser* p, const u8* bytes, size_t n);
    625 KitCgSym emit_string_literal_to_rodata(Parser* p, const u8* bytes,
    626                                        size_t nbytes, const Type* elem_ty);
    627 
    628 /* parse_init.c */
    629 void init_at(Parser* p, FrameSlot slot, const Type* arr_ty, u32 offset,
    630              const Type* ty);
    631 void zero_init_at(Parser* p, FrameSlot slot, const Type* arr_ty, u32 offset,
    632                   const Type* ty);
    633 /* Zero a whole sub-object with a single kit_cg_memset, instead of recursing to
    634  * one scalar store per leaf. Correct for any type (all-zero bytes is the zero
    635  * value of every C type on supported targets) and avoids O(leaves^2) blowup on
    636  * large aggregates. */
    637 void zero_object_bytes_at(Parser* p, FrameSlot slot, const Type* arr_ty,
    638                           u32 offset, const Type* ty);
    639 void parse_static_init_at(Parser* p, u8* buf, u32 buflen, u32 offset,
    640                           const Type* ty);
    641 void define_static_object(Parser* p, ObjSymId sym, ObjSecId section_id,
    642                           const Type* var_ty, u16 quals, int has_init,
    643                           SrcLoc loc, u32 align_override);
    644 void srl_push(Parser* p, u32 offset, u32 size, ObjSymId target, i64 addend);
    645 void srl_push_label(Parser* p, u32 offset, u32 size, CGLabel label, i64 addend);
    646 void encode_int_le(u8* dst, u32 size, i64 v);
    647 void push_subobject_lv(Parser* p, FrameSlot slot, const Type* arr_ty,
    648                        u32 offset, const Type* elem_ty);
    649 void emit_struct_copy_into_slot(Parser* p, FrameSlot dst_slot,
    650                                 const Type* dst_arr_ty, u32 dst_off,
    651                                 const Type* ty);
    652 int is_char_kind(const Type* ty);
    653 
    654 /* parse_stmt.c */
    655 void parse_stmt(Parser* p);
    656 void parse_compound_stmt(Parser* p);
    657 void parse_static_assert(Parser* p);
    658 GotoLabel* label_get_or_create(Parser* p, Sym name, SrcLoc loc);
    659 /* Records that `name`'s address is taken (GNU labels-as-values) and returns
    660  * its CG label. Used by both `&&label` expressions and static initializers. */
    661 CGLabel take_label_addr(Parser* p, Sym name, SrcLoc loc);
    662 
    663 /* parse.c (residual — TU driver) */
    664 void parse_param_list(Parser* p, ParamInfo** infos_out, u16* nparams_out,
    665                       u8* variadic_out);
    666 void parse_local_decl(Parser* p, const DeclSpecs* specs);
    667 FrameSlot make_local(Parser* p, Sym name, const Type* type, SrcLoc loc);
    668 FrameSlot make_local_aligned(Parser* p, Sym name, const Type* type, SrcLoc loc,
    669                              u32 align_override);
    670 void c_stack_protector_enable(Parser* p);
    671 void c_stack_protector_note_type(Parser* p, const Type* type);
    672 void c_stack_protector_note_address(Parser* p);
    673 Sym mint_static_local_sym(Parser* p, Sym orig);
    674 void record_braced_block(Parser* p);
    675 void replay_rewind(Parser* p);
    676 u32 count_recorded_top_level_items(const Tok* vec, u32 len);