From fbe0d3bc2e9181fa6d3582c750841d89017d579d Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Mon, 31 Mar 2025 11:41:14 -0700 Subject: [PATCH] set up eval scratch; promote raddbg_markup to base layer, plug in custom codebase vsnprintf --- build.bat | 1 + project.4coder | 13 ++- src/base/base_markup.h | 4 + src/eval/eval_interpret.c | 7 +- src/lib_raddbg_markup/raddbg_markup.h | 2 + src/raddbg/raddbg_main.c | 10 +- src/scratch/eval_scratch.c | 151 ++++++++++++++++++++++++++ 7 files changed, 175 insertions(+), 13 deletions(-) create mode 100644 src/scratch/eval_scratch.c diff --git a/build.bat b/build.bat index 0c9e0463..343f3f37 100644 --- a/build.bat +++ b/build.bat @@ -114,6 +114,7 @@ if "%rdi_from_dwarf%"=="1" set didbuild=1 && %compile% ..\src\rdi_fr if "%rdi_breakpad_from_pdb%"=="1" set didbuild=1 && %compile% ..\src\rdi_breakpad_from_pdb\rdi_breakpad_from_pdb_main.c %compile_link% %out%rdi_breakpad_from_pdb.exe || exit /b 1 if "%tester%"=="1" set didbuild=1 && %compile% ..\src\tester\tester_main.c %compile_link% %out%tester.exe || exit /b 1 if "%ryan_scratch%"=="1" set didbuild=1 && %compile% ..\src\scratch\ryan_scratch.c %compile_link% %out%ryan_scratch.exe || exit /b 1 +if "%eval_scratch%"=="1" set didbuild=1 && %compile% ..\src\scratch\eval_scratch.c %compile_link% %out%eval_scratch.exe || exit /b 1 if "%textperf%"=="1" set didbuild=1 && %compile% ..\src\scratch\textperf.c %compile_link% %out%textperf.exe || exit /b 1 if "%convertperf%"=="1" set didbuild=1 && %compile% ..\src\scratch\convertperf.c %compile_link% %out%convertperf.exe || exit /b 1 if "%debugstringperf%"=="1" set didbuild=1 && %compile% ..\src\scratch\debugstringperf.c %compile_link% %out%debugstringperf.exe || exit /b 1 diff --git a/project.4coder b/project.4coder index 6e727228..585fdf9b 100644 --- a/project.4coder +++ b/project.4coder @@ -46,12 +46,15 @@ load_paths = commands = { //- rjf: fkey command slots (change locally but do not commit) - .f1 = { .win = "raddbg_stable --ipc kill_all && build raddbg telemetry", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, - .f2 = { .win = "build rdi_from_pdb", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, + + //- rjf: [raddbg] + // .f1 = { .win = "raddbg_stable --ipc kill_all && build raddbg telemetry", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, + + //- rjf: [eval_scratch] + .f1 = { .win = "raddbg_stable --ipc kill_all && build no_meta eval_scratch && raddbg_stable --ipc bring_to_front && raddbg_stable --ipc run", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, + + //- rjf: running target .f3 = { .win = "raddbg_stable --ipc run", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, - // .f3 = { .win = "pushd build && raddbg.exe --user:local_dev.raddbg_user --project:local_dev.raddbg_project --xuto_run && popd",.linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, - // .f1 = { .win = "build textperf release telemetry", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, - // .f3 = { .win = "pushd build && textperf.exe --capture && popd",.linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, //- rjf: local target builds .build_raddbg = { .win = "build raddbg", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, diff --git a/src/base/base_markup.h b/src/base/base_markup.h index fd291375..8a1c6578 100644 --- a/src/base/base_markup.h +++ b/src/base/base_markup.h @@ -4,6 +4,10 @@ #ifndef BASE_MARKUP_H #define BASE_MARKUP_H +#define RADDBG_MARKUP_IMPLEMENTATION +#define RADDBG_MARKUP_VSNPRINTF raddbg_vsnprintf +#include "lib_raddbg_markup/raddbg_markup.h" + internal void set_thread_name(String8 string); internal void set_thread_namef(char *fmt, ...); #define ThreadNameF(...) (set_thread_namef(__VA_ARGS__)) diff --git a/src/eval/eval_interpret.c b/src/eval/eval_interpret.c index 0ebd1ed1..5f994405 100644 --- a/src/eval/eval_interpret.c +++ b/src/eval/eval_interpret.c @@ -14,11 +14,12 @@ internal void e_select_interpret_ctx(E_InterpretCtx *ctx, RDI_Parsed *primary_rdi, U64 ip_voff) { e_interpret_ctx = ctx; - + // compute and apply frame base + if(primary_rdi != 0) { E_Interpretation frame_base = { .code = ~0 }; - + RDI_Procedure *proc = rdi_procedure_from_voff(primary_rdi, ip_voff); for(U64 loc_block_idx = proc->frame_base_location_first; loc_block_idx < proc->frame_base_location_opl; loc_block_idx += 1) { @@ -45,7 +46,7 @@ e_select_interpret_ctx(E_InterpretCtx *ctx, RDI_Parsed *primary_rdi, U64 ip_voff break; } } - + if(frame_base.code == E_InterpretationCode_Good) { *ctx->frame_base = frame_base.value.u64; diff --git a/src/lib_raddbg_markup/raddbg_markup.h b/src/lib_raddbg_markup/raddbg_markup.h index 2eb8a77e..84bddf4e 100644 --- a/src/lib_raddbg_markup/raddbg_markup.h +++ b/src/lib_raddbg_markup/raddbg_markup.h @@ -99,7 +99,9 @@ extern "C" long long _InterlockedExchangeAdd64(long long volatile*, long long); #pragma intrinsic(_InterlockedCompareExchange64) #pragma intrinsic(_InterlockedExchangeAdd64) +#if RADDBG_MARKUP_DEFAULT_VSNPRINTF int RADDBG_MARKUP_VSNPRINTF(char * const, unsigned long long const, const char * const, va_list); +#endif #if defined(__cplusplus) } #endif diff --git a/src/raddbg/raddbg_main.c b/src/raddbg/raddbg_main.c index e6f78215..a127444a 100644 --- a/src/raddbg/raddbg_main.c +++ b/src/raddbg/raddbg_main.c @@ -27,7 +27,7 @@ // - The hover evaluation feature has been majorly upgraded to support all // features normally available in the `Watch` view. Hover evaluations now // explicitly show type information, and contain a view rule column, which -// can be edited in an identical way as the `Watch` view. +// can be edited in a way identical to the `Watch` view. // - Added "auto tabs", which are colored differently than normal tabs. These // tabs are automatically opened by the debugger when snapping to source code // which is not already opened. They are automatically replaced and recycled @@ -42,12 +42,13 @@ // those purposes, the `Threads` view is sufficient if not desirable, and // the extra information provided by `Processes` and `Machines`, while useful // in other contexts, is not useful in that common case. The `Machines` view -// now shows a superset of the information previosuly found in the +// now shows a superset of the information previously found in the // `Scheduler` view. // - The two separate interfaces for editing threads, breakpoints, and watch // pins (the right-click context menu and the dedicated tabs) have been -// merged. -// - Added the ability to add a list environment strings to targets. +// merged. Both interfaces support exactly the same features in exactly the +// same way. +// - Added the ability to add a list of environment strings to targets. // - The debugger releases are now packaged with a `raddbg_markup.h` // single-header library which contains a number of source code markup tools // which can be used in your programs. Some of these features are for direct @@ -388,7 +389,6 @@ //- rjf: [lib] #include "third_party/rad_lzb_simple/rad_lzb_simple.h" #include "third_party/rad_lzb_simple/rad_lzb_simple.c" -#include "lib_raddbg_markup/raddbg_markup.h" //- rjf: [h] #include "base/base_inc.h" diff --git a/src/scratch/eval_scratch.c b/src/scratch/eval_scratch.c new file mode 100644 index 00000000..3b43e616 --- /dev/null +++ b/src/scratch/eval_scratch.c @@ -0,0 +1,151 @@ +// Copyright (c) 2024 Epic Games Tools +// Licensed under the MIT license (https://opensource.org/license/mit/) + +//////////////////////////////// +//~ rjf: Includes + +//- rjf: [h] +#include "base/base_inc.h" +#include "os/os_inc.h" +#include "rdi_format/rdi_format_local.h" +#include "regs/regs.h" +#include "regs/rdi/regs_rdi.h" +#include "eval/eval_inc.h" + +//- rjf: [c] +#include "base/base_inc.c" +#include "os/os_inc.c" +#include "rdi_format/rdi_format_local.c" +#include "regs/regs.c" +#include "regs/rdi/regs_rdi.c" +#include "eval/eval_inc.c" + +//////////////////////////////// +//~ rjf: Entry Point + +internal void +entry_point(CmdLine *cmdline) +{ + Arena *arena = arena_alloc(); + char *indent_spaces = " "; + E_TypeCtx *type_ctx = push_array(arena, E_TypeCtx, 1); + e_select_type_ctx(type_ctx); + E_ParseCtx *parse_ctx = push_array(arena, E_ParseCtx, 1); + e_select_parse_ctx(parse_ctx); + E_IRCtx *ir_ctx = push_array(arena, E_IRCtx, 1); + e_select_ir_ctx(ir_ctx); + E_InterpretCtx *interpret_ctx = push_array(arena, E_InterpretCtx, 1); + e_select_interpret_ctx(interpret_ctx, 0, 0); + String8 exprs[] = + { + str8_lit("123"), + }; + for EachElement(idx, exprs) + { + //- rjf: begin expression + String8 expr_text = exprs[idx]; + raddbg_log("`%S`\n", expr_text); + + //- rjf: tokenize + E_TokenArray tokens = e_token_array_from_text(arena, expr_text); + raddbg_log(" tokens:\n"); + for EachIndex(idx, tokens.count) + { + E_Token token = tokens.v[idx]; + String8 token_string = str8_substr(expr_text, token.range); + raddbg_log(" %S: `%S`\n", e_token_kind_strings[token.kind], token_string); + } + + //- rjf: parse + E_Parse parse = e_parse_expr_from_text_tokens(arena, expr_text, &tokens); + { + typedef struct Task Task; + struct Task + { + Task *next; + E_Expr *expr; + S32 indent; + }; + raddbg_log(" expr:\n"); + Task start_task = {0, parse.exprs.first, 2}; + Task *first_task = &start_task; + for(Task *t = first_task; t != 0; t = t->next) + { + E_Expr *expr = t->expr; + raddbg_log("%.*s%S", (int)t->indent*2, indent_spaces, e_expr_kind_strings[expr->kind]); + switch(expr->kind) + { + default:{}break; + case E_ExprKind_LeafU64: + { + raddbg_log(" (%I64u)", expr->value.u64); + }break; + } + raddbg_log("\n"); + for(E_Expr *child = expr->first; child != &e_expr_nil; child = child->next) + { + Task *task = push_array(arena, Task, 1); + task->next = t->next; + t->next = task; + task->expr = child; + task->indent = t->indent+1; + } + } + } + + //- rjf: type + E_IRTreeAndType irtree = e_irtree_and_type_from_expr(arena, parse.exprs.first); + { + raddbg_log(" type:\n"); + S32 indent = 2; + for(E_TypeKey type_key = irtree.type_key; + !e_type_key_match(e_type_key_zero(), type_key); + type_key = e_type_direct_from_key(type_key), + indent += 1) + { + E_Type *type = e_type_from_key(arena, type_key); + raddbg_log("%.*s%S\n", (int)indent*2, indent_spaces, e_kind_basic_string_table[type->kind]); + } + } + + //- rjf: irtree + { + typedef struct Task Task; + struct Task + { + Task *next; + E_IRNode *irnode; + S32 indent; + }; + raddbg_log(" ir_tree:\n"); + Task start_task = {0, irtree.root, 2}; + Task *first_task = &start_task; + for(Task *t = first_task; t != 0; t = t->next) + { + E_IRNode *irnode = t->irnode; + raddbg_log("%.*s", (int)t->indent*2, indent_spaces); + switch(irnode->op) + { + default:{}break; +#define X(name) case RDI_EvalOp_##name:{raddbg_log(" " #name);}break; + RDI_EvalOp_XList +#undef X + } + if(irnode->value.u64 != 0) + { + raddbg_log(" (%I64u)", irnode->value.u64); + } + raddbg_log("\n"); + for(E_IRNode *child = irnode->first; child != &e_irnode_nil; child = child->next) + { + Task *task = push_array(arena, Task, 1); + task->next = t->next; + t->next = task; + task->irnode = child; + task->indent = t->indent+1; + } + } + } + + } +}