kit

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

c_abi.c (6563B)


      1 #include "abi/c_abi.h"
      2 
      3 #include <string.h>
      4 
      5 ABITypeInfo c_abi_type_info(KitCompiler* a, const Type* t) {
      6   KitCgTypeId id = type_cg_id(a, t);
      7   KitCgTypeKind kind = kit_cg_type_kind(a, id);
      8   ABITypeInfo r;
      9   memset(&r, 0, sizeof(r));
     10   r.size = (u32)kit_cg_type_size(a, id);
     11   r.align = kit_cg_type_align(a, id);
     12   switch (kind) {
     13     case KIT_CG_TYPE_VOID:
     14       r.scalar_kind = ABI_SC_VOID;
     15       break;
     16     case KIT_CG_TYPE_BOOL:
     17       r.scalar_kind = ABI_SC_BOOL;
     18       break;
     19     case KIT_CG_TYPE_INT:
     20     case KIT_CG_TYPE_ENUM:
     21       r.scalar_kind = ABI_SC_INT;
     22       break;
     23     case KIT_CG_TYPE_FLOAT:
     24       r.scalar_kind = ABI_SC_FLOAT;
     25       break;
     26     case KIT_CG_TYPE_PTR:
     27       r.scalar_kind = ABI_SC_PTR;
     28       break;
     29     default:
     30       r.scalar_kind = ABI_SC_VOID;
     31       break;
     32   }
     33   r.signed_ = type_is_signed_integer(t);
     34   return r;
     35 }
     36 
     37 u32 c_abi_sizeof(KitCompiler* a, const Type* t) {
     38   return c_abi_type_info(a, t).size;
     39 }
     40 
     41 u32 c_abi_alignof(KitCompiler* a, const Type* t) {
     42   return c_abi_type_info(a, t).align;
     43 }
     44 
     45 const ABIRecordLayout* c_abi_record_layout(KitCompiler* a, Pool* p,
     46                                            const Type* t) {
     47   KitCgTypeId id = type_cg_id_in_pool(a, p, t);
     48   ABIRecordLayout* L;
     49   ABIFieldLayout* fl = NULL;
     50   u32 nfields;
     51   if (kit_cg_type_kind(a, id) != KIT_CG_TYPE_RECORD) return NULL;
     52   nfields = kit_cg_type_record_nfields(a, id);
     53   L = arena_znew(p->arena, ABIRecordLayout);
     54   if (!L) return NULL;
     55   if (nfields) {
     56     fl = arena_zarray(p->arena, ABIFieldLayout, nfields);
     57     if (!fl) return NULL;
     58     for (u32 i = 0; i < nfields; ++i) {
     59       KitCgField f;
     60       uint64_t off = 0;
     61       memset(&f, 0, sizeof(f));
     62       if (kit_cg_type_record_field(a, id, i, &f, &off) != 0) return NULL;
     63       fl[i].offset = (u32)off;
     64       fl[i].storage_size = f.bit_storage_size
     65                                ? f.bit_storage_size
     66                                : (u32)kit_cg_type_size(a, f.type);
     67       if (t->rec.fields[i].flags & FIELD_BITFIELD) {
     68         fl[i].bit_width = t->rec.fields[i].bitfield_width;
     69         fl[i].bit_offset = f.bit_offset;
     70       }
     71     }
     72   }
     73   L->size = (u32)kit_cg_type_size(a, id);
     74   L->align = kit_cg_type_align(a, id);
     75   L->nfields = nfields;
     76   L->fields = fl;
     77   return L;
     78 }
     79 
     80 const ABIFuncInfo* c_abi_func_info(KitCompiler* a, Pool* p,
     81                                    const Type* fn_type) {
     82   KitCgTypeId id = type_cg_id_in_pool(a, p, fn_type);
     83   ABIFuncInfo* info;
     84   uint32_t nparams;
     85   if (kit_cg_type_kind(a, id) != KIT_CG_TYPE_FUNC) return NULL;
     86   nparams = kit_cg_type_func_nparams(a, id);
     87   info = arena_znew(p->arena, ABIFuncInfo);
     88   if (!info) return NULL;
     89   info->nparams = (u16)nparams;
     90   if (nparams) {
     91     info->params = arena_zarray(p->arena, ABIArgInfo, nparams);
     92     if (!info->params) return NULL;
     93   }
     94   return info;
     95 }
     96 
     97 static const Type* c_size_or_uintptr(KitCompiler* a, Pool* p) {
     98   KitTargetSpec target = kit_compiler_target_spec(a);
     99   if (kit_target_uses_lp64(target)) return type_prim(p, TY_ULONG);
    100   return target.ptr_size == 8 ? type_prim(p, TY_ULLONG) : type_prim(p, TY_UINT);
    101 }
    102 
    103 const Type* c_abi_size_type(KitCompiler* a, Pool* p) {
    104   return c_size_or_uintptr(a, p);
    105 }
    106 
    107 const Type* c_abi_ptrdiff_type(KitCompiler* a, Pool* p) {
    108   KitTargetSpec target = kit_compiler_target_spec(a);
    109   if (kit_target_uses_lp64(target)) return type_prim(p, TY_LONG);
    110   return target.ptr_size == 8 ? type_prim(p, TY_LLONG) : type_prim(p, TY_INT);
    111 }
    112 
    113 const Type* c_abi_intptr_type(KitCompiler* a, Pool* p) {
    114   return c_abi_ptrdiff_type(a, p);
    115 }
    116 
    117 const Type* c_abi_uintptr_type(KitCompiler* a, Pool* p) {
    118   return c_size_or_uintptr(a, p);
    119 }
    120 
    121 const Type* c_abi_va_list_type(KitCompiler* a, Pool* p) {
    122   /* Key the frontend `__builtin_va_list` spelling on the abstract va_list
    123    * shape the target ABI reports, not on a re-derived arch/os ladder. The
    124    * record field definitions are unchanged; only the dispatch is abstract:
    125    *   SYSV_X64 -> the System V __va_list_tag register-save record;
    126    *   AAPCS64  -> the AArch64 __va_list register-save record;
    127    *   POINTER / OPAQUE -> a single pointer that walks the arg area.
    128    * The old Apple-vs-AAPCS64 arm64 split disappears (Apple is POINTER), as
    129    * does the x86_64/rv64 split (both follow the abstract kind). */
    130   switch (kit_cg_target_va_list_kind(a)) {
    131     case KIT_CG_VALIST_SYSV_X64: {
    132       const Type* vp = type_ptr(p, type_void(p));
    133       const Type* uit = type_prim(p, TY_UINT);
    134       Sym name = kit_sym_intern(p->c, KIT_SLICE_LIT("__va_list_tag"));
    135       SrcLoc nl = {0, 0, 0};
    136       TagId tg = type_tag_new(p, TAG_STRUCT, name, nl);
    137       TypeRecordBuilder* b = type_record_begin(p, TY_STRUCT, tg, name);
    138       type_record_field(
    139           b, (Field){.name = kit_sym_intern(p->c, KIT_SLICE_LIT("gp_offset")),
    140                      .type = uit});
    141       type_record_field(
    142           b, (Field){.name = kit_sym_intern(p->c, KIT_SLICE_LIT("fp_offset")),
    143                      .type = uit});
    144       type_record_field(
    145           b, (Field){.name = kit_sym_intern(p->c,
    146                                             KIT_SLICE_LIT("overflow_arg_area")),
    147                      .type = vp});
    148       type_record_field(b, (Field){.name = kit_sym_intern(
    149                                        p->c, KIT_SLICE_LIT("reg_save_area")),
    150                                    .type = vp});
    151       return type_record_end(p, b);
    152     }
    153     case KIT_CG_VALIST_AAPCS64: {
    154       const Type* vp = type_ptr(p, type_void(p));
    155       const Type* it = type_prim(p, TY_INT);
    156       Sym name = kit_sym_intern(p->c, KIT_SLICE_LIT("__va_list"));
    157       SrcLoc nl = {0, 0, 0};
    158       TagId tg = type_tag_new(p, TAG_STRUCT, name, nl);
    159       TypeRecordBuilder* b = type_record_begin(p, TY_STRUCT, tg, name);
    160       type_record_field(
    161           b, (Field){.name = kit_sym_intern(p->c, KIT_SLICE_LIT("__stack")),
    162                      .type = vp});
    163       type_record_field(
    164           b, (Field){.name = kit_sym_intern(p->c, KIT_SLICE_LIT("__gr_top")),
    165                      .type = vp});
    166       type_record_field(
    167           b, (Field){.name = kit_sym_intern(p->c, KIT_SLICE_LIT("__vr_top")),
    168                      .type = vp});
    169       type_record_field(
    170           b, (Field){.name = kit_sym_intern(p->c, KIT_SLICE_LIT("__gr_offs")),
    171                      .type = it});
    172       type_record_field(
    173           b, (Field){.name = kit_sym_intern(p->c, KIT_SLICE_LIT("__vr_offs")),
    174                      .type = it});
    175       return type_record_end(p, b);
    176     }
    177     case KIT_CG_VALIST_POINTER:
    178     case KIT_CG_VALIST_OPAQUE:
    179       break;
    180   }
    181   return type_ptr(p, type_void(p));
    182 }