kit

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

cg.c (25145B)


      1 #include <string.h>
      2 
      3 #include "parse/parse_priv.h"
      4 
      5 #define C_CG_VALUE_LVALUE ((uint16_t)1u)
      6 #define C_CG_VALUE_MODIFIABLE ((uint16_t)2u)
      7 #define C_CG_VALUE_BITFIELD ((uint16_t)4u)
      8 #define C_CG_VALUE_NULL_PTR_CONST ((uint16_t)8u)
      9 #define C_CG_VALUE_REGISTER ((uint16_t)16u)
     10 
     11 KitCgTypeId c_cg_tid(Parser* p, const Type* ty) {
     12   return type_cg_id_in_pool(p->c, p->pool, ty);
     13 }
     14 
     15 static uint16_t c_cg_lvalue_flags_for_type(const Type* ty) {
     16   uint16_t flags = C_CG_VALUE_LVALUE;
     17   if (ty && !(ty->qual & Q_CONST) && ty->kind != TY_ARRAY &&
     18       ty->kind != TY_FUNC && ty->kind != TY_VOID) {
     19     flags |= C_CG_VALUE_MODIFIABLE;
     20   }
     21   return flags;
     22 }
     23 
     24 /* Resolve the operational CG type for a value-stack slot. A complete recorded
     25  * type is authoritative. A missing type, or an incomplete nominal record left
     26  * by dereferencing a pointer, crosses back through the frontend lang_type so a
     27  * by-value operation sees the completed layout. kit_cg_slot_cg_type reads the
     28  * slot's id directly (no struct copy). */
     29 static KitCgTypeId c_cg_slot_cg_id(Parser* p, u32 depth) {
     30   const Type* lang_ty =
     31       (const Type*)kit_cg_slot_lang_type(p->cg, depth);
     32   KitCgTypeId cg = kit_cg_slot_cg_type(p->cg, depth);
     33   KitCgTypeId resolved;
     34   if (cg && kit_cg_type_is_complete(p->c, cg)) return cg;
     35 
     36   /* A pointer to a record needs only its nominal CG declaration. Dereferencing
     37    * that pointer therefore leaves an incomplete record id on the value stack,
     38    * even when the C record itself is complete. A later by-value operation
     39    * (load/store/aggregate copy) must cross back through the language type so
     40    * its field layout is installed before the memory operation captures a byte
     41    * count. Returning the recorded id unconditionally made the first
     42    * `*dst = *src` for such a type a zero-byte copy. */
     43   resolved = lang_ty ? c_cg_tid(p, lang_ty) : KIT_CG_TYPE_NONE;
     44   return resolved ? resolved : cg;
     45 }
     46 
     47 static KitCgTypeId c_cg_top_cg_id(Parser* p) { return c_cg_slot_cg_id(p, 0); }
     48 
     49 static KitCgTypeId c_cg_top2_cg_id(Parser* p) { return c_cg_slot_cg_id(p, 1); }
     50 
     51 static KitCgMemAccess c_cg_mem_id(Parser* p, KitCgTypeId id, const Type* ty) {
     52   KitCgMemAccess m;
     53   (void)p;
     54   memset(&m, 0, sizeof m);
     55   m.type = id;
     56   if (ty && (ty->qual & Q_VOLATILE)) m.flags |= KIT_CG_MEM_VOLATILE;
     57   if (type_is_int(ty) && c_cg_type_is_signed(ty))
     58     m.flags |= KIT_CG_MEM_SOURCE_SIGNED;
     59   return m;
     60 }
     61 
     62 KitCgMemAccess c_cg_mem(Parser* p, const Type* ty) {
     63   return c_cg_mem_id(p, c_cg_tid(p, ty), ty);
     64 }
     65 
     66 const Type* c_cg_top_type(Parser* p) {
     67   return (const Type*)kit_cg_slot_lang_type(p->cg, 0);
     68 }
     69 
     70 const Type* c_cg_top2_type(Parser* p) {
     71   return (const Type*)kit_cg_slot_lang_type(p->cg, 1);
     72 }
     73 
     74 void c_cg_retag_top(Parser* p, const Type* ty) {
     75   kit_cg_retag_top(p->cg, ty, 0);
     76 }
     77 
     78 void c_cg_retag_at(Parser* p, u32 depth, const Type* ty, uint16_t flags) {
     79   kit_cg_retag_at(p->cg, depth, ty, flags);
     80 }
     81 
     82 void c_cg_retag_keep_flags(Parser* p, u32 depth, const Type* ty) {
     83   kit_cg_retag_at(p->cg, depth, ty, kit_cg_slot_lang_flags(p->cg, depth));
     84 }
     85 
     86 void c_cg_dup(Parser* p) { kit_cg_dup(p->cg); }
     87 
     88 void c_cg_swap(Parser* p) { kit_cg_swap(p->cg); }
     89 
     90 void c_cg_drop(Parser* p) { kit_cg_drop(p->cg); }
     91 
     92 void c_cg_reclaim_temps(Parser* p) { kit_cg_reclaim_temps(p->cg); }
     93 
     94 uint32_t c_cg_stack_depth(Parser* p) { return kit_cg_stack_depth(p->cg); }
     95 
     96 void c_cg_drop_to_depth(Parser* p, uint32_t depth) {
     97   while (kit_cg_stack_depth(p->cg) > depth) kit_cg_drop(p->cg);
     98 }
     99 
    100 int c_cg_top_is_bitfield(Parser* p) {
    101   return (kit_cg_slot_lang_flags(p->cg, 0) & C_CG_VALUE_BITFIELD) != 0;
    102 }
    103 
    104 void c_cg_set_top_bitfield(Parser* p) {
    105   kit_cg_set_top_flags(p->cg, C_CG_VALUE_BITFIELD, 0);
    106 }
    107 
    108 int c_cg_top_is_register(Parser* p) {
    109   return (kit_cg_slot_lang_flags(p->cg, 0) & C_CG_VALUE_REGISTER) != 0;
    110 }
    111 
    112 void c_cg_set_top_register(Parser* p) {
    113   kit_cg_set_top_flags(p->cg, C_CG_VALUE_REGISTER, 0);
    114 }
    115 
    116 int c_cg_top_is_lvalue(Parser* p) {
    117   return (kit_cg_slot_lang_flags(p->cg, 0) & C_CG_VALUE_LVALUE) != 0;
    118 }
    119 
    120 int c_cg_top_is_modifiable_lvalue(Parser* p) {
    121   uint16_t flags = kit_cg_slot_lang_flags(p->cg, 0);
    122   return (flags & (C_CG_VALUE_LVALUE | C_CG_VALUE_MODIFIABLE)) ==
    123          (C_CG_VALUE_LVALUE | C_CG_VALUE_MODIFIABLE);
    124 }
    125 
    126 int c_cg_top_is_null_ptr_const(Parser* p) {
    127   return (kit_cg_slot_lang_flags(p->cg, 0) & C_CG_VALUE_NULL_PTR_CONST) != 0;
    128 }
    129 
    130 void c_cg_set_top_lvalue(Parser* p) {
    131   const Type* ty = c_cg_top_type(p);
    132   kit_cg_retag_top(p->cg, ty, c_cg_lvalue_flags_for_type(ty));
    133 }
    134 
    135 int c_cg_emit_enabled(Parser* p) { return p && p->suppress_codegen == 0; }
    136 
    137 void c_cg_codegen_suppress_push(Parser* p) {
    138   if (!p) return;
    139   ++p->suppress_codegen;
    140   kit_cg_unevaluated_push(p->cg);
    141 }
    142 
    143 void c_cg_codegen_suppress_pop(Parser* p) {
    144   if (!p) return;
    145   if (!p->suppress_codegen)
    146     perr(p, "internal parser codegen suppression underflow");
    147   kit_cg_unevaluated_pop(p->cg);
    148   --p->suppress_codegen;
    149 }
    150 
    151 int c_cg_type_is_fp(const Type* ty) {
    152   return ty && type_kind_is_fp((TypeKind)ty->kind);
    153 }
    154 
    155 int c_cg_type_is_signed(const Type* ty) { return type_is_signed_integer(ty); }
    156 
    157 KitCgIntBinOp c_cg_int_binop(BinOp op) {
    158   switch (op) {
    159     case BO_IADD:
    160       return KIT_CG_INT_ADD;
    161     case BO_ISUB:
    162       return KIT_CG_INT_SUB;
    163     case BO_IMUL:
    164       return KIT_CG_INT_MUL;
    165     case BO_SDIV:
    166       return KIT_CG_INT_SDIV;
    167     case BO_UDIV:
    168       return KIT_CG_INT_UDIV;
    169     case BO_SREM:
    170       return KIT_CG_INT_SREM;
    171     case BO_UREM:
    172       return KIT_CG_INT_UREM;
    173     case BO_AND:
    174       return KIT_CG_INT_AND;
    175     case BO_OR:
    176       return KIT_CG_INT_OR;
    177     case BO_XOR:
    178       return KIT_CG_INT_XOR;
    179     case BO_SHL:
    180       return KIT_CG_INT_SHL;
    181     case BO_SHR_S:
    182       return KIT_CG_INT_ASHR;
    183     case BO_SHR_U:
    184       return KIT_CG_INT_LSHR;
    185     default:
    186       return KIT_CG_INT_ADD;
    187   }
    188 }
    189 
    190 KitCgFpBinOp c_cg_fp_binop(BinOp op) {
    191   switch (op) {
    192     case BO_FADD:
    193       return KIT_CG_FP_ADD;
    194     case BO_FSUB:
    195       return KIT_CG_FP_SUB;
    196     case BO_FMUL:
    197       return KIT_CG_FP_MUL;
    198     case BO_FDIV:
    199       return KIT_CG_FP_DIV;
    200     default:
    201       return KIT_CG_FP_ADD;
    202   }
    203 }
    204 
    205 KitCgIntCmpOp c_cg_int_cmp(CmpOp op) {
    206   switch (op) {
    207     case CMP_EQ:
    208       return KIT_CG_INT_EQ;
    209     case CMP_NE:
    210       return KIT_CG_INT_NE;
    211     case CMP_LT_S:
    212       return KIT_CG_INT_LT_S;
    213     case CMP_LE_S:
    214       return KIT_CG_INT_LE_S;
    215     case CMP_GT_S:
    216       return KIT_CG_INT_GT_S;
    217     case CMP_GE_S:
    218       return KIT_CG_INT_GE_S;
    219     case CMP_LT_U:
    220       return KIT_CG_INT_LT_U;
    221     case CMP_LE_U:
    222       return KIT_CG_INT_LE_U;
    223     case CMP_GT_U:
    224       return KIT_CG_INT_GT_U;
    225     case CMP_GE_U:
    226       return KIT_CG_INT_GE_U;
    227     default:
    228       return KIT_CG_INT_EQ;
    229   }
    230 }
    231 
    232 KitCgFpCmpOp c_cg_fp_cmp(CmpOp op) {
    233   switch (op) {
    234     case CMP_EQ:
    235       return KIT_CG_FP_OEQ;
    236     case CMP_NE:
    237       return KIT_CG_FP_UNE;
    238     case CMP_LT_F:
    239     case CMP_OLT_F:
    240       return KIT_CG_FP_OLT;
    241     case CMP_LE_F:
    242     case CMP_OLE_F:
    243       return KIT_CG_FP_OLE;
    244     case CMP_GT_F:
    245     case CMP_OGT_F:
    246       return KIT_CG_FP_OGT;
    247     case CMP_GE_F:
    248     case CMP_OGE_F:
    249       return KIT_CG_FP_OGE;
    250     case CMP_OEQ_F:
    251       return KIT_CG_FP_OEQ;
    252     case CMP_ONE_F:
    253       return KIT_CG_FP_ONE;
    254     case CMP_UEQ_F:
    255       return KIT_CG_FP_UEQ;
    256     case CMP_UNE_F:
    257       return KIT_CG_FP_UNE;
    258     case CMP_ULT_F:
    259       return KIT_CG_FP_ULT;
    260     case CMP_ULE_F:
    261       return KIT_CG_FP_ULE;
    262     case CMP_UGT_F:
    263       return KIT_CG_FP_UGT;
    264     case CMP_UGE_F:
    265       return KIT_CG_FP_UGE;
    266     default:
    267       return KIT_CG_FP_OEQ;
    268   }
    269 }
    270 
    271 KitCgAtomicOp c_cg_atomic_op(AtomicOp op) {
    272   switch (op) {
    273     case AO_XCHG:
    274       return KIT_CG_ATOMIC_XCHG;
    275     case AO_ADD:
    276       return KIT_CG_ATOMIC_ADD;
    277     case AO_SUB:
    278       return KIT_CG_ATOMIC_SUB;
    279     case AO_AND:
    280       return KIT_CG_ATOMIC_AND;
    281     case AO_OR:
    282       return KIT_CG_ATOMIC_OR;
    283     case AO_XOR:
    284       return KIT_CG_ATOMIC_XOR;
    285     case AO_NAND:
    286       return KIT_CG_ATOMIC_NAND;
    287   }
    288   return KIT_CG_ATOMIC_XCHG;
    289 }
    290 
    291 KitCgMemOrder c_cg_mem_order(MemOrder ord) { return (KitCgMemOrder)ord; }
    292 
    293 static int c_cg_slot_is_volatile(const FrameSlotDesc* fsd) {
    294   return fsd && ((fsd->flags & FSF_VOLATILE) ||
    295                  (fsd->type && (fsd->type->qual & Q_VOLATILE)));
    296 }
    297 
    298 FrameSlot c_cg_local(Parser* p, const FrameSlotDesc* fsd) {
    299   KitCgLocalAttrs attrs;
    300   if (!c_cg_emit_enabled(p)) return FRAME_SLOT_NONE;
    301   memset(&attrs, 0, sizeof attrs);
    302   attrs.name = fsd->name;
    303   attrs.align = fsd->align;
    304   attrs.debug_type = type_cg_debug_in_pool(p->cg, p->c, p->pool, fsd->type);
    305   if (c_cg_slot_is_volatile(fsd)) attrs.flags |= KIT_CG_LOCAL_MEMORY_REQUIRED;
    306   return kit_cg_local(p->cg, c_cg_tid(p, fsd->type), attrs);
    307 }
    308 
    309 FrameSlot c_cg_param_slot(Parser* p, u32 index, const FrameSlotDesc* fsd) {
    310   KitCgLocalAttrs attrs;
    311   if (!c_cg_emit_enabled(p)) return FRAME_SLOT_NONE;
    312   memset(&attrs, 0, sizeof attrs);
    313   attrs.name = fsd->name;
    314   attrs.align = fsd->align;
    315   attrs.debug_type = type_cg_debug_in_pool(p->cg, p->c, p->pool, fsd->type);
    316   if (c_cg_slot_is_volatile(fsd)) attrs.flags |= KIT_CG_LOCAL_MEMORY_REQUIRED;
    317   return kit_cg_param(p->cg, index, c_cg_tid(p, fsd->type), attrs);
    318 }
    319 
    320 void c_cg_param(Parser* p, const CGParamDesc* pd) {
    321   (void)p;
    322   (void)pd;
    323 }
    324 
    325 void c_cg_func_begin(Parser* p, const CGFuncDesc* fd) {
    326   KitCgFuncAttrs attrs;
    327   if (!c_cg_emit_enabled(p)) return;
    328   memset(&attrs, 0, sizeof attrs);
    329   attrs.inline_policy = fd->inline_policy;
    330   attrs.debug_type = type_cg_debug_in_pool(p->cg, p->c, p->pool, fd->fn_type);
    331   if (fd->flags & CGFD_NORETURN) attrs.flags |= KIT_CG_FUNC_NORETURN;
    332   kit_cg_func_begin_attrs(p->cg, fd->sym, attrs);
    333 }
    334 
    335 void c_cg_func_end(Parser* p) {
    336   if (c_cg_emit_enabled(p)) kit_cg_func_end(p->cg);
    337 }
    338 
    339 void c_cg_set_loc(Parser* p, SrcLoc loc) { kit_cg_set_loc(p->cg, loc); }
    340 
    341 static void c_cg_push_dummy_place(Parser* p, const Type* ty) {
    342   const Type* base = ty ? ty : type_void(p->pool);
    343   const Type* ptr_ty = type_ptr(p->pool, base);
    344   kit_cg_push_null(p->cg, c_cg_tid(p, ptr_ty));
    345   kit_cg_deref(p->cg, 0);
    346 }
    347 
    348 void c_cg_push_int(Parser* p, i64 v, const Type* ty) {
    349   uint16_t flags = 0;
    350   kit_cg_push_int(p->cg, (uint64_t)v, c_cg_tid(p, ty));
    351   if (v == 0) flags |= C_CG_VALUE_NULL_PTR_CONST;
    352   kit_cg_retag_top(p->cg, ty, flags);
    353 }
    354 
    355 void c_cg_push_float(Parser* p, double v, const Type* ty) {
    356   kit_cg_push_float(p->cg, v, c_cg_tid(p, ty));
    357   kit_cg_retag_top(p->cg, ty, 0);
    358 }
    359 
    360 void c_cg_push_local_typed(Parser* p, FrameSlot s, const Type* ty) {
    361   if (s == FRAME_SLOT_NONE) {
    362     c_cg_push_dummy_place(p, ty);
    363   } else {
    364     kit_cg_push_local(p->cg, s);
    365   }
    366   kit_cg_retag_top(p->cg, ty, c_cg_lvalue_flags_for_type(ty));
    367 }
    368 
    369 void c_cg_push_global(Parser* p, ObjSymId sym, const Type* ty) {
    370   if (sym == OBJ_SYM_NONE) {
    371     c_cg_push_dummy_place(p, ty);
    372   } else if (ty && ty->kind == TY_FUNC) {
    373     kit_cg_push_symbol_addr(p->cg, sym, 0);
    374   } else {
    375     kit_cg_push_symbol_addr(p->cg, sym, 0);
    376     kit_cg_deref(p->cg, 0);
    377   }
    378   kit_cg_retag_top(p->cg, ty, c_cg_lvalue_flags_for_type(ty));
    379 }
    380 
    381 void c_cg_load(Parser* p) {
    382   const Type* ty = c_cg_top_type(p);
    383   kit_cg_load(p->cg, c_cg_mem_id(p, c_cg_top_cg_id(p), ty));
    384   kit_cg_retag_top(p->cg, ty, 0);
    385 }
    386 
    387 void c_cg_addr(Parser* p) {
    388   const Type* ty = c_cg_top_type(p);
    389   const Type* ptr_ty = type_ptr(p->pool, ty ? ty : type_void(p->pool));
    390   if (!(ty && ty->kind == TY_FUNC)) kit_cg_addr(p->cg);
    391   kit_cg_retag_top(p->cg, ptr_ty, 0);
    392 }
    393 
    394 void c_cg_push_label_addr(Parser* p, CGLabel label) {
    395   const Type* vp = type_ptr(p->pool, type_void(p->pool));
    396   kit_cg_push_label_addr(p->cg, label, c_cg_tid(p, vp));
    397   kit_cg_retag_top(p->cg, vp, 0);
    398 }
    399 
    400 void c_cg_computed_goto(Parser* p, const CGLabel* targets, u32 ntargets) {
    401   kit_cg_computed_goto(p->cg, targets, ntargets);
    402 }
    403 
    404 CGLabel c_cg_label_new(Parser* p) {
    405   if (!c_cg_emit_enabled(p)) return (CGLabel)1;
    406   return kit_cg_label_new(p->cg);
    407 }
    408 
    409 void c_cg_label_place(Parser* p, CGLabel l) {
    410   if (c_cg_emit_enabled(p)) kit_cg_label_place(p->cg, l);
    411 }
    412 
    413 void c_cg_jump(Parser* p, CGLabel l) {
    414   if (c_cg_emit_enabled(p)) kit_cg_jump(p->cg, l);
    415 }
    416 
    417 void c_cg_branch_true(Parser* p, CGLabel l) {
    418   if (!c_cg_emit_enabled(p)) {
    419     if (c_cg_stack_depth(p)) c_cg_drop(p);
    420     return;
    421   }
    422   kit_cg_branch_true(p->cg, l);
    423 }
    424 
    425 void c_cg_branch_false(Parser* p, CGLabel l) {
    426   if (!c_cg_emit_enabled(p)) {
    427     if (c_cg_stack_depth(p)) c_cg_drop(p);
    428     return;
    429   }
    430   kit_cg_branch_false(p->cg, l);
    431 }
    432 
    433 void c_cg_store(Parser* p) {
    434   const Type* lv_ty = c_cg_top2_type(p);
    435   const Type* rv_ty = c_cg_top_type(p);
    436   const Type* mem_ty = lv_ty;
    437   KitCgTypeId mem_cg = c_cg_top2_cg_id(p);
    438   if (rv_ty && type_is_ptr(rv_ty) && (!lv_ty || !type_is_ptr(lv_ty))) {
    439     mem_ty = rv_ty;
    440     mem_cg = c_cg_top_cg_id(p);
    441   }
    442   kit_cg_store_keep(p->cg, c_cg_mem_id(p, mem_cg, mem_ty));
    443   kit_cg_retag_top(p->cg, rv_ty, 0);
    444 }
    445 
    446 void c_cg_store_void(Parser* p) {
    447   const Type* lv_ty = c_cg_top2_type(p);
    448   const Type* rv_ty = c_cg_top_type(p);
    449   const Type* mem_ty = lv_ty;
    450   KitCgTypeId mem_cg = c_cg_top2_cg_id(p);
    451   if (rv_ty && type_is_ptr(rv_ty) && (!lv_ty || !type_is_ptr(lv_ty))) {
    452     mem_ty = rv_ty;
    453     mem_cg = c_cg_top_cg_id(p);
    454   }
    455   kit_cg_store(p->cg, c_cg_mem_id(p, mem_cg, mem_ty));
    456 }
    457 
    458 void c_cg_deref(Parser* p, const Type* pointee) {
    459   const Type* ptr_ty = c_cg_top_type(p);
    460   if (pointee && pointee->kind == TY_FUNC) {
    461     c_cg_retag_top(p, pointee);
    462     c_cg_set_top_lvalue(p);
    463     return;
    464   }
    465   if (ptr_ty && ptr_ty->kind == TY_PTR && ptr_ty->ptr.pointee != pointee) {
    466     const Type* want_ptr_ty = type_ptr(p->pool, pointee);
    467     kit_cg_bitcast(p->cg, c_cg_tid(p, want_ptr_ty));
    468     c_cg_retag_top(p, want_ptr_ty);
    469   }
    470   kit_cg_deref(p->cg, 0);
    471   kit_cg_retag_top(p->cg, pointee, c_cg_lvalue_flags_for_type(pointee));
    472 }
    473 
    474 void c_cg_lv_member(Parser* p, i64 byte_offset, const Type* field_ty,
    475                     u16 bf_offset, u16 bf_width, u32 bf_storage_size) {
    476   const Type* base_ty = c_cg_top_type(p);
    477   int was_lvalue = c_cg_top_is_lvalue(p);
    478   int base_is_rvalue_agg =
    479       !was_lvalue && base_ty &&
    480       (base_ty->kind == TY_STRUCT || base_ty->kind == TY_UNION);
    481   uint16_t flags = 0;
    482   kit_cg_field_at(p->cg, byte_offset, c_cg_tid(p, field_ty));
    483   if (bf_width) {
    484     kit_cg_field_bits(p->cg, bf_offset, bf_width, bf_storage_size,
    485                       c_cg_type_is_signed(field_ty));
    486   }
    487   if (was_lvalue)
    488     flags = c_cg_lvalue_flags_for_type(field_ty);
    489   else if (base_is_rvalue_agg)
    490     flags = C_CG_VALUE_LVALUE;
    491   if (bf_width) flags |= C_CG_VALUE_BITFIELD;
    492   kit_cg_retag_top(p->cg, field_ty, flags);
    493 }
    494 
    495 void c_cg_lv_subscript(Parser* p, u32 elem_size, const Type* elem_ty) {
    496   (void)elem_size;
    497   kit_cg_elem(p->cg, 0);
    498   kit_cg_retag_top(p->cg, elem_ty, c_cg_lvalue_flags_for_type(elem_ty));
    499 }
    500 
    501 void c_cg_decay_array(Parser* p, const Type* arr_ty) {
    502   const Type* ptr_ty = type_ptr(p->pool, arr_ty->arr.elem);
    503   kit_cg_addr(p->cg);
    504   kit_cg_bitcast(p->cg, c_cg_tid(p, ptr_ty));
    505   kit_cg_retag_top(p->cg, ptr_ty, 0);
    506 }
    507 
    508 void c_cg_binop(Parser* p, BinOp op) {
    509   const Type* result = c_cg_top2_type(p);
    510   if (op == BO_FADD || op == BO_FSUB || op == BO_FMUL || op == BO_FDIV)
    511     kit_cg_fp_binop(p->cg, c_cg_fp_binop(op), KIT_CG_FP_NONE);
    512   else
    513     kit_cg_int_binop(p->cg, c_cg_int_binop(op), KIT_CG_INTOP_NONE);
    514   kit_cg_retag_top(p->cg, result, 0);
    515 }
    516 
    517 void c_cg_unop(Parser* p, UnOp op) {
    518   const Type* ty = c_cg_top_type(p);
    519   if (op == UO_NEG && c_cg_type_is_fp(ty)) {
    520     kit_cg_fp_unop(p->cg, KIT_CG_FP_NEG, KIT_CG_FP_NONE);
    521   } else {
    522     KitCgIntUnOp iop = op == UO_NOT    ? KIT_CG_INT_NOT
    523                        : op == UO_BNOT ? KIT_CG_INT_BNOT
    524                                        : KIT_CG_INT_NEG;
    525     kit_cg_int_unop(p->cg, iop, KIT_CG_INTOP_NONE);
    526   }
    527   kit_cg_retag_top(p->cg, ty, 0);
    528 }
    529 
    530 void c_cg_cmp(Parser* p, CmpOp op) {
    531   if (op >= CMP_LT_F ||
    532       ((op == CMP_EQ || op == CMP_NE) && c_cg_type_is_fp(c_cg_top_type(p))))
    533     kit_cg_fp_cmp(p->cg, c_cg_fp_cmp(op));
    534   else
    535     kit_cg_int_cmp(p->cg, c_cg_int_cmp(op));
    536   kit_cg_retag_top(p->cg, type_prim(p->pool, TY_INT), 0);
    537 }
    538 
    539 void c_cg_convert(Parser* p, const Type* dst) {
    540   const Type* src = c_cg_top_type(p);
    541   KitCgTypeId src_id = c_cg_top_cg_id(p);
    542   KitCgTypeId id = c_cg_tid(p, dst);
    543   u32 ss = (u32)kit_cg_type_size(p->c, src_id);
    544   u32 ds = (u32)kit_cg_type_size(p->c, id);
    545   int si = type_is_int(src) || type_is_ptr(src);
    546   int di = type_is_int(dst) || type_is_ptr(dst);
    547   int sf = c_cg_type_is_fp(src);
    548   int df = c_cg_type_is_fp(dst);
    549   if (src == dst) return;
    550   if (src && (src->kind == TY_STRUCT || src->kind == TY_UNION)) {
    551     c_cg_retag_keep_flags(p, 0, dst);
    552     return;
    553   }
    554   if (dst->kind == TY_BOOL && src->kind != TY_BOOL) {
    555     if (sf) {
    556       kit_cg_push_float(p->cg, 0.0, src_id);
    557       kit_cg_fp_cmp(p->cg, KIT_CG_FP_UNE);
    558     } else {
    559       kit_cg_push_int(p->cg, 0, src_id);
    560       kit_cg_int_cmp(p->cg, KIT_CG_INT_NE);
    561     }
    562     kit_cg_trunc(p->cg, id);
    563     kit_cg_retag_top(p->cg, dst, 0);
    564     return;
    565   }
    566   if (type_is_ptr(src) && type_is_ptr(dst)) {
    567     kit_cg_bitcast(p->cg, id);
    568   } else if (si && di) {
    569     if (ds < ss)
    570       kit_cg_trunc(p->cg, id);
    571     else if (ds > ss && type_is_int(src) && c_cg_type_is_signed(src))
    572       kit_cg_sext(p->cg, id);
    573     else if (ds > ss)
    574       kit_cg_zext(p->cg, id);
    575     else if (type_is_ptr(src) != type_is_ptr(dst))
    576       kit_cg_bitcast(p->cg, id);
    577   } else if (type_is_int(src) && df) {
    578     if (c_cg_type_is_signed(src))
    579       kit_cg_sint_to_float(p->cg, id, KIT_CG_ROUND_DEFAULT);
    580     else
    581       kit_cg_uint_to_float(p->cg, id, KIT_CG_ROUND_DEFAULT);
    582   } else if (sf && type_is_int(dst)) {
    583     if (c_cg_type_is_signed(dst))
    584       kit_cg_float_to_sint(p->cg, id, KIT_CG_ROUND_DEFAULT);
    585     else
    586       kit_cg_float_to_uint(p->cg, id, KIT_CG_ROUND_DEFAULT);
    587   } else if (sf && df) {
    588     if (ds > ss)
    589       kit_cg_fpext(p->cg, id);
    590     else if (ds < ss)
    591       kit_cg_fptrunc(p->cg, id);
    592   } else {
    593     kit_cg_bitcast(p->cg, id);
    594   }
    595   kit_cg_retag_top(p->cg, dst, 0);
    596 }
    597 
    598 static void c_cg_emit_inc_step(Parser* p, const Type* ty, BinOp op,
    599                                const Type* step_ty, u32 step) {
    600   if (c_cg_type_is_fp(ty)) {
    601     c_cg_push_float(p, 1.0, ty);
    602     c_cg_binop(p, op == BO_ISUB ? BO_FSUB : BO_FADD);
    603   } else {
    604     i64 amount = (ty && ty->kind == TY_PTR) ? (i64)step : 1;
    605     c_cg_push_int(p, amount, step_ty);
    606     c_cg_binop(p, op);
    607   }
    608 }
    609 
    610 void c_cg_inc_dec(Parser* p, BinOp op, int post) {
    611   const Type* ty = c_cg_top_type(p);
    612   const Type* step_ty = ty;
    613   u32 step = 1;
    614   KitCgMemAccess access = c_cg_mem_id(p, c_cg_top_cg_id(p), ty);
    615   if (ty && ty->kind == TY_PTR) {
    616     const Type* pointee = ty->ptr.pointee;
    617     if (pointee && pointee->kind == TY_VOID)
    618       perr(p, "pointer arithmetic on void pointer");
    619     step = c_abi_sizeof(p->abi, p->pool, pointee);
    620     step_ty = c_abi_ptrdiff_type(p->abi, p->pool);
    621   }
    622   c_cg_dup(p);
    623   c_cg_load(p);
    624   if (post) {
    625     FrameSlotDesc fsd;
    626     FrameSlot tmp;
    627     memset(&fsd, 0, sizeof fsd);
    628     fsd.type = ty;
    629     fsd.size = c_abi_sizeof(p->abi, p->pool, ty);
    630     fsd.align = c_abi_alignof(p->abi, p->pool, ty);
    631     fsd.kind = FS_LOCAL;
    632     tmp = c_cg_local(p, &fsd);
    633     c_cg_push_local_typed(p, tmp, ty);
    634     c_cg_swap(p);
    635     c_cg_store_void(p);
    636     c_cg_push_local_typed(p, tmp, ty);
    637     c_cg_load(p);
    638     c_cg_emit_inc_step(p, ty, op, step_ty, step);
    639     kit_cg_store(p->cg, access);
    640     c_cg_push_local_typed(p, tmp, ty);
    641     c_cg_load(p);
    642   } else {
    643     c_cg_emit_inc_step(p, ty, op, step_ty, step);
    644     kit_cg_store_keep(p->cg, access);
    645     kit_cg_retag_top(p->cg, ty, 0);
    646   }
    647 }
    648 
    649 void c_cg_call(Parser* p, u32 nargs, const Type* fn_type) {
    650   kit_cg_call_default(p->cg, nargs, c_cg_tid(p, fn_type));
    651   if (fn_type && fn_type->kind == TY_FUNC && fn_type->fn.ret->kind != TY_VOID)
    652     kit_cg_retag_top(p->cg, fn_type->fn.ret, 0);
    653 }
    654 
    655 void c_cg_call_symbol(Parser* p, KitCgSym sym, u32 nargs, const Type* fn_type) {
    656   KitCgCallAttrs attrs;
    657   memset(&attrs, 0, sizeof attrs);
    658   kit_cg_call_symbol(p->cg, sym, nargs, attrs);
    659   if (fn_type && fn_type->kind == TY_FUNC && fn_type->fn.ret->kind != TY_VOID)
    660     kit_cg_retag_top(p->cg, fn_type->fn.ret, 0);
    661 }
    662 
    663 void c_cg_ret(Parser* p, int has_value) {
    664   if (p->stack_protector_scan) {
    665     if (has_value) c_cg_drop(p);
    666     return;
    667   }
    668   if (has_value) {
    669     kit_cg_ret(p->cg);
    670   } else if (c_cg_emit_enabled(p)) {
    671     if (p->cur_func_ret && p->cur_func_ret->kind != TY_VOID)
    672       kit_cg_unreachable(p->cg);
    673     else
    674       kit_cg_ret(p->cg);
    675   }
    676 }
    677 
    678 void c_cg_alloca(Parser* p) {
    679   const Type* vp = type_ptr(p->pool, type_void(p->pool));
    680   c_stack_protector_enable(p);
    681   kit_cg_alloca(p->cg, 16, c_cg_tid(p, vp));
    682   kit_cg_retag_top(p->cg, vp, 0);
    683 }
    684 
    685 void c_cg_va_arg(Parser* p, const Type* ty) {
    686   kit_cg_vararg_next(p->cg, c_cg_tid(p, ty));
    687   kit_cg_retag_top(p->cg, ty, 0);
    688 }
    689 
    690 void c_cg_va_start(Parser* p) { kit_cg_vararg_start(p->cg); }
    691 
    692 void c_cg_va_end(Parser* p) { kit_cg_vararg_end(p->cg); }
    693 
    694 void c_cg_va_copy(Parser* p) { kit_cg_vararg_copy(p->cg); }
    695 
    696 void c_cg_atomic_load(Parser* p, MemOrder ord) {
    697   const Type* pty = c_cg_top_type(p);
    698   const Type* ty = (pty && pty->kind == TY_PTR) ? pty->ptr.pointee : pty;
    699   kit_cg_atomic_load(p->cg, c_cg_mem(p, ty), c_cg_mem_order(ord));
    700   kit_cg_retag_top(p->cg, ty, 0);
    701 }
    702 
    703 void c_cg_atomic_store(Parser* p, MemOrder ord) {
    704   const Type* pty = c_cg_top2_type(p);
    705   const Type* ty = (pty && pty->kind == TY_PTR) ? pty->ptr.pointee : pty;
    706   kit_cg_atomic_store(p->cg, c_cg_mem(p, ty), c_cg_mem_order(ord));
    707 }
    708 
    709 void c_cg_atomic_rmw(Parser* p, AtomicOp op, MemOrder ord) {
    710   const Type* pty = c_cg_top2_type(p);
    711   const Type* ty = (pty && pty->kind == TY_PTR) ? pty->ptr.pointee : pty;
    712   kit_cg_atomic_rmw(p->cg, c_cg_mem(p, ty), c_cg_atomic_op(op),
    713                     c_cg_mem_order(ord));
    714   kit_cg_retag_top(p->cg, ty, 0);
    715 }
    716 
    717 void c_cg_atomic_cas(Parser* p, MemOrder succ, MemOrder fail) {
    718   const Type* ty = c_cg_top2_type(p);
    719   kit_cg_atomic_cmpxchg(p->cg, c_cg_mem(p, ty), c_cg_mem_order(succ),
    720                         c_cg_mem_order(fail), 0);
    721   c_cg_retag_at(p, 1, ty, 0);
    722   c_cg_retag_top(p, type_prim(p->pool, TY_BOOL));
    723 }
    724 
    725 void c_cg_fence(Parser* p, MemOrder ord) {
    726   kit_cg_atomic_fence(p->cg, c_cg_mem_order(ord));
    727 }
    728 
    729 void c_cg_intrinsic_unary_to_int(Parser* p, IntrinKind k) {
    730   KitCgIntrinsic ck = k == INTRIN_CLZ   ? KIT_CG_INTRIN_CLZ
    731                       : k == INTRIN_CTZ ? KIT_CG_INTRIN_CTZ
    732                                         : KIT_CG_INTRIN_POPCOUNT;
    733   const Type* ity = type_prim(p->pool, TY_INT);
    734   kit_cg_intrinsic(p->cg, ck, 1, c_cg_tid(p, ity));
    735   kit_cg_retag_top(p->cg, ity, 0);
    736 }
    737 
    738 void c_cg_intrinsic_void(Parser* p, IntrinKind k) {
    739   if (k == INTRIN_UNREACHABLE) {
    740     kit_cg_unreachable(p->cg);
    741   } else {
    742     kit_cg_intrinsic(p->cg, KIT_CG_INTRIN_TRAP, 0,
    743                      kit_cg_type_builtin(p->c, KIT_CG_BUILTIN_VOID));
    744   }
    745 }
    746 
    747 void c_cg_syscall(Parser* p, u32 nargs, const Type* long_ty) {
    748   kit_cg_intrinsic(p->cg, KIT_CG_INTRIN_SYSCALL, nargs, c_cg_tid(p, long_ty));
    749   kit_cg_retag_top(p->cg, long_ty, 0);
    750 }
    751 
    752 void c_cg_readcyclecounter(Parser* p) {
    753   const Type* ull = type_prim(p->pool, TY_ULLONG);
    754   kit_cg_intrinsic(p->cg, KIT_CG_INTRIN_READCYCLECOUNTER, 0, c_cg_tid(p, ull));
    755   kit_cg_retag_top(p->cg, ull, 0);
    756 }
    757 
    758 void c_cg_frame_or_return_address(Parser* p, int is_return, u32 level) {
    759   const Type* void_ptr = type_ptr(p->pool, type_void(p->pool));
    760   KitCgIntrinsic intrin =
    761       is_return ? KIT_CG_INTRIN_RETURN_ADDRESS : KIT_CG_INTRIN_FRAME_ADDRESS;
    762   c_cg_push_int(p, (i64)level, type_prim(p->pool, TY_INT));
    763   kit_cg_intrinsic(p->cg, intrin, 1, c_cg_tid(p, void_ptr));
    764   kit_cg_retag_top(p->cg, void_ptr, 0);
    765 }
    766 
    767 void c_cg_inline_asm(Parser* p, const char* tmpl, const AsmConstraint* outs,
    768                      u32 nout, const AsmConstraint* ins, u32 nin,
    769                      const Sym* clobbers, u32 nclob, u32 flags) {
    770   KitCgInlineAsm a;
    771   KitCgAsmOperand* o = NULL;
    772   KitCgAsmOperand* in = NULL;
    773   KitSym* cl = NULL;
    774   memset(&a, 0, sizeof a);
    775   a.tmpl = kit_sym_intern(p->c, kit_slice_cstr(tmpl ? tmpl : ""));
    776   if (nout) {
    777     o = arena_zarray(p->pool->arena, KitCgAsmOperand, nout);
    778     for (u32 i = 0; i < nout; ++i) {
    779       o[i].constraint =
    780           kit_sym_intern(p->c, kit_slice_cstr(outs[i].str ? outs[i].str : ""));
    781       o[i].name = outs[i].name;
    782       o[i].type = c_cg_tid(p, outs[i].type);
    783       o[i].reg = outs[i].reg;
    784       o[i].dir = KIT_CG_ASM_OUT;
    785     }
    786   }
    787   if (nin) {
    788     in = arena_zarray(p->pool->arena, KitCgAsmOperand, nin);
    789     for (u32 i = 0; i < nin; ++i) {
    790       in[i].constraint =
    791           kit_sym_intern(p->c, kit_slice_cstr(ins[i].str ? ins[i].str : ""));
    792       in[i].name = ins[i].name;
    793       in[i].type = c_cg_tid(p, ins[i].type);
    794       in[i].reg = ins[i].reg;
    795       in[i].dir = (ins[i].dir == ASM_INOUT) ? KIT_CG_ASM_INOUT : KIT_CG_ASM_IN;
    796     }
    797   }
    798   if (nclob) {
    799     cl = arena_array(p->pool->arena, KitSym, nclob);
    800     for (u32 i = 0; i < nclob; ++i) cl[i] = clobbers[i];
    801   }
    802   a.outputs = o;
    803   a.noutputs = nout;
    804   a.inputs = in;
    805   a.ninputs = nin;
    806   a.clobbers = cl;
    807   a.nclobbers = nclob;
    808   a.flags = flags;
    809   kit_cg_inline_asm(p->cg, a);
    810   for (u32 i = 0; i < nout; ++i) {
    811     u32 depth = nout - 1u - i;
    812     c_cg_retag_at(p, depth, outs[i].type, 0);
    813   }
    814 }