kit

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

cgtarget.c (3791B)


      1 /* Public CgTarget constructor — dispatches through the registered arch impl.
      2  *
      3  * The lifecycle helpers (cgtarget_finalize, cgtarget_free) are arch-agnostic
      4  * shims over the vtable. */
      5 
      6 #include <kit/config.h>
      7 #include <string.h>
      8 
      9 #include "arch/arch.h"
     10 #include "cg/type.h"
     11 #include "debug/debug.h"
     12 
     13 CgTarget* cgtarget_new(Compiler* c, ObjBuilder* o) {
     14   const ArchImpl* arch = arch_for_compiler(c);
     15   if (arch && arch->cgtarget_new) {
     16     return arch->cgtarget_new(c, o, NULL);
     17   }
     18   {
     19     SrcLoc loc = {0, 0, 0};
     20     compiler_panic(c, loc, "cgtarget_new: unsupported target arch %d",
     21                    (int)c->target.arch);
     22   }
     23 }
     24 
     25 void cgtarget_set_finish_policy(CgTarget* t, const CgFinishPolicy* policy) {
     26   if (!t) return;
     27   memset(&t->finish_policy, 0, sizeof(t->finish_policy));
     28   if (policy) t->finish_policy = *policy;
     29 }
     30 
     31 void cgtarget_finalize(CgTarget* t) {
     32   if (t && t->finalize) t->finalize(t);
     33 }
     34 
     35 void cgtarget_free(CgTarget* t) {
     36   if (!t) return;
     37   if (t->destroy) t->destroy(t);
     38 }
     39 
     40 KitStatus cg_mc_debug_new(Compiler* c, ObjBuilder* o,
     41                           const KitCodeOptions* opts, MCEmitter** out_mc,
     42                           Debug** out_debug) {
     43   MCEmitter* mc;
     44   Debug* debug = NULL;
     45   *out_mc = NULL;
     46   *out_debug = NULL;
     47   mc = mc_new(c, o);
     48   if (!mc) return KIT_NOMEM;
     49 #if KIT_DWARF_ENABLED
     50   if (opts && opts->debug_info) {
     51     debug = debug_new(c, o);
     52     if (!debug) {
     53       mc_free(mc);
     54       return KIT_NOMEM;
     55     }
     56     mc->debug = debug;
     57   }
     58 #else
     59   (void)o;
     60   if (opts && opts->debug_info) {
     61     mc_free(mc);
     62     return KIT_UNSUPPORTED;
     63   }
     64 #endif
     65   *out_mc = mc;
     66   *out_debug = debug;
     67   return KIT_OK;
     68 }
     69 
     70 /* Default fold for backends without a native indexed addressing mode.
     71  *
     72  * If `addr` carries an index local (addr.v.ind.index != CG_LOCAL_NONE),
     73  * materialize `base + (index << log2_scale)` into `scratch` and return a plain
     74  * OPK_INDIRECT(scratch, ofs) with `index == CG_LOCAL_NONE`. Otherwise return
     75  * `addr` unchanged.
     76  *
     77  * The caller supplies `scratch` from its own scratch pool and is responsible
     78  * for freeing it after the memop completes. The returned operand keeps the
     79  * caller's `type` so the backend's load/store sees the same access type. */
     80 Operand arch_lower_indexed(CgTarget* t, Operand addr, Reg scratch) {
     81   Operand scratch_op;
     82   Operand shifted;
     83   KitCgTypeId ty;
     84   u8 log2;
     85 
     86   if (addr.kind != OPK_INDIRECT || addr.v.ind.index == REG_NONE) return addr;
     87 
     88   ty = builtin_id(KIT_CG_BUILTIN_I64);
     89   log2 = addr.v.ind.log2_scale;
     90   memset(&scratch_op, 0, sizeof scratch_op);
     91   scratch_op.kind = OPK_LOCAL;
     92   scratch_op.type = ty;
     93   scratch_op.v.local = scratch;
     94 
     95   memset(&shifted, 0, sizeof shifted);
     96   shifted.kind = OPK_LOCAL;
     97   shifted.type = ty;
     98   shifted.v.local = addr.v.ind.index;
     99 
    100   if (log2 == 0) {
    101     /* index * 1: just add the index directly to the base. */
    102     Operand base_op;
    103     memset(&base_op, 0, sizeof base_op);
    104     base_op.kind = OPK_LOCAL;
    105     base_op.type = ty;
    106     base_op.v.local = addr.v.ind.base;
    107     t->binop(t, BO_IADD, scratch_op, base_op, shifted);
    108   } else {
    109     /* scratch = index << log2 */
    110     Operand shamt;
    111     Operand base_op;
    112     memset(&shamt, 0, sizeof shamt);
    113     shamt.kind = OPK_IMM;
    114     shamt.type = ty;
    115     shamt.v.imm = (i64)log2;
    116     t->binop(t, BO_SHL, scratch_op, shifted, shamt);
    117     memset(&base_op, 0, sizeof base_op);
    118     base_op.kind = OPK_LOCAL;
    119     base_op.type = ty;
    120     base_op.v.local = addr.v.ind.base;
    121     /* scratch = base + scratch */
    122     t->binop(t, BO_IADD, scratch_op, base_op, scratch_op);
    123   }
    124 
    125   {
    126     Operand out;
    127     memset(&out, 0, sizeof out);
    128     out.kind = OPK_INDIRECT;
    129     out.type = ty;
    130     out.v.ind.base = scratch;
    131     out.v.ind.index = REG_NONE;
    132     out.v.ind.log2_scale = 0;
    133     out.v.ind.ofs = addr.v.ind.ofs;
    134     return out;
    135   }
    136 }