kit

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

debug.h (6091B)


      1 #ifndef KIT_DEBUG_H
      2 #define KIT_DEBUG_H
      3 
      4 #include "arch/mc.h"
      5 #include "core/core.h"
      6 
      7 /* DWARF debug info. The producer side (CG, CGTarget/MCEmitter, opt) feeds
      8  * events here as compilation runs; the emitter side writes .debug_*
      9  * sections into the same ObjBuilder when debug_emit is called.
     10  *
     11  * Type DIEs are addressed through opaque DebugTypeId handles. The core
     12  * Debug module is language-neutral: it knows about DWARF type kinds (base,
     13  * pointer, array, qualified, typedef, function, record, enum) but not
     14  * about any source-language type representation. Frontends own their
     15  * adapters and pass DebugTypeId values here.
     16  *
     17  * Producer responsibilities:
     18  *   - Parser: nothing directly; types are looked up on demand from those
     19  *     that reach debug_local / debug_param.
     20  *   - CG: function and scope lifecycle, parameter and local declarations,
     21  *     using frontend-provided DebugTypeId values.
     22  *   - MCEmitter (or the lowering pass inside opt at -O2): the line program
     23  *     and pc-range bounds for functions.
     24  *   - opt at -O2: location-list entries when a variable's location changes
     25  *     across the optimized function. */
     26 
     27 typedef struct Debug Debug;
     28 
     29 Debug* debug_new(Compiler*, ObjBuilder*);
     30 void debug_free(Debug*);
     31 
     32 /* file table — SourceManager owns paths; returns DWARF file index */
     33 u32 debug_file(Debug*, u32 source_file_id);
     34 
     35 /* ============================================================
     36  * Type DIE handles
     37  * ============================================================
     38  * Construction is one-shot per type: callers describe the type to Debug,
     39  * which records the DIE and returns an id. Ids are stable for the
     40  * lifetime of the Debug object. DEBUG_TYPE_NONE is the sentinel used for
     41  * "no type" (e.g. a void return without an explicit void DIE — callers
     42  * normally supply debug_type_void()).
     43  *
     44  * The core Debug module does not intern by source-language identity.
     45  * Constructing the same shape twice yields two distinct ids. */
     46 
     47 typedef u32 DebugTypeId;
     48 #define DEBUG_TYPE_NONE 0u
     49 
     50 typedef enum DebugBaseEncoding {
     51   DEBUG_BE_BOOL,
     52   DEBUG_BE_SIGNED,
     53   DEBUG_BE_UNSIGNED,
     54   DEBUG_BE_SIGNED_CHAR,
     55   DEBUG_BE_UNSIGNED_CHAR,
     56   DEBUG_BE_FLOAT,
     57   DEBUG_BE_UTF,
     58   DEBUG_BE_ADDRESS,
     59 } DebugBaseEncoding;
     60 
     61 DebugTypeId debug_type_base(Debug*, Sym name, DebugBaseEncoding, u32 byte_size);
     62 DebugTypeId debug_type_void(Debug*);
     63 DebugTypeId debug_type_ptr(Debug*, DebugTypeId pointee);
     64 /* count == 0 means incomplete/unknown bound */
     65 DebugTypeId debug_type_array(Debug*, DebugTypeId elem, u32 count);
     66 DebugTypeId debug_type_const(Debug*, DebugTypeId base);
     67 DebugTypeId debug_type_volatile(Debug*, DebugTypeId base);
     68 DebugTypeId debug_type_restrict(Debug*, DebugTypeId base);
     69 DebugTypeId debug_type_typedef(Debug*, Sym name, DebugTypeId base);
     70 DebugTypeId debug_type_func(Debug*, DebugTypeId ret, const DebugTypeId* params,
     71                             u32 nparams, int variadic);
     72 
     73 /* Records (struct/union) and enums are built incrementally so that
     74  * recursive shapes (a struct containing a pointer to itself) can be
     75  * expressed: open the builder, get an id back from _end, and pass that id
     76  * back through debug_type_ptr earlier if needed via the adapter's cache. */
     77 typedef struct DebugTypeBuilder DebugTypeBuilder;
     78 DebugTypeBuilder* debug_type_record_begin(Debug*, Sym tag, int is_union,
     79                                           u32 byte_size, u32 align);
     80 void debug_type_record_field(DebugTypeBuilder*, Sym name, DebugTypeId type,
     81                              u32 byte_offset);
     82 void debug_type_record_bitfield(DebugTypeBuilder*, Sym name, DebugTypeId type,
     83                                 u32 byte_offset, u16 bit_offset, u16 bit_width);
     84 DebugTypeId debug_type_record_end(DebugTypeBuilder*);
     85 
     86 typedef struct DebugEnumBuilder DebugEnumBuilder;
     87 DebugEnumBuilder* debug_type_enum_begin(Debug*, Sym tag, DebugTypeId base);
     88 void debug_type_enum_value(DebugEnumBuilder*, Sym name, i64 value);
     89 DebugTypeId debug_type_enum_end(DebugEnumBuilder*);
     90 
     91 /* ============================================================
     92  * Function and variable lifecycle
     93  * ============================================================ */
     94 
     95 void debug_func_begin(Debug*, ObjSymId, DebugTypeId fn_type, SrcLoc decl);
     96 void debug_func_select(Debug*, ObjSymId);
     97 void debug_func_pc_range(Debug*, ObjSecId text_section_id, u32 begin_ofs,
     98                          u32 end_ofs);
     99 void debug_func_end(Debug*);
    100 void debug_prune_removed_funcs(Debug*);
    101 
    102 /* lexical scopes (nested between func_begin/end) */
    103 void debug_scope_begin(Debug*, SrcLoc);
    104 void debug_scope_end(Debug*, SrcLoc);
    105 
    106 /* variable location */
    107 typedef enum DebugVarLocKind {
    108   DVL_FRAME,
    109   DVL_REG,
    110   DVL_GLOBAL,
    111   DVL_LOCLIST, /* time-varying location, see debug_loclist_* */
    112 } DebugVarLocKind;
    113 
    114 typedef struct DebugVarLoc {
    115   u8 kind;
    116   u8 pad[3];
    117   union {
    118     i32 frame_ofs;
    119     Reg reg;
    120     ObjSymId global;
    121     u32 loclist_id;
    122   } v;
    123 } DebugVarLoc;
    124 
    125 void debug_param(Debug*, Sym name, DebugTypeId, SrcLoc, u32 idx, DebugVarLoc);
    126 void debug_local(Debug*, Sym name, DebugTypeId, SrcLoc, DebugVarLoc);
    127 
    128 /* line program */
    129 void debug_line(Debug*, ObjSecId text_section_id, u32 text_offset, SrcLoc,
    130                 int is_stmt);
    131 
    132 /* Stash the most recent SrcLoc reported by the parser/harness. CG calls this
    133  * from cg_set_loc; the backend is free to read d->pending_loc when it doesn't
    134  * already have a loc on hand. */
    135 void debug_set_pending_loc(Debug*, SrcLoc);
    136 
    137 /* Backend-side line-program input: invoked after each emitted instruction.
    138  * Forwards to debug_line with is_stmt=1 and dedupes back-to-back identical
    139  * (section, offset, loc) triples. */
    140 void debug_emit_row(Debug*, ObjSecId text_section_id, u32 text_offset, SrcLoc);
    141 
    142 /* location lists — for opt'd code where a variable moves between locations */
    143 u32 debug_loclist_new(Debug*);
    144 void debug_loclist_add(Debug*, u32 id, u32 begin_pc, u32 end_pc, DebugVarLoc);
    145 
    146 /* Emit the accumulated debug info as DWARF sections into the ObjBuilder.
    147  * Must be called after all code sections are finalized but before the
    148  * file emitters run. */
    149 void debug_emit(Debug*);
    150 
    151 #endif