kit

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

parse_expr.c (123669B)


      1 /* parse_expr.c — precedence climbing, unary/primary, literal decoding,
      2  * constant evaluation. */
      3 
      4 #include "parse/literal_unicode.h"
      5 #include "parse/parse_priv.h"
      6 
      7 static const Type* ty_int(Parser* p) { return type_prim(p->pool, TY_INT); }
      8 static const Type* ty_size_t(Parser* p) {
      9   return c_abi_size_type(p->abi, p->pool);
     10 }
     11 static int type_is_fp(const Type* t);
     12 static int cg_const_is_zero(KitCgConstInt v);
     13 
     14 static int type_is_incomplete(const Type* t) {
     15   if (!t) return 1;
     16   if (t->kind == TY_VOID) return 1;
     17   if ((t->kind == TY_STRUCT || t->kind == TY_UNION) && t->rec.incomplete)
     18     return 1;
     19   if (t->kind == TY_ARRAY && t->arr.incomplete) return 1;
     20   return 0;
     21 }
     22 
     23 static void require_sizeof_type(Parser* p, const Type* ty) {
     24   if (!ty || type_is_incomplete(ty) || ty->kind == TY_FUNC) {
     25     perr(p, "sizeof operand has incomplete or function type");
     26   }
     27 }
     28 
     29 static int type_is_void_ptr(const Type* ty) {
     30   return ty && ty->kind == TY_PTR && ty->ptr.pointee &&
     31          ty->ptr.pointee->kind == TY_VOID;
     32 }
     33 
     34 static const Type* ty_char16(Parser* p) {
     35   return type_prim(p->pool, TY_USHORT);
     36 }
     37 
     38 static const Type* ty_char32(Parser* p) { return type_prim(p->pool, TY_UINT); }
     39 
     40 static const Type* ty_wchar(Parser* p) {
     41   /* sizeof(wchar_t) is a resolved data-model fact (2 on Windows, 4 else);
     42    * key on the width rather than re-deriving from the OS identity. */
     43   KitTargetSpec target = kit_compiler_target_spec(p->c);
     44   return target.wchar_size == 2 ? ty_char16(p) : ty_int(p);
     45 }
     46 
     47 static int pointer_pointees_compatible(Parser* p, const Type* lhs,
     48                                        const Type* rhs) {
     49   const Type* lp;
     50   const Type* rp;
     51   if (!lhs || !rhs || lhs->kind != TY_PTR || rhs->kind != TY_PTR) return 0;
     52   lp = lhs->ptr.pointee;
     53   rp = rhs->ptr.pointee;
     54   if (!lp || !rp) return 0;
     55   return type_compatible(type_unqual(p->pool, lp), type_unqual(p->pool, rp));
     56 }
     57 
     58 static int null_pointer_constant(Parser* p, const Type* ty) {
     59   KitCgConstInt v;
     60   return type_is_int(ty) &&
     61          (c_cg_top_is_null_ptr_const(p) ||
     62           (kit_cg_top_const_int_ex(p->cg, &v) && cg_const_is_zero(v)));
     63 }
     64 
     65 static void require_scalar(Parser* p, const Type* ty, const char* what) {
     66   if (!c_type_is_scalar(ty))
     67     perr(p, "%.*s requires scalar operand",
     68          KIT_SLICE_ARG(kit_slice_cstr(what)));
     69 }
     70 
     71 static void require_arith(Parser* p, const Type* ty, const char* what) {
     72   if (!type_is_arith(ty))
     73     perr(p, "%.*s requires arithmetic operand",
     74          KIT_SLICE_ARG(kit_slice_cstr(what)));
     75 }
     76 
     77 static const Type* conditional_pointer_type(Parser* p, const Type* then_ty,
     78                                             int then_null, const Type* else_ty,
     79                                             int else_null) {
     80   if (then_ty && then_ty->kind == TY_PTR && else_null) return then_ty;
     81   if (else_ty && else_ty->kind == TY_PTR && then_null) return else_ty;
     82   if (!then_ty || !else_ty || then_ty->kind != TY_PTR ||
     83       else_ty->kind != TY_PTR)
     84     return NULL;
     85   if (type_is_void_ptr(then_ty)) return then_ty;
     86   if (type_is_void_ptr(else_ty)) return else_ty;
     87   if (pointer_pointees_compatible(p, then_ty, else_ty)) return then_ty;
     88   return NULL;
     89 }
     90 
     91 /* ============================================================
     92  * Literal parsing
     93  * ============================================================ */
     94 
     95 static u32 integer_type_bits(Parser* p, const Type* ty);
     96 static int integer_type_signed(Parser* p, const Type* ty);
     97 
     98 static u64 parse_int_literal_u64(Parser* p, const Tok* t, int* decimal_out) {
     99   KitSlice spell_sl = pp_text_slice(p->pp, t);
    100   size_t len = spell_sl.len;
    101   const char* s = spell_sl.s;
    102   size_t i = 0;
    103   u64 base = 10;
    104   u64 acc = 0;
    105   int decimal = 1;
    106   if (!s) perr(p, "bad numeric literal");
    107   if (len >= 2 && s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) {
    108     base = 16;
    109     decimal = 0;
    110     i = 2;
    111   } else if (len >= 2 && s[0] == '0' && (s[1] == 'b' || s[1] == 'B')) {
    112     base = 2;
    113     decimal = 0;
    114     i = 2;
    115   } else if (len >= 1 && s[0] == '0') {
    116     base = 8;
    117     decimal = 0;
    118     i = 1;
    119   }
    120   for (; i < len; ++i) {
    121     int c = (unsigned char)s[i];
    122     int dv;
    123     if (c == 'u' || c == 'U' || c == 'l' || c == 'L') break;
    124     if (c >= '0' && c <= '9')
    125       dv = c - '0';
    126     else if (c >= 'a' && c <= 'f')
    127       dv = c - 'a' + 10;
    128     else if (c >= 'A' && c <= 'F')
    129       dv = c - 'A' + 10;
    130     else
    131       perr(p, "bad digit in numeric literal");
    132     if ((u64)dv >= base) perr(p, "digit out of range for base");
    133     if (acc > (~0ull - (u64)dv) / base) perr(p, "integer literal too large");
    134     acc = acc * base + dv;
    135   }
    136   if (decimal_out) *decimal_out = decimal;
    137   return acc;
    138 }
    139 
    140 static int uint_fits_type(Parser* p, u64 v, const Type* ty) {
    141   u32 nb = integer_type_bits(p, ty);
    142   if (integer_type_signed(p, ty)) {
    143     if (nb >= 64) return v <= 0x7fffffffffffffffull;
    144     return v <= ((1ull << (nb - 1u)) - 1ull);
    145   }
    146   if (nb >= 64) return 1;
    147   return v <= ((1ull << nb) - 1ull);
    148 }
    149 
    150 static const Type* first_fitting_type(Parser* p, u64 v, const TypeKind* kinds,
    151                                       u32 nkinds) {
    152   u32 i;
    153   for (i = 0; i < nkinds; ++i) {
    154     const Type* ty = type_prim(p->pool, kinds[i]);
    155     if (uint_fits_type(p, v, ty)) return ty;
    156   }
    157   perr(p, "integer literal too large for supported integer types");
    158 }
    159 
    160 i64 parse_int_literal(Parser* p, const Tok* t) {
    161   return (i64)parse_int_literal_u64(p, t, NULL);
    162 }
    163 
    164 static const Type* int_literal_type(Parser* p, const Tok* t) {
    165   int u = (t->flags & TF_INT_U) != 0;
    166   int l = (t->flags & TF_INT_L) != 0;
    167   int ll = (t->flags & TF_INT_LL) != 0;
    168   int decimal = 1;
    169   u64 v = parse_int_literal_u64(p, t, &decimal);
    170   if (u && ll) {
    171     static const TypeKind order[] = {TY_ULLONG};
    172     return first_fitting_type(p, v, order,
    173                               (u32)(sizeof order / sizeof order[0]));
    174   }
    175   if (!u && ll) {
    176     static const TypeKind dec_order[] = {TY_LLONG};
    177     static const TypeKind other_order[] = {TY_LLONG, TY_ULLONG};
    178     return decimal ? first_fitting_type(
    179                          p, v, dec_order,
    180                          (u32)(sizeof dec_order / sizeof dec_order[0]))
    181                    : first_fitting_type(
    182                          p, v, other_order,
    183                          (u32)(sizeof other_order / sizeof other_order[0]));
    184   }
    185   if (u && l) {
    186     static const TypeKind order[] = {TY_ULONG, TY_ULLONG};
    187     return first_fitting_type(p, v, order,
    188                               (u32)(sizeof order / sizeof order[0]));
    189   }
    190   if (!u && l) {
    191     static const TypeKind dec_order[] = {TY_LONG, TY_LLONG};
    192     static const TypeKind other_order[] = {TY_LONG, TY_ULONG, TY_LLONG,
    193                                            TY_ULLONG};
    194     return decimal ? first_fitting_type(
    195                          p, v, dec_order,
    196                          (u32)(sizeof dec_order / sizeof dec_order[0]))
    197                    : first_fitting_type(
    198                          p, v, other_order,
    199                          (u32)(sizeof other_order / sizeof other_order[0]));
    200   }
    201   if (u) {
    202     static const TypeKind order[] = {TY_UINT, TY_ULONG, TY_ULLONG};
    203     return first_fitting_type(p, v, order,
    204                               (u32)(sizeof order / sizeof order[0]));
    205   }
    206   if (decimal) {
    207     static const TypeKind order[] = {TY_INT, TY_LONG, TY_LLONG};
    208     return first_fitting_type(p, v, order,
    209                               (u32)(sizeof order / sizeof order[0]));
    210   } else {
    211     static const TypeKind order[] = {TY_INT,   TY_UINT,  TY_LONG,
    212                                      TY_ULONG, TY_LLONG, TY_ULLONG};
    213     return first_fitting_type(p, v, order,
    214                               (u32)(sizeof order / sizeof order[0]));
    215   }
    216 }
    217 
    218 double parse_float_literal(Parser* p, const Tok* t) {
    219   KitSlice spell_sl = pp_text_slice(p->pp, t);
    220   size_t len = spell_sl.len;
    221   const char* s = spell_sl.s;
    222   size_t i = 0;
    223   int is_hex = 0;
    224   double v = 0.0;
    225   int exp = 0;
    226   int dec_exp = 0;
    227   int frac_seen = 0;
    228   if (!s) perr(p, "bad float literal");
    229   if (len >= 2 && s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) {
    230     is_hex = 1;
    231     i = 2;
    232   }
    233   while (i < len) {
    234     int c = (unsigned char)s[i];
    235     int dv;
    236     if (c == '.' || c == 'e' || c == 'E' || c == 'p' || c == 'P' || c == 'f' ||
    237         c == 'F' || c == 'l' || c == 'L')
    238       break;
    239     if (c >= '0' && c <= '9')
    240       dv = c - '0';
    241     else if (is_hex && c >= 'a' && c <= 'f')
    242       dv = c - 'a' + 10;
    243     else if (is_hex && c >= 'A' && c <= 'F')
    244       dv = c - 'A' + 10;
    245     else
    246       perr(p, "bad digit in float literal");
    247     v = v * (is_hex ? 16.0 : 10.0) + (double)dv;
    248     i++;
    249   }
    250   if (i < len && s[i] == '.') {
    251     i++;
    252     while (i < len) {
    253       int c = (unsigned char)s[i];
    254       int dv;
    255       if (c == 'e' || c == 'E' || c == 'p' || c == 'P' || c == 'f' ||
    256           c == 'F' || c == 'l' || c == 'L')
    257         break;
    258       if (c >= '0' && c <= '9')
    259         dv = c - '0';
    260       else if (is_hex && c >= 'a' && c <= 'f')
    261         dv = c - 'a' + 10;
    262       else if (is_hex && c >= 'A' && c <= 'F')
    263         dv = c - 'A' + 10;
    264       else
    265         perr(p, "bad digit in float literal");
    266       v = v * (is_hex ? 16.0 : 10.0) + (double)dv;
    267       exp -= 1;
    268       frac_seen = 1;
    269       i++;
    270     }
    271   }
    272   (void)frac_seen;
    273   if (i < len && (s[i] == 'e' || s[i] == 'E' || s[i] == 'p' || s[i] == 'P')) {
    274     int neg = 0;
    275     int n = 0;
    276     int hex_exp = (s[i] == 'p' || s[i] == 'P');
    277     i++;
    278     if (i < len && (s[i] == '+' || s[i] == '-')) {
    279       if (s[i] == '-') neg = 1;
    280       i++;
    281     }
    282     while (i < len) {
    283       int c = (unsigned char)s[i];
    284       if (c < '0' || c > '9') break;
    285       n = n * 10 + (c - '0');
    286       i++;
    287     }
    288     dec_exp = neg ? -n : n;
    289     if (hex_exp) {
    290       dec_exp += exp * 4;
    291       exp = 0;
    292     }
    293   }
    294   while (exp < 0) {
    295     v /= (is_hex ? 16.0 : 10.0);
    296     exp++;
    297   }
    298   while (exp > 0) {
    299     v *= (is_hex ? 16.0 : 10.0);
    300     exp--;
    301   }
    302   if (is_hex) {
    303     while (dec_exp < 0) {
    304       v /= 2.0;
    305       dec_exp++;
    306     }
    307     while (dec_exp > 0) {
    308       v *= 2.0;
    309       dec_exp--;
    310     }
    311   } else {
    312     while (dec_exp < 0) {
    313       v /= 10.0;
    314       dec_exp++;
    315     }
    316     while (dec_exp > 0) {
    317       v *= 10.0;
    318       dec_exp--;
    319     }
    320   }
    321   return v;
    322 }
    323 
    324 static const Type* float_literal_type(Parser* p, const Tok* t) {
    325   if (t->flags & TF_FLT_F) return type_prim(p->pool, TY_FLOAT);
    326   if (t->flags & TF_FLT_L) return type_prim(p->pool, TY_LDOUBLE);
    327   return type_prim(p->pool, TY_DOUBLE);
    328 }
    329 
    330 const Type* char_literal_type(Parser* p, const Tok* t) {
    331   if (t->flags & TF_STR_U16) return ty_char16(p);
    332   if (t->flags & TF_STR_U32) return ty_char32(p);
    333   return ty_int(p);
    334 }
    335 
    336 static CLitStringEnc literal_string_encoding(const Tok* t) {
    337   if (t->flags & TF_STR_U8) return C_LIT_STR_UTF8;
    338   if (t->flags & TF_STR_U16) return C_LIT_STR_UTF16;
    339   if (t->flags & (TF_STR_WIDE | TF_STR_U32)) return C_LIT_STR_UTF32;
    340   return C_LIT_STR_ORDINARY;
    341 }
    342 
    343 const Type* string_literal_elem_type(Parser* p, const Tok* t) {
    344   if (t->flags & TF_STR_WIDE) return ty_wchar(p);
    345   if (t->flags & TF_STR_U16) return ty_char16(p);
    346   if (t->flags & TF_STR_U32) return ty_char32(p);
    347   return type_prim(p->pool, TY_CHAR);
    348 }
    349 
    350 int string_literal_initializes_array(Parser* p, const Type* elem,
    351                                      const Tok* t) {
    352   const Type* uelem;
    353   if (!elem || !t || t->kind != TOK_STR) return 0;
    354   uelem = type_unqual(p->pool, elem);
    355   if (!(t->flags & (TF_STR_WIDE | TF_STR_U16 | TF_STR_U32))) {
    356     return is_char_kind(uelem);
    357   }
    358   return type_compatible(uelem, string_literal_elem_type(p, t));
    359 }
    360 
    361 i64 decode_char_literal(Parser* p, const Tok* t) {
    362   KitSlice spell_sl = pp_text_slice(p->pp, t);
    363   size_t len = spell_sl.len;
    364   const char* s = spell_sl.s;
    365   size_t i = 0;
    366   CLitUnit unit;
    367   const char* err = NULL;
    368   u32 v;
    369   u32 bits = 8;
    370   CLitStringEnc enc = literal_string_encoding(t);
    371   if (!s) perr(p, "bad char literal");
    372   if (t->flags & TF_STR_U8)
    373     i = 2;
    374   else if (t->flags & (TF_STR_WIDE | TF_STR_U16 | TF_STR_U32))
    375     i = 1;
    376   if (t->flags & TF_STR_U16)
    377     bits = 16;
    378   else if (t->flags & (TF_STR_WIDE | TF_STR_U32))
    379     bits = 32;
    380   if (i >= len || s[i] != '\'') perr(p, "malformed character literal");
    381   i++;
    382   if (i >= len || s[i] == '\'') perr(p, "empty character literal");
    383   if (!c_lit_decode_unit(s, len, &i, &unit, &err)) {
    384     compiler_panic(
    385         p->c, pp_materialize_loc(p->pp, t->loc), "%.*s",
    386         KIT_SLICE_ARG(kit_slice_cstr(err ? err : "bad character literal")));
    387   }
    388   if (!c_lit_encode_char_unit(enc, bits, unit, &v, &err)) {
    389     compiler_panic(
    390         p->c, pp_materialize_loc(p->pp, t->loc), "%.*s",
    391         KIT_SLICE_ARG(kit_slice_cstr(err ? err : "bad character literal")));
    392   }
    393   if (i >= len || s[i] != '\'') {
    394     perr(p, "multi-character constants are not supported");
    395   }
    396   return (i64)v;
    397 }
    398 
    399 u8* decode_string_literal(Parser* p, const Tok* t, size_t* nlen_out) {
    400   KitSlice spell_sl = pp_text_slice(p->pp, t);
    401   size_t len = spell_sl.len;
    402   const char* s = spell_sl.s;
    403   size_t i = 0;
    404   Heap* h = kit_compiler_context(p->c)->heap;
    405   u8* buf;
    406   size_t k = 0;
    407   const Type* elem_ty;
    408   u32 elem_size;
    409   CLitStringEnc enc = literal_string_encoding(t);
    410   const char* err = NULL;
    411   if (!s) perr(p, "bad string literal");
    412   if (t->flags & TF_STR_U8)
    413     i = 2;
    414   else if (t->flags & (TF_STR_WIDE | TF_STR_U16 | TF_STR_U32))
    415     i = 1;
    416   elem_ty = string_literal_elem_type(p, t);
    417   elem_size = c_abi_sizeof(p->abi, p->pool, elem_ty);
    418   if (i >= len || s[i] != '"') perr(p, "malformed string literal");
    419   i++;
    420   buf = (u8*)h->alloc(h, (len + 1u) * elem_size, 1);
    421   if (!buf) perr(p, "out of memory in string literal");
    422   while (i < len && s[i] != '"') {
    423     CLitUnit unit;
    424     if (!c_lit_decode_unit(s, len, &i, &unit, &err)) {
    425       compiler_panic(
    426           p->c, pp_materialize_loc(p->pp, t->loc), "%.*s",
    427           KIT_SLICE_ARG(kit_slice_cstr(err ? err : "bad string literal")));
    428     }
    429     if (!c_lit_append_string_unit(buf, &k, enc, elem_size, unit, &err)) {
    430       compiler_panic(
    431           p->c, pp_materialize_loc(p->pp, t->loc), "%.*s",
    432           KIT_SLICE_ARG(kit_slice_cstr(err ? err : "bad string literal")));
    433     }
    434   }
    435   c_lit_encode_uint_le(buf + k, elem_size, 0);
    436   k += elem_size;
    437   *nlen_out = k;
    438   return buf;
    439 }
    440 
    441 KitCgSym emit_string_to_rodata(Parser* p, const u8* bytes, size_t n) {
    442   const Type* arr_ty =
    443       type_array(p->pool, type_prim(p->pool, TY_CHAR), (u32)n, 0);
    444   return kit_cg_const_data(p->cg, bytes, n, 1u, c_cg_tid(p, arr_ty));
    445 }
    446 
    447 KitCgSym emit_string_literal_to_rodata(Parser* p, const u8* bytes,
    448                                        size_t nbytes, const Type* elem_ty) {
    449   u32 elem_size = c_abi_sizeof(p->abi, p->pool, elem_ty);
    450   u32 count = elem_size ? (u32)(nbytes / elem_size) : 0;
    451   const Type* arr_ty = type_array(p->pool, elem_ty, count, 0);
    452   return kit_cg_const_data(p->cg, bytes, nbytes,
    453                            c_abi_alignof(p->abi, p->pool, elem_ty),
    454                            c_cg_tid(p, arr_ty));
    455 }
    456 
    457 /* ============================================================
    458  * Integer conversion helpers + constant-expression guard
    459  * ============================================================ */
    460 
    461 static const Type* offsetof_designator(Parser* p, const Type* base, u32* off);
    462 static const Type* common_fp_type(Parser* p, const Type* a, const Type* b);
    463 static void coerce_fp_cmp_operands(Parser* p, const Type* common);
    464 
    465 typedef struct CConstGuardMark {
    466   u32 depth;
    467   u32 not_eval;
    468   const char* error;
    469   SrcLoc error_loc;
    470 } CConstGuardMark;
    471 
    472 static int c_const_guard_active(Parser* p) {
    473   return p && p->const_guard_depth != 0;
    474 }
    475 
    476 static void c_const_guard_note_at(Parser* p, SrcLoc loc, const char* message) {
    477   if (!p || !p->const_guard_depth || p->const_guard_not_eval ||
    478       p->const_guard_error) {
    479     return;
    480   }
    481   p->const_guard_error = message;
    482   p->const_guard_error_loc = loc;
    483 }
    484 
    485 static void c_const_guard_note(Parser* p, const char* message) {
    486   c_const_guard_note_at(p, pp_materialize_loc(p->pp, p->cur.loc), message);
    487 }
    488 
    489 void c_const_guard_not_eval_push(Parser* p) {
    490   if (p && p->const_guard_depth) ++p->const_guard_not_eval;
    491 }
    492 
    493 void c_const_guard_not_eval_pop(Parser* p) {
    494   if (!p || !p->const_guard_depth) return;
    495   if (!p->const_guard_not_eval)
    496     perr(p, "internal parser constant guard not-evaluated underflow");
    497   --p->const_guard_not_eval;
    498 }
    499 
    500 static CConstGuardMark c_const_guard_push(Parser* p) {
    501   CConstGuardMark mark;
    502   memset(&mark, 0, sizeof mark);
    503   if (!p) return mark;
    504   mark.depth = p->const_guard_depth;
    505   mark.not_eval = p->const_guard_not_eval;
    506   mark.error = p->const_guard_error;
    507   mark.error_loc = p->const_guard_error_loc;
    508   if (p->const_guard_depth == 0) {
    509     p->const_guard_not_eval = 0;
    510     p->const_guard_error = NULL;
    511     memset(&p->const_guard_error_loc, 0, sizeof p->const_guard_error_loc);
    512   }
    513   ++p->const_guard_depth;
    514   return mark;
    515 }
    516 
    517 static int c_const_guard_pop(Parser* p, CConstGuardMark mark,
    518                              const char** error_out, SrcLoc* loc_out) {
    519   const char* error = p ? p->const_guard_error : NULL;
    520   SrcLoc loc;
    521   memset(&loc, 0, sizeof loc);
    522   if (p) {
    523     loc = p->const_guard_error_loc;
    524     if (!p->const_guard_depth)
    525       perr(p, "internal parser constant guard underflow");
    526     p->const_guard_depth = mark.depth;
    527     p->const_guard_not_eval = mark.not_eval;
    528     p->const_guard_error = mark.error;
    529     p->const_guard_error_loc = mark.error_loc;
    530   }
    531   if (error_out) *error_out = error;
    532   if (loc_out) *loc_out = loc;
    533   return error == NULL;
    534 }
    535 
    536 static u32 integer_type_bits(Parser* p, const Type* ty) {
    537   u32 sz = ty ? c_abi_sizeof(p->abi, p->pool, ty) : 8u;
    538   if (ty && (ty->kind == TY_INT128 || ty->kind == TY_UINT128)) return 128;
    539   if (sz >= 8) return 64;
    540   return sz * 8u;
    541 }
    542 
    543 static int integer_type_signed(Parser* p, const Type* ty) {
    544   (void)p;
    545   if (!ty) return 1;
    546   return type_is_signed_integer(ty) != 0;
    547 }
    548 
    549 static u32 integer_rank(const Type* ty) {
    550   return ty ? type_kind_int_rank((TypeKind)ty->kind) : 0;
    551 }
    552 
    553 static const Type* integer_unsigned_variant(Parser* p, const Type* ty) {
    554   TypeKind k = ty ? (TypeKind)ty->kind : TY_UINT;
    555   return type_prim(p->pool, type_kind_unsigned_variant(k));
    556 }
    557 
    558 static const Type* integer_promote_type(Parser* p, const Type* ty) {
    559   const Type* u = type_unqual(p->pool, ty);
    560   if (u && u->kind == TY_ENUM) return type_prim(p->pool, TY_INT);
    561   return type_promoted(p->pool, u);
    562 }
    563 
    564 static const Type* integer_common_type(Parser* p, const Type* a,
    565                                        const Type* b) {
    566   const Type* ap = integer_promote_type(p, a);
    567   const Type* bp = integer_promote_type(p, b);
    568   int as = integer_type_signed(p, ap);
    569   int bs = integer_type_signed(p, bp);
    570   u32 ar = integer_rank(ap);
    571   u32 br = integer_rank(bp);
    572   if (type_compatible(ap, bp)) return ap;
    573   if (as == bs) return ar >= br ? ap : bp;
    574   if (!as && ar >= br) return ap;
    575   if (!bs && br >= ar) return bp;
    576   if (as && integer_type_bits(p, ap) > integer_type_bits(p, bp)) return ap;
    577   if (bs && integer_type_bits(p, bp) > integer_type_bits(p, ap)) return bp;
    578   return integer_unsigned_variant(p, as ? ap : bp);
    579 }
    580 
    581 static int cg_const_is_zero(KitCgConstInt v) {
    582   return v.known && v.lo == 0 && v.hi == 0;
    583 }
    584 
    585 static int cg_top_const_truth(Parser* p, int* truth_out) {
    586   KitCgConstInt v;
    587   if (!kit_cg_top_const_int_ex(p->cg, &v)) return 0;
    588   if (truth_out) *truth_out = (v.lo != 0 || v.hi != 0);
    589   return 1;
    590 }
    591 
    592 static int cg_top2_const_int(Parser* p, KitCgConstInt* out) {
    593   if (!p || kit_cg_stack_depth(p->cg) < 2u) return 0;
    594   c_cg_swap(p);
    595   if (!kit_cg_top_const_int_ex(p->cg, out)) {
    596     c_cg_swap(p);
    597     return 0;
    598   }
    599   c_cg_swap(p);
    600   return 1;
    601 }
    602 
    603 static CConstInt cconst_from_cg(Parser* p, const Type* ty, KitCgConstInt v) {
    604   CConstInt r;
    605   memset(&r, 0, sizeof r);
    606   r.type = ty ? type_unqual(p->pool, ty) : ty_int(p);
    607   r.lo = v.lo;
    608   r.hi = v.hi;
    609   if (r.type && r.type->kind == TY_BOOL) {
    610     r.lo = (r.lo || r.hi) ? 1u : 0u;
    611     r.hi = 0;
    612   }
    613   return r;
    614 }
    615 
    616 i64 const_int_as_i64(Parser* p, CConstInt v) {
    617   u32 nb = integer_type_bits(p, v.type);
    618   u64 u = v.lo;
    619   if (integer_type_signed(p, v.type) && nb < 64) {
    620     u64 mask = (1ull << nb) - 1ull;
    621     u64 sign = 1ull << (nb - 1u);
    622     u &= mask;
    623     if (u & sign) u |= ~mask;
    624   }
    625   return (i64)u;
    626 }
    627 
    628 static i64 cg_const_as_i64(Parser* p, const Type* ty, KitCgConstInt v) {
    629   return const_int_as_i64(p, cconst_from_cg(p, ty, v));
    630 }
    631 
    632 static void c_const_check_divrem(Parser* p, BinOp bop, SrcLoc loc) {
    633   KitCgConstInt rhs;
    634   if (!c_const_guard_active(p)) return;
    635   if (bop != BO_SDIV && bop != BO_UDIV && bop != BO_SREM && bop != BO_UREM)
    636     return;
    637   if (kit_cg_top_const_int_ex(p->cg, &rhs) && cg_const_is_zero(rhs)) {
    638     compiler_panic(p->c, loc,
    639                    (bop == BO_SDIV || bop == BO_UDIV)
    640                        ? "division by zero in constant"
    641                        : "modulo by zero in constant");
    642   }
    643 }
    644 
    645 static void c_const_check_shift(Parser* p, BinOp bop, SrcLoc loc) {
    646   KitCgConstInt lhs;
    647   KitCgConstInt rhs;
    648   const Type* lhs_ty;
    649   i64 sh;
    650   if (!c_const_guard_active(p)) return;
    651   if (bop != BO_SHL && bop != BO_SHR_S && bop != BO_SHR_U) return;
    652   if (!kit_cg_top_const_int_ex(p->cg, &rhs)) return;
    653   lhs_ty = c_cg_top2_type(p);
    654   sh = cg_const_as_i64(p, c_cg_top_type(p), rhs);
    655   if (sh < 0 || sh >= (i64)integer_type_bits(p, lhs_ty)) {
    656     compiler_panic(p->c, loc,
    657                    "shift count out of range in constant expression");
    658   }
    659   if (bop == BO_SHL && integer_type_signed(p, lhs_ty) &&
    660       cg_top2_const_int(p, &lhs) && cg_const_as_i64(p, lhs_ty, lhs) < 0) {
    661     compiler_panic(p->c, loc,
    662                    "left shift of negative value in constant expression");
    663   }
    664 }
    665 
    666 CConstInt eval_const_int_typed(Parser* p, SrcLoc loc) {
    667   CConstGuardMark mark;
    668   KitCgConstInt cg_value;
    669   CConstInt value;
    670   const Type* ty;
    671   const char* guard_error = NULL;
    672   SrcLoc guard_loc;
    673   int has_const;
    674   u32 start_cg_depth;
    675 
    676   memset(&cg_value, 0, sizeof cg_value);
    677   memset(&value, 0, sizeof value);
    678   memset(&guard_loc, 0, sizeof guard_loc);
    679   start_cg_depth = kit_cg_stack_depth(p->cg);
    680 
    681   mark = c_const_guard_push(p);
    682   kit_cg_unevaluated_push(p->cg);
    683   parse_cond_expr(p);
    684   ty = c_cg_top_type(p);
    685   has_const = kit_cg_top_const_int_ex(p->cg, &cg_value);
    686   c_cg_drop_to_depth(p, start_cg_depth);
    687   kit_cg_unevaluated_pop(p->cg);
    688   if (!c_const_guard_pop(p, mark, &guard_error, &guard_loc)) {
    689     compiler_panic(p->c, guard_loc, "%.*s",
    690                    KIT_SLICE_ARG(kit_slice_cstr(guard_error)));
    691   }
    692 
    693   if (kit_cg_stack_depth(p->cg) != start_cg_depth) {
    694     compiler_panic(p->c, loc,
    695                    "internal parser constant expression stack imbalance");
    696   }
    697   if (!type_is_int(ty)) perr(p, "integer constant expression required");
    698   if (!has_const) perr(p, "integer constant expression required");
    699   value = cconst_from_cg(p, ty, cg_value);
    700   return value;
    701 }
    702 
    703 i64 eval_const_int(Parser* p, SrcLoc loc) {
    704   return const_int_as_i64(p, eval_const_int_typed(p, loc));
    705 }
    706 
    707 /* ============================================================
    708  * to_rvalue
    709  * ============================================================ */
    710 
    711 static void decay_array_to_pointer(Parser* p, const Type* arr_ty) {
    712   c_cg_decay_array(p, arr_ty);
    713 }
    714 
    715 static FrameSlot vla_size_slot_for_type(VLABound* bounds, const Type* ty) {
    716   for (VLABound* b = bounds; b; b = b->next) {
    717     if (b->array_ty == ty) return b->byte_slot;
    718   }
    719   return FRAME_SLOT_NONE;
    720 }
    721 
    722 void to_rvalue(Parser* p) {
    723   const Type* t = c_cg_top_type(p);
    724   int is_lvalue = c_cg_top_is_lvalue(p);
    725   if (t) {
    726     if (t->kind == TY_ARRAY) {
    727       decay_array_to_pointer(p, t);
    728       return;
    729     }
    730     if (t->kind == TY_FUNC) {
    731       c_cg_addr(p);
    732       return;
    733     }
    734     if (t->kind == TY_STRUCT || t->kind == TY_UNION) {
    735       const Type* uty = type_unqual(p->pool, t);
    736       c_cg_retag_keep_flags(p, 0, uty);
    737       return;
    738     }
    739   }
    740   if (is_lvalue) c_cg_load(p);
    741 }
    742 
    743 /* ============================================================
    744  * coerce_top_to_lvalue (used by assignment / initializers)
    745  * ============================================================ */
    746 
    747 void coerce_top_to_lvalue(Parser* p) {
    748   const Type* src = c_cg_top_type(p);
    749   const Type* dst = c_cg_top2_type(p);
    750   if (!src || !dst || src == dst) return;
    751   if (type_is_arith(src) && type_is_arith(dst)) {
    752     c_cg_convert(p, dst);
    753   } else if (type_is_arith(src) && type_is_ptr(dst)) {
    754     c_cg_convert(p, dst);
    755   } else if (type_is_ptr(src) && type_is_ptr(dst)) {
    756     c_cg_convert(p, dst);
    757   }
    758 }
    759 
    760 void coerce_top_to_type(Parser* p, const Type* dst) {
    761   const Type* src = c_cg_top_type(p);
    762   if (!src || !dst || src == dst) return;
    763   if (type_is_arith(src) && type_is_arith(dst)) {
    764     c_cg_convert(p, dst);
    765   } else if (type_is_arith(src) && type_is_ptr(dst)) {
    766     c_cg_convert(p, dst);
    767   } else if (type_is_ptr(src) && type_is_ptr(dst)) {
    768     c_cg_convert(p, dst);
    769   }
    770 }
    771 
    772 static const Type* atomic_pointee_type(Parser* p, const Type* ptr_ty,
    773                                        const char* who) {
    774   if (!ptr_ty || ptr_ty->kind != TY_PTR) {
    775     perr(p, "%.*s: pointer argument must have pointer type",
    776          KIT_SLICE_ARG(kit_slice_cstr(who)));
    777   }
    778   return ptr_ty->ptr.pointee;
    779 }
    780 
    781 static const Type* atomic_lock_free_type_for_size(Parser* p, i64 size) {
    782   const Type* ty = NULL;
    783   switch (size) {
    784     case 1:
    785       ty = type_prim(p->pool, TY_UCHAR);
    786       break;
    787     case 2:
    788       ty = type_prim(p->pool, TY_USHORT);
    789       break;
    790     case 4:
    791       ty = type_prim(p->pool, TY_UINT);
    792       break;
    793     case 8:
    794       ty = type_prim(p->pool, TY_ULLONG);
    795       break;
    796     case 16:
    797       ty = type_prim(p->pool, TY_UINT128);
    798       break;
    799     default:
    800       return NULL;
    801   }
    802   return c_abi_sizeof(p->abi, p->pool, ty) == (u32)size ? ty : NULL;
    803 }
    804 
    805 static int atomic_lock_free_for_const_size(Parser* p, i64 size) {
    806   if (size <= 0 || size > 16) return 0;
    807   const Type* ty = atomic_lock_free_type_for_size(p, size);
    808   return ty ? kit_cg_atomic_is_lock_free(p->c, c_cg_mem(p, ty)) : 0;
    809 }
    810 
    811 static KitCgSym builtin_libcall_sym(Parser* p, const char* name,
    812                                     const Type* fn_ty) {
    813   KitCgDecl decl;
    814   Sym source_name = kit_sym_intern(p->pool->c, kit_slice_cstr(name));
    815   memset(&decl, 0, sizeof decl);
    816   decl.kind = KIT_CG_DECL_FUNC;
    817   decl.display_name = source_name;
    818   decl.linkage_name = kit_cg_c_linkage_name(p->c, source_name);
    819   decl.type = c_cg_tid(p, fn_ty);
    820   decl.sym.bind = KIT_SB_GLOBAL;
    821   decl.sym.visibility = KIT_CG_VIS_DEFAULT;
    822   decl.as.func.debug_type = type_cg_debug_in_pool(p->cg, p->c, p->pool, fn_ty);
    823   return kit_cg_decl(p->cg, decl);
    824 }
    825 
    826 static int parse_builtin_mem_call(Parser* p, Sym name, SrcLoc loc) {
    827   const Type* void_ty = type_void(p->pool);
    828   const Type* void_ptr_ty = type_ptr(p->pool, void_ty);
    829   const Type* const_void_ptr_ty =
    830       type_ptr(p->pool, type_qualified(p->pool, void_ty, Q_CONST));
    831   const Type* size_ty = ty_size_t(p);
    832   const Type* int_ty = ty_int(p);
    833   const Type* params[3];
    834   const Type* fn_ty;
    835   const char* libname;
    836   KitCgSym sym;
    837 
    838   advance(p); /* IDENT */
    839   expect_punct(p, '(', "'(' after builtin");
    840 
    841   if (name == p->sym_b_memcpy || name == p->sym_b_memmove) {
    842     libname = name == p->sym_b_memcpy ? "memcpy" : "memmove";
    843     parse_assign_expr(p);
    844     to_rvalue(p);
    845     coerce_top_to_type(p, void_ptr_ty);
    846     expect_punct(p, ',', "',' in memory builtin");
    847     parse_assign_expr(p);
    848     to_rvalue(p);
    849     coerce_top_to_type(p, const_void_ptr_ty);
    850     expect_punct(p, ',', "',' in memory builtin");
    851     parse_assign_expr(p);
    852     to_rvalue(p);
    853     coerce_top_to_type(p, size_ty);
    854     expect_punct(p, ')', "')' after memory builtin");
    855     params[0] = void_ptr_ty;
    856     params[1] = const_void_ptr_ty;
    857     params[2] = size_ty;
    858     fn_ty = type_func(p->pool, void_ptr_ty, params, 3, 0);
    859   } else if (name == p->sym_b_memset) {
    860     libname = "memset";
    861     parse_assign_expr(p);
    862     to_rvalue(p);
    863     coerce_top_to_type(p, void_ptr_ty);
    864     expect_punct(p, ',', "',' in __builtin_memset");
    865     parse_assign_expr(p);
    866     to_rvalue(p);
    867     coerce_top_to_type(p, int_ty);
    868     expect_punct(p, ',', "',' in __builtin_memset");
    869     parse_assign_expr(p);
    870     to_rvalue(p);
    871     coerce_top_to_type(p, size_ty);
    872     expect_punct(p, ')', "')' after __builtin_memset");
    873     params[0] = void_ptr_ty;
    874     params[1] = int_ty;
    875     params[2] = size_ty;
    876     fn_ty = type_func(p->pool, void_ptr_ty, params, 3, 0);
    877   } else {
    878     libname = "memcmp";
    879     parse_assign_expr(p);
    880     to_rvalue(p);
    881     coerce_top_to_type(p, const_void_ptr_ty);
    882     expect_punct(p, ',', "',' in __builtin_memcmp");
    883     parse_assign_expr(p);
    884     to_rvalue(p);
    885     coerce_top_to_type(p, const_void_ptr_ty);
    886     expect_punct(p, ',', "',' in __builtin_memcmp");
    887     parse_assign_expr(p);
    888     to_rvalue(p);
    889     coerce_top_to_type(p, size_ty);
    890     expect_punct(p, ')', "')' after __builtin_memcmp");
    891     params[0] = const_void_ptr_ty;
    892     params[1] = const_void_ptr_ty;
    893     params[2] = size_ty;
    894     fn_ty = type_func(p->pool, int_ty, params, 3, 0);
    895   }
    896 
    897   sym = builtin_libcall_sym(p, libname, fn_ty);
    898   c_cg_set_loc(p, loc);
    899   c_cg_call_symbol(p, sym, 3, fn_ty);
    900   return 1;
    901 }
    902 
    903 static int parse_builtin_clear_cache_call(Parser* p, Sym name, SrcLoc loc) {
    904   const Type* void_ty = type_void(p->pool);
    905   const Type* void_ptr_ty = type_ptr(p->pool, void_ty);
    906   const Type* params[2];
    907   const Type* fn_ty;
    908   KitCgSym sym;
    909 
    910   if (name != p->sym_b_clear_cache) return 0;
    911 
    912   advance(p); /* IDENT */
    913   expect_punct(p, '(', "'(' after __builtin___clear_cache");
    914   parse_assign_expr(p);
    915   to_rvalue(p);
    916   coerce_top_to_type(p, void_ptr_ty);
    917   expect_punct(p, ',', "',' in __builtin___clear_cache");
    918   parse_assign_expr(p);
    919   to_rvalue(p);
    920   coerce_top_to_type(p, void_ptr_ty);
    921   expect_punct(p, ')', "')' after __builtin___clear_cache");
    922 
    923   /* Instruction-cache coherency is automatic on x86, and wasm has no separate
    924    * I-cache to flush (the engine handles code installation), so
    925    * __builtin___clear_cache is a no-op on those targets — matching GCC/Clang.
    926    * Emitting the __clear_cache libcall there would reference an undefined
    927    * symbol. Targets that need explicit coherency (ARM, RISC-V) keep the call.
    928    * The argument expressions are still evaluated for their side effects. The
    929    * coherency fact is a backend capability, not an arch identity. */
    930   if (kit_cg_target_backend_features(p->c) & KIT_CG_BACKEND_ICACHE_COHERENT) {
    931     c_cg_drop(p);
    932     c_cg_drop(p);
    933     c_cg_push_int(p, 0, ty_int(p));
    934     return 1;
    935   }
    936 
    937   params[0] = void_ptr_ty;
    938   params[1] = void_ptr_ty;
    939   fn_ty = type_func(p->pool, void_ty, params, 2, 0);
    940   sym = builtin_libcall_sym(p, "__clear_cache", fn_ty);
    941   c_cg_set_loc(p, loc);
    942   c_cg_call_symbol(p, sym, 2, fn_ty);
    943   c_cg_push_int(p, 0, ty_int(p));
    944   return 1;
    945 }
    946 
    947 static MemOrder parse_atomic_mem_order(Parser* p) {
    948   if (p->cur.kind == TOK_NUM) {
    949     return (MemOrder)eval_const_int(p, pp_materialize_loc(p->pp, p->cur.loc));
    950   }
    951   parse_assign_expr(p);
    952   to_rvalue(p);
    953   c_cg_drop(p);
    954   return MO_SEQ_CST;
    955 }
    956 
    957 /* ============================================================
    958  * Builtin call handling
    959  * ============================================================ */
    960 
    961 static int offsetof_find_member(Parser* p, const Type* rec_ty, Sym mname,
    962                                 const Type** out_ty, u32* out_off) {
    963   const ABIRecordLayout* L;
    964   rec_ty = type_unqual(p->pool, rec_ty);
    965   if (!rec_ty || (rec_ty->kind != TY_STRUCT && rec_ty->kind != TY_UNION))
    966     return 0;
    967   L = c_abi_record_layout(p->abi, p->pool, rec_ty);
    968   if (!L) return 0;
    969   for (u16 i = 0; i < rec_ty->rec.nfields; ++i) {
    970     const Field* f = &rec_ty->rec.fields[i];
    971     if (f->name == mname && mname != 0) {
    972       *out_ty = f->type;
    973       *out_off = L->fields[i].offset;
    974       return 1;
    975     }
    976   }
    977   for (u16 i = 0; i < rec_ty->rec.nfields; ++i) {
    978     const Field* f = &rec_ty->rec.fields[i];
    979     const Type* fty = type_unqual(p->pool, f->type);
    980     const Type* nested_ty = NULL;
    981     u32 nested_off = 0;
    982     if (!((f->flags & FIELD_ANON) &&
    983           (fty->kind == TY_STRUCT || fty->kind == TY_UNION))) {
    984       continue;
    985     }
    986     if (offsetof_find_member(p, fty, mname, &nested_ty, &nested_off)) {
    987       *out_ty = nested_ty;
    988       *out_off = L->fields[i].offset + nested_off;
    989       return 1;
    990     }
    991   }
    992   return 0;
    993 }
    994 
    995 static const Type* offsetof_designator(Parser* p, const Type* base, u32* off) {
    996   const Type* cur = base;
    997   if (p->cur.kind != TOK_IDENT ||
    998       ident_kw_inline(p, tok_ident(&p->cur)) != KW_NONE) {
    999     perr(p, "expected member name in __builtin_offsetof");
   1000   }
   1001   for (;;) {
   1002     if (cur->kind == TY_STRUCT || cur->kind == TY_UNION) {
   1003       Sym mname = tok_ident(&p->cur);
   1004       const Type* mty = NULL;
   1005       u32 moff = 0;
   1006       if (!offsetof_find_member(p, cur, mname, &mty, &moff))
   1007         perr(p, "no such member in __builtin_offsetof");
   1008       advance(p);
   1009       *off += moff;
   1010       cur = mty;
   1011     } else if (cur->kind == TY_ARRAY) {
   1012       /* fall through to bracket branch */
   1013     } else {
   1014       perr(p, "__builtin_offsetof step into non-aggregate");
   1015     }
   1016     if (is_punct(&p->cur, '.')) {
   1017       advance(p);
   1018       if (p->cur.kind != TOK_IDENT ||
   1019           ident_kw_inline(p, tok_ident(&p->cur)) != KW_NONE) {
   1020         perr(p, "expected member name after '.'");
   1021       }
   1022       continue;
   1023     }
   1024     if (is_punct(&p->cur, '[')) {
   1025       advance(p);
   1026       i64 idx = eval_const_int(p, pp_materialize_loc(p->pp, p->cur.loc));
   1027       expect_punct(p, ']', "']' in __builtin_offsetof");
   1028       if (cur->kind != TY_ARRAY) {
   1029         perr(p, "__builtin_offsetof '[' on non-array");
   1030       }
   1031       *off += (u32)((i64)c_abi_sizeof(p->abi, p->pool, cur->arr.elem) * idx);
   1032       cur = cur->arr.elem;
   1033       continue;
   1034     }
   1035     break;
   1036   }
   1037   return cur;
   1038 }
   1039 
   1040 typedef struct BuiltinOverflowInfo {
   1041   KitCgIntrinsic intrin;
   1042   TypeKind type_kind;
   1043   const char* name;
   1044 } BuiltinOverflowInfo;
   1045 
   1046 static int sym_eq_cstr(Parser* p, Sym sym, const char* want) {
   1047   KitSlice got = kit_sym_str(p->pool->c, sym);
   1048   return got.s && kit_slice_eq_cstr(got, want);
   1049 }
   1050 
   1051 static int builtin_overflow_info(Parser* p, Sym name,
   1052                                  BuiltinOverflowInfo* out) {
   1053   static const BuiltinOverflowInfo infos[] = {
   1054       {KIT_CG_INTRIN_SADD_OVERFLOW, TY_INT, "__builtin_sadd_overflow"},
   1055       {KIT_CG_INTRIN_SADD_OVERFLOW, TY_LONG, "__builtin_saddl_overflow"},
   1056       {KIT_CG_INTRIN_SADD_OVERFLOW, TY_LLONG, "__builtin_saddll_overflow"},
   1057       {KIT_CG_INTRIN_UADD_OVERFLOW, TY_UINT, "__builtin_uadd_overflow"},
   1058       {KIT_CG_INTRIN_UADD_OVERFLOW, TY_ULONG, "__builtin_uaddl_overflow"},
   1059       {KIT_CG_INTRIN_UADD_OVERFLOW, TY_ULLONG, "__builtin_uaddll_overflow"},
   1060       {KIT_CG_INTRIN_SSUB_OVERFLOW, TY_INT, "__builtin_ssub_overflow"},
   1061       {KIT_CG_INTRIN_SSUB_OVERFLOW, TY_LONG, "__builtin_ssubl_overflow"},
   1062       {KIT_CG_INTRIN_SSUB_OVERFLOW, TY_LLONG, "__builtin_ssubll_overflow"},
   1063       {KIT_CG_INTRIN_USUB_OVERFLOW, TY_UINT, "__builtin_usub_overflow"},
   1064       {KIT_CG_INTRIN_USUB_OVERFLOW, TY_ULONG, "__builtin_usubl_overflow"},
   1065       {KIT_CG_INTRIN_USUB_OVERFLOW, TY_ULLONG, "__builtin_usubll_overflow"},
   1066       {KIT_CG_INTRIN_SMUL_OVERFLOW, TY_INT, "__builtin_smul_overflow"},
   1067       {KIT_CG_INTRIN_SMUL_OVERFLOW, TY_LONG, "__builtin_smull_overflow"},
   1068       {KIT_CG_INTRIN_SMUL_OVERFLOW, TY_LLONG, "__builtin_smulll_overflow"},
   1069       {KIT_CG_INTRIN_UMUL_OVERFLOW, TY_UINT, "__builtin_umul_overflow"},
   1070       {KIT_CG_INTRIN_UMUL_OVERFLOW, TY_ULONG, "__builtin_umull_overflow"},
   1071       {KIT_CG_INTRIN_UMUL_OVERFLOW, TY_ULLONG, "__builtin_umulll_overflow"},
   1072   };
   1073   size_t i;
   1074   for (i = 0; i < sizeof(infos) / sizeof(infos[0]); ++i) {
   1075     if (sym_eq_cstr(p, name, infos[i].name)) {
   1076       if (out) *out = infos[i];
   1077       return 1;
   1078     }
   1079   }
   1080   return 0;
   1081 }
   1082 
   1083 static FrameSlot builtin_tmp_slot(Parser* p, const Type* ty) {
   1084   FrameSlotDesc fsd;
   1085   memset(&fsd, 0, sizeof fsd);
   1086   fsd.type = ty;
   1087   fsd.size = c_abi_sizeof(p->abi, p->pool, ty);
   1088   fsd.align = c_abi_alignof(p->abi, p->pool, ty);
   1089   fsd.kind = FS_LOCAL;
   1090   return c_cg_local(p, &fsd);
   1091 }
   1092 
   1093 static void builtin_store_top(Parser* p, FrameSlot slot, const Type* ty) {
   1094   c_cg_push_local_typed(p, slot, ty);
   1095   c_cg_swap(p);
   1096   c_cg_store_void(p);
   1097 }
   1098 
   1099 static void builtin_load_slot(Parser* p, FrameSlot slot, const Type* ty) {
   1100   c_cg_push_local_typed(p, slot, ty);
   1101   c_cg_load(p);
   1102 }
   1103 
   1104 typedef struct BuiltinBitInfo {
   1105   const char* name;
   1106   KitCgIntrinsic intrin;
   1107   TypeKind arg_kind;
   1108   TypeKind result_kind;
   1109 } BuiltinBitInfo;
   1110 
   1111 static int parse_builtin_bit_call(Parser* p, Sym name, SrcLoc loc) {
   1112   static const BuiltinBitInfo infos[] = {
   1113       {"__builtin_popcount", KIT_CG_INTRIN_POPCOUNT, TY_UINT, TY_INT},
   1114       {"__builtin_popcountl", KIT_CG_INTRIN_POPCOUNT, TY_ULONG, TY_INT},
   1115       {"__builtin_popcountll", KIT_CG_INTRIN_POPCOUNT, TY_ULLONG, TY_INT},
   1116       {"__builtin_bswap16", KIT_CG_INTRIN_BSWAP, TY_USHORT, TY_USHORT},
   1117       {"__builtin_bswap32", KIT_CG_INTRIN_BSWAP, TY_UINT, TY_UINT},
   1118       {"__builtin_bswap64", KIT_CG_INTRIN_BSWAP, TY_ULLONG, TY_ULLONG},
   1119   };
   1120   const BuiltinBitInfo* info = NULL;
   1121   const Type* arg_ty;
   1122   const Type* result_ty;
   1123   size_t i;
   1124   for (i = 0; i < sizeof infos / sizeof infos[0]; ++i) {
   1125     if (sym_eq_cstr(p, name, infos[i].name)) {
   1126       info = &infos[i];
   1127       break;
   1128     }
   1129   }
   1130   if (!info) return 0;
   1131   arg_ty = type_prim(p->pool, info->arg_kind);
   1132   result_ty = type_prim(p->pool, info->result_kind);
   1133   advance(p);
   1134   expect_punct(p, '(', "'(' after bit builtin");
   1135   parse_assign_expr(p);
   1136   to_rvalue(p);
   1137   coerce_top_to_type(p, arg_ty);
   1138   expect_punct(p, ')', "')' after bit builtin");
   1139   c_cg_set_loc(p, loc);
   1140   kit_cg_intrinsic(p->cg, info->intrin, 1, c_cg_tid(p, result_ty));
   1141   c_cg_retag_top(p, result_ty);
   1142   return 1;
   1143 }
   1144 
   1145 typedef struct BuiltinRotateInfo {
   1146   const char* name;
   1147   TypeKind type_kind;
   1148   u8 left;
   1149 } BuiltinRotateInfo;
   1150 
   1151 static int parse_builtin_rotate_call(Parser* p, Sym name) {
   1152   static const BuiltinRotateInfo infos[] = {
   1153       {"__builtin_rotateleft8", TY_UCHAR, 1},
   1154       {"__builtin_rotateleft16", TY_USHORT, 1},
   1155       {"__builtin_rotateleft32", TY_UINT, 1},
   1156       {"__builtin_rotateleft64", TY_ULLONG, 1},
   1157       {"__builtin_rotateright8", TY_UCHAR, 0},
   1158       {"__builtin_rotateright16", TY_USHORT, 0},
   1159       {"__builtin_rotateright32", TY_UINT, 0},
   1160       {"__builtin_rotateright64", TY_ULLONG, 0},
   1161   };
   1162   const BuiltinRotateInfo* info = NULL;
   1163   const Type* ty;
   1164   FrameSlot value_slot;
   1165   FrameSlot count_slot;
   1166   u32 bits;
   1167   size_t i;
   1168   for (i = 0; i < sizeof infos / sizeof infos[0]; ++i) {
   1169     if (sym_eq_cstr(p, name, infos[i].name)) {
   1170       info = &infos[i];
   1171       break;
   1172     }
   1173   }
   1174   if (!info) return 0;
   1175   ty = type_prim(p->pool, info->type_kind);
   1176   bits = integer_type_bits(p, ty);
   1177   value_slot = builtin_tmp_slot(p, ty);
   1178   count_slot = builtin_tmp_slot(p, ty);
   1179 
   1180   advance(p);
   1181   expect_punct(p, '(', "'(' after rotate builtin");
   1182   parse_assign_expr(p);
   1183   to_rvalue(p);
   1184   coerce_top_to_type(p, ty);
   1185   builtin_store_top(p, value_slot, ty);
   1186   expect_punct(p, ',', "',' in rotate builtin");
   1187   parse_assign_expr(p);
   1188   to_rvalue(p);
   1189   coerce_top_to_type(p, ty);
   1190   builtin_store_top(p, count_slot, ty);
   1191   expect_punct(p, ')', "')' after rotate builtin");
   1192 
   1193   /* CG shifts with KIT_CG_INTOP_NONE reduce the count modulo the operand
   1194    * width. Thus width-count deliberately becomes a zero shift when count is
   1195    * zero, avoiding the undefined full-width shift in the equivalent C idiom. */
   1196   builtin_load_slot(p, value_slot, ty);
   1197   builtin_load_slot(p, count_slot, ty);
   1198   c_cg_binop(p, info->left ? BO_SHL : BO_SHR_U);
   1199   builtin_load_slot(p, value_slot, ty);
   1200   c_cg_push_int(p, (i64)bits, ty);
   1201   builtin_load_slot(p, count_slot, ty);
   1202   c_cg_binop(p, BO_ISUB);
   1203   c_cg_binop(p, info->left ? BO_SHR_U : BO_SHL);
   1204   c_cg_binop(p, BO_OR);
   1205   return 1;
   1206 }
   1207 
   1208 static int parse_builtin_prefetch_call(Parser* p, Sym name, SrcLoc loc) {
   1209   const Type* ptr_ty;
   1210   u32 nargs = 1;
   1211   i64 rw = 0;
   1212   i64 locality = 3;
   1213   if (!sym_eq_cstr(p, name, "__builtin_prefetch")) return 0;
   1214   advance(p);
   1215   expect_punct(p, '(', "'(' after __builtin_prefetch");
   1216   parse_assign_expr(p);
   1217   to_rvalue(p);
   1218   ptr_ty = c_cg_top_type(p);
   1219   if (!ptr_ty || ptr_ty->kind != TY_PTR)
   1220     perr(p, "__builtin_prefetch address must be a pointer");
   1221   if (accept_punct(p, ',')) {
   1222     rw = eval_const_int(p, pp_materialize_loc(p->pp, p->cur.loc));
   1223     if (rw < 0 || rw > 1) perr(p, "__builtin_prefetch rw must be 0 or 1");
   1224     c_cg_push_int(p, rw, ty_int(p));
   1225     nargs = 2;
   1226     if (accept_punct(p, ',')) {
   1227       locality = eval_const_int(p, pp_materialize_loc(p->pp, p->cur.loc));
   1228       if (locality < 0 || locality > 3)
   1229         perr(p, "__builtin_prefetch locality must be in [0, 3]");
   1230       c_cg_push_int(p, locality, ty_int(p));
   1231       nargs = 3;
   1232     }
   1233   }
   1234   expect_punct(p, ')', "')' after __builtin_prefetch");
   1235   c_cg_set_loc(p, loc);
   1236   kit_cg_intrinsic(p->cg, KIT_CG_INTRIN_PREFETCH, nargs,
   1237                    c_cg_tid(p, type_void(p->pool)));
   1238   c_cg_push_int(p, 0, ty_int(p));
   1239   return 1;
   1240 }
   1241 
   1242 static int parse_builtin_assume_aligned_call(Parser* p, Sym name, SrcLoc loc) {
   1243   const Type* ptr_ty;
   1244   i64 align;
   1245   i64 offset = 0;
   1246   u32 nargs = 2;
   1247   if (!sym_eq_cstr(p, name, "__builtin_assume_aligned")) return 0;
   1248   advance(p);
   1249   expect_punct(p, '(', "'(' after __builtin_assume_aligned");
   1250   parse_assign_expr(p);
   1251   to_rvalue(p);
   1252   ptr_ty = c_cg_top_type(p);
   1253   if (!ptr_ty || ptr_ty->kind != TY_PTR)
   1254     perr(p, "__builtin_assume_aligned argument must be a pointer");
   1255   expect_punct(p, ',', "',' in __builtin_assume_aligned");
   1256   align = eval_const_int(p, pp_materialize_loc(p->pp, p->cur.loc));
   1257   if (align <= 0 || ((u64)align & ((u64)align - 1u)) != 0)
   1258     perr(p, "__builtin_assume_aligned alignment must be a power of two");
   1259   c_cg_push_int(p, align, ty_size_t(p));
   1260   if (accept_punct(p, ',')) {
   1261     offset = eval_const_int(p, pp_materialize_loc(p->pp, p->cur.loc));
   1262     c_cg_push_int(p, offset, ty_size_t(p));
   1263     nargs = 3;
   1264   }
   1265   expect_punct(p, ')', "')' after __builtin_assume_aligned");
   1266   c_cg_set_loc(p, loc);
   1267   kit_cg_intrinsic(p->cg, KIT_CG_INTRIN_ASSUME_ALIGNED, nargs,
   1268                    c_cg_tid(p, ptr_ty));
   1269   c_cg_retag_top(p, ptr_ty);
   1270   return 1;
   1271 }
   1272 
   1273 static int parse_builtin_cpu_relax_call(Parser* p, Sym name, SrcLoc loc) {
   1274   if (!sym_eq_cstr(p, name, "__builtin_kit_cpu_relax")) return 0;
   1275   advance(p);
   1276   expect_punct(p, '(', "'(' after __builtin_kit_cpu_relax");
   1277   expect_punct(p, ')', "')' after __builtin_kit_cpu_relax");
   1278   c_cg_set_loc(p, loc);
   1279   kit_cg_intrinsic(p->cg, KIT_CG_INTRIN_CPU_YIELD, 0,
   1280                    c_cg_tid(p, type_void(p->pool)));
   1281   c_cg_push_int(p, 0, ty_int(p));
   1282   return 1;
   1283 }
   1284 
   1285 static int parse_builtin_target_has_call(Parser* p, Sym name) {
   1286   Tok tok;
   1287   u8* bytes;
   1288   size_t nbytes = 0;
   1289   int enabled;
   1290   Heap* h;
   1291   if (!sym_eq_cstr(p, name, "__builtin_kit_target_has")) return 0;
   1292   advance(p);
   1293   expect_punct(p, '(', "'(' after __builtin_kit_target_has");
   1294   if (p->cur.kind != TOK_STR ||
   1295       (p->cur.flags & (TF_STR_WIDE | TF_STR_U16 | TF_STR_U32)))
   1296     perr(p, "__builtin_kit_target_has expects an ordinary string literal");
   1297   tok = p->cur;
   1298   bytes = decode_string_literal(p, &tok, &nbytes);
   1299   advance(p);
   1300   expect_punct(p, ')', "')' after __builtin_kit_target_has");
   1301   enabled = kit_target_has_feature(
   1302       kit_compiler_target(p->c),
   1303       (KitSlice){.s = (const char*)bytes, .len = nbytes ? nbytes - 1u : 0u});
   1304   h = kit_compiler_context(p->c)->heap;
   1305   h->free(h, bytes, 0);
   1306   c_cg_push_int(p, enabled, ty_int(p));
   1307   return 1;
   1308 }
   1309 
   1310 typedef struct BuiltinCarryInfo {
   1311   const char* name;
   1312   TypeKind type_kind;
   1313   u8 subtract;
   1314 } BuiltinCarryInfo;
   1315 
   1316 static int parse_builtin_carry_call(Parser* p, Sym name, SrcLoc loc) {
   1317   static const BuiltinCarryInfo infos[] = {
   1318       {"__builtin_addc", TY_UINT, 0},       {"__builtin_addcl", TY_ULONG, 0},
   1319       {"__builtin_addcll", TY_ULLONG, 0},  {"__builtin_subc", TY_UINT, 1},
   1320       {"__builtin_subcl", TY_ULONG, 1},    {"__builtin_subcll", TY_ULLONG, 1},
   1321   };
   1322   const BuiltinCarryInfo* info = NULL;
   1323   const Type* ty;
   1324   const Type* bool_ty = type_prim(p->pool, TY_BOOL);
   1325   const Type* ptr_ty;
   1326   FrameSlot a_slot, b_slot, in_slot, ptr_slot, value_slot, flag1_slot;
   1327   KitCgIntrinsic intrin;
   1328   size_t i;
   1329   for (i = 0; i < sizeof infos / sizeof infos[0]; ++i) {
   1330     if (sym_eq_cstr(p, name, infos[i].name)) {
   1331       info = &infos[i];
   1332       break;
   1333     }
   1334   }
   1335   if (!info) return 0;
   1336   ty = type_prim(p->pool, info->type_kind);
   1337   a_slot = builtin_tmp_slot(p, ty);
   1338   b_slot = builtin_tmp_slot(p, ty);
   1339   in_slot = builtin_tmp_slot(p, ty);
   1340   value_slot = builtin_tmp_slot(p, ty);
   1341   flag1_slot = builtin_tmp_slot(p, bool_ty);
   1342   intrin = info->subtract ? KIT_CG_INTRIN_USUB_OVERFLOW
   1343                           : KIT_CG_INTRIN_UADD_OVERFLOW;
   1344 
   1345   advance(p);
   1346   expect_punct(p, '(', "'(' after carry builtin");
   1347   parse_assign_expr(p);
   1348   to_rvalue(p);
   1349   coerce_top_to_type(p, ty);
   1350   builtin_store_top(p, a_slot, ty);
   1351   expect_punct(p, ',', "',' in carry builtin");
   1352   parse_assign_expr(p);
   1353   to_rvalue(p);
   1354   coerce_top_to_type(p, ty);
   1355   builtin_store_top(p, b_slot, ty);
   1356   expect_punct(p, ',', "',' in carry builtin");
   1357   parse_assign_expr(p);
   1358   to_rvalue(p);
   1359   coerce_top_to_type(p, ty);
   1360   builtin_store_top(p, in_slot, ty);
   1361   expect_punct(p, ',', "',' in carry builtin");
   1362   parse_assign_expr(p);
   1363   to_rvalue(p);
   1364   ptr_ty = c_cg_top_type(p);
   1365   if (!ptr_ty || ptr_ty->kind != TY_PTR ||
   1366       !type_compatible(type_unqual(p->pool, ptr_ty->ptr.pointee), ty))
   1367     perr(p, "carry builtin output must point to its unsigned operand type");
   1368   ptr_slot = builtin_tmp_slot(p, ptr_ty);
   1369   builtin_store_top(p, ptr_slot, ptr_ty);
   1370   expect_punct(p, ')', "')' after carry builtin");
   1371 
   1372   c_cg_set_loc(p, loc);
   1373   builtin_load_slot(p, a_slot, ty);
   1374   builtin_load_slot(p, b_slot, ty);
   1375   kit_cg_intrinsic(p->cg, intrin, 2, c_cg_tid(p, ty));
   1376   c_cg_retag_at(p, 1, ty, 0);
   1377   c_cg_retag_top(p, bool_ty);
   1378   builtin_store_top(p, flag1_slot, bool_ty);
   1379   builtin_store_top(p, value_slot, ty);
   1380 
   1381   builtin_load_slot(p, value_slot, ty);
   1382   builtin_load_slot(p, in_slot, ty);
   1383   kit_cg_intrinsic(p->cg, intrin, 2, c_cg_tid(p, ty));
   1384   c_cg_retag_at(p, 1, ty, 0);
   1385   c_cg_retag_top(p, bool_ty);
   1386   builtin_load_slot(p, flag1_slot, bool_ty);
   1387   c_cg_binop(p, BO_OR);
   1388   c_cg_convert(p, ty);
   1389 
   1390   builtin_load_slot(p, ptr_slot, ptr_ty);
   1391   c_cg_deref(p, ty);
   1392   c_cg_swap(p);
   1393   c_cg_store_void(p);
   1394   return 1; /* the second arithmetic result remains below the stored flag */
   1395 }
   1396 
   1397 typedef struct BuiltinMulHighInfo {
   1398   const char* name;
   1399   TypeKind type_kind;
   1400   KitCgIntrinsic intrin;
   1401 } BuiltinMulHighInfo;
   1402 
   1403 static int parse_builtin_mul_high_call(Parser* p, Sym name, SrcLoc loc) {
   1404   static const BuiltinMulHighInfo infos[] = {
   1405       {"__builtin_kit_umul_high32", TY_UINT, KIT_CG_INTRIN_UMUL_HIGH},
   1406       {"__builtin_kit_umul_high64", TY_ULLONG, KIT_CG_INTRIN_UMUL_HIGH},
   1407       {"__builtin_kit_smul_high32", TY_INT, KIT_CG_INTRIN_SMUL_HIGH},
   1408       {"__builtin_kit_smul_high64", TY_LLONG, KIT_CG_INTRIN_SMUL_HIGH},
   1409   };
   1410   const BuiltinMulHighInfo* info = NULL;
   1411   const Type* ty;
   1412   size_t i;
   1413   for (i = 0; i < sizeof infos / sizeof infos[0]; ++i) {
   1414     if (sym_eq_cstr(p, name, infos[i].name)) {
   1415       info = &infos[i];
   1416       break;
   1417     }
   1418   }
   1419   if (!info) return 0;
   1420   ty = type_prim(p->pool, info->type_kind);
   1421   advance(p);
   1422   expect_punct(p, '(', "'(' after multiply-high builtin");
   1423   parse_assign_expr(p);
   1424   to_rvalue(p);
   1425   coerce_top_to_type(p, ty);
   1426   expect_punct(p, ',', "',' in multiply-high builtin");
   1427   parse_assign_expr(p);
   1428   to_rvalue(p);
   1429   coerce_top_to_type(p, ty);
   1430   expect_punct(p, ')', "')' after multiply-high builtin");
   1431   c_cg_set_loc(p, loc);
   1432   kit_cg_intrinsic(p->cg, info->intrin, 2, c_cg_tid(p, ty));
   1433   c_cg_retag_top(p, ty);
   1434   return 1;
   1435 }
   1436 
   1437 /* The type-generic overflow builtins (no s/u + width suffix). They infer the
   1438  * operation type from the result pointer's pointee and the signed/unsigned
   1439  * intrinsic from that type's signedness, then reuse the same per-type
   1440  * KIT_CG_INTRIN_*_OVERFLOW machinery as the explicit __builtin_smull_overflow
   1441  * family. kit's own source uses these (e.g. cg_checked_scaled_offset), so they
   1442  * must self-host. */
   1443 typedef enum { OVF_ADD, OVF_SUB, OVF_MUL } OverflowOp;
   1444 
   1445 static int builtin_overflow_generic(Parser* p, Sym name, OverflowOp* op_out) {
   1446   static const struct {
   1447     OverflowOp op;
   1448     const char* name;
   1449   } g[] = {
   1450       {OVF_ADD, "__builtin_add_overflow"},
   1451       {OVF_SUB, "__builtin_sub_overflow"},
   1452       {OVF_MUL, "__builtin_mul_overflow"},
   1453   };
   1454   size_t i;
   1455   for (i = 0; i < sizeof(g) / sizeof(g[0]); ++i) {
   1456     if (sym_eq_cstr(p, name, g[i].name)) {
   1457       *op_out = g[i].op;
   1458       return 1;
   1459     }
   1460   }
   1461   return 0;
   1462 }
   1463 
   1464 static KitCgIntrinsic overflow_intrin_for(OverflowOp op, int is_signed) {
   1465   switch (op) {
   1466     case OVF_ADD:
   1467       return is_signed ? KIT_CG_INTRIN_SADD_OVERFLOW : KIT_CG_INTRIN_UADD_OVERFLOW;
   1468     case OVF_SUB:
   1469       return is_signed ? KIT_CG_INTRIN_SSUB_OVERFLOW : KIT_CG_INTRIN_USUB_OVERFLOW;
   1470     case OVF_MUL:
   1471     default:
   1472       return is_signed ? KIT_CG_INTRIN_SMUL_OVERFLOW : KIT_CG_INTRIN_UMUL_OVERFLOW;
   1473   }
   1474 }
   1475 
   1476 static int parse_builtin_overflow_call(Parser* p, Sym name, SrcLoc loc) {
   1477   BuiltinOverflowInfo info;
   1478   OverflowOp gop = OVF_ADD;
   1479   KitCgIntrinsic intrin;
   1480   const Type* op_ty;
   1481   const Type* ptr_ty;
   1482   const Type* out_ty;
   1483   const Type* bool_ty;
   1484   FrameSlot ptr_slot;
   1485   FrameSlot ov_slot;
   1486   int is_generic;
   1487 
   1488   if (builtin_overflow_info(p, name, &info)) {
   1489     is_generic = 0;
   1490     intrin = info.intrin;
   1491     op_ty = type_prim(p->pool, info.type_kind);
   1492   } else if (builtin_overflow_generic(p, name, &gop)) {
   1493     /* op_ty + intrin are resolved from the result pointee, parsed below. */
   1494     is_generic = 1;
   1495     intrin = KIT_CG_INTRIN_SADD_OVERFLOW;
   1496     op_ty = NULL;
   1497   } else {
   1498     return 0;
   1499   }
   1500   bool_ty = type_prim(p->pool, TY_BOOL);
   1501 
   1502   advance(p); /* IDENT */
   1503   expect_punct(p, '(', "'(' after overflow builtin");
   1504   parse_assign_expr(p);
   1505   to_rvalue(p);
   1506   if (!is_generic) coerce_top_to_type(p, op_ty);
   1507   expect_punct(p, ',', "',' in overflow builtin");
   1508   parse_assign_expr(p);
   1509   to_rvalue(p);
   1510   if (!is_generic) coerce_top_to_type(p, op_ty);
   1511   expect_punct(p, ',', "',' in overflow builtin");
   1512   parse_assign_expr(p);
   1513   to_rvalue(p);
   1514   ptr_ty = c_cg_top_type(p);
   1515   if (!ptr_ty || ptr_ty->kind != TY_PTR) {
   1516     perr(p, "overflow builtin result argument must be a pointer");
   1517   }
   1518   out_ty = ptr_ty->ptr.pointee;
   1519   if (is_generic) {
   1520     /* Result type (and thus the operation type) is the pointee; operands are
   1521      * coerced to it after the pointer is stashed (op_ty is unknown until now). */
   1522     const Type* res = type_unqual(p->pool, out_ty);
   1523     if (!type_is_int(res)) {
   1524       perr(p, "__builtin_*_overflow result must point to an integer");
   1525     }
   1526     op_ty = res;
   1527     intrin = overflow_intrin_for(gop, type_is_signed_integer(res));
   1528   } else if (!type_compatible(type_unqual(p->pool, out_ty), op_ty)) {
   1529     perr(p, "overflow builtin result pointer type mismatch");
   1530   }
   1531   expect_punct(p, ')', "')' after overflow builtin");
   1532 
   1533   ptr_slot = builtin_tmp_slot(p, ptr_ty);
   1534   c_cg_push_local_typed(p, ptr_slot, ptr_ty);
   1535   c_cg_swap(p);
   1536   c_cg_store_void(p);
   1537 
   1538   if (is_generic) {
   1539     /* Coerce both operands to the resolved op_ty now that the pointer is
   1540      * stashed (stack is [a, b], b on top). */
   1541     coerce_top_to_type(p, op_ty);
   1542     c_cg_swap(p);
   1543     coerce_top_to_type(p, op_ty);
   1544     c_cg_swap(p);
   1545   }
   1546 
   1547   c_cg_set_loc(p, loc);
   1548   kit_cg_intrinsic(p->cg, intrin, 2, c_cg_tid(p, op_ty));
   1549   c_cg_retag_at(p, 1, op_ty, 0);
   1550   c_cg_retag_top(p, bool_ty);
   1551 
   1552   ov_slot = builtin_tmp_slot(p, bool_ty);
   1553   c_cg_push_local_typed(p, ov_slot, bool_ty);
   1554   c_cg_swap(p);
   1555   c_cg_store_void(p);
   1556 
   1557   c_cg_push_local_typed(p, ptr_slot, ptr_ty);
   1558   c_cg_load(p);
   1559   c_cg_deref(p, out_ty);
   1560   c_cg_swap(p);
   1561   c_cg_store_void(p);
   1562 
   1563   c_cg_push_local_typed(p, ov_slot, bool_ty);
   1564   c_cg_load(p);
   1565   return 1;
   1566 }
   1567 
   1568 static int parse_builtin_isnan_call(Parser* p, Sym name, SrcLoc loc) {
   1569   const Type* arg_ty;
   1570   if (name != p->sym_b_isnan) return 0;
   1571 
   1572   reject_general_regs_only_fp(p, "floating-point builtins");
   1573   advance(p); /* IDENT */
   1574   expect_punct(p, '(', "'(' after __builtin_isnan");
   1575   parse_assign_expr(p);
   1576   to_rvalue(p);
   1577   arg_ty = c_cg_top_type(p);
   1578   if (!type_is_fp(arg_ty)) {
   1579     perr(p, "__builtin_isnan argument must have floating type");
   1580   }
   1581   expect_punct(p, ')', "')' after __builtin_isnan");
   1582 
   1583   c_cg_set_loc(p, loc);
   1584   c_cg_dup(p);
   1585   c_cg_cmp(p, CMP_NE);
   1586   return 1;
   1587 }
   1588 
   1589 /* C99 floating comparison builtins (Route A). The five relational forms map
   1590  * directly to ordered FP predicates (NaN -> false): isless/islessequal/
   1591  * isgreater/isgreaterequal -> OLT/OLE/OGT/OGE (the same predicates the bare
   1592  * `< <= > >=` operators produce, but as the explicit quiet macros), and
   1593  * islessgreater -> ONE (ordered-and-not-equal). isunordered has no standalone
   1594  * predicate in the CmpOp enum, so it is synthesized as (a != a) || (b != b)
   1595  * using the unordered self-compare that __builtin_isnan already relies on. */
   1596 static int parse_builtin_fp_cmp_call(Parser* p, Sym name, SrcLoc loc) {
   1597   CmpOp cop;
   1598   int is_unordered = 0;
   1599   const Type* common;
   1600 
   1601   if (name == p->sym_b_isless) {
   1602     cop = CMP_OLT_F;
   1603   } else if (name == p->sym_b_islessequal) {
   1604     cop = CMP_OLE_F;
   1605   } else if (name == p->sym_b_isgreater) {
   1606     cop = CMP_OGT_F;
   1607   } else if (name == p->sym_b_isgreaterequal) {
   1608     cop = CMP_OGE_F;
   1609   } else if (name == p->sym_b_islessgreater) {
   1610     cop = CMP_ONE_F;
   1611   } else if (name == p->sym_b_isunordered) {
   1612     cop = CMP_OEQ_F; /* unused; isunordered is synthesized below */
   1613     is_unordered = 1;
   1614   } else {
   1615     return 0;
   1616   }
   1617 
   1618   reject_general_regs_only_fp(p, "floating-point builtins");
   1619   advance(p); /* IDENT */
   1620   expect_punct(p, '(', "'(' after floating comparison builtin");
   1621   parse_assign_expr(p);
   1622   to_rvalue(p);
   1623   if (!type_is_fp(c_cg_top_type(p))) {
   1624     perr(p, "floating comparison builtin requires floating arguments");
   1625   }
   1626   expect_punct(p, ',', "',' between floating comparison builtin arguments");
   1627   parse_assign_expr(p);
   1628   to_rvalue(p);
   1629   if (!type_is_fp(c_cg_top_type(p))) {
   1630     perr(p, "floating comparison builtin requires floating arguments");
   1631   }
   1632   expect_punct(p, ')', "')' after floating comparison builtin");
   1633 
   1634   /* Bring both operands to a common floating type so the compare (and the
   1635    * synthesized self-compares) see matching widths, mirroring the bare
   1636    * relational path (parse_rel). */
   1637   common = common_fp_type(p, c_cg_top2_type(p), c_cg_top_type(p));
   1638   coerce_fp_cmp_operands(p, common);
   1639 
   1640   c_cg_set_loc(p, loc);
   1641   if (!is_unordered) {
   1642     c_cg_cmp(p, cop);
   1643     return 1;
   1644   }
   1645 
   1646   /* isunordered(a, b) == isnan(a) || isnan(b). Stash both operands, then OR the
   1647    * two unordered self-compares (each yields the 0/1 int isnan result). */
   1648   {
   1649     FrameSlot slot_a = builtin_tmp_slot(p, common);
   1650     FrameSlot slot_b = builtin_tmp_slot(p, common);
   1651     /* stack: [a, b] */
   1652     c_cg_push_local_typed(p, slot_b, common);
   1653     c_cg_swap(p);
   1654     c_cg_store_void(p);
   1655     /* stack: [a] */
   1656     c_cg_push_local_typed(p, slot_a, common);
   1657     c_cg_swap(p);
   1658     c_cg_store_void(p);
   1659     /* stack: [] */
   1660     c_cg_push_local_typed(p, slot_a, common);
   1661     c_cg_load(p);
   1662     c_cg_dup(p);
   1663     c_cg_cmp(p, CMP_NE); /* isnan(a): unordered not-equal */
   1664     c_cg_push_local_typed(p, slot_b, common);
   1665     c_cg_load(p);
   1666     c_cg_dup(p);
   1667     c_cg_cmp(p, CMP_NE); /* isnan(b) */
   1668     c_cg_binop(p, BO_OR);
   1669   }
   1670   return 1;
   1671 }
   1672 
   1673 static const Type* builtin_math_fp_type(Parser* p, Sym name) {
   1674   reject_general_regs_only_fp(p, "floating-point builtins");
   1675   if (name == p->sym_b_fabsf || name == p->sym_b_inff ||
   1676       name == p->sym_b_huge_valf || name == p->sym_b_nanf) {
   1677     return type_prim(p->pool, TY_FLOAT);
   1678   }
   1679   if (name == p->sym_b_fabsl || name == p->sym_b_infl ||
   1680       name == p->sym_b_huge_vall || name == p->sym_b_nanl) {
   1681     return type_prim(p->pool, TY_LDOUBLE);
   1682   }
   1683   return type_prim(p->pool, TY_DOUBLE);
   1684 }
   1685 
   1686 static int parse_builtin_inf_call(Parser* p, Sym name, SrcLoc loc) {
   1687   const Type* ty;
   1688   if (name != p->sym_b_inf && name != p->sym_b_inff && name != p->sym_b_infl &&
   1689       name != p->sym_b_huge_val && name != p->sym_b_huge_valf &&
   1690       name != p->sym_b_huge_vall) {
   1691     return 0;
   1692   }
   1693 
   1694   ty = builtin_math_fp_type(p, name);
   1695   advance(p); /* IDENT */
   1696   expect_punct(p, '(', "'(' after floating builtin");
   1697   expect_punct(p, ')', "')' after floating builtin");
   1698   c_cg_set_loc(p, loc);
   1699   c_cg_push_float(p, __builtin_inf(), ty);
   1700   return 1;
   1701 }
   1702 
   1703 /* __builtin_nan / nanf / nanl: produce a quiet NaN of the matching width.
   1704  * The argument is a (constant) tag string selecting the NaN payload; kit
   1705  * ignores the payload and always emits the default quiet NaN — matching the
   1706  * `""` tag that <math.h>'s NAN expands to (__builtin_nanf("")). */
   1707 static int parse_builtin_nan_call(Parser* p, Sym name, SrcLoc loc) {
   1708   const Type* ty;
   1709   if (name != p->sym_b_nan && name != p->sym_b_nanf && name != p->sym_b_nanl) {
   1710     return 0;
   1711   }
   1712   ty = builtin_math_fp_type(p, name);
   1713   advance(p); /* IDENT */
   1714   expect_punct(p, '(', "'(' after __builtin_nan");
   1715   parse_assign_expr(p); /* the tag string — evaluated and discarded */
   1716   to_rvalue(p);
   1717   c_cg_drop(p);
   1718   expect_punct(p, ')', "')' after __builtin_nan");
   1719   c_cg_set_loc(p, loc);
   1720   c_cg_push_float(p, __builtin_nan(""), ty);
   1721   return 1;
   1722 }
   1723 
   1724 /* __builtin_constant_p(expr): 1 if expr folds to a compile-time integer
   1725  * constant, else 0. kit answers from what its single-pass front end can fold at
   1726  * parse time — which matches GCC at -O0, where expressions GCC would fold only
   1727  * under optimization also report 0. The operand's value is never used: it is
   1728  * parsed and immediately dropped. kit's value stack is lazy, so a constant or
   1729  * otherwise side-effect-free operand emits no code; only an operand containing
   1730  * an eager side effect (a call) emits, and such an operand is never a constant
   1731  * (so the result — 0 — is still correct). The result is a pushed integer
   1732  * constant, usable anywhere a constant expression is. */
   1733 static int parse_builtin_constant_p_call(Parser* p, Sym name, SrcLoc loc) {
   1734   KitCgConstInt cval;
   1735   int is_const;
   1736   if (name != p->sym_b_constant_p) return 0;
   1737   advance(p); /* IDENT */
   1738   expect_punct(p, '(', "'(' after __builtin_constant_p");
   1739   c_const_guard_not_eval_push(p);
   1740   parse_assign_expr(p);
   1741   is_const = c_cg_emit_enabled(p) && kit_cg_top_const_int_ex(p->cg, &cval);
   1742   c_cg_drop(p);
   1743   c_const_guard_not_eval_pop(p);
   1744   expect_punct(p, ')', "')' after __builtin_constant_p");
   1745   c_cg_set_loc(p, loc);
   1746   c_cg_push_int(p, is_const ? 1 : 0, ty_int(p));
   1747   return 1;
   1748 }
   1749 
   1750 static int parse_builtin_fabs_call(Parser* p, Sym name, SrcLoc loc) {
   1751   const Type* ty;
   1752   FrameSlot slot;
   1753   CGLabel L_nonneg;
   1754   CGLabel L_nonzero;
   1755   if (name != p->sym_b_fabs && name != p->sym_b_fabsf &&
   1756       name != p->sym_b_fabsl) {
   1757     return 0;
   1758   }
   1759 
   1760   ty = builtin_math_fp_type(p, name);
   1761   advance(p); /* IDENT */
   1762   expect_punct(p, '(', "'(' after __builtin_fabs");
   1763   parse_assign_expr(p);
   1764   to_rvalue(p);
   1765   if (!type_is_fp(c_cg_top_type(p))) {
   1766     perr(p, "__builtin_fabs argument must have floating type");
   1767   }
   1768   coerce_top_to_type(p, ty);
   1769   expect_punct(p, ')', "')' after __builtin_fabs");
   1770 
   1771   slot = builtin_tmp_slot(p, ty);
   1772   c_cg_push_local_typed(p, slot, ty);
   1773   c_cg_swap(p);
   1774   c_cg_store_void(p);
   1775 
   1776   c_cg_set_loc(p, loc);
   1777   c_cg_push_local_typed(p, slot, ty);
   1778   c_cg_load(p);
   1779   c_cg_push_float(p, 0.0, ty);
   1780   c_cg_cmp(p, CMP_LT_F);
   1781   L_nonneg = c_cg_label_new(p);
   1782   c_cg_branch_false(p, L_nonneg);
   1783   c_cg_push_local_typed(p, slot, ty);
   1784   c_cg_push_local_typed(p, slot, ty);
   1785   c_cg_load(p);
   1786   c_cg_unop(p, UO_NEG);
   1787   c_cg_store_void(p);
   1788   c_cg_label_place(p, L_nonneg);
   1789   c_cg_push_local_typed(p, slot, ty);
   1790   c_cg_load(p);
   1791   c_cg_push_float(p, 0.0, ty);
   1792   c_cg_cmp(p, CMP_EQ);
   1793   L_nonzero = c_cg_label_new(p);
   1794   c_cg_branch_false(p, L_nonzero);
   1795   c_cg_push_local_typed(p, slot, ty);
   1796   c_cg_push_float(p, 0.0, ty);
   1797   c_cg_store_void(p);
   1798   c_cg_label_place(p, L_nonzero);
   1799   c_cg_push_local_typed(p, slot, ty);
   1800   c_cg_load(p);
   1801   return 1;
   1802 }
   1803 
   1804 static int parse_builtin_abs_call(Parser* p, Sym name, SrcLoc loc) {
   1805   KitSlice name_sl = kit_sym_str(p->pool->c, name);
   1806   size_t nlen = name_sl.len;
   1807   const char* nm = name_sl.s;
   1808   const char* libname = NULL;
   1809   const Type* int_ty = NULL;
   1810   const Type* params[1];
   1811   const Type* fn_ty;
   1812   KitCgSym sym;
   1813 
   1814   if (nm && nlen == 13u && memcmp(nm, "__builtin_abs", 13u) == 0) {
   1815     libname = "abs";
   1816     int_ty = type_prim(p->pool, TY_INT);
   1817   } else if (nm && nlen == 14u && memcmp(nm, "__builtin_labs", 14u) == 0) {
   1818     libname = "labs";
   1819     int_ty = type_prim(p->pool, TY_LONG);
   1820   } else if (nm && nlen == 15u && memcmp(nm, "__builtin_llabs", 15u) == 0) {
   1821     libname = "llabs";
   1822     int_ty = type_prim(p->pool, TY_LLONG);
   1823   } else {
   1824     return 0;
   1825   }
   1826 
   1827   advance(p); /* IDENT */
   1828   expect_punct(p, '(', "'(' after abs builtin");
   1829   parse_assign_expr(p);
   1830   to_rvalue(p);
   1831   coerce_top_to_type(p, int_ty);
   1832   expect_punct(p, ')', "')' after abs builtin");
   1833 
   1834   params[0] = int_ty;
   1835   fn_ty = type_func(p->pool, int_ty, params, 1, 0);
   1836   sym = builtin_libcall_sym(p, libname, fn_ty);
   1837   c_cg_set_loc(p, loc);
   1838   c_cg_call_symbol(p, sym, 1, fn_ty);
   1839   return 1;
   1840 }
   1841 
   1842 static int parse_kit_syscall_call(Parser* p, Sym name, SrcLoc loc) {
   1843   const Type* long_ty;
   1844   u32 arity = 0;
   1845   u32 nargs;
   1846   int found = 0;
   1847 
   1848   for (u32 i = 0; i < 7u; ++i) {
   1849     if (name == p->sym_kit_syscall[i]) {
   1850       arity = i;
   1851       found = 1;
   1852       break;
   1853     }
   1854   }
   1855   if (!found) return 0;
   1856 
   1857   long_ty = type_prim(p->pool, TY_LONG);
   1858   nargs = arity + 1u; /* syscall number plus payload args */
   1859   advance(p);         /* IDENT */
   1860   expect_punct(p, '(', "'(' after __kit_syscall");
   1861   for (u32 i = 0; i < nargs; ++i) {
   1862     if (i) expect_punct(p, ',', "',' in __kit_syscall");
   1863     parse_assign_expr(p);
   1864     to_rvalue(p);
   1865     coerce_top_to_type(p, long_ty);
   1866   }
   1867   expect_punct(p, ')', "')' after __kit_syscall");
   1868 
   1869   c_cg_set_loc(p, loc);
   1870   c_cg_syscall(p, nargs, long_ty);
   1871   return 1;
   1872 }
   1873 
   1874 static int try_parse_builtin_call(Parser* p) {
   1875   Sym name = tok_ident(&p->cur);
   1876   SrcLoc loc = pp_materialize_loc(p->pp, p->cur.loc);
   1877 
   1878   /* A resolved-target feature query is a parser-folded integer constant, not a
   1879    * runtime call, so it remains valid inside integer constant expressions. */
   1880   if (parse_builtin_target_has_call(p, name)) return 1;
   1881 
   1882   if (c_const_guard_active(p) && name != p->sym_b_offsetof &&
   1883       name != p->sym_b_constant_p) {
   1884     c_const_guard_note_at(p, loc,
   1885                           "function call in integer constant expression");
   1886   }
   1887 
   1888   if (parse_kit_syscall_call(p, name, loc)) return 1;
   1889 
   1890   if (parse_builtin_bit_call(p, name, loc)) return 1;
   1891   if (parse_builtin_rotate_call(p, name)) return 1;
   1892   if (parse_builtin_prefetch_call(p, name, loc)) return 1;
   1893   if (parse_builtin_assume_aligned_call(p, name, loc)) return 1;
   1894   if (parse_builtin_cpu_relax_call(p, name, loc)) return 1;
   1895   if (parse_builtin_carry_call(p, name, loc)) return 1;
   1896   if (parse_builtin_mul_high_call(p, name, loc)) return 1;
   1897 
   1898   if (name == p->sym_b_memcpy || name == p->sym_b_memmove ||
   1899       name == p->sym_b_memcmp || name == p->sym_b_memset) {
   1900     return parse_builtin_mem_call(p, name, loc);
   1901   }
   1902 
   1903   if (parse_builtin_overflow_call(p, name, loc)) return 1;
   1904   if (parse_builtin_isnan_call(p, name, loc)) return 1;
   1905   if (parse_builtin_fp_cmp_call(p, name, loc)) return 1;
   1906   if (parse_builtin_inf_call(p, name, loc)) return 1;
   1907   if (parse_builtin_nan_call(p, name, loc)) return 1;
   1908   if (parse_builtin_constant_p_call(p, name, loc)) return 1;
   1909   if (parse_builtin_fabs_call(p, name, loc)) return 1;
   1910   if (parse_builtin_abs_call(p, name, loc)) return 1;
   1911   if (parse_builtin_clear_cache_call(p, name, loc)) return 1;
   1912 
   1913   if (name != p->sym_b_alloca && name != p->sym_b_ctz &&
   1914       name != p->sym_b_ctzl && name != p->sym_b_ctzll && name != p->sym_b_clz &&
   1915       name != p->sym_b_clzl && name != p->sym_b_clzll &&
   1916       name != p->sym_b_trap && name != p->sym_b_unreachable &&
   1917       name != p->sym_b_return_address && name != p->sym_b_frame_address &&
   1918       name != p->sym_b_readcyclecounter && name != p->sym_b_expect &&
   1919       name != p->sym_b_offsetof && name != p->sym_b_va_start &&
   1920       name != p->sym_b_va_arg && name != p->sym_b_va_end &&
   1921       name != p->sym_b_va_copy && name != p->sym_a_load_n &&
   1922       name != p->sym_a_store_n && name != p->sym_a_exchange_n &&
   1923       name != p->sym_a_fetch_add && name != p->sym_a_fetch_sub &&
   1924       name != p->sym_a_fetch_and && name != p->sym_a_fetch_or &&
   1925       name != p->sym_a_fetch_xor && name != p->sym_a_fetch_nand &&
   1926       name != p->sym_a_cas_n && name != p->sym_a_always_lock_free &&
   1927       name != p->sym_a_is_lock_free && name != p->sym_a_thread_fence &&
   1928       name != p->sym_a_signal_fence && name != p->sym_sync_synchronize) {
   1929     return 0;
   1930   }
   1931   advance(p); /* IDENT */
   1932   expect_punct(p, '(', "'(' after builtin");
   1933 
   1934   if (name == p->sym_b_offsetof) {
   1935     const Type* root = parse_type_name(p);
   1936     expect_punct(p, ',', "',' in __builtin_offsetof");
   1937     u32 off = 0;
   1938     (void)offsetof_designator(p, root, &off);
   1939     expect_punct(p, ')', "')' after __builtin_offsetof");
   1940     c_cg_push_int(p, (i64)off, ty_size_t(p));
   1941     return 1;
   1942   }
   1943 
   1944   if (name == p->sym_b_expect) {
   1945     parse_assign_expr(p);
   1946     to_rvalue(p);
   1947     expect_punct(p, ',', "',' in __builtin_expect");
   1948     parse_assign_expr(p);
   1949     c_cg_drop(p);
   1950     expect_punct(p, ')', "')' after __builtin_expect");
   1951     return 1;
   1952   }
   1953 
   1954   if (name == p->sym_b_alloca) {
   1955     parse_assign_expr(p);
   1956     to_rvalue(p);
   1957     expect_punct(p, ')', "')' after __builtin_alloca");
   1958     c_cg_set_loc(p, loc);
   1959     c_cg_alloca(p);
   1960     return 1;
   1961   }
   1962 
   1963   if (name == p->sym_b_ctz || name == p->sym_b_ctzl || name == p->sym_b_ctzll) {
   1964     parse_assign_expr(p);
   1965     to_rvalue(p);
   1966     expect_punct(p, ')', "')' after __builtin_ctz");
   1967     c_cg_set_loc(p, loc);
   1968     c_cg_intrinsic_unary_to_int(p, INTRIN_CTZ);
   1969     return 1;
   1970   }
   1971 
   1972   if (name == p->sym_b_clz || name == p->sym_b_clzl || name == p->sym_b_clzll) {
   1973     parse_assign_expr(p);
   1974     to_rvalue(p);
   1975     expect_punct(p, ')', "')' after __builtin_clz");
   1976     c_cg_set_loc(p, loc);
   1977     /* The operand carries its own type, which drives the sf bit on
   1978      * aarch64 / REX.W on x64 / sf on rv64. Whether the caller used the
   1979      * `l` / `ll` suffix only changes the C-level type the user wrote;
   1980      * kit picks the instruction width from the value type. */
   1981     c_cg_intrinsic_unary_to_int(p, INTRIN_CLZ);
   1982     return 1;
   1983   }
   1984 
   1985   if (name == p->sym_b_trap || name == p->sym_b_unreachable) {
   1986     expect_punct(p, ')', "')' after __builtin_trap/unreachable");
   1987     c_cg_set_loc(p, loc);
   1988     c_cg_intrinsic_void(
   1989         p, name == p->sym_b_trap ? INTRIN_TRAP : INTRIN_UNREACHABLE);
   1990     /* Both are noreturn at the C level. Push a dummy `int 0` so callers
   1991      * that consume an expression value (e.g. ternary, comma) don't see
   1992      * an empty stack — the dead value will be folded out. */
   1993     c_cg_push_int(p, 0, ty_int(p));
   1994     return 1;
   1995   }
   1996 
   1997   if (name == p->sym_b_return_address || name == p->sym_b_frame_address) {
   1998     /* GCC requires the level to be an integer constant expression. */
   1999     int is_return = (name == p->sym_b_return_address);
   2000     i64 level = eval_const_int(p, pp_materialize_loc(p->pp, p->cur.loc));
   2001     expect_punct(p, ')',
   2002                  "')' after __builtin_return_address/__builtin_frame_address");
   2003     if (level < 0)
   2004       perr(p, "__builtin_%s: level must be non-negative",
   2005            is_return ? "return_address" : "frame_address");
   2006     c_cg_set_loc(p, loc);
   2007     c_cg_frame_or_return_address(p, is_return, (u32)level);
   2008     return 1;
   2009   }
   2010 
   2011   if (name == p->sym_b_readcyclecounter) {
   2012     expect_punct(p, ')', "')' after __builtin_readcyclecounter");
   2013     c_cg_set_loc(p, loc);
   2014     c_cg_readcyclecounter(p);
   2015     return 1;
   2016   }
   2017 
   2018   if (name == p->sym_b_va_start) {
   2019     parse_assign_expr(p);
   2020     c_cg_addr(p);
   2021     expect_punct(p, ',', "',' in __builtin_va_start");
   2022     parse_assign_expr(p);
   2023     c_cg_drop(p);
   2024     expect_punct(p, ')', "')' after __builtin_va_start");
   2025     c_cg_set_loc(p, loc);
   2026     c_cg_va_start(p);
   2027     c_cg_push_int(p, 0, ty_int(p));
   2028     return 1;
   2029   }
   2030 
   2031   if (name == p->sym_b_va_end) {
   2032     parse_assign_expr(p);
   2033     c_cg_addr(p);
   2034     expect_punct(p, ')', "')' after __builtin_va_end");
   2035     c_cg_set_loc(p, loc);
   2036     c_cg_va_end(p);
   2037     c_cg_push_int(p, 0, ty_int(p));
   2038     return 1;
   2039   }
   2040 
   2041   if (name == p->sym_b_va_copy) {
   2042     parse_assign_expr(p);
   2043     c_cg_addr(p);
   2044     expect_punct(p, ',', "',' in __builtin_va_copy");
   2045     parse_assign_expr(p);
   2046     c_cg_addr(p);
   2047     expect_punct(p, ')', "')' after __builtin_va_copy");
   2048     c_cg_set_loc(p, loc);
   2049     c_cg_va_copy(p);
   2050     c_cg_push_int(p, 0, ty_int(p));
   2051     return 1;
   2052   }
   2053 
   2054   if (name == p->sym_b_va_arg) {
   2055     parse_assign_expr(p);
   2056     c_cg_addr(p);
   2057     expect_punct(p, ',', "',' in __builtin_va_arg");
   2058     const Type* ty = parse_type_name(p);
   2059     expect_punct(p, ')', "')' after __builtin_va_arg");
   2060     c_cg_set_loc(p, loc);
   2061     c_cg_va_arg(p, ty);
   2062     return 1;
   2063   }
   2064 
   2065   if (name == p->sym_a_load_n) {
   2066     parse_assign_expr(p);
   2067     to_rvalue(p);
   2068     expect_punct(p, ',', "',' in __atomic_load_n");
   2069     MemOrder ord = parse_atomic_mem_order(p);
   2070     expect_punct(p, ')', "')' after __atomic_load_n");
   2071     c_cg_set_loc(p, loc);
   2072     c_cg_atomic_load(p, ord);
   2073     return 1;
   2074   }
   2075 
   2076   if (name == p->sym_a_store_n) {
   2077     parse_assign_expr(p);
   2078     to_rvalue(p);
   2079     const Type* val_ty =
   2080         atomic_pointee_type(p, c_cg_top_type(p), "__atomic_store_n");
   2081     expect_punct(p, ',', "',' in __atomic_store_n");
   2082     parse_assign_expr(p);
   2083     to_rvalue(p);
   2084     coerce_top_to_type(p, val_ty);
   2085     expect_punct(p, ',', "',' in __atomic_store_n");
   2086     MemOrder ord = parse_atomic_mem_order(p);
   2087     expect_punct(p, ')', "')' after __atomic_store_n");
   2088     c_cg_set_loc(p, loc);
   2089     c_cg_atomic_store(p, ord);
   2090     c_cg_push_int(p, 0, ty_int(p));
   2091     return 1;
   2092   }
   2093 
   2094   if (name == p->sym_a_thread_fence || name == p->sym_a_signal_fence) {
   2095     MemOrder ord = parse_atomic_mem_order(p);
   2096     expect_punct(p, ')', "')' after atomic fence");
   2097     c_cg_set_loc(p, loc);
   2098     c_cg_fence(p, ord);
   2099     c_cg_push_int(p, 0, ty_int(p));
   2100     return 1;
   2101   }
   2102 
   2103   /* __sync_synchronize(): the legacy GCC full barrier. No operands; always a
   2104    * sequentially-consistent fence (the __sync_* family is implicitly seq-cst).
   2105    */
   2106   if (name == p->sym_sync_synchronize) {
   2107     expect_punct(p, ')', "')' after __sync_synchronize");
   2108     c_cg_set_loc(p, loc);
   2109     c_cg_fence(p, MO_SEQ_CST);
   2110     c_cg_push_int(p, 0, ty_int(p));
   2111     return 1;
   2112   }
   2113 
   2114   if (name == p->sym_a_always_lock_free || name == p->sym_a_is_lock_free) {
   2115     i64 size = eval_const_int(p, pp_materialize_loc(p->pp, p->cur.loc));
   2116     expect_punct(p, ',', "',' in atomic lock-free builtin");
   2117     parse_assign_expr(p);
   2118     to_rvalue(p);
   2119     c_cg_drop(p);
   2120     expect_punct(p, ')', "')' after atomic lock-free builtin");
   2121     c_cg_push_int(p, atomic_lock_free_for_const_size(p, size), ty_int(p));
   2122     return 1;
   2123   }
   2124 
   2125   if (name == p->sym_a_cas_n) {
   2126     parse_assign_expr(p);
   2127     to_rvalue(p); /* ptr */
   2128     const Type* obj_ty =
   2129         atomic_pointee_type(p, c_cg_top_type(p), "__atomic_compare_exchange_n");
   2130     expect_punct(p, ',', "',' in __atomic_compare_exchange_n");
   2131 
   2132     parse_assign_expr(p);
   2133     to_rvalue(p); /* &expected */
   2134     const Type* eptr_ty = c_cg_top_type(p);
   2135     if (!eptr_ty || eptr_ty->kind != TY_PTR) {
   2136       perr(p, "__atomic_compare_exchange_n: arg 2 must be a pointer");
   2137     }
   2138     const Type* val_ty = eptr_ty->ptr.pointee;
   2139     if (val_ty != obj_ty) {
   2140       val_ty = obj_ty;
   2141     }
   2142 
   2143     FrameSlotDesc fsd;
   2144     memset(&fsd, 0, sizeof fsd);
   2145     fsd.type = eptr_ty;
   2146     fsd.size = c_abi_sizeof(p->abi, p->pool, eptr_ty);
   2147     fsd.align = c_abi_alignof(p->abi, p->pool, eptr_ty);
   2148     fsd.kind = FS_LOCAL;
   2149     FrameSlot eslot = c_cg_local(p, &fsd);
   2150     c_cg_push_local_typed(p, eslot, eptr_ty);
   2151     c_cg_swap(p);
   2152     c_cg_store_void(p);
   2153 
   2154     c_cg_push_local_typed(p, eslot, eptr_ty);
   2155     c_cg_load(p);
   2156     c_cg_deref(p, val_ty);
   2157     c_cg_load(p);
   2158 
   2159     expect_punct(p, ',', "',' in __atomic_compare_exchange_n");
   2160     parse_assign_expr(p);
   2161     to_rvalue(p); /* desired */
   2162     coerce_top_to_type(p, val_ty);
   2163     expect_punct(p, ',', "',' in __atomic_compare_exchange_n");
   2164 
   2165     (void)eval_const_int(p, pp_materialize_loc(p->pp, p->cur.loc)); /* weak */
   2166     expect_punct(p, ',', "',' in __atomic_compare_exchange_n");
   2167     MemOrder succ = parse_atomic_mem_order(p);
   2168     expect_punct(p, ',', "',' in __atomic_compare_exchange_n");
   2169     MemOrder fail = parse_atomic_mem_order(p);
   2170     expect_punct(p, ')', "')' after __atomic_compare_exchange_n");
   2171 
   2172     c_cg_set_loc(p, loc);
   2173     c_cg_atomic_cas(p, succ, fail);
   2174 
   2175     const Type* ok_ty = c_cg_top_type(p);
   2176     FrameSlotDesc okd;
   2177     memset(&okd, 0, sizeof okd);
   2178     okd.type = ok_ty;
   2179     okd.size = c_abi_sizeof(p->abi, p->pool, ok_ty);
   2180     okd.align = c_abi_alignof(p->abi, p->pool, ok_ty);
   2181     okd.kind = FS_LOCAL;
   2182     FrameSlot okslot = c_cg_local(p, &okd);
   2183     c_cg_push_local_typed(p, okslot, ok_ty);
   2184     c_cg_swap(p);
   2185     c_cg_store_void(p);
   2186 
   2187     FrameSlotDesc pd;
   2188     memset(&pd, 0, sizeof pd);
   2189     pd.type = val_ty;
   2190     pd.size = c_abi_sizeof(p->abi, p->pool, val_ty);
   2191     pd.align = c_abi_alignof(p->abi, p->pool, val_ty);
   2192     pd.kind = FS_LOCAL;
   2193     FrameSlot pslot = c_cg_local(p, &pd);
   2194     c_cg_push_local_typed(p, pslot, val_ty);
   2195     c_cg_swap(p);
   2196     c_cg_store_void(p);
   2197 
   2198     c_cg_push_local_typed(p, okslot, ok_ty);
   2199     c_cg_load(p);
   2200     CGLabel L_done = c_cg_label_new(p);
   2201     c_cg_branch_true(p, L_done);
   2202     c_cg_push_local_typed(p, eslot, eptr_ty);
   2203     c_cg_load(p);
   2204     c_cg_deref(p, val_ty);
   2205     c_cg_push_local_typed(p, pslot, val_ty);
   2206     c_cg_load(p);
   2207     c_cg_store_void(p);
   2208     c_cg_label_place(p, L_done);
   2209 
   2210     c_cg_push_local_typed(p, okslot, ok_ty);
   2211     c_cg_load(p);
   2212     return 1;
   2213   }
   2214 
   2215   AtomicOp op;
   2216   if (name == p->sym_a_exchange_n)
   2217     op = AO_XCHG;
   2218   else if (name == p->sym_a_fetch_add)
   2219     op = AO_ADD;
   2220   else if (name == p->sym_a_fetch_sub)
   2221     op = AO_SUB;
   2222   else if (name == p->sym_a_fetch_and)
   2223     op = AO_AND;
   2224   else if (name == p->sym_a_fetch_or)
   2225     op = AO_OR;
   2226   else if (name == p->sym_a_fetch_xor)
   2227     op = AO_XOR;
   2228   else if (name == p->sym_a_fetch_nand)
   2229     op = AO_NAND;
   2230   else {
   2231     perr(p, "internal: unhandled builtin");
   2232   }
   2233 
   2234   parse_assign_expr(p);
   2235   to_rvalue(p);
   2236   const Type* val_ty =
   2237       atomic_pointee_type(p, c_cg_top_type(p), "__atomic read-modify-write");
   2238   expect_punct(p, ',', "',' in atomic builtin");
   2239   parse_assign_expr(p);
   2240   to_rvalue(p);
   2241   coerce_top_to_type(p, val_ty);
   2242   expect_punct(p, ',', "',' in atomic builtin");
   2243   MemOrder ord = parse_atomic_mem_order(p);
   2244   expect_punct(p, ')', "')' after atomic builtin");
   2245   c_cg_set_loc(p, loc);
   2246   c_cg_atomic_rmw(p, op, ord);
   2247   return 1;
   2248 }
   2249 
   2250 /* ============================================================
   2251  * parse_primary, parse_postfix, parse_unary
   2252  * ============================================================ */
   2253 
   2254 static void parse_primary(Parser* p) {
   2255   Tok t = p->cur;
   2256   if (t.kind == TOK_NUM) {
   2257     i64 v = parse_int_literal(p, &t);
   2258     const Type* lty = int_literal_type(p, &t);
   2259     advance(p);
   2260     c_cg_push_int(p, v, lty);
   2261     return;
   2262   }
   2263   if (t.kind == TOK_FLT) {
   2264     reject_general_regs_only_fp(p, "floating-point literals");
   2265     double v = parse_float_literal(p, &t);
   2266     const Type* lty = float_literal_type(p, &t);
   2267     c_const_guard_note_at(p, pp_materialize_loc(p->pp, t.loc),
   2268                           "integer constant expression required");
   2269     advance(p);
   2270     c_cg_push_float(p, v, lty);
   2271     return;
   2272   }
   2273   if (is_punct(&t, '(')) {
   2274     advance(p);
   2275     parse_expr(p);
   2276     expect_punct(p, ')', "')'");
   2277     return;
   2278   }
   2279   if (t.kind == TOK_IDENT) {
   2280     SymEntry* e;
   2281     if (ident_kw_inline(p, tok_ident(&t)) != KW_NONE) {
   2282       perr(p, "unexpected keyword in expression");
   2283     }
   2284     {
   2285       Tok n = peek1(p);
   2286       if (is_punct(&n, '(') && try_parse_builtin_call(p)) return;
   2287     }
   2288     /* try_parse_builtin_call may rewrite the current ident in-place
   2289      * (e.g. __builtin_memcpy → memcpy) and return 0, asking us to
   2290      * resume normal lookup with the rewritten name. */
   2291     t = p->cur;
   2292     /* C99 §6.4.2.2: `__func__` inside a function-body acts as
   2293      *   static const char __func__[] = "<function-name>";
   2294      * GCC also exposes `__FUNCTION__` and `__PRETTY_FUNCTION__` with
   2295      * the same value. We synthesize the string lazily — the symbol
   2296      * lives in .rodata and the resulting type is `char[N+1]` (with the
   2297      * trailing NUL). */
   2298     if (tok_ident(&t) == p->sym_func || tok_ident(&t) == p->sym_func_gcc ||
   2299         tok_ident(&t) == p->sym_pretty_func_gcc) {
   2300       c_const_guard_note_at(p, pp_materialize_loc(p->pp, t.loc),
   2301                             "non-constant identifier in constant expression");
   2302       if (p->cur_func_name == 0) {
   2303         compiler_panic(
   2304             p->c, pp_materialize_loc(p->pp, t.loc),
   2305             "'%.*s' used outside a function",
   2306             KIT_SLICE_ARG(kit_slice_cstr(
   2307                 tok_ident(&t) == p->sym_func       ? "__func__"
   2308                 : tok_ident(&t) == p->sym_func_gcc ? "__FUNCTION__"
   2309                                                    : "__PRETTY_FUNCTION__")));
   2310       }
   2311       KitSlice fn_name_sl = kit_sym_str(p->pool->c, p->cur_func_name);
   2312       size_t nlen = fn_name_sl.len;
   2313       const char* fn_name = fn_name_sl.s;
   2314       Heap* h = kit_compiler_context(p->c)->heap;
   2315       u8* bytes = (u8*)h->alloc(h, nlen + 1u, 1u);
   2316       ObjSymId sym;
   2317       for (size_t i = 0; i < nlen; ++i) bytes[i] = (u8)fn_name[i];
   2318       bytes[nlen] = 0;
   2319       sym = c_cg_emit_enabled(p) ? emit_string_to_rodata(p, bytes, nlen + 1u)
   2320                                  : OBJ_SYM_NONE;
   2321       h->free(h, bytes, 0);
   2322       advance(p);
   2323       const Type* char_ty = type_prim(p->pool, TY_CHAR);
   2324       const Type* arr_ty = type_array(p->pool, char_ty, (u32)(nlen + 1u), 0);
   2325       c_cg_push_global(p, sym, arr_ty);
   2326       return;
   2327     }
   2328     e = scope_lookup(p, tok_ident(&t));
   2329     if (!e) {
   2330       KitSlice ident_sl = kit_sym_str(p->pool->c, tok_ident(&t));
   2331       size_t nlen = ident_sl.len;
   2332       const char* nm = ident_sl.s;
   2333       compiler_panic(p->c, pp_materialize_loc(p->pp, t.loc),
   2334                      "undeclared identifier '%.*s'", (int)nlen, nm ? nm : "?");
   2335     }
   2336     if (e->kind != SEK_ENUM_CST) {
   2337       c_const_guard_note_at(p, pp_materialize_loc(p->pp, t.loc),
   2338                             "non-constant identifier in constant expression");
   2339     }
   2340     advance(p);
   2341     switch (e->kind) {
   2342       case SEK_LOCAL:
   2343         c_cg_push_local_typed(p, e->v.slot, e->type);
   2344         if (e->storage == DS_REGISTER) c_cg_set_top_register(p);
   2345         if (e->vla_byte_slot != FRAME_SLOT_NONE) {
   2346           p->last_pushed_vla_slot = e->vla_byte_slot;
   2347         }
   2348         if (e->vla_bounds) {
   2349           p->last_pushed_vla_bounds = e->vla_bounds;
   2350         }
   2351         return;
   2352       case SEK_GLOBAL:
   2353       case SEK_FUNC:
   2354         c_cg_push_global(p, e->v.sym, e->type);
   2355         return;
   2356       case SEK_ENUM_CST:
   2357         c_cg_push_int(p, e->v.enum_value, e->type);
   2358         return;
   2359       case SEK_TYPEDEF:
   2360       default:
   2361         perr(p, "identifier is not a value");
   2362     }
   2363   }
   2364   if (t.kind == TOK_CHR) {
   2365     i64 v = decode_char_literal(p, &t);
   2366     const Type* lty = char_literal_type(p, &t);
   2367     advance(p);
   2368     c_cg_push_int(p, v, lty);
   2369     return;
   2370   }
   2371   if (t.kind == TOK_STR) {
   2372     size_t n = 0;
   2373     u8* bytes = decode_string_literal(p, &t, &n);
   2374     const Type* elem_ty = string_literal_elem_type(p, &t);
   2375     u32 elem_size = c_abi_sizeof(p->abi, p->pool, elem_ty);
   2376     ObjSymId sym = c_cg_emit_enabled(p)
   2377                        ? emit_string_literal_to_rodata(p, bytes, n, elem_ty)
   2378                        : OBJ_SYM_NONE;
   2379     c_const_guard_note_at(
   2380         p, pp_materialize_loc(p->pp, t.loc),
   2381         "address constant is not an integer constant expression");
   2382     kit_compiler_context(p->c)->heap->free(kit_compiler_context(p->c)->heap,
   2383                                            bytes, 0);
   2384     advance(p);
   2385     {
   2386       const Type* arr_ty =
   2387           type_array(p->pool, elem_ty, elem_size ? (u32)(n / elem_size) : 0, 0);
   2388       c_cg_push_global(p, sym, arr_ty);
   2389     }
   2390     return;
   2391   }
   2392   perr(p, "expected expression");
   2393 }
   2394 
   2395 /* Resolve `mname` inside `rec_ty`, recursing through anonymous struct/union
   2396  * members to arbitrary depth (like offsetof_find_member / find_field). On
   2397  * success accumulates the cumulative byte offset into *out_off, records the
   2398  * matched member type, and — for a bit-field leaf — the bit-field metadata
   2399  * pulled from the final ABIFieldLayout. */
   2400 static int find_record_member_path(Parser* p, const Type* rec_ty, Sym mname,
   2401                                    const Type** out_ty, i64* out_off,
   2402                                    u16* out_bf_off, u16* out_bf_w,
   2403                                    u32* out_bf_ss) {
   2404   const ABIRecordLayout* L;
   2405   rec_ty = type_unqual(p->pool, rec_ty);
   2406   if (!rec_ty || (rec_ty->kind != TY_STRUCT && rec_ty->kind != TY_UNION))
   2407     return 0;
   2408   L = c_abi_record_layout(p->abi, p->pool, rec_ty);
   2409   if (!L) return 0;
   2410   for (u16 i = 0; i < rec_ty->rec.nfields; ++i) {
   2411     const Field* f = &rec_ty->rec.fields[i];
   2412     if (f->name == mname && mname != 0) {
   2413       const ABIFieldLayout* fl = &L->fields[i];
   2414       *out_ty = f->type;
   2415       *out_off += (i64)fl->offset;
   2416       if (f->flags & FIELD_BITFIELD) {
   2417         *out_bf_off = fl->bit_offset;
   2418         *out_bf_w = fl->bit_width;
   2419         *out_bf_ss = fl->storage_size;
   2420       }
   2421       return 1;
   2422     }
   2423   }
   2424   for (u16 i = 0; i < rec_ty->rec.nfields; ++i) {
   2425     const Field* f = &rec_ty->rec.fields[i];
   2426     const Type* fty = type_unqual(p->pool, f->type);
   2427     i64 nested_off;
   2428     if (!((f->flags & FIELD_ANON) &&
   2429           (fty->kind == TY_STRUCT || fty->kind == TY_UNION))) {
   2430       continue;
   2431     }
   2432     nested_off = *out_off + (i64)L->fields[i].offset;
   2433     if (find_record_member_path(p, fty, mname, out_ty, &nested_off, out_bf_off,
   2434                                 out_bf_w, out_bf_ss)) {
   2435       *out_off = nested_off;
   2436       return 1;
   2437     }
   2438   }
   2439   return 0;
   2440 }
   2441 
   2442 static void parse_postfix(Parser* p) {
   2443   VLABound* vla_bounds;
   2444   p->last_pushed_vla_slot = FRAME_SLOT_NONE;
   2445   p->last_pushed_vla_bounds = NULL;
   2446   parse_primary(p);
   2447   vla_bounds = p->last_pushed_vla_bounds;
   2448   for (;;) {
   2449     Tok t = p->cur;
   2450     if (is_punct(&t, P_INC)) {
   2451       c_const_guard_note_at(
   2452           p, pp_materialize_loc(p->pp, t.loc),
   2453           "increment/decrement in integer constant expression");
   2454       advance(p);
   2455       if (!c_cg_top_is_modifiable_lvalue(p)) {
   2456         perr(p, "increment/decrement requires modifiable lvalue");
   2457       }
   2458       if (!c_type_is_scalar(c_cg_top_type(p))) {
   2459         perr(p, "increment/decrement requires scalar operand");
   2460       }
   2461       c_cg_inc_dec(p, BO_IADD, /*post=*/1);
   2462       continue;
   2463     }
   2464     if (is_punct(&t, P_DEC)) {
   2465       c_const_guard_note_at(
   2466           p, pp_materialize_loc(p->pp, t.loc),
   2467           "increment/decrement in integer constant expression");
   2468       advance(p);
   2469       if (!c_cg_top_is_modifiable_lvalue(p)) {
   2470         perr(p, "increment/decrement requires modifiable lvalue");
   2471       }
   2472       if (!c_type_is_scalar(c_cg_top_type(p))) {
   2473         perr(p, "increment/decrement requires scalar operand");
   2474       }
   2475       c_cg_inc_dec(p, BO_ISUB, /*post=*/1);
   2476       continue;
   2477     }
   2478     if (is_punct(&t, '(')) {
   2479       const Type* top = c_cg_top_type(p);
   2480       const Type* fn_type;
   2481       c_const_guard_note_at(p, pp_materialize_loc(p->pp, t.loc),
   2482                             "function call in integer constant expression");
   2483       if (top && top->kind == TY_FUNC) {
   2484         fn_type = top;
   2485       } else if (top && top->kind == TY_PTR && top->ptr.pointee &&
   2486                  top->ptr.pointee->kind == TY_FUNC) {
   2487         fn_type = top->ptr.pointee;
   2488         if (c_cg_top_is_lvalue(p)) c_cg_load(p);
   2489       } else {
   2490         perr(p, "called object is not a function");
   2491       }
   2492       advance(p); /* '(' */
   2493       u32 nargs = 0;
   2494       if (!is_punct(&p->cur, ')')) {
   2495         for (;;) {
   2496           const Type* param_ty =
   2497               (nargs < fn_type->fn.nparams) ? fn_type->fn.params[nargs] : NULL;
   2498           parse_assign_expr(p);
   2499           to_rvalue(p);
   2500           if (param_ty) {
   2501             CSemCheck chk =
   2502                 c_sem_check_assignment(p->pool, param_ty, c_cg_top_type(p));
   2503             if (!chk.ok)
   2504               perr(p, "%.*s", KIT_SLICE_ARG(kit_slice_cstr(chk.message)));
   2505             coerce_top_to_type(p, param_ty);
   2506           }
   2507           ++nargs;
   2508           if (!accept_punct(p, ',')) break;
   2509         }
   2510       }
   2511       expect_punct(p, ')', "')' after argument list");
   2512       if (fn_type->fn.nparams != nargs && !fn_type->fn.variadic) {
   2513         perr(p, "wrong number of arguments");
   2514       }
   2515       if (fn_type->fn.variadic && nargs < fn_type->fn.nparams) {
   2516         perr(p, "too few arguments to variadic function");
   2517       }
   2518       c_cg_call(p, nargs, fn_type);
   2519       if (fn_type->fn.ret && fn_type->fn.ret->kind == TY_VOID) {
   2520         c_cg_push_int(p, 0, ty_int(p));
   2521       }
   2522       continue;
   2523     }
   2524     if (is_punct(&t, '[')) {
   2525       const Type* lt0 = c_cg_top_type(p);
   2526       advance(p); /* '[' */
   2527       if (lt0 && lt0->kind == TY_ARRAY) {
   2528         decay_array_to_pointer(p, lt0);
   2529       } else if (lt0 && lt0->kind == TY_PTR) {
   2530         if (c_cg_top_is_lvalue(p)) c_cg_load(p);
   2531       }
   2532       parse_expr(p);
   2533       {
   2534         const Type* it0 = c_cg_top_type(p);
   2535         if (it0 && it0->kind == TY_ARRAY) {
   2536           decay_array_to_pointer(p, it0);
   2537         } else {
   2538           to_rvalue(p);
   2539         }
   2540       }
   2541       expect_punct(p, ']', "']' after subscript");
   2542       {
   2543         const Type* lt = c_cg_top2_type(p);
   2544         const Type* it = c_cg_top_type(p);
   2545         const Type* elem;
   2546         if (lt && lt->kind == TY_PTR && type_is_int(it)) {
   2547           elem = lt->ptr.pointee;
   2548         } else if (it && it->kind == TY_PTR && type_is_int(lt)) {
   2549           c_cg_swap(p);
   2550           elem = it->ptr.pointee;
   2551         } else {
   2552           perr(p, "invalid subscript: needs one pointer and one integer");
   2553         }
   2554         if (!elem) perr(p, "subscript on incomplete pointee");
   2555         coerce_top_to_type(p, c_abi_ptrdiff_type(p->abi, p->pool));
   2556         {
   2557           FrameSlot elem_vla_slot = vla_size_slot_for_type(vla_bounds, elem);
   2558           if (elem_vla_slot != FRAME_SLOT_NONE) {
   2559             c_cg_push_local_typed(p, elem_vla_slot, ty_size_t(p));
   2560             c_cg_load(p);
   2561             c_cg_binop(p, BO_IMUL);
   2562             c_cg_binop(p, BO_IADD);
   2563             c_cg_deref(p, elem);
   2564             p->last_pushed_vla_slot = elem_vla_slot;
   2565             p->last_pushed_vla_bounds = vla_bounds;
   2566           } else {
   2567             u32 elem_size = c_abi_sizeof(p->abi, p->pool, elem);
   2568             c_cg_lv_subscript(p, elem_size, elem);
   2569           }
   2570         }
   2571       }
   2572       continue;
   2573     }
   2574     if (is_punct(&t, '.')) {
   2575       const Type* lt = c_cg_top_type(p);
   2576       Sym mname;
   2577       const Type* mty = NULL;
   2578       i64 off = 0;
   2579       u16 bf_off = 0, bf_w = 0;
   2580       u32 bf_ss = 0;
   2581       advance(p); /* '.' */
   2582       if (!lt || (lt->kind != TY_STRUCT && lt->kind != TY_UNION)) {
   2583         perr(p,
   2584              "request for member in something that is not a struct or union");
   2585       }
   2586       if (p->cur.kind != TOK_IDENT ||
   2587           ident_kw_inline(p, tok_ident(&p->cur)) != KW_NONE) {
   2588         perr(p, "expected member name after '.'");
   2589       }
   2590       mname = tok_ident(&p->cur);
   2591       advance(p);
   2592       lt = type_unqual(p->pool, lt);
   2593       if (!find_record_member_path(p, lt, mname, &mty, &off, &bf_off, &bf_w,
   2594                                    &bf_ss))
   2595         perr(p, "no such member");
   2596       c_cg_lv_member(p, off, mty, bf_off, bf_w, bf_ss);
   2597       continue;
   2598     }
   2599     if (is_punct(&t, P_ARROW)) {
   2600       const Type* lt0;
   2601       const Type* rec_ty;
   2602       Sym mname;
   2603       const Type* mty = NULL;
   2604       i64 off = 0;
   2605       u16 bf_off = 0, bf_w = 0;
   2606       u32 bf_ss = 0;
   2607       advance(p); /* `->` */
   2608       to_rvalue(p);
   2609       lt0 = c_cg_top_type(p);
   2610       if (!lt0 || lt0->kind != TY_PTR) {
   2611         perr(p, "'->' requires a pointer operand");
   2612       }
   2613       rec_ty = type_unqual(p->pool, lt0->ptr.pointee);
   2614       if (!rec_ty || (rec_ty->kind != TY_STRUCT && rec_ty->kind != TY_UNION)) {
   2615         perr(p, "'->' on pointer to non-struct/union");
   2616       }
   2617       if (p->cur.kind != TOK_IDENT ||
   2618           ident_kw_inline(p, tok_ident(&p->cur)) != KW_NONE) {
   2619         perr(p, "expected member name after '->'");
   2620       }
   2621       mname = tok_ident(&p->cur);
   2622       advance(p);
   2623       if (!find_record_member_path(p, rec_ty, mname, &mty, &off, &bf_off, &bf_w,
   2624                                    &bf_ss))
   2625         perr(p, "no such member");
   2626       c_cg_deref(p, rec_ty);
   2627       c_cg_lv_member(p, off, mty, bf_off, bf_w, bf_ss);
   2628       continue;
   2629     }
   2630     break;
   2631   }
   2632 }
   2633 
   2634 void parse_unary(Parser* p) {
   2635   Tok t = p->cur;
   2636   if (is_punct(&t, '(')) {
   2637     Tok n = peek1(p);
   2638     if (starts_type_name(p, &n)) {
   2639       const Type* dst;
   2640       const Type* src;
   2641       advance(p); /* '(' */
   2642       dst = parse_type_name(p);
   2643       expect_punct(p, ')', "')' after type-name");
   2644       if (is_punct(&p->cur, '{')) {
   2645         FrameSlotDesc fsd;
   2646         FrameSlot slot;
   2647         const Type* lit_ty = dst;
   2648         if (lit_ty && lit_ty->kind == TY_ARRAY && lit_ty->arr.incomplete) {
   2649           lit_ty = complete_incomplete_array(p, lit_ty);
   2650         }
   2651         memset(&fsd, 0, sizeof fsd);
   2652         fsd.type = lit_ty;
   2653         fsd.size = c_abi_sizeof(p->abi, p->pool, lit_ty);
   2654         fsd.align = c_abi_alignof(p->abi, p->pool, lit_ty);
   2655         fsd.kind = FS_LOCAL;
   2656         fsd.flags = FSF_NONE;
   2657         slot = c_cg_local(p, &fsd);
   2658         init_at(p, slot, lit_ty, 0, lit_ty);
   2659         c_cg_push_local_typed(p, slot, lit_ty);
   2660         return;
   2661       }
   2662       if (c_const_guard_active(p) && p->cur.kind == TOK_FLT) {
   2663         const Type* tu = type_unqual(p->pool, dst);
   2664         if (tu && type_is_int(tu)) {
   2665           double fv = parse_float_literal(p, &p->cur);
   2666           advance(p);
   2667           c_cg_push_int(p, (i64)fv, tu);
   2668           return;
   2669         }
   2670       }
   2671       parse_unary(p);
   2672       to_rvalue(p);
   2673       src = c_cg_top_type(p);
   2674       if (dst && dst->kind == TY_VOID) {
   2675         c_cg_drop(p);
   2676         c_cg_push_int(p, 0, ty_int(p));
   2677         return;
   2678       }
   2679       if (!c_type_is_scalar(dst) || !c_type_is_scalar(src)) {
   2680         perr(p, "cast requires scalar type");
   2681       }
   2682       if (src && src->kind == TY_PTR && dst->kind == TY_PTR) {
   2683         c_cg_convert(p, dst);
   2684         return;
   2685       }
   2686       c_cg_convert(p, dst);
   2687       return;
   2688     }
   2689   }
   2690   if (is_punct(&t, '+')) {
   2691     advance(p);
   2692     parse_unary(p);
   2693     to_rvalue(p);
   2694     require_arith(p, c_cg_top_type(p), "unary '+'");
   2695     return;
   2696   }
   2697   if (is_punct(&t, '-')) {
   2698     advance(p);
   2699     parse_unary(p);
   2700     to_rvalue(p);
   2701     require_arith(p, c_cg_top_type(p), "unary '-'");
   2702     c_cg_unop(p, UO_NEG);
   2703     return;
   2704   }
   2705   if (is_punct(&t, '!')) {
   2706     advance(p);
   2707     parse_unary(p);
   2708     to_rvalue(p);
   2709     require_scalar(p, c_cg_top_type(p), "unary '!'");
   2710     c_cg_push_int(p, 0, ty_int(p));
   2711     c_cg_cmp(p, CMP_EQ);
   2712     return;
   2713   }
   2714   if (is_punct(&t, '~')) {
   2715     advance(p);
   2716     parse_unary(p);
   2717     to_rvalue(p);
   2718     if (!type_is_int(c_cg_top_type(p))) {
   2719       perr(p, "unary '~' requires integer operand");
   2720     }
   2721     c_cg_unop(p, UO_BNOT);
   2722     return;
   2723   }
   2724   if (is_punct(&t, P_AND)) {
   2725     /* GNU labels-as-values: `&&label` yields the label's address as void*. */
   2726     Sym name;
   2727     SrcLoc loc;
   2728     c_const_guard_note_at(
   2729         p, pp_materialize_loc(p->pp, t.loc),
   2730         "address constant is not an integer constant expression");
   2731     advance(p); /* '&&' */
   2732     if (p->cur.kind != TOK_IDENT ||
   2733         ident_kw_inline(p, tok_ident(&p->cur)) != KW_NONE) {
   2734       perr(p, "expected label name after '&&'");
   2735     }
   2736     name = tok_ident(&p->cur);
   2737     loc = pp_materialize_loc(p->pp, p->cur.loc);
   2738     advance(p);
   2739     c_cg_push_label_addr(p, take_label_addr(p, name, loc));
   2740     return;
   2741   }
   2742   if (is_punct(&t, '&')) {
   2743     c_const_guard_note_at(
   2744         p, pp_materialize_loc(p->pp, t.loc),
   2745         "address constant is not an integer constant expression");
   2746     advance(p);
   2747     parse_unary(p);
   2748     if (!c_cg_top_is_lvalue(p) &&
   2749         !(c_cg_top_type(p) && c_cg_top_type(p)->kind == TY_FUNC)) {
   2750       perr(p, "address-of requires lvalue operand");
   2751     }
   2752     if (c_cg_top_is_bitfield(p)) perr(p, "cannot take address of bit-field");
   2753     if (c_cg_top_is_register(p))
   2754       perr(p, "cannot take address of register object");
   2755     c_stack_protector_note_address(p);
   2756     c_cg_addr(p);
   2757     return;
   2758   }
   2759   if (is_punct(&t, '*')) {
   2760     const Type* pty;
   2761     const Type* pointee;
   2762     advance(p);
   2763     parse_unary(p);
   2764     to_rvalue(p);
   2765     pty = c_cg_top_type(p);
   2766     if (!pty || pty->kind != TY_PTR) {
   2767       perr(p, "indirection requires pointer operand");
   2768     }
   2769     pointee = pty->ptr.pointee;
   2770     if (pointee && pointee->kind == TY_VOID) {
   2771       perr(p, "dereferencing pointer to incomplete type");
   2772     }
   2773     c_cg_deref(p, pointee);
   2774     return;
   2775   }
   2776   if (is_punct(&t, P_INC) || is_punct(&t, P_DEC)) {
   2777     BinOp bop = is_punct(&t, P_INC) ? BO_IADD : BO_ISUB;
   2778     c_const_guard_note_at(p, pp_materialize_loc(p->pp, t.loc),
   2779                           "increment/decrement in integer constant expression");
   2780     advance(p);
   2781     parse_unary(p);
   2782     if (!c_cg_top_is_modifiable_lvalue(p)) {
   2783       perr(p, "increment/decrement requires modifiable lvalue");
   2784     }
   2785     if (!c_type_is_scalar(c_cg_top_type(p))) {
   2786       perr(p, "increment/decrement requires scalar operand");
   2787     }
   2788     c_cg_inc_dec(p, bop, /*post=*/0);
   2789     return;
   2790   }
   2791   if (is_kw(p, &t, KW_SIZEOF)) {
   2792     const Type* ty = NULL;
   2793     FrameSlot vla_slot = FRAME_SLOT_NONE;
   2794     advance(p);
   2795     if (is_punct(&p->cur, '(')) {
   2796       Tok n = peek1(p);
   2797       if (starts_type_name(p, &n)) {
   2798         advance(p);
   2799         ty = parse_type_name(p);
   2800         expect_punct(p, ')', "')'");
   2801       } else {
   2802         p->last_pushed_vla_slot = FRAME_SLOT_NONE;
   2803         c_const_guard_not_eval_push(p);
   2804         c_cg_codegen_suppress_push(p);
   2805         parse_unary(p);
   2806         ty = c_cg_top_type(p);
   2807         vla_slot = p->last_pushed_vla_slot;
   2808         if (c_cg_top_is_bitfield(p)) perr(p, "sizeof bit-field");
   2809         c_cg_drop(p);
   2810         c_cg_codegen_suppress_pop(p);
   2811         c_const_guard_not_eval_pop(p);
   2812       }
   2813     } else {
   2814       p->last_pushed_vla_slot = FRAME_SLOT_NONE;
   2815       c_const_guard_not_eval_push(p);
   2816       c_cg_codegen_suppress_push(p);
   2817       parse_unary(p);
   2818       ty = c_cg_top_type(p);
   2819       vla_slot = p->last_pushed_vla_slot;
   2820       if (c_cg_top_is_bitfield(p)) perr(p, "sizeof bit-field");
   2821       c_cg_drop(p);
   2822       c_cg_codegen_suppress_pop(p);
   2823       c_const_guard_not_eval_pop(p);
   2824     }
   2825     if (vla_slot != FRAME_SLOT_NONE) {
   2826       c_cg_push_local_typed(p, vla_slot, ty_size_t(p));
   2827       c_cg_load(p);
   2828     } else {
   2829       require_sizeof_type(p, ty);
   2830       c_cg_push_int(p, (i64)c_abi_sizeof(p->abi, p->pool, ty), ty_size_t(p));
   2831     }
   2832     return;
   2833   }
   2834   if (is_kw(p, &t, KW_GENERIC)) {
   2835     advance(p);
   2836     expect_punct(p, '(', "'('");
   2837     c_const_guard_not_eval_push(p);
   2838     c_cg_codegen_suppress_push(p);
   2839     parse_assign_expr(p);
   2840     to_rvalue(p);
   2841     const Type* ctl_ty = c_cg_top_type(p);
   2842     c_cg_drop(p);
   2843     c_cg_codegen_suppress_pop(p);
   2844     c_const_guard_not_eval_pop(p);
   2845     expect_punct(p, ',', "','");
   2846     int emitted = 0;
   2847     Tok* default_buf = NULL;
   2848     u32 default_len = 0;
   2849     const Type** assoc_types = NULL;
   2850     u32 assoc_n = 0;
   2851     u32 assoc_cap = 0;
   2852     int saw_default = 0;
   2853     for (;;) {
   2854       const Type* assoc_ty = NULL;
   2855       int is_default = 0;
   2856       if (is_kw(p, &p->cur, KW_DEFAULT)) {
   2857         advance(p);
   2858         is_default = 1;
   2859         if (saw_default) perr(p, "_Generic has duplicate default association");
   2860         saw_default = 1;
   2861       } else {
   2862         assoc_ty = parse_type_name(p);
   2863         {
   2864           const Type* au = type_unqual(p->pool, assoc_ty);
   2865           for (u32 ai = 0; ai < assoc_n; ++ai) {
   2866             if (type_compatible(assoc_types[ai], au)) {
   2867               perr(p, "_Generic association type is duplicated");
   2868             }
   2869           }
   2870           if (assoc_n == assoc_cap) {
   2871             u32 nc = assoc_cap ? assoc_cap * 2u : 8u;
   2872             const Type** nb = arena_array(p->pool->arena, const Type*, nc);
   2873             if (!nb) perr(p, "out of memory recording _Generic associations");
   2874             if (assoc_n) memcpy(nb, assoc_types, assoc_n * sizeof(*nb));
   2875             assoc_types = nb;
   2876             assoc_cap = nc;
   2877           }
   2878           assoc_types[assoc_n++] = au;
   2879         }
   2880       }
   2881       expect_punct(p, ':', "':' in _Generic association");
   2882       int take = 0;
   2883       if (!emitted && !is_default && ctl_ty && assoc_ty &&
   2884           type_compatible(type_unqual(p->pool, ctl_ty),
   2885                           type_unqual(p->pool, assoc_ty))) {
   2886         take = 1;
   2887       }
   2888       if (take) {
   2889         parse_assign_expr(p);
   2890         emitted = 1;
   2891       } else if (is_default && !default_buf) {
   2892         u32 cap = 16;
   2893         Tok* buf = arena_array(p->pool->arena, Tok, cap);
   2894         u32 len = 0;
   2895         int paren_depth = 0, brack_depth = 0, brace_depth = 0;
   2896         while (p->cur.kind != TOK_EOF) {
   2897           if (paren_depth == 0 && brack_depth == 0 && brace_depth == 0) {
   2898             if (is_punct(&p->cur, ',') || is_punct(&p->cur, ')')) break;
   2899           }
   2900           if (len == cap) {
   2901             u32 new_cap = cap * 2;
   2902             Tok* nv = arena_array(p->pool->arena, Tok, new_cap);
   2903             if (!nv) perr(p, "out of memory recording _Generic default");
   2904             memcpy(nv, buf, len * sizeof(Tok));
   2905             buf = nv;
   2906             cap = new_cap;
   2907           }
   2908           buf[len++] = p->cur;
   2909           if (is_punct(&p->cur, '('))
   2910             ++paren_depth;
   2911           else if (is_punct(&p->cur, ')'))
   2912             --paren_depth;
   2913           else if (is_punct(&p->cur, '['))
   2914             ++brack_depth;
   2915           else if (is_punct(&p->cur, ']'))
   2916             --brack_depth;
   2917           else if (is_punct(&p->cur, '{'))
   2918             ++brace_depth;
   2919           else if (is_punct(&p->cur, '}'))
   2920             --brace_depth;
   2921           advance(p);
   2922         }
   2923         if (len == cap) {
   2924           u32 new_cap = cap + 1;
   2925           Tok* nv = arena_array(p->pool->arena, Tok, new_cap);
   2926           if (!nv) perr(p, "out of memory recording _Generic default");
   2927           memcpy(nv, buf, len * sizeof(Tok));
   2928           buf = nv;
   2929           cap = new_cap;
   2930         }
   2931         memset(&buf[len], 0, sizeof(Tok));
   2932         buf[len].kind = TOK_PUNCT;
   2933         buf[len].aux = ',';
   2934         ++len;
   2935         default_buf = buf;
   2936         default_len = len;
   2937       } else {
   2938         int paren_depth = 0;
   2939         int brack_depth = 0;
   2940         int brace_depth = 0;
   2941         while (p->cur.kind != TOK_EOF) {
   2942           if (paren_depth == 0 && brack_depth == 0 && brace_depth == 0) {
   2943             if (is_punct(&p->cur, ',') || is_punct(&p->cur, ')')) break;
   2944           }
   2945           if (is_punct(&p->cur, '('))
   2946             ++paren_depth;
   2947           else if (is_punct(&p->cur, ')'))
   2948             --paren_depth;
   2949           else if (is_punct(&p->cur, '['))
   2950             ++brack_depth;
   2951           else if (is_punct(&p->cur, ']'))
   2952             --brack_depth;
   2953           else if (is_punct(&p->cur, '{'))
   2954             ++brace_depth;
   2955           else if (is_punct(&p->cur, '}'))
   2956             --brace_depth;
   2957           advance(p);
   2958         }
   2959       }
   2960       if (!accept_punct(p, ',')) break;
   2961     }
   2962     if (!emitted && default_buf) {
   2963       Tok* save_replay = p->replay;
   2964       u32 save_cap = p->replay_cap;
   2965       u32 save_len = p->replay_len;
   2966       u32 save_pos = p->replay_pos;
   2967       u8 save_active = p->replay_active;
   2968       Tok save_cur = p->cur;
   2969       int save_has_next = p->has_next;
   2970       p->replay = default_buf;
   2971       p->replay_cap = default_len;
   2972       p->replay_len = default_len;
   2973       p->replay_pos = 1;
   2974       p->replay_active = 1;
   2975       p->cur = default_buf[0];
   2976       p->has_next = 0;
   2977       parse_assign_expr(p);
   2978       emitted = 1;
   2979       p->replay = save_replay;
   2980       p->replay_cap = save_cap;
   2981       p->replay_len = save_len;
   2982       p->replay_pos = save_pos;
   2983       p->replay_active = save_active;
   2984       p->cur = save_cur;
   2985       p->has_next = save_has_next;
   2986     }
   2987     expect_punct(p, ')', "')' after _Generic");
   2988     if (!emitted) {
   2989       perr(p, "_Generic: no association matched and no default present");
   2990     }
   2991     return;
   2992   }
   2993   if (is_kw(p, &t, KW_ALIGNOF)) {
   2994     const Type* ty;
   2995     advance(p);
   2996     expect_punct(p, '(', "'('");
   2997     if (starts_type_name(p, &p->cur)) {
   2998       ty = parse_type_name(p);
   2999     } else {
   3000       c_const_guard_not_eval_push(p);
   3001       c_cg_codegen_suppress_push(p);
   3002       parse_unary(p);
   3003       ty = c_cg_top_type(p);
   3004       c_cg_drop(p);
   3005       c_cg_codegen_suppress_pop(p);
   3006       c_const_guard_not_eval_pop(p);
   3007     }
   3008     expect_punct(p, ')', "')'");
   3009     c_cg_push_int(p, (i64)c_abi_alignof(p->abi, p->pool, ty), ty_size_t(p));
   3010     return;
   3011   }
   3012   parse_postfix(p);
   3013 }
   3014 
   3015 /* ============================================================
   3016  * Binary operator levels
   3017  * ============================================================ */
   3018 
   3019 static int type_is_fp(const Type* t) {
   3020   return t &&
   3021          (t->kind == TY_FLOAT || t->kind == TY_DOUBLE || t->kind == TY_LDOUBLE);
   3022 }
   3023 
   3024 static const Type* common_fp_type(Parser* p, const Type* a, const Type* b) {
   3025   if (!type_is_fp(a) && !type_is_fp(b)) return NULL;
   3026   if ((a && a->kind == TY_LDOUBLE) || (b && b->kind == TY_LDOUBLE)) {
   3027     return type_prim(p->pool, TY_LDOUBLE);
   3028   }
   3029   if ((a && a->kind == TY_DOUBLE) || (b && b->kind == TY_DOUBLE)) {
   3030     return type_prim(p->pool, TY_DOUBLE);
   3031   }
   3032   return type_prim(p->pool, TY_FLOAT);
   3033 }
   3034 
   3035 static void emit_fp_binop(Parser* p, BinOp bop, const Type* common) {
   3036   if (c_cg_top_type(p) != common) c_cg_convert(p, common);
   3037   c_cg_swap(p);
   3038   if (c_cg_top_type(p) != common) c_cg_convert(p, common);
   3039   c_cg_swap(p);
   3040   BinOp fop;
   3041   switch (bop) {
   3042     case BO_IADD:
   3043       fop = BO_FADD;
   3044       break;
   3045     case BO_ISUB:
   3046       fop = BO_FSUB;
   3047       break;
   3048     case BO_IMUL:
   3049       fop = BO_FMUL;
   3050       break;
   3051     case BO_SDIV:
   3052       fop = BO_FDIV;
   3053       break;
   3054     default:
   3055       perr(p, "operator does not apply to floating types");
   3056       return;
   3057   }
   3058   c_cg_binop(p, fop);
   3059 }
   3060 
   3061 static void coerce_fp_cmp_operands(Parser* p, const Type* common) {
   3062   if (c_cg_top_type(p) != common) c_cg_convert(p, common);
   3063   c_cg_swap(p);
   3064   if (c_cg_top_type(p) != common) c_cg_convert(p, common);
   3065   c_cg_swap(p);
   3066 }
   3067 
   3068 static void coerce_arith_operands(Parser* p, const Type* common) {
   3069   if (!common) return;
   3070   if (c_cg_top_type(p) != common) c_cg_convert(p, common);
   3071   c_cg_swap(p);
   3072   if (c_cg_top_type(p) != common) c_cg_convert(p, common);
   3073   c_cg_swap(p);
   3074 }
   3075 
   3076 static CmpOp unsigned_rel_cmp(CmpOp cop) {
   3077   switch (cop) {
   3078     case CMP_LT_S:
   3079       return CMP_LT_U;
   3080     case CMP_LE_S:
   3081       return CMP_LE_U;
   3082     case CMP_GT_S:
   3083       return CMP_GT_U;
   3084     case CMP_GE_S:
   3085       return CMP_GE_U;
   3086     default:
   3087       return cop;
   3088   }
   3089 }
   3090 
   3091 static BinOp int_div_rem_binop(BinOp op, const Type* common) {
   3092   if (c_cg_type_is_signed(common)) return op;
   3093   switch (op) {
   3094     case BO_SDIV:
   3095       return BO_UDIV;
   3096     case BO_SREM:
   3097       return BO_UREM;
   3098     default:
   3099       return op;
   3100   }
   3101 }
   3102 
   3103 static void parse_mul(Parser* p) {
   3104   parse_unary(p);
   3105   for (;;) {
   3106     Tok t = p->cur;
   3107     SrcLoc op_loc;
   3108     BinOp bop;
   3109     if (is_punct(&t, '*')) {
   3110       bop = BO_IMUL;
   3111     } else if (is_punct(&t, '/')) {
   3112       bop = BO_SDIV;
   3113     } else if (is_punct(&t, '%')) {
   3114       bop = BO_SREM;
   3115     } else {
   3116       break;
   3117     }
   3118     op_loc = pp_materialize_loc(p->pp, t.loc);
   3119     advance(p);
   3120     to_rvalue(p);
   3121     parse_unary(p);
   3122     to_rvalue(p);
   3123     const Type* lt = c_cg_top2_type(p);
   3124     const Type* rt = c_cg_top_type(p);
   3125     const Type* common = common_fp_type(p, lt, rt);
   3126     if (bop == BO_SREM) {
   3127       if (!type_is_int(lt) || !type_is_int(rt))
   3128         perr(p, "operator '%' requires integer operands");
   3129     } else if (!type_is_arith(lt) || !type_is_arith(rt)) {
   3130       perr(p, "multiplicative operator requires arithmetic operands");
   3131     }
   3132     if (common) {
   3133       emit_fp_binop(p, bop, common);
   3134     } else {
   3135       const Type* icommon = integer_common_type(p, lt, rt);
   3136       BinOp ibop;
   3137       coerce_arith_operands(p, icommon);
   3138       ibop = int_div_rem_binop(bop, icommon);
   3139       c_const_check_divrem(p, ibop, op_loc);
   3140       c_cg_binop(p, ibop);
   3141     }
   3142   }
   3143 }
   3144 
   3145 static void scale_pointer_index(Parser* p, u32 elem_size) {
   3146   const Type* idx_ty = c_abi_ptrdiff_type(p->abi, p->pool);
   3147   coerce_top_to_type(p, idx_ty);
   3148   if (elem_size != 1) {
   3149     c_cg_push_int(p, (i64)elem_size, idx_ty);
   3150     c_cg_binop(p, BO_IMUL);
   3151   }
   3152 }
   3153 
   3154 static void emit_add_or_sub(Parser* p, BinOp bop) {
   3155   const Type* lt = c_cg_top2_type(p);
   3156   const Type* rt = c_cg_top_type(p);
   3157   int l_is_ptr = lt && lt->kind == TY_PTR;
   3158   int r_is_ptr = rt && rt->kind == TY_PTR;
   3159   if (bop == BO_IADD) {
   3160     if (l_is_ptr && r_is_ptr) {
   3161       perr(p, "invalid operands to binary +");
   3162     }
   3163     if (l_is_ptr && type_is_int(rt)) {
   3164       if (lt->ptr.pointee && lt->ptr.pointee->kind == TY_VOID)
   3165         perr(p, "pointer arithmetic on void pointer");
   3166       u32 esz = c_abi_sizeof(p->abi, p->pool, lt->ptr.pointee);
   3167       scale_pointer_index(p, esz);
   3168       c_cg_binop(p, BO_IADD);
   3169       return;
   3170     }
   3171     if (r_is_ptr && type_is_int(lt)) {
   3172       if (rt->ptr.pointee && rt->ptr.pointee->kind == TY_VOID)
   3173         perr(p, "pointer arithmetic on void pointer");
   3174       c_cg_swap(p);
   3175       u32 esz = c_abi_sizeof(p->abi, p->pool, rt->ptr.pointee);
   3176       scale_pointer_index(p, esz);
   3177       c_cg_binop(p, BO_IADD);
   3178       return;
   3179     }
   3180   } else { /* BO_ISUB */
   3181     if (l_is_ptr && type_is_int(rt)) {
   3182       if (lt->ptr.pointee && lt->ptr.pointee->kind == TY_VOID)
   3183         perr(p, "pointer arithmetic on void pointer");
   3184       u32 esz = c_abi_sizeof(p->abi, p->pool, lt->ptr.pointee);
   3185       scale_pointer_index(p, esz);
   3186       c_cg_binop(p, BO_ISUB);
   3187       return;
   3188     }
   3189     if (l_is_ptr && r_is_ptr) {
   3190       if (!pointer_pointees_compatible(p, lt, rt)) {
   3191         perr(p, "subtraction of incompatible pointer types");
   3192       }
   3193       u32 esz = c_abi_sizeof(p->abi, p->pool, lt->ptr.pointee);
   3194       c_cg_binop(p, BO_ISUB);
   3195       if (esz != 1) {
   3196         c_cg_push_int(p, (i64)esz, ty_size_t(p));
   3197         c_cg_binop(p, BO_SDIV);
   3198       }
   3199       c_cg_convert(p, c_abi_ptrdiff_type(p->abi, p->pool));
   3200       return;
   3201     }
   3202   }
   3203   if (l_is_ptr || r_is_ptr) {
   3204     perr(p, "invalid operands to additive operator");
   3205   }
   3206   const Type* common = common_fp_type(p, lt, rt);
   3207   if (!common && (!type_is_arith(lt) || !type_is_arith(rt))) {
   3208     perr(p, "additive operator requires arithmetic operands");
   3209   }
   3210   if (common) {
   3211     emit_fp_binop(p, bop, common);
   3212     return;
   3213   }
   3214   common = integer_common_type(p, lt, rt);
   3215   coerce_arith_operands(p, common);
   3216   c_cg_binop(p, bop);
   3217 }
   3218 
   3219 static void parse_add(Parser* p) {
   3220   parse_mul(p);
   3221   for (;;) {
   3222     Tok t = p->cur;
   3223     BinOp bop;
   3224     if (is_punct(&t, '+')) {
   3225       bop = BO_IADD;
   3226     } else if (is_punct(&t, '-')) {
   3227       bop = BO_ISUB;
   3228     } else {
   3229       break;
   3230     }
   3231     advance(p);
   3232     to_rvalue(p);
   3233     parse_mul(p);
   3234     to_rvalue(p);
   3235     emit_add_or_sub(p, bop);
   3236   }
   3237 }
   3238 
   3239 static void parse_shift(Parser* p) {
   3240   parse_add(p);
   3241   for (;;) {
   3242     Tok t = p->cur;
   3243     SrcLoc op_loc;
   3244     BinOp bop;
   3245     if (is_punct(&t, P_SHL)) {
   3246       bop = BO_SHL;
   3247     } else if (is_punct(&t, P_SHR)) {
   3248       bop = BO_SHR_S;
   3249     } else {
   3250       break;
   3251     }
   3252     op_loc = pp_materialize_loc(p->pp, t.loc);
   3253     advance(p);
   3254     to_rvalue(p);
   3255     {
   3256       const Type* lt = c_cg_top_type(p);
   3257       const Type* lp = integer_promote_type(p, lt);
   3258       if (!type_is_int(lt)) perr(p, "shift operator requires integer operands");
   3259       if (c_cg_top_type(p) != lp) c_cg_convert(p, lp);
   3260       if (bop == BO_SHR_S && !type_is_signed_integer(lp)) bop = BO_SHR_U;
   3261     }
   3262     parse_add(p);
   3263     to_rvalue(p);
   3264     {
   3265       const Type* rt = c_cg_top_type(p);
   3266       const Type* rp = integer_promote_type(p, rt);
   3267       if (!type_is_int(rt)) perr(p, "shift operator requires integer operands");
   3268       if (c_cg_top_type(p) != rp) c_cg_convert(p, rp);
   3269     }
   3270     if (!type_is_int(c_cg_top2_type(p)) || !type_is_int(c_cg_top_type(p))) {
   3271       perr(p, "shift operator requires integer operands");
   3272     }
   3273     c_const_check_shift(p, bop, op_loc);
   3274     c_cg_binop(p, bop);
   3275   }
   3276 }
   3277 
   3278 static void parse_rel(Parser* p) {
   3279   parse_shift(p);
   3280   for (;;) {
   3281     Tok t = p->cur;
   3282     CmpOp cop;
   3283     if (is_punct(&t, '<')) {
   3284       cop = CMP_LT_S;
   3285     } else if (is_punct(&t, '>')) {
   3286       cop = CMP_GT_S;
   3287     } else if (is_punct(&t, P_LE)) {
   3288       cop = CMP_LE_S;
   3289     } else if (is_punct(&t, P_GE)) {
   3290       cop = CMP_GE_S;
   3291     } else {
   3292       break;
   3293     }
   3294     advance(p);
   3295     to_rvalue(p);
   3296     parse_shift(p);
   3297     to_rvalue(p);
   3298     {
   3299       const Type* lt = c_cg_top2_type(p);
   3300       const Type* rt = c_cg_top_type(p);
   3301       const Type* common = common_fp_type(p, lt, rt);
   3302       if (lt && lt->kind == TY_PTR && rt && rt->kind == TY_PTR) {
   3303         if (!pointer_pointees_compatible(p, lt, rt)) {
   3304           perr(p, "comparison of incompatible pointer types");
   3305         }
   3306       } else if (!type_is_arith(lt) || !type_is_arith(rt)) {
   3307         perr(p,
   3308              "relational operator requires arithmetic or compatible pointer "
   3309              "operands");
   3310       }
   3311       if (common) {
   3312         coerce_fp_cmp_operands(p, common);
   3313         switch (cop) {
   3314           case CMP_LT_S:
   3315             cop = CMP_LT_F;
   3316             break;
   3317           case CMP_LE_S:
   3318             cop = CMP_LE_F;
   3319             break;
   3320           case CMP_GT_S:
   3321             cop = CMP_GT_F;
   3322             break;
   3323           case CMP_GE_S:
   3324             cop = CMP_GE_F;
   3325             break;
   3326           default:
   3327             break;
   3328         }
   3329       } else if (type_is_arith(lt) && type_is_arith(rt)) {
   3330         common = integer_common_type(p, lt, rt);
   3331         coerce_arith_operands(p, common);
   3332         if (!integer_type_signed(p, common)) cop = unsigned_rel_cmp(cop);
   3333       }
   3334     }
   3335     c_cg_cmp(p, cop);
   3336   }
   3337 }
   3338 
   3339 static void parse_eq(Parser* p) {
   3340   parse_rel(p);
   3341   for (;;) {
   3342     Tok t = p->cur;
   3343     CmpOp cop;
   3344     if (is_punct(&t, P_EQ)) {
   3345       cop = CMP_EQ;
   3346     } else if (is_punct(&t, P_NE)) {
   3347       cop = CMP_NE;
   3348     } else {
   3349       break;
   3350     }
   3351     int lhs_null = null_pointer_constant(p, c_cg_top_type(p));
   3352     advance(p);
   3353     to_rvalue(p);
   3354     parse_rel(p);
   3355     to_rvalue(p);
   3356     {
   3357       const Type* lt = c_cg_top2_type(p);
   3358       const Type* rt = c_cg_top_type(p);
   3359       const Type* common = common_fp_type(p, lt, rt);
   3360       int lnull = lhs_null;
   3361       int rnull = null_pointer_constant(p, rt);
   3362       if (lt && lt->kind == TY_PTR && rt && rt->kind == TY_PTR) {
   3363         if (!type_is_void_ptr(lt) && !type_is_void_ptr(rt) &&
   3364             !pointer_pointees_compatible(p, lt, rt)) {
   3365           perr(p, "comparison of incompatible pointer types");
   3366         }
   3367       } else if ((lt && lt->kind == TY_PTR) || (rt && rt->kind == TY_PTR)) {
   3368         if (!lnull && !rnull) perr(p, "comparison between pointer and integer");
   3369       } else if (!type_is_arith(lt) || !type_is_arith(rt)) {
   3370         perr(p, "equality operator requires scalar operands");
   3371       }
   3372       if (common)
   3373         coerce_fp_cmp_operands(p, common);
   3374       else if (type_is_arith(lt) && type_is_arith(rt)) {
   3375         common = integer_common_type(p, lt, rt);
   3376         coerce_arith_operands(p, common);
   3377       }
   3378     }
   3379     c_cg_cmp(p, cop);
   3380   }
   3381 }
   3382 
   3383 static void parse_band(Parser* p) {
   3384   parse_eq(p);
   3385   while (is_punct(&p->cur, '&')) {
   3386     advance(p);
   3387     to_rvalue(p);
   3388     parse_eq(p);
   3389     to_rvalue(p);
   3390     if (!type_is_int(c_cg_top2_type(p)) || !type_is_int(c_cg_top_type(p))) {
   3391       perr(p, "bitwise operator requires integer operands");
   3392     }
   3393     coerce_arith_operands(
   3394         p, integer_common_type(p, c_cg_top2_type(p), c_cg_top_type(p)));
   3395     c_cg_binop(p, BO_AND);
   3396   }
   3397 }
   3398 
   3399 static void parse_bxor(Parser* p) {
   3400   parse_band(p);
   3401   while (is_punct(&p->cur, '^')) {
   3402     advance(p);
   3403     to_rvalue(p);
   3404     parse_band(p);
   3405     to_rvalue(p);
   3406     if (!type_is_int(c_cg_top2_type(p)) || !type_is_int(c_cg_top_type(p))) {
   3407       perr(p, "bitwise operator requires integer operands");
   3408     }
   3409     coerce_arith_operands(
   3410         p, integer_common_type(p, c_cg_top2_type(p), c_cg_top_type(p)));
   3411     c_cg_binop(p, BO_XOR);
   3412   }
   3413 }
   3414 
   3415 static void parse_bor(Parser* p) {
   3416   parse_bxor(p);
   3417   while (is_punct(&p->cur, '|')) {
   3418     advance(p);
   3419     to_rvalue(p);
   3420     parse_bxor(p);
   3421     to_rvalue(p);
   3422     if (!type_is_int(c_cg_top2_type(p)) || !type_is_int(c_cg_top_type(p))) {
   3423       perr(p, "bitwise operator requires integer operands");
   3424     }
   3425     coerce_arith_operands(
   3426         p, integer_common_type(p, c_cg_top2_type(p), c_cg_top_type(p)));
   3427     c_cg_binop(p, BO_OR);
   3428   }
   3429 }
   3430 
   3431 static FrameSlot ll_tmp_slot(Parser* p, const Type* ty) {
   3432   FrameSlotDesc fsd;
   3433   memset(&fsd, 0, sizeof fsd);
   3434   fsd.type = ty;
   3435   fsd.size = c_abi_sizeof(p->abi, p->pool, ty);
   3436   fsd.align = c_abi_alignof(p->abi, p->pool, ty);
   3437   fsd.kind = FS_LOCAL;
   3438   fsd.flags = FSF_NONE;
   3439   return c_cg_local(p, &fsd);
   3440 }
   3441 
   3442 static void ll_store_const(Parser* p, FrameSlot tmp, const Type* ty, i64 v) {
   3443   c_cg_push_local_typed(p, tmp, ty);
   3444   c_cg_push_int(p, v, ty);
   3445   c_cg_store_void(p);
   3446 }
   3447 
   3448 static void parse_land(Parser* p) {
   3449   parse_bor(p);
   3450   while (is_punct(&p->cur, P_AND)) {
   3451     CGLabel L_false = c_cg_label_new(p);
   3452     CGLabel L_end = c_cg_label_new(p);
   3453     const Type* result_ty = ty_int(p);
   3454     FrameSlot tmp = ll_tmp_slot(p, result_ty);
   3455     int lhs_known;
   3456     int lhs_truth = 0;
   3457     int rhs_truth = 0;
   3458     advance(p);
   3459     to_rvalue(p);
   3460     require_scalar(p, c_cg_top_type(p), "logical '&&'");
   3461     lhs_known = cg_top_const_truth(p, &lhs_truth);
   3462     if (lhs_known && !lhs_truth) {
   3463       c_cg_drop(p);
   3464       c_const_guard_not_eval_push(p);
   3465       c_cg_codegen_suppress_push(p);
   3466       parse_bor(p);
   3467       to_rvalue(p);
   3468       require_scalar(p, c_cg_top_type(p), "logical '&&'");
   3469       c_cg_drop(p);
   3470       c_cg_codegen_suppress_pop(p);
   3471       c_const_guard_not_eval_pop(p);
   3472       c_cg_push_int(p, 0, result_ty);
   3473       continue;
   3474     }
   3475     c_cg_branch_false(p, L_false);
   3476     parse_bor(p);
   3477     to_rvalue(p);
   3478     require_scalar(p, c_cg_top_type(p), "logical '&&'");
   3479     if (lhs_known && lhs_truth && cg_top_const_truth(p, &rhs_truth)) {
   3480       c_cg_drop(p);
   3481       c_cg_push_int(p, rhs_truth ? 1 : 0, result_ty);
   3482       continue;
   3483     }
   3484     c_cg_branch_false(p, L_false);
   3485     ll_store_const(p, tmp, result_ty, 1);
   3486     c_cg_jump(p, L_end);
   3487     c_cg_label_place(p, L_false);
   3488     ll_store_const(p, tmp, result_ty, 0);
   3489     c_cg_label_place(p, L_end);
   3490     c_cg_push_local_typed(p, tmp, result_ty);
   3491   }
   3492 }
   3493 
   3494 static void parse_lor(Parser* p) {
   3495   parse_land(p);
   3496   while (is_punct(&p->cur, P_OR)) {
   3497     CGLabel L_true = c_cg_label_new(p);
   3498     CGLabel L_end = c_cg_label_new(p);
   3499     const Type* result_ty = ty_int(p);
   3500     FrameSlot tmp = ll_tmp_slot(p, result_ty);
   3501     int lhs_known;
   3502     int lhs_truth = 0;
   3503     int rhs_truth = 0;
   3504     advance(p);
   3505     to_rvalue(p);
   3506     require_scalar(p, c_cg_top_type(p), "logical '||'");
   3507     lhs_known = cg_top_const_truth(p, &lhs_truth);
   3508     if (lhs_known && lhs_truth) {
   3509       c_cg_drop(p);
   3510       c_const_guard_not_eval_push(p);
   3511       c_cg_codegen_suppress_push(p);
   3512       parse_land(p);
   3513       to_rvalue(p);
   3514       require_scalar(p, c_cg_top_type(p), "logical '||'");
   3515       c_cg_drop(p);
   3516       c_cg_codegen_suppress_pop(p);
   3517       c_const_guard_not_eval_pop(p);
   3518       c_cg_push_int(p, 1, result_ty);
   3519       continue;
   3520     }
   3521     c_cg_branch_true(p, L_true);
   3522     parse_land(p);
   3523     to_rvalue(p);
   3524     require_scalar(p, c_cg_top_type(p), "logical '||'");
   3525     if (lhs_known && !lhs_truth && cg_top_const_truth(p, &rhs_truth)) {
   3526       c_cg_drop(p);
   3527       c_cg_push_int(p, rhs_truth ? 1 : 0, result_ty);
   3528       continue;
   3529     }
   3530     c_cg_branch_true(p, L_true);
   3531     ll_store_const(p, tmp, result_ty, 0);
   3532     c_cg_jump(p, L_end);
   3533     c_cg_label_place(p, L_true);
   3534     ll_store_const(p, tmp, result_ty, 1);
   3535     c_cg_label_place(p, L_end);
   3536     c_cg_push_local_typed(p, tmp, result_ty);
   3537   }
   3538 }
   3539 
   3540 static void parse_ternary(Parser* p) {
   3541   parse_lor(p);
   3542   if (!is_punct(&p->cur, '?')) return;
   3543   CGLabel L_else = c_cg_label_new(p);
   3544   CGLabel L_then = c_cg_label_new(p);
   3545   CGLabel L_end = c_cg_label_new(p);
   3546   const Type* result_ty = ty_int(p);
   3547   const Type* then_store_ty;
   3548   int then_null = 0;
   3549   FrameSlot then_tmp;
   3550   FrameSlotDesc fsd;
   3551   advance(p); /* '?' */
   3552   to_rvalue(p);
   3553   require_scalar(p, c_cg_top_type(p), "conditional operator");
   3554   {
   3555     int cond_truth = 0;
   3556     if (c_const_guard_active(p) && cg_top_const_truth(p, &cond_truth)) {
   3557       const Type* selected_ty;
   3558       const Type* other_ty;
   3559       const Type* common;
   3560       c_cg_drop(p);
   3561       if (cond_truth) {
   3562         parse_expr(p);
   3563         to_rvalue(p);
   3564         selected_ty = c_cg_top_type(p);
   3565         expect_punct(p, ':', "':' in ternary");
   3566         c_const_guard_not_eval_push(p);
   3567         c_cg_codegen_suppress_push(p);
   3568         parse_assign_expr(p);
   3569         to_rvalue(p);
   3570         other_ty = c_cg_top_type(p);
   3571         c_cg_drop(p);
   3572         c_cg_codegen_suppress_pop(p);
   3573         c_const_guard_not_eval_pop(p);
   3574       } else {
   3575         c_const_guard_not_eval_push(p);
   3576         c_cg_codegen_suppress_push(p);
   3577         parse_expr(p);
   3578         to_rvalue(p);
   3579         other_ty = c_cg_top_type(p);
   3580         c_cg_drop(p);
   3581         c_cg_codegen_suppress_pop(p);
   3582         c_const_guard_not_eval_pop(p);
   3583         expect_punct(p, ':', "':' in ternary");
   3584         parse_assign_expr(p);
   3585         to_rvalue(p);
   3586         selected_ty = c_cg_top_type(p);
   3587       }
   3588       common = common_fp_type(p, selected_ty, other_ty);
   3589       if (!common && type_is_int(selected_ty) && type_is_int(other_ty))
   3590         common = integer_common_type(p, selected_ty, other_ty);
   3591       if (common && c_cg_top_type(p) != common) c_cg_convert(p, common);
   3592       return;
   3593     }
   3594   }
   3595   c_cg_branch_false(p, L_else);
   3596   parse_expr(p);
   3597   to_rvalue(p);
   3598   result_ty = c_cg_top_type(p);
   3599   then_null = null_pointer_constant(p, result_ty);
   3600   if (!result_ty) result_ty = ty_int(p);
   3601   if (type_is_int(result_ty)) {
   3602     result_ty = type_promoted(p->pool, result_ty);
   3603     if (c_cg_top_type(p) != result_ty) c_cg_convert(p, result_ty);
   3604   }
   3605   then_store_ty = result_ty;
   3606   memset(&fsd, 0, sizeof fsd);
   3607   fsd.type = then_store_ty;
   3608   fsd.size = c_abi_sizeof(p->abi, p->pool, then_store_ty);
   3609   fsd.align = c_abi_alignof(p->abi, p->pool, then_store_ty);
   3610   fsd.kind = FS_LOCAL;
   3611   fsd.flags = FSF_NONE;
   3612   then_tmp = c_cg_local(p, &fsd);
   3613   if (c_cg_top_type(p) != then_store_ty) c_cg_convert(p, then_store_ty);
   3614   c_cg_push_local_typed(p, then_tmp, then_store_ty);
   3615   c_cg_swap(p);
   3616   c_cg_store_void(p);
   3617   c_cg_jump(p, L_then);
   3618   c_cg_label_place(p, L_else);
   3619   expect_punct(p, ':', "':' in ternary");
   3620   parse_assign_expr(p);
   3621   to_rvalue(p);
   3622   {
   3623     const Type* else_ty = c_cg_top_type(p);
   3624     int else_null = null_pointer_constant(p, else_ty);
   3625     const Type* common = common_fp_type(p, then_store_ty, else_ty);
   3626     const Type* ptr_result = conditional_pointer_type(
   3627         p, then_store_ty, then_null, else_ty, else_null);
   3628     const Type* final_ty = then_store_ty;
   3629     FrameSlot final_tmp = then_tmp;
   3630     int use_final_tmp = 0;
   3631 
   3632     if (!common && type_is_int(then_store_ty) && type_is_int(else_ty))
   3633       common = integer_common_type(p, then_store_ty, else_ty);
   3634     if ((then_store_ty && then_store_ty->kind == TY_PTR) ||
   3635         (else_ty && else_ty->kind == TY_PTR)) {
   3636       if (!ptr_result) perr(p, "conditional operator pointer type mismatch");
   3637       final_ty = ptr_result;
   3638     } else if (type_is_arith(then_store_ty) && type_is_arith(else_ty)) {
   3639       if (common) final_ty = common;
   3640     } else if (!type_compatible(then_store_ty, else_ty)) {
   3641       perr(p, "conditional operator type mismatch");
   3642     }
   3643 
   3644     if (final_ty != then_store_ty) {
   3645       FrameSlotDesc ffsd;
   3646       memset(&ffsd, 0, sizeof ffsd);
   3647       ffsd.type = final_ty;
   3648       ffsd.size = c_abi_sizeof(p->abi, p->pool, final_ty);
   3649       ffsd.align = c_abi_alignof(p->abi, p->pool, final_ty);
   3650       ffsd.kind = FS_LOCAL;
   3651       ffsd.flags = FSF_NONE;
   3652       final_tmp = c_cg_local(p, &ffsd);
   3653       use_final_tmp = 1;
   3654     }
   3655 
   3656     if (c_cg_top_type(p) != final_ty) c_cg_convert(p, final_ty);
   3657     c_cg_push_local_typed(p, final_tmp, final_ty);
   3658     c_cg_swap(p);
   3659     c_cg_store_void(p);
   3660     c_cg_jump(p, L_end);
   3661 
   3662     c_cg_label_place(p, L_then);
   3663     if (use_final_tmp) {
   3664       c_cg_push_local_typed(p, then_tmp, then_store_ty);
   3665       c_cg_load(p);
   3666       if (c_cg_top_type(p) != final_ty) c_cg_convert(p, final_ty);
   3667       c_cg_push_local_typed(p, final_tmp, final_ty);
   3668       c_cg_swap(p);
   3669       c_cg_store_void(p);
   3670     }
   3671 
   3672     c_cg_label_place(p, L_end);
   3673     c_cg_push_local_typed(p, final_tmp, final_ty);
   3674     return;
   3675   }
   3676 }
   3677 
   3678 void parse_assign_expr(Parser* p) {
   3679   parse_ternary(p);
   3680   Tok t = p->cur;
   3681   SrcLoc op_loc = pp_materialize_loc(p->pp, t.loc);
   3682   BinOp compound;
   3683   int is_simple_assign;
   3684   if (is_punct(&t, '=')) {
   3685     is_simple_assign = 1;
   3686     compound = (BinOp)0;
   3687   } else if (is_punct(&t, P_ADD_ASSIGN)) {
   3688     is_simple_assign = 0;
   3689     compound = BO_IADD;
   3690   } else if (is_punct(&t, P_SUB_ASSIGN)) {
   3691     is_simple_assign = 0;
   3692     compound = BO_ISUB;
   3693   } else if (is_punct(&t, P_MUL_ASSIGN)) {
   3694     is_simple_assign = 0;
   3695     compound = BO_IMUL;
   3696   } else if (is_punct(&t, P_DIV_ASSIGN)) {
   3697     is_simple_assign = 0;
   3698     compound = BO_SDIV;
   3699   } else if (is_punct(&t, P_MOD_ASSIGN)) {
   3700     is_simple_assign = 0;
   3701     compound = BO_SREM;
   3702   } else if (is_punct(&t, P_AND_ASSIGN)) {
   3703     is_simple_assign = 0;
   3704     compound = BO_AND;
   3705   } else if (is_punct(&t, P_OR_ASSIGN)) {
   3706     is_simple_assign = 0;
   3707     compound = BO_OR;
   3708   } else if (is_punct(&t, P_XOR_ASSIGN)) {
   3709     is_simple_assign = 0;
   3710     compound = BO_XOR;
   3711   } else if (is_punct(&t, P_SHL_ASSIGN)) {
   3712     is_simple_assign = 0;
   3713     compound = BO_SHL;
   3714   } else if (is_punct(&t, P_SHR_ASSIGN)) {
   3715     is_simple_assign = 0;
   3716     compound = BO_SHR_S;
   3717   } else {
   3718     return;
   3719   }
   3720   c_const_guard_note_at(p, op_loc, "assignment in integer constant expression");
   3721   if (!c_cg_top_is_modifiable_lvalue(p)) {
   3722     perr(p, "assignment requires modifiable lvalue");
   3723   }
   3724   advance(p);
   3725   const Type* lhs = c_cg_top_type(p);
   3726   if (compound == BO_SHR_S && !type_is_signed_integer(lhs)) compound = BO_SHR_U;
   3727   {
   3728     if (lhs && (lhs->qual & Q_CONST)) {
   3729       perr(p, "assignment to const-qualified object");
   3730     }
   3731   }
   3732   if (is_simple_assign) {
   3733     parse_assign_expr(p);
   3734     to_rvalue(p);
   3735     {
   3736       const Type* rhs = c_cg_top_type(p);
   3737       CSemCheck chk = c_sem_check_assignment(p->pool, lhs, rhs);
   3738       if (!chk.ok) perr(p, "%.*s", KIT_SLICE_ARG(kit_slice_cstr(chk.message)));
   3739     }
   3740     coerce_top_to_lvalue(p);
   3741     c_cg_store(p);
   3742     return;
   3743   }
   3744   c_cg_dup(p);
   3745   c_cg_load(p);
   3746   parse_assign_expr(p);
   3747   to_rvalue(p);
   3748   {
   3749     const Type* rhs = c_cg_top_type(p);
   3750     int op = '+';
   3751     switch (compound) {
   3752       case BO_IADD:
   3753         op = '+';
   3754         break;
   3755       case BO_ISUB:
   3756         op = '-';
   3757         break;
   3758       case BO_IMUL:
   3759         op = '*';
   3760         break;
   3761       case BO_SDIV:
   3762         op = '/';
   3763         break;
   3764       case BO_SREM:
   3765         op = '%';
   3766         break;
   3767       case BO_AND:
   3768         op = '&';
   3769         break;
   3770       case BO_OR:
   3771         op = '|';
   3772         break;
   3773       case BO_XOR:
   3774         op = '^';
   3775         break;
   3776       case BO_SHL:
   3777         op = '<';
   3778         break;
   3779       case BO_SHR_S:
   3780         op = '>';
   3781         break;
   3782       case BO_SHR_U:
   3783         op = '>';
   3784         break;
   3785       default:
   3786         op = 0;
   3787         break;
   3788     }
   3789     CSemCheck chk = c_sem_check_compound_assignment(p->pool, lhs, rhs, op);
   3790     if (!chk.ok) perr(p, "%.*s", KIT_SLICE_ARG(kit_slice_cstr(chk.message)));
   3791   }
   3792   if (compound == BO_IADD || compound == BO_ISUB) {
   3793     emit_add_or_sub(p, compound);
   3794   } else {
   3795     const Type* lt = c_cg_top2_type(p);
   3796     const Type* rt = c_cg_top_type(p);
   3797     const Type* common = common_fp_type(p, lt, rt);
   3798     if (common) {
   3799       if (compound == BO_SREM)
   3800         perr(p, "operator '%%=' requires integer operands");
   3801       emit_fp_binop(p, compound, common);
   3802     } else {
   3803       const Type* icommon = integer_common_type(p, lt, rt);
   3804       coerce_arith_operands(p, icommon);
   3805       c_cg_binop(p, int_div_rem_binop(compound, icommon));
   3806     }
   3807   }
   3808   coerce_top_to_type(p, lhs);
   3809   c_cg_retag_keep_flags(p, 1, lhs);
   3810   c_cg_store(p);
   3811 }
   3812 
   3813 void parse_expr(Parser* p) {
   3814   parse_assign_expr(p);
   3815   while (is_punct(&p->cur, ',')) {
   3816     c_const_guard_note(p, "comma operator in integer constant expression");
   3817     advance(p);
   3818     c_cg_drop(p);
   3819     parse_assign_expr(p);
   3820   }
   3821 }
   3822 
   3823 /* parse_cond_expr is the ternary level, provided for completeness */
   3824 void parse_cond_expr(Parser* p) { parse_ternary(p); }