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