cg.h (76535B)
1 #ifndef KIT_PUBLIC_CG_H 2 #define KIT_PUBLIC_CG_H 3 4 #include <kit/core.h> 5 #include <kit/object.h> 6 #include <kit/asm_constraints.h> 7 8 /* ============================================================ 9 * Handles 10 * ============================================================ */ 11 12 typedef struct KitCg KitCg; 13 14 typedef uint32_t KitCgLabel; 15 typedef uint32_t KitCgLocal; 16 typedef uint32_t KitCgScope; 17 typedef uint32_t KitCgSym; 18 typedef uint32_t KitCgTypeId; 19 typedef uint32_t KitCgDebugType; 20 21 #define KIT_CG_LABEL_NONE 0u 22 #define KIT_CG_LOCAL_NONE 0u 23 #define KIT_CG_SCOPE_NONE 0u 24 #define KIT_CG_SYM_NONE 0u 25 /* Invalid or absent type sentinel. Void is represented by the real void 26 * builtin type id, never by KIT_CG_TYPE_NONE. */ 27 #define KIT_CG_TYPE_NONE 0u 28 /* Optional debug type sentinel. Declaration sites that pass NONE derive a 29 * default debug type from the operational KitCgTypeId. */ 30 #define KIT_CG_DEBUG_TYPE_NONE 0u 31 32 /* ============================================================ 33 * Lifecycle and Source Locations 34 * ============================================================ */ 35 36 KIT_API KitStatus kit_cg_new(KitCompiler*, KitCg** cg_out); 37 38 typedef struct KitCgUnitOptions { 39 KitSlice source_name; /* diagnostic/provenance label; may be empty */ 40 uint32_t source_id; /* 0 means "unspecified" */ 41 uint32_t flags; /* reserved; must be 0 */ 42 } KitCgUnitOptions; 43 44 typedef enum KitCgOutputKind { 45 KIT_CG_OUTPUT_RELOCATABLE = 0, 46 KIT_CG_OUTPUT_EXECUTABLE = 1, 47 KIT_CG_OUTPUT_SHARED = 2, 48 KIT_CG_OUTPUT_ARCHIVE_MEMBER = 3, 49 } KitCgOutputKind; 50 51 typedef enum KitCgInterpositionPolicy { 52 KIT_CG_INTERPOSITION_DEFAULT = 0, 53 KIT_CG_INTERPOSITION_NONE = 1, 54 KIT_CG_INTERPOSITION_DEFAULT_VISIBILITY = 2, 55 } KitCgInterpositionPolicy; 56 57 typedef struct KitCgFinishOptions { 58 uint8_t output_kind; /* KitCgOutputKind */ 59 uint8_t interposition_policy; /* KitCgInterpositionPolicy */ 60 uint8_t pad[2]; 61 const KitCgSym* preserved_symbols; 62 uint32_t npreserved_symbols; 63 } KitCgFinishOptions; 64 65 KIT_API KitStatus kit_cg_begin(KitCg*, KitObjBuilder* out, 66 const KitCodeOptions*); 67 KIT_API KitStatus kit_cg_begin_unit(KitCg*, const KitCgUnitOptions*); 68 KIT_API KitStatus kit_cg_end_unit(KitCg*); 69 KIT_API KitStatus kit_cg_finish(KitCg*, const KitCgFinishOptions*); 70 /* Release the session, abandoning any in-progress object/unit state. Used on 71 * both the success-detach and error-abort paths. */ 72 KIT_API KitStatus kit_cg_detach(KitCg*); 73 KIT_API void kit_cg_free(KitCg*); 74 75 /* Sticky source location. Function, scope, local, param, instruction, and 76 * data-definition debug records use the current location. */ 77 KIT_API void kit_cg_set_loc(KitCg*, KitSrcLoc); 78 79 /* ============================================================ 80 * ABI Descriptors 81 * ============================================================ */ 82 83 /* Source-selectable calling convention: the convention axis a frontend can vary 84 * *within one compilation*, not the target's ABI identity (that is fixed by the 85 * triple). KIT_CG_CC_TARGET_C selects the target's own C ABI — whichever of 86 * SysV / Win64 / AAPCS64 / wasm the triple implies — and is the only convention 87 * kit lowers today. A real variant that repartitions the call (e.g. an x86 88 * vectorcall/regparm, preserve_most) would be added here and gated by 89 * kit_cg_target_supports_call_conv. Definition-side conventions that change the 90 * prologue but not the call ABI (naked, interrupt) are function attributes — 91 * KIT_CG_FUNC_NAKED / KIT_CG_FUNC_INTERRUPT — not values here. */ 92 typedef enum KitCgCallConv { 93 KIT_CG_CC_TARGET_C, 94 } KitCgCallConv; 95 96 typedef enum KitCgAbiAttrFlag { 97 KIT_CG_ABI_NONE = 0, 98 KIT_CG_ABI_SIGNEXT = 1u << 0, 99 KIT_CG_ABI_ZEROEXT = 1u << 1, 100 KIT_CG_ABI_SRET = 1u << 2, 101 KIT_CG_ABI_BYVAL = 1u << 3, 102 KIT_CG_ABI_BYREF = 1u << 4, 103 KIT_CG_ABI_INREG = 1u << 5, 104 KIT_CG_ABI_NOALIAS = 1u << 6, 105 KIT_CG_ABI_READONLY = 1u << 7, 106 KIT_CG_ABI_WRITEONLY = 1u << 8, 107 KIT_CG_ABI_NONNULL = 1u << 9, 108 KIT_CG_ABI_NEST = 1u << 10, 109 } KitCgAbiAttrFlag; 110 111 typedef struct KitCgAbiAttrs { 112 uint32_t flags; /* KitCgAbiAttrFlag */ 113 uint32_t align; /* 0 = ABI default */ 114 uint64_t dereferenceable_size; 115 } KitCgAbiAttrs; 116 117 typedef struct KitCgFuncParam { 118 KitCgTypeId type; 119 KitCgAbiAttrs attrs; 120 } KitCgFuncParam; 121 122 /* A function result is described exactly like a parameter: a type plus ABI 123 * attrs. The legal attribute subsets differ (SRET on results; BYVAL/NEST on 124 * params), but the descriptor shape is identical, so KitCgFuncResult is an 125 * alias of KitCgFuncParam. result.type is always a valid type id; use 126 * kit_cg_type_builtin(c, KIT_CG_BUILTIN_VOID) for a function that returns no 127 * value. */ 128 typedef KitCgFuncParam KitCgFuncResult; 129 130 typedef struct KitCgFuncSig { 131 KitCgFuncResult result; /* void builtin means no value */ 132 const KitCgFuncParam* params; 133 uint32_t nparams; 134 KitCgCallConv call_conv; 135 bool abi_variadic; 136 } KitCgFuncSig; 137 138 /* Capability queries answer whether the selected target/API can lower the 139 * requested feature correctly, not whether it is fast. These are target 140 * facts, not knobs: frontends use them to choose a legal lowering or to emit 141 * an unsupported-feature diagnostic before asking CG to produce output. */ 142 KIT_API int kit_cg_target_supports_call_conv(KitCompiler*, KitCgCallConv); 143 144 /* ============================================================ 145 * Type System 146 * ============================================================ */ 147 148 typedef enum KitCgBuiltinType { 149 KIT_CG_BUILTIN_VOID, 150 KIT_CG_BUILTIN_BOOL, /* i1: compare result and branch condition */ 151 KIT_CG_BUILTIN_I8, 152 KIT_CG_BUILTIN_I16, 153 KIT_CG_BUILTIN_I32, 154 KIT_CG_BUILTIN_I64, 155 KIT_CG_BUILTIN_I128, 156 KIT_CG_BUILTIN_F32, 157 KIT_CG_BUILTIN_F64, 158 KIT_CG_BUILTIN_F128, 159 KIT_CG_BUILTIN_VARARG_STATE, 160 KIT_CG_BUILTIN_COUNT, 161 } KitCgBuiltinType; 162 163 typedef enum KitCgTypeKind { 164 KIT_CG_TYPE_VOID, 165 KIT_CG_TYPE_BOOL, 166 KIT_CG_TYPE_INT, 167 KIT_CG_TYPE_FLOAT, 168 KIT_CG_TYPE_PTR, 169 KIT_CG_TYPE_ARRAY, 170 KIT_CG_TYPE_FUNC, 171 KIT_CG_TYPE_RECORD, 172 KIT_CG_TYPE_ENUM, 173 KIT_CG_TYPE_VARARG_STATE, 174 } KitCgTypeKind; 175 176 /* Field descriptor for record completion (INPUT). Carries the field's source 177 * shape and layout *policy* — alignment knobs and bit-field width — never its 178 * position: CG computes byte/bit offsets from these and the target ABI. Query 179 * the results back with kit_cg_type_record_layout after completion. */ 180 typedef struct KitCgFieldDesc { 181 KitSym name; /* 0 for anonymous fields/tuple elements */ 182 KitCgTypeId type; 183 uint32_t align_override; /* 0 = natural, 1 = packed, >1 explicit align */ 184 uint32_t max_align; /* 0 = natural, otherwise cap field alignment */ 185 uint32_t flags; /* KitCgFieldFlag */ 186 uint16_t bit_width; /* bit-field width; 0 w/ BITFIELD = layout barrier */ 187 int bit_signed; /* signed extraction for bit-field loads */ 188 } KitCgFieldDesc; 189 190 typedef enum KitCgFieldFlag { 191 KIT_CG_FIELD_BITFIELD = 1u << 0, 192 } KitCgFieldFlag; 193 194 /* Computed layout of one record field (OUTPUT; borrowed via the record-layout 195 * view, never an input to completion). For a bit-field, `offset` is the byte 196 * offset of the storage unit and the bit_* members carry the geometry; for an 197 * ordinary field bit_width == 0 and the bit_* members are 0. */ 198 typedef struct KitCgFieldLayout { 199 KitSym name; 200 KitCgTypeId type; 201 uint64_t offset; /* byte offset of the field (or its storage unit) */ 202 uint32_t flags; /* KitCgFieldFlag */ 203 uint32_t bit_storage_size; /* storage-unit bytes for a bit-field, else 0 */ 204 uint16_t bit_offset; /* bit position within the storage unit */ 205 uint16_t bit_width; /* 0 for a non-bit-field */ 206 int bit_signed; /* signed extraction for bit-field loads */ 207 } KitCgFieldLayout; 208 209 /* Immutable, CG-owned record layout, borrowed via kit_cg_type_record_layout. 210 * The pointer and its fields array stay valid and unchanged for the compiler's 211 * lifetime once the record is complete, so frontends cache this pointer instead 212 * of copying offsets into a parallel layout table. */ 213 typedef struct KitCgRecordLayout { 214 uint64_t size; 215 uint32_t align; 216 uint32_t nfields; 217 const KitCgFieldLayout* fields; 218 } KitCgRecordLayout; 219 220 typedef struct KitCgEnumValue { 221 KitSym name; 222 uint64_t value; /* bit pattern interpreted using the enum's integer base */ 223 } KitCgEnumValue; 224 225 typedef struct KitCgRecordDesc { 226 KitSym tag; 227 const KitCgFieldDesc* fields; 228 uint32_t nfields; 229 int is_union; 230 uint32_t align_override; /* 0 = natural, >0 explicit record alignment */ 231 } KitCgRecordDesc; 232 233 typedef enum KitCgTypeFlag { 234 KIT_CG_TYPEF_COMPLETE = 1u << 0, 235 KIT_CG_TYPEF_SIZED = 1u << 1, 236 KIT_CG_TYPEF_BUILTIN = 1u << 2, 237 KIT_CG_TYPEF_NOMINAL = 1u << 3, 238 } KitCgTypeFlag; 239 240 typedef enum KitCgStorageKind { 241 KIT_CG_STORAGE_VOID, 242 KIT_CG_STORAGE_BOOL, 243 KIT_CG_STORAGE_INT, 244 KIT_CG_STORAGE_FLOAT, 245 KIT_CG_STORAGE_PTR, 246 KIT_CG_STORAGE_AGGREGATE, 247 } KitCgStorageKind; 248 249 typedef struct KitCgTypeLayout { 250 uint64_t size; 251 uint32_t align; 252 uint16_t scalar_width; /* bit width for scalar int/float/bool, else 0 */ 253 uint8_t storage_kind; /* KitCgStorageKind */ 254 uint8_t valid; /* 0 for invalid, incomplete, or unsized types */ 255 } KitCgTypeLayout; 256 257 typedef struct KitCgTypeInfo { 258 KitCgTypeId id; 259 KitCgTypeId storage_id; /* storage identity; always equal to id */ 260 KitCgTypeKind kind; /* exact kind */ 261 uint32_t flags; /* KitCgTypeFlag */ 262 KitCgTypeLayout layout; /* ABI/storage layout; valid only when sized */ 263 } KitCgTypeInfo; 264 265 /* Type ids are stable only within one compiler. Pointer, array, and function 266 * constructors return a stable id for the same exact shape within one compiler; 267 * aliases, records, and enums allocate fresh user-facing identities. Void is a 268 * builtin type id; KIT_CG_TYPE_NONE is invalid/absent only. 269 * 270 * Integer types are width-only storage types. Signedness is carried by 271 * operations, comparisons, conversions, and ABI extension attributes. */ 272 KIT_API KitCgTypeId kit_cg_type_builtin(KitCompiler*, KitCgBuiltinType which); 273 274 /* Interned structural types. Address space 0 is the normal target data 275 * address space. Function signatures must use the void builtin type id as the 276 * result type for a no-value return. */ 277 KIT_API KitCgTypeId kit_cg_type_func(KitCompiler*, KitCgFuncSig sig); 278 KIT_API KitCgTypeId kit_cg_type_ptr(KitCompiler*, KitCgTypeId pointee, 279 uint32_t address_space); 280 KIT_API KitCgTypeId kit_cg_type_array(KitCompiler*, KitCgTypeId elem, 281 uint64_t count); 282 283 /* Enums use a width-only integer base. */ 284 KIT_API KitCgTypeId kit_cg_type_enum(KitCompiler*, KitSym tag, KitCgTypeId base, 285 const KitCgEnumValue* values, 286 uint32_t nvalues); 287 288 /* Records are nominal and may be declared before they are complete. Pointers 289 * to incomplete records are valid; sizing, arrays, fields, by-value 290 * params/results, locals, and memory accesses require complete/sized types. 291 * Completion is one-shot and computes ABI/source layout for the record. */ 292 KIT_API KitCgTypeId kit_cg_type_record_decl(KitCompiler*, KitSym tag, 293 int is_union); 294 KIT_API KitStatus kit_cg_type_record_complete(KitCompiler*, KitCgTypeId record, 295 const KitCgRecordDesc*); 296 /* Convenience constructor: declare a fresh nominal record, complete it, and 297 * return its id, or KIT_CG_TYPE_NONE on failure. */ 298 static inline KitCgTypeId kit_cg_type_record(KitCompiler* c, 299 const KitCgRecordDesc* desc) { 300 KitCgTypeId record; 301 if (!desc) return KIT_CG_TYPE_NONE; 302 record = kit_cg_type_record_decl(c, desc->tag, desc->is_union); 303 if (record == KIT_CG_TYPE_NONE) return KIT_CG_TYPE_NONE; 304 if (kit_cg_type_record_complete(c, record, desc) != KIT_OK) 305 return KIT_CG_TYPE_NONE; 306 return record; 307 } 308 309 /* Type queries. 310 * 311 * Layout and width queries report ABI/storage facts. Shape-specific queries are 312 * exact over the operational type lattice. */ 313 KIT_API KitStatus kit_cg_type_info(KitCompiler*, KitCgTypeId, KitCgTypeInfo*); 314 315 /* Stable per-id identity view. Returns a pointer to an interned KitCgTypeInfo 316 * whose IDENTITY fields are authoritative for the lifetime of the compiler: 317 * id, storage_id (always id), kind, and the BUILTIN / NOMINAL flag bits. The 318 * layout substruct and the COMPLETE / SIZED flag bits are NOT maintained on 319 * this view — completeness and sizing can change as records complete, and 320 * layout is computed lazily — so call kit_cg_type_info for an authoritative 321 * full snapshot. Returns NULL for an invalid id. The cheap identity queries 322 * below are inline projections over this one extern. */ 323 KIT_API const KitCgTypeInfo* kit_cg_type_view(KitCompiler*, KitCgTypeId); 324 325 KIT_API int kit_cg_type_same_storage(KitCompiler*, KitCgTypeId, KitCgTypeId); 326 KIT_API int kit_cg_type_is_complete(KitCompiler*, KitCgTypeId); 327 KIT_API int kit_cg_type_is_sized(KitCompiler*, KitCgTypeId); 328 329 static inline KitCgTypeKind kit_cg_type_kind(KitCompiler* c, KitCgTypeId id) { 330 const KitCgTypeInfo* t = kit_cg_type_view(c, id); 331 return t ? t->kind : KIT_CG_TYPE_VOID; 332 } 333 /* The storage id. With no transparent wrapper kinds, this is identity. */ 334 static inline KitCgTypeId kit_cg_type_resolve_alias(KitCompiler* c, 335 KitCgTypeId id) { 336 const KitCgTypeInfo* t = kit_cg_type_view(c, id); 337 return t ? t->id : KIT_CG_TYPE_NONE; 338 } 339 static inline int kit_cg_type_is_void(KitCompiler* c, KitCgTypeId id) { 340 const KitCgTypeInfo* t = kit_cg_type_view(c, id); 341 return t && t->kind == KIT_CG_TYPE_VOID; 342 } 343 /* A function result carries a value unless it is absent or the void builtin. */ 344 static inline int kit_cg_func_result_has_value(KitCompiler* c, 345 KitCgFuncResult result) { 346 return result.type != KIT_CG_TYPE_NONE && 347 !kit_cg_type_is_void(c, result.type); 348 } 349 KIT_API uint64_t kit_cg_type_size(KitCompiler*, KitCgTypeId); 350 KIT_API uint32_t kit_cg_type_align(KitCompiler*, KitCgTypeId); 351 KIT_API uint32_t kit_cg_type_int_width(KitCompiler*, KitCgTypeId); 352 KIT_API uint32_t kit_cg_type_float_width(KitCompiler*, KitCgTypeId); 353 354 KIT_API KitCgTypeId kit_cg_type_ptr_pointee(KitCompiler*, KitCgTypeId); 355 KIT_API uint32_t kit_cg_type_ptr_address_space(KitCompiler*, KitCgTypeId); 356 KIT_API KitCgTypeId kit_cg_type_array_elem(KitCompiler*, KitCgTypeId); 357 KIT_API uint64_t kit_cg_type_array_count(KitCompiler*, KitCgTypeId); 358 359 /* The function's result. A no-value result uses the void builtin type id. */ 360 KIT_API KitCgFuncResult kit_cg_type_func_result(KitCompiler*, KitCgTypeId); 361 KIT_API uint32_t kit_cg_type_func_nparams(KitCompiler*, KitCgTypeId); 362 KIT_API KitCgFuncParam kit_cg_type_func_param(KitCompiler*, KitCgTypeId, 363 uint32_t index); 364 KIT_API KitCgCallConv kit_cg_type_func_call_conv(KitCompiler*, KitCgTypeId); 365 KIT_API int kit_cg_type_func_is_variadic(KitCompiler*, KitCgTypeId); 366 367 KIT_API KitSym kit_cg_type_record_tag(KitCompiler*, KitCgTypeId); 368 KIT_API int kit_cg_type_record_is_union(KitCompiler*, KitCgTypeId); 369 KIT_API uint32_t kit_cg_type_record_nfields(KitCompiler*, KitCgTypeId); 370 /* Borrow the computed layout of a complete, sized record: total size/align and 371 * each field's byte offset and bit geometry. Returns NULL for an invalid id, a 372 * non-record, or an incomplete/unsized record. The returned pointer is owned by 373 * CG and stable for the compiler's lifetime; frontends cache it instead of 374 * copying offsets into a parallel layout table. Replaces per-field record 375 * queries — fetch once and index fields[] directly. */ 376 KIT_API const KitCgRecordLayout* kit_cg_type_record_layout(KitCompiler*, 377 KitCgTypeId); 378 379 KIT_API KitSym kit_cg_type_enum_tag(KitCompiler*, KitCgTypeId); 380 KIT_API KitCgTypeId kit_cg_type_enum_base(KitCompiler*, KitCgTypeId); 381 KIT_API uint32_t kit_cg_type_enum_nvalues(KitCompiler*, KitCgTypeId); 382 KIT_API KitStatus kit_cg_type_enum_value(KitCompiler*, KitCgTypeId, 383 uint32_t index, KitCgEnumValue* out); 384 385 /* ============================================================ 386 * Debug Type Information 387 * ============================================================ */ 388 389 /* Debug base-type encoding. Mirrors the producer's DEBUG_BE_* set so frontends 390 * can round-trip source signedness into debug info without storage carrying it. 391 */ 392 typedef enum KitCgDebugEncoding { 393 KIT_CG_DEBUG_ENC_NONE, 394 KIT_CG_DEBUG_ENC_BOOL, 395 KIT_CG_DEBUG_ENC_SIGNED, 396 KIT_CG_DEBUG_ENC_UNSIGNED, 397 KIT_CG_DEBUG_ENC_SIGNED_CHAR, 398 KIT_CG_DEBUG_ENC_UNSIGNED_CHAR, 399 KIT_CG_DEBUG_ENC_FLOAT, 400 } KitCgDebugEncoding; 401 402 /* Debug type builders. These return KIT_CG_DEBUG_TYPE_NONE when debug emission 403 * is not active on the KitCg session. The resulting handles are owned by that 404 * session and are valid only for declaration attributes passed to the same 405 * session. */ 406 KIT_API KitCgDebugType kit_cg_debug_base(KitCg*, KitSym name, 407 KitCgDebugEncoding, uint32_t bytes); 408 KIT_API KitCgDebugType kit_cg_debug_typedef(KitCg*, KitSym name, 409 KitCgDebugType base); 410 KIT_API KitCgDebugType kit_cg_debug_ptr(KitCg*, KitCgDebugType pointee); 411 KIT_API KitCgDebugType kit_cg_debug_array(KitCg*, KitCgDebugType elem, 412 uint64_t count); 413 KIT_API KitCgDebugType kit_cg_debug_func(KitCg*, KitCgDebugType ret, 414 const KitCgDebugType* params, 415 uint32_t nparams, int variadic); 416 KIT_API KitCgDebugType kit_cg_debug_enum(KitCg*, KitCgTypeId enum_type, 417 KitCgDebugType base); 418 KIT_API KitCgDebugType kit_cg_debug_of_type(KitCg*, KitCgTypeId); 419 420 /* ============================================================ 421 * Target Facts 422 * ============================================================ */ 423 424 typedef enum KitCgBackendFeatureFlag { 425 KIT_CG_BACKEND_UNALIGNED_MEMORY = 1ull << 0, 426 KIT_CG_BACKEND_STRICT_ALIGNMENT = 1ull << 1, 427 KIT_CG_BACKEND_RED_ZONE = 1ull << 2, 428 KIT_CG_BACKEND_SIMD = 1ull << 3, 429 KIT_CG_BACKEND_POINTER_AUTH = 1ull << 4, 430 KIT_CG_BACKEND_BRANCH_PROTECTION = 1ull << 5, 431 /* Instruction and data caches are coherent: freshly written code is 432 * executable without an explicit cache-flush / instruction-sync sequence. 433 * Set for x86 (snooping I-cache) and wasm (no hardware cache model). Not set 434 * for aarch64 / RISC-V, where JITs and self-modifying code must issue an 435 * explicit __clear_cache (IC/DC maintenance + ISB; fence.i) before running 436 * newly emitted instructions. */ 437 KIT_CG_BACKEND_ICACHE_COHERENT = 1ull << 6, 438 } KitCgBackendFeatureFlag; 439 440 KIT_API uint64_t kit_cg_target_backend_features(KitCompiler*); 441 442 /* Shape of the target's `va_list` object, as an ABI fact. Frontends that 443 * lower <stdarg.h> consult this to pick the right va_list representation 444 * without reaching into libkit-internal ABI tables: 445 * KIT_CG_VALIST_OPAQUE : implementation-private blob. 446 * KIT_CG_VALIST_POINTER : a single pointer that walks the arg area. 447 * KIT_CG_VALIST_AAPCS64 : the AArch64 __va_list register-save record. 448 * KIT_CG_VALIST_SYSV_X64: the System V x86-64 register-save record. */ 449 typedef enum KitCgVaListKind { 450 KIT_CG_VALIST_OPAQUE, 451 KIT_CG_VALIST_POINTER, 452 KIT_CG_VALIST_AAPCS64, 453 KIT_CG_VALIST_SYSV_X64, 454 } KitCgVaListKind; 455 KIT_API KitCgVaListKind kit_cg_target_va_list_kind(const KitCompiler*); 456 457 /* The C source-level symbol prefix the active object format prepends on 458 * disk: "_" for Mach-O, "" for ELF / COFF / Wasm. Never NULL. Drives the 459 * preprocessor's __USER_LABEL_PREFIX__. */ 460 KIT_API const char* kit_cg_target_c_label_prefix(const KitCompiler*); 461 462 /* Pointer width in bytes for an architecture, as a target fact independent of 463 * any constructed KitTarget. Single source of truth for the byte-aligned 464 * pointer size, so the object-format detector, the driver triple parser, and 465 * any internal CG/link code agree on one mapping. Header-only (no KIT_API TU) 466 * so it links anywhere the public headers reach — including arches that have no 467 * codegen backend (x86_32 / arm32 / arm64 are still ABI-classifiable here). 468 * wasm reports 4 (wasm32; wasm64's 8-byte width is carried on the target spec, 469 * not the arch kind). Returns 0 for an unknown KitArchKind. */ 470 static inline uint8_t kit_arch_ptr_size(KitArchKind arch) { 471 switch (arch) { 472 case KIT_ARCH_X86_32: 473 case KIT_ARCH_ARM_32: 474 case KIT_ARCH_RV32: 475 case KIT_ARCH_WASM: 476 return 4u; 477 case KIT_ARCH_X86_64: 478 case KIT_ARCH_ARM_64: 479 case KIT_ARCH_RV64: 480 return 8u; 481 } 482 return 0u; 483 } 484 485 /* ============================================================ 486 * Declarations and Symbols 487 * ============================================================ */ 488 489 typedef enum KitCgVisibility { 490 /* Externally visible, object-format-default visibility. On ELF this maps to 491 * STV_DEFAULT and remains preemptible when bind/output mode allow it. On 492 * formats without an equivalent visibility field, this is the normal visible 493 * symbol state. Local-bind symbols are still local. */ 494 KIT_CG_VIS_DEFAULT, 495 KIT_CG_VIS_HIDDEN, 496 KIT_CG_VIS_PROTECTED, 497 } KitCgVisibility; 498 499 typedef enum KitCgSymbolFlag { 500 KIT_CG_SYMFLAG_NONE = 0, 501 KIT_CG_SYM_USED = 1u << 0, 502 KIT_CG_SYM_DLLIMPORT = 1u << 1, 503 KIT_CG_SYM_DLLEXPORT = 1u << 2, 504 } KitCgSymbolFlag; 505 506 typedef struct KitCgSymbolAttrs { 507 KitSymBind bind; 508 KitCgVisibility visibility; 509 uint32_t flags; /* KitCgSymbolFlag */ 510 } KitCgSymbolAttrs; 511 512 typedef enum KitCgSymbolFeature { 513 KIT_CG_SYMFEAT_WEAK, 514 KIT_CG_SYMFEAT_PROTECTED_VISIBILITY, 515 KIT_CG_SYMFEAT_DLLIMPORT, 516 KIT_CG_SYMFEAT_DLLEXPORT, 517 KIT_CG_SYMFEAT_COMDAT, 518 KIT_CG_SYMFEAT_COMMON, 519 KIT_CG_SYMFEAT_MERGE_SECTIONS, 520 KIT_CG_SYMFEAT_CONSTRUCTOR_PRIORITY, 521 KIT_CG_SYMFEAT_TLS_LOCAL_EXEC, 522 KIT_CG_SYMFEAT_TLS_INITIAL_EXEC, 523 KIT_CG_SYMFEAT_TLS_LOCAL_DYNAMIC, 524 KIT_CG_SYMFEAT_TLS_GENERAL_DYNAMIC, 525 } KitCgSymbolFeature; 526 527 /* Whether the selected target supports a symbol feature; see 528 * kit_cg_target_supports_call_conv for the capability-query contract. */ 529 KIT_API int kit_cg_target_supports_symbol_feature(KitCompiler*, 530 KitCgSymbolFeature); 531 532 typedef enum KitCgFuncFlag { 533 KIT_CG_FUNC_NONE = 0, 534 KIT_CG_FUNC_NORETURN = 1u << 0, 535 KIT_CG_FUNC_IFUNC = 1u << 1, 536 KIT_CG_FUNC_COLD = 1u << 2, 537 KIT_CG_FUNC_HOT = 1u << 3, 538 KIT_CG_FUNC_NAKED = 1u << 4, 539 KIT_CG_FUNC_INTERRUPT = 1u << 5, 540 KIT_CG_FUNC_NO_RED_ZONE = 1u << 6, 541 } KitCgFuncFlag; 542 543 typedef enum KitCgInlinePolicy { 544 KIT_CG_INLINE_DEFAULT, 545 KIT_CG_INLINE_HINT, 546 KIT_CG_INLINE_ALWAYS, 547 KIT_CG_INLINE_NEVER, 548 } KitCgInlinePolicy; 549 550 typedef struct KitCgFuncAttrs { 551 uint32_t flags; /* KitCgFuncFlag */ 552 uint32_t stack_align; /* 0 = ABI default */ 553 KitSym section; /* 0 = target default */ 554 KitSym target_features; 555 KitCgInlinePolicy inline_policy; 556 KitCgDebugType debug_type; /* 0 = derive from declared function type */ 557 /* Wasm-target import descriptor. Honored only by the wasm backend, ignored 558 * by other targets. Promotes an undefined function symbol into a wasm 559 * `(import "<module>" "<name>" ...)` entry instead of a missing definition. 560 * Both 0 leaves the backend to fall back to module="env", name=<sym name> 561 * when an undefined function is referenced. */ 562 KitSym wasm_import_module; 563 KitSym wasm_import_name; 564 } KitCgFuncAttrs; 565 566 typedef enum KitCgTlsModel { 567 /* Let the target/backend choose from the symbol properties, visibility, 568 * output mode, and object format. Non-AUTO values are frontend requests 569 * from source attributes or driver options; unsupported requests should be 570 * diagnosed or conservatively widened. Object-format mechanisms such as 571 * Mach-O TLVP are target-selected implementation details. */ 572 KIT_CG_TLS_AUTO, 573 KIT_CG_TLS_LOCAL_EXEC, 574 KIT_CG_TLS_INITIAL_EXEC, 575 KIT_CG_TLS_LOCAL_DYNAMIC, 576 KIT_CG_TLS_GENERAL_DYNAMIC, 577 } KitCgTlsModel; 578 579 typedef enum KitCgObjectFlag { 580 KIT_CG_OBJ_NONE = 0, 581 KIT_CG_OBJ_READONLY = 1u << 0, 582 KIT_CG_OBJ_TLS = 1u << 1, 583 } KitCgObjectFlag; 584 585 typedef struct KitCgObjectAttrs { 586 KitCgTlsModel tls_model; 587 uint32_t flags; /* KitCgObjectFlag */ 588 KitSym section; /* 0 = target default */ 589 uint32_t align; /* 0 = natural */ 590 KitCgDebugType debug_type; /* 0 = derive from object type */ 591 } KitCgObjectAttrs; 592 593 typedef enum KitCgDeclKind { 594 KIT_CG_DECL_FUNC, 595 KIT_CG_DECL_OBJECT, 596 } KitCgDeclKind; 597 598 typedef struct KitCgDecl { 599 KitCgDeclKind kind; 600 KitSym linkage_name; /* exact linker-visible spelling */ 601 KitSym display_name; /* optional source/debug spelling; 0 = linkage_name */ 602 KitCgTypeId type; 603 KitCgSymbolAttrs sym; 604 union { 605 KitCgFuncAttrs func; 606 KitCgObjectAttrs object; 607 } as; 608 } KitCgDecl; 609 610 typedef struct KitCgAlias { 611 KitSym linkage_name; 612 KitSym display_name; /* optional source/debug spelling; 0 = linkage_name */ 613 KitCgSym target; 614 KitCgSymbolAttrs sym; 615 } KitCgAlias; 616 617 /* The declared type is the function type for function declarations and the 618 * object type for object declarations. linkage_name is already mangled and 619 * object-format decorated as desired by the frontend; CG does not apply a 620 * C-language name policy. 621 * 622 * Undefined weak references are ordinary declarations with sym.bind = 623 * KIT_SB_WEAK and no definition. Weak aliases are aliases whose attrs bind 624 * is KIT_SB_WEAK. */ 625 KIT_API KitCgSym kit_cg_decl(KitCg*, KitCgDecl decl); 626 627 /* Defines alias.linkage_name as another symbol for alias.target. */ 628 KIT_API KitCgSym kit_cg_alias(KitCg*, KitCgAlias alias); 629 630 /* Converts a source-level C ABI symbol spelling to the exact object/linker 631 * spelling for the selected target. This is object-format decoration only 632 * (for example Mach-O's leading underscore); language-specific mangling 633 * remains the frontend's responsibility. Use this when filling 634 * KitCgDecl.linkage_name for symbols that should interoperate with C entry 635 * names, libc symbols, and linker entry lookup. */ 636 KIT_API KitSym kit_cg_c_linkage_name(KitCompiler*, KitSym source_name); 637 638 /* ============================================================ 639 * Function Bodies and Locals 640 * ============================================================ */ 641 642 KIT_API void kit_cg_func_begin(KitCg*, KitCgSym sym); 643 KIT_API void kit_cg_func_begin_attrs(KitCg*, KitCgSym sym, 644 KitCgFuncAttrs attrs); 645 /* Enable stack-canary instrumentation for the current function. Call after 646 * declaring parameters and before the first protected stack object is used. 647 * Idempotent. A no-op when KitCodeOptions.stack_protector is NONE. CG snapshots 648 * the target ABI guard, checks it before every subsequent return, and disables 649 * sibling/tail exits for the function. */ 650 KIT_API void kit_cg_stack_protector_enable(KitCg*); 651 KIT_API void kit_cg_func_end(KitCg*); 652 653 /* Reclaim the storage of dead compiler temporaries. A frontend calls this at a 654 * full-expression / statement boundary where it has consumed all values it 655 * pushed (the value stack is empty); the single-pass -O0 backend then recycles 656 * the frame homes of its per-subexpression temps, bounding the frame to 657 * max-simultaneous-live temps. A no-op when the value stack is non-empty or the 658 * backend does not recycle (optimizer / C-source targets). Purely an 659 * optimization: omitting it only enlarges the frame. */ 660 KIT_API void kit_cg_reclaim_temps(KitCg*); 661 662 typedef enum KitCgLocalFlag { 663 KIT_CG_LOCALFLAG_NONE = 0, 664 KIT_CG_LOCAL_ARTIFICIAL = 1u << 1, 665 KIT_CG_LOCAL_OPTIMIZED_OUT = 1u << 2, 666 KIT_CG_LOCAL_COMPILER_TEMP = 1u << 3, 667 /* Force an addressable storage home even when the type is scalar. Frontends 668 * use this for source objects whose accesses must remain memory operations 669 * (for example C volatile automatic objects). */ 670 KIT_CG_LOCAL_MEMORY_REQUIRED = 1u << 4, 671 } KitCgLocalFlag; 672 673 typedef struct KitCgLocalAttrs { 674 KitSym name; 675 uint32_t align; /* 0 = natural */ 676 uint32_t flags; /* KitCgLocalFlag */ 677 KitCgDebugType debug_type; /* 0 = derive from local/param type */ 678 } KitCgLocalAttrs; 679 680 KIT_API KitCgLocal kit_cg_local(KitCg*, KitCgTypeId type, 681 KitCgLocalAttrs attrs); 682 /* Declares a source parameter as a local handle. Parameters must be declared 683 * in order before ordinary locals; therefore the first n parameter handles in 684 * a function are also the first n local ids. */ 685 KIT_API KitCgLocal kit_cg_param(KitCg*, uint32_t index, KitCgTypeId type, 686 KitCgLocalAttrs attrs); 687 688 /* Pops a byte size and pushes a pointer to stack storage with at least align 689 * alignment. The allocation lifetime is the current function activation. */ 690 KIT_API void kit_cg_alloca(KitCg*, uint32_t align, KitCgTypeId result_ptr_type); 691 692 /* ============================================================ 693 * Control flow 694 * ============================================================ */ 695 696 /* Structured control flow scopes. 697 * 698 * kit_cg_scope_begin / kit_cg_block_begin create statement scopes with no 699 * result values. The *_value variants create single-result expression scopes; 700 * result_type must be a valid non-void type id. 701 * 702 * Stack effects for a value scope: 703 * break(scope) -> pop result, exit scope 704 * break_true(scope) -> stack is [result, bool]; pop bool; if true, pop 705 * result and exit; otherwise pop result 706 * break_false(scope) -> same but exit on false 707 * scope_end(scope) -> TOS is the fallthrough result 708 * 709 * continue/continue_true/continue_false never carry a result; they jump to 710 * the loop header, not the scope exit. */ 711 KIT_API KitCgScope kit_cg_scope_begin(KitCg*); 712 KIT_API KitCgScope kit_cg_scope_begin_value(KitCg*, KitCgTypeId result_type); 713 714 /* Like kit_cg_scope_begin but opens a forward-only block: break exits past 715 * the scope; continue is not legal. This is the natural shape for `if`/ 716 * `if-else` (a wrapping block whose break is "skip the rest"), and lets 717 * backends with structured control flow (Wasm) emit `block`/`end` directly 718 * instead of recognizing arbitrary forward-only label-and-jump patterns. */ 719 KIT_API KitCgScope kit_cg_block_begin(KitCg*); 720 KIT_API KitCgScope kit_cg_block_begin_value(KitCg*, KitCgTypeId result_type); 721 722 /* Multi-value scopes: a block/loop that carries N params and/or N results 723 * (the value-stack analogue of a Wasm multi-value block). params/results are 724 * listed value-stack bottom -> top. 725 * 726 * block_begin_sig: params stay on the value stack for the body to consume; 727 * break / scope_end carry `nresults` values across the exit edge. 728 * scope_begin_sig (loop): the API snapshots the `nparams` params off the 729 * stack into loop-param locals, then reloads them so every back edge sees 730 * the same shape. A back edge re-supplies fresh params via 731 * kit_cg_scope_store_params (which pops `nparams` into those locals, no 732 * jump) followed by a jump to kit_cg_scope_continue_label. 733 * 734 * kit_cg_scope_begin / kit_cg_block_begin are the nparams==0, nresults==0 735 * special cases; the *_value variants are nparams==0, nresults==1. 736 * Results must be valid non-void type ids. break, break_true, break_false, the 737 * continue ops and scope_end all generalize to N values. */ 738 typedef struct KitCgScopeSig { 739 const KitCgTypeId* params; /* value-stack bottom -> top */ 740 uint32_t nparams; 741 const KitCgTypeId* results; /* value-stack bottom -> top */ 742 uint32_t nresults; 743 } KitCgScopeSig; 744 KIT_API KitCgScope kit_cg_scope_begin_sig(KitCg*, 745 const KitCgScopeSig*); /*loop*/ 746 KIT_API KitCgScope kit_cg_block_begin_sig(KitCg*, const KitCgScopeSig*); 747 /* Pop `nparams` values into the loop's param locals (bottom->top), without 748 * jumping. The caller then jumps kit_cg_scope_continue_label to take the back 749 * edge. Valid only on a loop scope (one opened with a continue label). */ 750 KIT_API void kit_cg_scope_store_params(KitCg*, KitCgScope); 751 752 KIT_API void kit_cg_scope_end(KitCg*, KitCgScope); 753 /* Close a scope whose fall-through is unreachable (its body ended in a 754 * branch/return so there are no fall-through results to consume). Unlike 755 * kit_cg_scope_end it does not pop results off the stack; the value stack must 756 * already be at the scope's base depth. The scope's results (set by whatever 757 * branch exited it) are pushed on exit, exactly as kit_cg_scope_end does. */ 758 KIT_API void kit_cg_scope_end_unreachable(KitCg*, KitCgScope); 759 /* Expose the labels CG minted for this scope. Frontends that emit 760 * unstructured `jump`/`branch` ops (rather than going through the 761 * scope_break/scope_continue helpers) can use these to land control at 762 * the scope's break/continue points — handy when the same backend needs 763 * to translate label-targeted jumps back into structured `break;`/ 764 * `continue;` later (the C source target does this). */ 765 KIT_API KitCgLabel kit_cg_scope_break_label(KitCg*, KitCgScope); 766 KIT_API KitCgLabel kit_cg_scope_continue_label(KitCg*, KitCgScope); 767 KIT_API void kit_cg_break(KitCg*, KitCgScope); 768 KIT_API void kit_cg_break_true(KitCg*, KitCgScope); 769 KIT_API void kit_cg_break_false(KitCg*, KitCgScope); 770 KIT_API void kit_cg_continue(KitCg*, KitCgScope); 771 KIT_API void kit_cg_continue_true(KitCg*, KitCgScope); 772 KIT_API void kit_cg_continue_false(KitCg*, KitCgScope); 773 774 /* Unstructured labels and jumps. */ 775 KIT_API KitCgLabel kit_cg_label_new(KitCg*); 776 KIT_API void kit_cg_label_place(KitCg*, KitCgLabel); 777 KIT_API void kit_cg_jump(KitCg*, KitCgLabel); 778 KIT_API void kit_cg_branch_true(KitCg*, KitCgLabel); 779 KIT_API void kit_cg_branch_false(KitCg*, KitCgLabel); 780 781 typedef struct KitCgSwitchCase { 782 uint64_t value; /* bit pattern interpreted using selector_type */ 783 KitCgLabel label; 784 } KitCgSwitchCase; 785 786 typedef enum KitCgSwitchHint { 787 KIT_CG_SWITCH_TARGET_DEFAULT, 788 KIT_CG_SWITCH_BRANCH_CHAIN, 789 KIT_CG_SWITCH_JUMP_TABLE, 790 } KitCgSwitchHint; 791 792 typedef struct KitCgSwitch { 793 KitCgTypeId selector_type; 794 KitCgLabel default_label; 795 const KitCgSwitchCase* cases; 796 uint32_t ncases; 797 KitCgSwitchHint hint; 798 } KitCgSwitch; 799 800 /* Pops an integer selector and branches to the case whose value matches 801 * it, or to default_label if none does. Mirrors the shape of C's 802 * `switch (val) { case V1: ...; default: ...; }`. Frontends that want 803 * jump-table dispatch (wasm br_table, computed-goto-style direct 804 * threading) pass dense case values 0..N-1 — backends can detect the 805 * shape and emit a real table; the C target lets the host compiler 806 * decide. The hint is advisory; targets may ignore it. */ 807 KIT_API void kit_cg_switch(KitCg*, KitCgSwitch sw); 808 809 /* Pushes the address of a label in the current function. Label addresses are 810 * first-class pointer values for direct-threaded interpreters: they may be 811 * stored, loaded, selected from tables, compared for equality, and consumed by 812 * kit_cg_computed_goto. They are only valid within the defining function's 813 * dynamic activation and must not be called or dereferenced as data. */ 814 KIT_API void kit_cg_push_label_addr(KitCg*, KitCgLabel, KitCgTypeId ptr_type); 815 816 /* Pops a label address and branches to it. valid_targets must name the 817 * non-empty closed set of labels the target may resolve to; targets use it 818 * for validation, CFG construction, and branch-protection lowering. */ 819 KIT_API void kit_cg_computed_goto(KitCg*, const KitCgLabel* valid_targets, 820 uint32_t ntargets); 821 822 /* Terminates the current block with unreachable code. This is a real 823 * terminator, not a side-effect intrinsic. */ 824 KIT_API void kit_cg_unreachable(KitCg*); 825 826 /* ============================================================ 827 * Memory Access 828 * ============================================================ */ 829 830 typedef enum KitCgMemAccessFlag { 831 KIT_CG_MEM_NONE = 0, 832 /* Access is an externally observable side effect and must not be merged, 833 * removed, or reordered across other volatile accesses. */ 834 KIT_CG_MEM_VOLATILE = 1u << 0, 835 /* Backend hint (loads only): emit a sign-extending narrow load when 836 * supported. Frontends normally set KIT_CG_MEM_SOURCE_SIGNED and let 837 * kit_cg_load derive this for byte/half integer loads; direct callers may 838 * still set it when they already know the following use is sign-extension. 839 * Ignored on stores and bit-fields. */ 840 KIT_CG_MEM_SEXT_LOAD = 1u << 1, 841 /* The source-language object being accessed is a signed integer. KitCgTypeId 842 * intentionally carries width/category, not C signedness, so this keeps the 843 * source semantic fact separate from the backend SEXT-load hint above. */ 844 KIT_CG_MEM_SOURCE_SIGNED = 1u << 2, 845 } KitCgMemAccessFlag; 846 847 typedef struct KitCgMemAccess { 848 KitCgTypeId type; /* value type loaded/stored, or element type */ 849 uint32_t align; /* 0 = natural for type */ 850 uint32_t address_space; /* normally inherited from pointer type */ 851 uint32_t flags; /* KitCgMemAccessFlag */ 852 } KitCgMemAccess; 853 854 /* ============================================================ 855 * Value stack: PLACES and VALUES 856 * ============================================================ 857 * 858 * Every stack entry is exactly one of two kinds, and each op below declares the 859 * kinds it consumes and produces. The op enforces this: handing an op the wrong 860 * kind is a usage error and panics. CG never *infers* the kind of a stack entry 861 * or silently inserts a dereference — addressing is always built explicitly. 862 * 863 * PLACE — an addressable, typed location of an object (a local's storage, a 864 * global, or a computed `[base + index*scale + offset]`). Produced 865 * by push_local / deref / field / elem; consumed by load / store / addr. 866 * 867 * VALUE — a scalar rvalue: an integer, float, pointer, or 128-bit scalar. 868 * Produced by push_int/float/null, push_symbol_addr, 869 * push_local_addr, addr, and load; consumed by the arithmetic / call / branch 870 * ops. 871 * 872 * Aggregates (records, arrays) are ALWAYS a PLACE — there is no aggregate 873 * VALUE. Copying an aggregate is an explicit store/memcpy between places. 874 * 875 * The four building blocks of addressing: 876 * - push_local l : — -> PLACE (the local's storage) 877 * - addr : PLACE -> VALUE(ptr) (address of the place) 878 * - deref : VALUE(ptr) -> PLACE (the place the ptr names) 879 * - field i : PLACE(record)-> PLACE(field) (sub-object, by layout) 880 * - elem : VALUE(ptr),index VALUE -> PLACE (element of an array/ptr) 881 * From these, `*p` is `deref`, `p->f` is `deref; field`, `s.f` is `field`, 882 * `a[i]` is `addr; <decay to *elem>; elem`, and `&x` is `addr`. */ 883 884 KIT_API void kit_cg_dup(KitCg*); 885 KIT_API void kit_cg_dup2(KitCg*); /* duplicates the top two slots */ 886 KIT_API void kit_cg_swap(KitCg*); 887 KIT_API void kit_cg_drop(KitCg*); 888 KIT_API void kit_cg_rot3(KitCg*); /* [..., a, b, c] -> [..., b, c, a] */ 889 890 typedef struct KitCgSlotInfo { 891 KitCgTypeId cg_type; 892 const void* lang_type; 893 uint16_t lang_flags; 894 } KitCgSlotInfo; 895 896 /* Inspect and update frontend-owned facts on value-stack slots. CG treats 897 * lang_type as opaque and lang_flags as frontend-defined bits; stack-producing 898 * operations clear them, while structural stack operations copy/move them with 899 * the slot. depth_from_top 0 names TOS. 900 * 901 * kit_cg_slot_info returns the whole {cg_type, lang_type, lang_flags} fact by 902 * value (a zeroed struct when the slot does not exist). The narrower accessors 903 * read one field directly with no copy and return zero/NULL when the slot does 904 * not exist; prefer them on hot paths that need a single fact. */ 905 KIT_API KitCgSlotInfo kit_cg_slot_info(KitCg*, uint32_t depth_from_top); 906 KIT_API KitCgTypeId kit_cg_slot_cg_type(KitCg*, uint32_t depth_from_top); 907 KIT_API const void* kit_cg_slot_lang_type(KitCg*, uint32_t depth_from_top); 908 KIT_API uint16_t kit_cg_slot_lang_flags(KitCg*, uint32_t depth_from_top); 909 KIT_API void kit_cg_retag_top(KitCg*, const void* lang_type, 910 uint16_t lang_flags); 911 KIT_API void kit_cg_retag_at(KitCg*, uint32_t depth_from_top, 912 const void* lang_type, uint16_t lang_flags); 913 KIT_API void kit_cg_set_top_flags(KitCg*, uint16_t set, uint16_t clear); 914 915 /* The current value-stack depth. Lets a frontend record a base depth and later 916 * drop back to it (e.g. discarding the operands a Wasm polymorphic/unreachable 917 * region left behind). */ 918 KIT_API uint32_t kit_cg_stack_depth(KitCg*); 919 920 typedef struct KitCgConstInt { 921 uint64_t lo; /* low bits, always truncated to width */ 922 uint64_t hi; /* high bits for width > 64 */ 923 uint16_t width; /* 1..128 for integer constants */ 924 uint8_t is_signed; /* interpretation hint for convenience queries */ 925 uint8_t known; /* 0 => not a compile-time integer constant */ 926 } KitCgConstInt; 927 928 /* Suppress target emission while preserving value-stack shape and stack-owned 929 * constant facts. Nested pushes are allowed; pop diagnoses underflow. */ 930 KIT_API void kit_cg_unevaluated_push(KitCg*); 931 KIT_API void kit_cg_unevaluated_pop(KitCg*); 932 933 /* Width-complete integer-constant query. Reads the stack-side constant payload, 934 * not the emitted operand shape, and does not pop the value. */ 935 KIT_API int kit_cg_top_const_int_ex(KitCg*, KitCgConstInt* out_value); 936 937 /* Convenience query for constants representable as one 64-bit lane. */ 938 KIT_API int kit_cg_top_const_i64(KitCg*, int64_t* out_value); 939 940 /* Push a scalar integer VALUE with an explicit width-complete constant payload. 941 * The value is truncated to the destination type width when that width is 942 * integer-like and known. */ 943 KIT_API void kit_cg_push_const_int(KitCg*, KitCgTypeId type, 944 const KitCgConstInt* value); 945 946 /* Compatibility wrapper for older callers that only need a signed 64-bit 947 * result. */ 948 KIT_API int kit_cg_top_const_int(KitCg*, int64_t* out_value); 949 950 /* Push a scalar VALUE. */ 951 KIT_API void kit_cg_push_int(KitCg*, uint64_t value, KitCgTypeId type); 952 KIT_API void kit_cg_push_float(KitCg*, double value, KitCgTypeId type); 953 KIT_API void kit_cg_push_null(KitCg*, KitCgTypeId ptr_type); 954 /* Push the PLACE that is the local's storage. Stack: [] -> [place]. */ 955 KIT_API void kit_cg_push_local(KitCg*, KitCgLocal local); 956 /* Push the local's address as a pointer VALUE (sugar for push_local; addr). 957 * Stack: [] -> [ptr]. */ 958 KIT_API void kit_cg_push_local_addr(KitCg*, KitCgLocal local); 959 960 /* Anonymous immutable data. Returns a local readonly object symbol; callers 961 * can materialize its address (a VALUE) with push_symbol_addr. pointee_type 962 * describes the logical value at that address, enabling const_data + 963 * push_symbol_addr + deref + load to materialize arbitrary-width constants. */ 964 KIT_API KitCgSym kit_cg_const_data(KitCg*, const uint8_t* data, size_t len, 965 uint32_t align, KitCgTypeId pointee_type); 966 967 /* Push &sym + addend as a pointer VALUE. For TLS objects this means the address 968 * of the current thread's instance; the target chooses LE/IE/GD/TLVP or 969 * equivalent lowering from the symbol attrs and output mode. Stack: [] -> 970 * [ptr]. 971 */ 972 KIT_API void kit_cg_push_symbol_addr(KitCg*, KitCgSym sym, int64_t addend); 973 974 /* PLACE -> VALUE(ptr): the address of the place (e.g. `&x`, or to pass/escape). 975 * Stack: [place] -> [ptr]. Errors if TOS is not a PLACE. */ 976 KIT_API void kit_cg_addr(KitCg*); 977 978 /* VALUE(ptr) -> PLACE: the explicit pointer->place transition. The produced 979 * place is `*(ptr + offset bytes)`; `offset` is a byte displacement folded into 980 * the addressing mode (0 for a plain `*p`). Stack: [ptr] -> [place]. Errors if 981 * TOS is not a pointer VALUE — a PLACE must be turned into a pointer with 982 * `addr` first; the op never guesses. */ 983 KIT_API void kit_cg_deref(KitCg*, int64_t offset); 984 985 /* PLACE(record) -> PLACE(field): project a record place to one of its fields by 986 * index; the byte offset and field type come from the record's layout (CG owns 987 * layout). Stack: [place] -> [place]. Errors if TOS is not a record PLACE — for 988 * `p->f` the frontend does `deref; field`, not `field` on a pointer. 989 * 990 * Bit-field PLACE subkind: when field_index names a bit-field, `field` projects 991 * to a *bit-field place* — a PLACE that addresses the field's storage unit and 992 * additionally carries the bit-field descriptor (bit offset/width, storage-unit 993 * size, signedness) from the record layout. A bit-field place is a place like 994 * any other: a plain `load` reads the field (extract + sign/zero-extend) and a 995 * plain `store` writes it (read-modify-write insert). There is no separate 996 * bit-field memop and no bit-field rider on KitCgMemAccess; the place is the 997 * one and only carrier of bit-field geometry. `addr` and aggregate access on a 998 * bit-field place are not legal (a bit-field has no addressable byte location); 999 * the frontend rejects `&` / `sizeof` on a bit-field before reaching CG. */ 1000 KIT_API void kit_cg_field(KitCg*, uint32_t field_index); 1001 1002 /* PLACE -> PLACE: project to a byte-offset subobject with a frontend-supplied 1003 * field type. This is the layout-known counterpart to kit_cg_field: CG does no 1004 * record lookup, but still folds byte_offset into the place operand when the 1005 * target addressing mode can carry it. Bit-field geometry, if any, is attached 1006 * separately with kit_cg_field_bits. */ 1007 KIT_API void kit_cg_field_at(KitCg*, int64_t byte_offset, 1008 KitCgTypeId field_type); 1009 1010 /* PLACE -> PLACE(bit-field): tag the TOS place as a bit-field place carrying 1011 * the given bit geometry. This is the manual-addressing counterpart to the 1012 * implicit bit-field projection `field` performs: a frontend that builds the 1013 * storage-unit place itself (deref/elem onto the storage unit) calls this to 1014 * attach the descriptor, after which a plain load/store extracts/inserts the 1015 * field. The place must address the field's storage unit. bit_storage_size is 1016 * the storage- unit size in bytes; bit_signed selects signed extraction on 1017 * load. Stack: [place] -> [place]. There is no separate bit-field memop — the 1018 * place is the one carrier of bit-field geometry. */ 1019 KIT_API void kit_cg_field_bits(KitCg*, uint16_t bit_offset, uint16_t bit_width, 1020 uint32_t bit_storage_size, int bit_signed); 1021 1022 /* (VALUE(ptr to T), index VALUE) -> PLACE(T): the element at `*(base + 1023 * index*sizeof(T) + offset)`. The index is scaled by sizeof(T) (the pointer's 1024 * pointee) and the constant `offset` byte displacement is folded in, so the 1025 * place is a single `[base + index*scale + offset]` addressing mode (base and 1026 * index dynamic; scale and offset constant). The base is a pointer VALUE; an 1027 * array is decayed to a pointer (`addr` + cast to *T) by the frontend first. 1028 * Stack: [base, index] -> [place]. Errors if the base is not a pointer VALUE. 1029 */ 1030 KIT_API void kit_cg_elem(KitCg*, int64_t offset); 1031 1032 /* Like kit_cg_elem, but the index is scaled by an EXPLICIT `elem_size` instead 1033 * of the base pointer's pointee size, and the resulting place's access type is 1034 * the base pointee. Lets a frontend build `[base + index*elem_size + offset]` 1035 * where the index stride (the containing array's element size) differs from the 1036 * accessed sub-object's size — e.g. `arr[i].f` strides by sizeof(elem) while 1037 * accessing the field `f`. The caller bitcasts the base to the access type 1038 * first. Stack: [base, index] -> [place]. */ 1039 KIT_API void kit_cg_elem_scaled(KitCg*, uint32_t elem_size, int64_t offset); 1040 1041 /* Load a VALUE from a PLACE / store a VALUE into a PLACE. The PLACE carries all 1042 * addressing (built via push_local / deref / field / elem); the memop takes no 1043 * effective-address rider. When the PLACE is a bit-field place (produced by 1044 * `field` on a bit-field), the load/store extract/insert the field per the 1045 * descriptor the place carries — `access` then describes only the access type, 1046 * alignment, and volatility, never bit geometry. Both error if the addressed 1047 * operand is not a PLACE — a pointer VALUE must be `deref`'d first. 1048 * 1049 * Stack effects: 1050 * load: [place] -> [value] 1051 * store: [place, value] -> [] 1052 * store_keep: [place, value] -> [value] */ 1053 KIT_API void kit_cg_load(KitCg*, KitCgMemAccess access); 1054 KIT_API void kit_cg_store(KitCg*, KitCgMemAccess access); 1055 KIT_API void kit_cg_store_keep(KitCg*, KitCgMemAccess access); 1056 1057 /* ============================================================ 1058 * ABI variadic argument access 1059 * ============================================================ */ 1060 1061 /* This models only target calling-convention varargs; higher-level rest 1062 * parameters should lower to explicit aggregate parameters before reaching CG. 1063 * 1064 * The frontend allocates a local of KIT_CG_BUILTIN_VARARG_STATE and pushes 1065 * that local's address before each operation. The implementation reads and 1066 * writes the state in memory according to the target ABI. */ 1067 KIT_API void kit_cg_vararg_start(KitCg*); /* pop &state */ 1068 KIT_API void kit_cg_vararg_next(KitCg*, 1069 KitCgTypeId type); /* pop &state; push value */ 1070 KIT_API void kit_cg_vararg_end(KitCg*); /* pop &state */ 1071 KIT_API void kit_cg_vararg_copy(KitCg*); /* pop &dst, &src */ 1072 1073 /* ============================================================ 1074 * Integer Operations 1075 * ============================================================ */ 1076 1077 typedef enum KitCgIntBinOp { 1078 KIT_CG_INT_ADD, 1079 KIT_CG_INT_SUB, 1080 KIT_CG_INT_MUL, 1081 KIT_CG_INT_SDIV, 1082 KIT_CG_INT_UDIV, 1083 KIT_CG_INT_SREM, 1084 KIT_CG_INT_UREM, 1085 KIT_CG_INT_AND, 1086 KIT_CG_INT_OR, 1087 KIT_CG_INT_XOR, 1088 KIT_CG_INT_SHL, 1089 KIT_CG_INT_LSHR, 1090 KIT_CG_INT_ASHR, 1091 } KitCgIntBinOp; 1092 1093 typedef enum KitCgIntOpFlag { 1094 KIT_CG_INTOP_NONE = 0, 1095 KIT_CG_INTOP_NSW = 1u << 0, 1096 KIT_CG_INTOP_NUW = 1u << 1, 1097 KIT_CG_INTOP_EXACT = 1u << 2, 1098 /* Overflow semantics are explicit because integer types are width-only. 1099 * Signed and unsigned trap/saturate flags are mutually exclusive. */ 1100 KIT_CG_INTOP_TRAP_SIGNED_OVERFLOW = 1u << 3, 1101 KIT_CG_INTOP_TRAP_UNSIGNED_OVERFLOW = 1u << 4, 1102 KIT_CG_INTOP_SATURATE_SIGNED = 1u << 5, 1103 KIT_CG_INTOP_SATURATE_UNSIGNED = 1u << 6, 1104 } KitCgIntOpFlag; 1105 1106 typedef enum KitCgIntCmpOp { 1107 KIT_CG_INT_EQ, 1108 KIT_CG_INT_NE, 1109 KIT_CG_INT_LT_S, 1110 KIT_CG_INT_LE_S, 1111 KIT_CG_INT_GT_S, 1112 KIT_CG_INT_GE_S, 1113 KIT_CG_INT_LT_U, 1114 KIT_CG_INT_LE_U, 1115 KIT_CG_INT_GT_U, 1116 KIT_CG_INT_GE_U, 1117 } KitCgIntCmpOp; 1118 1119 typedef enum KitCgIntUnOp { 1120 KIT_CG_INT_NEG, 1121 KIT_CG_INT_NOT, 1122 KIT_CG_INT_BNOT, 1123 } KitCgIntUnOp; 1124 1125 KIT_API void kit_cg_int_binop(KitCg*, KitCgIntBinOp, uint32_t flags); 1126 KIT_API void kit_cg_int_unop(KitCg*, KitCgIntUnOp, uint32_t flags); 1127 KIT_API void kit_cg_int_cmp(KitCg*, KitCgIntCmpOp); 1128 1129 /* ============================================================ 1130 * Floating-Point Operations 1131 * ============================================================ */ 1132 1133 typedef enum KitCgFpBinOp { 1134 KIT_CG_FP_ADD, 1135 KIT_CG_FP_SUB, 1136 KIT_CG_FP_MUL, 1137 KIT_CG_FP_DIV, 1138 /* No FP remainder: it is a libcall (fmod/fmodf/fmodl), which the frontend 1139 * emits directly. */ 1140 } KitCgFpBinOp; 1141 1142 typedef enum KitCgFpCmpOp { 1143 KIT_CG_FP_OEQ, 1144 KIT_CG_FP_ONE, 1145 KIT_CG_FP_OLT, 1146 KIT_CG_FP_OLE, 1147 KIT_CG_FP_OGT, 1148 KIT_CG_FP_OGE, 1149 KIT_CG_FP_UEQ, 1150 KIT_CG_FP_UNE, 1151 KIT_CG_FP_ULT, 1152 KIT_CG_FP_ULE, 1153 KIT_CG_FP_UGT, 1154 KIT_CG_FP_UGE, 1155 } KitCgFpCmpOp; 1156 1157 typedef enum KitCgFpUnOp { 1158 KIT_CG_FP_NEG, 1159 } KitCgFpUnOp; 1160 1161 typedef enum KitCgFpFlag { 1162 KIT_CG_FP_NONE = 0, 1163 KIT_CG_FP_REASSOC = 1u << 0, 1164 KIT_CG_FP_NO_NANS = 1u << 1, 1165 KIT_CG_FP_NO_INFS = 1u << 2, 1166 KIT_CG_FP_NO_SIGNED_ZEROS = 1u << 3, 1167 KIT_CG_FP_ALLOW_RECIP = 1u << 4, 1168 KIT_CG_FP_APPROX = 1u << 5, 1169 } KitCgFpFlag; 1170 1171 KIT_API void kit_cg_fp_binop(KitCg*, KitCgFpBinOp, uint32_t flags); 1172 KIT_API void kit_cg_fp_unop(KitCg*, KitCgFpUnOp, uint32_t flags); 1173 KIT_API void kit_cg_fp_cmp(KitCg*, KitCgFpCmpOp); 1174 1175 /* ============================================================ 1176 * Conversions 1177 * ============================================================ */ 1178 1179 typedef enum KitCgRounding { 1180 KIT_CG_ROUND_DEFAULT, 1181 KIT_CG_ROUND_NEAREST_EVEN, 1182 KIT_CG_ROUND_TOWARD_ZERO, 1183 KIT_CG_ROUND_DOWN, 1184 KIT_CG_ROUND_UP, 1185 } KitCgRounding; 1186 1187 KIT_API void kit_cg_sext(KitCg*, KitCgTypeId dst); 1188 KIT_API void kit_cg_zext(KitCg*, KitCgTypeId dst); 1189 KIT_API void kit_cg_trunc(KitCg*, KitCgTypeId dst); 1190 KIT_API void kit_cg_ptr_to_int(KitCg*, KitCgTypeId dst); 1191 KIT_API void kit_cg_int_to_ptr(KitCg*, KitCgTypeId dst); 1192 KIT_API void kit_cg_bitcast(KitCg*, KitCgTypeId dst); 1193 KIT_API void kit_cg_fpext(KitCg*, KitCgTypeId dst); 1194 KIT_API void kit_cg_fptrunc(KitCg*, KitCgTypeId dst); 1195 KIT_API void kit_cg_sint_to_float(KitCg*, KitCgTypeId dst, 1196 KitCgRounding rounding); 1197 KIT_API void kit_cg_uint_to_float(KitCg*, KitCgTypeId dst, 1198 KitCgRounding rounding); 1199 KIT_API void kit_cg_float_to_sint(KitCg*, KitCgTypeId dst, 1200 KitCgRounding rounding); 1201 KIT_API void kit_cg_float_to_uint(KitCg*, KitCgTypeId dst, 1202 KitCgRounding rounding); 1203 1204 /* ============================================================ 1205 * Calls and Returns 1206 * ============================================================ */ 1207 1208 /* Tail-call policy for a call site. 1209 * 1210 * A tail call is a TERMINATOR: it ends the current function. It pushes no 1211 * result onto the value stack, and the caller must not emit kit_cg_ret 1212 * after it — the call is the return. 1213 * 1214 * Two distinct conditions govern whether a tail call is legal: 1215 * 1216 * - Signature match is a PRECONDITION the frontend must guarantee: the 1217 * callee's return type must be ABI-compatible with the enclosing 1218 * function's declared return type, and the call must sit in return 1219 * position. A violation is a frontend bug; CG aborts (compiler_panic) 1220 * regardless of policy — it is never treated as a fallback case. 1221 * 1222 * - ABI realizability is DISCOVERED during emission and is target-specific: 1223 * can control transfer to the callee while reusing (and tearing down) the 1224 * current frame, with the callee's outgoing argument area and return 1225 * mechanism fitting the space the caller itself received? sret and 1226 * variadic are NOT inherent blockers — an sret return is forwarded via the 1227 * function's own incoming sret pointer, and a variadic callee is fine when 1228 * its argument area fits the caller's incoming area. The usual blocker is 1229 * an outgoing argument area that exceeds that space; some are arch-specific 1230 * (e.g. wasm packs varargs into a caller-frame buffer that a sibling call 1231 * would dangle). This is what ALLOWED vs MUST governs. 1232 */ 1233 typedef enum KitCgTailPolicy { 1234 /* Ordinary call. Result is pushed; not a terminator. */ 1235 KIT_CG_TAIL_DEFAULT, 1236 /* Tail-call (terminator) if ABI-realizable; otherwise silently emit an 1237 * ordinary call and synthesize the caller's return of the result. Never 1238 * fails for realizability. */ 1239 KIT_CG_TAIL_ALLOWED, 1240 /* Tail-call (terminator); if not ABI-realizable, CG fails with a 1241 * diagnostic naming the reason. Never silently degrades to an ordinary 1242 * call. */ 1243 KIT_CG_TAIL_MUST, 1244 } KitCgTailPolicy; 1245 1246 typedef enum KitCgCallFlag { 1247 KIT_CG_CALL_NONE = 0, 1248 KIT_CG_CALL_COLD = 1u << 0, 1249 } KitCgCallFlag; 1250 1251 typedef struct KitCgCallAttrs { 1252 KitCgTailPolicy tail; 1253 uint32_t flags; /* KitCgCallFlag */ 1254 KitCgInlinePolicy inline_policy; 1255 } KitCgCallAttrs; 1256 1257 /* kit_cg_call pops a computed function pointer plus nargs arguments. 1258 * kit_cg_call_symbol emits a direct call to the declared function symbol, 1259 * allowing the backend/linker to choose PLT/stub/IAT/direct/IFUNC handling. 1260 * 1261 * For tail policies (see KitCgTailPolicy): the call is a terminator that 1262 * pushes no result. A MUST tail call that is not ABI-realizable fails with a 1263 * diagnostic; an ALLOWED tail call that is not realizable silently degrades 1264 * to an ordinary call followed by a synthesized return of the result. A 1265 * tail call whose callee return type is incompatible with the enclosing 1266 * function's return type is a frontend bug and aborts under any policy. 1267 * 1268 * Results: a non-tail call to a value-returning callee pushes the callee's 1269 * single result onto the stack (TOS). A void callee pushes nothing. */ 1270 KIT_API void kit_cg_call(KitCg*, uint32_t nargs, KitCgTypeId fn_type, 1271 KitCgCallAttrs attrs); 1272 KIT_API void kit_cg_call_symbol(KitCg*, KitCgSym sym, uint32_t nargs, 1273 KitCgCallAttrs attrs); 1274 /* Returns from the current function. Pops the enclosing function's single 1275 * result value from TOS, or nothing for a void function. This is the single 1276 * return entry point. */ 1277 KIT_API void kit_cg_ret(KitCg*); 1278 1279 /* ============================================================ 1280 * Intrinsics 1281 * ============================================================ */ 1282 1283 typedef enum KitCgIntrinsic { 1284 KIT_CG_INTRIN_TRAP, 1285 KIT_CG_INTRIN_CLZ, /* zero input returns bit width */ 1286 KIT_CG_INTRIN_CTZ, /* zero input returns bit width */ 1287 KIT_CG_INTRIN_POPCOUNT, 1288 KIT_CG_INTRIN_BSWAP, 1289 KIT_CG_INTRIN_SETJMP, /* pop &buf; push i32 */ 1290 KIT_CG_INTRIN_LONGJMP, /* pop &buf, val; no return */ 1291 KIT_CG_INTRIN_SADD_OVERFLOW, /* pop a, b; push result, overflow */ 1292 KIT_CG_INTRIN_UADD_OVERFLOW, /* pop a, b; push result, overflow */ 1293 KIT_CG_INTRIN_SSUB_OVERFLOW, /* pop a, b; push result, overflow */ 1294 KIT_CG_INTRIN_USUB_OVERFLOW, /* pop a, b; push result, overflow */ 1295 KIT_CG_INTRIN_SMUL_OVERFLOW, /* pop a, b; push result, overflow */ 1296 KIT_CG_INTRIN_UMUL_OVERFLOW, /* pop a, b; push result, overflow */ 1297 KIT_CG_INTRIN_FMA, /* pop a, b, c; push a * b + c */ 1298 KIT_CG_INTRIN_PREFETCH, /* pop addr; no result */ 1299 KIT_CG_INTRIN_EXPECT, /* pop val, expected; push val */ 1300 KIT_CG_INTRIN_ASSUME_ALIGNED, /* pop ptr; push aligned ptr */ 1301 KIT_CG_INTRIN_SYSCALL, /* pop nr, args...; push long */ 1302 KIT_CG_INTRIN_IRQ_SAVE, /* push unsigned long */ 1303 KIT_CG_INTRIN_IRQ_RESTORE, /* pop prev */ 1304 KIT_CG_INTRIN_IRQ_DISABLE, 1305 KIT_CG_INTRIN_IRQ_ENABLE, 1306 KIT_CG_INTRIN_DMB, /* pop KitCgBarrierScope */ 1307 KIT_CG_INTRIN_DSB, /* pop KitCgBarrierScope */ 1308 KIT_CG_INTRIN_ISB, 1309 KIT_CG_INTRIN_DCACHE_CLEAN, /* pop ptr, size */ 1310 KIT_CG_INTRIN_DCACHE_INVALIDATE, 1311 KIT_CG_INTRIN_DCACHE_CLEAN_INVALIDATE, 1312 KIT_CG_INTRIN_ICACHE_INVALIDATE, 1313 KIT_CG_INTRIN_CPU_NOP, 1314 KIT_CG_INTRIN_CPU_YIELD, 1315 KIT_CG_INTRIN_WFI, 1316 KIT_CG_INTRIN_WFE, /* arm/aarch64 only */ 1317 KIT_CG_INTRIN_SEV, /* arm/aarch64 only */ 1318 KIT_CG_INTRIN_CORO_SWITCH, /* pop from, to, value; push value */ 1319 /* Frame-pointer-chain introspection (GCC __builtin_frame_address / 1320 * __builtin_return_address). The level is a compile-time constant passed as a 1321 * single immediate operand (nargs == 1); level 0 names the current frame. 1322 * Both push a void*. Lowered as an unrolled FP walk; targets with no frame 1323 * pointer (wasm) report unsupported. */ 1324 KIT_CG_INTRIN_FRAME_ADDRESS, /* pop level(u32 const); push void* */ 1325 KIT_CG_INTRIN_RETURN_ADDRESS, /* pop level(u32 const); push void* */ 1326 /* Read the target cycle/timestamp counter (GCC/Clang 1327 * __builtin_readcyclecounter). No operands; pushes an unsigned 64-bit value. 1328 * Lowered to the native counter read (x86 RDTSC, aarch64 MRS CNTVCT_EL0, 1329 * riscv64 RDCYCLE). Targets without a single-register 64-bit counter read 1330 * report unsupported. */ 1331 KIT_CG_INTRIN_READCYCLECOUNTER, /* push u64 */ 1332 /* High half of a full-width integer product. Both pop two equal-width 1333 * integer operands and push a result of that width. SMUL_HIGH interprets 1334 * both operands as two's-complement signed; UMUL_HIGH is unsigned. */ 1335 KIT_CG_INTRIN_SMUL_HIGH, 1336 KIT_CG_INTRIN_UMUL_HIGH, 1337 } KitCgIntrinsic; 1338 1339 typedef enum KitCgBarrierScope { 1340 KIT_CG_BARRIER_FULL, 1341 KIT_CG_BARRIER_INNER, 1342 KIT_CG_BARRIER_INNER_STORE, 1343 KIT_CG_BARRIER_OUTER, 1344 KIT_CG_BARRIER_OUTER_STORE, 1345 KIT_CG_BARRIER_NON_SHARE, 1346 } KitCgBarrierScope; 1347 1348 /* Pops nargs operands. result_type must be a valid type id; the void builtin 1349 * means no result is pushed. Overflow intrinsics push two values: result, 1350 * overflow_bool regardless of result_type. Syscall uses nargs = argc + 1: the 1351 * syscall number plus 0..6 long arguments. Runtime-extension intrinsics mirror 1352 * rt/include/kit/{syscall,baremetal,coro}.h and must diagnose targets where 1353 * the primitive has no legal lowering. */ 1354 KIT_API void kit_cg_intrinsic(KitCg*, KitCgIntrinsic, uint32_t nargs, 1355 KitCgTypeId result_type); 1356 1357 /* Capability query for kit_cg_intrinsic: true when the selected target has a 1358 * legal lowering for this intrinsic (see kit_cg_target_supports_call_conv for 1359 * the contract). Frontends test this before requesting a baremetal/CPU 1360 * intrinsic so they can emit their own unsupported-feature diagnostic instead 1361 * of tripping the CG fatal. */ 1362 KIT_API int kit_cg_target_supports_intrinsic(KitCompiler*, KitCgIntrinsic); 1363 1364 /* ============================================================ 1365 * Fixed-Sized Memory Operations 1366 * ============================================================ */ 1367 1368 /* Stack: 1369 * memcpy/memmove: [dst, src] -> [] 1370 * memset: [dst] -> [] */ 1371 KIT_API void kit_cg_memcpy(KitCg*, uint64_t size, KitCgMemAccess dst, 1372 KitCgMemAccess src); 1373 KIT_API void kit_cg_memmove(KitCg*, uint64_t size, KitCgMemAccess dst, 1374 KitCgMemAccess src); 1375 KIT_API void kit_cg_memset(KitCg*, uint8_t val, uint64_t size, 1376 KitCgMemAccess dst); 1377 1378 /* ============================================================ 1379 * Atomics 1380 * ============================================================ */ 1381 1382 typedef enum KitCgAtomicOp { 1383 KIT_CG_ATOMIC_XCHG, 1384 KIT_CG_ATOMIC_ADD, 1385 KIT_CG_ATOMIC_SUB, 1386 KIT_CG_ATOMIC_AND, 1387 KIT_CG_ATOMIC_OR, 1388 KIT_CG_ATOMIC_XOR, 1389 KIT_CG_ATOMIC_NAND, 1390 } KitCgAtomicOp; 1391 1392 typedef enum KitCgMemOrder { 1393 KIT_CG_MO_RELAXED, 1394 KIT_CG_MO_CONSUME, 1395 KIT_CG_MO_ACQUIRE, 1396 KIT_CG_MO_RELEASE, 1397 KIT_CG_MO_ACQ_REL, 1398 KIT_CG_MO_SEQ_CST, 1399 } KitCgMemOrder; 1400 1401 KIT_API int kit_cg_atomic_is_legal(KitCompiler*, KitCgMemAccess access, 1402 KitCgMemOrder order); 1403 KIT_API int kit_cg_atomic_is_lock_free(KitCompiler*, KitCgMemAccess access); 1404 KIT_API void kit_cg_atomic_load(KitCg*, KitCgMemAccess access, 1405 KitCgMemOrder order); 1406 KIT_API void kit_cg_atomic_store(KitCg*, KitCgMemAccess access, 1407 KitCgMemOrder order); 1408 KIT_API void kit_cg_atomic_rmw(KitCg*, KitCgMemAccess access, KitCgAtomicOp, 1409 KitCgMemOrder order); 1410 /* Stack: [ptr, expected, desired] -> [prior, ok_bool]. */ 1411 KIT_API void kit_cg_atomic_cmpxchg(KitCg*, KitCgMemAccess access, 1412 KitCgMemOrder success, KitCgMemOrder failure, 1413 int weak); 1414 KIT_API void kit_cg_atomic_fence(KitCg*, KitCgMemOrder); 1415 1416 /* ============================================================ 1417 * Inline Assembly 1418 * ============================================================ */ 1419 1420 typedef enum KitCgAsmDir { 1421 KIT_CG_ASM_IN, 1422 KIT_CG_ASM_OUT, 1423 KIT_CG_ASM_INOUT, 1424 } KitCgAsmDir; 1425 1426 typedef enum KitCgAsmFlag { 1427 KIT_CG_ASM_NONE = 0, 1428 KIT_CG_ASM_VOLATILE = 1u << 0, 1429 KIT_CG_ASM_PURE = 1u << 1, 1430 KIT_CG_ASM_NOMEM = 1u << 2, 1431 KIT_CG_ASM_READONLY = 1u << 3, 1432 KIT_CG_ASM_PRESERVES_FLAGS = 1u << 4, 1433 KIT_CG_ASM_NOSTACK = 1u << 5, 1434 KIT_CG_ASM_NORETURN = 1u << 6, 1435 } KitCgAsmFlag; 1436 1437 typedef enum KitCgAsmClobberAbiSet { 1438 KIT_CG_ASM_CLOBBER_ABI_NONE = 0, 1439 KIT_CG_ASM_CLOBBER_ABI_CALLER_SAVED = 1u << 0, 1440 /* Every callee-saved register of the target ABI. The compiler preserves them 1441 * across the asm block (prologue/epilogue save on the optimizer path, a 1442 * per-block spill on the single-pass path) just as it would for named 1443 * callee-saved clobbers — an arch-neutral way to say "this asm trashes the 1444 * callee-saved register file". */ 1445 KIT_CG_ASM_CLOBBER_ABI_CALLEE_SAVED = 1u << 1, 1446 } KitCgAsmClobberAbiSet; 1447 1448 typedef struct KitCgAsmOperand { 1449 KitSym constraint; /* interned target constraint string */ 1450 KitSym name; /* interned symbolic operand name; 0 if absent */ 1451 KitCgTypeId type; 1452 /* Explicit hard register this operand must occupy, named by its target 1453 * spelling ("r10", "x8", "a7", ...); 0 when unconstrained. Set by a frontend 1454 * for a GNU local register variable (`register T x __asm__("r10")`) used as 1455 * an operand. The name is opaque to the frontend and CG — only the target's 1456 * register file resolves it to a physical register. */ 1457 KitSym reg; 1458 uint8_t dir; /* KitCgAsmDir */ 1459 uint8_t pad[3]; 1460 } KitCgAsmOperand; 1461 1462 typedef struct KitCgInlineAsm { 1463 KitSym tmpl; 1464 const KitCgAsmOperand* outputs; 1465 uint32_t noutputs; 1466 const KitCgAsmOperand* inputs; 1467 uint32_t ninputs; 1468 const KitSym* clobbers; 1469 uint32_t nclobbers; 1470 uint32_t flags; /* KitCgAsmFlag */ 1471 uint32_t clobber_abi_sets; /* KitCgAsmClobberAbiSet */ 1472 } KitCgInlineAsm; 1473 1474 /* Inputs are popped in declaration order. Outputs are pushed in declaration 1475 * order as fresh values after the asm block. INOUT outputs consume one 1476 * initial value each after the explicit inputs, in output declaration order; 1477 * tied operands, earlyclobber, register classes, explicit registers, 1478 * immediates, memory operands, and target-specific alternatives are expressed 1479 * in the per-operand constraint string. Template, constraints, and clobbers 1480 * are pre-interned strings. clobber_abi_sets names target-defined ABI register 1481 * sets such as all caller-saved registers. */ 1482 KIT_API void kit_cg_inline_asm(KitCg*, KitCgInlineAsm asm_block); 1483 KIT_API void kit_cg_file_scope_asm(KitCg*, KitSlice asm_source); 1484 1485 /* ============================================================ 1486 * Data Definitions 1487 * ============================================================ */ 1488 1489 typedef enum KitCgDataDefFlag { 1490 KIT_CG_DATADEF_NONE = 0, 1491 KIT_CG_DATADEF_RETAIN = 1u << 0, 1492 KIT_CG_DATADEF_MERGE = 1u << 1, 1493 KIT_CG_DATADEF_STRINGS = 1u << 2, 1494 KIT_CG_DATADEF_READONLY = 1u << 3, 1495 KIT_CG_DATADEF_ZERO_FILL = 1u << 4, 1496 /* Static storage with function/block scope for source backends. Native 1497 * object backends may still emit ordinary private data. */ 1498 KIT_CG_DATADEF_FUNCTION_LOCAL = 1u << 5, 1499 } KitCgDataDefFlag; 1500 1501 typedef struct KitCgDataDefAttrs { 1502 KitSym section; /* 0 = target default for the symbol */ 1503 uint32_t align; /* 0 = natural */ 1504 uint32_t entsize; /* 0 = target default; used by merge/string data */ 1505 uint32_t flags; /* KitCgDataDefFlag */ 1506 } KitCgDataDefAttrs; 1507 1508 /* data_begin defines storage for an already-declared object symbol. 1509 * data_common defines tentative/common zero-initialized storage when the 1510 * target format supports it. 1511 * 1512 * Data definitions may be emitted while a function body is open. The current 1513 * function remains open across data_begin/data_end so frontends can define 1514 * block-scope statics and computed-goto dispatch tables that need function 1515 * label context. */ 1516 KIT_API void kit_cg_data_begin(KitCg*, KitCgSym sym, KitCgDataDefAttrs attrs); 1517 KIT_API void kit_cg_data_common(KitCg*, KitCgSym sym, uint64_t size, 1518 uint32_t align); 1519 KIT_API void kit_cg_data_end(KitCg*); 1520 1521 /* Appends to the currently open data definition. */ 1522 KIT_API void kit_cg_data_align(KitCg*, uint32_t align); 1523 KIT_API void kit_cg_data_pad(KitCg*, uint64_t size, uint8_t value); 1524 KIT_API void kit_cg_data_int(KitCg*, uint64_t value, KitCgTypeId type); 1525 KIT_API void kit_cg_data_float(KitCg*, double value, KitCgTypeId type); 1526 KIT_API void kit_cg_data_bytes(KitCg*, const uint8_t* data, size_t len); 1527 KIT_API void kit_cg_data_zero(KitCg*, uint64_t size); 1528 1529 /* Relocatable data expressions. These describe the value encoded in the data 1530 * stream; they do not request a lowering strategy such as GOT, PLT, TLVP, or 1531 * a TLS access model. width is the encoded field width in bytes. address_space 1532 * is the pointer address space of address constants; use 0 for the target data 1533 * address space. */ 1534 KIT_API void kit_cg_data_addr(KitCg*, KitCgSym target, int64_t addend, 1535 uint32_t width, uint32_t address_space); 1536 /* Encodes a function-local label address for direct-threaded dispatch tables. 1537 * The target label must have been created by kit_cg_label_new; it does not 1538 * need to be placed yet, and the containing function must still be open so the 1539 * label-address object can be tied to that function's label namespace. This 1540 * supports the normal direct-threaded lowering: declare a dispatch-table 1541 * symbol, begin the function, create labels, emit the table as data while the 1542 * function is open, then resume code emission. The resulting value is an opaque 1543 * label-address pointer: it may be loaded, stored, compared for equality, 1544 * selected from tables, and consumed by kit_cg_computed_goto in the label's 1545 * defining function. It must not be called, dereferenced as data, or used by 1546 * another function's computed goto. */ 1547 KIT_API void kit_cg_data_label_addr(KitCg*, KitCgLabel target, int64_t addend, 1548 uint32_t width, uint32_t address_space); 1549 KIT_API void kit_cg_data_pcrel(KitCg*, KitCgSym target, int64_t addend, 1550 uint32_t width); 1551 KIT_API void kit_cg_data_symdiff(KitCg*, KitCgSym lhs, KitCgSym rhs, 1552 int64_t addend, uint32_t width); 1553 1554 /* ============================================================ 1555 * Static Inline Convenience Operations 1556 * ============================================================ */ 1557 1558 static inline void kit_cg_push_bytes(KitCg* cg, const uint8_t* data, size_t len, 1559 KitCgTypeId pointee_type) { 1560 KitCgSym sym = kit_cg_const_data(cg, data, len, 0, pointee_type); 1561 kit_cg_push_symbol_addr(cg, sym, 0); 1562 } 1563 1564 static inline void kit_cg_call_default(KitCg* cg, uint32_t nargs, 1565 KitCgTypeId fn_type) { 1566 KitCgCallAttrs attrs; 1567 attrs.tail = KIT_CG_TAIL_DEFAULT; 1568 attrs.flags = 0; 1569 attrs.inline_policy = KIT_CG_INLINE_DEFAULT; 1570 kit_cg_call(cg, nargs, fn_type, attrs); 1571 } 1572 1573 static inline void kit_cg_call_symbol_default(KitCg* cg, KitCgSym sym, 1574 uint32_t nargs) { 1575 KitCgCallAttrs attrs; 1576 attrs.tail = KIT_CG_TAIL_DEFAULT; 1577 attrs.flags = 0; 1578 attrs.inline_policy = KIT_CG_INLINE_DEFAULT; 1579 kit_cg_call_symbol(cg, sym, nargs, attrs); 1580 } 1581 1582 static inline void kit_cg_tail_call(KitCg* cg, uint32_t nargs, 1583 KitCgTypeId fn_type) { 1584 KitCgCallAttrs attrs; 1585 attrs.tail = KIT_CG_TAIL_ALLOWED; 1586 attrs.flags = 0; 1587 attrs.inline_policy = KIT_CG_INLINE_DEFAULT; 1588 kit_cg_call(cg, nargs, fn_type, attrs); 1589 } 1590 1591 static inline void kit_cg_tail_call_symbol(KitCg* cg, KitCgSym sym, 1592 uint32_t nargs) { 1593 KitCgCallAttrs attrs; 1594 attrs.tail = KIT_CG_TAIL_ALLOWED; 1595 attrs.flags = 0; 1596 attrs.inline_policy = KIT_CG_INLINE_DEFAULT; 1597 kit_cg_call_symbol(cg, sym, nargs, attrs); 1598 } 1599 1600 static inline void kit_cg_musttail_call(KitCg* cg, uint32_t nargs, 1601 KitCgTypeId fn_type) { 1602 KitCgCallAttrs attrs; 1603 attrs.tail = KIT_CG_TAIL_MUST; 1604 attrs.flags = 0; 1605 attrs.inline_policy = KIT_CG_INLINE_DEFAULT; 1606 kit_cg_call(cg, nargs, fn_type, attrs); 1607 } 1608 1609 static inline void kit_cg_musttail_call_symbol(KitCg* cg, KitCgSym sym, 1610 uint32_t nargs) { 1611 KitCgCallAttrs attrs; 1612 attrs.tail = KIT_CG_TAIL_MUST; 1613 attrs.flags = 0; 1614 attrs.inline_policy = KIT_CG_INLINE_DEFAULT; 1615 kit_cg_call_symbol(cg, sym, nargs, attrs); 1616 } 1617 1618 /* Read the scalar value of a local. Stack: [] -> [value]. */ 1619 static inline void kit_cg_local_read(KitCg* cg, KitCgLocal local, 1620 KitCgMemAccess access) { 1621 kit_cg_push_local(cg, local); 1622 kit_cg_load(cg, access); 1623 } 1624 1625 /* Write the scalar value on TOS into a local. Stack: [value] -> []. */ 1626 static inline void kit_cg_local_write(KitCg* cg, KitCgLocal local, 1627 KitCgMemAccess access) { 1628 kit_cg_push_local(cg, local); /* [value, lv] */ 1629 kit_cg_swap(cg); /* [lv, value] */ 1630 kit_cg_store(cg, access); 1631 } 1632 1633 /* Increment/decrement an lvalue in place. Stack: [lv] -> [result]. 1634 * post=1 pushes the old value; post=0 pushes the new value. 1635 * op is KIT_CG_INT_ADD or KIT_CG_INT_SUB. ty is the promoted integer type 1636 * of the lvalue. */ 1637 static inline void kit_cg_inc_dec(KitCg* cg, KitCgIntBinOp op, int post, 1638 KitCgTypeId ty, KitCgMemAccess access) { 1639 kit_cg_dup(cg); /* [lv, lv] */ 1640 kit_cg_load(cg, access); /* [lv, old] */ 1641 if (post) { 1642 kit_cg_dup(cg); /* [lv, old, old] */ 1643 kit_cg_push_int(cg, 1, ty); /* [lv, old, old, 1] */ 1644 kit_cg_int_binop(cg, op, 0); /* [lv, old, new] */ 1645 kit_cg_rot3(cg); /* [old, new, lv] */ 1646 kit_cg_swap(cg); /* [old, lv, new] */ 1647 kit_cg_store(cg, access); /* [old] */ 1648 } else { 1649 kit_cg_push_int(cg, 1, ty); /* [lv, old, 1] */ 1650 kit_cg_int_binop(cg, op, 0); /* [lv, new] */ 1651 kit_cg_dup(cg); /* [lv, new, new] */ 1652 kit_cg_rot3(cg); /* [new, new, lv] */ 1653 kit_cg_swap(cg); /* [new, lv, new] */ 1654 kit_cg_store(cg, access); /* [new] */ 1655 } 1656 } 1657 1658 /* `if (cond) then [else else_body]` lowering via two nested forward blocks. 1659 * 1660 * outer = block_begin (break = "end of if") 1661 * inner = block_begin (break = "else entry point") 1662 * break_false(inner) ; pop cond, skip then-body if false 1663 * then-body 1664 * if_else: break(outer); end inner 1665 * [optional else-body] 1666 * if_end: end outer 1667 * 1668 * Frontends must call kit_cg_if_else exactly once after the then-body 1669 * (even if there is no else clause — the call closes the inner block so 1670 * if_end can close only the outer). Using structured scopes means backends 1671 * that already lower BLOCK + break natively (every native arch and the Wasm 1672 * target) handle `if`/`if-else` without a CFG-to-structured pass. */ 1673 typedef struct KitCgIf { 1674 KitCgScope outer; 1675 KitCgScope inner; 1676 } KitCgIf; 1677 1678 static inline KitCgIf kit_cg_if_begin(KitCg* cg) { 1679 KitCgIf it; 1680 it.outer = kit_cg_block_begin(cg); 1681 it.inner = kit_cg_block_begin(cg); 1682 kit_cg_break_false(cg, it.inner); 1683 return it; 1684 } 1685 1686 static inline void kit_cg_if_else(KitCg* cg, KitCgIf it) { 1687 kit_cg_break(cg, it.outer); 1688 kit_cg_scope_end(cg, it.inner); 1689 } 1690 1691 static inline void kit_cg_if_end(KitCg* cg, KitCgIf it) { 1692 kit_cg_scope_end(cg, it.outer); 1693 } 1694 1695 /* Extract bits [lo, lo+width) from TOS as an unsigned value. 1696 * Stack: [value] -> [field]. ty is the integer type of the value. 1697 * width < 64 masks with (1<<width)-1; width == 64 keeps all bits. */ 1698 static inline void kit_cg_bitget(KitCg* cg, KitCgTypeId ty, uint32_t lo, 1699 uint32_t width) { 1700 if (lo > 0) { 1701 kit_cg_push_int(cg, lo, ty); 1702 kit_cg_int_binop(cg, KIT_CG_INT_LSHR, 0); 1703 } 1704 if (width < 64) { 1705 kit_cg_push_int(cg, (1ULL << width) - 1, ty); 1706 kit_cg_int_binop(cg, KIT_CG_INT_AND, 0); 1707 } 1708 } 1709 1710 /* Insert the low width bits of src into dst at bit position lo. 1711 * Stack: [dst, src] -> [result]. ty is the integer type. 1712 * result = (dst & ~field_mask) | ((src << lo) & field_mask) 1713 * where field_mask = ((1<<width)-1) << lo. width < 64; for width == 64 use 1714 * bitget + shift + or directly. */ 1715 static inline void kit_cg_bitset(KitCg* cg, KitCgTypeId ty, uint32_t lo, 1716 uint32_t width) { 1717 uint64_t field_mask = ((1ULL << width) - 1) << lo; 1718 uint64_t clear_mask = ~field_mask; 1719 kit_cg_swap(cg); /* [src, dst] */ 1720 kit_cg_dup(cg); /* [src, dst, dst] */ 1721 kit_cg_push_int(cg, clear_mask, ty); 1722 kit_cg_int_binop(cg, KIT_CG_INT_AND, 0); /* [src, dst, dst_cleared] */ 1723 kit_cg_rot3(cg); /* [dst, dst_cleared, src] */ 1724 if (lo > 0) { 1725 kit_cg_push_int(cg, lo, ty); 1726 kit_cg_int_binop(cg, KIT_CG_INT_SHL, 0); /* [dst, dst_cleared, src<<lo] */ 1727 } 1728 kit_cg_push_int(cg, field_mask, ty); 1729 kit_cg_int_binop(cg, KIT_CG_INT_AND, 0); /* [dst, dst_cleared, bits] */ 1730 kit_cg_rot3(cg); /* [dst_cleared, bits, dst] */ 1731 kit_cg_drop(cg); /* [dst_cleared, bits] */ 1732 kit_cg_int_binop(cg, KIT_CG_INT_OR, 0); /* [result] */ 1733 } 1734 1735 #endif