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 }