kit

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

type.h (6793B)


      1 #ifndef KIT_TYPE_H
      2 #define KIT_TYPE_H
      3 
      4 #include <kit/cg.h>
      5 
      6 #include "c_support.h"
      7 
      8 typedef enum TypeKind {
      9   TY_VOID,
     10   TY_BOOL,
     11   TY_CHAR,
     12   TY_SCHAR,
     13   TY_UCHAR,
     14   TY_SHORT,
     15   TY_USHORT,
     16   TY_INT,
     17   TY_UINT,
     18   TY_LONG,
     19   TY_ULONG,
     20   TY_LLONG,
     21   TY_ULLONG,
     22   TY_INT128,
     23   TY_UINT128,
     24   TY_FLOAT,
     25   TY_DOUBLE,
     26   TY_LDOUBLE,
     27   TY_PTR,
     28   TY_ARRAY,
     29   TY_FUNC,
     30   TY_STRUCT,
     31   TY_UNION,
     32   TY_ENUM,
     33 } TypeKind;
     34 
     35 /* C tag identity is scoped declaration identity, not the spelling. `Sym tag`
     36  * remains the diagnostic/debug name; TagId prevents two scoped `struct S`
     37  * declarations from collapsing under global Type interning. */
     38 typedef u32 TagId;
     39 #define TAG_NONE 0u
     40 
     41 typedef enum TagDeclKind {
     42   TAG_STRUCT,
     43   TAG_UNION,
     44   TAG_ENUM,
     45 } TagDeclKind;
     46 
     47 typedef struct TagDecl {
     48   TagId id;
     49   Sym spelling;
     50   SrcLoc loc;
     51   u8 kind; /* TagDeclKind */
     52   u8 complete;
     53   u16 pad;
     54 } TagDecl;
     55 
     56 typedef enum TypeQual {
     57   Q_CONST = 1u << 0,
     58   Q_VOLATILE = 1u << 1,
     59   Q_RESTRICT = 1u << 2,
     60   Q_ATOMIC = 1u << 3,
     61 } TypeQual;
     62 
     63 typedef struct Type Type;
     64 
     65 /* Defined in abi/c_abi.h (which includes this header), forward-declared here so
     66  * Type can cache a computed record layout pointer without a header cycle. */
     67 struct ABIRecordLayout;
     68 
     69 typedef enum FieldFlag {
     70   FIELD_NONE = 0,
     71   FIELD_BITFIELD = 1u << 0,
     72   FIELD_ZERO_WIDTH = 1u << 1,
     73   FIELD_ANON = 1u << 2,
     74   FIELD_FLEXIBLE_ARRAY = 1u << 3,
     75 } FieldFlag;
     76 
     77 typedef struct Field {
     78   Sym name;
     79   const Type* type;
     80   u16 bitfield_width; /* valid when FIELD_BITFIELD is set; may be 0 */
     81   u16 flags;          /* FieldFlag */
     82   /* Phase 2 attribute carriers — populated by the parser when the member
     83    * carries __attribute__((aligned(N))) / ((packed)). Zero means "no
     84    * override"; c_abi_record_layout interprets them. */
     85   u16 align_override;
     86   u16 max_align;
     87   u8 packed;
     88 } Field;
     89 
     90 /* One enumerator (name = value), collected by parse_enum and carried on the
     91  * enum Type so CG/debug lowering can emit DW_TAG_enumerator children. */
     92 typedef struct EnumConst {
     93   Sym name;
     94   i64 value;
     95 } EnumConst;
     96 
     97 struct Type {
     98   u16 kind;
     99   u16 qual;
    100   /* Memoized VALUE-mode CG lowering of this canonical node (0 = not yet
    101    * lowered). Sits in the alignment hole before the 8-aligned union, so the
    102    * node stays the same size. NOT part of type identity: the structural intern
    103    * set compares named fields and type_tagged_eq compares the rec/enm payload,
    104    * so this mutable cache never participates in interning. See type_cg_lower.
    105    */
    106   KitCgTypeId cg_id;
    107   /* Memoized record layout for TY_STRUCT/TY_UNION (NULL = not yet built). Like
    108    * the lowering caches this is mutable state, NOT part of type identity — the
    109    * interning comparisons never read it. Only c_abi_record_layout writes it,
    110    * and only for a complete record, whose layout is immutable + arena-lived for
    111    * the pool's lifetime, so sharing the pointer across qualified variants is
    112    * safe. */
    113   const struct ABIRecordLayout* abi_layout;
    114   union {
    115     struct {
    116       const Type* pointee;
    117     } ptr;
    118     struct {
    119       const Type* elem;
    120       u32 count;
    121       u8 incomplete;
    122     } arr;
    123     struct {
    124       const Type* ret;
    125       const Type** params;
    126       u16 nparams;
    127       u8 variadic;
    128     } fn;
    129     struct {
    130       TagId tag_id;
    131       Sym tag;
    132       const Field* fields;
    133       u16 nfields;
    134       u8 incomplete;
    135       /* Phase 2 attribute carriers — record-level
    136        * __attribute__((packed)) / ((aligned(N))). Both zero means
    137        * "natural layout". c_abi_record_layout honors them. */
    138       u8 packed;
    139       u16 max_align;
    140       u16 align_override;
    141     } rec; /* struct / union */
    142     struct {
    143       TagId tag_id;
    144       Sym tag;
    145       const Type* base;
    146       const EnumConst* consts; /* enumerators, NULL until the body is parsed */
    147       u16 nconsts;
    148     } enm;
    149   };
    150 };
    151 
    152 const Type* type_void(Pool*);
    153 const Type* type_prim(Pool*, TypeKind);
    154 const Type* type_ptr(Pool*, const Type*);
    155 const Type* type_array(Pool*, const Type* elem, u32 count, int incomplete);
    156 const Type* type_func(Pool*, const Type* ret, const Type** params, u16 n,
    157                       int variadic);
    158 const Type* type_qualified(Pool*, const Type*, u16 qual);
    159 
    160 /* Aggregate construction is mutable only through TypeRecordBuilder. The
    161  * committed Type is immutable and interned; field offsets, record
    162  * size/alignment, and bitfield storage are target ABI facts. */
    163 typedef struct TypeRecordBuilder TypeRecordBuilder;
    164 TagId type_tag_new(Pool*, TagDeclKind, Sym spelling, SrcLoc);
    165 TypeRecordBuilder* type_record_begin(Pool*, TypeKind kind, TagId,
    166                                      Sym tag); /* TY_STRUCT or TY_UNION */
    167 
    168 /* Phase 2 record options carried from __attribute__((packed))/aligned(N)).
    169  * Zero-initialized = natural layout. Fields kept as a struct so future
    170  * options (e.g. transparent_union) don't churn the call sites. */
    171 typedef struct TypeRecordOpts {
    172   u8 packed;
    173   u16 max_align;
    174   u16 align_override;
    175 } TypeRecordOpts;
    176 
    177 /* Variant of type_record_begin that records record-level attribute
    178  * options on the builder; type_record_end copies them to Type.rec. The
    179  * plain type_record_begin is equivalent to passing a zeroed
    180  * TypeRecordOpts. */
    181 TypeRecordBuilder* type_record_begin_ex(Pool*, TypeKind kind, TagId, Sym tag,
    182                                         TypeRecordOpts);
    183 void type_record_field(TypeRecordBuilder*, Field);
    184 const Type* type_record_end(Pool*, TypeRecordBuilder*);
    185 /* Forward-declared struct/union: returns a mutable, incomplete Type with the
    186  * given tag identity but no fields. Pointers to it are valid; sizeof/member
    187  * access are not until type_record_install is called. The same Type* identity
    188  * survives completion, so any TY_PTR(forward) pointer types remain valid. */
    189 Type* type_record_forward(Pool*, TypeKind kind, TagId, Sym tag);
    190 void type_record_install(Type* forward, const Field* fields, u16 nfields);
    191 const Type* type_enum(Pool*, TagId, Sym tag, const Type* base);
    192 
    193 const Type* type_unqual(Pool*, const Type*);
    194 const Type* type_promoted(Pool*, const Type*);
    195 int type_compatible(const Type*, const Type*);
    196 const Type* type_composite(Pool*, const Type*, const Type*);
    197 int type_is_arith(const Type*);
    198 int type_is_int(const Type*);
    199 int type_is_ptr(const Type*);
    200 int type_is_signed_integer(const Type*);
    201 
    202 /* Per-TypeKind scalar facts, backed by a single property table in type.c.
    203  * These take a bare TypeKind so callers that already have one (and the
    204  * Type* wrappers above) share the same source of truth. */
    205 int type_kind_is_int(TypeKind);
    206 int type_kind_is_fp(TypeKind);
    207 int type_kind_is_signed_integer(TypeKind);
    208 u32 type_kind_int_rank(TypeKind);
    209 TypeKind type_kind_unsigned_variant(TypeKind);
    210 
    211 KitCgTypeId type_cg_id_in_pool(KitCompiler*, Pool*, const Type*);
    212 KitCgDebugType type_cg_debug_in_pool(KitCg*, KitCompiler*, Pool*, const Type*);
    213 
    214 #endif