kit

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

native_direct_target.h (6340B)


      1 #ifndef KIT_CG_NATIVE_DIRECT_TARGET_H
      2 #define KIT_CG_NATIVE_DIRECT_TARGET_H
      3 
      4 #include "arch/native_target.h"
      5 #include "cg/cgtarget.h"
      6 
      7 /* NativeDirectTarget is the shared direct -O0 implementation of CgTarget for
      8  * native backends. It owns semantic local homes, direct-mode scratch policy,
      9  * local register caching, and conservative flushes. Arch code supplies a
     10  * NativeTarget plus this small adapter for ABI/frame/legality decisions. */
     11 
     12 typedef struct NativeDirectTarget NativeDirectTarget;
     13 
     14 typedef struct NativeDirectScope {
     15   u8 kind; /* ScopeKind */
     16   u8 owns_break;
     17   u8 pad[2];
     18   Label break_label;
     19   Label continue_label;
     20 } NativeDirectScope;
     21 
     22 typedef enum NativeDirectBarrier {
     23   NATIVE_DIRECT_BARRIER_CALL = 1u << 0,
     24   NATIVE_DIRECT_BARRIER_MEMORY = 1u << 1,
     25   NATIVE_DIRECT_BARRIER_VOLATILE = 1u << 2,
     26   NATIVE_DIRECT_BARRIER_ATOMIC = 1u << 3,
     27   NATIVE_DIRECT_BARRIER_INLINE_ASM = 1u << 4,
     28 } NativeDirectBarrier;
     29 
     30 typedef struct NativeDirectLocal {
     31   KitCgTypeId type;
     32   u32 size;
     33   u32 align;
     34   u32 flags; /* CGLocalFlag */
     35 
     36   NativeFrameSlot home;
     37   Reg reg;
     38   u8 cls; /* NativeAllocClass */
     39   u8 dirty;
     40   u8 address_taken;
     41   u8 memory_required;
     42   u32 last_use; /* d->use_tick at the most recent cache touch (LRU victim key)
     43                  */
     44   /* Intrusive doubly-linked list of currently-cached locals, in insertion
     45    * (caching) order so nd_cache_link is O(1) tail insertion. Values are 0-based
     46    * indices into NativeDirectTarget.locals (or -1); only valid while this local
     47    * is cached (l->reg != REG_NONE). */
     48   i32 cache_next;
     49   i32 cache_prev;
     50 } NativeDirectLocal;
     51 
     52 typedef enum NativeDirectAddrLegality {
     53   NATIVE_DIRECT_ADDR_ILLEGAL,
     54   NATIVE_DIRECT_ADDR_LEGAL,
     55   NATIVE_DIRECT_ADDR_LEGAL_IF_UNSCALED,
     56 } NativeDirectAddrLegality;
     57 
     58 typedef struct NativeOps NativeOps;
     59 /* Semantic-only adapter the arch supplies on the NDT path. `ops` is mandatory:
     60  * aa64_backend_make and aa64_semantic_target_new always pass it. Pure
     61  * pass-throughs to NativeTarget (reg_info, func_begin/func_end, frame-slot
     62  * allocation, class_for_type, addr_legal) are not mirrored here -- NDT calls
     63  * d->native->X directly for those. */
     64 struct NativeOps {
     65   void (*bind_param)(NativeDirectTarget*, const CGParamDesc*, CGLocal,
     66                      NativeDirectLocal*);
     67 
     68   int (*operand_legal)(NativeDirectTarget*, const Operand*, NativeAllocClass);
     69   NativeDirectAddrLegality (*semantic_addr_legal)(NativeDirectTarget*,
     70                                                   Operand addr, MemAccess);
     71 
     72   void (*plan_call)(NativeDirectTarget*, const NativeCallDesc*,
     73                     NativeCallPlan*);
     74   const char* (*tail_call_unrealizable_reason)(NativeDirectTarget*,
     75                                                const CGCallDesc*);
     76   void (*emit_call)(NativeDirectTarget*, const NativeCallPlan*);
     77   /* `value` is the single returned local, or CG_LOCAL_NONE for void. */
     78   void (*emit_ret)(NativeDirectTarget*, CGLocal value);
     79 
     80   void (*va_start_)(NativeDirectTarget*, Operand ap_addr);
     81   void (*va_arg_)(NativeDirectTarget*, Operand dst, Operand ap_addr,
     82                   KitCgTypeId type);
     83   void (*va_end_)(NativeDirectTarget*, Operand ap_addr);
     84   void (*va_copy_)(NativeDirectTarget*, Operand dst_ap_addr,
     85                    Operand src_ap_addr);
     86 
     87   void (*asm_block)(NativeDirectTarget*, const char* tmpl,
     88                     const AsmConstraint* outs, u32 nout, Operand* out_ops,
     89                     const AsmConstraint* ins, u32 nin, const Operand* in_ops,
     90                     const Sym* clobbers, u32 nclob, u32 clobber_abi_sets);
     91 
     92   void (*barrier)(NativeDirectTarget*, u32 flags);
     93 };
     94 
     95 /* Fixed transient buffers for per-op location/label arrays (call args/results,
     96  * return values, intrinsic operands, indirect-branch targets). The common case
     97  * fits these and allocates nothing; overflow falls back to the TU arena. */
     98 #define ND_ARG_BUF 16u
     99 #define ND_RET_BUF 8u
    100 #define ND_LBL_BUF 16u
    101 
    102 typedef struct NativeDirectTargetConfig {
    103   NativeTarget* native;
    104   const NativeOps* ops;
    105   void* user;
    106   u32 flags;
    107 } NativeDirectTargetConfig;
    108 
    109 struct NativeDirectTarget {
    110   CgTarget base;
    111   u32 magic;
    112   NativeTarget* native;
    113   const NativeOps* ops;
    114   void* user;
    115 
    116   /* Register info and per-class info resolved once at construction (constant
    117    * for the program), so scratch acquire / cache alloc / evict do an O(1)
    118    * lookup instead of re-resolving reg_info and linearly scanning ri->classes.
    119    */
    120   const NativeRegInfo* reg_info;
    121   const NativeAllocClassInfo* class_info[3];
    122 
    123   const CGFuncDesc* func;
    124   SrcLoc loc;
    125 
    126   NativeDirectLocal* locals;
    127   u32 nlocals;
    128   u32 locals_cap;
    129 
    130   MCLabel* labels;
    131   u32 nlabels;
    132   u32 labels_cap;
    133 
    134   NativeDirectScope* scopes;
    135   u32 nscopes;
    136   u32 scopes_cap;
    137 
    138   u32 scratch_used[3];
    139   /* Per-function callee-saved registers borrowed by direct scratch/cache
    140    * allocation. Reported to the native backend before prologue patching. */
    141   u32 callee_saved_used[3];
    142   /* Local register cache (write-back, basic-block-scoped). reg_owner[cls][reg]
    143    * names the semantic local currently cached in that physical register, or
    144    * CG_LOCAL_NONE. scratch_used doubles as the per-class "pinned for the
    145    * current instruction" mask. Per-local cache state (reg/cls/dirty) lives on
    146    * NativeDirectLocal. See doc/CODEGEN.md "local register cache". */
    147   CGLocal reg_owner[3][32];
    148   u32 use_tick; /* monotonic counter stamped onto NativeDirectLocal.last_use */
    149   /* Head/tail of the intrusive cached-locals list (in caching order), -1 when
    150    * empty; ncached is its length. Lets nd_flush_all run in O(cached) instead of
    151    * scanning all nlocals on every control-flow / barrier op; cache_tail makes
    152    * nd_cache_link an O(1) tail insertion. */
    153   i32 cache_head;
    154   i32 cache_tail;
    155   u32 ncached;
    156   u32 max_outgoing;
    157 
    158   /* Transient per-op buffers; see ND_*_BUF. Inputs use argbuf, outputs retbuf;
    159    * never live across more than one op, so reuse between ops is safe. */
    160   NativeLoc argbuf[ND_ARG_BUF];
    161   NativeLoc retbuf[ND_RET_BUF];
    162   MCLabel lblbuf[ND_LBL_BUF];
    163 
    164   ObjSecId local_static_sec;
    165   ObjSymId local_static_sym;
    166   u32 local_static_base;
    167   u32 local_static_size;
    168   u8 local_static_active;
    169 };
    170 
    171 CgTarget* native_direct_target_new(Compiler*, ObjBuilder*,
    172                                    const NativeDirectTargetConfig*);
    173 NativeTarget* native_direct_target_native(CgTarget*);
    174 
    175 #endif