kit

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

abi.h (5968B)


      1 #ifndef KIT_ABI_H
      2 #define KIT_ABI_H
      3 
      4 #include <kit/cg.h>
      5 
      6 #include "core/core.h"
      7 
      8 /* TargetABI is the single authority for target-dependent storage layout and
      9  * calling convention decisions. Frontends lower source-language types to
     10  * KitCgTypeId before entering this generic ABI layer. */
     11 typedef struct TargetABI TargetABI;
     12 
     13 typedef enum ABIScalarKind {
     14   ABI_SC_VOID,
     15   ABI_SC_BOOL,
     16   ABI_SC_INT,
     17   ABI_SC_FLOAT,
     18   ABI_SC_PTR,
     19 } ABIScalarKind;
     20 
     21 typedef struct ABITypeInfo {
     22   u32 size;
     23   u32 align;
     24   u8 scalar_kind; /* ABIScalarKind; ABI_SC_VOID for aggregates/void */
     25   u8 signed_;
     26   u8 atomic;
     27   u8 pad;
     28 } ABITypeInfo;
     29 
     30 typedef enum ABIVaListKind {
     31   ABI_VA_LIST_OPAQUE,
     32   ABI_VA_LIST_POINTER,
     33   ABI_VA_LIST_AAPCS64,
     34   ABI_VA_LIST_SYSV_X64,
     35 } ABIVaListKind;
     36 
     37 typedef struct ABIVaListInfo {
     38   ABITypeInfo type;
     39   u8 kind; /* ABIVaListKind */
     40   u8 pad[3];
     41   u32 stack_offset;
     42   u32 gr_top_offset;
     43   u32 vr_top_offset;
     44   u32 gr_offs_offset;
     45   u32 vr_offs_offset;
     46   u32 gp_reg_count;
     47   u32 fp_reg_count;
     48   u32 gp_slot_size;
     49   u32 fp_slot_size;
     50 } ABIVaListInfo;
     51 
     52 typedef struct ABIFieldLayout {
     53   u32 offset;       /* byte offset from record base */
     54   u16 bit_offset;   /* bit offset within storage unit for bitfields */
     55   u16 bit_width;    /* 0 for non-bitfield */
     56   u32 storage_size; /* bytes in the bitfield storage unit; 0 otherwise */
     57 } ABIFieldLayout;
     58 
     59 typedef struct ABIRecordLayout {
     60   u32 size;
     61   u32 align;
     62   u32 nfields;
     63   const ABIFieldLayout* fields;
     64 } ABIRecordLayout;
     65 
     66 typedef enum ABIArgKind {
     67   ABI_ARG_IGNORE,
     68   ABI_ARG_DIRECT,   /* one or more inspectable parts */
     69   ABI_ARG_INDIRECT, /* caller passes address */
     70   ABI_ARG_EXPAND,   /* aggregate split into parts below */
     71 } ABIArgKind;
     72 
     73 typedef enum ABIArgClass {
     74   ABI_CLASS_NONE,
     75   ABI_CLASS_INT,
     76   ABI_CLASS_FP,
     77   ABI_CLASS_VEC,
     78   ABI_CLASS_MEM,
     79 } ABIArgClass;
     80 
     81 typedef enum ABIArgLoc {
     82   ABI_LOC_NONE,
     83   ABI_LOC_REG,
     84   ABI_LOC_STACK,
     85   ABI_LOC_EITHER,
     86 } ABIArgLoc;
     87 
     88 typedef enum ABIArgFlag {
     89   ABI_AF_NONE = 0,
     90   ABI_AF_SRET = 1u << 0,  /* hidden structure-return pointer */
     91   ABI_AF_BYVAL = 1u << 1, /* caller passes an address to a copy */
     92   ABI_AF_SIGN_EXT = 1u << 2,
     93   ABI_AF_ZERO_EXT = 1u << 3,
     94   ABI_AF_VARARG = 1u << 4, /* placement affected by variadic rules */
     95   ABI_AF_SPLIT = 1u << 5,  /* source value is split across parts */
     96 } ABIArgFlag;
     97 
     98 typedef struct ABIArgPart {
     99   u8 cls;          /* ABIArgClass */
    100   u8 loc;          /* ABIArgLoc preference */
    101   u16 flags;       /* ABIArgFlag */
    102   u32 src_offset;  /* byte offset within source object */
    103   u32 size;        /* bytes carried by this part */
    104   u32 align;       /* part alignment */
    105   u32 stack_align; /* required stack alignment if stack-passed */
    106 } ABIArgPart;
    107 
    108 typedef struct ABIArgInfo {
    109   u8 kind;  /* ABIArgKind */
    110   u8 flags; /* ABIArgFlag applying to the whole argument */
    111   u16 reserved;
    112   /* A fixed-size by-value aggregate is not bounded by the argument-register
    113    * bank: its remaining word parts continue on the stack. Keep this count
    114    * wide enough to describe the full object rather than truncating at 64K
    115    * carrier lanes. */
    116   u32 nparts;
    117   u32 indirect_align; /* required alignment for ABI_ARG_INDIRECT/byval copy */
    118   const ABIArgPart* parts;
    119 } ABIArgInfo;
    120 
    121 typedef struct ABIFuncInfo {
    122   ABIArgInfo ret;
    123   const ABIArgInfo* params;
    124   u16 nparams;
    125   u8 variadic;
    126   u8 has_sret;
    127   /* True when the sret (indirect-result) pointer is passed in the first
    128    * integer argument register and therefore consumes that arg slot — SysV-x64
    129    * (rdi), Win64 (rcx), RISC-V (a0). ABIs that return it in a dedicated
    130    * register (AArch64 x8) leave this 0. Lets generic code reason about arg-slot
    131    * consumption from the ABI descriptor instead of by arch identity. */
    132   u8 sret_consumes_int_arg;
    133   /* True when the trailing `...` portion of a variadic call must be
    134    * routed to the stack exclusively, bypassing the GPR/FPR arg pools.
    135    * Apple ARM64 sets this; AAPCS64 / SysV-x64 leave it 0 (variadics
    136    * use the same register routing as fixed args). */
    137   u8 vararg_on_stack;
    138   /* True when floating-point arguments to a variadic function are passed
    139    * through the integer argument registers/slots rather than the FP pool.
    140    * Windows-ARM64 sets this so its plain-pointer `va_list` can walk a single
    141    * register save area; AAPCS64 / SysV-x64 / Apple ARM64 leave it 0. Lets the
    142    * aarch64 backend stop inspecting target.os==WINDOWS for varargs routing. */
    143   u8 vararg_fp_via_int;
    144   /* Minimum stack slot size/alignment for scalar stack-passed arguments.
    145    * Zero means the backend default. Apple ARM64 uses 4-byte compact slots for
    146    * stack arguments such as int32; AAPCS64 uses 8-byte slots. */
    147   u8 stack_arg_min_align;
    148   /* Minimum stack slot size/alignment for variadic arguments forced to the
    149    * stack. Zero means use stack_arg_min_align/backend default. Apple ARM64
    150    * keeps fixed stack args compact but uses 8-byte variadic slots. */
    151   u8 vararg_stack_arg_min_align;
    152   u32 vararg_gp_offset;
    153   u32 vararg_fp_offset;
    154   u32 vararg_overflow_offset;
    155 } ABIFuncInfo;
    156 
    157 void abi_init(TargetABI*, Compiler*);
    158 void abi_fini(TargetABI*);
    159 
    160 /* Heap-allocating wrappers around abi_init/abi_fini, used by compiler_init.
    161  * The returned pointer is valid until abi_free returns. */
    162 TargetABI* abi_new(Compiler*);
    163 void abi_free(TargetABI*);
    164 Compiler* abi_compiler(TargetABI*);
    165 
    166 ABITypeInfo abi_cg_type_info(TargetABI*, KitCgTypeId);
    167 u32 abi_cg_sizeof(TargetABI*, KitCgTypeId);
    168 u32 abi_cg_alignof(TargetABI*, KitCgTypeId);
    169 u32 abi_cg_scalar_split_lane_size(TargetABI*, KitCgTypeId);
    170 const ABIRecordLayout* abi_cg_record_layout(TargetABI*, KitCgTypeId);
    171 const ABIFuncInfo* abi_cg_func_info(TargetABI*, KitCgTypeId fn_type);
    172 ABITypeInfo abi_va_list_info(TargetABI*);
    173 ABIVaListInfo abi_va_list_layout(TargetABI*);
    174 /* Page granularity for Windows-style large-frame stack probing; 0 when the
    175  * target auto-grows its stack and needs no probe. See ABIVtable. */
    176 u32 abi_stack_probe_interval(TargetABI*);
    177 
    178 #endif