kit

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

abi.h (5702B)


      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 nparts;
    112   u32 indirect_align; /* required alignment for ABI_ARG_INDIRECT/byval copy */
    113   const ABIArgPart* parts;
    114 } ABIArgInfo;
    115 
    116 typedef struct ABIFuncInfo {
    117   ABIArgInfo ret;
    118   const ABIArgInfo* params;
    119   u16 nparams;
    120   u8 variadic;
    121   u8 has_sret;
    122   /* True when the sret (indirect-result) pointer is passed in the first
    123    * integer argument register and therefore consumes that arg slot — SysV-x64
    124    * (rdi), Win64 (rcx), RISC-V (a0). ABIs that return it in a dedicated
    125    * register (AArch64 x8) leave this 0. Lets generic code reason about arg-slot
    126    * consumption from the ABI descriptor instead of by arch identity. */
    127   u8 sret_consumes_int_arg;
    128   /* True when the trailing `...` portion of a variadic call must be
    129    * routed to the stack exclusively, bypassing the GPR/FPR arg pools.
    130    * Apple ARM64 sets this; AAPCS64 / SysV-x64 leave it 0 (variadics
    131    * use the same register routing as fixed args). */
    132   u8 vararg_on_stack;
    133   /* True when floating-point arguments to a variadic function are passed
    134    * through the integer argument registers/slots rather than the FP pool.
    135    * Windows-ARM64 sets this so its plain-pointer `va_list` can walk a single
    136    * register save area; AAPCS64 / SysV-x64 / Apple ARM64 leave it 0. Lets the
    137    * aarch64 backend stop inspecting target.os==WINDOWS for varargs routing. */
    138   u8 vararg_fp_via_int;
    139   /* Minimum stack slot size/alignment for scalar stack-passed arguments.
    140    * Zero means the backend default. Apple ARM64 uses 4-byte compact slots for
    141    * stack arguments such as int32; AAPCS64 uses 8-byte slots. */
    142   u8 stack_arg_min_align;
    143   /* Minimum stack slot size/alignment for variadic arguments forced to the
    144    * stack. Zero means use stack_arg_min_align/backend default. Apple ARM64
    145    * keeps fixed stack args compact but uses 8-byte variadic slots. */
    146   u8 vararg_stack_arg_min_align;
    147   u32 vararg_gp_offset;
    148   u32 vararg_fp_offset;
    149   u32 vararg_overflow_offset;
    150 } ABIFuncInfo;
    151 
    152 void abi_init(TargetABI*, Compiler*);
    153 void abi_fini(TargetABI*);
    154 
    155 /* Heap-allocating wrappers around abi_init/abi_fini, used by compiler_init.
    156  * The returned pointer is valid until abi_free returns. */
    157 TargetABI* abi_new(Compiler*);
    158 void abi_free(TargetABI*);
    159 Compiler* abi_compiler(TargetABI*);
    160 
    161 ABITypeInfo abi_cg_type_info(TargetABI*, KitCgTypeId);
    162 u32 abi_cg_sizeof(TargetABI*, KitCgTypeId);
    163 u32 abi_cg_alignof(TargetABI*, KitCgTypeId);
    164 u32 abi_cg_scalar_split_lane_size(TargetABI*, KitCgTypeId);
    165 const ABIRecordLayout* abi_cg_record_layout(TargetABI*, KitCgTypeId);
    166 const ABIFuncInfo* abi_cg_func_info(TargetABI*, KitCgTypeId fn_type);
    167 ABITypeInfo abi_va_list_info(TargetABI*);
    168 ABIVaListInfo abi_va_list_layout(TargetABI*);
    169 /* Page granularity for Windows-style large-frame stack probing; 0 when the
    170  * target auto-grows its stack and needs no probe. See ABIVtable. */
    171 u32 abi_stack_probe_interval(TargetABI*);
    172 
    173 #endif