kit

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

debug_abbrev.c (3118B)


      1 /* Abbrev pool: dedup by (tag, has_children, attr-list).
      2  *
      3  * Linear search dedup. Abbrev pools for our DIE shapes top out in the low
      4  * tens; not worth a hashmap. Codes are 1-based in DWARF. */
      5 
      6 #include <string.h>
      7 
      8 #include "core/buf.h"
      9 #include "core/core.h"
     10 #include "core/heap.h"
     11 #include "core/vec.h"
     12 #include "debug/debug_internal.h"
     13 
     14 void abbrev_init(DebugAbbrevPool* p, Heap* h) {
     15   (void)h;
     16   p->items = NULL;
     17   p->n = 0;
     18   p->cap = 0;
     19 }
     20 
     21 /* Teardown frees the per-abbrev attr arrays, which requires a heap — so the
     22  * sole entry point is abbrev_fini_heap below. Callers (debug.c) hold the
     23  * heap that abbrev_init received and pass it back here. */
     24 static void abbrev_free_attrs(DebugAbbrevPool* p, Heap* h) {
     25   u32 i;
     26   for (i = 0; i < p->n; ++i) {
     27     if (p->items[i].attrs) {
     28       h->free(h, p->items[i].attrs,
     29               sizeof(DebugAbbrevAttr) * p->items[i].nattrs);
     30       p->items[i].attrs = NULL;
     31       p->items[i].nattrs = 0;
     32     }
     33   }
     34   if (p->items) {
     35     h->free(h, p->items, sizeof(*p->items) * p->cap);
     36     p->items = NULL;
     37     p->n = 0;
     38     p->cap = 0;
     39   }
     40 }
     41 
     42 /* Public-ish helper: debug.c will call this at fini time. We expose a
     43  * thin wrapper that simply forwards. */
     44 void abbrev_fini_heap(DebugAbbrevPool* p, Heap* h);
     45 void abbrev_fini_heap(DebugAbbrevPool* p, Heap* h) { abbrev_free_attrs(p, h); }
     46 
     47 static int attr_eq(const DebugAbbrevAttr* a, const DebugAbbrevAttr* b, u32 n) {
     48   u32 i;
     49   for (i = 0; i < n; ++i) {
     50     if (a[i].attr != b[i].attr) return 0;
     51     if (a[i].form != b[i].form) return 0;
     52     if (a[i].implicit_const != b[i].implicit_const) return 0;
     53   }
     54   return 1;
     55 }
     56 
     57 u32 abbrev_intern(DebugAbbrevPool* p, Heap* h, u16 tag, u8 has_children,
     58                   const DebugAbbrevAttr* attrs, u32 nattrs) {
     59   u32 i;
     60   DebugAbbrev* slot;
     61   for (i = 0; i < p->n; ++i) {
     62     DebugAbbrev* it = &p->items[i];
     63     if (it->tag == tag && it->has_children == has_children &&
     64         it->nattrs == nattrs && attr_eq(it->attrs, attrs, nattrs)) {
     65       return it->code;
     66     }
     67   }
     68   if (VEC_GROW(h, p->items, p->cap, p->n + 1)) return 0;
     69   slot = &p->items[p->n];
     70   slot->code = p->n + 1;
     71   slot->tag = tag;
     72   slot->has_children = has_children;
     73   slot->pad = 0;
     74   slot->nattrs = nattrs;
     75   if (nattrs) {
     76     slot->attrs = (DebugAbbrevAttr*)h->alloc(
     77         h, sizeof(DebugAbbrevAttr) * nattrs, _Alignof(DebugAbbrevAttr));
     78     if (!slot->attrs) return 0;
     79     memcpy(slot->attrs, attrs, sizeof(DebugAbbrevAttr) * nattrs);
     80   } else {
     81     slot->attrs = NULL;
     82   }
     83   p->n++;
     84   return slot->code;
     85 }
     86 
     87 void abbrev_encode(const DebugAbbrevPool* p, Buf* out) {
     88   u32 i, j;
     89   for (i = 0; i < p->n; ++i) {
     90     const DebugAbbrev* a = &p->items[i];
     91     form_uleb(out, a->code);
     92     form_uleb(out, a->tag);
     93     form_u8(out, a->has_children);
     94     for (j = 0; j < a->nattrs; ++j) {
     95       form_uleb(out, a->attrs[j].attr);
     96       form_uleb(out, a->attrs[j].form);
     97       /* DW_FORM_implicit_const carries a sleb here, but we never use it. */
     98     }
     99     /* (0,0) terminator for attr list */
    100     form_uleb(out, 0);
    101     form_uleb(out, 0);
    102   }
    103   /* code 0 terminates the abbrev table */
    104   form_uleb(out, 0);
    105 }