Author SHA1 Message Date
ed 76ce8a79c2 Made ease of use scripts for building and cleaning 2024-02-09 17:50:42 -05:00
ed 932db741fa Merge remote-tracking branch 'leidegre/feature/odin' into build_scripts 2024-02-09 16:08:40 -05:00
Ryan Fleury c757388bb4 fix serialization/deserialization of top-level watch view rules 2024-02-06 15:38:42 -08:00
Ryan Fleury fb43eb9c72 default to no d3d11 debug features; use command line flag to enable 2024-02-06 14:59:41 -08:00
Ryan Fleury 9ef1b4b021 fix system processes lister fuzzy matching; fix ctrl layer locking modules on detach (demon was not reporting module string!) 2024-02-06 13:59:43 -08:00
Ryan Fleury 7305c12166 reset control context unwind count when submitting all runs 2024-02-06 13:48:05 -08:00
Ryan Fleury e3f18d3b87 fix mutable eval root key stability w.r.t. view rules & so on 2024-02-06 13:28:14 -08:00
Ryan Fleury 86e332f2ef allow compound macro expressions in eval system; poison used macro names, before descending 2024-02-06 11:55:51 -08:00
Ryan Fleury 6296d2bd96 first pass of watch window macros; fix active-but-disabled line edit rendering; other minor fixes 2024-02-06 11:47:52 -08:00
Ryan Fleury c2d96a8df6 pull out eval watch view cursor state; begin prepping for multirow table selection 2024-02-06 09:21:14 -08:00
Ryan Fleury c0cf0bf2da fix small visual issues with hover eval 2024-02-06 08:55:55 -08:00
Ryan Fleury 87ed6a8c62 per-run tls base vaddr cache; cleanup/fixes/improvements on fuzzy filtering of scheduler view 2024-02-06 08:48:09 -08:00
Ryan Fleury 0696eab974 address some jank with query view focuses intermixing with deselection/hover-eval/etc. 2024-02-06 07:35:51 -08:00
Martins MozeikoandRyan Fleury 9c02f947c7 show git commit id in window title & fatal exception dialog 2024-02-06 07:30:58 -08:00
Ryan Fleury 816bf195c2 more filtering coverage; fuzzy filtering on search tags as well as entity display string; display a few known frames from callstack in thread entity description buttons 2024-02-05 14:36:33 -08:00
Ryan Fleury 95b8b71322 dedup multiple unwinder paths; just collapse down to using the ctrl one 2024-02-05 14:06:06 -08:00
Ryan Fleury ef317c1ffc procedures view 2024-02-05 13:58:19 -08:00
Ryan Fleury 9504946376 entity view filtering 2024-02-05 12:08:50 -08:00
Ryan Fleury e03e1dd136 eval lexer: same as last 2024-02-05 11:28:29 -08:00
Ryan Fleury 0b6b0947ed eval lexer: allow a few more corner cases of various compiler/linker-inserted identifiers, so that eval works in all cases 2024-02-05 11:26:37 -08:00
Ryan Fleury 38b8bfd6fb fix ordering of event consumption w/ filter box 2024-02-05 11:24:31 -08:00
Ryan Fleury 87e0e9a7e9 bugfix truncated string hover rule 2024-02-05 11:19:34 -08:00
Ryan Fleury 6e874c7449 syschar -> defwindowproc 2024-02-05 11:07:36 -08:00
Ryan Fleury d2d3d14c41 demon/win32: roll back on all hit traps, even if explicit. the previous implementation would silently skip threads past explicit traps that they hit, as a way of implicitly storing the fact that trap exceptions had been reported, and the user could continue past them. this resulted in incorrect instruction pointer display in those circumstances. this change adjusts this, so that after a trap exception of any kind, the instruction pointer is ALWAYS rolled back. to ensure that the trap is not repeatedly hit, if the associated exception has already been reported, to allow the user to e.g. step over traps (this is the behavior of Visual Studio), additional state is stored per-thread-entity, which allows a subsequent demon_os_run to adjust RIPs past their previously reported traps before running again. 2024-02-05 10:47:57 -08:00
Ryan Fleury 2359c82fba extend ctrl process memory cache with waiting mechanism; employ to wait for changes to propagate through process memory cache, when forcibly mutating debuggee process memory 2024-02-05 10:04:00 -08:00
Ryan Fleury f2c74cbcb2 float mousemove detection & ui mouse position rules down to ui core layer 2024-02-05 09:29:50 -08:00
Ryan Fleury f03f3e4421 robustify ctrl memory streaming cache & texture cache layer to unreasonably large sizes/dimensions 2024-02-05 09:24:00 -08:00
Ryan Fleury 95eea70682 fix failure condition in entry point detection 2024-02-05 08:54:45 -08:00
Ryan Fleury 762013899f switch entry point detection/trap strategy to finding *all* possible candidates, and trapping all of them, rather than forcing the ctrl thread to decide on one specific entry point voff 2024-02-05 08:41:18 -08:00
Ryan Fleury 0be4680ec9 os_gfx -> report mouse move events; still allow passive mouse interaction if window is unfocused, but have recently received mousemove events 2024-02-03 18:04:21 -08:00
Ryan Fleury 985a6f37e9 notes 2024-02-03 17:37:39 -08:00
Ryan Fleury f9e2aa99a9 fix padding calculation - prohibit all overlapping members 2024-02-03 09:56:24 -08:00
Ryan Fleury 509089d95d remain robust to busted range queries for ctrl process memory cache 2024-02-03 09:20:31 -08:00
Ryan Fleury 647558b140 fix plural language in singular scenarios 2024-02-02 17:28:22 -08:00
Ryan Fleury cbe842c5ec dont do padding members for unions, oops 2024-02-02 17:15:55 -08:00
Ryan Fleury f796f64c2f process memory read failuer visualization in eval watch view tables 2024-02-02 17:05:55 -08:00
Ryan Fleury 36d749ddb5 slightly stronger padding visualization 2024-02-02 16:46:54 -08:00
Ryan Fleury 7e589e8cd2 padding visualization 2024-02-02 16:42:08 -08:00
Ryan Fleury 708517a668 move fuzzy range match visualization into formal ui rendering path; write dedicated truncated fuzzy match rendering path; fixes some visual bugs & makes all fuzzy range match visualization consistent and not ad-hoc 2024-02-02 15:35:44 -08:00
Ryan Fleury 876d9338fc auto-close universal ctx menus when entities/tabs invalidate; some visual fixes 2024-02-02 14:13:00 -08:00
Ryan Fleury 6897c0bb57 only show mid-row cache line boundaries when unexpanded, since the expansion will show more precise info 2024-02-02 12:53:34 -08:00
Ryan Fleury 15e239a0dc cache line boundary visualization 2024-02-02 12:47:51 -08:00
Ryan Fleury 5d3aa301f0 enum type evaluation visualization - can now use watch windows to inspect all possible enum values 2024-02-02 11:50:21 -08:00
Ryan Fleury 847749337b eval parser: more coverage for c++-compiler-generated & various C++-style identifier names 2024-02-02 11:33:06 -08:00
Ryan Fleury 542753ddcc deduplicate editability/expandability determination path for viz row build 2024-02-02 11:12:20 -08:00
Ryan Fleury 9d8efa3a44 deduplicate common parts of viz row building 2024-02-02 11:03:14 -08:00
Ryan Fleury 410a340a09 oops -> carry over dbgi target with viz block splits 2024-02-02 10:13:39 -08:00
Ryan Fleury 8958b414e2 properly parameterize viz block & viz row building paths based on dbgi table target 2024-02-02 10:09:30 -08:00
Ryan Fleury ac895a85eb eliminate old eval watch view code 2024-02-02 09:30:22 -08:00
Ryan Fleury ad57a0d3e8 stop following expansion nodes at the first non-expanded one, when converting watch view selection coords when ancestor has been collapsed 2024-02-02 09:28:15 -08:00
Ryan Fleury 20ff4acecc simplify/collapse/deduplicate eval viz block building code; correctly build filtered-info-table-sorted expansions for filtered debug info table watches; eliminate special-case empty row in watch views, just feed everything through the viz blocks path 2024-02-01 17:05:08 -08:00
Ryan Fleury be4c52b7ef first part of collapsing globals/types/threadlocals path into being single viz block building path; more filtering ui work 2024-02-01 13:54:34 -08:00
Ryan Fleury 6740520bbe straighten out table coordinates <-> viz block coordinate space mappings, since search-backed tables no longer can assume those two things are the same; clang -> o2; fix clang build 2024-02-01 13:21:07 -08:00
Ryan Fleury 28fdd791ae extend eval viz blocks & windowed row build path with optional member info - use to extend watch type info visualization with size/offset information 2024-02-01 10:59:55 -08:00
Martins MozeikoandRyan Fleury d6608adf60 make msvc release build much faster
cl.exe for some reason spends unreasonable amount of time optimizing
df_window_update_and_render function,  we can use pragma to skip
optimization for this function
2024-02-01 09:53:14 -08:00
Ryan Fleury 45b59e4cc4 apply fuzzy filtering correctly to globals/thread-locals/types views 2024-01-31 15:06:20 -08:00
Ryan Fleury 02979ba26c first pass at equipping frontend line edit with fuzzy match range visualization; shift new debug-info-range viz block -> viz row path to using a backing filtered item array to map the abstract index space into the debug info table spaces 2024-01-31 14:54:49 -08:00
Ryan Fleury f3f0e2a697 plug in basic, half-finished filtering functionality to watch/locals/registers/types/globals/threadlocals views 2024-01-31 14:35:14 -08:00
Ryan Fleury 630272ec37 expand dbgi asynchronous fuzzy matching system to allow selection of target table; this allows asynchronous fuzzy matching over types, globals, thread locals, and procedures 2024-01-31 14:22:12 -08:00
Ryan Fleury 41b853b874 simplify fuzzy matching path to a single query 2024-01-31 14:07:16 -08:00
Ryan Fleury 071ff82673 introduce general-purpose filtering path for tabs; control whether or not it is enabled via view spec flags. + feature flags for automatically bring up filtering box when typing 2024-01-31 14:01:53 -08:00
Ryan Fleury 9106190893 first pass at types view 2024-01-31 12:31:09 -08:00
Ryan Fleury 8602e5b23e first pass at thread-locals view 2024-01-31 12:24:57 -08:00
Ryan Fleury c8010b7542 first pass at globals view 2024-01-31 12:17:43 -08:00
Ryan Fleury edb204bc5f eliminate old expand-key-based eval history - ctrl process memory cache offers much better comprehensive replacement. also eliminate per-row and per-block eval views, since we've collapsed all eval views to one per list-of-watch-trees 2024-01-31 11:12:59 -08:00
Ryan Fleury 2bf8179fee eliminate old registers/locals view states 2024-01-31 10:49:47 -08:00
Ryan Fleury 4e9cf2ef89 eliminate old locals view path; dont constantly mutate root expressions, simply query locals & build blocks 2024-01-31 10:48:49 -08:00
Ryan Fleury 14db7dbab4 stub out globals, thread-locals, types views; eliminate unnecssary uniquifier u64 in expand tree hash keys - simplify eval watch views to using a single eval view for the entire view, rather than allocating one per root expression. expand keys are now simply comprised of parent hash * child num 2024-01-31 10:39:18 -08:00
Ryan Fleury 8aac3f7bda escape textual string data before visualizing it in single-line eval visualization 2024-01-31 09:22:47 -08:00
Ryan Fleury 385014adcb raddbg nil tables, autofill empty tables with 1-sized nils; use element-from-idx wrapper to bounds-check and nilify all out-of-bounds raddbg table accesses 2024-01-31 08:43:33 -08:00
Ryan Fleury a6f42502ec symbol lister -> show procedure # in debug info, source location, name in tooltip; busyloop to wait to commit new fuzzy search results if scope touches active; sort fuzzy match results 2024-01-31 07:22:07 -08:00
Ryan Fleury 94d2be1683 some hover eval adjustments 2024-01-31 06:29:25 -08:00
Ryan Fleury 09f2b83603 fix function name breakpoint serialization 2024-01-31 06:20:49 -08:00
Ryan Fleury 00594a841a notes 2024-01-30 14:44:11 -08:00
Ryan Fleury 2731bdac59 extend fuzzy search cache nodes to having 3 buckets - 3rd bucket can be used to abort working copy, and speed an updated query along 2024-01-30 14:19:11 -08:00
Ryan Fleury 6e456424b0 handle thread name events correllated with only TID, without corresponding thread entity - correllate upon thread creation as-needed 2024-01-30 13:50:23 -08:00
Ryan Fleury c700264445 use explicit thread name exception thread ID parameter, when not implicit 2024-01-30 13:11:37 -08:00
Ryan Fleury d9f69cdf14 complete first pass of fuzzy matching symbol lister for go-to-name, and setting function breakpoints 2024-01-30 12:58:24 -08:00
Ryan Fleury 4ef814acb5 fix more tab bar stuff; further sketchout of asynchronous dbgi layer fuzzy searching 2024-01-30 09:57:15 -08:00
Ryan Fleury d139c2874c add optional command spec restriction to cmd param slot -> view spec table; eliminate mouse testing when windows are not focused 2024-01-30 09:14:59 -08:00
Ryan Fleury c61ff1910c split ui view clamp rule into separate x/y flags 2024-01-30 08:02:25 -08:00
Ryan Fleury c9b22acd5a sketch out symbol lister view; float fuzzy matching code into base string layer; bugfix unnecessary ui layer view clamping 2024-01-30 07:59:24 -08:00
Ryan Fleury 38af1a5cab fix bottom tab clipping 2024-01-30 06:52:03 -08:00
Ryan Fleury fe5f38c306 only retry findthread given missing debug info or RIP if ctrl thread is stopped 2024-01-30 06:33:16 -08:00
Ryan Fleury f130f23b3f include jmc line number hacks in line step-over and step-into trap-net 2024-01-30 06:18:02 -08:00
John LeidegrenandGitHub 0add3ef72c Merge branch 'master' into feature/odin 2024-01-21 15:59:23 +01:00
John LeidegrenandGitHub e417a96ce4 Fixed typo 2024-01-20 17:53:49 +01:00
John Leidegren b2262532a7 Fixed mistakes 2024-01-20 15:21:55 +01:00
John Leidegren b24326f502 Fixed formatting 2024-01-20 14:27:38 +01:00
John Leidegren 66c1fa337c Adds syntax colors to .odin files 2024-01-20 14:23:23 +01:00
68 changed files with 5565 additions and 3415 deletions
+4 -1
View File
@@ -46,7 +46,7 @@ set clang_common= -I..\src\ -I..\local\ -gcodeview -fdiagnostics-absolute-paths
set cl_debug= call cl /Od %cl_common% %auto_compile_flags%
set cl_release= call cl /O2 /DNDEBUG %cl_common% %auto_compile_flags%
set clang_debug= call clang -g -O0 %clang_common% %auto_compile_flags%
set clang_release= call clang -g -O3 -DNDEBUG %clang_common% %auto_compile_flags%
set clang_release= call clang -g -O2 -DNDEBUG %clang_common% %auto_compile_flags%
set cl_link= /link /MANIFEST:EMBED /INCREMENTAL:NO /natvis:"%~dp0\src\natvis\base.natvis" logo.res
set clang_link= -fuse-ld=lld -Xlinker /MANIFEST:EMBED -Xlinker /natvis:"%~dp0\src\natvis\base.natvis" logo.res
set cl_out= /out:
@@ -84,6 +84,9 @@ pushd build
%rc% /nologo /fo logo.res ..\data\logo.rc || exit /b 1
popd
:: --- Get Current Git Commit Id ----------------------------------------------
for /f %%i in ('call git describe --always --dirty') do set compile=%compile% -DRADDBG_GIT=\"%%i\"
:: --- Build & Run Metaprogram ------------------------------------------------
if "%no_meta%"=="1" echo [skipping metagen]
if not "%no_meta%"=="1" (
+9
View File
@@ -81,6 +81,15 @@ commands =
.save_dirty_files = true,
.cursor_at_end = false,
},
.build_raddbg_release_telemetry =
{
.win = "build raddbg release telemetry",
.linux = "",
.out = "*compilation*",
.footer_panel = true,
.save_dirty_files = true,
.cursor_at_end = false,
},
.build_raddbg_from_pdb =
{
.win = "build raddbg_from_pdb",
+16
View File
@@ -0,0 +1,16 @@
Clear-Host
$path_root = git rev-parse --show-toplevel
if ($IsWindows) {
$devshell = Join-Path $path_root 'scripts/helpers/devshell.ps1'
# This HandmadeHero implementation is only designed for 64-bit systems
& $devshell -arch amd64
}
Push-Location $path_root
$build_bat = Join-Path $path_root 'build.bat'
& $build_bat @args
Pop-Location
+10
View File
@@ -0,0 +1,10 @@
Clear-Host
$path_root = git rev-parse --show-toplevel
$build_dir = Join-Path $path_root 'build'
if (Test-Path $build_dir) {
Get-ChildItem -Path $build_dir -Recurse | Remove-Item -Force -Recurse
Write-Host "Build directory cleaned."
} else {
Write-Host "Build directory does not exist."
}
+28
View File
@@ -0,0 +1,28 @@
if ($env:VCINSTALLDIR) {
return
}
$ErrorActionPreference = "Stop"
# Use vswhere to find the latest Visual Studio installation
$vswhere_out = & "C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" -latest -property installationPath
if ($null -eq $vswhere_out) {
Write-Host "ERROR: Visual Studio installation not found"
exit 1
}
# Find Launch-VsDevShell.ps1 in the Visual Studio installation
$vs_path = $vswhere_out
$vs_devshell = Join-Path $vs_path "\Common7\Tools\Launch-VsDevShell.ps1"
if ( -not (Test-Path $vs_devshell) ) {
Write-Host "ERROR: Launch-VsDevShell.ps1 not found in Visual Studio installation"
Write-Host Tested path: $vs_devshell
exit 1
}
# Launch the Visual Studio Developer Shell
Push-Location
write-host @args
& $vs_devshell @args
Pop-Location
+16 -17
View File
@@ -10,44 +10,44 @@ arena_alloc__sized(U64 init_res, U64 init_cmt)
ProfBeginFunction();
Assert(ARENA_HEADER_SIZE < init_cmt && init_cmt <= init_res);
void *memory;
U64 res;
U64 cmt;
void *memory = 0;
U64 res = 0;
U64 cmt = 0;
B32 large_pages = os_large_pages_enabled();
if (large_pages) {
if(large_pages)
{
U64 page_size = os_large_page_size();
res = AlignPow2(init_res, page_size);
#if OS_WINDOWS
cmt = res;
#else
cmt = AlignPow2(init_cmt, page_size);
#endif
memory = os_reserve_large(res);
if (!os_commit_large(memory, cmt)) {
if(!os_commit_large(memory, cmt))
{
memory = 0;
os_release(memory, res);
}
} else {
}
else
{
U64 page_size = os_page_size();
res = AlignPow2(init_res, page_size);
cmt = AlignPow2(init_cmt, page_size);
memory = os_reserve(res);
if (!os_commit(memory, cmt)) {
if(!os_commit(memory, cmt))
{
memory = 0;
os_release(memory, res);
}
}
Assert(memory);
AsanPoisonMemoryRegion(memory, cmt);
AsanUnpoisonMemoryRegion(memory, ARENA_HEADER_SIZE);
Arena *arena = (Arena*)memory;
if (arena) {
if(arena)
{
AsanPoisonMemoryRegion(memory, cmt);
AsanUnpoisonMemoryRegion(memory, ARENA_HEADER_SIZE);
arena->prev = 0;
arena->current = arena;
arena->base_pos = 0;
@@ -148,7 +148,6 @@ arena_push__impl(Arena *arena, U64 size)
cmt_new_size = cmt_new_clamped - current->cmt;
is_cmt_ok = os_commit((U8*)current + current->cmt, cmt_new_size);
}
Assert(is_cmt_ok);
if (is_cmt_ok) {
current->cmt = cmt_new_clamped;
+61 -60
View File
@@ -406,13 +406,11 @@ push_str8_cat(Arena *arena, String8 s1, String8 s2){
internal String8
push_str8_copy(Arena *arena, String8 s){
//ProfBeginFunction();
String8 str;
str.size = s.size;
str.str = push_array_no_zero(arena, U8, str.size + 1);
MemoryCopy(str.str, s.str, s.size);
str.str[str.size] = 0;
//ProfEnd();
return(str);
}
@@ -543,64 +541,6 @@ try_s64_from_str8_c_rules(String8 string, S64 *x){
return(is_integer);
}
//- rjf: string -> integer (base64 & base16)
internal U64
base64_size_from_data_size(U64 size_in_bytes){
U64 bits = size_in_bytes*8;
U64 base64_size = (bits + 5)/6;
return(base64_size);
}
internal U64
base64_from_data(U8 *dst, U8 *src, U64 src_size){
U8 *dst_base = dst;
U8 *opl = src + src_size;
U32 bit_num = 0;
if (src < opl){
U8 byte = *src;
for (;;){
U32 x = 0;
for (U32 i = 0; i < 6; i += 1){
x |= ((byte >> bit_num) & 1) << i;
bit_num += 1;
if (bit_num == 8){
bit_num = 0;
src += 1;
byte = (src < opl)?(*src):0;
}
}
*dst = base64[x];
dst += 1;
if (src >= opl){
break;
}
}
}
return(dst - dst_base);
}
internal U64
base16_size_from_data_size(U64 size_in_bytes){
U64 base16_size = size_in_bytes*2;
return(base16_size);
}
internal U64
base16_from_data(U8 *dst, U8 *src, U64 src_size){
U8 *dst_base = dst;
U8 *opl = src + src_size;
for (;src < opl;){
U8 byte = *src;
*dst = integer_symbols[byte & 0xF];
dst += 1;
*dst = integer_symbols[byte >> 4];
dst += 1;
src += 1;
}
return(dst - dst_base);
}
//- rjf: integer -> string
internal String8
@@ -1657,6 +1597,67 @@ rgba_from_hex_string_4f32(String8 hex_string)
return rgba;
}
////////////////////////////////
//~ rjf: String Fuzzy Matching
internal FuzzyMatchRangeList
fuzzy_match_find(Arena *arena, String8 needle, String8 haystack)
{
FuzzyMatchRangeList result = {0};
Temp scratch = scratch_begin(&arena, 1);
String8List needles = str8_split(scratch.arena, needle, (U8*)" ", 1, 0);
result.needle_part_count = needles.node_count;
for(String8Node *needle_n = needles.first; needle_n != 0; needle_n = needle_n->next)
{
U64 find_pos = 0;
for(;find_pos < haystack.size;)
{
find_pos = str8_find_needle(haystack, find_pos, needle_n->string, StringMatchFlag_CaseInsensitive);
B32 is_in_gathered_ranges = 0;
for(FuzzyMatchRangeNode *n = result.first; n != 0; n = n->next)
{
if(n->range.min <= find_pos && find_pos < n->range.max)
{
is_in_gathered_ranges = 1;
find_pos = n->range.max;
break;
}
}
if(!is_in_gathered_ranges)
{
break;
}
}
if(find_pos < haystack.size)
{
Rng1U64 range = r1u64(find_pos, find_pos+needle_n->string.size);
FuzzyMatchRangeNode *n = push_array(arena, FuzzyMatchRangeNode, 1);
n->range = range;
SLLQueuePush(result.first, result.last, n);
result.count += 1;
result.total_dim += dim_1u64(range);
}
}
scratch_end(scratch);
return result;
}
internal FuzzyMatchRangeList
fuzzy_match_range_list_copy(Arena *arena, FuzzyMatchRangeList *src)
{
FuzzyMatchRangeList dst = {0};
for(FuzzyMatchRangeNode *src_n = src->first; src_n != 0; src_n = src_n->next)
{
FuzzyMatchRangeNode *dst_n = push_array(arena, FuzzyMatchRangeNode, 1);
SLLQueuePush(dst.first, dst.last, dst_n);
dst_n->range = src_n->range;
}
dst.count = src->count;
dst.needle_part_count = src->needle_part_count;
dst.total_dim = src->total_dim;
return dst;
}
////////////////////////////////
//~ NOTE(allen): Serialization Helpers
+26 -6
View File
@@ -128,6 +128,26 @@ struct UnicodeDecode
U32 codepoint;
};
////////////////////////////////
//~ rjf: String Fuzzy Matching Types
typedef struct FuzzyMatchRangeNode FuzzyMatchRangeNode;
struct FuzzyMatchRangeNode
{
FuzzyMatchRangeNode *next;
Rng1U64 range;
};
typedef struct FuzzyMatchRangeList FuzzyMatchRangeList;
struct FuzzyMatchRangeList
{
FuzzyMatchRangeNode *first;
FuzzyMatchRangeNode *last;
U64 count;
U64 needle_part_count;
U64 total_dim;
};
////////////////////////////////
//~ rjf: Character Classification & Conversion Functions
@@ -216,12 +236,6 @@ internal S64 s64_from_str8(String8 string, U32 radix);
internal B32 try_u64_from_str8_c_rules(String8 string, U64 *x);
internal B32 try_s64_from_str8_c_rules(String8 string, S64 *x);
//- rjf: string -> integer (base64 & base16)
internal U64 base64_size_from_data_size(U64 size_in_bytes);
internal U64 base64_from_data(U8 *dst, U8 *src, U64 src_size);
internal U64 base16_size_from_data_size(U64 size_in_bytes);
internal U64 base16_from_data(U8 *dst, U8 *src, U64 src_size);
//- rjf: integer -> string
internal String8 str8_from_memory_size(Arena *arena, U64 z);
internal String8 str8_from_u64(Arena *arena, U64 u64, U32 radix, U8 min_digits, U8 digit_group_separator);
@@ -318,6 +332,12 @@ internal String8 string_from_elapsed_time(Arena *arena, DateTime dt);
internal String8 hex_string_from_rgba_4f32(Arena *arena, Vec4F32 rgba);
internal Vec4F32 rgba_from_hex_string_4f32(String8 hex_string);
////////////////////////////////
//~ rjf: String Fuzzy Matching
internal FuzzyMatchRangeList fuzzy_match_find(Arena *arena, String8 needle, String8 haystack);
internal FuzzyMatchRangeList fuzzy_match_range_list_copy(Arena *arena, FuzzyMatchRangeList *src);
////////////////////////////////
//~ NOTE(allen): Serialization Helpers
+287 -198
View File
@@ -35,6 +35,7 @@ ctrl_init(CTRL_WakeupFunctionType *wakeup_hook)
for(U64 idx = 0; idx < ctrl_state->process_memory_cache.stripes_count; idx += 1)
{
ctrl_state->process_memory_cache.stripes[idx].rw_mutex = os_rw_mutex_alloc();
ctrl_state->process_memory_cache.stripes[idx].cv = os_condition_variable_alloc();
}
ctrl_state->u2c_ring_size = KB(64);
ctrl_state->u2c_ring_base = push_array_no_zero(arena, U8, ctrl_state->u2c_ring_size);
@@ -58,7 +59,7 @@ ctrl_init(CTRL_WakeupFunctionType *wakeup_hook)
ctrl_state->u2ms_ring_mutex = os_mutex_alloc();
ctrl_state->u2ms_ring_cv = os_condition_variable_alloc();
ctrl_state->ctrl_thread = os_launch_thread(ctrl_thread__entry_point, 0, 0);
ctrl_state->ms_thread_count = Min(4, os_logical_core_count()-1);
ctrl_state->ms_thread_count = Clamp(1, os_logical_core_count()-1, 4);
ctrl_state->ms_threads = push_array(arena, OS_Handle, ctrl_state->ms_thread_count);
for(U64 idx = 0; idx < ctrl_state->ms_thread_count; idx += 1)
{
@@ -242,9 +243,8 @@ ctrl_append_resolved_module_user_bp_traps(Arena *arena, DEMON_Handle process, DE
}
// rjf: src_id * pt -> push
if(0 < src_id && src_id < rdbg->source_file_count)
{
RADDBG_SourceFile *src = rdbg->source_files + src_id;
RADDBG_SourceFile *src = raddbg_element_from_idx(rdbg, source_files, src_id);
RADDBG_ParsedLineMap line_map = {0};
raddbg_line_map_from_source_file(rdbg, src, &line_map);
U32 voff_count = 0;
@@ -760,10 +760,73 @@ ctrl_process_write(CTRL_MachineID machine_id, CTRL_Handle process, Rng1U64 range
ProfBeginFunction();
U64 size = dim_1u64(range);
B32 result = demon_write_memory(ctrl_demon_handle_from_ctrl(process), range.min, src, size);
//- rjf: success -> increment memgen
if(result)
{
ins_atomic_u64_inc_eval(&ctrl_state->memgen_idx);
}
//- rjf: success -> wait for cache updates, for small regions - prefer relatively seamless
// writes within calling frame's "view" of the memory, at the expense of a small amount of
// time.
if(result)
{
Temp scratch = scratch_begin(0, 0);
U64 endt_us = os_now_microseconds()+5000;
//- rjf: gather tasks for all affected cached regions
typedef struct Task Task;
struct Task
{
Task *next;
CTRL_MachineID machine_id;
CTRL_Handle process;
Rng1U64 range;
};
Task *first_task = 0;
Task *last_task = 0;
CTRL_ProcessMemoryCache *cache = &ctrl_state->process_memory_cache;
for(U64 slot_idx = 0; slot_idx < cache->slots_count; slot_idx += 1)
{
U64 stripe_idx = slot_idx%cache->stripes_count;
CTRL_ProcessMemoryCacheSlot *slot = &cache->slots[slot_idx];
CTRL_ProcessMemoryCacheStripe *stripe = &cache->stripes[stripe_idx];
OS_MutexScopeW(stripe->rw_mutex)
{
for(CTRL_ProcessMemoryCacheNode *proc_n = slot->first; proc_n != 0; proc_n = proc_n->next)
{
for(U64 range_hash_idx = 0; range_hash_idx < proc_n->range_hash_slots_count; range_hash_idx += 1)
{
CTRL_ProcessMemoryRangeHashSlot *range_slot = &proc_n->range_hash_slots[range_hash_idx];
for(CTRL_ProcessMemoryRangeHashNode *n = range_slot->first; n != 0; n = n->next)
{
Rng1U64 intersection_w_range = intersect_1u64(range, n->vaddr_range);
if(dim_1u64(intersection_w_range) != 0 && dim_1u64(n->vaddr_range) <= KB(64))
{
Task *task = push_array(scratch.arena, Task, 1);
task->machine_id = proc_n->machine_id;
task->process = proc_n->process;
task->range = n->vaddr_range;
SLLQueuePush(first_task, last_task, task);
}
}
}
}
}
}
//- rjf: for all tasks, wait for up-to-date results
for(Task *task = first_task; task != 0; task = task->next)
{
Temp temp = temp_begin(scratch.arena);
ctrl_query_cached_data_from_process_vaddr_range(temp.arena, task->machine_id, task->process, task->range, endt_us);
temp_end(temp);
}
scratch_end(scratch);
}
ProfEnd();
return result;
}
@@ -786,11 +849,11 @@ ctrl_hash_store_key_from_process_vaddr_range(CTRL_MachineID machine_id, CTRL_Han
}
internal U128
ctrl_stored_hash_from_process_vaddr_range(CTRL_MachineID machine_id, CTRL_Handle process, Rng1U64 range, B32 zero_terminated)
ctrl_stored_hash_from_process_vaddr_range(CTRL_MachineID machine_id, CTRL_Handle process, Rng1U64 range, B32 zero_terminated, U64 endt_us)
{
U128 result = {0};
U64 size = dim_1u64(range);
if(size != 0)
if(size != 0) for(;;)
{
CTRL_ProcessMemoryCache *cache = &ctrl_state->process_memory_cache;
U64 process_hash = ctrl_hash_from_string(str8_struct(&process));
@@ -805,23 +868,31 @@ ctrl_stored_hash_from_process_vaddr_range(CTRL_MachineID machine_id, CTRL_Handle
B32 is_stale = 0;
OS_MutexScopeR(process_stripe->rw_mutex)
{
for(CTRL_ProcessMemoryCacheNode *n = process_slot->first; n != 0; n = n->next)
for(;;)
{
if(n->machine_id == machine_id && ctrl_handle_match(n->process, process))
for(CTRL_ProcessMemoryCacheNode *n = process_slot->first; n != 0; n = n->next)
{
U64 range_slot_idx = range_hash%n->range_hash_slots_count;
CTRL_ProcessMemoryRangeHashSlot *range_slot = &n->range_hash_slots[range_slot_idx];
for(CTRL_ProcessMemoryRangeHashNode *range_n = range_slot->first; range_n != 0; range_n = range_n->next)
if(n->machine_id == machine_id && ctrl_handle_match(n->process, process))
{
if(MemoryMatchStruct(&range_n->vaddr_range, &range) && range_n->zero_terminated == zero_terminated)
U64 range_slot_idx = range_hash%n->range_hash_slots_count;
CTRL_ProcessMemoryRangeHashSlot *range_slot = &n->range_hash_slots[range_slot_idx];
for(CTRL_ProcessMemoryRangeHashNode *range_n = range_slot->first; range_n != 0; range_n = range_n->next)
{
result = range_n->hash;
is_good = 1;
is_stale = range_n->memgen_idx < ctrl_memgen_idx();
goto read_cache__break_all;
if(MemoryMatchStruct(&range_n->vaddr_range, &range) && range_n->zero_terminated == zero_terminated)
{
result = range_n->hash;
is_good = 1;
is_stale = range_n->memgen_idx < ctrl_memgen_idx();
goto read_cache__break_all;
}
}
}
}
if(os_now_microseconds() >= endt_us)
{
break;
}
os_condition_variable_wait_rw_r(process_stripe->cv, process_stripe->rw_mutex, endt_us);
}
read_cache__break_all:;
}
@@ -880,6 +951,12 @@ ctrl_stored_hash_from_process_vaddr_range(CTRL_MachineID machine_id, CTRL_Handle
SLLQueuePush(range_slot->first, range_slot->last, range_n);
range_n->vaddr_range = range;
range_n->zero_terminated = zero_terminated;
range_n->vaddr_range_clamped = range;
{
range_n->vaddr_range_clamped.max = Max(range_n->vaddr_range_clamped.max, range_n->vaddr_range_clamped.min);
U64 max_size_cap = Min(max_U64-range_n->vaddr_range_clamped.min, GB(1));
range_n->vaddr_range_clamped.max = Min(range_n->vaddr_range_clamped.max, range_n->vaddr_range_clamped.min+max_size_cap);
}
break;
}
}
@@ -890,7 +967,13 @@ ctrl_stored_hash_from_process_vaddr_range(CTRL_MachineID machine_id, CTRL_Handle
//- rjf: not good, or is stale -> submit hash request
if(!is_good || is_stale)
{
ctrl_u2ms_enqueue_req(machine_id, process, range, zero_terminated, 0);
ctrl_u2ms_enqueue_req(machine_id, process, range, zero_terminated, endt_us);
}
//- rjf: out of time? -> exit
if(os_now_microseconds() >= endt_us)
{
break;
}
}
return result;
@@ -899,11 +982,9 @@ ctrl_stored_hash_from_process_vaddr_range(CTRL_MachineID machine_id, CTRL_Handle
//- rjf: process memory cache reading helpers
internal CTRL_ProcessMemorySlice
ctrl_query_cached_data_from_process_vaddr_range(Arena *arena, CTRL_MachineID machine_id, CTRL_Handle process, Rng1U64 range)
ctrl_query_cached_data_from_process_vaddr_range(Arena *arena, CTRL_MachineID machine_id, CTRL_Handle process, Rng1U64 range, U64 endt_us)
{
CTRL_ProcessMemorySlice result = {0};
result.byte_bad_flags = push_array(arena, U64, (dim_1u64(range)+63)/64);
result.byte_changed_flags = push_array(arena, U64, (dim_1u64(range)+63)/64);
if(range.max > range.min &&
dim_1u64(range) <= MB(256) &&
range.min <= 0x000FFFFFFFFFFFFFull &&
@@ -925,7 +1006,7 @@ ctrl_query_cached_data_from_process_vaddr_range(Arena *arena, CTRL_MachineID mac
{
U64 page_base_vaddr = page_range.min + page_idx*page_size;
U128 page_key = ctrl_hash_store_key_from_process_vaddr_range(machine_id, process, r1u64(page_base_vaddr, page_base_vaddr+page_size), 0);
U128 page_hash = ctrl_stored_hash_from_process_vaddr_range(machine_id, process, r1u64(page_base_vaddr, page_base_vaddr+page_size), 0);
U128 page_hash = ctrl_stored_hash_from_process_vaddr_range(machine_id, process, r1u64(page_base_vaddr, page_base_vaddr+page_size), 0, endt_us);
U128 page_last_hash = hs_hash_from_key(page_key, 1);
page_hashes[page_idx] = page_hash;
page_last_hashes[page_idx] = page_last_hash;
@@ -933,8 +1014,8 @@ ctrl_query_cached_data_from_process_vaddr_range(Arena *arena, CTRL_MachineID mac
//- rjf: setup output buffers
void *read_out = push_array(arena, U8, dim_1u64(range));
U64 *byte_bad_flags = result.byte_bad_flags;
U64 *byte_changed_flags = result.byte_changed_flags;
U64 *byte_bad_flags = push_array(arena, U64, (dim_1u64(range)+63)/64);
U64 *byte_changed_flags = push_array(arena, U64, (dim_1u64(range)+63)/64);
//- rjf: iterate pages, fill output
{
@@ -959,6 +1040,22 @@ ctrl_query_cached_data_from_process_vaddr_range(Arena *arena, CTRL_MachineID mac
// rjf: write this chunk
MemoryCopy((U8*)read_out+write_off, in_range_data.str, in_range_data.size);
// rjf; if this page's data doesn't fill the entire range, mark
// missing bytes as bad
if(data.size < page_size)
{
for(U64 invalid_vaddr = data_vaddr_range.min+data.size;
invalid_vaddr < data_vaddr_range.min + page_size;
invalid_vaddr += 1)
{
if(contains_1u64(range, invalid_vaddr))
{
U64 idx_in_range = invalid_vaddr-range.min;
byte_bad_flags[idx_in_range/64] |= (1ull<<(idx_in_range%64));
}
}
}
// rjf: if this page's hash & last_hash don't match, diff each byte &
// fill out changed flags
if(!u128_match(page_hashes[page_idx], page_last_hashes[page_idx]))
@@ -1010,7 +1107,7 @@ ctrl_query_cached_data_from_process_vaddr_range(Arena *arena, CTRL_MachineID mac
internal CTRL_ProcessMemorySlice
ctrl_query_cached_zero_terminated_data_from_process_vaddr_limit(Arena *arena, CTRL_MachineID machine_id, CTRL_Handle process, U64 vaddr, U64 limit, U64 endt_us)
{
CTRL_ProcessMemorySlice result = ctrl_query_cached_data_from_process_vaddr_range(arena, machine_id, process, r1u64(vaddr, vaddr+limit));
CTRL_ProcessMemorySlice result = ctrl_query_cached_data_from_process_vaddr_range(arena, machine_id, process, r1u64(vaddr, vaddr+limit), endt_us);
for(U64 idx = 0; idx < result.data.size; idx += 1)
{
if(result.data.str[idx] == 0)
@@ -1187,7 +1284,7 @@ ctrl_unwind_from_process_thread(Arena *arena, CTRL_MachineID machine_id, CTRL_Ha
frame->rip = rip;
frame->regs = push_array_no_zero(arena, U8, arch_reg_block_size);
MemoryCopy(frame->regs, regs_block, arch_reg_block_size);
SLLQueuePush(unwind.first, unwind.last, frame);
DLLPushBack(unwind.first, unwind.last, frame);
unwind.count += 1;
// rjf: unwind one step
@@ -1553,9 +1650,9 @@ ctrl_thread__next_demon_event(Arena *arena, CTRL_Msg *msg, DEMON_RunCtrls *run_c
{
U32 id_count = 0;
U32 *ids = raddbg_matches_from_map_node(rdbg, node, &id_count);
if(id_count > 0 && 0 < ids[0] && ids[0] < rdbg->global_variable_count)
if(id_count > 0)
{
RADDBG_GlobalVariable *global_var = &rdbg->global_variables[ids[0]];
RADDBG_GlobalVariable *global_var = raddbg_element_from_idx(rdbg, global_variables, ids[0]);
U64 global_var_voff = global_var->voff;
U64 global_var_vaddr = global_var->voff + demon_base_vaddr_from_module(ctrl_demon_handle_from_ctrl(module));
Architecture arch = demon_arch_from_object(ev->thread);
@@ -1770,6 +1867,7 @@ ctrl_thread__next_demon_event(Arena *arena, CTRL_Msg *msg, DEMON_RunCtrls *run_c
out_evt->entity = ctrl_handle_from_demon(event->thread);
out_evt->parent = ctrl_handle_from_demon(event->process);
out_evt->string = event->string;
out_evt->entity_id = event->code;
}break;
}
ctrl_c2u_push_events(&evts);
@@ -1934,7 +2032,9 @@ ctrl_thread__launch_and_init(CTRL_Msg *msg)
ProfBeginFunction();
Temp scratch = scratch_begin(0, 0);
//////////////////////////////
//- rjf: launch
//
OS_LaunchOptions opts = {0};
{
opts.cmd_line = msg->cmd_line_string_list;
@@ -1944,7 +2044,9 @@ ctrl_thread__launch_and_init(CTRL_Msg *msg)
}
U32 id = demon_launch_process(&opts);
//////////////////////////////
//- rjf: record start
//
{
CTRL_EventList evts = {0};
CTRL_Event *event = ctrl_event_list_push(scratch.arena, &evts);
@@ -1952,14 +2054,13 @@ ctrl_thread__launch_and_init(CTRL_Msg *msg)
ctrl_c2u_push_events(&evts);
}
//////////////////////////////
//- rjf: run to initialization (entry point)
//
DEMON_Event *stop_event = 0;
if(id != 0)
{
DEMON_Handle unfrozen_process[8] = {0};
DEMON_TrapChunkList demon_traps = {0};
U64 entry_vaddr = 0;
DEMON_Handle entry_vaddr_proc = 0;
DEMON_RunCtrls run_ctrls = {0};
run_ctrls.run_entities_are_unfrozen = 1;
run_ctrls.run_entities_are_processes = 1;
@@ -1970,7 +2071,7 @@ ctrl_thread__launch_and_init(CTRL_Msg *msg)
{
default:{}break;
// rjf: new process -> freeze process
//- rjf: new process -> freeze process
case DEMON_EventKind_CreateProcess:
if(run_ctrls.run_entity_count < ArrayCount(unfrozen_process))
{
@@ -1979,22 +2080,32 @@ ctrl_thread__launch_and_init(CTRL_Msg *msg)
run_ctrls.run_entity_count += 1;
}break;
// rjf: breakpoint -> if it's the entry point, we're done. otherwise, keep going
//- rjf: breakpoint -> if it's the entry point, we're done. otherwise, keep going
case DEMON_EventKind_Breakpoint:
if(event->instruction_pointer == entry_vaddr)
{
done = 1;
stop_event = event;
for(DEMON_TrapChunkNode *n = run_ctrls.traps.first; n != 0; n = n->next)
{
for(U64 idx = 0; idx < n->count; idx += 1)
{
if(n->v[idx].address == event->instruction_pointer)
{
done = 1;
stop_event = event;
goto end_look_for_entry_match;
}
}
}
end_look_for_entry_match:;
}break;
// rjf: exception -> done
//- rjf: exception -> done
case DEMON_EventKind_Exception:
{
done = 1;
stop_event = event;
}break;
// rjf: process ended? -> remove from unfrozen processes. zero processes -> done.
//- rjf: process ended? -> remove from unfrozen processes. zero processes -> done.
case DEMON_EventKind_ExitProcess:
{
for(U64 idx = 0; idx < run_ctrls.run_entity_count; idx += 1)
@@ -2006,7 +2117,10 @@ ctrl_thread__launch_and_init(CTRL_Msg *msg)
break;
}
}
run_ctrls.run_entity_count -= 1;
if(run_ctrls.run_entity_count > 0)
{
run_ctrls.run_entity_count -= 1;
}
if(run_ctrls.run_entity_count == 0)
{
done = 1;
@@ -2014,123 +2128,29 @@ ctrl_thread__launch_and_init(CTRL_Msg *msg)
}
}break;
// rjf: done with handshake -> ready to find entry point. search launched processes
//- rjf: done with handshake -> ready to find entry point. search launched processes
case DEMON_EventKind_HandshakeComplete:
{
DBGI_Scope *scope = dbgi_scope_open();
// rjf: find entry point vaddr
//- rjf: add traps for all possible entry points
for(U64 process_idx = 0; process_idx < run_ctrls.run_entity_count; process_idx += 1)
{
//- rjf: unpack first module info
DEMON_HandleArray modules = demon_modules_from_process(scratch.arena, run_ctrls.run_entities[process_idx]);
if(modules.count == 0) { continue; }
DEMON_Handle module = modules.handles[0];
U64 module_base_vaddr = demon_base_vaddr_from_module(module);
String8 exe_path = demon_full_path_from_module(scratch.arena, module);
DBGI_Parse *dbgi = dbgi_parse_from_exe_path(scope, exe_path, max_U64);
RADDBG_Parsed *rdbg = &dbgi->rdbg;
RADDBG_NameMap *unparsed_map = raddbg_name_map_from_kind(rdbg, RADDBG_NameMapKind_Procedures);
RADDBG_ParsedNameMap map = {0};
raddbg_name_map_parse(rdbg, unparsed_map, &map);
String8 default_entry_points[] =
{
str8_lit("WinMain"),
str8_lit("wWinMain"),
str8_lit("main"),
str8_lit("wmain"),
str8_lit("WinMainCRTStartup"),
str8_lit("wWinMainCRTStartup"),
str8_lit("mainCRTStartup"),
str8_lit("wmainCRTStartup"),
};
// rjf: default to picking PE header's entry
B32 entry_is_user_defined = 0;
U64 entry_voff = dbgi->pe.entry_point;
if(rdbg->scope_vmap != 0 && rdbg->procedures != 0 &&
rdbg->unit_vmap != 0 && rdbg->units != 0 &&
rdbg->file_paths)
{
U64 scope_idx = raddbg_vmap_idx_from_voff(rdbg->scope_vmap, rdbg->scope_vmap_count, entry_voff);
RADDBG_Scope *scope = &rdbg->scopes[scope_idx];
U64 proc_idx = scope->proc_idx;
RADDBG_Procedure *procedure = &rdbg->procedures[proc_idx];
U64 name_size = 0;
U8 *name_base = raddbg_string_from_idx(rdbg, procedure->name_string_idx, &name_size);
String8 name = str8(name_base, name_size);
U64 unit_idx = raddbg_vmap_idx_from_voff(rdbg->unit_vmap, rdbg->unit_vmap_count, entry_voff);
RADDBG_Unit *unit = &rdbg->units[unit_idx];
RADDBG_ParsedLineInfo unit_line_info = {0};
raddbg_line_info_from_unit(rdbg, unit, &unit_line_info);
U64 line_info_idx = raddbg_line_info_idx_from_voff(&unit_line_info, entry_voff);
if(name_size != 0 && line_info_idx < unit_line_info.count)
{
String8 obj_path = {0};
{
String8List obj_path_nodes = {0};
for(U32 idx = unit->object_file_path_node; idx != 0; idx = rdbg->file_paths[idx].parent_path_node)
{
RADDBG_FilePathNode *n = &rdbg->file_paths[idx];
U64 n_name_size = 0;
U8 *n_name_base = raddbg_string_from_idx(rdbg, n->name_string_idx, &n_name_size);
str8_list_push_front(scratch.arena, &obj_path_nodes, str8(n_name_base, n_name_size));
}
StringJoin join = {0};
join.sep = str8_lit("/");
obj_path = str8_list_join(scratch.arena, &obj_path_nodes, &join);
}
FileProperties props = os_properties_from_file_path(obj_path);
if(props.modified)
{
entry_is_user_defined = 1;
}
}
B32 entry_point_matches_defaults = 0;
for(U64 idx = 0; idx < ArrayCount(default_entry_points); idx += 1)
{
if(str8_match(name, default_entry_points[idx], 0))
{
entry_point_matches_defaults = 1;
}
}
if(!entry_point_matches_defaults && name.size != 0)
{
entry_is_user_defined = 1;
}
}
// rjf: find voff for one of the default entry points
if(!entry_is_user_defined)
{
for(U64 idx = 0; idx < ArrayCount(default_entry_points); idx += 1)
{
U32 procedure_id = 0;
{
String8 name = default_entry_points[idx];
RADDBG_NameMapNode *node = raddbg_name_map_lookup(rdbg, &map, name.str, name.size);
if(node != 0)
{
U32 id_count = 0;
U32 *ids = raddbg_matches_from_map_node(rdbg, node, &id_count);
if(id_count > 0)
{
procedure_id = ids[0];
}
}
}
if(procedure_id != 0)
{
U64 new_voff = raddbg_first_voff_from_proc(rdbg, procedure_id);
if(new_voff != 0)
{
entry_voff = new_voff;
break;
}
}
}
}
// rjf: find voff for one of the custom entry points attached to this msg
if(rdbg->procedures != 0 && unparsed_map != 0)
//- rjf: add trap for user-specified entry point, if specified
B32 entries_found = 0;
if(!entries_found)
{
for(String8Node *n = msg->strings.first; n != 0; n = n->next)
{
@@ -2138,30 +2158,25 @@ ctrl_thread__launch_and_init(CTRL_Msg *msg)
{
String8 name = n->string;
RADDBG_NameMapNode *node = raddbg_name_map_lookup(rdbg, &map, name.str, name.size);
if(node != 0)
U32 id_count = 0;
U32 *ids = raddbg_matches_from_map_node(rdbg, node, &id_count);
if(id_count > 0)
{
U32 id_count = 0;
U32 *ids = raddbg_matches_from_map_node(rdbg, node, &id_count);
if(id_count > 0)
{
procedure_id = ids[0];
}
procedure_id = ids[0];
}
}
if(procedure_id != 0)
U64 voff = raddbg_first_voff_from_proc(rdbg, procedure_id);
if(voff != 0)
{
U64 new_voff = raddbg_first_voff_from_proc(rdbg, procedure_id);
if(new_voff != 0)
{
entry_voff = new_voff;
break;
}
entries_found = 1;
DEMON_Trap trap = {run_ctrls.run_entities[process_idx], module_base_vaddr + voff};
demon_trap_chunk_list_push(scratch.arena, &run_ctrls.traps, 256, &trap);
}
}
}
// rjf: find voff for one of the user's custom entry points
if(rdbg->procedures != 0 && unparsed_map != 0)
//- rjf: add traps for all custom user entry points
if(!entries_found)
{
for(String8Node *n = ctrl_state->user_entry_points.first; n != 0; n = n->next)
{
@@ -2169,46 +2184,102 @@ ctrl_thread__launch_and_init(CTRL_Msg *msg)
{
String8 name = n->string;
RADDBG_NameMapNode *node = raddbg_name_map_lookup(rdbg, &map, name.str, name.size);
if(node != 0)
U32 id_count = 0;
U32 *ids = raddbg_matches_from_map_node(rdbg, node, &id_count);
if(id_count > 0)
{
U32 id_count = 0;
U32 *ids = raddbg_matches_from_map_node(rdbg, node, &id_count);
if(id_count > 0)
{
procedure_id = ids[0];
}
procedure_id = ids[0];
}
}
if(procedure_id != 0)
U64 voff = raddbg_first_voff_from_proc(rdbg, procedure_id);
if(voff != 0)
{
U64 new_voff = raddbg_first_voff_from_proc(rdbg, procedure_id);
if(new_voff != 0)
{
entry_voff = new_voff;
break;
}
DEMON_Trap trap = {run_ctrls.run_entities[process_idx], module_base_vaddr + voff};
demon_trap_chunk_list_push(scratch.arena, &run_ctrls.traps, 256, &trap);
break;
}
}
}
// rjf: nonzero voff? => store
if(entry_voff != 0)
//- rjf: add traps for all high-level entry points
if(!entries_found)
{
U64 base_vaddr = demon_base_vaddr_from_module(module);
entry_vaddr = base_vaddr + entry_voff;
entry_vaddr_proc = run_ctrls.run_entities[process_idx];
String8 hi_entry_points[] =
{
str8_lit("WinMain"),
str8_lit("wWinMain"),
str8_lit("main"),
str8_lit("wmain"),
};
for(U64 idx = 0; idx < ArrayCount(hi_entry_points); idx += 1)
{
U32 procedure_id = 0;
{
String8 name = hi_entry_points[idx];
RADDBG_NameMapNode *node = raddbg_name_map_lookup(rdbg, &map, name.str, name.size);
U32 id_count = 0;
U32 *ids = raddbg_matches_from_map_node(rdbg, node, &id_count);
if(id_count > 0)
{
procedure_id = ids[0];
}
}
U64 voff = raddbg_first_voff_from_proc(rdbg, procedure_id);
if(voff != 0)
{
entries_found = 1;
DEMON_Trap trap = {run_ctrls.run_entities[process_idx], module_base_vaddr + voff};
demon_trap_chunk_list_push(scratch.arena, &run_ctrls.traps, 256, &trap);
}
}
}
// rjf: found entry point -> insert into trap controls
if(entry_vaddr != 0)
//- rjf: add trap for PE header entry
if(!entries_found)
{
DEMON_Trap trap = {entry_vaddr_proc, entry_vaddr};
demon_trap_chunk_list_push(scratch.arena, &demon_traps, 256, &trap);
run_ctrls.traps = demon_traps;
U64 voff = dbgi->pe.entry_point;
if(voff != 0)
{
DEMON_Trap trap = {run_ctrls.run_entities[process_idx], module_base_vaddr + voff};
demon_trap_chunk_list_push(scratch.arena, &run_ctrls.traps, 256, &trap);
}
}
// rjf: no entry point found -> done
else
//- rjf: add traps for all low-level entry points
if(!entries_found)
{
String8 lo_entry_points[] =
{
str8_lit("WinMainCRTStartup"),
str8_lit("wWinMainCRTStartup"),
str8_lit("mainCRTStartup"),
str8_lit("wmainCRTStartup"),
};
for(U64 idx = 0; idx < ArrayCount(lo_entry_points); idx += 1)
{
U32 procedure_id = 0;
{
String8 name = lo_entry_points[idx];
RADDBG_NameMapNode *node = raddbg_name_map_lookup(rdbg, &map, name.str, name.size);
U32 id_count = 0;
U32 *ids = raddbg_matches_from_map_node(rdbg, node, &id_count);
if(id_count > 0)
{
procedure_id = ids[0];
}
}
U64 voff = raddbg_first_voff_from_proc(rdbg, procedure_id);
if(voff != 0)
{
entries_found = 1;
DEMON_Trap trap = {run_ctrls.run_entities[process_idx], module_base_vaddr + voff};
demon_trap_chunk_list_push(scratch.arena, &run_ctrls.traps, 256, &trap);
}
}
}
//- rjf: no entry point found -> done
if(run_ctrls.traps.trap_count == 0)
{
done = 1;
stop_event = event;
@@ -2221,7 +2292,9 @@ ctrl_thread__launch_and_init(CTRL_Msg *msg)
}
}
//////////////////////////////
//- rjf: record bad stop
//
if(stop_event == 0 && id == 0)
{
CTRL_EventList evts = {0};
@@ -2231,7 +2304,9 @@ ctrl_thread__launch_and_init(CTRL_Msg *msg)
ctrl_c2u_push_events(&evts);
}
//////////////////////////////
//- rjf: record stop
//
{
CTRL_EventList evts = {0};
CTRL_Event *event = ctrl_event_list_push(scratch.arena, &evts);
@@ -2250,7 +2325,9 @@ ctrl_thread__launch_and_init(CTRL_Msg *msg)
ctrl_c2u_push_events(&evts);
}
//////////////////////////////
//- rjf: push request resolution event
//
{
CTRL_EventList evts = {0};
CTRL_Event *evt = ctrl_event_list_push(scratch.arena, &evts);
@@ -2812,7 +2889,7 @@ ctrl_thread__run(CTRL_Msg *msg)
EVAL_IRTreeAndType ir_tree_and_type = {&eval_irtree_nil};
if(parse_has_expr && errors.count == 0)
{
ir_tree_and_type = eval_irtree_and_type_from_expr(temp.arena, parse_ctx.type_graph, rdbg, parse.expr, &errors);
ir_tree_and_type = eval_irtree_and_type_from_expr(temp.arena, parse_ctx.type_graph, rdbg, &eval_string2expr_map_nil, parse.expr, &errors);
}
EVAL_OpList op_list = {0};
if(parse_has_expr && ir_tree_and_type.tree != &eval_irtree_nil)
@@ -3219,6 +3296,7 @@ ctrl_mem_stream_thread__entry_point(void *p)
B32 got_task = 0;
U64 preexisting_memgen_idx = 0;
U128 preexisting_hash = {0};
Rng1U64 vaddr_range_clamped = {0};
OS_MutexScopeW(process_stripe->rw_mutex)
{
for(CTRL_ProcessMemoryCacheNode *n = process_slot->first; n != 0; n = n->next)
@@ -3234,6 +3312,7 @@ ctrl_mem_stream_thread__entry_point(void *p)
got_task = !ins_atomic_u32_eval_cond_assign(&range_n->is_taken, 1, 0);
preexisting_memgen_idx = range_n->memgen_idx;
preexisting_hash = range_n->hash;
vaddr_range_clamped = range_n->vaddr_range_clamped;
goto take_task__break_all;
}
}
@@ -3250,31 +3329,38 @@ ctrl_mem_stream_thread__entry_point(void *p)
U64 memgen_idx = ctrl_memgen_idx();
if(got_task && memgen_idx != preexisting_memgen_idx)
{
range_size = dim_1u64(vaddr_range);
range_size = dim_1u64(vaddr_range_clamped);
U64 arena_size = AlignPow2(range_size + ARENA_HEADER_SIZE, KB(64));
range_arena = arena_alloc__sized(range_size+ARENA_HEADER_SIZE, range_size+ARENA_HEADER_SIZE);
range_base = push_array_no_zero(range_arena, U8, range_size);
U64 bytes_read = ctrl_process_read(machine_id, process, vaddr_range, range_base);
if(bytes_read == 0)
if(range_arena == 0)
{
arena_release(range_arena);
range_base = 0;
range_size = 0;
range_arena = 0;
}
else if(bytes_read < range_size)
else
{
MemoryZero((U8 *)range_base + bytes_read, range_size-bytes_read);
}
zero_terminated_size = range_size;
if(zero_terminated)
{
for(U64 idx = 0; idx < bytes_read; idx += 1)
range_base = push_array_no_zero(range_arena, U8, range_size);
U64 bytes_read = ctrl_process_read(machine_id, process, vaddr_range_clamped, range_base);
if(bytes_read == 0)
{
if(((U8 *)range_base)[idx] == 0)
arena_release(range_arena);
range_base = 0;
range_size = 0;
range_arena = 0;
}
else if(bytes_read < range_size)
{
MemoryZero((U8 *)range_base + bytes_read, range_size-bytes_read);
}
zero_terminated_size = range_size;
if(zero_terminated)
{
for(U64 idx = 0; idx < bytes_read; idx += 1)
{
zero_terminated_size = idx;
break;
if(((U8 *)range_base)[idx] == 0)
{
zero_terminated_size = idx;
break;
}
}
}
}
@@ -3313,5 +3399,8 @@ ctrl_mem_stream_thread__entry_point(void *p)
}
commit__break_all:;
}
//- rjf: broadcast changes
os_condition_variable_broadcast(process_stripe->cv);
}
}
+6 -3
View File
@@ -53,6 +53,7 @@ typedef struct CTRL_UnwindFrame CTRL_UnwindFrame;
struct CTRL_UnwindFrame
{
CTRL_UnwindFrame *next;
CTRL_UnwindFrame *prev;
U64 rip;
void *regs;
};
@@ -317,6 +318,7 @@ struct CTRL_ProcessMemoryRangeHashNode
CTRL_ProcessMemoryRangeHashNode *next;
Rng1U64 vaddr_range;
B32 zero_terminated;
Rng1U64 vaddr_range_clamped;
U128 hash;
U64 memgen_idx;
B32 is_taken;
@@ -352,6 +354,7 @@ typedef struct CTRL_ProcessMemoryCacheStripe CTRL_ProcessMemoryCacheStripe;
struct CTRL_ProcessMemoryCacheStripe
{
OS_Handle rw_mutex;
OS_Handle cv;
};
typedef struct CTRL_ProcessMemoryCache CTRL_ProcessMemoryCache;
@@ -529,10 +532,10 @@ internal B32 ctrl_process_write(CTRL_MachineID machine_id, CTRL_Handle process,
//- rjf: process memory cache interaction
internal U128 ctrl_hash_store_key_from_process_vaddr_range(CTRL_MachineID machine_id, CTRL_Handle process, Rng1U64 range, B32 zero_terminated);
internal U128 ctrl_stored_hash_from_process_vaddr_range(CTRL_MachineID machine_id, CTRL_Handle process, Rng1U64 range, B32 zero_terminated);
internal U128 ctrl_stored_hash_from_process_vaddr_range(CTRL_MachineID machine_id, CTRL_Handle process, Rng1U64 range, B32 zero_terminated, U64 endt_us);
//- rjf: process memory cache reading helpers
internal CTRL_ProcessMemorySlice ctrl_query_cached_data_from_process_vaddr_range(Arena *arena, CTRL_MachineID machine_id, CTRL_Handle process, Rng1U64 range);
internal CTRL_ProcessMemorySlice ctrl_query_cached_data_from_process_vaddr_range(Arena *arena, CTRL_MachineID machine_id, CTRL_Handle process, Rng1U64 range, U64 endt_us);
internal CTRL_ProcessMemorySlice ctrl_query_cached_zero_terminated_data_from_process_vaddr_limit(Arena *arena, CTRL_MachineID machine_id, CTRL_Handle process, U64 vaddr, U64 limit, U64 endt_us);
//- rjf: register reading/writing
@@ -546,7 +549,7 @@ internal U64 ctrl_tls_root_vaddr_from_thread(CTRL_MachineID machine_id, CTRL_Han
internal CTRL_Handle ctrl_module_from_process_vaddr(CTRL_MachineID machine_id, CTRL_Handle process, U64 vaddr);
//- rjf: unwinding
internal CTRL_Unwind ctrl_unwind_from_thread(Arena *arena, CTRL_MachineID machine_id, CTRL_Handle thread);
internal CTRL_Unwind ctrl_unwind_from_process_thread(Arena *arena, CTRL_MachineID machine_id, CTRL_Handle process, CTRL_Handle thread);
//- rjf: name -> register/alias hash tables, for eval
internal EVAL_String2NumMap *ctrl_string2reg_from_arch(Architecture arch);
+443 -1
View File
@@ -30,6 +30,16 @@ dbgi_init(void)
dbgi_shared->binary_stripes[idx].rw_mutex = os_rw_mutex_alloc();
dbgi_shared->binary_stripes[idx].cv = os_condition_variable_alloc();
}
dbgi_shared->fuzzy_search_slots_count = 64;
dbgi_shared->fuzzy_search_stripes_count = 8;
dbgi_shared->fuzzy_search_slots = push_array(arena, DBGI_FuzzySearchSlot, dbgi_shared->fuzzy_search_slots_count);
dbgi_shared->fuzzy_search_stripes = push_array(arena, DBGI_FuzzySearchStripe, dbgi_shared->fuzzy_search_stripes_count);
for(U64 idx = 0; idx < dbgi_shared->fuzzy_search_stripes_count; idx += 1)
{
dbgi_shared->fuzzy_search_stripes[idx].arena = arena_alloc();
dbgi_shared->fuzzy_search_stripes[idx].rw_mutex = os_rw_mutex_alloc();
dbgi_shared->fuzzy_search_stripes[idx].cv = os_condition_variable_alloc();
}
dbgi_shared->u2p_ring_mutex = os_mutex_alloc();
dbgi_shared->u2p_ring_cv = os_condition_variable_alloc();
dbgi_shared->u2p_ring_size = KB(64);
@@ -44,6 +54,17 @@ dbgi_init(void)
{
dbgi_shared->parse_threads[idx] = os_launch_thread(dbgi_parse_thread_entry_point, (void *)idx, 0);
}
dbgi_shared->fuzzy_thread_count = Clamp(1, os_logical_core_count()-1, 1);
dbgi_shared->fuzzy_threads = push_array(arena, DBGI_FuzzySearchThread, dbgi_shared->fuzzy_thread_count);
for(U64 idx = 0; idx < dbgi_shared->fuzzy_thread_count; idx += 1)
{
DBGI_FuzzySearchThread *thread = &dbgi_shared->fuzzy_threads[idx];
thread->u2f_ring_mutex = os_mutex_alloc();
thread->u2f_ring_cv = os_condition_variable_alloc();
thread->u2f_ring_size = KB(64);
thread->u2f_ring_base = push_array_no_zero(dbgi_shared->arena, U8, thread->u2f_ring_size);
thread->thread = os_launch_thread(dbgi_fuzzy_thread__entry_point, (void *)idx, 0);
}
}
////////////////////////////////
@@ -74,6 +95,62 @@ dbgi_hash_from_string(String8 string)
return result;
}
internal U64
dbgi_fuzzy_item_num_from_array_element_idx__linear_search(DBGI_FuzzySearchItemArray *array, U64 element_idx)
{
U64 fuzzy_item_num = 0;
for(U64 idx = 0; idx < array->count; idx += 1)
{
if(array->v[idx].idx == element_idx)
{
fuzzy_item_num = idx+1;
break;
}
}
return fuzzy_item_num;
}
internal String8
dbgi_fuzzy_item_string_from_rdbg_target_element_idx(RADDBG_Parsed *rdbg, DBGI_FuzzySearchTarget target, U64 element_idx)
{
String8 result = {0};
switch(target)
{
// NOTE(rjf): no default - warn if we miss a case
case DBGI_FuzzySearchTarget_Procedures:
{
RADDBG_Procedure *proc = raddbg_element_from_idx(rdbg, procedures, element_idx);
U64 name_size = 0;
U8 *name_base = raddbg_string_from_idx(rdbg, proc->name_string_idx, &name_size);
result = str8(name_base, name_size);
}break;
case DBGI_FuzzySearchTarget_GlobalVariables:
{
RADDBG_GlobalVariable *gvar = raddbg_element_from_idx(rdbg, global_variables, element_idx);
U64 name_size = 0;
U8 *name_base = raddbg_string_from_idx(rdbg, gvar->name_string_idx, &name_size);
result = str8(name_base, name_size);
}break;
case DBGI_FuzzySearchTarget_ThreadVariables:
{
RADDBG_ThreadVariable *tvar = raddbg_element_from_idx(rdbg, thread_variables, element_idx);
U64 name_size = 0;
U8 *name_base = raddbg_string_from_idx(rdbg, tvar->name_string_idx, &name_size);
result = str8(name_base, name_size);
}break;
case DBGI_FuzzySearchTarget_UDTs:
{
RADDBG_UDT *udt = raddbg_element_from_idx(rdbg, udts, element_idx);
RADDBG_TypeNode *type_node = raddbg_element_from_idx(rdbg, type_nodes, udt->self_type_idx);
U64 name_size = 0;
U8 *name_base = raddbg_string_from_idx(rdbg, type_node->user_defined.name_string_idx, &name_size);
result = str8(name_base, name_size);
}break;
case DBGI_FuzzySearchTarget_COUNT:{}break;
}
return result;
}
////////////////////////////////
//~ rjf: Forced Override Cache Functions
@@ -169,6 +246,12 @@ dbgi_scope_close(DBGI_Scope *scope)
ins_atomic_u64_dec_eval(&tb->binary->scope_touch_count);
SLLStackPush(dbgi_tctx->free_tb, tb);
}
for(DBGI_TouchedFuzzySearch *tfs = scope->first_tfs, *next = 0; tfs != 0; tfs = next)
{
next = tfs->next;
ins_atomic_u64_dec_eval(&tfs->node->scope_touch_count);
SLLStackPush(dbgi_tctx->free_tfs, tfs);
}
SLLStackPush(dbgi_tctx->free_scope, scope);
}
@@ -189,6 +272,23 @@ dbgi_scope_touch_binary__stripe_mutex_r_guarded(DBGI_Scope *scope, DBGI_Binary *
SLLQueuePush(scope->first_tb, scope->last_tb, tb);
}
internal void
dbgi_scope_touch_fuzzy_search__stripe_mutex_r_guarded(DBGI_Scope *scope, DBGI_FuzzySearchNode *node)
{
DBGI_TouchedFuzzySearch *tfs = dbgi_tctx->free_tfs;
ins_atomic_u64_inc_eval(&node->scope_touch_count);
if(tfs != 0)
{
SLLStackPop(dbgi_tctx->free_tfs);
}
else
{
tfs = push_array(dbgi_tctx->arena, DBGI_TouchedFuzzySearch, 1);
}
tfs->node = node;
SLLQueuePush(scope->first_tfs, scope->last_tfs, tfs);
}
////////////////////////////////
//~ rjf: Binary Cache Functions
@@ -291,6 +391,7 @@ dbgi_parse_from_exe_path(DBGI_Scope *scope, String8 exe_path, U64 endt_us)
Temp scratch = scratch_begin(0, 0);
exe_path = path_normalized_from_string(scratch.arena, exe_path);
DBGI_Parse *parse = &dbgi_parse_nil;
if(exe_path.size != 0)
{
U64 hash = dbgi_hash_from_string(exe_path);
U64 slot_idx = hash%dbgi_shared->binary_slots_count;
@@ -336,6 +437,92 @@ dbgi_parse_from_exe_path(DBGI_Scope *scope, String8 exe_path, U64 endt_us)
return parse;
}
////////////////////////////////
//~ rjf: Fuzzy Search Cache Functions
internal DBGI_FuzzySearchItemArray
dbgi_fuzzy_search_items_from_key_exe_query(DBGI_Scope *scope, U128 key, String8 exe_path, String8 query, DBGI_FuzzySearchTarget target, U64 endt_us, B32 *stale_out)
{
Temp scratch = scratch_begin(0, 0);
DBGI_FuzzySearchItemArray items = {0};
exe_path = path_normalized_from_string(scratch.arena, exe_path);
{
//- rjf: unpack key
U64 slot_idx = key.u64[1]%dbgi_shared->fuzzy_search_slots_count;
U64 stripe_idx = slot_idx%dbgi_shared->fuzzy_search_stripes_count;
DBGI_FuzzySearchSlot *slot = &dbgi_shared->fuzzy_search_slots[slot_idx];
DBGI_FuzzySearchStripe *stripe = &dbgi_shared->fuzzy_search_stripes[stripe_idx];
//- rjf: query and/or request
OS_MutexScopeR(stripe->rw_mutex) for(;;)
{
// rjf: map key -> node
DBGI_FuzzySearchNode *node = 0;
for(DBGI_FuzzySearchNode *n = slot->first; n != 0; n = n->next)
{
if(u128_match(n->key, key))
{
node = n;
break;
}
}
// rjf: no node? -> allocate
if(node == 0) OS_MutexScopeRWPromote(stripe->rw_mutex)
{
node = push_array(stripe->arena, DBGI_FuzzySearchNode, 1);
SLLQueuePush(slot->first, slot->last, node);
node->key = key;
for(U64 idx = 0; idx < ArrayCount(node->buckets); idx += 1)
{
node->buckets[idx].arena = arena_alloc();
}
}
// rjf: try to grab last valid results for this key/query; determine if stale
B32 stale = 1;
if(str8_match(exe_path, node->buckets[node->gen%ArrayCount(node->buckets)].exe_path, 0) &&
target == node->buckets[node->gen%ArrayCount(node->buckets)].target &&
node->gen != 0)
{
dbgi_scope_touch_fuzzy_search__stripe_mutex_r_guarded(scope, node);
items = node->gen_items;
stale = !str8_match(query, node->buckets[node->gen%ArrayCount(node->buckets)].query, 0);
*stale_out = stale;
}
// rjf: if stale -> request again
if(stale) OS_MutexScopeRWPromote(stripe->rw_mutex)
{
if(node->gen <= node->submit_gen && node->submit_gen < node->gen + ArrayCount(node->buckets)-1)
{
node->submit_gen += 1;
arena_clear(node->buckets[node->submit_gen%ArrayCount(node->buckets)].arena);
node->buckets[node->submit_gen%ArrayCount(node->buckets)].exe_path = push_str8_copy(node->buckets[node->submit_gen%ArrayCount(node->buckets)].arena, exe_path);
node->buckets[node->submit_gen%ArrayCount(node->buckets)].query = push_str8_copy(node->buckets[node->submit_gen%ArrayCount(node->buckets)].arena, query);
node->buckets[node->submit_gen%ArrayCount(node->buckets)].target = target;
}
if((node->submit_gen > node->gen+1 || os_now_microseconds() >= node->last_time_submitted_us+100000) &&
dbgi_u2f_enqueue_req(key, endt_us))
{
node->last_time_submitted_us = os_now_microseconds();
}
}
// rjf: not stale, or timeout -> break
if(!stale || os_now_microseconds() >= endt_us)
{
break;
}
// rjf: no results, but have time to wait -> wait
os_condition_variable_wait_rw_r(stripe->cv, stripe->rw_mutex, endt_us);
}
}
scratch_end(scratch);
return items;
}
////////////////////////////////
//~ rjf: Analysis Threads
@@ -830,7 +1017,7 @@ dbgi_parse_thread_entry_point(void *p)
}
//- rjf: parse raddbg info
RADDBG_Parsed raddbg_parsed = {0};
RADDBG_Parsed raddbg_parsed = dbgi_parse_nil.rdbg;
U64 arch_addr_size = 8;
if(do_task)
{
@@ -897,3 +1084,258 @@ dbgi_parse_thread_entry_point(void *p)
scratch_end(scratch);
}
}
////////////////////////////////
//~ rjf: Fuzzy Searching Threads
internal B32
dbgi_u2f_enqueue_req(U128 key, U64 endt_us)
{
B32 sent = 0;
DBGI_FuzzySearchThread *thread = &dbgi_shared->fuzzy_threads[key.u64[1]%dbgi_shared->fuzzy_thread_count];
OS_MutexScope(thread->u2f_ring_mutex) for(;;)
{
U64 unconsumed_size = thread->u2f_ring_write_pos - thread->u2f_ring_read_pos;
U64 available_size = thread->u2f_ring_size - unconsumed_size;
if(available_size >= sizeof(U128))
{
sent = 1;
thread->u2f_ring_write_pos += ring_write_struct(thread->u2f_ring_base, thread->u2f_ring_size, thread->u2f_ring_write_pos, &key);
break;
}
os_condition_variable_wait(thread->u2f_ring_cv, thread->u2f_ring_mutex, endt_us);
}
if(sent)
{
os_condition_variable_broadcast(thread->u2f_ring_cv);
}
return sent;
}
internal void
dbgi_u2f_dequeue_req(Arena *arena, DBGI_FuzzySearchThread *thread, U128 *key_out)
{
OS_MutexScope(thread->u2f_ring_mutex) for(;;)
{
U64 unconsumed_size = thread->u2f_ring_write_pos - thread->u2f_ring_read_pos;
if(unconsumed_size >= sizeof(U128))
{
thread->u2f_ring_read_pos += ring_read_struct(thread->u2f_ring_base, thread->u2f_ring_size, thread->u2f_ring_read_pos, key_out);
break;
}
os_condition_variable_wait(thread->u2f_ring_cv, thread->u2f_ring_mutex, max_U64);
}
os_condition_variable_broadcast(thread->u2f_ring_cv);
}
internal int
dbgi_qsort_compare_fuzzy_search_items(DBGI_FuzzySearchItem *a, DBGI_FuzzySearchItem *b)
{
int result = 0;
if(a->match_ranges.count > b->match_ranges.count)
{
result = -1;
}
else if(a->match_ranges.count < b->match_ranges.count)
{
result = +1;
}
else if(a->missed_size < b->missed_size)
{
result = -1;
}
else if(a->missed_size > b->missed_size)
{
result = +1;
}
return result;
}
internal void
dbgi_fuzzy_thread__entry_point(void *p)
{
TCTX tctx_;
tctx_init_and_equip(&tctx_);
ProfThreadName("[dbgi] fuzzy search #%I64U", (U64)p);
DBGI_FuzzySearchThread *thread = &dbgi_shared->fuzzy_threads[(U64)p];
for(;;)
{
Temp scratch = scratch_begin(0, 0);
DBGI_Scope *scope = dbgi_scope_open();
//- rjf: dequeue next request
U128 key = {0};
dbgi_u2f_dequeue_req(scratch.arena, thread, &key);
U64 slot_idx = key.u64[1]%dbgi_shared->fuzzy_search_slots_count;
U64 stripe_idx = slot_idx%dbgi_shared->fuzzy_search_stripes_count;
DBGI_FuzzySearchSlot *slot = &dbgi_shared->fuzzy_search_slots[slot_idx];
DBGI_FuzzySearchStripe *stripe = &dbgi_shared->fuzzy_search_stripes[stripe_idx];
//- rjf: grab next exe_path/query for this key
B32 task_is_good = 0;
Arena *task_arena = 0;
String8 exe_path = {0};
String8 query = {0};
DBGI_FuzzySearchTarget target = DBGI_FuzzySearchTarget_Procedures;
U64 initial_submit_gen = 0;
OS_MutexScopeW(stripe->rw_mutex)
{
for(DBGI_FuzzySearchNode *n = slot->first; n != 0; n = n->next)
{
if(u128_match(n->key, key))
{
task_is_good = 1;
initial_submit_gen = n->submit_gen;
task_arena = n->buckets[n->submit_gen%ArrayCount(n->buckets)].arena;
exe_path = n->buckets[n->submit_gen%ArrayCount(n->buckets)].exe_path;
query = n->buckets[n->submit_gen%ArrayCount(n->buckets)].query;
target = n->buckets[n->submit_gen%ArrayCount(n->buckets)].target;
break;
}
}
}
//- rjf: exe_path -> dbgi_parse, raddbg
DBGI_Parse *dbgi = dbgi_parse_from_exe_path(scope, exe_path, max_U64);
RADDBG_Parsed *rdbg = &dbgi->rdbg;
//- rjf: rdbg * query -> item list
U64 table_ptr_off = 0;
U64 element_name_idx_off = 0;
U64 element_count = 0;
U64 element_size = 0;
switch(target)
{
// NOTE(rjf): no default!
case DBGI_FuzzySearchTarget_COUNT:{}break;
case DBGI_FuzzySearchTarget_Procedures:
{
table_ptr_off = OffsetOf(RADDBG_Parsed, procedures);
element_name_idx_off = OffsetOf(RADDBG_Procedure, name_string_idx);
element_count = rdbg->procedures_count;
element_size = sizeof(RADDBG_Procedure);
}break;
case DBGI_FuzzySearchTarget_GlobalVariables:
{
table_ptr_off = OffsetOf(RADDBG_Parsed, global_variables);
element_name_idx_off = OffsetOf(RADDBG_GlobalVariable, name_string_idx);
element_count = rdbg->global_variables_count;
element_size = sizeof(RADDBG_GlobalVariable);
}break;
case DBGI_FuzzySearchTarget_ThreadVariables:
{
table_ptr_off = OffsetOf(RADDBG_Parsed, thread_variables);
element_name_idx_off = OffsetOf(RADDBG_ThreadVariable, name_string_idx);
element_count = rdbg->thread_variables_count;
element_size = sizeof(RADDBG_ThreadVariable);
}break;
case DBGI_FuzzySearchTarget_UDTs:
{
table_ptr_off = OffsetOf(RADDBG_Parsed, udts);
element_count = rdbg->udts_count;
element_size = sizeof(RADDBG_UDT);
}break;
}
DBGI_FuzzySearchItemChunkList items_list = {0};
if(task_is_good)
{
void *table_base = (U8*)rdbg + table_ptr_off;
for(U64 idx = 1; task_is_good && idx < element_count; idx += 1)
{
void *element = (U8 *)(*(void **)table_base) + element_size*idx;
U32 *name_idx_ptr = (U32 *)((U8 *)element + element_name_idx_off);
if(target == DBGI_FuzzySearchTarget_UDTs)
{
RADDBG_UDT *udt = (RADDBG_UDT *)element;
RADDBG_TypeNode *type_node = raddbg_element_from_idx(rdbg, type_nodes, udt->self_type_idx);
name_idx_ptr = &type_node->user_defined.name_string_idx;
}
U32 name_idx = *name_idx_ptr;
U64 name_size = 0;
U8 *name_base = raddbg_string_from_idx(rdbg, name_idx, &name_size);
String8 name = str8(name_base, name_size);
if(name.size == 0) { continue; }
FuzzyMatchRangeList matches = fuzzy_match_find(task_arena, query, name);
if(matches.count == matches.needle_part_count)
{
DBGI_FuzzySearchItemChunk *chunk = items_list.last;
if(chunk == 0 || chunk->count >= chunk->cap)
{
chunk = push_array(scratch.arena, DBGI_FuzzySearchItemChunk, 1);
chunk->cap = 512;
chunk->count = 0;
chunk->v = push_array_no_zero(scratch.arena, DBGI_FuzzySearchItem, chunk->cap);
SLLQueuePush(items_list.first, items_list.last, chunk);
items_list.chunk_count += 1;
}
chunk->v[chunk->count].idx = idx;
chunk->v[chunk->count].match_ranges = matches;
chunk->v[chunk->count].missed_size = (name_size > matches.total_dim) ? (name_size-matches.total_dim) : 0;
chunk->count += 1;
items_list.total_count += 1;
}
if(idx%100 == 99) OS_MutexScopeR(stripe->rw_mutex)
{
for(DBGI_FuzzySearchNode *n = slot->first; n != 0; n = n->next)
{
if(u128_match(n->key, key) && n->submit_gen > initial_submit_gen)
{
task_is_good = 0;
break;
}
}
}
}
}
//- rjf: item list -> item array
DBGI_FuzzySearchItemArray items = {0};
if(task_is_good)
{
items.count = items_list.total_count;
items.v = push_array_no_zero(task_arena, DBGI_FuzzySearchItem, items.count);
U64 idx = 0;
for(DBGI_FuzzySearchItemChunk *chunk = items_list.first; chunk != 0; chunk = chunk->next)
{
MemoryCopy(items.v+idx, chunk->v, sizeof(DBGI_FuzzySearchItem)*chunk->count);
idx += chunk->count;
}
}
//- rjf: sort item array
if(items.count != 0 && query.size != 0)
{
qsort(items.v, items.count, sizeof(DBGI_FuzzySearchItem), (int (*)(const void *, const void *))dbgi_qsort_compare_fuzzy_search_items);
}
//- rjf: commit to cache - busyloop on scope touches
if(task_is_good)
{
for(B32 done = 0; !done;)
{
B32 found = 0;
OS_MutexScopeW(stripe->rw_mutex) for(DBGI_FuzzySearchNode *n = slot->first; n != 0; n = n->next)
{
if(u128_match(n->key, key))
{
if(n->scope_touch_count == 0)
{
n->gen = initial_submit_gen;
n->gen_items = items;
done = 1;
}
found = 1;
break;
}
}
if(!found)
{
break;
}
}
}
dbgi_scope_close(scope);
scratch_end(scratch);
}
}
+176 -1
View File
@@ -97,6 +97,101 @@ struct DBGI_BinaryStripe
OS_Handle cv;
};
////////////////////////////////
//~ rjf: Fuzzy Search Cache Types
typedef enum DBGI_FuzzySearchTarget
{
DBGI_FuzzySearchTarget_Procedures,
DBGI_FuzzySearchTarget_GlobalVariables,
DBGI_FuzzySearchTarget_ThreadVariables,
DBGI_FuzzySearchTarget_UDTs,
DBGI_FuzzySearchTarget_COUNT
}
DBGI_FuzzySearchTarget;
typedef struct DBGI_FuzzySearchItem DBGI_FuzzySearchItem;
struct DBGI_FuzzySearchItem
{
U64 idx;
U64 missed_size;
FuzzyMatchRangeList match_ranges;
};
typedef struct DBGI_FuzzySearchItemChunk DBGI_FuzzySearchItemChunk;
struct DBGI_FuzzySearchItemChunk
{
DBGI_FuzzySearchItemChunk *next;
DBGI_FuzzySearchItem *v;
U64 count;
U64 cap;
};
typedef struct DBGI_FuzzySearchItemChunkList DBGI_FuzzySearchItemChunkList;
struct DBGI_FuzzySearchItemChunkList
{
DBGI_FuzzySearchItemChunk *first;
DBGI_FuzzySearchItemChunk *last;
U64 chunk_count;
U64 total_count;
};
typedef struct DBGI_FuzzySearchItemArray DBGI_FuzzySearchItemArray;
struct DBGI_FuzzySearchItemArray
{
DBGI_FuzzySearchItem *v;
U64 count;
};
typedef struct DBGI_FuzzySearchBucket DBGI_FuzzySearchBucket;
struct DBGI_FuzzySearchBucket
{
Arena *arena;
String8 exe_path;
String8 query;
DBGI_FuzzySearchTarget target;
};
typedef struct DBGI_FuzzySearchNode DBGI_FuzzySearchNode;
struct DBGI_FuzzySearchNode
{
DBGI_FuzzySearchNode *next;
U128 key;
U64 scope_touch_count;
U64 last_time_submitted_us;
DBGI_FuzzySearchBucket buckets[3];
U64 gen;
U64 submit_gen;
DBGI_FuzzySearchItemArray gen_items;
};
typedef struct DBGI_FuzzySearchSlot DBGI_FuzzySearchSlot;
struct DBGI_FuzzySearchSlot
{
DBGI_FuzzySearchNode *first;
DBGI_FuzzySearchNode *last;
};
typedef struct DBGI_FuzzySearchStripe DBGI_FuzzySearchStripe;
struct DBGI_FuzzySearchStripe
{
Arena *arena;
OS_Handle rw_mutex;
OS_Handle cv;
};
typedef struct DBGI_FuzzySearchThread DBGI_FuzzySearchThread;
struct DBGI_FuzzySearchThread
{
OS_Handle thread;
OS_Handle u2f_ring_mutex;
OS_Handle u2f_ring_cv;
U64 u2f_ring_size;
U8 *u2f_ring_base;
U64 u2f_ring_write_pos;
U64 u2f_ring_read_pos;
};
////////////////////////////////
//~ rjf: Weak Access Scope Types
@@ -107,12 +202,21 @@ struct DBGI_TouchedBinary
DBGI_Binary *binary;
};
typedef struct DBGI_TouchedFuzzySearch DBGI_TouchedFuzzySearch;
struct DBGI_TouchedFuzzySearch
{
DBGI_TouchedFuzzySearch *next;
DBGI_FuzzySearchNode *node;
};
typedef struct DBGI_Scope DBGI_Scope;
struct DBGI_Scope
{
DBGI_Scope *next;
DBGI_TouchedBinary *first_tb;
DBGI_TouchedBinary *last_tb;
DBGI_TouchedFuzzySearch *first_tfs;
DBGI_TouchedFuzzySearch *last_tfs;
};
typedef struct DBGI_ThreadCtx DBGI_ThreadCtx;
@@ -121,6 +225,7 @@ struct DBGI_ThreadCtx
Arena *arena;
DBGI_Scope *free_scope;
DBGI_TouchedBinary *free_tb;
DBGI_TouchedFuzzySearch *free_tfs;
};
////////////////////////////////
@@ -179,6 +284,12 @@ struct DBGI_Shared
DBGI_BinarySlot *binary_slots;
DBGI_BinaryStripe *binary_stripes;
// rjf: fuzzy search cache table
U64 fuzzy_search_slots_count;
U64 fuzzy_search_stripes_count;
DBGI_FuzzySearchSlot *fuzzy_search_slots;
DBGI_FuzzySearchStripe *fuzzy_search_stripes;
// rjf: user -> parse ring
OS_Handle u2p_ring_mutex;
OS_Handle u2p_ring_cv;
@@ -198,6 +309,8 @@ struct DBGI_Shared
// rjf: threads
U64 parse_thread_count;
OS_Handle *parse_threads;
U64 fuzzy_thread_count;
DBGI_FuzzySearchThread *fuzzy_threads;
};
////////////////////////////////
@@ -205,7 +318,51 @@ struct DBGI_Shared
global DBGI_Shared *dbgi_shared = 0;
thread_static DBGI_ThreadCtx *dbgi_tctx = 0;
global DBGI_Parse dbgi_parse_nil = {0};
global DBGI_Parse dbgi_parse_nil =
{
0,
0,
0,
{0},
{0},
0,
{0},
{0},
{
0,
0,
0,
0,
{0},
0,
0,
0,
0,
0,
0,
0,
&raddbg_binary_section_nil, 1,
&raddbg_file_path_node_nil, 1,
&raddbg_source_file_nil, 1,
&raddbg_unit_nil, 1,
&raddbg_vmap_entry_nil, 1,
&raddbg_type_node_nil, 1,
&raddbg_udt_nil, 1,
&raddbg_member_nil, 1,
&raddbg_enum_member_nil, 1,
&raddbg_global_variable_nil, 1,
&raddbg_vmap_entry_nil, 1,
&raddbg_thread_variable_nil, 1,
&raddbg_procedure_nil, 1,
&raddbg_scope_nil, 1,
&raddbg_voff_nil, 1,
&raddbg_vmap_entry_nil, 1,
&raddbg_local_nil, 1,
&raddbg_location_block_nil, 1,
0, 0,
0, 0,
},
};
////////////////////////////////
//~ rjf: Main Layer Initialization
@@ -221,6 +378,8 @@ internal void dbgi_ensure_tctx_inited(void);
//~ rjf: Helpers
internal U64 dbgi_hash_from_string(String8 string);
internal U64 dbgi_fuzzy_item_num_from_array_element_idx__linear_search(DBGI_FuzzySearchItemArray *array, U64 element_idx);
internal String8 dbgi_fuzzy_item_string_from_rdbg_target_element_idx(RADDBG_Parsed *rdbg, DBGI_FuzzySearchTarget target, U64 element_idx);
////////////////////////////////
//~ rjf: Forced Override Cache Functions
@@ -234,6 +393,7 @@ internal String8 dbgi_forced_dbg_path_from_exe_path(Arena *arena, String8 exe_pa
internal DBGI_Scope *dbgi_scope_open(void);
internal void dbgi_scope_close(DBGI_Scope *scope);
internal void dbgi_scope_touch_binary__stripe_mutex_r_guarded(DBGI_Scope *scope, DBGI_Binary *binary);
internal void dbgi_scope_touch_fuzzy_search__stripe_mutex_r_guarded(DBGI_Scope *scope, DBGI_FuzzySearchNode *node);
////////////////////////////////
//~ rjf: Binary Cache Functions
@@ -242,6 +402,11 @@ internal void dbgi_binary_open(String8 exe_path);
internal void dbgi_binary_close(String8 exe_path);
internal DBGI_Parse *dbgi_parse_from_exe_path(DBGI_Scope *scope, String8 exe_path, U64 endt_us);
////////////////////////////////
//~ rjf: Fuzzy Search Cache Functions
internal DBGI_FuzzySearchItemArray dbgi_fuzzy_search_items_from_key_exe_query(DBGI_Scope *scope, U128 key, String8 exe_path, String8 query, DBGI_FuzzySearchTarget target, U64 endt_us, B32 *stale_out);
////////////////////////////////
//~ rjf: Parse Threads
@@ -253,4 +418,14 @@ internal DBGI_EventList dbgi_p2u_pop_events(Arena *arena, U64 endt_us);
internal void dbgi_parse_thread_entry_point(void *p);
////////////////////////////////
//~ rjf: Fuzzy Searching Threads
internal B32 dbgi_u2f_enqueue_req(U128 key, U64 endt_us);
internal void dbgi_u2f_dequeue_req(Arena *arena, DBGI_FuzzySearchThread *thread, U128 *key_out);
internal int dbgi_qsort_compare_fuzzy_search_items(DBGI_FuzzySearchItem *a, DBGI_FuzzySearchItem *b);
internal void dbgi_fuzzy_thread__entry_point(void *p);
#endif //DBGI_H
+1 -5
View File
@@ -144,11 +144,7 @@ demon_accel_read_regs(DEMON_Entity *thread){
// update reg cache
if (accel->reg_cache_time != demon_time){
accel->reg_cache_time = demon_time;
B32 success = 0;
switch (thread->arch){
case Architecture_x86:{success = demon_os_read_regs_x86(thread, &accel->regs.x86);}break;
case Architecture_x64:{success = demon_os_read_regs_x64(thread, &accel->regs.x64);}break;
}
B32 success = demon_os_read_regs(thread, &accel->regs);
if (!success){
MemoryZeroStruct(&accel->regs);
}
+2 -2
View File
@@ -30,8 +30,8 @@ struct DEMON_Entity
DEMON_Entity *first;
DEMON_Entity *last;
U16 kind;
U16 arch;
DEMON_EntityKind kind;
Architecture arch;
U32 gen;
U64 id;
U64 addr_range_dim;
+1
View File
@@ -4,6 +4,7 @@
#include "demon_core.c"
#include "demon_common.c"
#include "demon_accel.c"
#include "demon_os.c"
#if OS_WINDOWS
# include "win32/demon_os_win32.c"
+28
View File
@@ -0,0 +1,28 @@
////////////////////////////////
//~ rjf: Helpers
internal B32
demon_os_read_regs(DEMON_Entity *thread, void *dst)
{
B32 result = 0;
switch(thread->arch)
{
default:{}break;
case Architecture_x86:{result = demon_os_read_regs_x86(thread, (REGS_RegBlockX86 *)dst);}break;
case Architecture_x64:{result = demon_os_read_regs_x64(thread, (REGS_RegBlockX64 *)dst);}break;
}
return result;
}
internal B32
demon_os_write_regs(DEMON_Entity *thread, void *src)
{
B32 result = 0;
switch(thread->arch)
{
default:{}break;
case Architecture_x86:{result = demon_os_write_regs_x86(thread, (REGS_RegBlockX86 *)src);}break;
case Architecture_x64:{result = demon_os_write_regs_x64(thread, (REGS_RegBlockX64 *)src);}break;
}
return result;
}
+6
View File
@@ -35,6 +35,12 @@ struct DEMON_OS_RunCtrls
U64 trap_count;
};
////////////////////////////////
//~ rjf: Helpers
internal B32 demon_os_read_regs(DEMON_Entity *thread, void *dst);
internal B32 demon_os_write_regs(DEMON_Entity *thread, void *src);
////////////////////////////////
//~ rjf: @demon_os_hooks Main Layer Initialization
+69 -26
View File
@@ -432,6 +432,7 @@ demon_os_run(Arena *arena, DEMON_OS_RunCtrls *ctrls){
DEMON_Event *e = demon_push_event(arena, &result, DEMON_EventKind_UnloadModule);
e->process = demon_ent_handle_from_ptr(process);
e->module = demon_ent_handle_from_ptr(child);
e->string = demon_os_full_path_from_module(arena, child);
}
}
@@ -571,20 +572,24 @@ demon_os_run(Arena *arena, DEMON_OS_RunCtrls *ctrls){
}
}
// prep threads that will be allowed to run
for (DEMON_W32_EntityNode *node = first_run_thread;
node != 0;
node = node->next){
// prep suspension state of threads that will be allowed to run
for(DEMON_W32_EntityNode *node = first_run_thread;
node != 0;
node = node->next)
{
DEMON_Entity *thread = node->entity;
DEMON_W32_Ext *thread_ext = demon_w32_ext(thread);
DWORD resume_result = ResumeThread(thread_ext->thread.handle);
if (resume_result == max_U32){
if(resume_result == max_U32)
{
// TODO(allen): Error. Unknown cause (do GetLastError, FromatMessage)
}
else{
else
{
DWORD desired_counter = 0;
DWORD current_counter = resume_result - 1;
if (current_counter != desired_counter){
if(current_counter != desired_counter)
{
// NOTE(rjf): Warning. The user has manually suspended this thread,
// so even though from Demon's perspective it thinks this thread
// should run, it will not, because the user has manually called
@@ -593,6 +598,33 @@ demon_os_run(Arena *arena, DEMON_OS_RunCtrls *ctrls){
}
}
// rjf: if run threads are marked as having reported an explicit trap
// on their last run, shift their RIPs past that trap instruction, so
// that they may continue
for(DEMON_W32_EntityNode *node = first_run_thread;
node != 0;
node = node->next)
{
DEMON_Entity *thread = node->entity;
DEMON_W32_Ext *thread_ext = demon_w32_ext(thread);
if(thread_ext->thread.last_run_reported_trap)
{
Temp temp = temp_begin(scratch.arena);
U64 regs_block_size = regs_block_size_from_architecture(thread->arch);
void *regs_block = push_array(temp.arena, U8, regs_block_size);
B32 good = demon_os_read_regs(thread, regs_block);
U64 pre_rip = regs_rip_from_arch_block(thread->arch, regs_block);
if(good && pre_rip == thread_ext->thread.last_run_reported_trap_pre_rip)
{
regs_arch_block_write_rip(thread->arch, regs_block, thread_ext->thread.last_run_reported_trap_post_rip);
demon_os_write_regs(thread, regs_block);
}
temp_end(temp);
thread_ext->thread.last_run_reported_trap = 0;
thread_ext->thread.last_run_reported_trap_post_rip = 0;
}
}
// send last saved continue signal
B32 good_state = 1;
if (demon_w32_resume_needed != 0){
@@ -988,27 +1020,22 @@ demon_os_run(Arena *arena, DEMON_OS_RunCtrls *ctrls){
}
// rjf: determine whether to roll back instruction pointer
B32 rollback = (is_trap && !hit_explicit_trap);
B32 rollback = (is_trap);
// rjf: roll back
if (rollback){
// TODO(allen): possibly buggy
switch (thread->arch){
case Architecture_x86:
{
REGS_RegBlockX86 regs = {0};
demon_os_read_regs_x86(thread, &regs);
regs.eip.u32 = instruction_pointer;
demon_os_write_regs_x86(thread, &regs);
}break;
case Architecture_x64:
{
REGS_RegBlockX64 regs = {0};
demon_os_read_regs_x64(thread, &regs);
regs.rip.u64 = instruction_pointer;
demon_os_write_regs_x64(thread, &regs);
}break;
U64 post_trap_rip = 0;
if(rollback)
{
Temp temp = temp_begin(scratch.arena);
U64 regs_block_size = regs_block_size_from_architecture(thread->arch);
void *regs_block = push_array(scratch.arena, U8, regs_block_size);
if(demon_os_read_regs(thread, regs_block))
{
post_trap_rip = regs_rip_from_arch_block(thread->arch, regs_block);
regs_arch_block_write_rip(thread->arch, regs_block, instruction_pointer);
demon_os_write_regs(thread, regs_block);
}
temp_end(temp);
}
// allen: if this is not a user trap or explicit trap it's a previous trap
@@ -1018,7 +1045,9 @@ demon_os_run(Arena *arena, DEMON_OS_RunCtrls *ctrls){
B32 skip_event = (hit_previous_trap);
// emit event
if (!skip_event){
if(!skip_event)
{
// rjf: fill top-level info
DEMON_Event *e = demon_push_event(arena, &result, DEMON_EventKind_Exception);
e->process = demon_ent_handle_from_ptr(process);
e->thread = demon_ent_handle_from_ptr(thread);
@@ -1026,6 +1055,16 @@ demon_os_run(Arena *arena, DEMON_OS_RunCtrls *ctrls){
e->flags = exception->ExceptionFlags;
e->instruction_pointer = (U64)exception->ExceptionAddress;
// rjf: explicit trap -> mark this thread as having reported this trap
if(hit_explicit_trap)
{
DEMON_W32_Ext *thread_ext = demon_w32_ext(thread);
thread_ext->thread.last_run_reported_trap = 1;
thread_ext->thread.last_run_reported_trap_pre_rip = instruction_pointer;
thread_ext->thread.last_run_reported_trap_post_rip = post_trap_rip;
}
// rjf: fill by exception code
switch (exception->ExceptionCode){
case DEMON_W32_EXCEPTION_BREAKPOINT:
{
@@ -1124,6 +1163,10 @@ demon_os_run(Arena *arena, DEMON_OS_RunCtrls *ctrls){
}
e->kind = DEMON_EventKind_SetThreadName;
e->string = str8_list_join(arena, &thread_name_strings, 0);
if(exception->NumberParameters > 2)
{
e->code = exception->ExceptionInformation[2];
}
}
}break;
+3
View File
@@ -37,6 +37,9 @@ union DEMON_W32_Ext
U64 thread_local_base;
U64 last_name_hash;
U64 name_gather_time_us;
B32 last_run_reported_trap;
U64 last_run_reported_trap_pre_rip;
U64 last_run_reported_trap_post_rip;
} thread;
struct{
HANDLE handle;
+582 -445
View File
File diff suppressed because it is too large Load Diff
+129 -121
View File
@@ -35,7 +35,6 @@ struct DF_HandleList
typedef struct DF_ExpandKey DF_ExpandKey;
struct DF_ExpandKey
{
U64 uniquifier;
U64 parent_hash;
U64 child_num;
};
@@ -70,24 +69,6 @@ struct DF_ExpandTreeTable
DF_ExpandNode *free_node;
};
////////////////////////////////
//~ rjf: Fuzzy Matching
typedef struct DF_FuzzyMatchRangeNode DF_FuzzyMatchRangeNode;
struct DF_FuzzyMatchRangeNode
{
DF_FuzzyMatchRangeNode *next;
Rng1U64 range;
};
typedef struct DF_FuzzyMatchRangeList DF_FuzzyMatchRangeList;
struct DF_FuzzyMatchRangeList
{
DF_FuzzyMatchRangeNode *first;
DF_FuzzyMatchRangeNode *last;
U64 count;
};
////////////////////////////////
//~ rjf: Control Context Types
@@ -261,31 +242,9 @@ struct DF_CtrlFlowInfo
S64 cumulative_sp_delta;
};
////////////////////////////////
//~ rjf: Unwind Types
typedef struct DF_UnwindFrame DF_UnwindFrame;
struct DF_UnwindFrame
{
DF_UnwindFrame *next;
U64 rip;
void *regs;
};
typedef struct DF_Unwind DF_Unwind;
struct DF_Unwind
{
DF_UnwindFrame *first;
DF_UnwindFrame *last;
U64 count;
B32 error;
};
////////////////////////////////
//~ rjf: Evaluation Types
//- rjf: primary artifact from evaluation
typedef struct DF_Eval DF_Eval;
struct DF_Eval
{
@@ -303,44 +262,13 @@ struct DF_Eval
EVAL_ErrorList errors;
};
//- rjf: value history types
typedef struct DF_EvalHistoryVal DF_EvalHistoryVal;
struct DF_EvalHistoryVal
{
EVAL_EvalMode mode;
U64 offset;
U64 imm_u128[2];
};
typedef struct DF_EvalHistoryCacheNode DF_EvalHistoryCacheNode;
struct DF_EvalHistoryCacheNode
{
DF_EvalHistoryCacheNode *lru_next;
DF_EvalHistoryCacheNode *lru_prev;
DF_EvalHistoryCacheNode *hash_next;
DF_EvalHistoryCacheNode *hash_prev;
DF_ExpandKey key;
U64 first_run_idx;
U64 last_run_idx;
U64 newest_val_idx;
DF_EvalHistoryVal values[64];
};
typedef struct DF_EvalHistoryCacheSlot DF_EvalHistoryCacheSlot;
struct DF_EvalHistoryCacheSlot
{
DF_EvalHistoryCacheNode *first;
DF_EvalHistoryCacheNode *last;
};
////////////////////////////////
//~ rjf: View Rule Hook Types
#define DF_CORE_VIEW_RULE_EVAL_RESOLUTION_FUNCTION_SIG(name) DF_Eval name(Arena *arena, DBGI_Scope *dbgi_scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_Eval eval, struct DF_CfgVal *val)
#define DF_CORE_VIEW_RULE_EVAL_RESOLUTION_FUNCTION_SIG(name) DF_Eval name(Arena *arena, DBGI_Scope *dbgi_scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, EVAL_String2ExprMap *macro_map, DF_Eval eval, struct DF_CfgVal *val)
#define DF_CORE_VIEW_RULE_EVAL_RESOLUTION_FUNCTION_NAME(name) df_core_view_rule_eval_resolution__##name
#define DF_CORE_VIEW_RULE_EVAL_RESOLUTION_FUNCTION_DEF(name) internal DF_CORE_VIEW_RULE_EVAL_RESOLUTION_FUNCTION_SIG(DF_CORE_VIEW_RULE_EVAL_RESOLUTION_FUNCTION_NAME(name))
#define DF_CORE_VIEW_RULE_VIZ_BLOCK_PROD_FUNCTION_SIG(name) void name(Arena *arena, DBGI_Scope *dbgi_scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, struct DF_EvalView *eval_view, DF_Eval eval, struct DF_CfgTable *cfg_table, DF_ExpandKey parent_key, DF_ExpandKey key, S32 depth, struct DF_CfgNode *cfg, struct DF_EvalVizBlockList *out)
#define DF_CORE_VIEW_RULE_VIZ_BLOCK_PROD_FUNCTION_SIG(name) void name(Arena *arena, DBGI_Scope *dbgi_scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, EVAL_String2ExprMap *macro_map, struct DF_EvalView *eval_view, DF_Eval eval, struct DF_CfgTable *cfg_table, DF_ExpandKey parent_key, DF_ExpandKey key, S32 depth, struct DF_CfgNode *cfg, struct DF_EvalVizBlockList *out)
#define DF_CORE_VIEW_RULE_VIZ_BLOCK_PROD_FUNCTION_NAME(name) df_core_view_rule_viz_block_prod__##name
#define DF_CORE_VIEW_RULE_VIZ_BLOCK_PROD_FUNCTION_DEF(name) internal DF_CORE_VIEW_RULE_VIZ_BLOCK_PROD_FUNCTION_SIG(DF_CORE_VIEW_RULE_VIZ_BLOCK_PROD_FUNCTION_NAME(name))
typedef DF_CORE_VIEW_RULE_EVAL_RESOLUTION_FUNCTION_SIG(DF_CoreViewRuleEvalResolutionHookFunctionType);
@@ -564,6 +492,23 @@ struct DF_EntityRec
S32 pop_count;
};
////////////////////////////////
//~ rjf: Entity Fuzzy Listing Types
typedef struct DF_EntityFuzzyItem DF_EntityFuzzyItem;
struct DF_EntityFuzzyItem
{
DF_Entity *entity;
FuzzyMatchRangeList matches;
};
typedef struct DF_EntityFuzzyItemArray DF_EntityFuzzyItemArray;
struct DF_EntityFuzzyItemArray
{
DF_EntityFuzzyItem *v;
U64 count;
};
////////////////////////////////
//~ rjf: Text Slices (output type from data which can be used to produce readable text)
@@ -693,13 +638,6 @@ struct DF_EvalView
// rjf: expansion state
DF_ExpandTreeTable expand_tree_table;
// rjf: key -> value history cache
U64 history_cache_table_size;
U64 history_cache_table_num_active_nodes;
DF_EvalHistoryCacheSlot *history_cache_table;
DF_EvalHistoryCacheNode *history_cache_lru_first;
DF_EvalHistoryCacheNode *history_cache_lru_last;
// rjf: key -> view rule cache
DF_EvalViewRuleCacheTable view_rule_table;
};
@@ -752,11 +690,14 @@ struct DF_EvalLinkBaseArray
typedef enum DF_EvalVizBlockKind
{
DF_EvalVizBlockKind_Root,
DF_EvalVizBlockKind_Members,
DF_EvalVizBlockKind_Elements,
DF_EvalVizBlockKind_Links,
DF_EvalVizBlockKind_Canvas,
DF_EvalVizBlockKind_Null, // empty
DF_EvalVizBlockKind_Root, // root of tree or subtree; possibly-expandable expression.
DF_EvalVizBlockKind_Members, // members of struct, class, union
DF_EvalVizBlockKind_EnumMembers, // members of enum
DF_EvalVizBlockKind_Elements, // elements of array
DF_EvalVizBlockKind_Links, // flattened nodes in a linked list
DF_EvalVizBlockKind_Canvas, // escape hatch for arbitrary UI
DF_EvalVizBlockKind_DebugInfoTable, // block of filtered debug info table elements
DF_EvalVizBlockKind_COUNT,
}
DF_EvalVizBlockKind;
@@ -764,26 +705,50 @@ DF_EvalVizBlockKind;
typedef struct DF_EvalVizBlock DF_EvalVizBlock;
struct DF_EvalVizBlock
{
DF_EvalVizBlock *next;
// rjf: kind & keys
DF_EvalVizBlockKind kind;
DF_EvalView *eval_view;
DF_Eval eval;
TG_Key link_member_type_key;
U64 link_member_off;
DF_CfgTable cfg_table;
String8 string;
DF_ExpandKey parent_key;
DF_ExpandKey key;
S32 depth;
// rjf: evaluation info
DF_Eval eval;
String8 string;
TG_Member *member;
// rjf: info about ranges that this block spans
Rng1U64 visual_idx_range;
Rng1U64 semantic_idx_range;
S32 depth;
DBGI_FuzzySearchTarget dbgi_target;
DBGI_FuzzySearchItemArray backing_search_items;
// rjf: visualization config extensions
DF_CfgTable cfg_table;
TG_Key link_member_type_key;
U64 link_member_off;
};
typedef struct DF_EvalVizBlockNode DF_EvalVizBlockNode;
struct DF_EvalVizBlockNode
{
DF_EvalVizBlockNode *next;
DF_EvalVizBlock v;
};
typedef struct DF_EvalVizBlockList DF_EvalVizBlockList;
struct DF_EvalVizBlockList
{
DF_EvalVizBlock *first;
DF_EvalVizBlock *last;
DF_EvalVizBlockNode *first;
DF_EvalVizBlockNode *last;
U64 count;
U64 total_visual_row_count;
U64 total_semantic_row_count;
};
typedef struct DF_EvalVizBlockArray DF_EvalVizBlockArray;
struct DF_EvalVizBlockArray
{
DF_EvalVizBlock *v;
U64 count;
U64 total_visual_row_count;
U64 total_semantic_row_count;
@@ -803,6 +768,7 @@ enum
DF_EvalVizRowFlag_CanExpand = (1<<0),
DF_EvalVizRowFlag_CanEditValue = (1<<1),
DF_EvalVizRowFlag_Canvas = (1<<2),
DF_EvalVizRowFlag_ExprIsSpecial= (1<<3),
};
typedef struct DF_EvalVizRow DF_EvalVizRow;
@@ -811,8 +777,12 @@ struct DF_EvalVizRow
DF_EvalVizRow *next;
DF_EvalVizRowFlags flags;
// rjf: eval & eval view state
DF_EvalView *eval_view;
// rjf: block info
S32 depth;
DF_ExpandKey parent_key;
DF_ExpandKey key;
// rjf: evaluation artifacts
DF_Eval eval;
// rjf: basic visualization contents
@@ -831,14 +801,6 @@ struct DF_EvalVizRow
// rjf: value area override view rule spec
struct DF_GfxViewRuleSpec *value_ui_rule_spec;
struct DF_CfgNode *value_ui_rule_node;
// rjf: errors
EVAL_ErrorList errors;
// rjf: tree depth & keys
S32 depth;
DF_ExpandKey parent_key;
DF_ExpandKey key;
};
typedef struct DF_EvalVizWindowedRowList DF_EvalVizWindowedRowList;
@@ -976,7 +938,8 @@ struct DF_RunUnwindCacheNode
{
DF_RunUnwindCacheNode *hash_next;
DF_Handle thread;
DF_Unwind unwind;
CTRL_Unwind unwind;
U64 tls_base_vaddr;
};
typedef struct DF_RunUnwindCacheSlot DF_RunUnwindCacheSlot;
@@ -994,6 +957,33 @@ struct DF_RunUnwindCache
DF_RunUnwindCacheSlot *table;
};
//- rjf: per-run tls-base-vaddr cache
typedef struct DF_RunTLSBaseCacheNode DF_RunTLSBaseCacheNode;
struct DF_RunTLSBaseCacheNode
{
DF_RunTLSBaseCacheNode *hash_next;
DF_Handle process;
U64 root_vaddr;
U64 rip_vaddr;
U64 tls_base_vaddr;
};
typedef struct DF_RunTLSBaseCacheSlot DF_RunTLSBaseCacheSlot;
struct DF_RunTLSBaseCacheSlot
{
DF_RunTLSBaseCacheNode *first;
DF_RunTLSBaseCacheNode *last;
};
typedef struct DF_RunTLSBaseCache DF_RunTLSBaseCache;
struct DF_RunTLSBaseCache
{
Arena *arena;
U64 slots_count;
DF_RunTLSBaseCacheSlot *slots;
};
//- rjf: per-run locals cache
typedef struct DF_RunLocalsCacheNode DF_RunLocalsCacheNode;
@@ -1146,6 +1136,9 @@ struct DF_State
U64 unwind_cache_reggen_idx;
U64 unwind_cache_memgen_idx;
DF_RunUnwindCache unwind_cache;
U64 tls_base_cache_reggen_idx;
U64 tls_base_cache_memgen_idx;
DF_RunTLSBaseCache tls_base_cache;
U64 locals_cache_reggen_idx;
DF_RunLocalsCache locals_cache;
U64 member_cache_reggen_idx;
@@ -1300,7 +1293,7 @@ internal void df_state_delta_history_wind(DF_StateDeltaHistory *hist, Side side)
//~ rjf: Sparse Tree Expansion State Data Structure
//- rjf: keys
internal DF_ExpandKey df_expand_key_make(U64 uniquifier, U64 parent_hash, U64 child_num);
internal DF_ExpandKey df_expand_key_make(U64 parent_hash, U64 child_num);
internal DF_ExpandKey df_expand_key_zero(void);
internal B32 df_expand_key_match(DF_ExpandKey a, DF_ExpandKey b);
@@ -1396,6 +1389,10 @@ internal void df_entity_list_push(Arena *arena, DF_EntityList *list, DF_Entity *
internal DF_EntityArray df_entity_array_from_list(Arena *arena, DF_EntityList *list);
#define df_first_entity_from_list(list) ((list)->first != 0 ? (list)->first->entity : &df_g_nil_entity)
//- rjf: entity fuzzy list building
internal DF_EntityFuzzyItemArray df_entity_fuzzy_item_array_from_entity_list_needle(Arena *arena, DF_EntityList *list, String8 needle);
internal DF_EntityFuzzyItemArray df_entity_fuzzy_item_array_from_entity_array_needle(Arena *arena, DF_EntityArray *array, String8 needle);
//- rjf: entity -> text info
internal TXTI_Handle df_txti_handle_from_entity(DF_Entity *entity);
@@ -1408,6 +1405,9 @@ internal String8 df_full_path_from_entity(Arena *arena, DF_Entity *entity);
//- rjf: display string entities, for referencing entities in ui
internal String8 df_display_string_from_entity(Arena *arena, DF_Entity *entity);
//- rjf: extra search tag strings for fuzzy filtering entities
internal String8 df_search_tags_from_entity(Arena *arena, DF_Entity *entity);
//- rjf: entity -> color operations
internal Vec4F32 df_hsva_from_entity(DF_Entity *entity);
internal Vec4F32 df_rgba_from_entity(DF_Entity *entity);
@@ -1543,9 +1543,9 @@ internal U64 df_type_num_from_binary_name(DF_Entity *binary, String8 name);
//- rjf: thread info extraction helpers
internal DF_Entity *df_module_from_process_vaddr(DF_Entity *process, U64 vaddr);
internal DF_Entity *df_module_from_thread(DF_Entity *thread);
internal U64 df_tls_base_vaddr_from_thread(DF_Entity *thread);
internal U64 df_tls_base_vaddr_from_process_root_rip(DF_Entity *process, U64 root_vaddr, U64 rip_vaddr);
internal Architecture df_architecture_from_entity(DF_Entity *entity);
internal DF_Unwind df_push_unwind_from_thread(Arena *arena, DF_Entity *thread);
internal CTRL_Unwind df_push_unwind_from_thread(Arena *arena, DF_Entity *thread);
internal U64 df_rip_from_thread(DF_Entity *thread);
internal U64 df_rip_from_thread_unwind(DF_Entity *thread, U64 unwind_count);
internal EVAL_String2NumMap *df_push_locals_map_from_binary_voff(Arena *arena, DBGI_Scope *scope, DF_Entity *binary, U64 voff);
@@ -1576,10 +1576,10 @@ internal CTRL_Event df_ctrl_last_stop_event(void);
internal B32 df_eval_memory_read(void *u, void *out, U64 addr, U64 size);
internal EVAL_ParseCtx df_eval_parse_ctx_from_process_vaddr(DBGI_Scope *scope, DF_Entity *process, U64 vaddr);
internal EVAL_ParseCtx df_eval_parse_ctx_from_src_loc(DBGI_Scope *scope, DF_Entity *file, TxtPt pt);
internal DF_Eval df_eval_from_string(Arena *arena, DBGI_Scope *scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, String8 string);
internal DF_Eval df_eval_from_string(Arena *arena, DBGI_Scope *scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, EVAL_String2ExprMap *macro_map, String8 string);
internal DF_Eval df_value_mode_eval_from_eval(TG_Graph *graph, RADDBG_Parsed *rdbg, DF_CtrlCtx *ctrl_ctx, DF_Eval eval);
internal DF_Eval df_dynamically_typed_eval_from_eval(TG_Graph *graph, RADDBG_Parsed *rdbg, DF_CtrlCtx *ctrl_ctx, DF_Eval eval);
internal DF_Eval df_eval_from_eval_cfg_table(Arena *arena, DBGI_Scope *scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_Eval eval, DF_CfgTable *cfg);
internal DF_Eval df_eval_from_eval_cfg_table(Arena *arena, DBGI_Scope *scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, EVAL_String2ExprMap *macro_map, DF_Eval eval, DF_CfgTable *cfg);
////////////////////////////////
//~ rjf: Evaluation Views
@@ -1593,16 +1593,12 @@ internal B32 df_eval_view_key_match(DF_EvalViewKey a, DF_EvalViewKey b);
//- rjf: cache lookup
internal DF_EvalView *df_eval_view_from_key(DF_EvalViewKey key);
//- rjf: key -> eval history
internal DF_EvalHistoryCacheNode *df_eval_history_cache_node_from_key(DF_EvalView *eval_view, DF_ExpandKey key);
internal B32 df_eval_view_record_history_val(DF_EvalView *eval_view, DF_ExpandKey key, DF_EvalHistoryVal val);
//- rjf: key -> view rules
internal void df_eval_view_set_key_rule(DF_EvalView *eval_view, DF_ExpandKey key, String8 view_rule_string);
internal String8 df_eval_view_rule_from_key(DF_EvalView *eval_view, DF_ExpandKey key);
////////////////////////////////
//~ rjf: Evaluation View Visualization & Interaction
//~ rjf: Evaluation Visualization
//- rjf: evaluation value string builder helpers
internal String8 df_string_from_ascii_value(Arena *arena, U8 val);
@@ -1617,11 +1613,22 @@ internal DF_EvalLinkBaseChunkList df_eval_link_base_chunk_list_from_eval(Arena *
internal DF_EvalLinkBase df_eval_link_base_from_chunk_list_index(DF_EvalLinkBaseChunkList *list, U64 idx);
internal DF_EvalLinkBaseArray df_eval_link_base_array_from_chunk_list(Arena *arena, DF_EvalLinkBaseChunkList *chunks);
//- rjf: watch tree visualization
internal void df_append_viz_blocks_for_parent__rec(Arena *arena, DBGI_Scope *scope, DF_EvalView *view, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_ExpandKey parent_key, DF_ExpandKey key, String8 string, DF_Eval eval, DF_CfgTable *cfg_table, S32 depth, DF_EvalVizBlockList *list_out);
internal DF_EvalVizBlockList df_eval_viz_block_list_from_eval_view_expr(Arena *arena, DBGI_Scope *scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_EvalView *eval_view, String8 expr);
//- rjf: viz block collection building
internal DF_EvalVizBlock *df_eval_viz_block_begin(Arena *arena, DF_EvalVizBlockKind kind, DF_ExpandKey parent_key, DF_ExpandKey key, S32 depth);
internal DF_EvalVizBlock *df_eval_viz_block_split_and_continue(Arena *arena, DF_EvalVizBlockList *list, DF_EvalVizBlock *split_block, U64 split_idx);
internal void df_eval_viz_block_end(DF_EvalVizBlockList *list, DF_EvalVizBlock *block);
internal void df_append_viz_blocks_for_parent__rec(Arena *arena, DBGI_Scope *scope, DF_EvalView *view, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, EVAL_String2ExprMap *macro_map, DF_ExpandKey parent_key, DF_ExpandKey key, String8 string, DF_Eval eval, TG_Member *opt_member, DF_CfgTable *cfg_table, S32 depth, DF_EvalVizBlockList *list_out);
internal DF_EvalVizBlockList df_eval_viz_block_list_from_eval_view_expr_num(Arena *arena, DBGI_Scope *scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, EVAL_String2ExprMap *macro_map, DF_EvalView *eval_view, String8 expr, U64 num);
internal void df_eval_viz_block_list_concat__in_place(DF_EvalVizBlockList *dst, DF_EvalVizBlockList *to_push);
//- rjf: viz block list <-> table coordinates
internal S64 df_row_num_from_viz_block_list_key(DF_EvalVizBlockList *blocks, DF_ExpandKey key);
internal DF_ExpandKey df_key_from_viz_block_list_row_num(DF_EvalVizBlockList *blocks, S64 row_num);
internal DF_ExpandKey df_parent_key_from_viz_block_list_row_num(DF_EvalVizBlockList *blocks, S64 row_num);
//- rjf: viz row list building
internal DF_EvalVizRow *df_eval_viz_row_list_push_new(Arena *arena, EVAL_ParseCtx *parse_ctx, DF_EvalVizWindowedRowList *rows, DF_EvalVizBlock *block, DF_ExpandKey key, DF_Eval eval);
////////////////////////////////
//~ rjf: Main State Accessors/Mutators
@@ -1668,9 +1675,10 @@ internal DF_EntityList df_push_active_binary_list(Arena *arena);
internal DF_EntityList df_push_active_target_list(Arena *arena);
//- rjf: per-run caches
internal DF_Unwind df_query_cached_unwind_from_thread(DF_Entity *thread);
internal CTRL_Unwind df_query_cached_unwind_from_thread(DF_Entity *thread);
internal U64 df_query_cached_rip_from_thread(DF_Entity *thread);
internal U64 df_query_cached_rip_from_thread_unwind(DF_Entity *thread, U64 unwind_count);
internal U64 df_query_cached_tls_base_vaddr_from_process_root_rip(DF_Entity *process, U64 root_vaddr, U64 rip_vaddr);
internal EVAL_String2NumMap *df_query_cached_locals_map_from_binary_voff(DF_Entity *binary, U64 voff);
internal EVAL_String2NumMap *df_query_cached_member_map_from_binary_voff(DF_Entity *binary, U64 voff);
+13 -3
View File
@@ -66,6 +66,7 @@ DF_EntityKindTable:
{Thread thread 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 "Label" Thread "Thread" }
{Module module 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 "Label" Module "Module" }
{DebugInfoOverride debug_info_override 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 "Label" Null "Debug Info Override" }
{PendingThreadName pending_thread_name 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 "Label" Threads "Pending Thread Name" }
//- rjf: parser task entities
{ConversionTask conversion_task 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 "Label" Null "Conversion Task" }
@@ -353,19 +354,28 @@ DF_CoreCmdTable:// | | |
{SpawnEntityView 1 Null Nil 0 0 0 0 0 0 Null "spawn_entity_view" "Spawn Entity View" "Spawns a new view, given an entity and other parameterizations." "" }
{FindCodeLocation 1 FilePath Nil 0 0 0 0 0 1 FileOutline "find_code_location" "Find Code Location" "Finds a specific source code location given file, line, and column coordinates. Opens the file if necessary." "" }
//- rjf: general-purpose view filtering
{Filter 0 Null Nil 0 0 0 0 0 0 Find "filter" "Filter" "Begins filtering the active view." "sort,search,filter,find" }
{ApplyFilter 0 Null Nil 0 0 0 0 0 0 Find "apply_filter" "Apply Filter" "Applies the typed filter to the active view." "sort,search,filter,find,apply" }
{ClearFilter 0 Null Nil 0 0 0 0 0 0 Find "clear_filter" "Clear Filter" "Clears the filter applied to the active view." "sort,search,filter,find,clear" }
//- rjf: view drivers
{Commands 0 Null Nil 0 0 0 0 0 0 List "commands" "Commands" "Opens the list of all commands." "" }
{Commands 1 Null Nil 0 0 0 0 0 0 List "commands" "Commands" "Opens the list of all commands." "" }
{Target 1 Null Nil 0 0 0 0 0 0 Target "target" "Target" "Opens the editor for a target." "" }
{Targets 0 Null Nil 0 0 0 0 0 0 Target "targets" "Targets" "Opens the list of all targets." "" }
{FilePathMap 0 Null Nil 0 0 0 0 0 0 FileOutline "file_path_map" "File Path Map" "Opens the file path mapping editor." "" }
{Scheduler 0 Null Nil 0 0 0 0 0 0 Scheduler "scheduler" "Scheduler" "Opens the scheduler view, for process and thread controls." "" }
{Scheduler 0 Null Nil 0 0 0 0 0 0 Scheduler "scheduler" "Scheduler" "Opens the scheduler view, for process and thread controls." "threads,processes,targets" }
{CallStack 0 Null Nil 0 0 0 0 0 0 Thread "call_stack" "Call Stack" "Opens the call stack view." "callstack,thread" }
{Modules 0 Null Nil 0 0 0 0 0 0 Module "modules" "Modules" "Opens the modules view." "" }
{PendingEntity 1 Null Nil 0 0 0 0 0 0 FileOutline "pending_entity" "Pending Entity" "Opens a view which waits for the passed entity to be completely loaded, then replaces itself with a new view." "" }
{Code 1 Null Nil 0 0 0 0 0 0 FileOutline "code" "Code" "Opens the code view for an already-loaded file." "" }
{Watch 0 Null Nil 0 0 0 0 0 0 Binoculars "watch" "Watch" "Opens a watch view." "" }
{Locals 0 Null Nil 0 0 0 0 0 0 Binoculars "locals" "Locals" "Opens a locals view." "" }
{Registers 0 Null Nil 0 0 0 0 0 0 Binoculars "registers" "Registers" "Opens a registers view for the currently selected thread." "" }
{Registers 0 Null Nil 0 0 0 0 0 0 Binoculars "registers" "Registers" "Opens a registers view." "" }
{Globals 0 Null Nil 0 0 0 0 0 0 Binoculars "globals" "Globals" "Opens a globals view." "" }
{ThreadLocals 0 Null Nil 0 0 0 0 0 0 Binoculars "thread_locals" "Thread Locals" "Opens a thread locals view." "" }
{Types 0 Null Nil 0 0 0 0 0 0 Binoculars "types" "Types" "Opens a types view." "" }
{Procedures 0 Null Nil 0 0 0 0 0 0 Binoculars "procedures" "Procedures" "Opens a procedures view." "" }
{Output 0 Null Nil 0 0 0 0 0 0 List "output" "Output" "Opens an output view." "" }
{Memory 0 Null Nil 0 0 0 0 0 0 Grid "memory" "Memory" "Opens a memory view." "" }
{Disassembly 0 Null Nil 0 0 0 0 0 0 Glasses "disassembly" "Disassembly" "Opens the disassembly view." "disasm" }
+10 -3
View File
@@ -179,18 +179,25 @@ DF_CmdSpecInfo df_g_core_cmd_kind_spec_info_table[] =
{ str8_lit_comp("entity_ref_fast_path"), str8_lit_comp("Activates the default behavior when clicking an entity reference."), str8_lit_comp(""), str8_lit_comp("Entity Reference Fast Path"), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("spawn_entity_view"), str8_lit_comp("Spawns a new view, given an entity and other parameterizations."), str8_lit_comp(""), str8_lit_comp("Spawn Entity View"), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("find_code_location"), str8_lit_comp("Finds a specific source code location given file, line, and column coordinates. Opens the file if necessary."), str8_lit_comp(""), str8_lit_comp("Find Code Location"), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_FilePath, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*1)}, DF_IconKind_FileOutline},
{ str8_lit_comp("commands"), str8_lit_comp("Opens the list of all commands."), str8_lit_comp(""), str8_lit_comp("Commands"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_List},
{ str8_lit_comp("filter"), str8_lit_comp("Begins filtering the active view."), str8_lit_comp("sort,search,filter,find"), str8_lit_comp("Filter"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Find},
{ str8_lit_comp("apply_filter"), str8_lit_comp("Applies the typed filter to the active view."), str8_lit_comp("sort,search,filter,find,apply"), str8_lit_comp("Apply Filter"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Find},
{ str8_lit_comp("clear_filter"), str8_lit_comp("Clears the filter applied to the active view."), str8_lit_comp("sort,search,filter,find,clear"), str8_lit_comp("Clear Filter"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Find},
{ str8_lit_comp("commands"), str8_lit_comp("Opens the list of all commands."), str8_lit_comp(""), str8_lit_comp("Commands"), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_List},
{ str8_lit_comp("target"), str8_lit_comp("Opens the editor for a target."), str8_lit_comp(""), str8_lit_comp("Target"), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Target},
{ str8_lit_comp("targets"), str8_lit_comp("Opens the list of all targets."), str8_lit_comp(""), str8_lit_comp("Targets"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Target},
{ str8_lit_comp("file_path_map"), str8_lit_comp("Opens the file path mapping editor."), str8_lit_comp(""), str8_lit_comp("File Path Map"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_FileOutline},
{ str8_lit_comp("scheduler"), str8_lit_comp("Opens the scheduler view, for process and thread controls."), str8_lit_comp(""), str8_lit_comp("Scheduler"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Scheduler},
{ str8_lit_comp("scheduler"), str8_lit_comp("Opens the scheduler view, for process and thread controls."), str8_lit_comp("threads,processes,targets"), str8_lit_comp("Scheduler"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Scheduler},
{ str8_lit_comp("call_stack"), str8_lit_comp("Opens the call stack view."), str8_lit_comp("callstack,thread"), str8_lit_comp("Call Stack"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Thread},
{ str8_lit_comp("modules"), str8_lit_comp("Opens the modules view."), str8_lit_comp(""), str8_lit_comp("Modules"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Module},
{ str8_lit_comp("pending_entity"), str8_lit_comp("Opens a view which waits for the passed entity to be completely loaded, then replaces itself with a new view."), str8_lit_comp(""), str8_lit_comp("Pending Entity"), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_FileOutline},
{ str8_lit_comp("code"), str8_lit_comp("Opens the code view for an already-loaded file."), str8_lit_comp(""), str8_lit_comp("Code"), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_FileOutline},
{ str8_lit_comp("watch"), str8_lit_comp("Opens a watch view."), str8_lit_comp(""), str8_lit_comp("Watch"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Binoculars},
{ str8_lit_comp("locals"), str8_lit_comp("Opens a locals view."), str8_lit_comp(""), str8_lit_comp("Locals"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Binoculars},
{ str8_lit_comp("registers"), str8_lit_comp("Opens a registers view for the currently selected thread."), str8_lit_comp(""), str8_lit_comp("Registers"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Binoculars},
{ str8_lit_comp("registers"), str8_lit_comp("Opens a registers view."), str8_lit_comp(""), str8_lit_comp("Registers"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Binoculars},
{ str8_lit_comp("globals"), str8_lit_comp("Opens a globals view."), str8_lit_comp(""), str8_lit_comp("Globals"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Binoculars},
{ str8_lit_comp("thread_locals"), str8_lit_comp("Opens a thread locals view."), str8_lit_comp(""), str8_lit_comp("Thread Locals"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Binoculars},
{ str8_lit_comp("types"), str8_lit_comp("Opens a types view."), str8_lit_comp(""), str8_lit_comp("Types"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Binoculars},
{ str8_lit_comp("procedures"), str8_lit_comp("Opens a procedures view."), str8_lit_comp(""), str8_lit_comp("Procedures"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Binoculars},
{ str8_lit_comp("output"), str8_lit_comp("Opens an output view."), str8_lit_comp(""), str8_lit_comp("Output"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_List},
{ str8_lit_comp("memory"), str8_lit_comp("Opens a memory view."), str8_lit_comp(""), str8_lit_comp("Memory"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Grid},
{ str8_lit_comp("disassembly"), str8_lit_comp("Opens the disassembly view."), str8_lit_comp("disasm"), str8_lit_comp("Disassembly"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Glasses},
+13
View File
@@ -40,6 +40,7 @@ DF_EntityKind_Process,
DF_EntityKind_Thread,
DF_EntityKind_Module,
DF_EntityKind_DebugInfoOverride,
DF_EntityKind_PendingThreadName,
DF_EntityKind_ConversionTask,
DF_EntityKind_ConversionFail,
DF_EntityKind_EndedProcess,
@@ -230,6 +231,9 @@ DF_CoreCmdKind_RegisterAsJITDebugger,
DF_CoreCmdKind_EntityRefFastPath,
DF_CoreCmdKind_SpawnEntityView,
DF_CoreCmdKind_FindCodeLocation,
DF_CoreCmdKind_Filter,
DF_CoreCmdKind_ApplyFilter,
DF_CoreCmdKind_ClearFilter,
DF_CoreCmdKind_Commands,
DF_CoreCmdKind_Target,
DF_CoreCmdKind_Targets,
@@ -242,6 +246,10 @@ DF_CoreCmdKind_Code,
DF_CoreCmdKind_Watch,
DF_CoreCmdKind_Locals,
DF_CoreCmdKind_Registers,
DF_CoreCmdKind_Globals,
DF_CoreCmdKind_ThreadLocals,
DF_CoreCmdKind_Types,
DF_CoreCmdKind_Procedures,
DF_CoreCmdKind_Output,
DF_CoreCmdKind_Memory,
DF_CoreCmdKind_Disassembly,
@@ -1555,6 +1563,7 @@ DF_IconKind_Threads,
DF_IconKind_Thread,
DF_IconKind_Module,
DF_IconKind_Null,
DF_IconKind_Threads,
DF_IconKind_Null,
DF_IconKind_Null,
DF_IconKind_Null,
@@ -1585,6 +1594,7 @@ str8_lit_comp("Process"),
str8_lit_comp("Thread"),
str8_lit_comp("Module"),
str8_lit_comp("Debug Info Override"),
str8_lit_comp("Pending Thread Name"),
str8_lit_comp("Conversion Task"),
str8_lit_comp("Conversion Failure"),
str8_lit_comp("EndedProcess"),
@@ -1618,6 +1628,7 @@ str8_lit_comp("Label"),
str8_lit_comp("Label"),
str8_lit_comp("Label"),
str8_lit_comp("Label"),
str8_lit_comp("Label"),
};
DF_EntityKindFlags df_g_entity_kind_flags_table[] =
@@ -1648,6 +1659,7 @@ DF_EntityKindFlags df_g_entity_kind_flags_table[] =
(0*DF_EntityKindFlag_LeafMutationUserConfig | 0*DF_EntityKindFlag_LeafMutationProfileConfig | 0*DF_EntityKindFlag_LeafMutationSoftHalt | 0*DF_EntityKindFlag_LeafMutationDebugInfoMap | 0*DF_EntityKindFlag_TreeMutationUserConfig | 0*DF_EntityKindFlag_TreeMutationProfileConfig | 0*DF_EntityKindFlag_TreeMutationSoftHalt | 0*DF_EntityKindFlag_TreeMutationDebugInfoMap | 0*DF_EntityKindFlag_NameIsCode | 0*DF_EntityKindFlag_UserDefinedLifetime),
(0*DF_EntityKindFlag_LeafMutationUserConfig | 0*DF_EntityKindFlag_LeafMutationProfileConfig | 0*DF_EntityKindFlag_LeafMutationSoftHalt | 0*DF_EntityKindFlag_LeafMutationDebugInfoMap | 0*DF_EntityKindFlag_TreeMutationUserConfig | 0*DF_EntityKindFlag_TreeMutationProfileConfig | 0*DF_EntityKindFlag_TreeMutationSoftHalt | 0*DF_EntityKindFlag_TreeMutationDebugInfoMap | 0*DF_EntityKindFlag_NameIsCode | 0*DF_EntityKindFlag_UserDefinedLifetime),
(0*DF_EntityKindFlag_LeafMutationUserConfig | 0*DF_EntityKindFlag_LeafMutationProfileConfig | 0*DF_EntityKindFlag_LeafMutationSoftHalt | 0*DF_EntityKindFlag_LeafMutationDebugInfoMap | 0*DF_EntityKindFlag_TreeMutationUserConfig | 0*DF_EntityKindFlag_TreeMutationProfileConfig | 0*DF_EntityKindFlag_TreeMutationSoftHalt | 0*DF_EntityKindFlag_TreeMutationDebugInfoMap | 0*DF_EntityKindFlag_NameIsCode | 0*DF_EntityKindFlag_UserDefinedLifetime),
(0*DF_EntityKindFlag_LeafMutationUserConfig | 0*DF_EntityKindFlag_LeafMutationProfileConfig | 0*DF_EntityKindFlag_LeafMutationSoftHalt | 0*DF_EntityKindFlag_LeafMutationDebugInfoMap | 0*DF_EntityKindFlag_TreeMutationUserConfig | 0*DF_EntityKindFlag_TreeMutationProfileConfig | 0*DF_EntityKindFlag_TreeMutationSoftHalt | 0*DF_EntityKindFlag_TreeMutationDebugInfoMap | 0*DF_EntityKindFlag_NameIsCode | 0*DF_EntityKindFlag_UserDefinedLifetime),
};
DF_EntityOpFlags df_g_entity_kind_op_flags_table[] =
@@ -1675,6 +1687,7 @@ DF_EntityOpFlags df_g_entity_kind_op_flags_table[] =
(0*DF_EntityOpFlag_Delete) | (1*DF_EntityOpFlag_Freeze) | (0*DF_EntityOpFlag_Edit) | (1*DF_EntityOpFlag_Rename) | (0*DF_EntityOpFlag_Enable) | (0*DF_EntityOpFlag_Condition) | (0*DF_EntityOpFlag_Duplicate),
(0*DF_EntityOpFlag_Delete) | (0*DF_EntityOpFlag_Freeze) | (0*DF_EntityOpFlag_Edit) | (0*DF_EntityOpFlag_Rename) | (0*DF_EntityOpFlag_Enable) | (0*DF_EntityOpFlag_Condition) | (0*DF_EntityOpFlag_Duplicate),
(0*DF_EntityOpFlag_Delete) | (0*DF_EntityOpFlag_Freeze) | (0*DF_EntityOpFlag_Edit) | (0*DF_EntityOpFlag_Rename) | (0*DF_EntityOpFlag_Enable) | (0*DF_EntityOpFlag_Condition) | (0*DF_EntityOpFlag_Duplicate),
(0*DF_EntityOpFlag_Delete) | (0*DF_EntityOpFlag_Freeze) | (0*DF_EntityOpFlag_Edit) | (0*DF_EntityOpFlag_Rename) | (0*DF_EntityOpFlag_Enable) | (0*DF_EntityOpFlag_Condition) | (0*DF_EntityOpFlag_Duplicate),
(0*DF_EntityOpFlag_Delete) | (0*DF_EntityOpFlag_Freeze) | (0*DF_EntityOpFlag_Edit) | (1*DF_EntityOpFlag_Rename) | (0*DF_EntityOpFlag_Enable) | (0*DF_EntityOpFlag_Condition) | (0*DF_EntityOpFlag_Duplicate),
(0*DF_EntityOpFlag_Delete) | (0*DF_EntityOpFlag_Freeze) | (0*DF_EntityOpFlag_Edit) | (1*DF_EntityOpFlag_Rename) | (0*DF_EntityOpFlag_Enable) | (0*DF_EntityOpFlag_Condition) | (0*DF_EntityOpFlag_Duplicate),
(1*DF_EntityOpFlag_Delete) | (0*DF_EntityOpFlag_Freeze) | (0*DF_EntityOpFlag_Edit) | (1*DF_EntityOpFlag_Rename) | (0*DF_EntityOpFlag_Enable) | (0*DF_EntityOpFlag_Condition) | (0*DF_EntityOpFlag_Duplicate),
+1035 -740
View File
File diff suppressed because it is too large Load Diff
+41 -23
View File
@@ -164,9 +164,12 @@ typedef DF_VIEW_UI_FUNCTION_SIG(DF_ViewUIFunctionType);
typedef U32 DF_ViewSpecFlags;
enum
{
DF_ViewSpecFlag_ParameterizedByEntity = (1<<0),
DF_ViewSpecFlag_CanSerialize = (1<<1),
DF_ViewSpecFlag_CanSerializeEntityPath = (1<<2),
DF_ViewSpecFlag_ParameterizedByEntity = (1<<0),
DF_ViewSpecFlag_CanSerialize = (1<<1),
DF_ViewSpecFlag_CanSerializeEntityPath = (1<<2),
DF_ViewSpecFlag_CanFilter = (1<<3),
DF_ViewSpecFlag_FilterIsCode = (1<<4),
DF_ViewSpecFlag_TypingAutomaticallyFilters = (1<<5),
};
typedef struct DF_ViewSpecInfo DF_ViewSpecInfo;
@@ -197,6 +200,22 @@ struct DF_ViewSpecInfoArray
U64 count;
};
typedef struct DF_CmdParamSlotViewSpecRuleNode DF_CmdParamSlotViewSpecRuleNode;
struct DF_CmdParamSlotViewSpecRuleNode
{
DF_CmdParamSlotViewSpecRuleNode *next;
DF_ViewSpec *view_spec;
DF_CmdSpec *cmd_spec;
};
typedef struct DF_CmdParamSlotViewSpecRuleList DF_CmdParamSlotViewSpecRuleList;
struct DF_CmdParamSlotViewSpecRuleList
{
DF_CmdParamSlotViewSpecRuleNode *first;
DF_CmdParamSlotViewSpecRuleNode *last;
U64 count;
};
////////////////////////////////
//~ rjf: View Types
@@ -242,6 +261,10 @@ struct DF_View
DF_ViewSpec *spec;
DF_Handle entity;
// rjf: filter mode
B32 is_filtering;
F32 is_filtering_t;
// rjf: query -> params data
TxtPt query_cursor;
TxtPt query_mark;
@@ -333,11 +356,11 @@ enum
#define DF_GFX_VIEW_RULE_LINE_STRINGIZE_FUNCTION_NAME(name) df_gfx_view_rule_line_stringize__##name
#define DF_GFX_VIEW_RULE_LINE_STRINGIZE_FUNCTION_DEF(name) internal DF_GFX_VIEW_RULE_LINE_STRINGIZE_FUNCTION_SIG(DF_GFX_VIEW_RULE_LINE_STRINGIZE_FUNCTION_NAME(name))
#define DF_GFX_VIEW_RULE_ROW_UI_FUNCTION_SIG(name) void name(DF_ExpandKey key, DF_Eval eval, DBGI_Scope *scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, struct DF_CfgNode *cfg)
#define DF_GFX_VIEW_RULE_ROW_UI_FUNCTION_SIG(name) void name(DF_ExpandKey key, DF_Eval eval, DBGI_Scope *scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, EVAL_String2ExprMap *macro_map, struct DF_CfgNode *cfg)
#define DF_GFX_VIEW_RULE_ROW_UI_FUNCTION_NAME(name) df_gfx_view_rule_row_ui__##name
#define DF_GFX_VIEW_RULE_ROW_UI_FUNCTION_DEF(name) DF_GFX_VIEW_RULE_ROW_UI_FUNCTION_SIG(DF_GFX_VIEW_RULE_ROW_UI_FUNCTION_NAME(name))
#define DF_GFX_VIEW_RULE_BLOCK_UI_FUNCTION_SIG(name) void name(struct DF_Window *ws, DF_ExpandKey key, DF_Eval eval, DBGI_Scope *dbgi_scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, struct DF_CfgNode *cfg, Vec2F32 dim)
#define DF_GFX_VIEW_RULE_BLOCK_UI_FUNCTION_SIG(name) void name(struct DF_Window *ws, DF_ExpandKey key, DF_Eval eval, DBGI_Scope *dbgi_scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, EVAL_String2ExprMap *macro_map, struct DF_CfgNode *cfg, Vec2F32 dim)
#define DF_GFX_VIEW_RULE_BLOCK_UI_FUNCTION_NAME(name) df_gfx_view_rule_block_ui__##name
#define DF_GFX_VIEW_RULE_BLOCK_UI_FUNCTION_DEF(name) DF_GFX_VIEW_RULE_BLOCK_UI_FUNCTION_SIG(DF_GFX_VIEW_RULE_BLOCK_UI_FUNCTION_NAME(name))
@@ -483,7 +506,7 @@ struct DF_AutoCompListerItem
{
String8 string;
String8 kind_string;
DF_FuzzyMatchRangeList matches;
FuzzyMatchRangeList matches;
};
typedef struct DF_AutoCompListerItemChunkNode DF_AutoCompListerItemChunkNode;
@@ -709,8 +732,8 @@ struct DF_GfxState
DF_ViewRuleBlockSlot *view_rule_block_slots;
DF_ViewRuleBlockNode *free_view_rule_block_node;
// rjf: cmd param slot -> view spec table
DF_ViewSpec *cmd_param_slot_view_spec_table[DF_CmdParamSlot_COUNT];
// rjf: cmd param slot -> view spec rule table
DF_CmdParamSlotViewSpecRuleList cmd_param_slot_view_spec_table[DF_CmdParamSlot_COUNT];
// rjf: windows
OS_WindowRepaintFunctionType *repaint_hook;
@@ -804,7 +827,6 @@ global DF_DragDropPayload df_g_drag_drop_payload = {0};
//~ rjf: Basic Helpers
internal DF_PathQuery df_path_query_from_string(String8 string);
internal DF_FuzzyMatchRangeList df_fuzzy_match_find(Arena *arena, String8List needles, String8 haystack);
////////////////////////////////
//~ rjf: View Type Functions
@@ -892,7 +914,7 @@ internal U64 df_get_hovered_line_info_voff(void);
internal void df_register_view_specs(DF_ViewSpecInfoArray specs);
internal DF_ViewSpec *df_view_spec_from_string(String8 string);
internal DF_ViewSpec *df_view_spec_from_gfx_view_kind(DF_GfxViewKind gfx_view_kind);
internal DF_ViewSpec *df_view_spec_from_cmd_param_slot(DF_CmdParamSlot slot);
internal DF_ViewSpec *df_view_spec_from_cmd_param_slot_spec(DF_CmdParamSlot slot, DF_CmdSpec *cmd_spec);
////////////////////////////////
//~ rjf: View Rule Spec State Functions
@@ -938,8 +960,9 @@ internal void df_window_update_and_render(Arena *arena, OS_EventList *events, DF
////////////////////////////////
//~ rjf: Eval Viz
internal String8List df_single_line_eval_value_strings_from_eval(Arena *arena, DF_EvalVizStringFlags flags, TG_Graph *graph, RADDBG_Parsed *rdbg, DF_CtrlCtx *ctrl_ctx, U32 default_radix, F_Tag font, F32 font_size, F32 max_size, S32 depth, DF_Eval eval, DF_CfgTable *cfg_table);
internal DF_EvalVizWindowedRowList df_eval_viz_windowed_row_list_from_viz_block_list(Arena *arena, DBGI_Scope *scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, U32 default_radix, F_Tag font, F32 font_size, Rng1S64 visible_range, DF_EvalVizBlockList *blocks);
internal String8 df_eval_escaped_from_raw_string(Arena *arena, String8 raw);
internal String8List df_single_line_eval_value_strings_from_eval(Arena *arena, DF_EvalVizStringFlags flags, TG_Graph *graph, RADDBG_Parsed *rdbg, DF_CtrlCtx *ctrl_ctx, U32 default_radix, F_Tag font, F32 font_size, F32 max_size, S32 depth, DF_Eval eval, TG_Member *opt_member, DF_CfgTable *cfg_table);
internal DF_EvalVizWindowedRowList df_eval_viz_windowed_row_list_from_viz_block_list(Arena *arena, DBGI_Scope *scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, EVAL_String2ExprMap *macro_map, DF_EvalView *eval_view, U32 default_radix, F_Tag font, F32 font_size, Rng1S64 visible_range, DF_EvalVizBlockList *blocks);
////////////////////////////////
//~ rjf: Hover Eval
@@ -996,11 +1019,6 @@ internal F32 df_font_size_from_slot(DF_Window *ws, DF_FontSlot slot);
//- rjf: config serialization
internal String8List df_cfg_strings_from_gfx(Arena *arena, String8 root_path, DF_CfgSrc source);
////////////////////////////////
//~ rjf: UI Helpers
internal void df_box_equip_fuzzy_match_range_list_vis(UI_Box *box, DF_FuzzyMatchRangeList range_list);
////////////////////////////////
//~ rjf: UI Widgets: Fancy Buttons
@@ -1008,10 +1026,10 @@ internal void df_cmd_binding_button(DF_CmdSpec *spec);
internal UI_Signal df_menu_bar_button(String8 string);
internal UI_Signal df_cmd_spec_button(DF_CmdSpec *spec);
internal void df_cmd_list_menu_buttons(DF_Window *ws, U64 count, DF_CoreCmdKind *cmds, U32 *fastpath_codepoints);
internal UI_Signal df_icon_button(DF_IconKind kind, String8 string);
internal UI_Signal df_icon_buttonf(DF_IconKind kind, char *fmt, ...);
internal UI_Signal df_icon_button(DF_IconKind kind, FuzzyMatchRangeList *matches, String8 string);
internal UI_Signal df_icon_buttonf(DF_IconKind kind, FuzzyMatchRangeList *matches, char *fmt, ...);
internal void df_entity_tooltips(DF_Entity *entity);
internal void df_entity_desc_button(DF_Window *ws, DF_Entity *entity);
internal void df_entity_desc_button(DF_Window *ws, DF_Entity *entity, FuzzyMatchRangeList *name_matches, String8 fuzzy_query);
internal void df_entity_src_loc_button(DF_Window *ws, DF_Entity *entity, TxtPt point);
////////////////////////////////
@@ -1031,13 +1049,13 @@ internal B32 df_do_dasm_controls(DASM_Handle handle, U64 line_count_per_page, Tx
internal UI_Signal df_error_label(String8 string);
internal B32 df_help_label(String8 string);
internal D_FancyStringList df_fancy_string_list_from_code_string(Arena *arena, F32 alpha, B32 indirection_size_change, Vec4F32 base_color, String8 string);
internal void df_code_label(F32 alpha, B32 indirection_size_change, Vec4F32 base_color, String8 string);
internal UI_Box *df_code_label(F32 alpha, B32 indirection_size_change, Vec4F32 base_color, String8 string);
////////////////////////////////
//~ rjf: UI Widgets: Line Edit
internal UI_Signal df_line_edit(DF_LineEditFlags flags, S32 depth, TxtPt *cursor, TxtPt *mark, U8 *edit_buffer, U64 edit_buffer_size, U64 *edit_string_size_out, B32 *expanded_out, String8 pre_edit_value, String8 string);
internal UI_Signal df_line_editf(DF_LineEditFlags flags, S32 depth, TxtPt *cursor, TxtPt *mark, U8 *edit_buffer, U64 edit_buffer_size, U64 *edit_string_size_out, B32 *expanded_out, String8 pre_edit_value, char *fmt, ...);
internal UI_Signal df_line_edit(DF_LineEditFlags flags, S32 depth, FuzzyMatchRangeList *matches, TxtPt *cursor, TxtPt *mark, U8 *edit_buffer, U64 edit_buffer_size, U64 *edit_string_size_out, B32 *expanded_out, String8 pre_edit_value, String8 string);
internal UI_Signal df_line_editf(DF_LineEditFlags flags, S32 depth, FuzzyMatchRangeList *matches, TxtPt *cursor, TxtPt *mark, U8 *edit_buffer, U64 edit_buffer_size, U64 *edit_string_size_out, B32 *expanded_out, String8 pre_edit_value, char *fmt, ...);
////////////////////////////////
//~ rjf: Continuous Frame Requests
+55 -120
View File
@@ -52,10 +52,10 @@ DF_DefaultBindingTable:
//- rjf: focused panel changing
{ "next_panel" Comma ctrl 0 0 }
{ "prev_panel" Comma ctrl shift 0 }
{ "focus_panel_right" Right ctrl shift alt }
{ "focus_panel_left" Left ctrl shift alt }
{ "focus_panel_up" Up ctrl shift alt }
{ "focus_panel_down" Down ctrl shift alt }
{ "focus_panel_right" Right ctrl 0 alt }
{ "focus_panel_left" Left ctrl 0 alt }
{ "focus_panel_up" Up ctrl 0 alt }
{ "focus_panel_down" Down ctrl 0 alt }
//- rjf: undo/redo
//{ "undo" Z ctrl 0 0 }
@@ -76,8 +76,8 @@ DF_DefaultBindingTable:
{ "move_tab_right" PageDown ctrl shift 0 }
{ "move_tab_left" PageUp ctrl shift 0 }
{ "close_tab" W ctrl 0 0 }
{ "tab_bar_top" Up ctrl 0 alt }
{ "tab_bar_bottom" Down ctrl 0 alt }
{ "tab_bar_top" Up ctrl shift alt }
{ "tab_bar_bottom" Down ctrl shift alt }
//- rjf: files
{ "open" O ctrl 0 0 }
@@ -156,12 +156,11 @@ DF_DefaultBindingTable:
//- rjf: attaching
{ "attach" F6 0 shift 0 }
//- rjf: view drivers
{ "run_command" F1 0 0 0 }
//- rjf: filtering
{ "filter" Slash ctrl 0 0 }
//- rjf: developer commands
{ "clear_diag_log" D ctrl 0 alt }
{ "open_diag_log" D ctrl 0 0 }
//- rjf: command lister
{ "run_command" F1 0 0 0 }
}
////////////////////////////////
@@ -178,109 +177,53 @@ DF_BindingVersionRemapTable:
////////////////////////////////
//~ rjf: Gfx Layer View Kinds
@table(name, name_lower, display_string, name_kind, icon, parameterized_by_entity, can_serialize, can_serialize_entity_path, inc_in_docs, docs_desc)
@table(name, name_lower, display_string, name_kind, icon, parameterized_by_entity, can_serialize, can_serialize_entity_path, can_filter, filter_is_code, typing_automatically_filters, inc_in_docs, docs_desc)
DF_GfxViewTable:
{
{ Null "null" "" Null Null 0 0 0 0 "" }
{ Empty "empty" "" Null Null 0 0 0 0 "" }
{ Commands "commands" "Commands" Null List 0 0 0 0 "" }
{ FileSystem "file_system" "File System" Null FileOutline 0 0 0 0 "" }
{ SystemProcesses "system_processes" "System Processes" Null Null 0 0 0 0 "" }
{ EntityLister "entity_lister" "Entity List" EntityKindName Null 0 0 0 0 "" }
{ Target "target" "Target" EntityName Target 1 0 0 0 "" }
{ Targets "targets" "Targets" Null Target 0 1 0 1 "Displays a list of all targets, as well as controls for enabling, disabling, launching, editing, or deleting each target. For more information on targets, read the `Targets` section." }
{ FilePathMap "file_path_map" "File Path Map" Null FileOutline 0 1 0 1 "Displays a table of *path maps*. Each path map is a pair of file or folder paths, one being a 'source' path, and one being a 'destination' path. These pairs are used by the debugger when automatically searching for specific files - for instance, when attempting to snap to a source code location specified by debug info. If debug info refers to a path on the machine on which a target executable was originally built, but that path is not valid on the debugger machine, but some alternative path exists, then path maps may be used to redirect the debugger from the debug info's specified paths to the associated appropriate debugger machine file paths." }
{ Scheduler "scheduler" "Scheduler" Null Scheduler 0 1 0 1 "Displays all processes and threads to which the debugger is currently attached, and contains controls for selecting and freezing threads." }
{ CallStack "call_stack" "Call Stack" Null Thread 0 1 0 1 "Displays the call stack of the currently selected thread. Each frame in the call stack contains the associated module, function name, and return address. Allows selection of a particular call stack frame other than the top." }
{ Modules "modules" "Modules" Null Module 0 1 0 1 "Displays a table of all modules currently loaded by any process to which the debugger is attached. This table displays each module's name, virtual address range in the containing process' address space, and which debug info file is being used by the debugger for the associated module." }
{ PendingEntity "pending_entity" "Pending Entity" EntityName FileOutline 1 0 0 0 "" }
{ Code "code" "Code" EntityName FileOutline 1 1 1 0 "" }
{ Disassembly "disassembly" "Disassembly" Null Glasses 0 1 0 1 "Displays disassembled instructions in a textual form from the selected thread's containing process virtual address space." }
{ Watch "watch" "Watch" Null Binoculars 0 1 0 1 "The familiar 'watch window' debugger interface. Allows the inputting of a number of expressions. Each expression in the table is evaluated within the context of the selected thread's selected call stack frame. If applicable (depending on visualization rules and the expression's type), these expressions may be hierarchically expanded, which displays children as more rows in the table. The values of these expressions may also be edited, and if possible, can be used to write to registers or memory in attached processes. Also contains a new *view rule* column, not found in other major debuggers, which allows per-row specification of various visualization rules. These view rules may be used to visualize and inspect the evaluation of expressions in a variety of ways. To learn more, read the 'View Rules' section." }
{ Locals "locals" "Locals" Null Binoculars 0 1 0 1 "Nearly identical to `Watch`, but automatically filled with local variables found within the selected call stack frame of the selected thread, according to the associated debug info. View rules and evaluation values can be edited, like in `Watch`, but unlike `Watch`, expressions cannot be edited or added to the table." }
{ Registers "registers" "Registers" Null Binoculars 0 1 0 1 "Nearly identical to `Watch`, but automatically filled with all register names according to the selected thread's architecture. View rules and evaluation values can be edited, like in `Watch`, but unlike `Watch`, expressions cannot be edited or added to the table." }
{ Output "output" "Output" Null List 0 1 0 1 "Displays textual output from the selected thread's containing process." }
{ Memory "memory" "Memory" Null Grid 0 1 1 1 "A familiar hex-editor-like interface for viewing memory of attached processes." }
{ Breakpoints "breakpoints" "Breakpoints" Null CircleFilled 0 1 0 1 "Displays a table of all breakpoints, containing information about each breakpoint's name, location, and hit count. Also contains per-breakpoint controls for enabling, deleting, or editing each breakpoint. For more information on breakpoints and their features, read the 'Breakpoints' section." }
{ WatchPins "watch_pins" "Watch Pins" Null Pin 0 1 0 1 "Displays a table of all watch pins (watched expressions, like those found in `Watch`, but instead of being within a table, being pinned to some source code location, like breakpoints). This table contains each pin's name, location, and controls for editing or deleting each pin." }
{ ExceptionFilters "exception_filters" "Exception Filters" Null Gear 0 1 0 1 "An interface which controls whether or not the debugger will halt attached processes upon encountering specific exception codes for the first time." }
{ Theme "theme" "Theme" Null Palette 0 1 0 1 "An interface for modifying the colors used in the debugger's UI. Allows selecting a theme preset, loading a theme from a file, and modifying individual colors within a theme." }
}
////////////////////////////////
//~ rjf: Default Command -> View Map
@table(cmd view entity_kind_lock)
DF_CmdSpec2ViewSpecMap:
{
{"launch_and_run" "entity_lister" Target }
{"launch_and_init" "entity_lister" Target }
{"kill" "entity_lister" Process }
{"detach" "entity_lister" Process }
{"select_thread" "entity_lister" Thread }
{"select_thread_window" "entity_lister" Thread }
{"select_thread_view" "entity_lister" Thread }
{"freeze_thread" "entity_lister" Thread }
{"thaw_thread" "entity_lister" Thread }
{"freeze_process" "entity_lister" Process }
{"thaw_process" "entity_lister" Process }
{"freeze_machine" "entity_lister" Machine }
{"thaw_machine" "entity_lister" Machine }
{"set_current_path" "file_system" Null }
{"open" "file_system" Null }
{"reload" "entity_lister" File }
{"switch" "entity_lister" File }
{"load_user" "file_system" Null }
{"load_profile" "file_system" Null }
{"find_thread" "entity_lister" Thread }
{"open_thread_disasm" "entity_lister" Thread }
{"open_file_memory" "entity_lister" File }
{"open_process_memory" "entity_lister" Process }
{"remove_breakpoint" "entity_lister" Breakpoint }
{"edit_breakpoint" "entity_lister" Breakpoint }
{"enable_breakpoint" "entity_lister" Breakpoint }
{"disable_breakpoint" "entity_lister" Breakpoint }
{"edit_breakpoint" "entity_lister" Breakpoint }
{"add_target" "file_system" Null }
{"remove_target" "entity_lister" Target }
{"edit_target" "entity_lister" Target }
{"retry_ended_process" "entity_lister" EndedProcess }
{"attach" "system_processes" Null }
{"commands" "commands" Null }
{"target_editor" "target" Null }
{"targets" "targets" Null }
{"file_path_map" "file_path_map" Null }
{"scheduler" "scheduler" Null }
{"call_stack" "call_stack" Null }
{"modules" "modules" Null }
{"pending_entity" "pending_entity" Null }
{"code" "code" Null }
{"watch" "watch" Null }
{"locals" "locals" Null }
{"registers" "registers" Null }
{"output" "output" Null }
{"memory" "memory" Null }
{"disassembly" "disassembly" Null }
{"breakpoints" "breakpoints" Null }
{"watch_pins" "watch_pins" Null }
{"exception_filters" "exception_filters" Null }
{"theme" "theme" Null }
{"pick_file" "file_system" Null }
{"clear_diag_log" "entity_lister" DiagLog }
{"open_diag_log" "entity_lister" DiagLog }
{ Null "null" "" Null Null 0 0 0 0 0 0 0 "" }
{ Empty "empty" "" Null Null 0 0 0 0 0 0 0 "" }
{ Commands "commands" "Commands" Null List 0 0 0 0 0 0 0 "" }
{ FileSystem "file_system" "File System" Null FileOutline 0 0 0 0 0 0 0 "" }
{ SystemProcesses "system_processes" "System Processes" Null Null 0 0 0 0 0 0 0 "" }
{ EntityLister "entity_lister" "Entity List" EntityKindName Null 0 0 0 0 0 0 0 "" }
{ SymbolLister "symbol_lister" "Symbols" Null Null 0 0 0 0 0 0 0 "" }
{ Target "target" "Target" EntityName Target 1 0 0 0 0 0 0 "" }
{ Targets "targets" "Targets" Null Target 0 1 0 1 0 1 1 "Displays a list of all targets, as well as controls for enabling, disabling, launching, editing, or deleting each target. For more information on targets, read the `Targets` section." }
{ FilePathMap "file_path_map" "File Path Map" Null FileOutline 0 1 0 0 0 0 1 "Displays a table of *path maps*. Each path map is a pair of file or folder paths, one being a 'source' path, and one being a 'destination' path. These pairs are used by the debugger when automatically searching for specific files - for instance, when attempting to snap to a source code location specified by debug info. If debug info refers to a path on the machine on which a target executable was originally built, but that path is not valid on the debugger machine, but some alternative path exists, then path maps may be used to redirect the debugger from the debug info's specified paths to the associated appropriate debugger machine file paths." }
{ Scheduler "scheduler" "Scheduler" Null Scheduler 0 1 0 1 1 1 1 "Displays all processes and threads to which the debugger is currently attached, and contains controls for selecting and freezing threads." }
{ CallStack "call_stack" "Call Stack" Null Thread 0 1 0 0 0 0 1 "Displays the call stack of the currently selected thread. Each frame in the call stack contains the associated module, function name, and return address. Allows selection of a particular call stack frame other than the top." }
{ Modules "modules" "Modules" Null Module 0 1 0 1 0 1 1 "Displays a table of all modules currently loaded by any process to which the debugger is attached. This table displays each module's name, virtual address range in the containing process' address space, and which debug info file is being used by the debugger for the associated module." }
{ PendingEntity "pending_entity" "Pending Entity" EntityName FileOutline 1 0 0 0 0 0 0 "" }
{ Code "code" "Code" EntityName FileOutline 1 1 1 0 0 0 0 "" }
{ Disassembly "disassembly" "Disassembly" Null Glasses 0 1 0 0 0 0 1 "Displays disassembled instructions in a textual form from the selected thread's containing process virtual address space." }
{ Watch "watch" "Watch" Null Binoculars 0 1 0 1 1 1 1 "The familiar 'watch window' debugger interface. Allows the inputting of a number of expressions. Each expression in the table is evaluated within the context of the selected thread's selected call stack frame. If applicable (depending on visualization rules and the expression's type), these expressions may be hierarchically expanded, which displays children as more rows in the table. The values of these expressions may also be edited, and if possible, can be used to write to registers or memory in attached processes. Also contains a new *view rule* column, not found in other major debuggers, which allows per-row specification of various visualization rules. These view rules may be used to visualize and inspect the evaluation of expressions in a variety of ways. To learn more, read the 'View Rules' section." }
{ Locals "locals" "Locals" Null Binoculars 0 1 0 1 1 1 1 "Nearly identical to `Watch`, but automatically filled with local variables found within the selected call stack frame of the selected thread, according to the associated debug info. View rules and evaluation values can be edited, like in `Watch`, but unlike `Watch`, expressions cannot be edited or added to the table." }
{ Registers "registers" "Registers" Null Binoculars 0 1 0 1 1 1 1 "Nearly identical to `Watch`, but automatically filled with all register names according to the selected thread's architecture. View rules and evaluation values can be edited, like in `Watch`, but unlike `Watch`, expressions cannot be edited or added to the table." }
{ Globals "globals" "Globals" Null Binoculars 0 1 0 1 1 1 1 "Nearly identical to `Watch`, but automatically filled with all global variables within the selected thread's module. View rules and evaluation values can be edited, like in `Watch`, but unlike `Watch`, expressions cannot be edited or added to the table." }
{ ThreadLocals "thread_locals" "Thread Locals" Null Binoculars 0 1 0 1 1 1 1 "Nearly identical to `Watch`, but automatically filled with all thread local variables within the selected thread's module. View rules and evaluation values can be edited, like in `Watch`, but unlike `Watch`, expressions cannot be edited or added to the table." }
{ Types "types" "Types" Null Binoculars 0 1 0 1 1 1 1 "Nearly identical to `Watch`, but automatically filled with all types within the selected thread's module. View rules can be edited, like in `Watch`, but unlike `Watch`, expressions cannot be edited or added to the table." }
{ Procedures "procedures" "Procedures" Null Binoculars 0 1 0 1 1 1 1 "Nearly identical to `Watch`, but automatically filled with all procedures within the selected thread's module. View rules can be edited, like in `Watch`, but unlike `Watch`, expressions cannot be edited or added to the table." }
{ Output "output" "Output" Null List 0 1 0 0 0 0 1 "Displays textual output from the selected thread's containing process." }
{ Memory "memory" "Memory" Null Grid 0 1 1 0 0 0 1 "A familiar hex-editor-like interface for viewing memory of attached processes." }
{ Breakpoints "breakpoints" "Breakpoints" Null CircleFilled 0 1 0 1 0 1 1 "Displays a table of all breakpoints, containing information about each breakpoint's name, location, and hit count. Also contains per-breakpoint controls for enabling, deleting, or editing each breakpoint. For more information on breakpoints and their features, read the 'Breakpoints' section." }
{ WatchPins "watch_pins" "Watch Pins" Null Pin 0 1 0 1 1 1 1 "Displays a table of all watch pins (watched expressions, like those found in `Watch`, but instead of being within a table, being pinned to some source code location, like breakpoints). This table contains each pin's name, location, and controls for editing or deleting each pin." }
{ ExceptionFilters "exception_filters" "Exception Filters" Null Gear 0 1 0 1 0 1 1 "An interface which controls whether or not the debugger will halt attached processes upon encountering specific exception codes for the first time." }
{ Theme "theme" "Theme" Null Palette 0 1 0 0 0 0 1 "An interface for modifying the colors used in the debugger's UI. Allows selecting a theme preset, loading a theme from a file, and modifying individual colors within a theme." }
}
////////////////////////////////
//~ rjf: Command Parameter Slot -> View
@table(slot view_spec)
@table(slot view_spec opt_cmd_spec)
DF_CmdParamSlot2ViewSpecMap:
{
{Entity "entity_lister" }
{EntityList "entity_lister" }
{FilePath "file_system" }
{CmdSpec "commands" }
{ID "system_processes" }
{Entity "entity_lister" "" }
{EntityList "entity_lister" "" }
{FilePath "file_system" "" }
{CmdSpec "commands" "" }
{ID "system_processes" "" }
{String "symbol_lister" "goto_name" }
{String "symbol_lister" "function_breakpoint" }
}
////////////////////////////////
@@ -555,20 +498,6 @@ df_g_theme_preset_colors_table:
@expand(DF_ThemePresetTable a) `df_g_theme_preset_colors__$(a.name_lower),`;
}
//- rjf: default cmd -> view tables
@table_gen_data(type: String8, fallback:`{0}`)
df_g_cmd2view_table_src:
{
@expand(DF_CmdSpec2ViewSpecMap a) `str8_lit_comp("$(a.cmd)"),`
}
@table_gen_data(type: String8, fallback:`{0}`)
df_g_cmd2view_table_dst:
{
@expand(DF_CmdSpec2ViewSpecMap a) `str8_lit_comp("$(a.view)"),`
}
//- rjf: cmd param slot -> view spec tables
@table_gen_data(type: DF_CmdParamSlot, fallback:`DF_CmdParamSlot_Null`)
@@ -583,6 +512,12 @@ df_g_cmd_param_slot_2_view_spec_dst_map:
@expand(DF_CmdParamSlot2ViewSpecMap a) `str8_lit_comp("$(a.view_spec)"),`
}
@table_gen_data(type: String8, fallback:`{0}`)
df_g_cmd_param_slot_2_view_spec_cmd_map:
{
@expand(DF_CmdParamSlot2ViewSpecMap a) `str8_lit_comp("$(a.opt_cmd_spec)"),`
}
//- rjf: default bindings table
@table_gen_data(type: DF_StringBindingPair, fallback: `{0}`)
@@ -644,7 +579,7 @@ df_g_gfx_view_rule_spec_info_table:
@table_gen_data(type: DF_ViewSpecInfo, fallback: `{0}`)
df_g_gfx_view_kind_spec_info_table:
{
@expand(DF_GfxViewTable a) ```{(0|$(a.parameterized_by_entity)*DF_ViewSpecFlag_ParameterizedByEntity|$(a.can_serialize)*DF_ViewSpecFlag_CanSerialize|$(a.can_serialize_entity_path)*DF_ViewSpecFlag_CanSerializeEntityPath), str8_lit_comp("$(a.name_lower)"), str8_lit_comp("$(a.display_string)"), DF_NameKind_$(a.name_kind), DF_IconKind_$(a.icon), DF_VIEW_SETUP_FUNCTION_NAME($(a.name)), DF_VIEW_STRING_FROM_STATE_FUNCTION_NAME($(a.name)), DF_VIEW_CMD_FUNCTION_NAME($(a.name)), DF_VIEW_UI_FUNCTION_NAME($(a.name))},```;
@expand(DF_GfxViewTable a) ```{(0|$(a.parameterized_by_entity)*DF_ViewSpecFlag_ParameterizedByEntity|$(a.can_serialize)*DF_ViewSpecFlag_CanSerialize|$(a.can_serialize_entity_path)*DF_ViewSpecFlag_CanSerializeEntityPath|$(a.can_filter)*DF_ViewSpecFlag_CanFilter|$(a.filter_is_code)*DF_ViewSpecFlag_FilterIsCode|$(a.typing_automatically_filters)*DF_ViewSpecFlag_TypingAutomaticallyFilters), str8_lit_comp("$(a.name_lower)"), str8_lit_comp("$(a.display_string)"), DF_NameKind_$(a.name_kind), DF_IconKind_$(a.icon), DF_VIEW_SETUP_FUNCTION_NAME($(a.name)), DF_VIEW_STRING_FROM_STATE_FUNCTION_NAME($(a.name)), DF_VIEW_CMD_FUNCTION_NAME($(a.name)), DF_VIEW_UI_FUNCTION_NAME($(a.name))},```;
}
//- rjf: theme color tables
+55 -91
View File
@@ -30,7 +30,7 @@ df_view_rule_hooks__rgba_from_eval(DF_Eval eval, TG_Graph *graph, RADDBG_Parsed
U64 array_total_size = tg_byte_size_from_graph_raddbg_key(graph, raddbg, type_key);
U64 array_total_size_capped = ClampTop(array_total_size, 64);
Rng1U64 array_memory_vaddr_rng = r1u64(eval.offset, eval.offset + array_total_size_capped);
CTRL_ProcessMemorySlice array_slice = ctrl_query_cached_data_from_process_vaddr_range(scratch.arena, process->ctrl_machine_id, process->ctrl_handle, array_memory_vaddr_rng);
CTRL_ProcessMemorySlice array_slice = ctrl_query_cached_data_from_process_vaddr_range(scratch.arena, process->ctrl_machine_id, process->ctrl_handle, array_memory_vaddr_rng, 0);
String8 array_memory = array_slice.data;
TG_Key element_type_key = tg_unwrapped_direct_from_graph_raddbg_key(graph, raddbg, type_key);
TG_Kind element_type_kind = tg_kind_from_key(element_type_key);
@@ -67,7 +67,7 @@ df_view_rule_hooks__rgba_from_eval(DF_Eval eval, TG_Graph *graph, RADDBG_Parsed
U64 struct_total_size = tg_byte_size_from_graph_raddbg_key(graph, raddbg, type_key);
U64 struct_total_size_capped = ClampTop(struct_total_size, 64);
Rng1U64 struct_memory_vaddr_rng = r1u64(eval.offset, eval.offset + struct_total_size_capped);
CTRL_ProcessMemorySlice struct_slice = ctrl_query_cached_data_from_process_vaddr_range(scratch.arena, process->ctrl_machine_id, process->ctrl_handle, struct_memory_vaddr_rng);
CTRL_ProcessMemorySlice struct_slice = ctrl_query_cached_data_from_process_vaddr_range(scratch.arena, process->ctrl_machine_id, process->ctrl_handle, struct_memory_vaddr_rng, 0);
String8 struct_memory = struct_slice.data;
TG_Type *type = tg_type_from_graph_raddbg_key(scratch.arena, graph, raddbg, type_key);
for(U64 element_idx = 0, member_idx = 0;
@@ -198,7 +198,7 @@ df_view_rule_hooks__eval_commit_rgba(DF_Eval eval, TG_Graph *graph, RADDBG_Parse
}
internal DF_BitmapTopologyInfo
df_view_rule_hooks__bitmap_topology_info_from_cfg(DBGI_Scope *scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_CfgNode *cfg)
df_view_rule_hooks__bitmap_topology_info_from_cfg(DBGI_Scope *scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, EVAL_String2ExprMap *macro_map, DF_CfgNode *cfg)
{
Temp scratch = scratch_begin(0, 0);
DF_BitmapTopologyInfo info = {0};
@@ -222,10 +222,10 @@ df_view_rule_hooks__bitmap_topology_info_from_cfg(DBGI_Scope *scope, DF_CtrlCtx
String8 width_expr = str8_list_join(scratch.arena, &width_expr_strs, 0);
String8 height_expr = str8_list_join(scratch.arena, &height_expr_strs, 0);
String8 fmt_string = fmt_cfg->first->string;
DF_Eval width_eval = df_eval_from_string(scratch.arena, scope, ctrl_ctx, parse_ctx, width_expr);
DF_Eval width_eval = df_eval_from_string(scratch.arena, scope, ctrl_ctx, parse_ctx, macro_map, width_expr);
DF_Eval width_eval_value = df_value_mode_eval_from_eval(parse_ctx->type_graph, parse_ctx->rdbg, ctrl_ctx, width_eval);
info.width = width_eval_value.imm_u64;
DF_Eval height_eval = df_eval_from_string(scratch.arena, scope, ctrl_ctx, parse_ctx, height_expr);
DF_Eval height_eval = df_eval_from_string(scratch.arena, scope, ctrl_ctx, parse_ctx, macro_map, height_expr);
DF_Eval height_eval_value = df_value_mode_eval_from_eval(parse_ctx->type_graph, parse_ctx->rdbg, ctrl_ctx, height_eval);
info.height = height_eval_value.imm_u64;
if(fmt_string.size != 0)
@@ -245,7 +245,7 @@ df_view_rule_hooks__bitmap_topology_info_from_cfg(DBGI_Scope *scope, DF_CtrlCtx
}
internal DF_GeoTopologyInfo
df_view_rule_hooks__geo_topology_info_from_cfg(DBGI_Scope *scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_CfgNode *cfg)
df_view_rule_hooks__geo_topology_info_from_cfg(DBGI_Scope *scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, EVAL_String2ExprMap *macro_map, DF_CfgNode *cfg)
{
Temp scratch = scratch_begin(0, 0);
DF_GeoTopologyInfo result = {0};
@@ -273,9 +273,9 @@ df_view_rule_hooks__geo_topology_info_from_cfg(DBGI_Scope *scope, DF_CtrlCtx *ct
String8 count_expr = str8_list_join(scratch.arena, &count_expr_strs, &join);
String8 vertices_base_expr = str8_list_join(scratch.arena, &vertices_base_expr_strs, &join);
String8 vertices_size_expr = str8_list_join(scratch.arena, &vertices_size_expr_strs, &join);
DF_Eval count_eval = df_eval_from_string(scratch.arena, scope, ctrl_ctx, parse_ctx, count_expr);
DF_Eval vertices_base_eval = df_eval_from_string(scratch.arena, scope, ctrl_ctx, parse_ctx, vertices_base_expr);
DF_Eval vertices_size_eval = df_eval_from_string(scratch.arena, scope, ctrl_ctx, parse_ctx, vertices_size_expr);
DF_Eval count_eval = df_eval_from_string(scratch.arena, scope, ctrl_ctx, parse_ctx, macro_map, count_expr);
DF_Eval vertices_base_eval = df_eval_from_string(scratch.arena, scope, ctrl_ctx, parse_ctx, macro_map, vertices_base_expr);
DF_Eval vertices_size_eval = df_eval_from_string(scratch.arena, scope, ctrl_ctx, parse_ctx, macro_map, vertices_size_expr);
DF_Eval count_val_eval = df_value_mode_eval_from_eval(parse_ctx->type_graph, parse_ctx->rdbg, ctrl_ctx, count_eval);
DF_Eval vertices_base_val_eval = df_value_mode_eval_from_eval(parse_ctx->type_graph, parse_ctx->rdbg, ctrl_ctx, vertices_base_eval);
DF_Eval vertices_size_val_eval = df_value_mode_eval_from_eval(parse_ctx->type_graph, parse_ctx->rdbg, ctrl_ctx, vertices_size_eval);
@@ -288,7 +288,7 @@ df_view_rule_hooks__geo_topology_info_from_cfg(DBGI_Scope *scope, DF_CtrlCtx *ct
}
internal DF_TxtTopologyInfo
df_view_rule_hooks__txt_topology_info_from_cfg(DBGI_Scope *scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_CfgNode *cfg)
df_view_rule_hooks__txt_topology_info_from_cfg(DBGI_Scope *scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, EVAL_String2ExprMap *macro_map, DF_CfgNode *cfg)
{
Temp scratch = scratch_begin(0, 0);
DF_TxtTopologyInfo result = zero_struct;
@@ -305,7 +305,7 @@ df_view_rule_hooks__txt_topology_info_from_cfg(DBGI_Scope *scope, DF_CtrlCtx *ct
}
lang_string = lang_cfg->first->string;
String8 size_expr = str8_list_join(scratch.arena, &size_expr_strs, &join);
DF_Eval size_eval = df_eval_from_string(scratch.arena, scope, ctrl_ctx, parse_ctx, size_expr);
DF_Eval size_eval = df_eval_from_string(scratch.arena, scope, ctrl_ctx, parse_ctx, macro_map, size_expr);
DF_Eval size_val_eval = df_value_mode_eval_from_eval(parse_ctx->type_graph, parse_ctx->rdbg, ctrl_ctx, size_eval);
result.lang = txt_lang_kind_from_extension(lang_string);
result.size_cap = size_val_eval.imm_u64;
@@ -336,7 +336,7 @@ DF_CORE_VIEW_RULE_EVAL_RESOLUTION_FUNCTION_DEF(array)
str8_list_push(scratch.arena, &array_size_expr_strs, child->string);
}
String8 array_size_expr = str8_list_join(scratch.arena, &array_size_expr_strs, 0);
DF_Eval array_size_eval = df_eval_from_string(arena, dbgi_scope, ctrl_ctx, parse_ctx, array_size_expr);
DF_Eval array_size_eval = df_eval_from_string(arena, dbgi_scope, ctrl_ctx, parse_ctx, macro_map, array_size_expr);
DF_Eval array_size_eval_value = df_value_mode_eval_from_eval(parse_ctx->type_graph, parse_ctx->rdbg, ctrl_ctx, array_size_eval);
eval_error_list_concat_in_place(&eval.errors, &array_size_eval.errors);
array_size = array_size_eval_value.imm_u64;
@@ -483,20 +483,12 @@ struct DF_ViewRuleHooks_RGBAState
DF_CORE_VIEW_RULE_VIZ_BLOCK_PROD_FUNCTION_DEF(rgba)
{
DF_EvalVizBlock *block = push_array(arena, DF_EvalVizBlock, 1);
block->kind = DF_EvalVizBlockKind_Canvas;
block->eval_view = eval_view;
block->eval = eval;
block->cfg_table = *cfg_table;
block->parent_key = key;
block->key = df_expand_key_make((U64)eval_view, df_hash_from_expand_key(key), 1);
block->visual_idx_range = r1u64(0, 8);
block->semantic_idx_range = r1u64(0, 1);
block->depth = depth;
SLLQueuePush(out->first, out->last, block);
out->count += 1;
out->total_visual_row_count += 8;
out->total_semantic_row_count += 1;
DF_EvalVizBlock *vb = df_eval_viz_block_begin(arena, DF_EvalVizBlockKind_Canvas, key, df_expand_key_make(df_hash_from_expand_key(key), 1), depth);
vb->eval = eval;
vb->cfg_table = *cfg_table;
vb->visual_idx_range = r1u64(0, 8);
vb->semantic_idx_range = r1u64(0, 1);
df_eval_viz_block_end(out, vb);
}
DF_GFX_VIEW_RULE_ROW_UI_FUNCTION_DEF(rgba)
@@ -657,20 +649,12 @@ struct DF_ViewRuleHooks_TextState
DF_CORE_VIEW_RULE_VIZ_BLOCK_PROD_FUNCTION_DEF(text)
{
DF_EvalVizBlock *block = push_array(arena, DF_EvalVizBlock, 1);
block->kind = DF_EvalVizBlockKind_Canvas;
block->eval_view = eval_view;
block->eval = eval;
block->cfg_table = *cfg_table;
block->parent_key = key;
block->key = df_expand_key_make((U64)eval_view, df_hash_from_expand_key(key), 1);
block->visual_idx_range = r1u64(0, 8);
block->semantic_idx_range = r1u64(0, 1);
block->depth = depth;
SLLQueuePush(out->first, out->last, block);
out->count += 1;
out->total_visual_row_count += 8;
out->total_semantic_row_count += 1;
DF_EvalVizBlock *vb = df_eval_viz_block_begin(arena, DF_EvalVizBlockKind_Canvas, key, df_expand_key_make(df_hash_from_expand_key(key), 1), depth);
vb->eval = eval;
vb->cfg_table = *cfg_table;
vb->visual_idx_range = r1u64(0, 8);
vb->semantic_idx_range = r1u64(0, 1);
df_eval_viz_block_end(out, vb);
}
DF_GFX_VIEW_RULE_BLOCK_UI_FUNCTION_DEF(text)
@@ -691,7 +675,7 @@ DF_GFX_VIEW_RULE_BLOCK_UI_FUNCTION_DEF(text)
state->last_open_frame_idx = df_frame_index();
{
//- rjf: unpack params
DF_TxtTopologyInfo top = df_view_rule_hooks__txt_topology_info_from_cfg(dbgi_scope, ctrl_ctx, parse_ctx, cfg);
DF_TxtTopologyInfo top = df_view_rule_hooks__txt_topology_info_from_cfg(dbgi_scope, ctrl_ctx, parse_ctx, macro_map, cfg);
//- rjf: resolve to address value & range
DF_Eval value_eval = df_value_mode_eval_from_eval(parse_ctx->type_graph, parse_ctx->rdbg, ctrl_ctx, eval);
@@ -716,7 +700,7 @@ DF_GFX_VIEW_RULE_BLOCK_UI_FUNCTION_DEF(text)
}
//- rjf: address range -> hash
U128 hash = ctrl_stored_hash_from_process_vaddr_range(process->ctrl_machine_id, process->ctrl_handle, vaddr_range, 1);
U128 hash = ctrl_stored_hash_from_process_vaddr_range(process->ctrl_machine_id, process->ctrl_handle, vaddr_range, 1, 0);
//- rjf: hash -> data
String8 data = hs_data_from_hash(hs_scope, hash);
@@ -766,20 +750,12 @@ DF_GFX_VIEW_RULE_BLOCK_UI_FUNCTION_DEF(text)
DF_CORE_VIEW_RULE_VIZ_BLOCK_PROD_FUNCTION_DEF(disasm)
{
DF_EvalVizBlock *block = push_array(arena, DF_EvalVizBlock, 1);
block->kind = DF_EvalVizBlockKind_Canvas;
block->eval_view = eval_view;
block->eval = eval;
block->cfg_table = *cfg_table;
block->parent_key = key;
block->key = df_expand_key_make((U64)eval_view, df_hash_from_expand_key(key), 1);
block->visual_idx_range = r1u64(0, 8);
block->semantic_idx_range = r1u64(0, 1);
block->depth = depth;
SLLQueuePush(out->first, out->last, block);
out->count += 1;
out->total_visual_row_count += 8;
out->total_semantic_row_count += 1;
DF_EvalVizBlock *vb = df_eval_viz_block_begin(arena, DF_EvalVizBlockKind_Canvas, key, df_expand_key_make(df_hash_from_expand_key(key), 1), depth);
vb->eval = eval;
vb->cfg_table = *cfg_table;
vb->visual_idx_range = r1u64(0, 8);
vb->semantic_idx_range = r1u64(0, 1);
df_eval_viz_block_end(out, vb);
}
DF_GFX_VIEW_RULE_BLOCK_UI_FUNCTION_DEF(disasm)
@@ -858,27 +834,19 @@ internal UI_BOX_CUSTOM_DRAW(df_view_rule_hooks__bitmap_zoom_draw)
DF_CORE_VIEW_RULE_VIZ_BLOCK_PROD_FUNCTION_DEF(bitmap)
{
DF_EvalVizBlock *block = push_array(arena, DF_EvalVizBlock, 1);
block->kind = DF_EvalVizBlockKind_Canvas;
block->eval_view = eval_view;
block->eval = eval;
block->cfg_table = *cfg_table;
block->parent_key = key;
block->key = df_expand_key_make((U64)eval_view, df_hash_from_expand_key(key), 1);
block->visual_idx_range = r1u64(0, 8);
block->semantic_idx_range = r1u64(0, 1);
block->depth = depth;
SLLQueuePush(out->first, out->last, block);
out->count += 1;
out->total_visual_row_count += 8;
out->total_semantic_row_count += 1;
DF_EvalVizBlock *vb = df_eval_viz_block_begin(arena, DF_EvalVizBlockKind_Canvas, key, df_expand_key_make(df_hash_from_expand_key(key), 1), depth);
vb->eval = eval;
vb->cfg_table = *cfg_table;
vb->visual_idx_range = r1u64(0, 8);
vb->semantic_idx_range = r1u64(0, 1);
df_eval_viz_block_end(out, vb);
}
DF_GFX_VIEW_RULE_ROW_UI_FUNCTION_DEF(bitmap)
{
DF_Eval value_eval = df_value_mode_eval_from_eval(parse_ctx->type_graph, parse_ctx->rdbg, ctrl_ctx, eval);
U64 base_vaddr = value_eval.imm_u64 ? value_eval.imm_u64 : value_eval.offset;
DF_BitmapTopologyInfo topology = df_view_rule_hooks__bitmap_topology_info_from_cfg(scope, ctrl_ctx, parse_ctx, cfg);
DF_BitmapTopologyInfo topology = df_view_rule_hooks__bitmap_topology_info_from_cfg(scope, ctrl_ctx, parse_ctx, macro_map, cfg);
U64 expected_size = topology.width*topology.height*r_tex2d_format_bytes_per_pixel_table[topology.fmt];
UI_Font(df_font_from_slot(DF_FontSlot_Code)) UI_TextColor(df_rgba_from_theme_color(DF_ThemeColor_WeakText))
ui_labelf("0x%I64x -> Bitmap (%I64u x %I64u)", base_vaddr, topology.width, topology.height);
@@ -905,7 +873,7 @@ DF_GFX_VIEW_RULE_BLOCK_UI_FUNCTION_DEF(bitmap)
DF_Entity *process = df_entity_ancestor_from_kind(thread, DF_EntityKind_Process);
//- rjf: unpack image dimensions & form vaddr range
DF_BitmapTopologyInfo topology_info = df_view_rule_hooks__bitmap_topology_info_from_cfg(dbgi_scope, ctrl_ctx, parse_ctx, cfg);
DF_BitmapTopologyInfo topology_info = df_view_rule_hooks__bitmap_topology_info_from_cfg(dbgi_scope, ctrl_ctx, parse_ctx, macro_map, cfg);
U64 expected_size = topology_info.width*topology_info.height*r_tex2d_format_bytes_per_pixel_table[topology_info.fmt];
Rng1U64 vaddr_range = r1u64(base_vaddr, base_vaddr+expected_size);
@@ -923,7 +891,7 @@ DF_GFX_VIEW_RULE_BLOCK_UI_FUNCTION_DEF(bitmap)
}
//- rjf: address range -> hash
U128 hash = ctrl_stored_hash_from_process_vaddr_range(process->ctrl_machine_id, process->ctrl_handle, vaddr_range, 0);
U128 hash = ctrl_stored_hash_from_process_vaddr_range(process->ctrl_machine_id, process->ctrl_handle, vaddr_range, 0, 0);
//- rjf: hash & topology -> texture
TEX_Topology topology = tex_topology_make(v2s32((S32)topology_info.width, (S32)topology_info.height), topology_info.fmt);
@@ -965,7 +933,11 @@ DF_GFX_VIEW_RULE_BLOCK_UI_FUNCTION_DEF(bitmap)
df_gfx_request_frame();
}
}
if(sig.hovering)
if(sig.hovering && r_handle_match(texture, r_handle_zero())) UI_Tooltip
{
ui_labelf("Texture not loaded.");
}
if(sig.hovering && !r_handle_match(texture, r_handle_zero()))
{
if(dim.y > (F32)topology_info.height)
{
@@ -1105,20 +1077,12 @@ internal UI_BOX_CUSTOM_DRAW(df_view_rule_hooks__geo_box_draw)
DF_CORE_VIEW_RULE_VIZ_BLOCK_PROD_FUNCTION_DEF(geo)
{
DF_EvalVizBlock *block = push_array(arena, DF_EvalVizBlock, 1);
block->kind = DF_EvalVizBlockKind_Canvas;
block->eval_view = eval_view;
block->eval = eval;
block->cfg_table = *cfg_table;
block->parent_key = key;
block->key = df_expand_key_make((U64)eval_view, df_hash_from_expand_key(key), 1);
block->visual_idx_range = r1u64(0, 16);
block->semantic_idx_range = r1u64(0, 1);
block->depth = depth;
SLLQueuePush(out->first, out->last, block);
out->count += 1;
out->total_visual_row_count += 16;
out->total_semantic_row_count += 1;
DF_EvalVizBlock *vb = df_eval_viz_block_begin(arena, DF_EvalVizBlockKind_Canvas, key, df_expand_key_make(df_hash_from_expand_key(key), 1), depth);
vb->eval = eval;
vb->cfg_table = *cfg_table;
vb->visual_idx_range = r1u64(0, 16);
vb->semantic_idx_range = r1u64(0, 1);
df_eval_viz_block_end(out, vb);
}
DF_GFX_VIEW_RULE_ROW_UI_FUNCTION_DEF(geo)
@@ -1152,7 +1116,7 @@ DF_GFX_VIEW_RULE_BLOCK_UI_FUNCTION_DEF(geo)
U64 base_vaddr = value_eval.imm_u64 ? value_eval.imm_u64 : value_eval.offset;
//- rjf: extract extra geo topology info from view rule
DF_GeoTopologyInfo top = df_view_rule_hooks__geo_topology_info_from_cfg(dbgi_scope, ctrl_ctx, parse_ctx, cfg);
DF_GeoTopologyInfo top = df_view_rule_hooks__geo_topology_info_from_cfg(dbgi_scope, ctrl_ctx, parse_ctx, macro_map, cfg);
Rng1U64 index_buffer_vaddr_range = r1u64(base_vaddr, base_vaddr+top.index_count*sizeof(U32));
Rng1U64 vertex_buffer_vaddr_range = top.vertices_vaddr_range;
@@ -1187,8 +1151,8 @@ DF_GFX_VIEW_RULE_BLOCK_UI_FUNCTION_DEF(geo)
}
//- rjf: address range -> hash
U128 index_buffer_hash = ctrl_stored_hash_from_process_vaddr_range(process->ctrl_machine_id, process->ctrl_handle, index_buffer_vaddr_range, 0);
U128 vertex_buffer_hash = ctrl_stored_hash_from_process_vaddr_range(process->ctrl_machine_id, process->ctrl_handle, vertex_buffer_vaddr_range, 0);
U128 index_buffer_hash = ctrl_stored_hash_from_process_vaddr_range(process->ctrl_machine_id, process->ctrl_handle, index_buffer_vaddr_range, 0, 0);
U128 vertex_buffer_hash = ctrl_stored_hash_from_process_vaddr_range(process->ctrl_machine_id, process->ctrl_handle, vertex_buffer_vaddr_range, 0, 0);
//- rjf: get gpu buffers
R_Handle index_buffer = geo_buffer_from_key_hash(geo_scope, index_buffer_key, index_buffer_hash);
+3 -3
View File
@@ -34,8 +34,8 @@ struct DF_TxtTopologyInfo
internal Vec4F32 df_view_rule_hooks__rgba_from_eval(DF_Eval eval, TG_Graph *graph, RADDBG_Parsed *raddbg, DF_Entity *process);
internal void df_view_rule_hooks__eval_commit_rgba(DF_Eval eval, TG_Graph *graph, RADDBG_Parsed *raddbg, DF_CtrlCtx *ctrl_ctx, Vec4F32 rgba);
internal DF_BitmapTopologyInfo df_view_rule_hooks__bitmap_topology_info_from_cfg(DBGI_Scope *scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_CfgNode *cfg);
internal DF_GeoTopologyInfo df_view_rule_hooks__geo_topology_info_from_cfg(DBGI_Scope *scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_CfgNode *cfg);
internal DF_TxtTopologyInfo df_view_rule_hooks__txt_topology_info_from_cfg(DBGI_Scope *scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_CfgNode *cfg);
internal DF_BitmapTopologyInfo df_view_rule_hooks__bitmap_topology_info_from_cfg(DBGI_Scope *scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, EVAL_String2ExprMap *macro_map, DF_CfgNode *cfg);
internal DF_GeoTopologyInfo df_view_rule_hooks__geo_topology_info_from_cfg(DBGI_Scope *scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, EVAL_String2ExprMap *macro_map, DF_CfgNode *cfg);
internal DF_TxtTopologyInfo df_view_rule_hooks__txt_topology_info_from_cfg(DBGI_Scope *scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, EVAL_String2ExprMap *macro_map, DF_CfgNode *cfg);
#endif //DF_VIEW_RULE_HOOKS_H
+941 -713
View File
File diff suppressed because it is too large Load Diff
+42 -39
View File
@@ -22,7 +22,7 @@ struct DF_FileInfo
{
String8 filename;
FileProperties props;
DF_FuzzyMatchRangeList match_ranges;
FuzzyMatchRangeList match_ranges;
};
typedef struct DF_FileInfoNode DF_FileInfoNode;
@@ -66,9 +66,9 @@ struct DF_CmdListerItem
DF_CmdSpec *cmd_spec;
U64 registrar_idx;
U64 ordering_idx;
DF_FuzzyMatchRangeList name_match_ranges;
DF_FuzzyMatchRangeList desc_match_ranges;
DF_FuzzyMatchRangeList tags_match_ranges;
FuzzyMatchRangeList name_match_ranges;
FuzzyMatchRangeList desc_match_ranges;
FuzzyMatchRangeList tags_match_ranges;
};
typedef struct DF_CmdListerItemNode DF_CmdListerItemNode;
@@ -113,7 +113,7 @@ typedef struct DF_EntityListerItem DF_EntityListerItem;
struct DF_EntityListerItem
{
DF_Entity *entity;
DF_FuzzyMatchRangeList name_match_ranges;
FuzzyMatchRangeList name_match_ranges;
};
typedef struct DF_EntityListerItemNode DF_EntityListerItemNode;
@@ -146,9 +146,9 @@ struct DF_ProcessInfo
{
DEMON_ProcessInfo info;
B32 is_attached;
DF_FuzzyMatchRangeList attached_match_ranges;
DF_FuzzyMatchRangeList name_match_ranges;
DF_FuzzyMatchRangeList pid_match_ranges;
FuzzyMatchRangeList attached_match_ranges;
FuzzyMatchRangeList name_match_ranges;
FuzzyMatchRangeList pid_match_ranges;
};
typedef struct DF_ProcessInfoNode DF_ProcessInfoNode;
@@ -274,15 +274,38 @@ typedef enum DF_EvalWatchViewColumnKind
}
DF_EvalWatchViewColumnKind;
typedef enum DF_EvalWatchViewFillKind
{
DF_EvalWatchViewFillKind_Mutable,
DF_EvalWatchViewFillKind_Registers,
DF_EvalWatchViewFillKind_Locals,
DF_EvalWatchViewFillKind_Globals,
DF_EvalWatchViewFillKind_ThreadLocals,
DF_EvalWatchViewFillKind_Types,
DF_EvalWatchViewFillKind_Procedures,
DF_EvalWatchViewFillKind_COUNT
}
DF_EvalWatchViewFillKind;
typedef struct DF_EvalWatchViewPoint DF_EvalWatchViewPoint;
struct DF_EvalWatchViewPoint
{
DF_EvalWatchViewColumnKind column_kind;
DF_ExpandKey parent_key;
DF_ExpandKey key;
};
typedef struct DF_EvalWatchViewState DF_EvalWatchViewState;
struct DF_EvalWatchViewState
{
B32 initialized;
// rjf; selection state
DF_EvalWatchViewColumnKind selected_column;
DF_ExpandKey selected_parent_key;
DF_ExpandKey selected_key;
// rjf: fill kind (way that the contents of the watch view are computed)
DF_EvalWatchViewFillKind fill_kind;
// rjf; table cursor state
DF_EvalWatchViewPoint cursor;
DF_EvalWatchViewPoint mark;
// rjf: text input state
TxtPt input_cursor;
@@ -297,35 +320,13 @@ struct DF_EvalWatchViewState
F32 type_column_pct;
F32 view_rule_column_pct;
// rjf: top-level expression state
// rjf: mutable fill-kind root expression state
DF_EvalRoot *first_root;
DF_EvalRoot *last_root;
DF_EvalRoot *first_free_root;
U64 root_count;
};
typedef struct DF_EvalThreadDerivedReadOnlyWatchViewState DF_EvalThreadDerivedReadOnlyWatchViewState;
struct DF_EvalThreadDerivedReadOnlyWatchViewState
{
Architecture cached_architecture;
DF_Handle cached_binary;
U64 cached_vaddr;
DF_EvalWatchViewState ewv;
};
typedef struct DF_RegistersViewArchState DF_RegistersViewArchState;
struct DF_RegistersViewArchState
{
B32 initialized;
DF_EvalWatchViewState ewv;
};
typedef struct DF_RegistersViewState DF_RegistersViewState;
struct DF_RegistersViewState
{
DF_RegistersViewArchState arch_state[Architecture_COUNT];
};
////////////////////////////////
//~ rjf: Code @view_types
@@ -442,20 +443,22 @@ internal TXTI_TokenArray df_txti_token_array_from_dasm_arch_string(Arena *arena,
////////////////////////////////
//~ rjf: Eval/Watch Views
//- rjf: eval watch view instance -> eval view key
internal DF_EvalViewKey df_eval_view_key_from_eval_watch_view(DF_EvalWatchViewState *ewv);
//- rjf: root allocation/deallocation/mutation
internal DF_EvalRoot * df_eval_root_alloc(DF_View *view, DF_EvalWatchViewState *ews);
internal void df_eval_root_release(DF_EvalWatchViewState *ews, DF_EvalRoot *root);
internal void df_eval_root_equip_string(DF_EvalRoot *root, String8 string);
internal DF_EvalRoot * df_eval_root_from_string(DF_EvalWatchViewState *ews, String8 string);
internal DF_EvalRoot * df_eval_root_from_expand_key(DF_EvalWatchViewState *ews, DF_ExpandKey expand_key);
internal DF_EvalRoot * df_eval_root_from_expand_key(DF_EvalWatchViewState *ews, DF_EvalView *eval_view, DF_ExpandKey expand_key);
internal String8 df_string_from_eval_root(DF_EvalRoot *root);
internal DF_ExpandKey df_expand_key_from_eval_root(DF_EvalRoot *root);
//- rjf: windowed watch tree visualization
internal DF_EvalVizBlockList df_eval_viz_block_list_from_watch_view_state(Arena *arena, DBGI_Scope *scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_EvalWatchViewState *ews);
internal DF_EvalVizBlockList df_eval_viz_block_list_from_watch_view_state(Arena *arena, DBGI_Scope *scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, EVAL_String2ExprMap *macro_map, DF_View *view, DF_EvalWatchViewState *ews);
//- rjf: eval/watch views main hooks
internal void df_eval_watch_view_init(DF_EvalWatchViewState *ewv, DF_View *view);
internal void df_eval_watch_view_init(DF_EvalWatchViewState *ewv, DF_View *view, DF_EvalWatchViewFillKind fill_kind);
internal void df_eval_watch_view_cmds(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_EvalWatchViewState *ewv, DF_CmdList *cmds);
internal void df_eval_watch_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_EvalWatchViewState *ewv, B32 modifiable, U32 default_radix, Rng2F32 rect);
+76 -150
View File
@@ -14,6 +14,7 @@ DF_GfxViewKind_Commands,
DF_GfxViewKind_FileSystem,
DF_GfxViewKind_SystemProcesses,
DF_GfxViewKind_EntityLister,
DF_GfxViewKind_SymbolLister,
DF_GfxViewKind_Target,
DF_GfxViewKind_Targets,
DF_GfxViewKind_FilePathMap,
@@ -26,6 +27,10 @@ DF_GfxViewKind_Disassembly,
DF_GfxViewKind_Watch,
DF_GfxViewKind_Locals,
DF_GfxViewKind_Registers,
DF_GfxViewKind_Globals,
DF_GfxViewKind_ThreadLocals,
DF_GfxViewKind_Types,
DF_GfxViewKind_Procedures,
DF_GfxViewKind_Output,
DF_GfxViewKind_Memory,
DF_GfxViewKind_Breakpoints,
@@ -113,6 +118,7 @@ DF_VIEW_SETUP_FUNCTION_DEF(Commands);
DF_VIEW_SETUP_FUNCTION_DEF(FileSystem);
DF_VIEW_SETUP_FUNCTION_DEF(SystemProcesses);
DF_VIEW_SETUP_FUNCTION_DEF(EntityLister);
DF_VIEW_SETUP_FUNCTION_DEF(SymbolLister);
DF_VIEW_SETUP_FUNCTION_DEF(Target);
DF_VIEW_SETUP_FUNCTION_DEF(Targets);
DF_VIEW_SETUP_FUNCTION_DEF(FilePathMap);
@@ -125,6 +131,10 @@ DF_VIEW_SETUP_FUNCTION_DEF(Disassembly);
DF_VIEW_SETUP_FUNCTION_DEF(Watch);
DF_VIEW_SETUP_FUNCTION_DEF(Locals);
DF_VIEW_SETUP_FUNCTION_DEF(Registers);
DF_VIEW_SETUP_FUNCTION_DEF(Globals);
DF_VIEW_SETUP_FUNCTION_DEF(ThreadLocals);
DF_VIEW_SETUP_FUNCTION_DEF(Types);
DF_VIEW_SETUP_FUNCTION_DEF(Procedures);
DF_VIEW_SETUP_FUNCTION_DEF(Output);
DF_VIEW_SETUP_FUNCTION_DEF(Memory);
DF_VIEW_SETUP_FUNCTION_DEF(Breakpoints);
@@ -137,6 +147,7 @@ DF_VIEW_STRING_FROM_STATE_FUNCTION_DEF(Commands);
DF_VIEW_STRING_FROM_STATE_FUNCTION_DEF(FileSystem);
DF_VIEW_STRING_FROM_STATE_FUNCTION_DEF(SystemProcesses);
DF_VIEW_STRING_FROM_STATE_FUNCTION_DEF(EntityLister);
DF_VIEW_STRING_FROM_STATE_FUNCTION_DEF(SymbolLister);
DF_VIEW_STRING_FROM_STATE_FUNCTION_DEF(Target);
DF_VIEW_STRING_FROM_STATE_FUNCTION_DEF(Targets);
DF_VIEW_STRING_FROM_STATE_FUNCTION_DEF(FilePathMap);
@@ -149,6 +160,10 @@ DF_VIEW_STRING_FROM_STATE_FUNCTION_DEF(Disassembly);
DF_VIEW_STRING_FROM_STATE_FUNCTION_DEF(Watch);
DF_VIEW_STRING_FROM_STATE_FUNCTION_DEF(Locals);
DF_VIEW_STRING_FROM_STATE_FUNCTION_DEF(Registers);
DF_VIEW_STRING_FROM_STATE_FUNCTION_DEF(Globals);
DF_VIEW_STRING_FROM_STATE_FUNCTION_DEF(ThreadLocals);
DF_VIEW_STRING_FROM_STATE_FUNCTION_DEF(Types);
DF_VIEW_STRING_FROM_STATE_FUNCTION_DEF(Procedures);
DF_VIEW_STRING_FROM_STATE_FUNCTION_DEF(Output);
DF_VIEW_STRING_FROM_STATE_FUNCTION_DEF(Memory);
DF_VIEW_STRING_FROM_STATE_FUNCTION_DEF(Breakpoints);
@@ -161,6 +176,7 @@ DF_VIEW_CMD_FUNCTION_DEF(Commands);
DF_VIEW_CMD_FUNCTION_DEF(FileSystem);
DF_VIEW_CMD_FUNCTION_DEF(SystemProcesses);
DF_VIEW_CMD_FUNCTION_DEF(EntityLister);
DF_VIEW_CMD_FUNCTION_DEF(SymbolLister);
DF_VIEW_CMD_FUNCTION_DEF(Target);
DF_VIEW_CMD_FUNCTION_DEF(Targets);
DF_VIEW_CMD_FUNCTION_DEF(FilePathMap);
@@ -173,6 +189,10 @@ DF_VIEW_CMD_FUNCTION_DEF(Disassembly);
DF_VIEW_CMD_FUNCTION_DEF(Watch);
DF_VIEW_CMD_FUNCTION_DEF(Locals);
DF_VIEW_CMD_FUNCTION_DEF(Registers);
DF_VIEW_CMD_FUNCTION_DEF(Globals);
DF_VIEW_CMD_FUNCTION_DEF(ThreadLocals);
DF_VIEW_CMD_FUNCTION_DEF(Types);
DF_VIEW_CMD_FUNCTION_DEF(Procedures);
DF_VIEW_CMD_FUNCTION_DEF(Output);
DF_VIEW_CMD_FUNCTION_DEF(Memory);
DF_VIEW_CMD_FUNCTION_DEF(Breakpoints);
@@ -185,6 +205,7 @@ DF_VIEW_UI_FUNCTION_DEF(Commands);
DF_VIEW_UI_FUNCTION_DEF(FileSystem);
DF_VIEW_UI_FUNCTION_DEF(SystemProcesses);
DF_VIEW_UI_FUNCTION_DEF(EntityLister);
DF_VIEW_UI_FUNCTION_DEF(SymbolLister);
DF_VIEW_UI_FUNCTION_DEF(Target);
DF_VIEW_UI_FUNCTION_DEF(Targets);
DF_VIEW_UI_FUNCTION_DEF(FilePathMap);
@@ -197,6 +218,10 @@ DF_VIEW_UI_FUNCTION_DEF(Disassembly);
DF_VIEW_UI_FUNCTION_DEF(Watch);
DF_VIEW_UI_FUNCTION_DEF(Locals);
DF_VIEW_UI_FUNCTION_DEF(Registers);
DF_VIEW_UI_FUNCTION_DEF(Globals);
DF_VIEW_UI_FUNCTION_DEF(ThreadLocals);
DF_VIEW_UI_FUNCTION_DEF(Types);
DF_VIEW_UI_FUNCTION_DEF(Procedures);
DF_VIEW_UI_FUNCTION_DEF(Output);
DF_VIEW_UI_FUNCTION_DEF(Memory);
DF_VIEW_UI_FUNCTION_DEF(Breakpoints);
@@ -774,124 +799,6 @@ df_g_theme_preset_colors__four_coder,
df_g_theme_preset_colors__far_manager,
};
String8 df_g_cmd2view_table_src[] =
{
str8_lit_comp("launch_and_run"),
str8_lit_comp("launch_and_init"),
str8_lit_comp("kill"),
str8_lit_comp("detach"),
str8_lit_comp("select_thread"),
str8_lit_comp("select_thread_window"),
str8_lit_comp("select_thread_view"),
str8_lit_comp("freeze_thread"),
str8_lit_comp("thaw_thread"),
str8_lit_comp("freeze_process"),
str8_lit_comp("thaw_process"),
str8_lit_comp("freeze_machine"),
str8_lit_comp("thaw_machine"),
str8_lit_comp("set_current_path"),
str8_lit_comp("open"),
str8_lit_comp("reload"),
str8_lit_comp("switch"),
str8_lit_comp("load_user"),
str8_lit_comp("load_profile"),
str8_lit_comp("find_thread"),
str8_lit_comp("open_thread_disasm"),
str8_lit_comp("open_file_memory"),
str8_lit_comp("open_process_memory"),
str8_lit_comp("remove_breakpoint"),
str8_lit_comp("edit_breakpoint"),
str8_lit_comp("enable_breakpoint"),
str8_lit_comp("disable_breakpoint"),
str8_lit_comp("edit_breakpoint"),
str8_lit_comp("add_target"),
str8_lit_comp("remove_target"),
str8_lit_comp("edit_target"),
str8_lit_comp("retry_ended_process"),
str8_lit_comp("attach"),
str8_lit_comp("commands"),
str8_lit_comp("target_editor"),
str8_lit_comp("targets"),
str8_lit_comp("file_path_map"),
str8_lit_comp("scheduler"),
str8_lit_comp("call_stack"),
str8_lit_comp("modules"),
str8_lit_comp("pending_entity"),
str8_lit_comp("code"),
str8_lit_comp("watch"),
str8_lit_comp("locals"),
str8_lit_comp("registers"),
str8_lit_comp("output"),
str8_lit_comp("memory"),
str8_lit_comp("disassembly"),
str8_lit_comp("breakpoints"),
str8_lit_comp("watch_pins"),
str8_lit_comp("exception_filters"),
str8_lit_comp("theme"),
str8_lit_comp("pick_file"),
str8_lit_comp("clear_diag_log"),
str8_lit_comp("open_diag_log"),
};
String8 df_g_cmd2view_table_dst[] =
{
str8_lit_comp("entity_lister"),
str8_lit_comp("entity_lister"),
str8_lit_comp("entity_lister"),
str8_lit_comp("entity_lister"),
str8_lit_comp("entity_lister"),
str8_lit_comp("entity_lister"),
str8_lit_comp("entity_lister"),
str8_lit_comp("entity_lister"),
str8_lit_comp("entity_lister"),
str8_lit_comp("entity_lister"),
str8_lit_comp("entity_lister"),
str8_lit_comp("entity_lister"),
str8_lit_comp("entity_lister"),
str8_lit_comp("file_system"),
str8_lit_comp("file_system"),
str8_lit_comp("entity_lister"),
str8_lit_comp("entity_lister"),
str8_lit_comp("file_system"),
str8_lit_comp("file_system"),
str8_lit_comp("entity_lister"),
str8_lit_comp("entity_lister"),
str8_lit_comp("entity_lister"),
str8_lit_comp("entity_lister"),
str8_lit_comp("entity_lister"),
str8_lit_comp("entity_lister"),
str8_lit_comp("entity_lister"),
str8_lit_comp("entity_lister"),
str8_lit_comp("entity_lister"),
str8_lit_comp("file_system"),
str8_lit_comp("entity_lister"),
str8_lit_comp("entity_lister"),
str8_lit_comp("entity_lister"),
str8_lit_comp("system_processes"),
str8_lit_comp("commands"),
str8_lit_comp("target"),
str8_lit_comp("targets"),
str8_lit_comp("file_path_map"),
str8_lit_comp("scheduler"),
str8_lit_comp("call_stack"),
str8_lit_comp("modules"),
str8_lit_comp("pending_entity"),
str8_lit_comp("code"),
str8_lit_comp("watch"),
str8_lit_comp("locals"),
str8_lit_comp("registers"),
str8_lit_comp("output"),
str8_lit_comp("memory"),
str8_lit_comp("disassembly"),
str8_lit_comp("breakpoints"),
str8_lit_comp("watch_pins"),
str8_lit_comp("exception_filters"),
str8_lit_comp("theme"),
str8_lit_comp("file_system"),
str8_lit_comp("entity_lister"),
str8_lit_comp("entity_lister"),
};
DF_CmdParamSlot df_g_cmd_param_slot_2_view_spec_src_map[] =
{
DF_CmdParamSlot_Entity,
@@ -899,6 +806,8 @@ DF_CmdParamSlot_EntityList,
DF_CmdParamSlot_FilePath,
DF_CmdParamSlot_CmdSpec,
DF_CmdParamSlot_ID,
DF_CmdParamSlot_String,
DF_CmdParamSlot_String,
};
String8 df_g_cmd_param_slot_2_view_spec_dst_map[] =
@@ -908,6 +817,19 @@ str8_lit_comp("entity_lister"),
str8_lit_comp("file_system"),
str8_lit_comp("commands"),
str8_lit_comp("system_processes"),
str8_lit_comp("symbol_lister"),
str8_lit_comp("symbol_lister"),
};
String8 df_g_cmd_param_slot_2_view_spec_cmd_map[] =
{
str8_lit_comp(""),
str8_lit_comp(""),
str8_lit_comp(""),
str8_lit_comp(""),
str8_lit_comp(""),
str8_lit_comp("goto_name"),
str8_lit_comp("function_breakpoint"),
};
DF_StringBindingPair df_g_default_binding_table[] =
@@ -936,10 +858,10 @@ DF_StringBindingPair df_g_default_binding_table[] =
{str8_lit_comp("rotate_panel_columns"), {OS_Key_2, 0 |OS_EventFlag_Ctrl }},
{str8_lit_comp("next_panel"), {OS_Key_Comma, 0 |OS_EventFlag_Ctrl }},
{str8_lit_comp("prev_panel"), {OS_Key_Comma, 0 |OS_EventFlag_Ctrl |OS_EventFlag_Shift }},
{str8_lit_comp("focus_panel_right"), {OS_Key_Right, 0 |OS_EventFlag_Ctrl |OS_EventFlag_Shift |OS_EventFlag_Alt}},
{str8_lit_comp("focus_panel_left"), {OS_Key_Left, 0 |OS_EventFlag_Ctrl |OS_EventFlag_Shift |OS_EventFlag_Alt}},
{str8_lit_comp("focus_panel_up"), {OS_Key_Up, 0 |OS_EventFlag_Ctrl |OS_EventFlag_Shift |OS_EventFlag_Alt}},
{str8_lit_comp("focus_panel_down"), {OS_Key_Down, 0 |OS_EventFlag_Ctrl |OS_EventFlag_Shift |OS_EventFlag_Alt}},
{str8_lit_comp("focus_panel_right"), {OS_Key_Right, 0 |OS_EventFlag_Ctrl |OS_EventFlag_Alt}},
{str8_lit_comp("focus_panel_left"), {OS_Key_Left, 0 |OS_EventFlag_Ctrl |OS_EventFlag_Alt}},
{str8_lit_comp("focus_panel_up"), {OS_Key_Up, 0 |OS_EventFlag_Ctrl |OS_EventFlag_Alt}},
{str8_lit_comp("focus_panel_down"), {OS_Key_Down, 0 |OS_EventFlag_Ctrl |OS_EventFlag_Alt}},
{str8_lit_comp("close_panel"), {OS_Key_P, 0 |OS_EventFlag_Ctrl |OS_EventFlag_Shift }},
{str8_lit_comp("next_tab"), {OS_Key_PageDown, 0 |OS_EventFlag_Ctrl }},
{str8_lit_comp("prev_tab"), {OS_Key_PageUp, 0 |OS_EventFlag_Ctrl }},
@@ -948,8 +870,8 @@ DF_StringBindingPair df_g_default_binding_table[] =
{str8_lit_comp("move_tab_right"), {OS_Key_PageDown, 0 |OS_EventFlag_Ctrl |OS_EventFlag_Shift }},
{str8_lit_comp("move_tab_left"), {OS_Key_PageUp, 0 |OS_EventFlag_Ctrl |OS_EventFlag_Shift }},
{str8_lit_comp("close_tab"), {OS_Key_W, 0 |OS_EventFlag_Ctrl }},
{str8_lit_comp("tab_bar_top"), {OS_Key_Up, 0 |OS_EventFlag_Ctrl |OS_EventFlag_Alt}},
{str8_lit_comp("tab_bar_bottom"), {OS_Key_Down, 0 |OS_EventFlag_Ctrl |OS_EventFlag_Alt}},
{str8_lit_comp("tab_bar_top"), {OS_Key_Up, 0 |OS_EventFlag_Ctrl |OS_EventFlag_Shift |OS_EventFlag_Alt}},
{str8_lit_comp("tab_bar_bottom"), {OS_Key_Down, 0 |OS_EventFlag_Ctrl |OS_EventFlag_Shift |OS_EventFlag_Alt}},
{str8_lit_comp("open"), {OS_Key_O, 0 |OS_EventFlag_Ctrl }},
{str8_lit_comp("reload_active"), {OS_Key_R, 0 |OS_EventFlag_Ctrl |OS_EventFlag_Shift }},
{str8_lit_comp("switch"), {OS_Key_I, 0 |OS_EventFlag_Ctrl }},
@@ -1007,9 +929,8 @@ DF_StringBindingPair df_g_default_binding_table[] =
{str8_lit_comp("toggle_breakpoint_cursor"), {OS_Key_F9, 0 }},
{str8_lit_comp("add_target"), {OS_Key_T, 0 |OS_EventFlag_Ctrl }},
{str8_lit_comp("attach"), {OS_Key_F6, 0 |OS_EventFlag_Shift }},
{str8_lit_comp("filter"), {OS_Key_Slash, 0 |OS_EventFlag_Ctrl }},
{str8_lit_comp("run_command"), {OS_Key_F1, 0 }},
{str8_lit_comp("clear_diag_log"), {OS_Key_D, 0 |OS_EventFlag_Ctrl |OS_EventFlag_Alt}},
{str8_lit_comp("open_diag_log"), {OS_Key_D, 0 |OS_EventFlag_Ctrl }},
};
String8 df_g_binding_version_remap_old_name_table[] =
@@ -1028,30 +949,35 @@ str8_lit_comp("open_profile"),
DF_ViewSpecInfo df_g_gfx_view_kind_spec_info_table[] =
{
{(0|0*DF_ViewSpecFlag_ParameterizedByEntity|0*DF_ViewSpecFlag_CanSerialize|0*DF_ViewSpecFlag_CanSerializeEntityPath), str8_lit_comp("null"), str8_lit_comp(""), DF_NameKind_Null, DF_IconKind_Null, DF_VIEW_SETUP_FUNCTION_NAME(Null), DF_VIEW_STRING_FROM_STATE_FUNCTION_NAME(Null), DF_VIEW_CMD_FUNCTION_NAME(Null), DF_VIEW_UI_FUNCTION_NAME(Null)},
{(0|0*DF_ViewSpecFlag_ParameterizedByEntity|0*DF_ViewSpecFlag_CanSerialize|0*DF_ViewSpecFlag_CanSerializeEntityPath), str8_lit_comp("empty"), str8_lit_comp(""), DF_NameKind_Null, DF_IconKind_Null, DF_VIEW_SETUP_FUNCTION_NAME(Empty), DF_VIEW_STRING_FROM_STATE_FUNCTION_NAME(Empty), DF_VIEW_CMD_FUNCTION_NAME(Empty), DF_VIEW_UI_FUNCTION_NAME(Empty)},
{(0|0*DF_ViewSpecFlag_ParameterizedByEntity|0*DF_ViewSpecFlag_CanSerialize|0*DF_ViewSpecFlag_CanSerializeEntityPath), str8_lit_comp("commands"), str8_lit_comp("Commands"), DF_NameKind_Null, DF_IconKind_List, DF_VIEW_SETUP_FUNCTION_NAME(Commands), DF_VIEW_STRING_FROM_STATE_FUNCTION_NAME(Commands), DF_VIEW_CMD_FUNCTION_NAME(Commands), DF_VIEW_UI_FUNCTION_NAME(Commands)},
{(0|0*DF_ViewSpecFlag_ParameterizedByEntity|0*DF_ViewSpecFlag_CanSerialize|0*DF_ViewSpecFlag_CanSerializeEntityPath), str8_lit_comp("file_system"), str8_lit_comp("File System"), DF_NameKind_Null, DF_IconKind_FileOutline, DF_VIEW_SETUP_FUNCTION_NAME(FileSystem), DF_VIEW_STRING_FROM_STATE_FUNCTION_NAME(FileSystem), DF_VIEW_CMD_FUNCTION_NAME(FileSystem), DF_VIEW_UI_FUNCTION_NAME(FileSystem)},
{(0|0*DF_ViewSpecFlag_ParameterizedByEntity|0*DF_ViewSpecFlag_CanSerialize|0*DF_ViewSpecFlag_CanSerializeEntityPath), str8_lit_comp("system_processes"), str8_lit_comp("System Processes"), DF_NameKind_Null, DF_IconKind_Null, DF_VIEW_SETUP_FUNCTION_NAME(SystemProcesses), DF_VIEW_STRING_FROM_STATE_FUNCTION_NAME(SystemProcesses), DF_VIEW_CMD_FUNCTION_NAME(SystemProcesses), DF_VIEW_UI_FUNCTION_NAME(SystemProcesses)},
{(0|0*DF_ViewSpecFlag_ParameterizedByEntity|0*DF_ViewSpecFlag_CanSerialize|0*DF_ViewSpecFlag_CanSerializeEntityPath), str8_lit_comp("entity_lister"), str8_lit_comp("Entity List"), DF_NameKind_EntityKindName, DF_IconKind_Null, DF_VIEW_SETUP_FUNCTION_NAME(EntityLister), DF_VIEW_STRING_FROM_STATE_FUNCTION_NAME(EntityLister), DF_VIEW_CMD_FUNCTION_NAME(EntityLister), DF_VIEW_UI_FUNCTION_NAME(EntityLister)},
{(0|1*DF_ViewSpecFlag_ParameterizedByEntity|0*DF_ViewSpecFlag_CanSerialize|0*DF_ViewSpecFlag_CanSerializeEntityPath), str8_lit_comp("target"), str8_lit_comp("Target"), DF_NameKind_EntityName, DF_IconKind_Target, DF_VIEW_SETUP_FUNCTION_NAME(Target), DF_VIEW_STRING_FROM_STATE_FUNCTION_NAME(Target), DF_VIEW_CMD_FUNCTION_NAME(Target), DF_VIEW_UI_FUNCTION_NAME(Target)},
{(0|0*DF_ViewSpecFlag_ParameterizedByEntity|1*DF_ViewSpecFlag_CanSerialize|0*DF_ViewSpecFlag_CanSerializeEntityPath), str8_lit_comp("targets"), str8_lit_comp("Targets"), DF_NameKind_Null, DF_IconKind_Target, DF_VIEW_SETUP_FUNCTION_NAME(Targets), DF_VIEW_STRING_FROM_STATE_FUNCTION_NAME(Targets), DF_VIEW_CMD_FUNCTION_NAME(Targets), DF_VIEW_UI_FUNCTION_NAME(Targets)},
{(0|0*DF_ViewSpecFlag_ParameterizedByEntity|1*DF_ViewSpecFlag_CanSerialize|0*DF_ViewSpecFlag_CanSerializeEntityPath), str8_lit_comp("file_path_map"), str8_lit_comp("File Path Map"), DF_NameKind_Null, DF_IconKind_FileOutline, DF_VIEW_SETUP_FUNCTION_NAME(FilePathMap), DF_VIEW_STRING_FROM_STATE_FUNCTION_NAME(FilePathMap), DF_VIEW_CMD_FUNCTION_NAME(FilePathMap), DF_VIEW_UI_FUNCTION_NAME(FilePathMap)},
{(0|0*DF_ViewSpecFlag_ParameterizedByEntity|1*DF_ViewSpecFlag_CanSerialize|0*DF_ViewSpecFlag_CanSerializeEntityPath), str8_lit_comp("scheduler"), str8_lit_comp("Scheduler"), DF_NameKind_Null, DF_IconKind_Scheduler, DF_VIEW_SETUP_FUNCTION_NAME(Scheduler), DF_VIEW_STRING_FROM_STATE_FUNCTION_NAME(Scheduler), DF_VIEW_CMD_FUNCTION_NAME(Scheduler), DF_VIEW_UI_FUNCTION_NAME(Scheduler)},
{(0|0*DF_ViewSpecFlag_ParameterizedByEntity|1*DF_ViewSpecFlag_CanSerialize|0*DF_ViewSpecFlag_CanSerializeEntityPath), str8_lit_comp("call_stack"), str8_lit_comp("Call Stack"), DF_NameKind_Null, DF_IconKind_Thread, DF_VIEW_SETUP_FUNCTION_NAME(CallStack), DF_VIEW_STRING_FROM_STATE_FUNCTION_NAME(CallStack), DF_VIEW_CMD_FUNCTION_NAME(CallStack), DF_VIEW_UI_FUNCTION_NAME(CallStack)},
{(0|0*DF_ViewSpecFlag_ParameterizedByEntity|1*DF_ViewSpecFlag_CanSerialize|0*DF_ViewSpecFlag_CanSerializeEntityPath), str8_lit_comp("modules"), str8_lit_comp("Modules"), DF_NameKind_Null, DF_IconKind_Module, DF_VIEW_SETUP_FUNCTION_NAME(Modules), DF_VIEW_STRING_FROM_STATE_FUNCTION_NAME(Modules), DF_VIEW_CMD_FUNCTION_NAME(Modules), DF_VIEW_UI_FUNCTION_NAME(Modules)},
{(0|1*DF_ViewSpecFlag_ParameterizedByEntity|0*DF_ViewSpecFlag_CanSerialize|0*DF_ViewSpecFlag_CanSerializeEntityPath), str8_lit_comp("pending_entity"), str8_lit_comp("Pending Entity"), DF_NameKind_EntityName, DF_IconKind_FileOutline, DF_VIEW_SETUP_FUNCTION_NAME(PendingEntity), DF_VIEW_STRING_FROM_STATE_FUNCTION_NAME(PendingEntity), DF_VIEW_CMD_FUNCTION_NAME(PendingEntity), DF_VIEW_UI_FUNCTION_NAME(PendingEntity)},
{(0|1*DF_ViewSpecFlag_ParameterizedByEntity|1*DF_ViewSpecFlag_CanSerialize|1*DF_ViewSpecFlag_CanSerializeEntityPath), str8_lit_comp("code"), str8_lit_comp("Code"), DF_NameKind_EntityName, DF_IconKind_FileOutline, DF_VIEW_SETUP_FUNCTION_NAME(Code), DF_VIEW_STRING_FROM_STATE_FUNCTION_NAME(Code), DF_VIEW_CMD_FUNCTION_NAME(Code), DF_VIEW_UI_FUNCTION_NAME(Code)},
{(0|0*DF_ViewSpecFlag_ParameterizedByEntity|1*DF_ViewSpecFlag_CanSerialize|0*DF_ViewSpecFlag_CanSerializeEntityPath), str8_lit_comp("disassembly"), str8_lit_comp("Disassembly"), DF_NameKind_Null, DF_IconKind_Glasses, DF_VIEW_SETUP_FUNCTION_NAME(Disassembly), DF_VIEW_STRING_FROM_STATE_FUNCTION_NAME(Disassembly), DF_VIEW_CMD_FUNCTION_NAME(Disassembly), DF_VIEW_UI_FUNCTION_NAME(Disassembly)},
{(0|0*DF_ViewSpecFlag_ParameterizedByEntity|1*DF_ViewSpecFlag_CanSerialize|0*DF_ViewSpecFlag_CanSerializeEntityPath), str8_lit_comp("watch"), str8_lit_comp("Watch"), DF_NameKind_Null, DF_IconKind_Binoculars, DF_VIEW_SETUP_FUNCTION_NAME(Watch), DF_VIEW_STRING_FROM_STATE_FUNCTION_NAME(Watch), DF_VIEW_CMD_FUNCTION_NAME(Watch), DF_VIEW_UI_FUNCTION_NAME(Watch)},
{(0|0*DF_ViewSpecFlag_ParameterizedByEntity|1*DF_ViewSpecFlag_CanSerialize|0*DF_ViewSpecFlag_CanSerializeEntityPath), str8_lit_comp("locals"), str8_lit_comp("Locals"), DF_NameKind_Null, DF_IconKind_Binoculars, DF_VIEW_SETUP_FUNCTION_NAME(Locals), DF_VIEW_STRING_FROM_STATE_FUNCTION_NAME(Locals), DF_VIEW_CMD_FUNCTION_NAME(Locals), DF_VIEW_UI_FUNCTION_NAME(Locals)},
{(0|0*DF_ViewSpecFlag_ParameterizedByEntity|1*DF_ViewSpecFlag_CanSerialize|0*DF_ViewSpecFlag_CanSerializeEntityPath), str8_lit_comp("registers"), str8_lit_comp("Registers"), DF_NameKind_Null, DF_IconKind_Binoculars, DF_VIEW_SETUP_FUNCTION_NAME(Registers), DF_VIEW_STRING_FROM_STATE_FUNCTION_NAME(Registers), DF_VIEW_CMD_FUNCTION_NAME(Registers), DF_VIEW_UI_FUNCTION_NAME(Registers)},
{(0|0*DF_ViewSpecFlag_ParameterizedByEntity|1*DF_ViewSpecFlag_CanSerialize|0*DF_ViewSpecFlag_CanSerializeEntityPath), str8_lit_comp("output"), str8_lit_comp("Output"), DF_NameKind_Null, DF_IconKind_List, DF_VIEW_SETUP_FUNCTION_NAME(Output), DF_VIEW_STRING_FROM_STATE_FUNCTION_NAME(Output), DF_VIEW_CMD_FUNCTION_NAME(Output), DF_VIEW_UI_FUNCTION_NAME(Output)},
{(0|0*DF_ViewSpecFlag_ParameterizedByEntity|1*DF_ViewSpecFlag_CanSerialize|1*DF_ViewSpecFlag_CanSerializeEntityPath), str8_lit_comp("memory"), str8_lit_comp("Memory"), DF_NameKind_Null, DF_IconKind_Grid, DF_VIEW_SETUP_FUNCTION_NAME(Memory), DF_VIEW_STRING_FROM_STATE_FUNCTION_NAME(Memory), DF_VIEW_CMD_FUNCTION_NAME(Memory), DF_VIEW_UI_FUNCTION_NAME(Memory)},
{(0|0*DF_ViewSpecFlag_ParameterizedByEntity|1*DF_ViewSpecFlag_CanSerialize|0*DF_ViewSpecFlag_CanSerializeEntityPath), str8_lit_comp("breakpoints"), str8_lit_comp("Breakpoints"), DF_NameKind_Null, DF_IconKind_CircleFilled, DF_VIEW_SETUP_FUNCTION_NAME(Breakpoints), DF_VIEW_STRING_FROM_STATE_FUNCTION_NAME(Breakpoints), DF_VIEW_CMD_FUNCTION_NAME(Breakpoints), DF_VIEW_UI_FUNCTION_NAME(Breakpoints)},
{(0|0*DF_ViewSpecFlag_ParameterizedByEntity|1*DF_ViewSpecFlag_CanSerialize|0*DF_ViewSpecFlag_CanSerializeEntityPath), str8_lit_comp("watch_pins"), str8_lit_comp("Watch Pins"), DF_NameKind_Null, DF_IconKind_Pin, DF_VIEW_SETUP_FUNCTION_NAME(WatchPins), DF_VIEW_STRING_FROM_STATE_FUNCTION_NAME(WatchPins), DF_VIEW_CMD_FUNCTION_NAME(WatchPins), DF_VIEW_UI_FUNCTION_NAME(WatchPins)},
{(0|0*DF_ViewSpecFlag_ParameterizedByEntity|1*DF_ViewSpecFlag_CanSerialize|0*DF_ViewSpecFlag_CanSerializeEntityPath), str8_lit_comp("exception_filters"), str8_lit_comp("Exception Filters"), DF_NameKind_Null, DF_IconKind_Gear, DF_VIEW_SETUP_FUNCTION_NAME(ExceptionFilters), DF_VIEW_STRING_FROM_STATE_FUNCTION_NAME(ExceptionFilters), DF_VIEW_CMD_FUNCTION_NAME(ExceptionFilters), DF_VIEW_UI_FUNCTION_NAME(ExceptionFilters)},
{(0|0*DF_ViewSpecFlag_ParameterizedByEntity|1*DF_ViewSpecFlag_CanSerialize|0*DF_ViewSpecFlag_CanSerializeEntityPath), str8_lit_comp("theme"), str8_lit_comp("Theme"), DF_NameKind_Null, DF_IconKind_Palette, DF_VIEW_SETUP_FUNCTION_NAME(Theme), DF_VIEW_STRING_FROM_STATE_FUNCTION_NAME(Theme), DF_VIEW_CMD_FUNCTION_NAME(Theme), DF_VIEW_UI_FUNCTION_NAME(Theme)},
{(0|0*DF_ViewSpecFlag_ParameterizedByEntity|0*DF_ViewSpecFlag_CanSerialize|0*DF_ViewSpecFlag_CanSerializeEntityPath|0*DF_ViewSpecFlag_CanFilter|0*DF_ViewSpecFlag_FilterIsCode|0*DF_ViewSpecFlag_TypingAutomaticallyFilters), str8_lit_comp("null"), str8_lit_comp(""), DF_NameKind_Null, DF_IconKind_Null, DF_VIEW_SETUP_FUNCTION_NAME(Null), DF_VIEW_STRING_FROM_STATE_FUNCTION_NAME(Null), DF_VIEW_CMD_FUNCTION_NAME(Null), DF_VIEW_UI_FUNCTION_NAME(Null)},
{(0|0*DF_ViewSpecFlag_ParameterizedByEntity|0*DF_ViewSpecFlag_CanSerialize|0*DF_ViewSpecFlag_CanSerializeEntityPath|0*DF_ViewSpecFlag_CanFilter|0*DF_ViewSpecFlag_FilterIsCode|0*DF_ViewSpecFlag_TypingAutomaticallyFilters), str8_lit_comp("empty"), str8_lit_comp(""), DF_NameKind_Null, DF_IconKind_Null, DF_VIEW_SETUP_FUNCTION_NAME(Empty), DF_VIEW_STRING_FROM_STATE_FUNCTION_NAME(Empty), DF_VIEW_CMD_FUNCTION_NAME(Empty), DF_VIEW_UI_FUNCTION_NAME(Empty)},
{(0|0*DF_ViewSpecFlag_ParameterizedByEntity|0*DF_ViewSpecFlag_CanSerialize|0*DF_ViewSpecFlag_CanSerializeEntityPath|0*DF_ViewSpecFlag_CanFilter|0*DF_ViewSpecFlag_FilterIsCode|0*DF_ViewSpecFlag_TypingAutomaticallyFilters), str8_lit_comp("commands"), str8_lit_comp("Commands"), DF_NameKind_Null, DF_IconKind_List, DF_VIEW_SETUP_FUNCTION_NAME(Commands), DF_VIEW_STRING_FROM_STATE_FUNCTION_NAME(Commands), DF_VIEW_CMD_FUNCTION_NAME(Commands), DF_VIEW_UI_FUNCTION_NAME(Commands)},
{(0|0*DF_ViewSpecFlag_ParameterizedByEntity|0*DF_ViewSpecFlag_CanSerialize|0*DF_ViewSpecFlag_CanSerializeEntityPath|0*DF_ViewSpecFlag_CanFilter|0*DF_ViewSpecFlag_FilterIsCode|0*DF_ViewSpecFlag_TypingAutomaticallyFilters), str8_lit_comp("file_system"), str8_lit_comp("File System"), DF_NameKind_Null, DF_IconKind_FileOutline, DF_VIEW_SETUP_FUNCTION_NAME(FileSystem), DF_VIEW_STRING_FROM_STATE_FUNCTION_NAME(FileSystem), DF_VIEW_CMD_FUNCTION_NAME(FileSystem), DF_VIEW_UI_FUNCTION_NAME(FileSystem)},
{(0|0*DF_ViewSpecFlag_ParameterizedByEntity|0*DF_ViewSpecFlag_CanSerialize|0*DF_ViewSpecFlag_CanSerializeEntityPath|0*DF_ViewSpecFlag_CanFilter|0*DF_ViewSpecFlag_FilterIsCode|0*DF_ViewSpecFlag_TypingAutomaticallyFilters), str8_lit_comp("system_processes"), str8_lit_comp("System Processes"), DF_NameKind_Null, DF_IconKind_Null, DF_VIEW_SETUP_FUNCTION_NAME(SystemProcesses), DF_VIEW_STRING_FROM_STATE_FUNCTION_NAME(SystemProcesses), DF_VIEW_CMD_FUNCTION_NAME(SystemProcesses), DF_VIEW_UI_FUNCTION_NAME(SystemProcesses)},
{(0|0*DF_ViewSpecFlag_ParameterizedByEntity|0*DF_ViewSpecFlag_CanSerialize|0*DF_ViewSpecFlag_CanSerializeEntityPath|0*DF_ViewSpecFlag_CanFilter|0*DF_ViewSpecFlag_FilterIsCode|0*DF_ViewSpecFlag_TypingAutomaticallyFilters), str8_lit_comp("entity_lister"), str8_lit_comp("Entity List"), DF_NameKind_EntityKindName, DF_IconKind_Null, DF_VIEW_SETUP_FUNCTION_NAME(EntityLister), DF_VIEW_STRING_FROM_STATE_FUNCTION_NAME(EntityLister), DF_VIEW_CMD_FUNCTION_NAME(EntityLister), DF_VIEW_UI_FUNCTION_NAME(EntityLister)},
{(0|0*DF_ViewSpecFlag_ParameterizedByEntity|0*DF_ViewSpecFlag_CanSerialize|0*DF_ViewSpecFlag_CanSerializeEntityPath|0*DF_ViewSpecFlag_CanFilter|0*DF_ViewSpecFlag_FilterIsCode|0*DF_ViewSpecFlag_TypingAutomaticallyFilters), str8_lit_comp("symbol_lister"), str8_lit_comp("Symbols"), DF_NameKind_Null, DF_IconKind_Null, DF_VIEW_SETUP_FUNCTION_NAME(SymbolLister), DF_VIEW_STRING_FROM_STATE_FUNCTION_NAME(SymbolLister), DF_VIEW_CMD_FUNCTION_NAME(SymbolLister), DF_VIEW_UI_FUNCTION_NAME(SymbolLister)},
{(0|1*DF_ViewSpecFlag_ParameterizedByEntity|0*DF_ViewSpecFlag_CanSerialize|0*DF_ViewSpecFlag_CanSerializeEntityPath|0*DF_ViewSpecFlag_CanFilter|0*DF_ViewSpecFlag_FilterIsCode|0*DF_ViewSpecFlag_TypingAutomaticallyFilters), str8_lit_comp("target"), str8_lit_comp("Target"), DF_NameKind_EntityName, DF_IconKind_Target, DF_VIEW_SETUP_FUNCTION_NAME(Target), DF_VIEW_STRING_FROM_STATE_FUNCTION_NAME(Target), DF_VIEW_CMD_FUNCTION_NAME(Target), DF_VIEW_UI_FUNCTION_NAME(Target)},
{(0|0*DF_ViewSpecFlag_ParameterizedByEntity|1*DF_ViewSpecFlag_CanSerialize|0*DF_ViewSpecFlag_CanSerializeEntityPath|1*DF_ViewSpecFlag_CanFilter|0*DF_ViewSpecFlag_FilterIsCode|1*DF_ViewSpecFlag_TypingAutomaticallyFilters), str8_lit_comp("targets"), str8_lit_comp("Targets"), DF_NameKind_Null, DF_IconKind_Target, DF_VIEW_SETUP_FUNCTION_NAME(Targets), DF_VIEW_STRING_FROM_STATE_FUNCTION_NAME(Targets), DF_VIEW_CMD_FUNCTION_NAME(Targets), DF_VIEW_UI_FUNCTION_NAME(Targets)},
{(0|0*DF_ViewSpecFlag_ParameterizedByEntity|1*DF_ViewSpecFlag_CanSerialize|0*DF_ViewSpecFlag_CanSerializeEntityPath|0*DF_ViewSpecFlag_CanFilter|0*DF_ViewSpecFlag_FilterIsCode|0*DF_ViewSpecFlag_TypingAutomaticallyFilters), str8_lit_comp("file_path_map"), str8_lit_comp("File Path Map"), DF_NameKind_Null, DF_IconKind_FileOutline, DF_VIEW_SETUP_FUNCTION_NAME(FilePathMap), DF_VIEW_STRING_FROM_STATE_FUNCTION_NAME(FilePathMap), DF_VIEW_CMD_FUNCTION_NAME(FilePathMap), DF_VIEW_UI_FUNCTION_NAME(FilePathMap)},
{(0|0*DF_ViewSpecFlag_ParameterizedByEntity|1*DF_ViewSpecFlag_CanSerialize|0*DF_ViewSpecFlag_CanSerializeEntityPath|1*DF_ViewSpecFlag_CanFilter|1*DF_ViewSpecFlag_FilterIsCode|1*DF_ViewSpecFlag_TypingAutomaticallyFilters), str8_lit_comp("scheduler"), str8_lit_comp("Scheduler"), DF_NameKind_Null, DF_IconKind_Scheduler, DF_VIEW_SETUP_FUNCTION_NAME(Scheduler), DF_VIEW_STRING_FROM_STATE_FUNCTION_NAME(Scheduler), DF_VIEW_CMD_FUNCTION_NAME(Scheduler), DF_VIEW_UI_FUNCTION_NAME(Scheduler)},
{(0|0*DF_ViewSpecFlag_ParameterizedByEntity|1*DF_ViewSpecFlag_CanSerialize|0*DF_ViewSpecFlag_CanSerializeEntityPath|0*DF_ViewSpecFlag_CanFilter|0*DF_ViewSpecFlag_FilterIsCode|0*DF_ViewSpecFlag_TypingAutomaticallyFilters), str8_lit_comp("call_stack"), str8_lit_comp("Call Stack"), DF_NameKind_Null, DF_IconKind_Thread, DF_VIEW_SETUP_FUNCTION_NAME(CallStack), DF_VIEW_STRING_FROM_STATE_FUNCTION_NAME(CallStack), DF_VIEW_CMD_FUNCTION_NAME(CallStack), DF_VIEW_UI_FUNCTION_NAME(CallStack)},
{(0|0*DF_ViewSpecFlag_ParameterizedByEntity|1*DF_ViewSpecFlag_CanSerialize|0*DF_ViewSpecFlag_CanSerializeEntityPath|1*DF_ViewSpecFlag_CanFilter|0*DF_ViewSpecFlag_FilterIsCode|1*DF_ViewSpecFlag_TypingAutomaticallyFilters), str8_lit_comp("modules"), str8_lit_comp("Modules"), DF_NameKind_Null, DF_IconKind_Module, DF_VIEW_SETUP_FUNCTION_NAME(Modules), DF_VIEW_STRING_FROM_STATE_FUNCTION_NAME(Modules), DF_VIEW_CMD_FUNCTION_NAME(Modules), DF_VIEW_UI_FUNCTION_NAME(Modules)},
{(0|1*DF_ViewSpecFlag_ParameterizedByEntity|0*DF_ViewSpecFlag_CanSerialize|0*DF_ViewSpecFlag_CanSerializeEntityPath|0*DF_ViewSpecFlag_CanFilter|0*DF_ViewSpecFlag_FilterIsCode|0*DF_ViewSpecFlag_TypingAutomaticallyFilters), str8_lit_comp("pending_entity"), str8_lit_comp("Pending Entity"), DF_NameKind_EntityName, DF_IconKind_FileOutline, DF_VIEW_SETUP_FUNCTION_NAME(PendingEntity), DF_VIEW_STRING_FROM_STATE_FUNCTION_NAME(PendingEntity), DF_VIEW_CMD_FUNCTION_NAME(PendingEntity), DF_VIEW_UI_FUNCTION_NAME(PendingEntity)},
{(0|1*DF_ViewSpecFlag_ParameterizedByEntity|1*DF_ViewSpecFlag_CanSerialize|1*DF_ViewSpecFlag_CanSerializeEntityPath|0*DF_ViewSpecFlag_CanFilter|0*DF_ViewSpecFlag_FilterIsCode|0*DF_ViewSpecFlag_TypingAutomaticallyFilters), str8_lit_comp("code"), str8_lit_comp("Code"), DF_NameKind_EntityName, DF_IconKind_FileOutline, DF_VIEW_SETUP_FUNCTION_NAME(Code), DF_VIEW_STRING_FROM_STATE_FUNCTION_NAME(Code), DF_VIEW_CMD_FUNCTION_NAME(Code), DF_VIEW_UI_FUNCTION_NAME(Code)},
{(0|0*DF_ViewSpecFlag_ParameterizedByEntity|1*DF_ViewSpecFlag_CanSerialize|0*DF_ViewSpecFlag_CanSerializeEntityPath|0*DF_ViewSpecFlag_CanFilter|0*DF_ViewSpecFlag_FilterIsCode|0*DF_ViewSpecFlag_TypingAutomaticallyFilters), str8_lit_comp("disassembly"), str8_lit_comp("Disassembly"), DF_NameKind_Null, DF_IconKind_Glasses, DF_VIEW_SETUP_FUNCTION_NAME(Disassembly), DF_VIEW_STRING_FROM_STATE_FUNCTION_NAME(Disassembly), DF_VIEW_CMD_FUNCTION_NAME(Disassembly), DF_VIEW_UI_FUNCTION_NAME(Disassembly)},
{(0|0*DF_ViewSpecFlag_ParameterizedByEntity|1*DF_ViewSpecFlag_CanSerialize|0*DF_ViewSpecFlag_CanSerializeEntityPath|1*DF_ViewSpecFlag_CanFilter|1*DF_ViewSpecFlag_FilterIsCode|1*DF_ViewSpecFlag_TypingAutomaticallyFilters), str8_lit_comp("watch"), str8_lit_comp("Watch"), DF_NameKind_Null, DF_IconKind_Binoculars, DF_VIEW_SETUP_FUNCTION_NAME(Watch), DF_VIEW_STRING_FROM_STATE_FUNCTION_NAME(Watch), DF_VIEW_CMD_FUNCTION_NAME(Watch), DF_VIEW_UI_FUNCTION_NAME(Watch)},
{(0|0*DF_ViewSpecFlag_ParameterizedByEntity|1*DF_ViewSpecFlag_CanSerialize|0*DF_ViewSpecFlag_CanSerializeEntityPath|1*DF_ViewSpecFlag_CanFilter|1*DF_ViewSpecFlag_FilterIsCode|1*DF_ViewSpecFlag_TypingAutomaticallyFilters), str8_lit_comp("locals"), str8_lit_comp("Locals"), DF_NameKind_Null, DF_IconKind_Binoculars, DF_VIEW_SETUP_FUNCTION_NAME(Locals), DF_VIEW_STRING_FROM_STATE_FUNCTION_NAME(Locals), DF_VIEW_CMD_FUNCTION_NAME(Locals), DF_VIEW_UI_FUNCTION_NAME(Locals)},
{(0|0*DF_ViewSpecFlag_ParameterizedByEntity|1*DF_ViewSpecFlag_CanSerialize|0*DF_ViewSpecFlag_CanSerializeEntityPath|1*DF_ViewSpecFlag_CanFilter|1*DF_ViewSpecFlag_FilterIsCode|1*DF_ViewSpecFlag_TypingAutomaticallyFilters), str8_lit_comp("registers"), str8_lit_comp("Registers"), DF_NameKind_Null, DF_IconKind_Binoculars, DF_VIEW_SETUP_FUNCTION_NAME(Registers), DF_VIEW_STRING_FROM_STATE_FUNCTION_NAME(Registers), DF_VIEW_CMD_FUNCTION_NAME(Registers), DF_VIEW_UI_FUNCTION_NAME(Registers)},
{(0|0*DF_ViewSpecFlag_ParameterizedByEntity|1*DF_ViewSpecFlag_CanSerialize|0*DF_ViewSpecFlag_CanSerializeEntityPath|1*DF_ViewSpecFlag_CanFilter|1*DF_ViewSpecFlag_FilterIsCode|1*DF_ViewSpecFlag_TypingAutomaticallyFilters), str8_lit_comp("globals"), str8_lit_comp("Globals"), DF_NameKind_Null, DF_IconKind_Binoculars, DF_VIEW_SETUP_FUNCTION_NAME(Globals), DF_VIEW_STRING_FROM_STATE_FUNCTION_NAME(Globals), DF_VIEW_CMD_FUNCTION_NAME(Globals), DF_VIEW_UI_FUNCTION_NAME(Globals)},
{(0|0*DF_ViewSpecFlag_ParameterizedByEntity|1*DF_ViewSpecFlag_CanSerialize|0*DF_ViewSpecFlag_CanSerializeEntityPath|1*DF_ViewSpecFlag_CanFilter|1*DF_ViewSpecFlag_FilterIsCode|1*DF_ViewSpecFlag_TypingAutomaticallyFilters), str8_lit_comp("thread_locals"), str8_lit_comp("Thread Locals"), DF_NameKind_Null, DF_IconKind_Binoculars, DF_VIEW_SETUP_FUNCTION_NAME(ThreadLocals), DF_VIEW_STRING_FROM_STATE_FUNCTION_NAME(ThreadLocals), DF_VIEW_CMD_FUNCTION_NAME(ThreadLocals), DF_VIEW_UI_FUNCTION_NAME(ThreadLocals)},
{(0|0*DF_ViewSpecFlag_ParameterizedByEntity|1*DF_ViewSpecFlag_CanSerialize|0*DF_ViewSpecFlag_CanSerializeEntityPath|1*DF_ViewSpecFlag_CanFilter|1*DF_ViewSpecFlag_FilterIsCode|1*DF_ViewSpecFlag_TypingAutomaticallyFilters), str8_lit_comp("types"), str8_lit_comp("Types"), DF_NameKind_Null, DF_IconKind_Binoculars, DF_VIEW_SETUP_FUNCTION_NAME(Types), DF_VIEW_STRING_FROM_STATE_FUNCTION_NAME(Types), DF_VIEW_CMD_FUNCTION_NAME(Types), DF_VIEW_UI_FUNCTION_NAME(Types)},
{(0|0*DF_ViewSpecFlag_ParameterizedByEntity|1*DF_ViewSpecFlag_CanSerialize|0*DF_ViewSpecFlag_CanSerializeEntityPath|1*DF_ViewSpecFlag_CanFilter|1*DF_ViewSpecFlag_FilterIsCode|1*DF_ViewSpecFlag_TypingAutomaticallyFilters), str8_lit_comp("procedures"), str8_lit_comp("Procedures"), DF_NameKind_Null, DF_IconKind_Binoculars, DF_VIEW_SETUP_FUNCTION_NAME(Procedures), DF_VIEW_STRING_FROM_STATE_FUNCTION_NAME(Procedures), DF_VIEW_CMD_FUNCTION_NAME(Procedures), DF_VIEW_UI_FUNCTION_NAME(Procedures)},
{(0|0*DF_ViewSpecFlag_ParameterizedByEntity|1*DF_ViewSpecFlag_CanSerialize|0*DF_ViewSpecFlag_CanSerializeEntityPath|0*DF_ViewSpecFlag_CanFilter|0*DF_ViewSpecFlag_FilterIsCode|0*DF_ViewSpecFlag_TypingAutomaticallyFilters), str8_lit_comp("output"), str8_lit_comp("Output"), DF_NameKind_Null, DF_IconKind_List, DF_VIEW_SETUP_FUNCTION_NAME(Output), DF_VIEW_STRING_FROM_STATE_FUNCTION_NAME(Output), DF_VIEW_CMD_FUNCTION_NAME(Output), DF_VIEW_UI_FUNCTION_NAME(Output)},
{(0|0*DF_ViewSpecFlag_ParameterizedByEntity|1*DF_ViewSpecFlag_CanSerialize|1*DF_ViewSpecFlag_CanSerializeEntityPath|0*DF_ViewSpecFlag_CanFilter|0*DF_ViewSpecFlag_FilterIsCode|0*DF_ViewSpecFlag_TypingAutomaticallyFilters), str8_lit_comp("memory"), str8_lit_comp("Memory"), DF_NameKind_Null, DF_IconKind_Grid, DF_VIEW_SETUP_FUNCTION_NAME(Memory), DF_VIEW_STRING_FROM_STATE_FUNCTION_NAME(Memory), DF_VIEW_CMD_FUNCTION_NAME(Memory), DF_VIEW_UI_FUNCTION_NAME(Memory)},
{(0|0*DF_ViewSpecFlag_ParameterizedByEntity|1*DF_ViewSpecFlag_CanSerialize|0*DF_ViewSpecFlag_CanSerializeEntityPath|1*DF_ViewSpecFlag_CanFilter|0*DF_ViewSpecFlag_FilterIsCode|1*DF_ViewSpecFlag_TypingAutomaticallyFilters), str8_lit_comp("breakpoints"), str8_lit_comp("Breakpoints"), DF_NameKind_Null, DF_IconKind_CircleFilled, DF_VIEW_SETUP_FUNCTION_NAME(Breakpoints), DF_VIEW_STRING_FROM_STATE_FUNCTION_NAME(Breakpoints), DF_VIEW_CMD_FUNCTION_NAME(Breakpoints), DF_VIEW_UI_FUNCTION_NAME(Breakpoints)},
{(0|0*DF_ViewSpecFlag_ParameterizedByEntity|1*DF_ViewSpecFlag_CanSerialize|0*DF_ViewSpecFlag_CanSerializeEntityPath|1*DF_ViewSpecFlag_CanFilter|1*DF_ViewSpecFlag_FilterIsCode|1*DF_ViewSpecFlag_TypingAutomaticallyFilters), str8_lit_comp("watch_pins"), str8_lit_comp("Watch Pins"), DF_NameKind_Null, DF_IconKind_Pin, DF_VIEW_SETUP_FUNCTION_NAME(WatchPins), DF_VIEW_STRING_FROM_STATE_FUNCTION_NAME(WatchPins), DF_VIEW_CMD_FUNCTION_NAME(WatchPins), DF_VIEW_UI_FUNCTION_NAME(WatchPins)},
{(0|0*DF_ViewSpecFlag_ParameterizedByEntity|1*DF_ViewSpecFlag_CanSerialize|0*DF_ViewSpecFlag_CanSerializeEntityPath|1*DF_ViewSpecFlag_CanFilter|0*DF_ViewSpecFlag_FilterIsCode|1*DF_ViewSpecFlag_TypingAutomaticallyFilters), str8_lit_comp("exception_filters"), str8_lit_comp("Exception Filters"), DF_NameKind_Null, DF_IconKind_Gear, DF_VIEW_SETUP_FUNCTION_NAME(ExceptionFilters), DF_VIEW_STRING_FROM_STATE_FUNCTION_NAME(ExceptionFilters), DF_VIEW_CMD_FUNCTION_NAME(ExceptionFilters), DF_VIEW_UI_FUNCTION_NAME(ExceptionFilters)},
{(0|0*DF_ViewSpecFlag_ParameterizedByEntity|1*DF_ViewSpecFlag_CanSerialize|0*DF_ViewSpecFlag_CanSerializeEntityPath|0*DF_ViewSpecFlag_CanFilter|0*DF_ViewSpecFlag_FilterIsCode|0*DF_ViewSpecFlag_TypingAutomaticallyFilters), str8_lit_comp("theme"), str8_lit_comp("Theme"), DF_NameKind_Null, DF_IconKind_Palette, DF_VIEW_SETUP_FUNCTION_NAME(Theme), DF_VIEW_STRING_FROM_STATE_FUNCTION_NAME(Theme), DF_VIEW_CMD_FUNCTION_NAME(Theme), DF_VIEW_UI_FUNCTION_NAME(Theme)},
};
String8 df_g_theme_color_display_string_table[] =
+54 -7
View File
@@ -439,16 +439,14 @@ d_truncated_fancy_run_list(Vec2F32 p, D_FancyRunList *list, F32 max_x, F_Run tra
{
ProfBeginFunction();
// rjf: grab total advance
F32 run_list_total_advance = list->dim.x;
//- rjf: total advance > max? -> enable trailer
B32 trailer_enabled = (list->dim.x >= max_x && trailer_run.dim.x < max_x);
// rjf: total advance > max? -> enable trailer
B32 trailer_enabled = (run_list_total_advance >= max_x && trailer_run.dim.x < max_x);
// rjf: draw runs
//- rjf: draw runs
F32 advance = 0;
B32 trailer_found = 0;
Vec4F32 last_color = {0};
U64 byte_off = 0;
for(D_FancyRunNode *n = list->first; n != 0; n = n->next)
{
D_FancyRun *fr = &n->v;
@@ -479,6 +477,7 @@ d_truncated_fancy_run_list(Vec2F32 p, D_FancyRunList *list, F32 max_x, F_Run tra
if(!r_handle_match(texture, r_handle_zero()))
{
d_img(dst, src, texture, fr->color, 0, 0, 0);
//d_rect(dst, v4f32(1, 0, 0, 1), 0, 1.f, 0.f);
}
advance += piece->advance;
}
@@ -501,7 +500,7 @@ d_truncated_fancy_run_list(Vec2F32 p, D_FancyRunList *list, F32 max_x, F_Run tra
}
end_draw:;
// rjf: draw trailer
//- rjf: draw trailer
if(trailer_found)
{
F_Piece *piece_first = trailer_run.pieces.v;
@@ -531,6 +530,54 @@ d_truncated_fancy_run_list(Vec2F32 p, D_FancyRunList *list, F32 max_x, F_Run tra
ProfEnd();
}
internal void
d_truncated_fancy_run_fuzzy_matches(Vec2F32 p, D_FancyRunList *list, F32 max_x, FuzzyMatchRangeList *ranges, Vec4F32 color)
{
for(FuzzyMatchRangeNode *match_n = ranges->first; match_n != 0; match_n = match_n->next)
{
Rng1U64 byte_range = match_n->range;
Rng1F32 pixel_range = {0};
{
pixel_range.min = 100000;
pixel_range.max = 0;
}
F32 last_piece_end_pad = 0;
U64 byte_off = 0;
F32 advance = 0;
F32 ascent = 0;
F32 descent = 0;
for(D_FancyRunNode *fr_n = list->first; fr_n != 0; fr_n = fr_n->next)
{
D_FancyRun *fr = &fr_n->v;
F_Run *run = &fr->run;
ascent = run->ascent;
descent = run->descent;
for(U64 piece_idx = 0; piece_idx < run->pieces.count; piece_idx += 1)
{
F_Piece *piece = &run->pieces.v[piece_idx];
if(contains_1u64(byte_range, byte_off))
{
F32 pre_advance = advance+piece->offset.x;
F32 post_advance = advance+piece->advance;
last_piece_end_pad = ((F32)piece->offset.x+(F32)dim_2s16(piece->subrect).x) - piece->advance;
pixel_range.min = Min(pre_advance, pixel_range.min);
pixel_range.max = Max(post_advance, pixel_range.max);
}
byte_off += piece->decode_size;
advance += piece->advance;
}
}
if(pixel_range.min < pixel_range.max)
{
Rng2F32 rect = r2f32p(p.x + pixel_range.min, p.y - descent - ascent,
p.x + pixel_range.max + last_piece_end_pad/2, p.y - descent - ascent + list->dim.y);
rect.x0 = Min(rect.x0, p.x+max_x);
rect.x1 = Min(rect.x1, p.x+max_x);
d_rect(rect, color, (descent+ascent)/4.f, 0, 1.f);
}
}
}
internal void
d_text_run(Vec2F32 p, Vec4F32 color, F_Run run)
{
+1
View File
@@ -183,6 +183,7 @@ internal void d_sub_bucket(D_Bucket *bucket);
//- rjf: text
internal void d_truncated_fancy_run_list(Vec2F32 p, D_FancyRunList *list, F32 max_x, F_Run trailer_run);
internal void d_truncated_fancy_run_fuzzy_matches(Vec2F32 p, D_FancyRunList *list, F32 max_x, FuzzyMatchRangeList *ranges, Vec4F32 color);
internal void d_text_run(Vec2F32 p, Vec4F32 color, F_Run run);
internal void d_truncated_text_run(Vec2F32 p, Vec4F32 color, F32 max_x, F_Run text_run, F_Run trailer_run);
internal void d_text(F_Tag font, F32 size, Vec2F32 p, Vec4F32 color, String8 string);
+5 -2
View File
@@ -39,16 +39,19 @@ EVAL_ExprKindTable:
{ Ternary 3 "? " }
{ LeafBytecode 0 "bytecode" }
{ LeafBytecode 0 "bytecode" }
{ LeafMember 0 "member" }
{ LeafU64 0 "U64" }
{ LeafF64 0 "F64" }
{ LeafF32 0 "F32" }
{ TypeIdent 0 "type_ident" }
{ TypeIdent 0 "type_ident" }
{ Ptr 1 "ptr" }
{ Array 2 "array" }
{ Func 1 "function" }
{ Define 2 "=" }
{ LeafIdent 0 "leaf_ident" }
}
@table_gen
+79 -52
View File
@@ -1,49 +1,12 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
////////////////////////////////
//~ allen: Eval Errors
internal void
eval_error(Arena *arena, EVAL_ErrorList *list, EVAL_ErrorKind kind, void *location, String8 text){
EVAL_Error *error = push_array_no_zero(arena, EVAL_Error, 1);
SLLQueuePush(list->first, list->last, error);
list->count += 1;
list->max_kind = Max(kind, list->max_kind);
error->kind = kind;
error->location = location;
error->text = text;
}
internal void
eval_errorf(Arena *arena, EVAL_ErrorList *list, EVAL_ErrorKind kind, void *location, char *fmt, ...){
va_list args;
va_start(args, fmt);
String8 text = push_str8fv(arena, fmt, args);
va_end(args);
eval_error(arena, list, kind, location, text);
}
internal void
eval_error_list_concat_in_place(EVAL_ErrorList *dst, EVAL_ErrorList *to_push){
if (dst->last != 0){
if (to_push->last != 0){
dst->last->next = to_push->first;
dst->last = to_push->last;
dst->count += to_push->count;
}
}
else{
*dst = *to_push;
}
MemoryZeroStruct(to_push);
}
////////////////////////////////
//~ allen: EVAL Bytecode Helpers
internal String8
eval_bytecode_from_oplist(Arena *arena, EVAL_OpList *list){
ProfBeginFunction();
// allocate output
U64 size = list->encoded_size;
U8 *str = push_array_no_zero(arena, U8, size);
@@ -94,6 +57,7 @@ eval_bytecode_from_oplist(Arena *arena, EVAL_OpList *list){
String8 result = {0};
result.size = size;
result.str = str;
ProfEnd();
return(result);
}
@@ -282,6 +246,16 @@ eval_expr_leaf_member(Arena *arena, void *location, String8 name){
return(result);
}
internal EVAL_Expr*
eval_expr_leaf_ident(Arena *arena, void *location, String8 name)
{
EVAL_Expr *result = push_array(arena, EVAL_Expr, 1);
result->location = location;
result->kind = EVAL_ExprKind_LeafIdent;
result->name = name;
return(result);
}
internal EVAL_Expr*
eval_expr_leaf_bytecode(Arena *arena, void *location, TG_Key type_key, String8 bytecode, EVAL_EvalMode mode){
EVAL_Expr *result = push_array(arena, EVAL_Expr, 1);
@@ -715,6 +689,31 @@ eval_irtree_resolve_to_value(Arena *arena, TG_Graph *graph, RADDBG_Parsed *rdbg,
////////////////////////////////
//~ allen: EVAL Compiler Phases
internal void
eval_push_leaf_ident_exprs_from_expr__in_place(Arena *arena, EVAL_String2ExprMap *map, EVAL_Expr *expr, EVAL_ErrorList *eout)
{
switch(expr->kind)
{
default:
{
U64 children_count = eval_expr_kind_child_counts[expr->kind];
for(U64 idx = 0; idx < children_count; idx += 1)
{
eval_push_leaf_ident_exprs_from_expr__in_place(arena, map, expr->children[idx], eout);
}
}break;
case EVAL_ExprKind_Define:
{
EVAL_Expr *exprl = expr->children[0];
EVAL_Expr *exprr = expr->children[1];
if(exprl->kind == EVAL_ExprKind_LeafIdent)
{
eval_string2expr_map_insert(arena, map, exprl->name, exprr);
}
}break;
}
}
internal TG_Key
eval_type_from_type_expr(Arena *arena, TG_Graph *graph, RADDBG_Parsed *rdbg, EVAL_Expr *expr, EVAL_ErrorList *eout){
TG_Key result = zero_struct;
@@ -759,8 +758,9 @@ eval_type_from_type_expr(Arena *arena, TG_Graph *graph, RADDBG_Parsed *rdbg, EVA
}
internal EVAL_IRTreeAndType
eval_irtree_and_type_from_expr(Arena *arena, TG_Graph *graph, RADDBG_Parsed *rdbg, EVAL_Expr *expr, EVAL_ErrorList *eout)
eval_irtree_and_type_from_expr(Arena *arena, TG_Graph *graph, RADDBG_Parsed *rdbg, EVAL_String2ExprMap *leaf_ident_expr_map, EVAL_Expr *expr, EVAL_ErrorList *eout)
{
ProfBeginFunction();
EVAL_IRTreeAndType result = {0};
result.tree = &eval_irtree_nil;
@@ -777,8 +777,8 @@ eval_irtree_and_type_from_expr(Arena *arena, TG_Graph *graph, RADDBG_Parsed *rdb
EVAL_Expr *exprl = expr->children[0];
EVAL_Expr *exprr = expr->children[1];
EVAL_IRTreeAndType l = eval_irtree_and_type_from_expr(arena, graph, rdbg, exprl, eout);
EVAL_IRTreeAndType r = eval_irtree_and_type_from_expr(arena, graph, rdbg, exprr, eout);
EVAL_IRTreeAndType l = eval_irtree_and_type_from_expr(arena, graph, rdbg, leaf_ident_expr_map, exprl, eout);
EVAL_IRTreeAndType r = eval_irtree_and_type_from_expr(arena, graph, rdbg, leaf_ident_expr_map, exprr, eout);
if (l.tree->op != 0 && r.tree->op != 0){
TG_Key l_restype = tg_unwrapped_from_graph_raddbg_key(graph, rdbg, l.type_key);
@@ -857,7 +857,7 @@ eval_irtree_and_type_from_expr(Arena *arena, TG_Graph *graph, RADDBG_Parsed *rdb
EVAL_Expr *exprl = expr->children[0];
EVAL_Expr *exprr = expr->children[1];
EVAL_IRTreeAndType l = eval_irtree_and_type_from_expr(arena, graph, rdbg, exprl, eout);
EVAL_IRTreeAndType l = eval_irtree_and_type_from_expr(arena, graph, rdbg, leaf_ident_expr_map, exprl, eout);
if (l.tree->op != 0 && !tg_key_match(tg_key_zero(), l.type_key)){
TG_Key l_restype = tg_unwrapped_from_graph_raddbg_key(graph, rdbg, l.type_key);
@@ -975,7 +975,7 @@ eval_irtree_and_type_from_expr(Arena *arena, TG_Graph *graph, RADDBG_Parsed *rdb
{
EVAL_Expr *exprc = expr->children[0];
EVAL_IRTreeAndType c = eval_irtree_and_type_from_expr(arena, graph, rdbg, exprc, eout);
EVAL_IRTreeAndType c = eval_irtree_and_type_from_expr(arena, graph, rdbg, leaf_ident_expr_map, exprc, eout);
if (c.tree->op != 0){
TG_Key c_restype = tg_unwrapped_from_graph_raddbg_key(graph, rdbg, c.type_key);
@@ -1032,7 +1032,7 @@ eval_irtree_and_type_from_expr(Arena *arena, TG_Graph *graph, RADDBG_Parsed *rdb
case EVAL_ExprKind_Address:
{
EVAL_Expr *exprc = expr->children[0];
EVAL_IRTreeAndType c = eval_irtree_and_type_from_expr(arena, graph, rdbg, exprc, eout);
EVAL_IRTreeAndType c = eval_irtree_and_type_from_expr(arena, graph, rdbg, leaf_ident_expr_map, exprc, eout);
if(c.tree->op != 0 && !tg_key_match(c.type_key, tg_key_zero()))
{
TG_Key c_restype = tg_unwrapped_from_graph_raddbg_key(graph, rdbg, c.type_key);
@@ -1066,7 +1066,7 @@ eval_irtree_and_type_from_expr(Arena *arena, TG_Graph *graph, RADDBG_Parsed *rdb
TG_Key cast_type_key = eval_type_from_type_expr(arena, graph, rdbg, exprl, eout);
TG_Kind cast_type_kind = tg_kind_from_key(cast_type_key);
EVAL_IRTreeAndType c = eval_irtree_and_type_from_expr(arena, graph, rdbg, exprr, eout);
EVAL_IRTreeAndType c = eval_irtree_and_type_from_expr(arena, graph, rdbg, leaf_ident_expr_map, exprr, eout);
if(cast_type_kind != TG_Kind_Null && c.tree->op != 0)
{
@@ -1132,7 +1132,7 @@ eval_irtree_and_type_from_expr(Arena *arena, TG_Graph *graph, RADDBG_Parsed *rdb
// size of value expression
default:
{
EVAL_IRTreeAndType c = eval_irtree_and_type_from_expr(arena, graph, rdbg, exprc, eout);
EVAL_IRTreeAndType c = eval_irtree_and_type_from_expr(arena, graph, rdbg, leaf_ident_expr_map, exprc, eout);
type_key = c.type_key;
}break;
}
@@ -1160,7 +1160,7 @@ eval_irtree_and_type_from_expr(Arena *arena, TG_Graph *graph, RADDBG_Parsed *rdb
{
EVAL_Expr *exprc = expr->children[0];
EVAL_IRTreeAndType c = eval_irtree_and_type_from_expr(arena, graph, rdbg, exprc, eout);
EVAL_IRTreeAndType c = eval_irtree_and_type_from_expr(arena, graph, rdbg, leaf_ident_expr_map, exprc, eout);
if (c.tree->op != 0){
TG_Key c_restype = tg_unwrapped_from_graph_raddbg_key(graph, rdbg, c.type_key);
TG_Key p_type = eval_type_promote(graph, rdbg, c_restype);
@@ -1214,8 +1214,8 @@ eval_irtree_and_type_from_expr(Arena *arena, TG_Graph *graph, RADDBG_Parsed *rdb
EVAL_Expr *exprl = expr->children[0];
EVAL_Expr *exprr = expr->children[1];
EVAL_IRTreeAndType l = eval_irtree_and_type_from_expr(arena, graph, rdbg, exprl, eout);
EVAL_IRTreeAndType r = eval_irtree_and_type_from_expr(arena, graph, rdbg, exprr, eout);
EVAL_IRTreeAndType l = eval_irtree_and_type_from_expr(arena, graph, rdbg, leaf_ident_expr_map, exprl, eout);
EVAL_IRTreeAndType r = eval_irtree_and_type_from_expr(arena, graph, rdbg, leaf_ident_expr_map, exprr, eout);
if (l.tree->op != 0 && r.tree->op != 0){
TG_Key l_restype = tg_unwrapped_from_graph_raddbg_key(graph, rdbg, l.type_key);
@@ -1404,9 +1404,9 @@ eval_irtree_and_type_from_expr(Arena *arena, TG_Graph *graph, RADDBG_Parsed *rdb
EVAL_Expr *exprl = expr->children[1];
EVAL_Expr *exprr = expr->children[2];
EVAL_IRTreeAndType c = eval_irtree_and_type_from_expr(arena, graph, rdbg, exprc, eout);
EVAL_IRTreeAndType l = eval_irtree_and_type_from_expr(arena, graph, rdbg, exprl, eout);
EVAL_IRTreeAndType r = eval_irtree_and_type_from_expr(arena, graph, rdbg, exprr, eout);
EVAL_IRTreeAndType c = eval_irtree_and_type_from_expr(arena, graph, rdbg, leaf_ident_expr_map, exprc, eout);
EVAL_IRTreeAndType l = eval_irtree_and_type_from_expr(arena, graph, rdbg, leaf_ident_expr_map, exprl, eout);
EVAL_IRTreeAndType r = eval_irtree_and_type_from_expr(arena, graph, rdbg, leaf_ident_expr_map, exprr, eout);
if (l.tree->op != 0 && r.tree->op != 0 && c.tree->op != 0){
@@ -1533,13 +1533,39 @@ eval_irtree_and_type_from_expr(Arena *arena, TG_Graph *graph, RADDBG_Parsed *rdb
{
eval_errorf(arena, eout, EVAL_ErrorKind_MalformedInput, expr->location, "Type expression not expected.");
}break;
case EVAL_ExprKind_Define:
{
if(expr->children[0]->kind != EVAL_ExprKind_LeafIdent)
{
eval_errorf(arena, eout, EVAL_ErrorKind_MalformedInput, expr->location, "Left side of assignment must be an identifier.");
}
result = eval_irtree_and_type_from_expr(arena, graph, rdbg, leaf_ident_expr_map, expr->children[1], eout);
}break;
case EVAL_ExprKind_LeafIdent:
{
String8 name = expr->name;
EVAL_Expr *leaf_ident_expr = eval_expr_from_string(leaf_ident_expr_map, name);
if(leaf_ident_expr == &eval_expr_nil)
{
eval_errorf(arena, eout, EVAL_ErrorKind_ResolutionFailure, expr->location, "\"%S\" could not be found.", name);
}
else
{
eval_string2expr_map_inc_poison(leaf_ident_expr_map, name);
result = eval_irtree_and_type_from_expr(arena, graph, rdbg, leaf_ident_expr_map, leaf_ident_expr, eout);
eval_string2expr_map_dec_poison(leaf_ident_expr_map, name);
}
}break;
}
ProfEnd();
return(result);
}
internal void
eval_oplist_from_irtree(Arena *arena, EVAL_IRTree *tree, EVAL_OpList *out){
ProfBeginFunction();
U32 op = tree->op;
switch (op){
case RADDBG_EvalOp_Stop:
@@ -1604,4 +1630,5 @@ eval_oplist_from_irtree(Arena *arena, EVAL_IRTree *tree, EVAL_OpList *out){
}
}break;
}
ProfEnd();
}
+3 -124
View File
@@ -4,129 +4,6 @@
#ifndef EVAL_COMPILER_H
#define EVAL_COMPILER_H
////////////////////////////////
//~ allen: EVAL Error Types
typedef enum EVAL_ErrorKind
{
EVAL_ErrorKind_Null,
EVAL_ErrorKind_MalformedInput,
EVAL_ErrorKind_MissingInfo,
EVAL_ErrorKind_ResolutionFailure,
EVAL_ErrorKind_COUNT
}
EVAL_ErrorKind;
typedef struct EVAL_Error EVAL_Error;
struct EVAL_Error{
EVAL_Error *next;
EVAL_ErrorKind kind;
void *location;
String8 text;
};
typedef struct EVAL_ErrorList EVAL_ErrorList;
struct EVAL_ErrorList{
EVAL_Error *first;
EVAL_Error *last;
EVAL_ErrorKind max_kind;
U64 count;
};
////////////////////////////////
//~ allen: EVAL Op List Types
enum{
EVAL_IRExtKind_Bytecode = RADDBG_EvalOp_COUNT,
EVAL_IRExtKind_COUNT
};
typedef struct EVAL_Op EVAL_Op;
struct EVAL_Op{
EVAL_Op *next;
RADDBG_EvalOp opcode;
union{
U64 p;
String8 bytecode;
};
};
typedef struct EVAL_OpList EVAL_OpList;
struct EVAL_OpList{
EVAL_Op *first_op;
EVAL_Op *last_op;
U32 op_count;
U32 encoded_size;
};
////////////////////////////////
//- allen: EVAL Expression Types
#include "eval/generated/eval.meta.h"
typedef enum EVAL_EvalMode{
EVAL_EvalMode_NULL,
EVAL_EvalMode_Value,
EVAL_EvalMode_Addr,
EVAL_EvalMode_Reg
}
EVAL_EvalMode;
typedef struct EVAL_Expr EVAL_Expr;
struct EVAL_Expr{
EVAL_ExprKind kind;
void *location;
union{
EVAL_Expr *children[3];
U32 u32;
U64 u64;
F32 f32;
F64 f64;
struct{
EVAL_Expr *child;
U64 u64;
} child_and_constant;
String8 name;
struct{
TG_Key type_key;
String8 bytecode;
EVAL_EvalMode mode;
};
};
};
global read_only EVAL_Expr eval_expr_nil = {0};
////////////////////////////////
//~ allen: EVAL Compiler Types
typedef struct EVAL_IRTree EVAL_IRTree;
struct EVAL_IRTree{
RADDBG_EvalOp op;
EVAL_IRTree *children[3];
union{
U64 p;
String8 bytecode;
};
};
global read_only EVAL_IRTree eval_irtree_nil = {0};
typedef struct EVAL_IRTreeAndType EVAL_IRTreeAndType;
struct EVAL_IRTreeAndType{
EVAL_IRTree *tree;
TG_Key type_key;
EVAL_EvalMode mode;
};
////////////////////////////////
//~ allen: Eval Error Helpers
internal void eval_error(Arena *arena, EVAL_ErrorList *list, EVAL_ErrorKind kind, void *location, String8 text);
internal void eval_errorf(Arena *arena, EVAL_ErrorList *list, EVAL_ErrorKind kind, void *location, char *fmt, ...);
internal void eval_error_list_concat_in_place(EVAL_ErrorList *dst, EVAL_ErrorList *to_push);
////////////////////////////////
//~ allen: EVAL Bytecode Helpers
@@ -155,6 +32,7 @@ internal EVAL_Expr* eval_expr_f64(Arena *arena, void *location, F64 f64);
internal EVAL_Expr* eval_expr_f32(Arena *arena, void *location, F32 f32);
internal EVAL_Expr* eval_expr_child_and_u64(Arena *arena, EVAL_ExprKind kind, void *location, EVAL_Expr *child, U64 u64);
internal EVAL_Expr* eval_expr_leaf_member(Arena *arena, void *location, String8 name);
internal EVAL_Expr* eval_expr_leaf_ident(Arena *arena, void *location, String8 name);
internal EVAL_Expr* eval_expr_leaf_bytecode(Arena *arena, void *location, TG_Key type_key, String8 bytecode, EVAL_EvalMode mode);
internal EVAL_Expr* eval_expr_leaf_op_list(Arena *arena, void *location, TG_Key type_key, EVAL_OpList *ops, EVAL_EvalMode mode);
internal EVAL_Expr* eval_expr_leaf_type(Arena *arena, void *location, TG_Key type_key);
@@ -196,8 +74,9 @@ internal EVAL_IRTree* eval_irtree_resolve_to_value(Arena *arena, TG_Graph *graph
////////////////////////////////
//~ allen: EVAL Compiler Phases
internal void eval_push_leaf_ident_exprs_from_expr__in_place(Arena *arena, EVAL_String2ExprMap *map, EVAL_Expr *expr, EVAL_ErrorList *eout);
internal TG_Key eval_type_from_type_expr(Arena *arena, TG_Graph *graph, RADDBG_Parsed *rdbg, EVAL_Expr *expr, EVAL_ErrorList *eout);
internal EVAL_IRTreeAndType eval_irtree_and_type_from_expr(Arena *arena, TG_Graph *graph, RADDBG_Parsed *rdbg, EVAL_Expr *expr, EVAL_ErrorList *eout);
internal EVAL_IRTreeAndType eval_irtree_and_type_from_expr(Arena *arena, TG_Graph *graph, RADDBG_Parsed *rdbg, EVAL_String2ExprMap *leaf_ident_expr_map, EVAL_Expr *expr, EVAL_ErrorList *eout);
internal void eval_oplist_from_irtree(Arena *arena, EVAL_IRTree *tree, EVAL_OpList *out);
#endif //EVAL_COMPILER_H
+213
View File
@@ -0,0 +1,213 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
////////////////////////////////
//~ rjf: Basic Functions
internal U64
eval_hash_from_string(String8 string)
{
U64 result = 5381;
for(U64 i = 0; i < string.size; i += 1)
{
result = ((result << 5) + result) + string.str[i];
}
return result;
}
////////////////////////////////
//~ rjf: Error List Building Functions
internal void
eval_error(Arena *arena, EVAL_ErrorList *list, EVAL_ErrorKind kind, void *location, String8 text){
EVAL_Error *error = push_array_no_zero(arena, EVAL_Error, 1);
SLLQueuePush(list->first, list->last, error);
list->count += 1;
list->max_kind = Max(kind, list->max_kind);
error->kind = kind;
error->location = location;
error->text = text;
}
internal void
eval_errorf(Arena *arena, EVAL_ErrorList *list, EVAL_ErrorKind kind, void *location, char *fmt, ...){
va_list args;
va_start(args, fmt);
String8 text = push_str8fv(arena, fmt, args);
va_end(args);
eval_error(arena, list, kind, location, text);
}
internal void
eval_error_list_concat_in_place(EVAL_ErrorList *dst, EVAL_ErrorList *to_push){
if (dst->last != 0){
if (to_push->last != 0){
dst->last->next = to_push->first;
dst->last = to_push->last;
dst->count += to_push->count;
}
}
else{
*dst = *to_push;
}
MemoryZeroStruct(to_push);
}
////////////////////////////////
//~ rjf: Map Functions
//- rjf: string -> num
internal EVAL_String2NumMap
eval_string2num_map_make(Arena *arena, U64 slot_count)
{
EVAL_String2NumMap map = {0};
map.slots_count = slot_count;
map.slots = push_array(arena, EVAL_String2NumMapSlot, map.slots_count);
return map;
}
internal void
eval_string2num_map_insert(Arena *arena, EVAL_String2NumMap *map, String8 string, U64 num)
{
U64 hash = eval_hash_from_string(string);
U64 slot_idx = hash%map->slots_count;
EVAL_String2NumMapNode *existing_node = 0;
for(EVAL_String2NumMapNode *node = map->slots[slot_idx].first; node != 0; node = node->hash_next)
{
if(str8_match(node->string, string, 0) && node->num == num)
{
existing_node = node;
break;
}
}
if(existing_node == 0)
{
EVAL_String2NumMapNode *node = push_array(arena, EVAL_String2NumMapNode, 1);
SLLQueuePush_N(map->slots[slot_idx].first, map->slots[slot_idx].last, node, hash_next);
SLLQueuePush_N(map->first, map->last, node, order_next);
node->string = push_str8_copy(arena, string);
node->num = num;
}
}
internal U64
eval_num_from_string(EVAL_String2NumMap *map, String8 string)
{
U64 num = 0;
if(map->slots_count != 0)
{
U64 hash = eval_hash_from_string(string);
U64 slot_idx = hash%map->slots_count;
EVAL_String2NumMapNode *existing_node = 0;
for(EVAL_String2NumMapNode *node = map->slots[slot_idx].first; node != 0; node = node->hash_next)
{
if(str8_match(node->string, string, 0))
{
existing_node = node;
break;
}
}
if(existing_node != 0)
{
num = existing_node->num;
}
}
return num;
}
//- rjf: string -> expr
internal EVAL_String2ExprMap
eval_string2expr_map_make(Arena *arena, U64 slot_count)
{
EVAL_String2ExprMap map = {0};
map.slots_count = slot_count;
map.slots = push_array(arena, EVAL_String2ExprMapSlot, map.slots_count);
return map;
}
internal void
eval_string2expr_map_insert(Arena *arena, EVAL_String2ExprMap *map, String8 string, EVAL_Expr *expr)
{
U64 hash = eval_hash_from_string(string);
U64 slot_idx = hash%map->slots_count;
EVAL_String2ExprMapNode *existing_node = 0;
for(EVAL_String2ExprMapNode *node = map->slots[slot_idx].first;
node != 0;
node = node->hash_next)
{
if(str8_match(node->string, string, 0))
{
existing_node = node;
break;
}
}
if(existing_node == 0)
{
EVAL_String2ExprMapNode *node = push_array(arena, EVAL_String2ExprMapNode, 1);
SLLQueuePush_N(map->slots[slot_idx].first, map->slots[slot_idx].last, node, hash_next);
node->string = push_str8_copy(arena, string);
existing_node = node;
}
existing_node->expr = expr;
}
internal void
eval_string2expr_map_inc_poison(EVAL_String2ExprMap *map, String8 string)
{
U64 hash = eval_hash_from_string(string);
U64 slot_idx = hash%map->slots_count;
for(EVAL_String2ExprMapNode *node = map->slots[slot_idx].first;
node != 0;
node = node->hash_next)
{
if(str8_match(node->string, string, 0))
{
node->poison_count += 1;
break;
}
}
}
internal void
eval_string2expr_map_dec_poison(EVAL_String2ExprMap *map, String8 string)
{
U64 hash = eval_hash_from_string(string);
U64 slot_idx = hash%map->slots_count;
for(EVAL_String2ExprMapNode *node = map->slots[slot_idx].first;
node != 0;
node = node->hash_next)
{
if(str8_match(node->string, string, 0) && node->poison_count > 0)
{
node->poison_count -= 1;
break;
}
}
}
internal EVAL_Expr *
eval_expr_from_string(EVAL_String2ExprMap *map, String8 string)
{
EVAL_Expr *expr = &eval_expr_nil;
if(map->slots_count != 0)
{
U64 hash = eval_hash_from_string(string);
U64 slot_idx = hash%map->slots_count;
EVAL_String2ExprMapNode *existing_node = 0;
for(EVAL_String2ExprMapNode *node = map->slots[slot_idx].first; node != 0; node = node->hash_next)
{
if(str8_match(node->string, string, 0) && node->poison_count == 0)
{
existing_node = node;
break;
}
}
if(existing_node != 0)
{
expr = existing_node->expr;
}
}
return expr;
}
+220
View File
@@ -0,0 +1,220 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#ifndef EVAL_CORE_H
#define EVAL_CORE_H
////////////////////////////////
//~ rjf: Errors
typedef enum EVAL_ErrorKind
{
EVAL_ErrorKind_Null,
EVAL_ErrorKind_MalformedInput,
EVAL_ErrorKind_MissingInfo,
EVAL_ErrorKind_ResolutionFailure,
EVAL_ErrorKind_COUNT
}
EVAL_ErrorKind;
typedef struct EVAL_Error EVAL_Error;
struct EVAL_Error
{
EVAL_Error *next;
EVAL_ErrorKind kind;
void *location;
String8 text;
};
typedef struct EVAL_ErrorList EVAL_ErrorList;
struct EVAL_ErrorList
{
EVAL_Error *first;
EVAL_Error *last;
EVAL_ErrorKind max_kind;
U64 count;
};
////////////////////////////////
//~ rjf: Operation Types
enum
{
EVAL_IRExtKind_Bytecode = RADDBG_EvalOp_COUNT,
EVAL_IRExtKind_COUNT
};
typedef struct EVAL_Op EVAL_Op;
struct EVAL_Op
{
EVAL_Op *next;
RADDBG_EvalOp opcode;
union
{
U64 p;
String8 bytecode;
};
};
typedef struct EVAL_OpList EVAL_OpList;
struct EVAL_OpList
{
EVAL_Op *first_op;
EVAL_Op *last_op;
U32 op_count;
U32 encoded_size;
};
////////////////////////////////
//~ rjf: Generated Code
#include "eval/generated/eval.meta.h"
////////////////////////////////
//~ rjf: Expression Tree Types
typedef enum EVAL_EvalMode
{
EVAL_EvalMode_NULL,
EVAL_EvalMode_Value,
EVAL_EvalMode_Addr,
EVAL_EvalMode_Reg
}
EVAL_EvalMode;
typedef struct EVAL_Expr EVAL_Expr;
struct EVAL_Expr
{
EVAL_ExprKind kind;
void *location;
union
{
EVAL_Expr *children[3];
U32 u32;
U64 u64;
F32 f32;
F64 f64;
struct
{
EVAL_Expr *child;
U64 u64;
} child_and_constant;
String8 name;
struct
{
TG_Key type_key;
String8 bytecode;
EVAL_EvalMode mode;
};
};
};
////////////////////////////////
//~ rjf: IR Tree Types
typedef struct EVAL_IRTree EVAL_IRTree;
struct EVAL_IRTree{
RADDBG_EvalOp op;
EVAL_IRTree *children[3];
union{
U64 p;
String8 bytecode;
};
};
typedef struct EVAL_IRTreeAndType EVAL_IRTreeAndType;
struct EVAL_IRTreeAndType{
EVAL_IRTree *tree;
TG_Key type_key;
EVAL_EvalMode mode;
};
////////////////////////////////
//~ rjf: Map Types
//- rjf: string -> num
typedef struct EVAL_String2NumMapNode EVAL_String2NumMapNode;
struct EVAL_String2NumMapNode
{
EVAL_String2NumMapNode *order_next;
EVAL_String2NumMapNode *hash_next;
String8 string;
U64 num;
};
typedef struct EVAL_String2NumMapSlot EVAL_String2NumMapSlot;
struct EVAL_String2NumMapSlot
{
EVAL_String2NumMapNode *first;
EVAL_String2NumMapNode *last;
};
typedef struct EVAL_String2NumMap EVAL_String2NumMap;
struct EVAL_String2NumMap
{
U64 slots_count;
EVAL_String2NumMapSlot *slots;
EVAL_String2NumMapNode *first;
EVAL_String2NumMapNode *last;
};
//- rjf: string -> expr
typedef struct EVAL_String2ExprMapNode EVAL_String2ExprMapNode;
struct EVAL_String2ExprMapNode
{
EVAL_String2ExprMapNode *hash_next;
String8 string;
EVAL_Expr *expr;
U64 poison_count;
};
typedef struct EVAL_String2ExprMapSlot EVAL_String2ExprMapSlot;
struct EVAL_String2ExprMapSlot
{
EVAL_String2ExprMapNode *first;
EVAL_String2ExprMapNode *last;
};
typedef struct EVAL_String2ExprMap EVAL_String2ExprMap;
struct EVAL_String2ExprMap
{
U64 slots_count;
EVAL_String2ExprMapSlot *slots;
};
////////////////////////////////
//~ rjf: Globals
global read_only EVAL_Expr eval_expr_nil = {0};
global read_only EVAL_IRTree eval_irtree_nil = {0};
////////////////////////////////
//~ rjf: Basic Functions
internal U64 eval_hash_from_string(String8 string);
////////////////////////////////
//~ rjf: Error List Building Functions
internal void eval_error(Arena *arena, EVAL_ErrorList *list, EVAL_ErrorKind kind, void *location, String8 text);
internal void eval_errorf(Arena *arena, EVAL_ErrorList *list, EVAL_ErrorKind kind, void *location, char *fmt, ...);
internal void eval_error_list_concat_in_place(EVAL_ErrorList *dst, EVAL_ErrorList *to_push);
////////////////////////////////
//~ rjf: Map Functions
//- rjf: string -> num
internal EVAL_String2NumMap eval_string2num_map_make(Arena *arena, U64 slot_count);
internal void eval_string2num_map_insert(Arena *arena, EVAL_String2NumMap *map, String8 string, U64 num);
internal U64 eval_num_from_string(EVAL_String2NumMap *map, String8 string);
//- rjf: string -> expr
internal EVAL_String2ExprMap eval_string2expr_map_make(Arena *arena, U64 slot_count);
internal void eval_string2expr_map_insert(Arena *arena, EVAL_String2NumMap *map, String8 string, EVAL_Expr *expr);
internal void eval_string2expr_map_inc_poison(EVAL_String2ExprMap *map, String8 string);
internal void eval_string2expr_map_dec_poison(EVAL_String2ExprMap *map, String8 string);
internal EVAL_Expr *eval_expr_from_string(EVAL_String2ExprMap *map, String8 string);
#endif // EVAL_CORE_H
+7
View File
@@ -0,0 +1,7 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#include "eval/eval_core.c"
#include "eval/eval_compiler.c"
#include "eval/eval_machine.c"
#include "eval/eval_parser.c"
+12
View File
@@ -0,0 +1,12 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#ifndef EVAL_INC_H
#define EVAL_INC_H
#include "eval/eval_core.h"
#include "eval/eval_compiler.h"
#include "eval/eval_machine.h"
#include "eval/eval_parser.h"
#endif // EVAL_INC_H
+2
View File
@@ -6,6 +6,7 @@
internal EVAL_Result
eval_interpret(EVAL_Machine *machine, String8 bytecode){
ProfBeginFunction();
EVAL_Result result = {0};
// TODO(allen): We could scan the bytecode and figure out the
@@ -626,5 +627,6 @@ eval_interpret(EVAL_Machine *machine, String8 bytecode){
}
scratch_end(scratch);
ProfEnd();
return(result);
}
+60 -105
View File
@@ -48,84 +48,11 @@ global read_only struct {EVAL_ExprKind kind; String8 string; S64 precedence;} ev
{ EVAL_ExprKind_BitOr, str8_lit_comp("|"), 10 },
{ EVAL_ExprKind_LogAnd, str8_lit_comp("&&"), 11 },
{ EVAL_ExprKind_LogOr, str8_lit_comp("||"), 12 },
{ EVAL_ExprKind_Define, str8_lit_comp("="), 13 },
};
global read_only S64 eval_g_max_precedence = 15;
////////////////////////////////
//~ rjf: Basic Functions
internal U64
eval_hash_from_string(String8 string)
{
U64 result = 5381;
for(U64 i = 0; i < string.size; i += 1)
{
result = ((result << 5) + result) + string.str[i];
}
return result;
}
////////////////////////////////
//~ rjf: Map Functions
internal EVAL_String2NumMap
eval_string2num_map_make(Arena *arena, U64 slot_count)
{
EVAL_String2NumMap map = {0};
map.slots_count = slot_count;
map.slots = push_array(arena, EVAL_String2NumMapSlot, map.slots_count);
return map;
}
internal void
eval_string2num_map_insert(Arena *arena, EVAL_String2NumMap *map, String8 string, U64 num)
{
U64 hash = eval_hash_from_string(string);
U64 slot_idx = hash%map->slots_count;
EVAL_String2NumMapNode *existing_node = 0;
for(EVAL_String2NumMapNode *node = map->slots[slot_idx].first; node != 0; node = node->next)
{
if(str8_match(node->string, string, 0) && node->num == num)
{
existing_node = node;
break;
}
}
if(existing_node == 0)
{
EVAL_String2NumMapNode *node = push_array(arena, EVAL_String2NumMapNode, 1);
SLLQueuePush(map->slots[slot_idx].first, map->slots[slot_idx].last, node);
node->string = push_str8_copy(arena, string);
node->num = num;
}
}
internal U64
eval_num_from_string(EVAL_String2NumMap *map, String8 string)
{
U64 num = 0;
if(map->slots_count != 0)
{
U64 hash = eval_hash_from_string(string);
U64 slot_idx = hash%map->slots_count;
EVAL_String2NumMapNode *existing_node = 0;
for(EVAL_String2NumMapNode *node = map->slots[slot_idx].first; node != 0; node = node->next)
{
if(str8_match(node->string, string, 0))
{
existing_node = node;
break;
}
}
if(existing_node != 0)
{
num = existing_node->num;
}
}
return num;
}
////////////////////////////////
//~ rjf: Map Building Fast Paths
@@ -224,7 +151,7 @@ eval_push_member_map_from_raddbg_voff(Arena *arena, RADDBG_Parsed *rdbg, U64 vof
if(tightest_scope != 0 && rdbg->procedures != 0)
{
U32 proc_idx = tightest_scope->proc_idx;
if(0 < proc_idx && proc_idx < rdbg->procedure_count)
if(0 < proc_idx && proc_idx < rdbg->procedures_count)
{
procedure = &rdbg->procedures[proc_idx];
}
@@ -235,7 +162,7 @@ eval_push_member_map_from_raddbg_voff(Arena *arena, RADDBG_Parsed *rdbg, U64 vof
if(procedure != 0 && rdbg->udts != 0 && procedure->link_flags & RADDBG_LinkFlag_TypeScoped)
{
U32 udt_idx = procedure->container_idx;
if(0 < udt_idx && udt_idx < rdbg->udt_count)
if(0 < udt_idx && udt_idx < rdbg->udts_count)
{
udt = &rdbg->udts[udt_idx];
}
@@ -253,7 +180,7 @@ eval_push_member_map_from_raddbg_voff(Arena *arena, RADDBG_Parsed *rdbg, U64 vof
member_idx < udt->member_first+udt->member_count;
member_idx += 1)
{
if(member_idx < 1 || rdbg->member_count <= member_idx)
if(member_idx < 1 || rdbg->members_count <= member_idx)
{
break;
}
@@ -315,12 +242,14 @@ eval_token_array_from_chunk_list(Arena *arena, EVAL_TokenChunkList *list)
internal EVAL_TokenArray
eval_token_array_from_text(Arena *arena, String8 text)
{
ProfBeginFunction();
Temp scratch = scratch_begin(&arena, 1);
//- rjf: lex loop
EVAL_TokenChunkList tokens = {0};
U64 active_token_start_idx = 0;
EVAL_TokenKind active_token_kind = EVAL_TokenKind_Null;
B32 active_token_kind_started_with_tick = 0;
B32 escaped = 0;
for(U64 idx = 0, advance = 0; idx <= text.size; idx += advance)
{
@@ -335,10 +264,11 @@ eval_token_array_from_text(Arena *arena, String8 text)
//- rjf: no active token -> seek token starter
default:
{
if(char_is_alpha(byte) || byte == '_')
if(char_is_alpha(byte) || byte == '_' || byte == '`' || byte == '$')
{
active_token_kind = EVAL_TokenKind_Identifier;
active_token_start_idx = idx;
active_token_kind_started_with_tick = (byte == '`');
}
else if(char_is_digit(byte, 10) || (byte == '.' && char_is_digit(byte_next, 10)))
{
@@ -370,13 +300,47 @@ eval_token_array_from_text(Arena *arena, String8 text)
//- rjf: active tokens -> seek enders
case EVAL_TokenKind_Identifier:
{
if(byte == ':' && byte_next == ':' && (char_is_alpha(byte_next2) || byte_next2 == '_'))
if(byte == ':' && byte_next == ':' && (char_is_alpha(byte_next2) || byte_next2 == '_' || byte_next2 == '<'))
{
// NOTE(rjf): encountering C++-style namespaces - skip over scope resolution symbol
// & keep going.
advance = 2;
}
else if(!char_is_alpha(byte) && !char_is_digit(byte, 10) && byte != '_')
else if((byte == '\'' || byte == '`') && active_token_kind_started_with_tick)
{
// NOTE(rjf): encountering ` -> ' or ` -> ` style identifier escapes
active_token_kind_started_with_tick = 0;
advance = 1;
}
else if(byte == '<')
{
// NOTE(rjf): encountering C++-style templates - try to find ender. if no ender found,
// assume this is an operator & just consume the identifier part.
S64 nest = 1;
for(U64 idx2 = idx+1; idx2 <= text.size; idx2 += 1)
{
if(idx2 < text.size && text.str[idx2] == '<')
{
nest += 1;
}
else if(idx2 < text.size && text.str[idx2] == '>')
{
nest -= 1;
if(nest == 0)
{
advance = (idx2+1-idx);
break;
}
}
else if(idx2 == text.size && nest != 0)
{
token_formed = 1;
advance = 0;
break;
}
}
}
else if(!char_is_alpha(byte) && !char_is_digit(byte, 10) && byte != '_' && !active_token_kind_started_with_tick && byte != '@' && byte != '$')
{
advance = 0;
token_formed = 1;
@@ -485,6 +449,7 @@ eval_token_array_from_text(Arena *arena, String8 text)
//- rjf: chunk list -> array & return
EVAL_TokenArray array = eval_token_array_from_chunk_list(arena, &tokens);
scratch_end(scratch);
ProfEnd();
return array;
}
@@ -515,13 +480,9 @@ eval_leaf_type_from_name(RADDBG_Parsed *rdbg, String8 name)
U32 *matches = raddbg_matches_from_map_node(rdbg, node, &match_count);
if(match_count != 0)
{
U32 type_node_idx = matches[0];
if(type_node_idx < rdbg->type_node_count)
{
RADDBG_TypeNode *type_node = &rdbg->type_nodes[type_node_idx];
key = tg_key_ext(tg_kind_from_raddbg_type_kind(type_node->kind), (U64)type_node_idx);
found = 1;
}
RADDBG_TypeNode *type_node = raddbg_element_from_idx(rdbg, type_nodes, matches[0]);
found = type_node->kind != RADDBG_TypeKind_NULL;
key = tg_key_ext(tg_kind_from_raddbg_type_kind(type_node->kind), (U64)matches[0]);
}
}
}
@@ -666,6 +627,7 @@ eval_parse_type_from_text_tokens(Arena *arena, EVAL_ParseCtx *ctx, String8 text,
internal EVAL_ParseResult
eval_parse_expr_from_text_tokens__prec(Arena *arena, EVAL_ParseCtx *ctx, String8 text, EVAL_TokenArray *tokens, S64 max_precedence)
{
ProfBeginFunction();
Temp scratch = scratch_begin(&arena, 1);
EVAL_Token *it = tokens->v;
EVAL_Token *it_opl = tokens->v + tokens->count;
@@ -877,13 +839,13 @@ eval_parse_expr_from_text_tokens__prec(Arena *arena, EVAL_ParseCtx *ctx, String8
if(mapped_identifier == 0)
{
U64 local_num = eval_num_from_string(ctx->locals_map, local_lookup_string);
if(local_num != 0 &&
ctx->rdbg->locals != 0 && (1 <= local_num && local_num <= ctx->rdbg->local_count) &&
ctx->rdbg->type_nodes != 0)
if(local_num != 0)
{
mapped_identifier = 1;
identifier_type_is_possibly_dynamically_overridden = 1;
RADDBG_Local *local_var = &ctx->rdbg->locals[local_num-1];
RADDBG_Local *local_var = raddbg_element_from_idx(ctx->rdbg, locals, local_num-1);
RADDBG_TypeNode *type_node = raddbg_element_from_idx(ctx->rdbg, type_nodes, local_var->type_idx);
type_key = tg_key_ext(tg_kind_from_raddbg_type_kind(type_node->kind), (U64)local_var->type_idx);
// rjf: grab location info
for(U32 loc_block_idx = local_var->location_first;
@@ -927,14 +889,6 @@ eval_parse_expr_from_text_tokens__prec(Arena *arena, EVAL_ParseCtx *ctx, String8
}
}
}
// rjf: get type
if(0 <= local_var->type_idx && local_var->type_idx < ctx->rdbg->type_node_count)
{
U32 type_idx = local_var->type_idx;
RADDBG_TypeNode *type_node = &ctx->rdbg->type_nodes[type_idx];
type_key = tg_key_ext(tg_kind_from_raddbg_type_kind(type_node->kind), (U64)type_idx);
}
}
}
@@ -994,7 +948,7 @@ eval_parse_expr_from_text_tokens__prec(Arena *arena, EVAL_ParseCtx *ctx, String8
loc_kind = RADDBG_LocationKind_AddrBytecodeStream;
loc_bytecode = eval_bytecode_from_oplist(arena, &oplist);
U32 type_idx = global_var->type_idx;
if(type_idx < ctx->rdbg->type_node_count)
if(type_idx < ctx->rdbg->type_nodes_count)
{
RADDBG_TypeNode *type_node = &ctx->rdbg->type_nodes[type_idx];
type_key = tg_key_ext(tg_kind_from_raddbg_type_kind(type_node->kind), (U64)type_idx);
@@ -1032,7 +986,7 @@ eval_parse_expr_from_text_tokens__prec(Arena *arena, EVAL_ParseCtx *ctx, String8
loc_kind = RADDBG_LocationKind_AddrBytecodeStream;
loc_bytecode = eval_bytecode_from_oplist(arena, &oplist);
U32 type_idx = thread_var->type_idx;
if(type_idx < ctx->rdbg->type_node_count)
if(type_idx < ctx->rdbg->type_nodes_count)
{
RADDBG_TypeNode *type_node = &ctx->rdbg->type_nodes[type_idx];
type_key = tg_key_ext(tg_kind_from_raddbg_type_kind(type_node->kind), (U64)type_idx);
@@ -1072,7 +1026,7 @@ eval_parse_expr_from_text_tokens__prec(Arena *arena, EVAL_ParseCtx *ctx, String8
loc_kind = RADDBG_LocationKind_ValBytecodeStream;
loc_bytecode = eval_bytecode_from_oplist(arena, &oplist);
U32 type_idx = procedure->type_idx;
if(type_idx < ctx->rdbg->type_node_count)
if(type_idx < ctx->rdbg->type_nodes_count)
{
RADDBG_TypeNode *type_node = &ctx->rdbg->type_nodes[type_idx];
type_key = tg_key_ext(tg_kind_from_raddbg_type_kind(type_node->kind), (U64)type_idx);
@@ -1182,10 +1136,10 @@ eval_parse_expr_from_text_tokens__prec(Arena *arena, EVAL_ParseCtx *ctx, String8
}
}
// rjf: error on map failure
if(mapped_identifier == 0)
//- rjf: map failure -> attach as leaf identifier, to be resolved later
if(!mapped_identifier)
{
eval_errorf(arena, &result.errors, EVAL_ErrorKind_ResolutionFailure, token_string.str, "Unknown identifier \"%S\".", token_string);
atom = eval_expr_leaf_ident(arena, token_string.str, token_string);
it += 1;
}
}break;
@@ -1476,6 +1430,7 @@ eval_parse_expr_from_text_tokens__prec(Arena *arena, EVAL_ParseCtx *ctx, String8
result.last_token = it;
result.expr = atom;
scratch_end(scratch);
ProfEnd();
return result;
}
+4 -40
View File
@@ -1,33 +1,8 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#ifndef EVAL2_PARSER_H
#define EVAL2_PARSER_H
////////////////////////////////
//~ rjf: Maps
typedef struct EVAL_String2NumMapNode EVAL_String2NumMapNode;
struct EVAL_String2NumMapNode
{
EVAL_String2NumMapNode *next;
String8 string;
U64 num;
};
typedef struct EVAL_String2NumMapSlot EVAL_String2NumMapSlot;
struct EVAL_String2NumMapSlot
{
EVAL_String2NumMapNode *first;
EVAL_String2NumMapNode *last;
};
typedef struct EVAL_String2NumMap EVAL_String2NumMap;
struct EVAL_String2NumMap
{
U64 slots_count;
EVAL_String2NumMapSlot *slots;
};
#ifndef EVAL_PARSER_H
#define EVAL_PARSER_H
////////////////////////////////
//~ rjf: Token Types
@@ -104,20 +79,9 @@ struct EVAL_ParseCtx
//~ rjf: Globals
read_only global EVAL_String2NumMap eval_string2num_map_nil = {0};
read_only global EVAL_String2ExprMap eval_string2expr_map_nil = {0};
global read_only EVAL_ParseResult eval_parse_result_nil = {0, &eval_expr_nil};
////////////////////////////////
//~ rjf: Basic Functions
internal U64 eval_hash_from_string(String8 string);
////////////////////////////////
//~ rjf: Map Functions
internal EVAL_String2NumMap eval_string2num_map_make(Arena *arena, U64 slot_count);
internal void eval_string2num_map_insert(Arena *arena, EVAL_String2NumMap *map, String8 string, U64 num);
internal U64 eval_num_from_string(EVAL_String2NumMap *map, String8 string);
////////////////////////////////
//~ rjf: Debug-Info-Driven Map Building Fast Paths
@@ -142,4 +106,4 @@ internal EVAL_ParseResult eval_parse_type_from_text_tokens(Arena *arena, EVAL_Pa
internal EVAL_ParseResult eval_parse_expr_from_text_tokens__prec(Arena *arena, EVAL_ParseCtx *ctx, String8 text, EVAL_TokenArray *tokens, S64 max_precedence);
internal EVAL_ParseResult eval_parse_expr_from_text_tokens(Arena *arena, EVAL_ParseCtx *ctx, String8 text, EVAL_TokenArray *tokens);
#endif // EVAL2_PARSER_H
#endif // EVAL_PARSER_H
+8
View File
@@ -46,6 +46,8 @@ EVAL_ExprKind_TypeIdent,
EVAL_ExprKind_Ptr,
EVAL_ExprKind_Array,
EVAL_ExprKind_Func,
EVAL_ExprKind_Define,
EVAL_ExprKind_LeafIdent,
EVAL_ExprKind_COUNT
};
@@ -88,6 +90,8 @@ U8 eval_expr_kind_child_counts[] =
1,
2,
1,
2,
0,
};
String8 eval_expr_kind_strings[] =
@@ -129,6 +133,8 @@ str8_lit_comp("TypeIdent"),
str8_lit_comp("Ptr"),
str8_lit_comp("Array"),
str8_lit_comp("Func"),
str8_lit_comp("Define"),
str8_lit_comp("LeafIdent"),
};
String8 eval_expr_op_strings[] =
@@ -170,6 +176,8 @@ str8_lit_comp("type_ident"),
str8_lit_comp("ptr"),
str8_lit_comp("array"),
str8_lit_comp("function"),
str8_lit_comp("="),
str8_lit_comp("leaf_ident"),
};
+2 -2
View File
@@ -24,11 +24,11 @@ fs_init(void)
fs_shared->u2s_ring_base = push_array_no_zero(arena, U8, fs_shared->u2s_ring_size);
fs_shared->u2s_ring_cv = os_condition_variable_alloc();
fs_shared->u2s_ring_mutex = os_mutex_alloc();
fs_shared->streamer_count = Min(4, os_logical_core_count()-1);
fs_shared->streamer_count = Clamp(1, os_logical_core_count()-1, 4);
fs_shared->streamers = push_array(arena, OS_Handle, 1);
for(U64 idx = 0; idx < fs_shared->streamer_count; idx += 1)
{
fs_shared->streamers[idx] = os_launch_thread(fs_streamer_thread__entry_point, &idx, 0);
fs_shared->streamers[idx] = os_launch_thread(fs_streamer_thread__entry_point, (void *)idx, 0);
}
}
+1 -1
View File
@@ -35,7 +35,7 @@ geo_init(void)
geo_shared->u2x_ring_base = push_array_no_zero(arena, U8, geo_shared->u2x_ring_size);
geo_shared->u2x_ring_cv = os_condition_variable_alloc();
geo_shared->u2x_ring_mutex = os_mutex_alloc();
geo_shared->xfer_thread_count = Min(4, os_logical_core_count()-1);
geo_shared->xfer_thread_count = Clamp(1, os_logical_core_count()-1, 4);
geo_shared->xfer_threads = push_array(arena, OS_Handle, geo_shared->xfer_thread_count);
for(U64 idx = 0; idx < geo_shared->xfer_thread_count; idx += 1)
{
+27
View File
@@ -2266,6 +2266,31 @@ debug_string_tests(void)
#endif
}
////////////////////////////////
//~ rjf: Interrupt Stepping Tests
#include <assert.h>
static void
interrupt_stepping_tests(void)
{
for(int i = 0; i < 1000; i += 1)
{
if(i == 999)
{
__debugbreak();
}
}
for(int i = 0; i < 1000; i += 1)
{
if(i == 999)
{
assert(0);
}
}
int x = 0;
}
////////////////////////////////
// NOTE(allen): Exception Stepping
@@ -2561,6 +2586,8 @@ mule_main(int argc, char** argv){
debug_string_tests();
interrupt_stepping_tests();
exception_stepping_tests();
return(0);
+1
View File
@@ -40,6 +40,7 @@ typedef enum OS_EventKind
OS_EventKind_Null,
OS_EventKind_Press,
OS_EventKind_Release,
OS_EventKind_MouseMove,
OS_EventKind_Text,
OS_EventKind_Scroll,
OS_EventKind_WindowLoseFocus,
+10 -1
View File
@@ -429,6 +429,13 @@ w32_wnd_proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
}
}break;
case WM_MOUSEMOVE:
{
OS_Event *event = w32_push_event(OS_EventKind_MouseMove, window);
event->pos.x = (F32)LOWORD(lParam);
event->pos.y = (F32)HIWORD(lParam);
}break;
case WM_MOUSEWHEEL:
{
S16 wheel_delta = HIWORD(wParam);
@@ -485,7 +492,9 @@ w32_wnd_proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
}break;
case WM_SYSCHAR:
{}break;
{
result = DefWindowProcW(hwnd, uMsg, wParam, lParam);
}break;
case WM_CHAR:
{
+18 -26
View File
@@ -4,6 +4,10 @@
////////////////////////////////
//~ rjf: Frontend/UI Pass Tasks
//
// [x] hover-eval when window is not focused - maybe just start directly
// using mouse-move events here
// [x] CRT asserts - stepping over int 29 should work just like stepping over
// an int3
// [ ] committing needs to happen when navigating focus away for any reason
//
// [ ] source view -> floating margin/line-nums
@@ -40,10 +44,13 @@
// always have the same color ordering?
//
// [ ] middle mouse button on tab should close it
// [ ] pipe failure-to-launch errors back to frontend
////////////////////////////////
//~ rjf: Hot, High Priority Tasks (Complete Unusability, Crashes, Fire-Worthy)
//
// [ ] Jump table thunks, on code w/o /INCREMENTAL:NO
//
// [ ] ** Thread/process control bullet-proofing, including solo-step mode
//
// [ ] ** In solo-stepping mode, if I step over something like CreateFileA, it
@@ -69,15 +76,11 @@
////////////////////////////////
//~ rjf: Hot, Medium Priority Tasks (Low-Hanging-Fruit Features, UI Jank, Cleanup)
//
// [ ] Watch Window Type Evaluation
// [ ] Globals, Thread-Locals, Types Views
// [ ] Watch Window Filtering
//
// [ ] investigate /DEBUG:FASTLINK - can we somehow alert that we do not
// support it?
//
// [x] escaping in config files - breakpoint labels etc.
//
// [ ] visualize conversion failures
//
// [ ] I was a little confused about what a profile file was. I understood
@@ -88,16 +91,6 @@
// to say that I was confused about it after reading the manual, so
// perhaps you could elaborate a little more on it in there.
//
// [ ] ** "Find Name" may not be working as advertised. In the description, it
// says you can jump to a file, but if I type in the complete filename of
// a file in the project and hit return, it just turns red and says it
// couldn't find it. This happens even if the file is already open in a
// tab.
// [ ] "Find Name" would be a lot more useful if you could type partial
// things, and it displayed a list, more like what happens in a
// traditional text editor. Typing the entire name of a function to jump
// to it is too laborious.
//
// [ ] Right-clicking on a thread in the Scheduler window pops up a context
// menu, but you can't actually see it because the tooltip for the thread
// draws on top of it, so you can't see the menu.
@@ -139,10 +132,6 @@
// have alternating bright/dim letters to show sections of a number. Is
// this in the theme colors somewhere?
//
// [ ] For breakpoint-on-function, it would be great if it showed a list of
// (partial) matches as you type, so you can stop typing once it gets the
// right function instead of having to type the entire function name.
//
// [ ] ** I couldn't figure out how to really view threads in the debugger.
// The only place I found a thread list was in "The Scheduler", but it
// only lists threads by ID, which is hard to use. I can hover over them
@@ -197,11 +186,6 @@
// opens the context window. It seems like maybe menus should be right,
// and left should do the default action, more consistently?
//
// [x] Hovering over disassembly highlights blocks of instructions, which I
// assume correspond to source lines. But perhaps it should also highlight
// the source lines? The inverse hover works (you hover over source, and
// it highlights ASM), but ASM->source doesn't.
//
// [ ] It wasn't clear to me how you save a user or profile file. I can see
// how to load them, but not how you save them. Obviously I can just copy
// the files myself in the shell, but it seemed weird that there was no
@@ -297,6 +281,7 @@
// [ ] Fancy View Rules
// [ ] table column boundaries should be checked against *AFTER* table
// contents, not before
// [ ] `array:(x, y)` - multidimensional array
// [ ] `text[:lang]` - interpret memory as text, in lang `lang`
// [ ] `disasm:arch` - interpret memory as machine code for isa `arch`
// [ ] `memory` - view memory in usual memory hex-editor view
@@ -322,6 +307,7 @@
//
// [ ] @feature processor/data breakpoints
// [ ] @feature automatically snap to search matches when searching source files
// [ ] automatically start search query with selected text
// [ ] @feature entity views: filtering & reordering
////////////////////////////////
@@ -418,13 +404,19 @@
#define RADDBG_VERSION_MAJOR 0
#define RADDBG_VERSION_MINOR 9
#define RADDBG_VERSION_PATCH 7
#define RADDBG_VERSION_PATCH 8
#define RADDBG_VERSION_STRING_LITERAL Stringify(RADDBG_VERSION_MAJOR) "." Stringify(RADDBG_VERSION_MINOR) "." Stringify(RADDBG_VERSION_PATCH)
#if defined(NDEBUG)
# define RADDBG_TITLE_STRING_LITERAL "The RAD Debugger (" RADDBG_VERSION_STRING_LITERAL " ALPHA) - " __DATE__ ""
# define RADDBG_BUILD_STR ""
#else
# define RADDBG_TITLE_STRING_LITERAL "The RAD Debugger (" RADDBG_VERSION_STRING_LITERAL " ALPHA) - " __DATE__ " [Debug]"
# define RADDBG_BUILD_STR " [Debug]"
#endif
#if defined(RADDBG_GIT)
# define RADDBG_GIT_STR " [" RADDBG_GIT "]"
#else
# define RADDBG_GIT_STR ""
#endif
#define RADDBG_TITLE_STRING_LITERAL "The RAD Debugger (" RADDBG_VERSION_STRING_LITERAL " ALPHA) - " __DATE__ "" RADDBG_GIT_STR RADDBG_BUILD_STR
#define RADDBG_GITHUB_ISSUES "https://github.com/EpicGames/raddebugger/issues"
////////////////////////////////
+15 -17
View File
@@ -1,3 +1,6 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
////////////////////////////////
//~ rjf: Includes
@@ -29,9 +32,7 @@
#include "type_graph/type_graph.h"
#include "dbgi/dbgi.h"
#include "demon/demon_inc.h"
#include "eval/eval_compiler.h"
#include "eval/eval_machine.h"
#include "eval/eval_parser.h"
#include "eval/eval_inc.h"
#include "unwind/unwind.h"
#include "ctrl/ctrl_inc.h"
#include "dasm/dasm.h"
@@ -72,9 +73,7 @@
#include "type_graph/type_graph.c"
#include "dbgi/dbgi.c"
#include "demon/demon_inc.c"
#include "eval/eval_compiler.c"
#include "eval/eval_machine.c"
#include "eval/eval_parser.c"
#include "eval/eval_inc.c"
#include "unwind/unwind.c"
#include "ctrl/ctrl_inc.c"
#include "dasm/dasm.c"
@@ -132,7 +131,7 @@ win32_exception_filter(EXCEPTION_POINTERS* exception_ptrs)
int buflen = 0;
DWORD exception_code = exception_ptrs->ExceptionRecord->ExceptionCode;
buflen += wnsprintfW(buffer + buflen, sizeof(buffer) - buflen, L"A fatal exception (code 0x%x) occurred. The process is terminating.\n", exception_code);
buflen += wnsprintfW(buffer + buflen, ArrayCount(buffer) - buflen, L"A fatal exception (code 0x%x) occurred. The process is terminating.\n", exception_code);
// load dbghelp dynamically just in case if it is missing
HMODULE dbghelp = LoadLibraryA("dbghelp.dll");
@@ -213,7 +212,7 @@ win32_exception_filter(EXCEPTION_POINTERS* exception_ptrs)
const U32 max_frames = 32;
if(idx == max_frames)
{
buflen += wnsprintfW(buffer + buflen, sizeof(buffer) - buflen, L"...");
buflen += wnsprintfW(buffer + buflen, ArrayCount(buffer) - buflen, L"...");
break;
}
@@ -230,13 +229,13 @@ win32_exception_filter(EXCEPTION_POINTERS* exception_ptrs)
if(idx==0)
{
buflen += wnsprintfW(buffer + buflen, sizeof(buffer) - buflen,
buflen += wnsprintfW(buffer + buflen, ArrayCount(buffer) - buflen,
L"\nPress Ctrl+C to copy this text to clipboard, then create a new issue in\n"
L"<a href=\"%S\">%S</a>\n\n", RADDBG_GITHUB_ISSUES, RADDBG_GITHUB_ISSUES);
buflen += wnsprintfW(buffer + buflen, sizeof(buffer) - buflen, L"Call stack:\n");
buflen += wnsprintfW(buffer + buflen, ArrayCount(buffer) - buflen, L"Call stack:\n");
}
buflen += wnsprintfW(buffer + buflen, sizeof(buffer) - buflen, L"%u. [0x%I64x]", idx, address);
buflen += wnsprintfW(buffer + buflen, ArrayCount(buffer) - buflen, L"%u. [0x%I64x]", idx + 1, address);
struct {
SYMBOL_INFOW info;
@@ -249,7 +248,7 @@ win32_exception_filter(EXCEPTION_POINTERS* exception_ptrs)
DWORD64 displacement = 0;
if(dbg_SymFromAddrW(process, address, &displacement, &symbol.info))
{
buflen += wnsprintfW(buffer + buflen, sizeof(buffer) - buflen, L" %s +%u", symbol.info.Name, (DWORD)displacement);
buflen += wnsprintfW(buffer + buflen, ArrayCount(buffer) - buflen, L" %s +%u", symbol.info.Name, (DWORD)displacement);
IMAGEHLP_LINEW64 line = {0};
line.SizeOfStruct = sizeof(line);
@@ -257,7 +256,7 @@ win32_exception_filter(EXCEPTION_POINTERS* exception_ptrs)
DWORD line_displacement = 0;
if(dbg_SymGetLineFromAddrW64(process, address, &line_displacement, &line))
{
buflen += wnsprintfW(buffer + buflen, sizeof(buffer) - buflen, L", %s line %u", PathFindFileNameW(line.FileName), line.LineNumber);
buflen += wnsprintfW(buffer + buflen, ArrayCount(buffer) - buflen, L", %s line %u", PathFindFileNameW(line.FileName), line.LineNumber);
}
}
else
@@ -266,19 +265,18 @@ win32_exception_filter(EXCEPTION_POINTERS* exception_ptrs)
module.SizeOfStruct = sizeof(module);
if(dbg_SymGetModuleInfoW64(process, address, &module))
{
buflen += wnsprintfW(buffer + buflen, sizeof(buffer) - buflen, L" %s", module.ModuleName);
buflen += wnsprintfW(buffer + buflen, ArrayCount(buffer) - buflen, L" %s", module.ModuleName);
}
}
buflen += wnsprintfW(buffer + buflen, sizeof(buffer) - buflen, L"\n");
buflen += wnsprintfW(buffer + buflen, ArrayCount(buffer) - buflen, L"\n");
}
}
}
}
}
// remove last newline
buffer[buflen] = 0;
buflen += wnsprintfW(buffer + buflen, ArrayCount(buffer) - buflen, L"\nVersion: %S%S", RADDBG_VERSION_STRING_LITERAL, RADDBG_GIT_STR);
TASKDIALOGCONFIG dialog = {0};
dialog.cbSize = sizeof(dialog);
+41 -20
View File
@@ -121,16 +121,16 @@ raddbg_parse(RADDBG_U8 *data, RADDBG_U64 size, RADDBG_Parsed *out){
out->top_level_info = tli;
}
raddbg_parse__extract_primary(out, out->binary_sections, &out->binary_section_count,
raddbg_parse__extract_primary(out, out->binary_sections, &out->binary_sections_count,
RADDBG_DataSectionTag_BinarySections);
raddbg_parse__extract_primary(out, out->file_paths, &out->file_path_count,
raddbg_parse__extract_primary(out, out->file_paths, &out->file_paths_count,
RADDBG_DataSectionTag_FilePathNodes);
raddbg_parse__extract_primary(out, out->source_files, &out->source_file_count,
raddbg_parse__extract_primary(out, out->source_files, &out->source_files_count,
RADDBG_DataSectionTag_SourceFiles);
raddbg_parse__extract_primary(out, out->units, &out->unit_count,
raddbg_parse__extract_primary(out, out->units, &out->units_count,
RADDBG_DataSectionTag_Units);
raddbg_parse__extract_primary(out, out->unit_vmap, &out->unit_vmap_count,
@@ -139,54 +139,54 @@ raddbg_parse(RADDBG_U8 *data, RADDBG_U64 size, RADDBG_Parsed *out){
raddbg_parse__extract_primary(out, out->unit_vmap, &out->unit_vmap_count,
RADDBG_DataSectionTag_UnitVmap);
raddbg_parse__extract_primary(out, out->type_nodes, &out->type_node_count,
raddbg_parse__extract_primary(out, out->type_nodes, &out->type_nodes_count,
RADDBG_DataSectionTag_TypeNodes);
raddbg_parse__extract_primary(out, out->udts, &out->udt_count,
raddbg_parse__extract_primary(out, out->udts, &out->udts_count,
RADDBG_DataSectionTag_UDTs);
raddbg_parse__extract_primary(out, out->members, &out->member_count,
raddbg_parse__extract_primary(out, out->members, &out->members_count,
RADDBG_DataSectionTag_Members);
raddbg_parse__extract_primary(out, out->enum_members, &out->enum_member_count,
raddbg_parse__extract_primary(out, out->enum_members, &out->enum_members_count,
RADDBG_DataSectionTag_EnumMembers);
raddbg_parse__extract_primary(out, out->global_variables, &out->global_variable_count,
raddbg_parse__extract_primary(out, out->global_variables, &out->global_variables_count,
RADDBG_DataSectionTag_GlobalVariables);
raddbg_parse__extract_primary(out, out->global_vmap, &out->global_vmap_count,
RADDBG_DataSectionTag_GlobalVmap);
raddbg_parse__extract_primary(out, out->thread_variables, &out->thread_variable_count,
raddbg_parse__extract_primary(out, out->thread_variables, &out->thread_variables_count,
RADDBG_DataSectionTag_ThreadVariables);
raddbg_parse__extract_primary(out, out->procedures, &out->procedure_count,
raddbg_parse__extract_primary(out, out->procedures, &out->procedures_count,
RADDBG_DataSectionTag_Procedures);
raddbg_parse__extract_primary(out, out->scopes, &out->scope_count,
raddbg_parse__extract_primary(out, out->scopes, &out->scopes_count,
RADDBG_DataSectionTag_Scopes);
raddbg_parse__extract_primary(out, out->scope_voffs, &out->scope_voff_count,
raddbg_parse__extract_primary(out, out->scope_voffs, &out->scope_voffs_count,
RADDBG_DataSectionTag_ScopeVoffData);
raddbg_parse__extract_primary(out, out->scope_vmap, &out->scope_vmap_count,
RADDBG_DataSectionTag_ScopeVmap);
raddbg_parse__extract_primary(out, out->locals, &out->local_count,
raddbg_parse__extract_primary(out, out->locals, &out->locals_count,
RADDBG_DataSectionTag_Locals);
raddbg_parse__extract_primary(out, out->location_blocks, &out->location_block_count,
raddbg_parse__extract_primary(out, out->location_blocks, &out->location_blocks_count,
RADDBG_DataSectionTag_LocationBlocks);
raddbg_parse__extract_primary(out, out->location_data, &out->location_data_size,
RADDBG_DataSectionTag_LocationData);
{
raddbg_parse__extract_primary(out, out->name_maps, &out->name_map_count,
raddbg_parse__extract_primary(out, out->name_maps, &out->name_maps_count,
RADDBG_DataSectionTag_NameMaps);
RADDBG_NameMap *name_map_ptr = out->name_maps;
RADDBG_NameMap *name_map_opl = out->name_maps + out->name_map_count;
RADDBG_NameMap *name_map_opl = out->name_maps + out->name_maps_count;
for (; name_map_ptr < name_map_opl; name_map_ptr += 1){
if (out->name_maps_by_kind[name_map_ptr->kind] == 0){
out->name_maps_by_kind[name_map_ptr->kind] = name_map_ptr;
@@ -194,6 +194,27 @@ raddbg_parse(RADDBG_U8 *data, RADDBG_U64 size, RADDBG_Parsed *out){
}
}
#if !defined(RADDBG_DISABLE_NILS)
if(out->binary_sections == 0) { out->binary_sections = &raddbg_binary_section_nil; out->binary_sections_count = 1; }
if(out->file_paths == 0) { out->file_paths = &raddbg_file_path_node_nil; out->file_paths_count = 1; }
if(out->source_files == 0) { out->source_files = &raddbg_source_file_nil; out->source_files_count = 1; }
if(out->units == 0) { out->units = &raddbg_unit_nil; out->units_count = 1; }
if(out->unit_vmap == 0) { out->unit_vmap = &raddbg_vmap_entry_nil; out->unit_vmap_count = 1; }
if(out->type_nodes == 0) { out->type_nodes = &raddbg_type_node_nil; out->type_nodes_count = 1; }
if(out->udts == 0) { out->udts = &raddbg_udt_nil; out->udts_count = 1; }
if(out->members == 0) { out->members = &raddbg_member_nil; out->members_count = 1; }
if(out->enum_members == 0) { out->enum_members = &raddbg_enum_member_nil; out->enum_members_count = 1; }
if(out->global_variables == 0) { out->global_variables = &raddbg_global_variable_nil; out->global_variables_count = 1; }
if(out->global_vmap == 0) { out->global_vmap = &raddbg_vmap_entry_nil; out->global_vmap_count = 1; }
if(out->thread_variables == 0) { out->thread_variables = &raddbg_thread_variable_nil; out->thread_variables_count = 1; }
if(out->procedures == 0) { out->procedures = &raddbg_procedure_nil; out->procedures_count = 1; }
if(out->scopes == 0) { out->scopes = &raddbg_scope_nil; out->scopes_count = 1; }
if(out->scope_voffs == 0) { out->scope_voffs = &raddbg_voff_nil; out->scope_voffs_count = 1; }
if(out->scope_vmap == 0) { out->scope_vmap = &raddbg_vmap_entry_nil; out->scope_vmap_count = 1; }
if(out->locals == 0) { out->locals = &raddbg_local_nil; out->locals_count = 1; }
if(out->location_blocks == 0) { out->location_blocks = &raddbg_location_block_nil; out->location_blocks_count = 1; }
#endif
}
return(result);
@@ -495,13 +516,13 @@ raddbg_matches_from_map_node(RADDBG_Parsed *p, RADDBG_NameMapNode *node,
RADDBG_PROC RADDBG_U64
raddbg_first_voff_from_proc(RADDBG_Parsed *p, RADDBG_U32 proc_id){
RADDBG_U64 result = 0;
if (0 < proc_id && proc_id < p->procedure_count){
if (0 < proc_id && proc_id < p->procedures_count){
RADDBG_Procedure *proc = p->procedures + proc_id;
RADDBG_U32 scope_id = proc->root_scope_idx;
if (0 < scope_id && scope_id < p->scope_count){
if (0 < scope_id && scope_id < p->scopes_count){
RADDBG_Scope *scope = p->scopes + scope_id;
if (scope->voff_range_first < scope->voff_range_opl &&
scope->voff_range_first < p->scope_voff_count){
scope->voff_range_first < p->scope_voffs_count){
result = p->scope_voffs[scope->voff_range_first];
}
}
+39 -16
View File
@@ -30,45 +30,45 @@ typedef struct RADDBG_Parsed{
RADDBG_TopLevelInfo* top_level_info;
RADDBG_BinarySection* binary_sections;
RADDBG_U64 binary_section_count;
RADDBG_U64 binary_sections_count;
RADDBG_FilePathNode* file_paths;
RADDBG_U64 file_path_count;
RADDBG_U64 file_paths_count;
RADDBG_SourceFile* source_files;
RADDBG_U64 source_file_count;
RADDBG_U64 source_files_count;
RADDBG_Unit* units;
RADDBG_U64 unit_count;
RADDBG_U64 units_count;
RADDBG_VMapEntry* unit_vmap;
RADDBG_U64 unit_vmap_count;
RADDBG_TypeNode* type_nodes;
RADDBG_U64 type_node_count;
RADDBG_U64 type_nodes_count;
RADDBG_UDT* udts;
RADDBG_U64 udt_count;
RADDBG_U64 udts_count;
RADDBG_Member* members;
RADDBG_U64 member_count;
RADDBG_U64 members_count;
RADDBG_EnumMember* enum_members;
RADDBG_U64 enum_member_count;
RADDBG_U64 enum_members_count;
RADDBG_GlobalVariable* global_variables;
RADDBG_U64 global_variable_count;
RADDBG_U64 global_variables_count;
RADDBG_VMapEntry* global_vmap;
RADDBG_U64 global_vmap_count;
RADDBG_ThreadVariable* thread_variables;
RADDBG_U64 thread_variable_count;
RADDBG_U64 thread_variables_count;
RADDBG_Procedure* procedures;
RADDBG_U64 procedure_count;
RADDBG_U64 procedures_count;
RADDBG_Scope* scopes;
RADDBG_U64 scope_count;
RADDBG_U64 scopes_count;
RADDBG_U64* scope_voffs;
RADDBG_U64 scope_voff_count;
RADDBG_U64 scope_voffs_count;
RADDBG_VMapEntry* scope_vmap;
RADDBG_U64 scope_vmap_count;
RADDBG_Local* locals;
RADDBG_U64 local_count;
RADDBG_U64 locals_count;
RADDBG_LocationBlock* location_blocks;
RADDBG_U64 location_block_count;
RADDBG_U64 location_blocks_count;
RADDBG_U8* location_data;
RADDBG_U64 location_data_size;
RADDBG_NameMap* name_maps;
RADDBG_U64 name_map_count;
RADDBG_U64 name_maps_count;
// other helpers
@@ -124,6 +124,27 @@ typedef struct RADDBG_ParsedNameMap{
RADDBG_U64 node_count;
} RADDBG_ParsedNameMap;
////////////////////////////////
//~ Global Nils
#if !defined(RADDBG_DISABLE_NILS)
static RADDBG_BinarySection raddbg_binary_section_nil = {0};
static RADDBG_FilePathNode raddbg_file_path_node_nil = {0};
static RADDBG_SourceFile raddbg_source_file_nil = {0};
static RADDBG_Unit raddbg_unit_nil = {0};
static RADDBG_VMapEntry raddbg_vmap_entry_nil = {0};
static RADDBG_TypeNode raddbg_type_node_nil = {0};
static RADDBG_UDT raddbg_udt_nil = {0};
static RADDBG_Member raddbg_member_nil = {0};
static RADDBG_EnumMember raddbg_enum_member_nil = {0};
static RADDBG_GlobalVariable raddbg_global_variable_nil = {0};
static RADDBG_ThreadVariable raddbg_thread_variable_nil = {0};
static RADDBG_Procedure raddbg_procedure_nil = {0};
static RADDBG_Scope raddbg_scope_nil = {0};
static U64 raddbg_voff_nil = 0;
static RADDBG_LocationBlock raddbg_location_block_nil = {0};
static RADDBG_Local raddbg_local_nil = {0};
#endif
////////////////////////////////
//~ RADDBG Parse API
@@ -138,6 +159,8 @@ RADDBG_PROC RADDBG_U32*
raddbg_idx_run_from_first_count(RADDBG_Parsed *parsed, RADDBG_U32 first, RADDBG_U32 raw_count,
RADDBG_U32 *n_out);
//- table lookups
#define raddbg_element_from_idx(parsed, name, idx) ((0 <= (idx) && (idx) < (parsed)->name##_count) ? &(parsed)->name[idx] : (parsed)->name ? &(parsed)->name[0] : 0)
//- line info
RADDBG_PROC void
+44 -44
View File
@@ -143,7 +143,7 @@ r_init(CmdLine *cmdln)
//- rjf: create base device
UINT creation_flags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;
#if !defined(NDEBUG)
if(!cmd_line_has_flag(cmdln, str8_lit("disable_d3d11_debug")))
if(cmd_line_has_flag(cmdln, str8_lit("d3d11_debug")))
{
creation_flags |= D3D11_CREATE_DEVICE_DEBUG;
}
@@ -172,7 +172,7 @@ r_init(CmdLine *cmdln)
D3D11_SDK_VERSION,
&r_d3d11_state->base_device, 0, &r_d3d11_state->base_device_ctx);
}
if(FAILED(error))
{
char buffer[256] = {0};
@@ -183,7 +183,7 @@ r_init(CmdLine *cmdln)
//- rjf: enable break-on-error
#if !defined(NDEBUG)
if(!cmd_line_has_flag(cmdln, str8_lit("disable_d3d11_debug")))
if(cmd_line_has_flag(cmdln, str8_lit("d3d11_debug")))
{
ID3D11InfoQueue *info = 0;
error = r_d3d11_state->base_device->QueryInterface(__uuidof(ID3D11InfoQueue), (void **)(&info));
@@ -240,7 +240,7 @@ r_init(CmdLine *cmdln)
}
error = r_d3d11_state->device->CreateBlendState(&desc, &r_d3d11_state->no_blend_state);
}
//- rjf: create nearest-neighbor sampler
{
D3D11_SAMPLER_DESC desc = zero_struct;
@@ -349,7 +349,7 @@ r_init(CmdLine *cmdln)
vshad_source_blob->GetBufferSize(),
&ilay);
}
vshad_source_blob->Release();
// rjf: store
@@ -393,7 +393,7 @@ r_init(CmdLine *cmdln)
error = r_d3d11_state->device->CreatePixelShader(pshad_source_blob->GetBufferPointer(), pshad_source_blob->GetBufferSize(), 0, &pshad);
}
}
pshad_source_blob->Release();
// rjf: store
@@ -1196,49 +1196,49 @@ r_window_submit(OS_Handle window, R_Handle window_equip, R_PassList *passes)
ID3D11VertexShader *vshad = r_d3d11_state->vshads[R_D3D11_VShadKind_Blur];
ID3D11PixelShader *pshad = r_d3d11_state->pshads[R_D3D11_PShadKind_Blur];
ID3D11Buffer *uniforms_buffer = r_d3d11_state->uniform_type_kind_buffers[R_D3D11_VShadKind_Blur];
// rjf: setup output merger
d_ctx->OMSetDepthStencilState(r_d3d11_state->noop_depth_stencil, 0);
d_ctx->OMSetBlendState(r_d3d11_state->no_blend_state, 0, 0xffffffff);
// rjf: set up viewport
Vec2S32 resolution = wnd->last_resolution;
D3D11_VIEWPORT viewport = { 0.0f, 0.0f, (F32)resolution.x, (F32)resolution.y, 0.0f, 1.0f };
d_ctx->RSSetViewports(1, &viewport);
d_ctx->RSSetState(r_d3d11_state->main_rasterizer);
// rjf: setup input assembly
d_ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
d_ctx->IASetInputLayout(0);
// rjf: setup shaders
d_ctx->VSSetShader(vshad, 0, 0);
d_ctx->VSSetConstantBuffers(0, 1, &uniforms_buffer);
d_ctx->PSSetShader(pshad, 0, 0);
d_ctx->PSSetSamplers(0, 1, &sampler);
// rjf: setup scissor rect
{
D3D11_RECT rect = { 0 };
rect.left = 0;
rect.right = (LONG)wnd->last_resolution.x;
rect.top = 0;
rect.bottom = (LONG)wnd->last_resolution.y;
d_ctx->RSSetScissorRects(1, &rect);
D3D11_RECT rect = { 0 };
rect.left = 0;
rect.right = (LONG)wnd->last_resolution.x;
rect.top = 0;
rect.bottom = (LONG)wnd->last_resolution.y;
d_ctx->RSSetScissorRects(1, &rect);
}
// rjf: set up uniforms
R_D3D11_Uniforms_Blur uniforms = { 0 };
{
F32 weights[ArrayCount(uniforms.kernel)*2] = {0};
F32 blur_size = Min(params->blur_size, ArrayCount(weights));
U64 blur_count = (U64)round_f32(blur_size);
F32 stdev = (blur_size-1.f)/2.f;
F32 one_over_root_2pi_stdev2 = 1/sqrt_f32(2*pi32*stdev*stdev);
F32 euler32 = 2.718281828459045f;
weights[0] = 1.f;
if(stdev > 0.f)
{
@@ -1262,64 +1262,64 @@ r_window_submit(OS_Handle window, R_Handle window_equip, R_PassList *passes)
// thus w=w0+w1 and t=w1/w
for (U64 idx = 1; idx < blur_count; idx += 2)
{
F32 w0 = weights[idx + 0];
F32 w1 = weights[idx + 1];
F32 w = w0 + w1;
F32 t = w1 / w;
// each kernel element is float2(weight, offset)
// weights & offsets are adjusted for bilinear sampling
// zw elements are not used, a bit of waste but it allows for simpler shader code
uniforms.kernel[(idx+1)/2] = v4f32(w, (F32)idx + t, 0, 0);
F32 w0 = weights[idx + 0];
F32 w1 = weights[idx + 1];
F32 w = w0 + w1;
F32 t = w1 / w;
// each kernel element is float2(weight, offset)
// weights & offsets are adjusted for bilinear sampling
// zw elements are not used, a bit of waste but it allows for simpler shader code
uniforms.kernel[(idx+1)/2] = v4f32(w, (F32)idx + t, 0, 0);
}
}
uniforms.kernel[0].x = weights[0];
// technically we need just direction be different
// but there are 256 bytes of usable space anyway for each constant buffer chunk
uniforms.passes[Axis2_X].viewport_size = v2f32(resolution.x, resolution.y);
uniforms.passes[Axis2_X].rect = params->rect;
uniforms.passes[Axis2_X].direction = v2f32(1.f / resolution.x, 0);
uniforms.passes[Axis2_X].blur_count = 1 + blur_count / 2; // 2x smaller because of bilinear sampling
MemoryCopyArray(uniforms.passes[Axis2_X].corner_radii.v, params->corner_radii);
uniforms.passes[Axis2_Y].viewport_size = v2f32(resolution.x, resolution.y);
uniforms.passes[Axis2_Y].rect = params->rect;
uniforms.passes[Axis2_Y].direction = v2f32(0, 1.f / resolution.y);
uniforms.passes[Axis2_Y].blur_count = 1 + blur_count / 2; // 2x smaller because of bilinear sampling
MemoryCopyArray(uniforms.passes[Axis2_Y].corner_radii.v, params->corner_radii);
D3D11_MAPPED_SUBRESOURCE sub_rsrc = {0};
r_d3d11_state->device_ctx->Map(uniforms_buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &sub_rsrc);
MemoryCopy((U8 *)sub_rsrc.pData, &uniforms, sizeof(uniforms));
r_d3d11_state->device_ctx->Unmap(uniforms_buffer, 0);
}
ID3D11Buffer* uniforms_buffers[] = { uniforms_buffer, uniforms_buffer };
U32 uniform_offset[Axis2_COUNT][2] =
{
{ 0 * sizeof(R_D3D11_Uniforms_BlurPass) / 16, (U32)OffsetOf(R_D3D11_Uniforms_Blur, kernel) / 16 },
{ 1 * sizeof(R_D3D11_Uniforms_BlurPass) / 16, (U32)OffsetOf(R_D3D11_Uniforms_Blur, kernel) / 16 },
{ 0 * sizeof(R_D3D11_Uniforms_BlurPass) / 16, (U32)OffsetOf(R_D3D11_Uniforms_Blur, kernel) / 16 },
{ 1 * sizeof(R_D3D11_Uniforms_BlurPass) / 16, (U32)OffsetOf(R_D3D11_Uniforms_Blur, kernel) / 16 },
};
U32 uniform_count[Axis2_COUNT][2] =
{
{ sizeof(R_D3D11_Uniforms_BlurPass) / 16, sizeof(uniforms.kernel) / 16 },
{ sizeof(R_D3D11_Uniforms_BlurPass) / 16, sizeof(uniforms.kernel) / 16 },
{ sizeof(R_D3D11_Uniforms_BlurPass) / 16, sizeof(uniforms.kernel) / 16 },
{ sizeof(R_D3D11_Uniforms_BlurPass) / 16, sizeof(uniforms.kernel) / 16 },
};
// rjf: for unsetting srv
ID3D11ShaderResourceView* srv = 0;
// horizontal pass
d_ctx->OMSetRenderTargets(1, &wnd->stage_scratch_color_rtv, 0);
d_ctx->PSSetConstantBuffers1(0, ArrayCount(uniforms_buffers), uniforms_buffers, uniform_offset[Axis2_X], uniform_count[Axis2_X]);
d_ctx->PSSetShaderResources(0, 1, &wnd->stage_color_srv);
d_ctx->Draw(4, 0);
d_ctx->PSSetShaderResources(0, 1, &srv);
// vertical pass
d_ctx->OMSetRenderTargets(1, &wnd->stage_color_rtv, 0);
d_ctx->PSSetConstantBuffers1(0, ArrayCount(uniforms_buffers), uniforms_buffers, uniform_offset[Axis2_Y], uniform_count[Axis2_Y]);
-55
View File
@@ -193,61 +193,6 @@ struct R_PassList
U64 count;
};
////////////////////////////////
//~ rjf: 2D Rendering Types
typedef enum R2_CmdKind
{
R2_CmdKind_Null,
R2_CmdKind_Rects,
R2_CmdKind_COUNT
}
R2_CmdKind;
typedef struct R2_CmdInst_Rect R2_CmdInst_Rect;
struct R2_CmdInst_Rect
{
Rng2F32 dst;
Rng2F32 src;
Vec4F32 colors[Corner_COUNT];
F32 corner_radii[Corner_COUNT];
F32 border_thickness;
F32 edge_softness;
F32 white_texture_override;
F32 _unused_[1];
};
typedef struct R2_Cmd R2_Cmd;
struct R2_Cmd
{
R2_CmdKind kind;
R_Handle texture;
Rng2F32 clip;
Vec2F32 translate;
F32 transparency;
U64 count;
union
{
void *data;
R2_CmdInst_Rect *data__rect;
};
};
typedef struct R2_CmdNode R2_CmdNode;
struct R2_CmdNode
{
R2_CmdNode *next;
R2_Cmd cmd;
};
typedef struct R2_CmdList R2_CmdList;
struct R2_CmdList
{
R2_CmdNode *first;
R2_CmdNode *last;
U64 count;
};
////////////////////////////////
//~ rjf: Handle Type Functions
+1 -1
View File
@@ -3,7 +3,7 @@
#include <Windows.h>
int main(void)
int main(int argument_count, char **arguments)
{
for(int i = 0; i < 1000; i += 1)
{
+1 -1
View File
@@ -412,7 +412,7 @@ txt_init(void)
txt_shared->u2p_ring_base = push_array_no_zero(arena, U8, txt_shared->u2p_ring_size);
txt_shared->u2p_ring_cv = os_condition_variable_alloc();
txt_shared->u2p_ring_mutex = os_mutex_alloc();
txt_shared->parse_thread_count = Min(4, os_logical_core_count()-1);
txt_shared->parse_thread_count = Clamp(1, os_logical_core_count()-1, 4);
txt_shared->parse_threads = push_array(arena, OS_Handle, txt_shared->parse_thread_count);
for(U64 idx = 0; idx < txt_shared->parse_thread_count; idx += 1)
{
+4 -4
View File
@@ -8,8 +8,8 @@ internal TEX_Topology
tex_topology_make(Vec2S32 dim, R_Tex2DFormat fmt)
{
TEX_Topology top = {0};
top.dim.x = (S16)dim.x;
top.dim.y = (S16)dim.y;
top.dim.x = (S16)Clamp(0, dim.x, max_S32);
top.dim.y = (S16)Clamp(0, dim.y, max_S32);
top.fmt = fmt;
return top;
}
@@ -48,7 +48,7 @@ tex_init(void)
tex_shared->u2x_ring_base = push_array_no_zero(arena, U8, tex_shared->u2x_ring_size);
tex_shared->u2x_ring_cv = os_condition_variable_alloc();
tex_shared->u2x_ring_mutex = os_mutex_alloc();
tex_shared->xfer_thread_count = Min(4, os_logical_core_count()-1);
tex_shared->xfer_thread_count = Clamp(1, os_logical_core_count()-1, 4);
tex_shared->xfer_threads = push_array(arena, OS_Handle, tex_shared->xfer_thread_count);
for(U64 idx = 0; idx < tex_shared->xfer_thread_count; idx += 1)
{
@@ -352,7 +352,7 @@ tex_xfer_thread__entry_point(void *p)
//- rjf: data * topology -> texture
R_Handle texture = {0};
if(got_task && top.dim.x != 0 && top.dim.y != 0 && data.size >= (U64)top.dim.x*(U64)top.dim.y*r_tex2d_format_bytes_per_pixel_table[top.fmt])
if(got_task && top.dim.x > 0 && top.dim.y > 0 && data.size >= (U64)top.dim.x*(U64)top.dim.y*(U64)r_tex2d_format_bytes_per_pixel_table[top.fmt])
{
texture = r_tex2d_alloc(R_Tex2DKind_Static, v2s32(top.dim.x, top.dim.y), top.fmt, data.str);
}
+247 -1
View File
@@ -20,7 +20,7 @@ txti_init(void)
txti_state->entity_map_stripes.v[idx].cv = os_condition_variable_alloc();
txti_state->entity_map_stripes.v[idx].rw_mutex = os_rw_mutex_alloc();
}
txti_state->mut_thread_count = Min(4, os_logical_core_count());
txti_state->mut_thread_count = Clamp(1, os_logical_core_count(), 4);
txti_state->mut_threads = push_array(txti_state->arena, TXTI_MutThread, txti_state->mut_thread_count);
for(U64 idx = 0; idx < txti_state->mut_thread_count; idx += 1)
{
@@ -69,6 +69,10 @@ txti_lang_kind_from_extension(String8 extension)
{
kind = TXTI_LangKind_CPlusPlus;
}
else if(str8_match(extension, str8_lit("odin"), 0))
{
kind = TXTI_LangKind_Odin;
}
return kind;
}
@@ -421,6 +425,244 @@ txti_token_array_from_string__cpp(Arena *arena, U64 *bytes_processed_counter, St
return result;
}
internal TXTI_TokenArray
txti_token_array_from_string__odin(Arena *arena, U64 *bytes_processed_counter, String8 string)
{
//- jle: based on txti_token_array_from_string__cpp (alot of it is exactly the same)
//
// tokenization is a lot like C
// unique set of keywords
// has #tags and #directives
//
// tokenizer source code can be found here
// https://github.com/odin-lang/Odin/tree/master/core/odin/tokenizer
Temp scratch = scratch_begin(&arena, 1);
//- rjf: generate token list
TXTI_TokenChunkList tokens = {0};
{
B32 comment_is_single_line = 0;
B32 string_is_char = 0;
TXTI_TokenKind active_token_kind = TXTI_TokenKind_Null;
U64 active_token_start_idx = 0;
B32 escaped = 0;
B32 next_escaped = 0;
U64 byte_process_start_idx = 0;
for(U64 idx = 0; idx <= string.size;)
{
U8 byte = (idx+0 < string.size) ? (string.str[idx+0]) : 0;
U8 next_byte = (idx+1 < string.size) ? (string.str[idx+1]) : 0;
// rjf: update counter
if(bytes_processed_counter != 0 && ((idx-byte_process_start_idx) >= 1000 || idx == string.size))
{
ins_atomic_u64_add_eval(bytes_processed_counter, (idx-byte_process_start_idx));
byte_process_start_idx = idx;
}
// rjf: escaping
if(escaped && (byte != '\r' && byte != '\n'))
{
next_escaped = 0;
}
else if(!escaped && byte == '\\')
{
next_escaped = 1;
}
// rjf: take starter, determine active token kind
if(active_token_kind == TXTI_TokenKind_Null)
{
// rjf: use next bytes to start a new token
if(0){}
else if(char_is_space(byte)) { active_token_kind = TXTI_TokenKind_Whitespace; }
else if(byte == '_' ||
byte == '$' ||
char_is_alpha(byte)) { active_token_kind = char_is_lower(byte) ? TXTI_TokenKind_Identifier: TXTI_TokenKind_Type; }
else if(char_is_digit(byte, 10) ||
(byte == '.' &&
char_is_digit(next_byte, 10))) { active_token_kind = TXTI_TokenKind_Numeric; }
else if(byte == '"') { active_token_kind = TXTI_TokenKind_String; string_is_char = 0; }
else if(byte == '\'') { active_token_kind = TXTI_TokenKind_String; string_is_char = 1; }
else if(byte == '/' && next_byte == '/') { active_token_kind = TXTI_TokenKind_Comment; comment_is_single_line = 1; }
else if(byte == '/' && next_byte == '*') { active_token_kind = TXTI_TokenKind_Comment; comment_is_single_line = 0; }
else if(byte == '~' || byte == '!' ||
byte == '%' || byte == '^' ||
byte == '&' || byte == '*' ||
byte == '(' || byte == ')' ||
byte == '-' || byte == '=' ||
byte == '+' || byte == '[' ||
byte == ']' || byte == '{' ||
byte == '}' || byte == ':' ||
byte == ';' || byte == ',' ||
byte == '.' || byte == '<' ||
byte == '>' || byte == '/' ||
byte == '?' || byte == '|') { active_token_kind = TXTI_TokenKind_Symbol; }
else if(byte == '#') { active_token_kind = TXTI_TokenKind_Meta; }
// rjf: start new token
if(active_token_kind != TXTI_TokenKind_Null)
{
active_token_start_idx = idx;
}
// rjf: invalid token kind -> emit error
else
{
TXTI_Token token = {TXTI_TokenKind_Error, r1u64(idx, idx+1)};
txti_token_chunk_list_push(scratch.arena, &tokens, 4096, &token);
}
}
// rjf: look for ender
U64 ender_pad = 0;
B32 ender_found = 0;
if(active_token_kind != TXTI_TokenKind_Null && idx>active_token_start_idx)
{
if(idx == string.size)
{
ender_pad = 0;
ender_found = 1;
}
else switch(active_token_kind)
{
default:break;
case TXTI_TokenKind_Whitespace:
{
ender_found = !char_is_space(byte);
}break;
case TXTI_TokenKind_Identifier:
case TXTI_TokenKind_Type:
{
ender_found = (!char_is_alpha(byte) && !char_is_digit(byte, 10) && byte != '_' && byte != '$');
}break;
case TXTI_TokenKind_Numeric:
{
ender_found = (!char_is_alpha(byte) && !char_is_digit(byte, 10) && byte != '_' && byte != '.');
}break;
case TXTI_TokenKind_String:
{
ender_found = (!escaped && ((!string_is_char && byte == '"') || (string_is_char && byte == '\'')));
ender_pad += 1;
}break;
case TXTI_TokenKind_Symbol:
{
ender_found = (byte != '~' && byte != '!' &&
byte != '%' && byte != '^' &&
byte != '&' && byte != '*' &&
byte != '(' && byte != ')' &&
byte != '-' && byte != '=' &&
byte != '+' && byte != '[' &&
byte != ']' && byte != '{' &&
byte != '}' && byte != ':' &&
byte != ';' && byte != ',' &&
byte != '.' && byte != '<' &&
byte != '>' && byte != '/' &&
byte != '?' && byte != '|');
}break;
case TXTI_TokenKind_Comment:
{
if(comment_is_single_line)
{
ender_found = (!escaped && (byte == '\r' || byte == '\n'));
}
else
{
ender_found = (active_token_start_idx+1 < idx && byte == '*' && next_byte == '/');
ender_pad += 2;
}
}break;
case TXTI_TokenKind_Meta:
{
ender_found = (!char_is_alpha(byte) && !char_is_digit(byte, 10) && byte != '_' && byte != '$');
}break;
}
}
// rjf: next byte is ender => emit token
if(ender_found)
{
TXTI_Token token = {active_token_kind, r1u64(active_token_start_idx, idx+ender_pad)};
active_token_kind = TXTI_TokenKind_Null;
// rjf: identifier -> keyword in special cases
if(token.kind == TXTI_TokenKind_Identifier)
{
read_only local_persist String8 cpp_keywords[] =
{
str8_lit_comp("asm"),
str8_lit_comp("auto_cast"),
str8_lit_comp("bit_set"),
str8_lit_comp("break"),
str8_lit_comp("case"),
str8_lit_comp("cast"),
str8_lit_comp("context"),
str8_lit_comp("continue"),
str8_lit_comp("defer"),
str8_lit_comp("distinct"),
str8_lit_comp("do"),
str8_lit_comp("dynamic"),
str8_lit_comp("else"),
str8_lit_comp("enum"),
str8_lit_comp("fallthrough"),
str8_lit_comp("for"),
str8_lit_comp("foreign"),
str8_lit_comp("if"),
str8_lit_comp("in"),
str8_lit_comp("map"),
str8_lit_comp("matrix"),
str8_lit_comp("not_in"),
str8_lit_comp("or_break"),
str8_lit_comp("or_continue"),
str8_lit_comp("or_else"),
str8_lit_comp("or_return"),
str8_lit_comp("package"),
str8_lit_comp("proc"),
str8_lit_comp("return"),
str8_lit_comp("struct"),
str8_lit_comp("switch"),
str8_lit_comp("transmute"),
str8_lit_comp("typeid"),
str8_lit_comp("union"),
str8_lit_comp("using"),
str8_lit_comp("when"),
str8_lit_comp("where"),
str8_lit_comp("import"),
};
String8 token_string = str8_substr(string, r1u64(active_token_start_idx, idx+ender_pad));
for(U64 keyword_idx = 0; keyword_idx < ArrayCount(cpp_keywords); keyword_idx += 1)
{
if(str8_match(cpp_keywords[keyword_idx], token_string, 0))
{
token.kind = TXTI_TokenKind_Keyword;
break;
}
}
}
// rjf: push
txti_token_chunk_list_push(scratch.arena, &tokens, 4096, &token);
// rjf: increment by ender padding
idx += ender_pad;
}
// rjf: advance by 1 byte if we haven't found an ender
if(!ender_found)
{
idx += 1;
}
escaped = next_escaped;
}
}
//- rjf: token list -> token array
TXTI_TokenArray result = txti_token_array_from_chunk_list(arena, &tokens);
scratch_end(scratch);
return result;
}
////////////////////////////////
//~ rjf: Message Type Functions
@@ -1007,6 +1249,10 @@ txti_mut_thread_entry_point(void *p)
{
lex_function = txti_token_array_from_string__cpp;
}break;
case TXTI_LangKind_Odin:
{
lex_function = txti_token_array_from_string__odin;
}break;
}
//- rjf: detect line end kind
+2
View File
@@ -80,6 +80,7 @@ typedef enum TXTI_TokenKind
TXTI_TokenKind_Symbol,
TXTI_TokenKind_Comment,
TXTI_TokenKind_Meta, // preprocessor, etc.
TXTI_TokenKind_Type,
TXTI_TokenKind_COUNT
}
TXTI_TokenKind;
@@ -146,6 +147,7 @@ typedef enum TXTI_LangKind
TXTI_LangKind_Null,
TXTI_LangKind_C,
TXTI_LangKind_CPlusPlus,
TXTI_LangKind_Odin,
TXTI_LangKind_COUNT
}
TXTI_LangKind;
+9 -9
View File
@@ -178,15 +178,15 @@ str8_lit_comp(""),
str8_lit_comp(""),
str8_lit_comp(""),
str8_lit_comp(""),
str8_lit_comp(""),
str8_lit_comp(""),
str8_lit_comp(""),
str8_lit_comp(""),
str8_lit_comp(""),
str8_lit_comp(""),
str8_lit_comp(""),
str8_lit_comp(""),
str8_lit_comp(""),
str8_lit_comp("struct"),
str8_lit_comp("class"),
str8_lit_comp("union"),
str8_lit_comp("enum"),
str8_lit_comp("typedef"),
str8_lit_comp("struct"),
str8_lit_comp("union"),
str8_lit_comp("class"),
str8_lit_comp("enum"),
str8_lit_comp(""),
str8_lit_comp(""),
};
+104 -24
View File
@@ -331,7 +331,7 @@ tg_type_from_graph_raddbg_key(Arena *arena, TG_Graph *graph, RADDBG_Parsed *rdbg
case TG_KeyKind_Ext:
{
U64 type_node_idx = key.u64[0];
if(0 <= type_node_idx && type_node_idx < rdbg->type_node_count)
if(0 <= type_node_idx && type_node_idx < rdbg->type_nodes_count)
{
RADDBG_TypeNode *rdbg_type = &rdbg->type_nodes[type_node_idx];
TG_Kind kind = tg_kind_from_raddbg_type_kind(rdbg_type->kind);
@@ -343,35 +343,33 @@ tg_type_from_graph_raddbg_key(Arena *arena, TG_Graph *graph, RADDBG_Parsed *rdbg
String8 name = {0};
name.str = raddbg_string_from_idx(rdbg, rdbg_type->user_defined.name_string_idx, &name.size);
// rjf: unpack UDT info
RADDBG_UDT *udt = raddbg_element_from_idx(rdbg, udts, rdbg_type->user_defined.udt_idx);
// rjf: unpack members
TG_Member *members = 0;
U32 members_count = 0;
{
U32 udt_idx = rdbg_type->user_defined.udt_idx;
if(0 <= udt_idx && udt_idx < rdbg->udt_count)
members_count = udt->member_count;
members = push_array(arena, TG_Member, members_count);
if(members_count != 0 && 0 <= udt->member_first && udt->member_first+udt->member_count <= rdbg->members_count)
{
RADDBG_UDT *udt = &rdbg->udts[udt_idx];
members_count = udt->member_count;
members = push_array(arena, TG_Member, members_count);
if(members_count != 0 && 0 <= udt->member_first && udt->member_first+udt->member_count <= rdbg->member_count)
for(U32 member_idx = udt->member_first;
member_idx < udt->member_first+udt->member_count;
member_idx += 1)
{
for(U32 member_idx = udt->member_first;
member_idx < udt->member_first+udt->member_count;
member_idx += 1)
RADDBG_Member *src = &rdbg->members[member_idx];
TG_Kind member_type_kind = TG_Kind_Null;
if(src->type_idx < rdbg->type_nodes_count)
{
RADDBG_Member *src = &rdbg->members[member_idx];
TG_Kind member_type_kind = TG_Kind_Null;
if(src->type_idx < rdbg->type_node_count)
{
RADDBG_TypeNode *member_type = &rdbg->type_nodes[src->type_idx];
member_type_kind = tg_kind_from_raddbg_type_kind(member_type->kind);
}
TG_Member *dst = &members[member_idx-udt->member_first];
dst->kind = tg_member_kind_from_raddbg_member_kind(src->kind);
dst->type_key = tg_key_ext(member_type_kind, (U64)src->type_idx);
dst->name.str = raddbg_string_from_idx(rdbg, src->name_string_idx, &dst->name.size);
dst->off = (U64)src->off;
RADDBG_TypeNode *member_type = &rdbg->type_nodes[src->type_idx];
member_type_kind = tg_kind_from_raddbg_type_kind(member_type->kind);
}
TG_Member *dst = &members[member_idx-udt->member_first];
dst->kind = tg_member_kind_from_raddbg_member_kind(src->kind);
dst->type_key = tg_key_ext(member_type_kind, (U64)src->type_idx);
dst->name.str = raddbg_string_from_idx(rdbg, src->name_string_idx, &dst->name.size);
dst->off = (U64)src->off;
}
}
}
@@ -406,12 +404,12 @@ tg_type_from_graph_raddbg_key(Arena *arena, TG_Graph *graph, RADDBG_Parsed *rdbg
U32 enum_vals_count = 0;
{
U32 udt_idx = rdbg_type->user_defined.udt_idx;
if(0 <= udt_idx && udt_idx < rdbg->udt_count)
if(0 <= udt_idx && udt_idx < rdbg->udts_count)
{
RADDBG_UDT *udt = &rdbg->udts[udt_idx];
enum_vals_count = udt->member_count;
enum_vals = push_array(arena, TG_EnumVal, enum_vals_count);
if(0 <= udt->member_first && udt->member_first+udt->member_count < rdbg->enum_member_count)
if(0 <= udt->member_first && udt->member_first+udt->member_count < rdbg->enum_members_count)
{
for(U32 member_idx = udt->member_first;
member_idx < udt->member_first+udt->member_count;
@@ -931,6 +929,16 @@ tg_kind_from_key(TG_Key key)
return kind;
}
internal TG_Member *
tg_member_copy(Arena *arena, TG_Member *src)
{
TG_Member *dst = push_array(arena, TG_Member, 1);
MemoryCopyStruct(dst, src);
dst->name = push_str8_copy(arena, src->name);
dst->inheritance_key_chain = tg_key_list_copy(arena, &src->inheritance_key_chain);
return dst;
}
internal TG_MemberArray
tg_members_from_graph_raddbg_key(Arena *arena, TG_Graph *graph, RADDBG_Parsed *rdbg, TG_Key key)
{
@@ -957,6 +965,9 @@ internal TG_MemberArray
tg_data_members_from_graph_raddbg_key(Arena *arena, TG_Graph *graph, RADDBG_Parsed *rdbg, TG_Key key)
{
Temp scratch = scratch_begin(&arena, 1);
TG_Kind root_type_kind = tg_kind_from_key(key);
//- rjf: walk type tree; gather members list
TG_MemberList members_list = {0};
B32 members_need_offset_sort = 0;
{
@@ -978,6 +989,7 @@ tg_data_members_from_graph_raddbg_key(Arena *arena, TG_Graph *graph, RADDBG_Pars
TG_Type *type = task->type;
if(type->members != 0)
{
U64 last_member_off = 0;
for(U64 member_idx = 0; member_idx < type->count; member_idx += 1)
{
if(type->members[member_idx].kind == TG_MemberKind_DataField)
@@ -988,6 +1000,8 @@ tg_data_members_from_graph_raddbg_key(Arena *arena, TG_Graph *graph, RADDBG_Pars
n->v.inheritance_key_chain = task->inheritance_chain;
SLLQueuePush(members_list.first, members_list.last, n);
members_list.count += 1;
members_need_offset_sort = members_need_offset_sort || (n->v.off < last_member_off);
last_member_off = n->v.off;
}
else if(type->members[member_idx].kind == TG_MemberKind_Base)
{
@@ -1004,6 +1018,8 @@ tg_data_members_from_graph_raddbg_key(Arena *arena, TG_Graph *graph, RADDBG_Pars
}
}
}
//- rjf: convert to array
TG_MemberArray members = {0};
{
members.count = members_list.count;
@@ -1017,10 +1033,74 @@ tg_data_members_from_graph_raddbg_key(Arena *arena, TG_Graph *graph, RADDBG_Pars
idx += 1;
}
}
//- rjf: sort array by offset if needed
if(members_need_offset_sort)
{
qsort(members.v, members.count, sizeof(TG_Member), (int (*)(const void *, const void *))tg_qsort_compare_members_offset);
}
//- rjf: find all padding instances
typedef struct PaddingNode PaddingNode;
struct PaddingNode
{
PaddingNode *next;
U64 off;
U64 size;
U64 prev_member_idx;
};
PaddingNode *first_padding = 0;
PaddingNode *last_padding = 0;
U64 padding_count = 0;
if(root_type_kind == TG_Kind_Struct || root_type_kind == TG_Kind_Class)
{
for(U64 idx = 0; idx < members.count; idx += 1)
{
TG_Member *member = &members.v[idx];
if(idx+1 < members.count)
{
U64 member_byte_size = tg_byte_size_from_graph_raddbg_key(graph, rdbg, member->type_key);
Rng1U64 member_byte_range = r1u64(member->off, member->off + member_byte_size);
if(member[1].off > member_byte_range.max)
{
PaddingNode *n = push_array(scratch.arena, PaddingNode, 1);
SLLQueuePush(first_padding, last_padding, n);
n->off = member_byte_range.max;
n->size = member[1].off - member_byte_range.max;
n->prev_member_idx = idx;
padding_count += 1;
}
}
}
}
//- rjf: produce new members array, if we have any padding
if(padding_count != 0)
{
TG_MemberArray new_members = {0};
new_members.count = members.count + padding_count;
new_members.v = push_array(arena, TG_Member, new_members.count);
MemoryCopy(new_members.v, members.v, sizeof(TG_Member)*members.count);
U64 padding_idx = 0;
for(PaddingNode *n = first_padding; n != 0; n = n->next)
{
if(members.count+padding_idx > n->prev_member_idx+1)
{
MemoryCopy(new_members.v + n->prev_member_idx + 2,
new_members.v + n->prev_member_idx + 1,
sizeof(TG_Member) * (members.count + padding_idx - (n->prev_member_idx+1)));
}
TG_Member *padding_member = &new_members.v[n->prev_member_idx+1];
MemoryZeroStruct(padding_member);
padding_member->kind = TG_MemberKind_Padding;
padding_member->type_key = tg_cons_type_make(graph, TG_Kind_Array, tg_key_basic(TG_Kind_U8), n->size);
padding_member->off = n->off;
padding_member->name = str8_lit("[padding]");
padding_idx += 1;
}
members = new_members;
}
scratch_end(scratch);
return members;
}
+2
View File
@@ -99,6 +99,7 @@ typedef enum TG_MemberKind
TG_MemberKind_Base,
TG_MemberKind_VirtualBase,
TG_MemberKind_NestedType,
TG_MemberKind_Padding,
TG_MemberKind_COUNT
}
TG_MemberKind;
@@ -232,6 +233,7 @@ internal TG_Key tg_ptee_from_graph_raddbg_key(TG_Graph *graph, RADDBG_Parsed *rd
internal TG_Key tg_unwrapped_from_graph_raddbg_key(TG_Graph *graph, RADDBG_Parsed *rdbg, TG_Key key);
internal U64 tg_byte_size_from_graph_raddbg_key(TG_Graph *graph, RADDBG_Parsed *rdbg, TG_Key key);
internal TG_Kind tg_kind_from_key(TG_Key key);
internal TG_Member *tg_member_copy(Arena *arena, TG_Member *src);
internal TG_MemberArray tg_members_from_graph_raddbg_key(Arena *arena, TG_Graph *graph, RADDBG_Parsed *rdbg, TG_Key key);
internal TG_MemberArray tg_data_members_from_graph_raddbg_key(Arena *arena, TG_Graph *graph, RADDBG_Parsed *rdbg, TG_Key key);
internal void tg_lhs_string_from_key(Arena *arena, TG_Graph *graph, RADDBG_Parsed *rdbg, TG_Key key, String8List *out, U32 prec, B32 skip_return);
+9 -9
View File
@@ -51,15 +51,15 @@ TG_KindTable:
{Function "" 0 }
{Method "" 0 }
{MemberPtr "" 0 }
{Struct "" 0 }
{Class "" 0 }
{Union "" 0 }
{Enum "" 0 }
{Alias "" 0 }
{IncompleteStruct "" 0 }
{IncompleteUnion "" 0 }
{IncompleteClass "" 0 }
{IncompleteEnum "" 0 }
{Struct "struct" 0 }
{Class "class" 0 }
{Union "union" 0 }
{Enum "enum" 0 }
{Alias "typedef" 0 }
{IncompleteStruct "struct" 0 }
{IncompleteUnion "union" 0 }
{IncompleteClass "class" 0 }
{IncompleteEnum "enum" 0 }
{Bitfield "" 0 }
{Variadic "" 0 }
}
+20 -10
View File
@@ -141,18 +141,19 @@ internal UI_BOX_CUSTOM_DRAW(ui_line_edit_draw)
TxtPt mark = draw_data->mark;
F32 cursor_pixel_off = f_dim_from_tag_size_string(font, font_size, str8_prefix(edited_string, cursor.column-1)).x + font_size/8.f;
F32 mark_pixel_off = f_dim_from_tag_size_string(font, font_size, str8_prefix(edited_string, mark.column-1)).x + font_size/8.f;
F32 cursor_thickness = ClampBot(4.f, font_size/6.f);
Rng2F32 cursor_rect =
{
text_position.x-ClampBot(2.f, font_size/4.f) + cursor_pixel_off,
text_position.x-cursor_thickness*0.40f + cursor_pixel_off,
box->rect.y0+4.f,
text_position.x+ClampBot(2.f, font_size/4.f) + cursor_pixel_off,
text_position.x+cursor_thickness*0.60f + cursor_pixel_off,
box->rect.y1-4.f,
};
Rng2F32 mark_rect =
{
text_position.x-2.f + mark_pixel_off,
text_position.x-cursor_thickness*0.40f + mark_pixel_off,
box->rect.y0+2.f,
text_position.x+2.f + mark_pixel_off,
text_position.x+cursor_thickness*0.60f + mark_pixel_off,
box->rect.y1-2.f,
};
Rng2F32 select_rect = union_2f32(cursor_rect, mark_rect);
@@ -173,6 +174,8 @@ ui_line_edit(TxtPt *cursor, TxtPt *mark, U8 *edit_buffer, U64 edit_buffer_size,
ui_push_focus_active(is_auto_focus_active ? UI_FocusKind_On : UI_FocusKind_Null);
B32 is_focus_hot = ui_is_focus_hot();
B32 is_focus_active = ui_is_focus_active();
B32 is_focus_hot_disabled = (!is_focus_hot && ui_top_focus_hot() == UI_FocusKind_On);
B32 is_focus_active_disabled = (!is_focus_active && ui_top_focus_active() == UI_FocusKind_On);
//- rjf: build top-level box
ui_set_next_hover_cursor(is_focus_active ? OS_Cursor_IBar : OS_Cursor_HandPoint);
@@ -182,7 +185,7 @@ ui_line_edit(TxtPt *cursor, TxtPt *mark, U8 *edit_buffer, U64 edit_buffer_size,
UI_BoxFlag_ClickToFocus|
((is_auto_focus_hot || is_auto_focus_active)*UI_BoxFlag_KeyboardClickable)|
UI_BoxFlag_DrawHotEffects|
is_focus_active*(UI_BoxFlag_Clip|UI_BoxFlag_AllowOverflowX|UI_BoxFlag_ViewClamp),
(is_focus_active || is_focus_active_disabled)*(UI_BoxFlag_Clip|UI_BoxFlag_AllowOverflowX|UI_BoxFlag_ViewClamp),
key);
//- rjf: take navigation actions for editing
@@ -239,7 +242,7 @@ ui_line_edit(TxtPt *cursor, TxtPt *mark, U8 *edit_buffer, U64 edit_buffer_size,
UI_Parent(box)
{
String8 edit_string = str8(edit_buffer, edit_string_size_out[0]);
if(!is_focus_active)
if(!is_focus_active && !is_focus_active_disabled)
{
String8 display_string = ui_display_part_from_key_string(string);
if(pre_edit_value.size != 0)
@@ -846,6 +849,8 @@ ui_pane_end(void)
thread_static U64 ui_ts_col_pct_count = 0;
thread_static F32 *ui_ts_col_pcts_stable = 0;
thread_static U64 ui_ts_vector_idx = 0;
thread_static U64 ui_ts_cell_idx = 0;
internal void
ui_table_begin(U64 column_pct_count, F32 **column_pcts, String8 string)
@@ -957,6 +962,8 @@ ui_table_begin(U64 column_pct_count, F32 **column_pcts, String8 string)
{
ui_ts_col_pcts_stable[idx] = *column_pcts[idx];
}
ui_ts_vector_idx = 0;
}
internal void
@@ -983,6 +990,8 @@ ui_named_table_vector_begin(String8 string)
ui_set_next_pref_width(ui_pct(1, 0));
ui_set_next_child_layout_axis(Axis2_X);
UI_Box *vector = ui_build_box_from_string(UI_BoxFlag_DrawSideBottom, string);
ui_ts_vector_idx += 1;
ui_ts_cell_idx = 0;
ui_push_parent(vector);
return vector;
}
@@ -1004,7 +1013,7 @@ internal UI_Box *
ui_table_vector_begin(void)
{
UI_Box *table = ui_top_parent();
UI_Box *vector = ui_named_table_vector_beginf("###tbl_vec_%p_%I64u", table, table->child_count);
UI_Box *vector = ui_named_table_vector_beginf("###tbl_vec_%p_%I64u", table, ui_ts_vector_idx);
return vector;
}
@@ -1019,7 +1028,7 @@ internal UI_Box *
ui_table_cell_begin(void)
{
UI_Box *vector = ui_top_parent();
U64 column_idx = vector->child_count;
U64 column_idx = ui_ts_cell_idx;
F32 width_pct = column_idx < ui_ts_col_pct_count ? ui_ts_col_pcts_stable[column_idx] : 1.f;
return ui_table_cell_sized_begin(ui_pct(width_pct, 0));
}
@@ -1035,10 +1044,11 @@ internal UI_Box *
ui_table_cell_sized_begin(UI_Size size)
{
UI_Box *vector = ui_top_parent();
U64 column_idx = vector->child_count;
U64 column_idx = ui_ts_cell_idx;
ui_ts_cell_idx += 1;
ui_set_next_pref_width(size);
ui_set_next_child_layout_axis(Axis2_X);
UI_Box *cell = ui_build_box_from_stringf((column_idx > 0 ? UI_BoxFlag_DrawSideLeft : 0), "###tbl_cell_%p_%I64u", vector, vector->child_count);
UI_Box *cell = ui_build_box_from_stringf((column_idx > 0 ? UI_BoxFlag_DrawSideLeft : 0), "###tbl_cell_%p_%I64u", vector, ui_ts_cell_idx);
ui_push_parent(cell);
return cell;
}
+62 -30
View File
@@ -646,12 +646,21 @@ ui_begin_build(OS_EventList *events, OS_Handle window, UI_NavActionList *nav_act
ui_state->ctx_menu_changed = 0;
}
//- rjf: detect mouse-moves
for(OS_Event *e = events->first; e != 0; e = e->next)
{
if(e->kind == OS_EventKind_MouseMove && os_handle_match(e->window, window))
{
ui_state->last_time_mousemoved_us = os_now_microseconds();
}
}
//- rjf: fill build phase parameters
{
ui_state->events = events;
ui_state->window = window;
ui_state->nav_actions = nav_actions;
ui_state->mouse = os_mouse_from_window(window);
ui_state->mouse = (os_window_is_focused(window) || ui_state->last_time_mousemoved_us+500000 >= os_now_microseconds()) ? os_mouse_from_window(window) : v2f32(-100, -100);
ui_state->animation_dt = animation_dt;
MemoryZeroStruct(&ui_state->icon_info);
ui_state->icon_info.icon_font = icon_info->icon_font;
@@ -922,8 +931,7 @@ ui_begin_build(OS_EventList *events, OS_Handle window, UI_NavActionList *nav_act
}
//- rjf: setup parent box for tooltip
Vec2F32 mouse = ui_state->mouse;
UI_FixedX(mouse.x+15.f) UI_FixedY(mouse.y) UI_PrefWidth(ui_children_sum(1.f)) UI_PrefHeight(ui_children_sum(1.f))
UI_FixedX(ui_state->mouse.x+15.f) UI_FixedY(ui_state->mouse.y) UI_PrefWidth(ui_children_sum(1.f)) UI_PrefHeight(ui_children_sum(1.f))
{
ui_set_next_child_layout_axis(Axis2_Y);
ui_state->tooltip_root = ui_build_box_from_stringf(0, "###tooltip_%I64x", window.u64[0]);
@@ -1151,6 +1159,7 @@ ui_end_build(void)
box->first_touched_build_index == box->first_disabled_build_index);
B32 is_focus_hot = !!(box->flags & UI_BoxFlag_FocusHot) && !(box->flags & UI_BoxFlag_FocusHotDisabled);
B32 is_focus_active = !!(box->flags & UI_BoxFlag_FocusActive) && !(box->flags & UI_BoxFlag_FocusActiveDisabled);
B32 is_focus_active_disabled = !!(box->flags & UI_BoxFlag_FocusActiveDisabled);
// rjf: determine rates
F32 hot_rate = fast_rate;
@@ -1165,15 +1174,16 @@ ui_end_build(void)
box_is_animating = (box_is_animating || abs_f32((F32)is_disabled - box->disabled_t) > 0.01f);
box_is_animating = (box_is_animating || abs_f32((F32)is_focus_hot - box->focus_hot_t) > 0.01f);
box_is_animating = (box_is_animating || abs_f32((F32)is_focus_active - box->focus_active_t) > 0.01f);
box_is_animating = (box_is_animating || abs_f32((F32)is_focus_active_disabled - box->focus_active_disabled_t) > 0.01f);
box_is_animating = (box_is_animating || abs_f32(box->view_off_target.x - box->view_off.x) > 0.5f);
box_is_animating = (box_is_animating || abs_f32(box->view_off_target.y - box->view_off.y) > 0.5f);
if(box->flags & UI_BoxFlag_AnimatePosX)
{
box_is_animating = (box_is_animating || fabsf(box->fixed_position_animated.x - box->fixed_position.x) > 0.5f);
box_is_animating = (box_is_animating || abs_f32(box->fixed_position_animated.x - box->fixed_position.x) > 0.5f);
}
if(box->flags & UI_BoxFlag_AnimatePosY)
{
box_is_animating = (box_is_animating || fabsf(box->fixed_position_animated.y - box->fixed_position.y) > 0.5f);
box_is_animating = (box_is_animating || abs_f32(box->fixed_position_animated.y - box->fixed_position.y) > 0.5f);
}
ui_state->is_animating = (ui_state->is_animating || box_is_animating);
#if 0 // NOTE(rjf): enable to debug animation-causing-frames (or not)
@@ -1185,21 +1195,22 @@ ui_end_build(void)
#endif
// rjf: animate interaction transition states
box->hot_t += hot_rate * ((F32)is_hot - box->hot_t);
box->active_t += active_rate * ((F32)is_active - box->active_t);
box->disabled_t += disabled_rate * ((F32)is_disabled - box->disabled_t);
box->focus_hot_t += focus_rate * ((F32)is_focus_hot - box->focus_hot_t);
box->focus_active_t += focus_rate * ((F32)is_focus_active - box->focus_active_t);
box->hot_t += hot_rate * ((F32)is_hot - box->hot_t);
box->active_t += active_rate * ((F32)is_active - box->active_t);
box->disabled_t += disabled_rate * ((F32)is_disabled - box->disabled_t);
box->focus_hot_t += focus_rate * ((F32)is_focus_hot - box->focus_hot_t);
box->focus_active_t += focus_rate * ((F32)is_focus_active - box->focus_active_t);
box->focus_active_disabled_t += focus_rate * ((F32)is_focus_active_disabled - box->focus_active_disabled_t);
// rjf: animate positions
{
box->fixed_position_animated.x += fast_rate * (box->fixed_position.x - box->fixed_position_animated.x);
box->fixed_position_animated.y += fast_rate * (box->fixed_position.y - box->fixed_position_animated.y);
if(fabsf(box->fixed_position.x - box->fixed_position_animated.x) < 1)
if(abs_f32(box->fixed_position.x - box->fixed_position_animated.x) < 1)
{
box->fixed_position_animated.x = box->fixed_position.x;
}
if(fabsf(box->fixed_position.y - box->fixed_position_animated.y) < 1)
if(abs_f32(box->fixed_position.y - box->fixed_position_animated.y) < 1)
{
box->fixed_position_animated.y = box->fixed_position.y;
}
@@ -1213,19 +1224,19 @@ ui_end_build(void)
ClampBot(0, box->view_bounds.x - box->fixed_size.x),
ClampBot(0, box->view_bounds.y - box->fixed_size.y),
};
box->view_off_target.x = Clamp(0, box->view_off_target.x, max_view_off_target.x);
box->view_off_target.y = Clamp(0, box->view_off_target.y, max_view_off_target.y);
if(box->flags & UI_BoxFlag_ViewClampX) { box->view_off_target.x = Clamp(0, box->view_off_target.x, max_view_off_target.x); }
if(box->flags & UI_BoxFlag_ViewClampY) { box->view_off_target.y = Clamp(0, box->view_off_target.y, max_view_off_target.y); }
}
// rjf: animate view offset
{
box->view_off.x += fast_rate * (box->view_off_target.x - box->view_off.x);
box->view_off.y += fast_rate * (box->view_off_target.y - box->view_off.y);
if(fabsf(box->view_off.x - box->view_off_target.x) < 2)
if(abs_f32(box->view_off.x - box->view_off_target.x) < 2)
{
box->view_off.x = box->view_off_target.x;
}
if(fabsf(box->view_off.y - box->view_off_target.y) < 2)
if(abs_f32(box->view_off.y - box->view_off_target.y) < 2)
{
box->view_off.y = box->view_off_target.y;
}
@@ -1302,6 +1313,8 @@ ui_end_build(void)
}
//- rjf: hovering possibly-truncated drawn text -> store text
if(ui_key_match(ui_key_zero(), ui_state->active_box_key[Side_Min]) &&
ui_key_match(ui_key_zero(), ui_state->active_box_key[Side_Max]))
{
B32 found = 0;
for(UI_Box *box = ui_state->root, *next = 0; !ui_box_is_nil(box); box = next)
@@ -1316,12 +1329,13 @@ ui_end_build(void)
String8 box_display_string = ui_box_display_string(b);
Vec2F32 text_pos = ui_box_text_position(b);
Vec2F32 drawn_text_dim = b->display_string_runs.dim;
if(drawn_text_dim.x > dim_2f32(b->rect).x &&
contains_2f32(r2f32p(text_pos.x,
b->rect.y0,
Min(text_pos.x+drawn_text_dim.x, b->rect.x1),
b->rect.y1),
ui_state->mouse))
B32 text_is_truncated = (drawn_text_dim.x + text_pos.x > b->rect.x1);
B32 mouse_is_hovering = contains_2f32(r2f32p(text_pos.x,
b->rect.y0,
Min(text_pos.x+drawn_text_dim.x, b->rect.x1),
b->rect.y1),
ui_state->mouse);
if(text_is_truncated && mouse_is_hovering)
{
if(!str8_match(box_display_string, ui_state->string_hover_string, 0))
{
@@ -1335,7 +1349,7 @@ ui_end_build(void)
goto break_all_hover_string;
}
}
if(b != box && contains_2f32(b->rect, ui_state->mouse))
if(b != box && contains_2f32(b->rect, ui_state->mouse) && b->flags & UI_BoxFlag_DrawText)
{
goto break_all_hover_string;
}
@@ -2195,6 +2209,13 @@ ui_box_equip_display_string_fancy_runs(UI_Box *box, String8 string, D_FancyRunLi
box->display_string_runs = d_fancy_run_list_copy(ui_build_arena(), runs);
}
internal inline void
ui_box_equip_fuzzy_match_ranges(UI_Box *box, FuzzyMatchRangeList *matches)
{
box->flags |= UI_BoxFlag_HasFuzzyMatchRanges;
box->fuzzy_match_ranges = fuzzy_match_range_list_copy(ui_build_arena(), matches);
}
internal void
ui_box_equip_draw_bucket(UI_Box *box, D_Bucket *bucket)
{
@@ -2236,7 +2257,7 @@ ui_box_text_position(UI_Box *box)
F_Tag font = box->font;
F32 font_size = box->font_size;
F_Metrics font_metrics = f_metrics_from_tag_size(font, font_size);
result.y = ceilf((box->rect.p0.y + box->rect.p1.y)/2.f + (font_metrics.capital_height/2));
result.y = ceil_f32((box->rect.p0.y + box->rect.p1.y)/2.f + (font_metrics.capital_height/2) - font_metrics.line_gap/2);
switch(box->text_align)
{
default:
@@ -2546,6 +2567,14 @@ ui_signal_from_box(UI_Box *box)
{
Swap(F32, delta.x, delta.y);
}
if(!(box->flags & UI_BoxFlag_ViewScrollX))
{
delta.x = 0;
}
if(!(box->flags & UI_BoxFlag_ViewScrollY))
{
delta.y = 0;
}
os_eat_event(events, event);
box->view_off_target.x += delta.x;
box->view_off_target.y += delta.y;
@@ -2553,13 +2582,16 @@ ui_signal_from_box(UI_Box *box)
}
}
}
Vec2F32 max_view_off_target =
if(box->flags & UI_BoxFlag_ViewClamp)
{
ClampBot(0, box->view_bounds.x - box->fixed_size.x),
ClampBot(0, box->view_bounds.y - box->fixed_size.y),
};
box->view_off_target.x = Clamp(0, box->view_off_target.x, max_view_off_target.x);
box->view_off_target.y = Clamp(0, box->view_off_target.y, max_view_off_target.y);
Vec2F32 max_view_off_target =
{
ClampBot(0, box->view_bounds.x - box->fixed_size.x),
ClampBot(0, box->view_bounds.y - box->fixed_size.y),
};
if(box->flags & UI_BoxFlag_ViewClampX) { box->view_off_target.x = Clamp(0, box->view_off_target.x, max_view_off_target.x); }
if(box->flags & UI_BoxFlag_ViewClampY) { box->view_off_target.y = Clamp(0, box->view_off_target.y, max_view_off_target.y); }
}
}
//- rjf: focus + clicks
+51 -43
View File
@@ -188,52 +188,55 @@ typedef U64 UI_BoxFlags;
# define UI_BoxFlag_KeyboardClickable (UI_BoxFlags)(1ull<<1)
# define UI_BoxFlag_ClickToFocus (UI_BoxFlags)(1ull<<2)
# define UI_BoxFlag_Scroll (UI_BoxFlags)(1ull<<3)
# define UI_BoxFlag_ViewScroll (UI_BoxFlags)(1ull<<4)
# define UI_BoxFlag_ViewClamp (UI_BoxFlags)(1ull<<5)
# define UI_BoxFlag_FocusHot (UI_BoxFlags)(1ull<<6)
# define UI_BoxFlag_FocusActive (UI_BoxFlags)(1ull<<7)
# define UI_BoxFlag_FocusHotDisabled (UI_BoxFlags)(1ull<<8)
# define UI_BoxFlag_FocusActiveDisabled (UI_BoxFlags)(1ull<<9)
# define UI_BoxFlag_DefaultFocusNavX (UI_BoxFlags)(1ull<<10)
# define UI_BoxFlag_DefaultFocusNavY (UI_BoxFlags)(1ull<<11)
# define UI_BoxFlag_DefaultFocusEdit (UI_BoxFlags)(1ull<<12)
# define UI_BoxFlag_FocusNavSkip (UI_BoxFlags)(1ull<<13)
# define UI_BoxFlag_Disabled (UI_BoxFlags)(1ull<<14)
# define UI_BoxFlag_ViewScrollX (UI_BoxFlags)(1ull<<4)
# define UI_BoxFlag_ViewScrollY (UI_BoxFlags)(1ull<<5)
# define UI_BoxFlag_ViewClampX (UI_BoxFlags)(1ull<<6)
# define UI_BoxFlag_ViewClampY (UI_BoxFlags)(1ull<<7)
# define UI_BoxFlag_FocusHot (UI_BoxFlags)(1ull<<8)
# define UI_BoxFlag_FocusActive (UI_BoxFlags)(1ull<<9)
# define UI_BoxFlag_FocusHotDisabled (UI_BoxFlags)(1ull<<10)
# define UI_BoxFlag_FocusActiveDisabled (UI_BoxFlags)(1ull<<11)
# define UI_BoxFlag_DefaultFocusNavX (UI_BoxFlags)(1ull<<12)
# define UI_BoxFlag_DefaultFocusNavY (UI_BoxFlags)(1ull<<13)
# define UI_BoxFlag_DefaultFocusEdit (UI_BoxFlags)(1ull<<14)
# define UI_BoxFlag_FocusNavSkip (UI_BoxFlags)(1ull<<15)
# define UI_BoxFlag_Disabled (UI_BoxFlags)(1ull<<16)
//- rjf: layout
# define UI_BoxFlag_FloatingX (UI_BoxFlags)(1ull<<15)
# define UI_BoxFlag_FloatingY (UI_BoxFlags)(1ull<<16)
# define UI_BoxFlag_FixedWidth (UI_BoxFlags)(1ull<<17)
# define UI_BoxFlag_FixedHeight (UI_BoxFlags)(1ull<<18)
# define UI_BoxFlag_AllowOverflowX (UI_BoxFlags)(1ull<<19)
# define UI_BoxFlag_AllowOverflowY (UI_BoxFlags)(1ull<<20)
# define UI_BoxFlag_SkipViewOffX (UI_BoxFlags)(1ull<<21)
# define UI_BoxFlag_SkipViewOffY (UI_BoxFlags)(1ull<<22)
# define UI_BoxFlag_FloatingX (UI_BoxFlags)(1ull<<17)
# define UI_BoxFlag_FloatingY (UI_BoxFlags)(1ull<<18)
# define UI_BoxFlag_FixedWidth (UI_BoxFlags)(1ull<<19)
# define UI_BoxFlag_FixedHeight (UI_BoxFlags)(1ull<<20)
# define UI_BoxFlag_AllowOverflowX (UI_BoxFlags)(1ull<<21)
# define UI_BoxFlag_AllowOverflowY (UI_BoxFlags)(1ull<<22)
# define UI_BoxFlag_SkipViewOffX (UI_BoxFlags)(1ull<<23)
# define UI_BoxFlag_SkipViewOffY (UI_BoxFlags)(1ull<<24)
//- rjf: appearance / animation
# define UI_BoxFlag_DrawDropShadow (UI_BoxFlags)(1ull<<23)
# define UI_BoxFlag_DrawBackgroundBlur (UI_BoxFlags)(1ull<<24)
# define UI_BoxFlag_DrawBackground (UI_BoxFlags)(1ull<<25)
# define UI_BoxFlag_DrawBorder (UI_BoxFlags)(1ull<<26)
# define UI_BoxFlag_DrawSideTop (UI_BoxFlags)(1ull<<27)
# define UI_BoxFlag_DrawSideBottom (UI_BoxFlags)(1ull<<28)
# define UI_BoxFlag_DrawSideLeft (UI_BoxFlags)(1ull<<29)
# define UI_BoxFlag_DrawSideRight (UI_BoxFlags)(1ull<<30)
# define UI_BoxFlag_DrawText (UI_BoxFlags)(1ull<<31)
# define UI_BoxFlag_DrawTextFastpathCodepoint (UI_BoxFlags)(1ull<<32)
# define UI_BoxFlag_DrawHotEffects (UI_BoxFlags)(1ull<<33)
# define UI_BoxFlag_DrawActiveEffects (UI_BoxFlags)(1ull<<34)
# define UI_BoxFlag_DrawOverlay (UI_BoxFlags)(1ull<<35)
# define UI_BoxFlag_DrawBucket (UI_BoxFlags)(1ull<<36)
# define UI_BoxFlag_Clip (UI_BoxFlags)(1ull<<37)
# define UI_BoxFlag_AnimatePosX (UI_BoxFlags)(1ull<<38)
# define UI_BoxFlag_AnimatePosY (UI_BoxFlags)(1ull<<39)
# define UI_BoxFlag_DisableTextTrunc (UI_BoxFlags)(1ull<<40)
# define UI_BoxFlag_DisableIDString (UI_BoxFlags)(1ull<<41)
# define UI_BoxFlag_DisableFocusViz (UI_BoxFlags)(1ull<<42)
# define UI_BoxFlag_RequireFocusBackground (UI_BoxFlags)(1ull<<43)
# define UI_BoxFlag_HasDisplayString (UI_BoxFlags)(1ull<<44)
# define UI_BoxFlag_RoundChildrenByParent (UI_BoxFlags)(1ull<<45)
# define UI_BoxFlag_DrawDropShadow (UI_BoxFlags)(1ull<<25)
# define UI_BoxFlag_DrawBackgroundBlur (UI_BoxFlags)(1ull<<26)
# define UI_BoxFlag_DrawBackground (UI_BoxFlags)(1ull<<27)
# define UI_BoxFlag_DrawBorder (UI_BoxFlags)(1ull<<28)
# define UI_BoxFlag_DrawSideTop (UI_BoxFlags)(1ull<<29)
# define UI_BoxFlag_DrawSideBottom (UI_BoxFlags)(1ull<<30)
# define UI_BoxFlag_DrawSideLeft (UI_BoxFlags)(1ull<<31)
# define UI_BoxFlag_DrawSideRight (UI_BoxFlags)(1ull<<32)
# define UI_BoxFlag_DrawText (UI_BoxFlags)(1ull<<33)
# define UI_BoxFlag_DrawTextFastpathCodepoint (UI_BoxFlags)(1ull<<34)
# define UI_BoxFlag_DrawHotEffects (UI_BoxFlags)(1ull<<35)
# define UI_BoxFlag_DrawActiveEffects (UI_BoxFlags)(1ull<<36)
# define UI_BoxFlag_DrawOverlay (UI_BoxFlags)(1ull<<37)
# define UI_BoxFlag_DrawBucket (UI_BoxFlags)(1ull<<38)
# define UI_BoxFlag_Clip (UI_BoxFlags)(1ull<<39)
# define UI_BoxFlag_AnimatePosX (UI_BoxFlags)(1ull<<40)
# define UI_BoxFlag_AnimatePosY (UI_BoxFlags)(1ull<<41)
# define UI_BoxFlag_DisableTextTrunc (UI_BoxFlags)(1ull<<42)
# define UI_BoxFlag_DisableIDString (UI_BoxFlags)(1ull<<43)
# define UI_BoxFlag_DisableFocusViz (UI_BoxFlags)(1ull<<44)
# define UI_BoxFlag_RequireFocusBackground (UI_BoxFlags)(1ull<<45)
# define UI_BoxFlag_HasDisplayString (UI_BoxFlags)(1ull<<46)
# define UI_BoxFlag_HasFuzzyMatchRanges (UI_BoxFlags)(1ull<<47)
# define UI_BoxFlag_RoundChildrenByParent (UI_BoxFlags)(1ull<<48)
//- rjf: bundles
# define UI_BoxFlag_Clickable (UI_BoxFlag_MouseClickable|UI_BoxFlag_KeyboardClickable)
@@ -242,6 +245,8 @@ typedef U64 UI_BoxFlags;
# define UI_BoxFlag_FixedSize (UI_BoxFlag_FixedWidth|UI_BoxFlag_FixedHeight)
# define UI_BoxFlag_AllowOverflow (UI_BoxFlag_AllowOverflowX|UI_BoxFlag_AllowOverflowY)
# define UI_BoxFlag_AnimatePos (UI_BoxFlag_AnimatePosX|UI_BoxFlag_AnimatePosY)
# define UI_BoxFlag_ViewScroll (UI_BoxFlag_ViewScrollX|UI_BoxFlag_ViewScrollY)
# define UI_BoxFlag_ViewClamp (UI_BoxFlag_ViewClampX|UI_BoxFlag_ViewClampY)
//}
typedef struct UI_Box UI_Box;
@@ -290,7 +295,7 @@ struct UI_Box
Rng2F32 rect;
Vec2F32 fixed_position_animated;
Vec2F32 position_delta;
U64 num_focus_children;
FuzzyMatchRangeList fuzzy_match_ranges;
//- rjf: persistent data
U64 first_touched_build_index;
@@ -301,6 +306,7 @@ struct UI_Box
F32 disabled_t;
F32 focus_hot_t;
F32 focus_active_t;
F32 focus_active_disabled_t;
Vec2F32 view_off;
Vec2F32 view_off_target;
Vec2F32 view_bounds;
@@ -421,6 +427,7 @@ struct UI_State
D_FancyRunList string_hover_fancy_runs;
U64 string_hover_begin_us;
U64 string_hover_build_index;
U64 last_time_mousemoved_us;
//- rjf: tooltip state
F32 tooltip_open_t;
@@ -601,6 +608,7 @@ internal UI_Box * ui_build_box_from_stringf(UI_BoxFlags flags, char *fm
internal inline void ui_box_equip_display_string(UI_Box *box, String8 string);
internal inline void ui_box_equip_display_fancy_strings(UI_Box *box, D_FancyStringList *strings);
internal inline void ui_box_equip_display_string_fancy_runs(UI_Box *box, String8 string, D_FancyRunList *runs);
internal inline void ui_box_equip_fuzzy_match_ranges(UI_Box *box, FuzzyMatchRangeList *matches);
internal inline void ui_box_equip_draw_bucket(UI_Box *box, D_Bucket *bucket);
internal inline void ui_box_equip_custom_draw(UI_Box *box, UI_BoxCustomDrawFunctionType *custom_draw, void *user_data);