From 98d76e7d97912f53fe5ab3064076e4314f5c7d5c Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Sat, 7 Oct 2023 20:20:36 +0100 Subject: [PATCH] Add mechanism for storing comments in code blobs --- src/jit/jit-code.c | 147 ++++++++++++++++++++++++++++++++++++++++++++- src/jit/jit-dump.c | 30 ++++----- src/jit/jit-priv.h | 12 ++++ src/jit/jit-x86.c | 1 + 4 files changed, 171 insertions(+), 19 deletions(-) diff --git a/src/jit/jit-code.c b/src/jit/jit-code.c index 9dba83af..6425de19 100644 --- a/src/jit/jit-code.c +++ b/src/jit/jit-code.c @@ -29,6 +29,7 @@ #include #include #include +#include #if defined __MINGW32__ #include @@ -83,12 +84,26 @@ STATIC_ASSERT(CODE_PAGE_SIZE % THREAD_CACHE_SIZE == 0); typedef struct _code_page code_page_t; +typedef struct { + uintptr_t addr; + char *text; +} code_comment_t; + +typedef struct { + unsigned count; + unsigned max; + code_comment_t *comments; +} code_debug_t; + typedef struct _code_span { code_cache_t *owner; code_span_t *next; ident_t name; uint8_t *base; size_t size; +#ifdef DEBUG + code_debug_t debug; +#endif } code_span_t; typedef struct _patch_list { @@ -293,10 +308,21 @@ static void code_disassemble(code_span_t *span, uintptr_t mark, cs_insn *insn = cs_malloc(span->owner->capstone); +#ifdef DEBUG + code_comment_t *comment = span->debug.comments; +#endif + const uint8_t *const eptr = span->base + span->size; for (const uint8_t *ptr = span->base; ptr < eptr; ) { - size_t size = eptr - ptr; uint64_t address = (uint64_t)ptr; + +#ifdef DEBUG + for (; comment < span->debug.comments + span->debug.count + && comment->addr <= address; comment++) + printf("%30s;; %s\n", "", comment->text); +#endif + + size_t size = eptr - ptr; int col = 0; if (cs_disasm_iter(span->owner->capstone, &ptr, &size, &address, insn)) { char hex1[33], *p = hex1; @@ -564,6 +590,125 @@ void code_blob_patch(code_blob_t *blob, jit_label_t label, code_patch_fn_t fn) } } +#ifdef DEBUG +static void code_blob_print_value(text_buf_t *tb, jit_value_t value) +{ + switch (value.kind) { + case JIT_VALUE_REG: + tb_printf(tb, "R%d", value.reg); + break; + case JIT_VALUE_INT64: + if (value.int64 < 4096) + tb_printf(tb, "#%"PRIi64, value.int64); + else + tb_printf(tb, "#0x%"PRIx64, value.int64); + break; + case JIT_VALUE_DOUBLE: + tb_printf(tb, "%%%g", value.dval); + break; + case JIT_ADDR_CPOOL: + tb_printf(tb, "[CP+%"PRIi64"]", value.int64); + break; + case JIT_ADDR_REG: + tb_printf(tb, "[R%d", value.reg); + if (value.disp != 0) + tb_printf(tb, "+%d", value.disp); + tb_cat(tb, "]"); + break; + case JIT_ADDR_ABS: + tb_printf(tb, "[#%016"PRIx64"]", value.int64); + break; + case JIT_ADDR_COVER: + tb_printf(tb, "@%"PRIi64, value.int64); + break; + case JIT_VALUE_LABEL: + tb_printf(tb, "%d", value.label); + break; + case JIT_VALUE_HANDLE: + tb_printf(tb, "<%d>", value.handle); + break; + case JIT_VALUE_EXIT: + tb_printf(tb, "%s", jit_exit_name(value.exit)); + break; + case JIT_VALUE_LOC: + tb_printf(tb, "<%s:%d>", loc_file_str(&value.loc), value.loc.first_line); + break; + case JIT_VALUE_FOREIGN: + tb_printf(tb, "$%s", istr(ffi_get_sym(value.foreign))); + break; + case JIT_VALUE_LOCUS: + tb_printf(tb, "%s%+d", istr(value.ident), value.disp); + break; + case JIT_VALUE_VPOS: + tb_printf(tb, "%u:%u", value.vpos.block, value.vpos.op); + break; + default: + tb_cat(tb, "???"); + } +} + +static void code_blob_add_comment(code_blob_t *blob, char *text) +{ + code_debug_t *dbg = &(blob->span->debug); + + if (dbg->count == dbg->max) { + dbg->max = MAX(128, dbg->max * 2); + dbg->comments = xrealloc_array(dbg->comments, dbg->max, + sizeof(code_comment_t)); + } + + dbg->comments[dbg->count].addr = (uintptr_t)blob->wptr; + dbg->comments[dbg->count].text = text; + dbg->count++; +} + +void code_blob_print_ir(code_blob_t *blob, jit_ir_t *ir) +{ + LOCAL_TEXT_BUF tb = tb_new(); + tb_printf(tb, "%s%s", jit_op_name(ir->op), jit_cc_name(ir->cc)); + + if (ir->size != JIT_SZ_UNSPEC) + tb_printf(tb, ".%d", 1 << (3 + ir->size)); + + tb_printf(tb, "%*.s", (int)MAX(0, 10 - tb_len(tb)), ""); + + if (ir->result != JIT_REG_INVALID) + tb_printf(tb, "R%d", ir->result); + + if (ir->arg1.kind != JIT_VALUE_INVALID) { + if (ir->result != JIT_REG_INVALID) + tb_cat(tb, ", "); + code_blob_print_value(tb, ir->arg1); + } + + if (ir->arg2.kind != JIT_VALUE_INVALID) { + tb_cat(tb, ", "); + code_blob_print_value(tb, ir->arg2); + } + + code_blob_add_comment(blob, tb_claim(tb)); +} + +void code_blob_printf(code_blob_t *blob, const char *fmt, ...) +{ + code_debug_t *dbg = &(blob->span->debug); + + if (dbg->count == dbg->max) { + dbg->max = MAX(128, dbg->max * 2); + dbg->comments = xrealloc_array(dbg->comments, dbg->max, + sizeof(code_comment_t)); + } + + va_list ap; + va_start(ap, fmt); + + char *text = xvasprintf(fmt, ap); + code_blob_add_comment(blob, text); + + va_end(ap); +} +#endif // DEBUG + #ifdef ARCH_ARM64 static void *arm64_emit_trampoline(code_blob_t *blob, uintptr_t dest) { diff --git a/src/jit/jit-dump.c b/src/jit/jit-dump.c index 471a1c90..f442f313 100644 --- a/src/jit/jit-dump.c +++ b/src/jit/jit-dump.c @@ -63,6 +63,16 @@ const char *jit_op_name(jit_op_t op) } } +const char *jit_cc_name(jit_cc_t cc) +{ + static const char *names[] = { + "", ".T", ".F", ".EQ", ".NE", ".LT", ".GE", ".GT", ".LE", + ".O", ".NO", ".C", ".NC" + }; + assert(cc < ARRAY_LEN(names)); + return names[cc]; +} + const char *jit_exit_name(jit_exit_t exit) { static const char *names[] = { @@ -231,27 +241,11 @@ static void jit_dump_ir(jit_dump_t *d, jit_ir_t *ir) } int col = 0; - col += printf("\t%s", jit_op_name(ir->op)); - switch (ir->cc) { - case JIT_CC_NONE: break; - case JIT_CC_T: col += printf(".T"); break; - case JIT_CC_F: col += printf(".F"); break; - case JIT_CC_EQ: col += printf(".EQ"); break; - case JIT_CC_NE: col += printf(".NE"); break; - case JIT_CC_LT: col += printf(".LT"); break; - case JIT_CC_GT: col += printf(".GT"); break; - case JIT_CC_LE: col += printf(".LE"); break; - case JIT_CC_GE: col += printf(".GE"); break; - case JIT_CC_O: col += printf(".O"); break; - case JIT_CC_NO: col += printf(".NO"); break; - case JIT_CC_C: col += printf(".C"); break; - case JIT_CC_NC: col += printf(".NC"); break; - } + col += printf("\t%s%s", jit_op_name(ir->op), jit_cc_name(ir->cc)); if (ir->size != JIT_SZ_UNSPEC) col += printf(".%d", 1 << (3 + ir->size)); - while (col < 15) - col += printf(" "); + col += printf("%*.s", (int)MAX(0, 15 - col), ""); if (ir->result != JIT_REG_INVALID) col += printf("R%d", ir->result); diff --git a/src/jit/jit-priv.h b/src/jit/jit-priv.h index a91329bd..d5028ad2 100644 --- a/src/jit/jit-priv.h +++ b/src/jit/jit-priv.h @@ -351,6 +351,7 @@ void jit_dump(jit_func_t *f); void jit_dump_with_mark(jit_func_t *f, jit_label_t label, bool cpool); void jit_dump_interleaved(jit_func_t *f); const char *jit_op_name(jit_op_t op); +const char *jit_cc_name(jit_cc_t cc); const char *jit_exit_name(jit_exit_t exit); void jit_interp(jit_func_t *f, jit_anchor_t *caller, jit_scalar_t *args, tlab_t *tlab); @@ -394,6 +395,17 @@ void code_blob_mark(code_blob_t *blob, jit_label_t label); void code_blob_patch(code_blob_t *blob, jit_label_t label, code_patch_fn_t fn); void code_load_object(code_blob_t *blob, const void *data, size_t size); +#ifdef DEBUG +__attribute__((format(printf, 2, 3))) +void code_blob_printf(code_blob_t *blob, const char *fmt, ...); + +void code_blob_print_ir(code_blob_t *blob, jit_ir_t *ir); +#else + +#define code_blob_printf(blob, fmt, ...) +#define code_blob_print_ir(blob, ir) +#endif + bool jit_pack_fill(jit_pack_t *jp, jit_t *j, jit_func_t *f); void jit_pack_put(jit_pack_t *jp, ident_t name, const uint8_t *cpool, const char *strtab, const uint8_t *buf); diff --git a/src/jit/jit-x86.c b/src/jit/jit-x86.c index 39334850..f149fe6d 100644 --- a/src/jit/jit-x86.c +++ b/src/jit/jit-x86.c @@ -1848,6 +1848,7 @@ static void jit_x86_cgen(jit_t *j, jit_handle_t handle, void *context) for (int i = 0; i < f->nirs; i++) { if (f->irbuf[i].target) code_blob_mark(blob, i); + code_blob_print_ir(blob, &(f->irbuf[i])); jit_x86_op(blob, state, &(f->irbuf[i])); } -- 2.39.2