kit

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

native_frame.c (3834B)


      1 #include "cg/native_frame.h"
      2 
      3 #include <string.h>
      4 
      5 #include "core/arena.h"
      6 
      7 static u32 nf_align_up(u32 v, u32 align) {
      8   u32 mask = align ? align - 1u : 0u;
      9   return (v + mask) & ~mask;
     10 }
     11 
     12 static void nf_panic(NativeFrame* f, const char* msg) {
     13   compiler_panic(f->c, (SrcLoc){0, 0, 0}, "native frame: %s", msg);
     14 }
     15 
     16 void native_frame_init(NativeFrame* f, Compiler* c) {
     17   memset(f, 0, sizeof *f);
     18   f->c = c;
     19 }
     20 
     21 void native_frame_reset(NativeFrame* f) {
     22   /* Keep the slots buffer (slots/slots_cap) for reuse across functions in the
     23    * translation unit; nslots = 0 logically clears it. */
     24   f->nslots = 0;
     25   f->cum_off = 0;
     26   f->max_outgoing = 0;
     27   f->ncallee_saves = 0;
     28   f->frame_final = 0;
     29   f->known_frame = 0;
     30   f->has_alloca = 0;
     31 }
     32 
     33 NativeFrameSlot native_frame_slot_alloc(NativeFrame* f,
     34                                         const NativeFrameSlotDesc* d) {
     35   NativeFrameSlotEntry* s;
     36   u32 size = d->size ? d->size : 8u;
     37   u32 align = d->align ? d->align : 1u;
     38   if (f->frame_final) nf_panic(f, "frame slot requested after prologue");
     39   if (f->nslots == f->slots_cap) {
     40     u32 cap = f->slots_cap ? f->slots_cap * 2u : 16u;
     41     NativeFrameSlotEntry* nb =
     42         arena_zarray(f->c->tu, NativeFrameSlotEntry, cap);
     43     if (f->slots) memcpy(nb, f->slots, sizeof(*nb) * f->nslots);
     44     f->slots = nb;
     45     f->slots_cap = cap;
     46   }
     47   f->cum_off = nf_align_up(f->cum_off + size, align);
     48   s = &f->slots[f->nslots++];
     49   s->off = f->cum_off;
     50   s->size = size;
     51   s->align = align;
     52   s->kind = d->kind;
     53   return (NativeFrameSlot)f->nslots;
     54 }
     55 
     56 NativeFrameSlotEntry* native_frame_slot_at(NativeFrame* f,
     57                                            NativeFrameSlot slot) {
     58   if (slot == NATIVE_FRAME_SLOT_NONE || slot > f->nslots)
     59     nf_panic(f, "bad frame slot");
     60   return &f->slots[slot - 1u];
     61 }
     62 
     63 void native_frame_note_outgoing(NativeFrame* f, u32 bytes) {
     64   if (bytes > f->max_outgoing) f->max_outgoing = bytes;
     65 }
     66 
     67 void native_frame_set_final(NativeFrame* f) { f->frame_final = 1; }
     68 
     69 void native_frame_set_callee_saves(NativeFrame* f, const u32* used_by_class,
     70                                    u32 nclasses,
     71                                    const NativeFrameSaveSpec* spec_by_class,
     72                                    u32 nspec, int alloc_slots) {
     73   f->ncallee_saves = 0;
     74   if (!used_by_class) return;
     75   for (u32 cls = 0; cls < nclasses; ++cls) {
     76     u32 mask = used_by_class[cls];
     77     for (Reg r = 0; r < 32u && mask; ++r) {
     78       NativeFrameCalleeSave* cs;
     79       if ((mask & (1u << r)) == 0) continue;
     80       mask &= ~(1u << r);
     81       if (f->ncallee_saves >= NATIVE_FRAME_MAX_CALLEE_SAVES)
     82         nf_panic(f, "too many callee-saved registers");
     83       cs = &f->callee_saves[f->ncallee_saves++];
     84       cs->cls = (u8)cls;
     85       cs->reg = r;
     86       cs->slot = NATIVE_FRAME_SLOT_NONE;
     87       cs->type = 0;
     88       if (cls < nspec && spec_by_class) cs->type = spec_by_class[cls].type;
     89       if (alloc_slots) {
     90         NativeFrameSlotDesc sd;
     91         const NativeFrameSaveSpec* sp =
     92             (cls < nspec && spec_by_class) ? &spec_by_class[cls] : NULL;
     93         memset(&sd, 0, sizeof sd);
     94         sd.type = cs->type;
     95         sd.size = sp && sp->size ? sp->size : 8u;
     96         sd.align = sp && sp->align ? sp->align : 8u;
     97         sd.kind = NATIVE_FRAME_SLOT_SAVE;
     98         cs->slot = native_frame_slot_alloc(f, &sd);
     99       }
    100     }
    101   }
    102 }
    103 
    104 u32 native_frame_collect_saves(const NativeFrame* f, NativeAllocClass cls,
    105                                Reg* out, u32 cap) {
    106   u32 n = 0;
    107   for (u32 i = 0; i < f->ncallee_saves; ++i) {
    108     if (f->callee_saves[i].cls != (u8)cls) continue;
    109     if (n >= cap) break;
    110     out[n++] = f->callee_saves[i].reg;
    111   }
    112   return n;
    113 }
    114 
    115 u32 native_frame_va_save_bytes(TargetABI* abi) {
    116   ABIVaListInfo va = abi_va_list_layout(abi);
    117   return va.gp_reg_count * va.gp_slot_size + va.fp_reg_count * va.fp_slot_size;
    118 }