Merge tag 'v0.9.24-alpha'

This commit is contained in:
ed
2025-10-23 23:36:21 -04:00
44 changed files with 2526 additions and 1170 deletions
+32
View File
@@ -1,3 +1,35 @@
# v0.9.24-alpha
## Debugger Changes
- Added the ability for the debugger to load, use, and evaluate using debug
info, even when not actively debugging. The debugger will now keep a process'
debug info loaded, even after the process ends. It stores the set of loaded
debug info files in the project configuration file, meaning it will also
automatically load the same debug info across many runs. Debug info can also
be loaded manually (without ever launching a process) with the
`Load Debug Info` command. There is also a new tab, `Debug Info`, which allows
viewing and managing the set of loaded debug info files.
- Improved the debugger's behavior when used as a drag & drop target, to allow
for debug info loading as an option (when relevant), and to better handle the
case where many files (potentially of different types) are dropped together.
- Improved debug info searching performance and reponsiveness in large projects.
- Fixed some crashes and incorrect results with the new `list` view.
- Fixed some cases where RDIs did not contain some basic types from their
originating PDBs.
- Allowed `.` and `->` operators to be used with array types.
- Fixed the debugger's treatment of quoted command line arguments when building
targets. In previous versions, calling `raddbg main.exe "foo bar baz"` would
create a target `main.exe` with arguments `foo bar baz` (dropping the quotes).
This is now fixed, such that the target's arguments string will also contain
the quotes, and pass them to the target when launched.
- Fixed the debugger not correctly responding (through font and UI scale) to DPI
changes.
- Fixed the debugger incorrectly generating conflicting source line info records
in PDB -> RDI conversion, which in some scenarios was preventing source line
maps from working (leading to breakpoint resolution failing).
- Other small fixes, improvements, and tweaks.
# v0.9.23-alpha # v0.9.23-alpha
## Debugger Changes ## Debugger Changes
+79 -3
View File
@@ -18,6 +18,9 @@ ac_init(void)
ac_shared->req_batches[idx].mutex = mutex_alloc(); ac_shared->req_batches[idx].mutex = mutex_alloc();
ac_shared->req_batches[idx].arena = arena_alloc(); ac_shared->req_batches[idx].arena = arena_alloc();
} }
ac_shared->cancel_thread = thread_launch(ac_cancel_thread_entry_point, 0);
ac_shared->cancel_thread_mutex = mutex_alloc();
mutex_take(ac_shared->cancel_thread_mutex);
} }
//////////////////////////////// ////////////////////////////////
@@ -138,9 +141,9 @@ ac_artifact_from_key_(Access *access, String8 key, AC_ArtifactParams *params, U6
node->key = str8_copy(stripe->arena, key); node->key = str8_copy(stripe->arena, key);
node->working_count = 1; node->working_count = 1;
node->evict_threshold_us = params->evict_threshold_us; node->evict_threshold_us = params->evict_threshold_us;
node->access_pt.last_time_touched_us = os_now_microseconds();
node->access_pt.last_update_idx_touched = update_tick_idx();
} }
node->access_pt.last_time_touched_us = os_now_microseconds();
node->access_pt.last_update_idx_touched = update_tick_idx();
// rjf: request // rjf: request
if(need_request) if(need_request)
@@ -161,8 +164,8 @@ ac_artifact_from_key_(Access *access, String8 key, AC_ArtifactParams *params, U6
} }
n->v.key = str8_copy(req_batch->arena, key); n->v.key = str8_copy(req_batch->arena, key);
n->v.gen = params->gen; n->v.gen = params->gen;
n->v.cancel_signal = &node->cancelled;
n->v.create = params->create; n->v.create = params->create;
n->v.cancel_signal = params->cancel_signal;
} }
cond_var_broadcast(async_tick_start_cond_var); cond_var_broadcast(async_tick_start_cond_var);
ins_atomic_u32_eval_assign(&async_loop_again, 1); ins_atomic_u32_eval_assign(&async_loop_again, 1);
@@ -210,6 +213,14 @@ ac_async_tick(void)
{ {
Temp scratch = scratch_begin(0, 0); Temp scratch = scratch_begin(0, 0);
//////////////////////////////
//- rjf: enable cancellation scanning
//
if(lane_idx() == 0)
{
mutex_drop(ac_shared->cancel_thread_mutex);
}
////////////////////////////// //////////////////////////////
//- rjf: do eviction pass across all caches //- rjf: do eviction pass across all caches
// //
@@ -574,5 +585,70 @@ ac_async_tick(void)
} }
lane_sync(); lane_sync();
//////////////////////////////
//- rjf: disable cancellation scanning
//
if(lane_idx() == 0)
{
mutex_take(ac_shared->cancel_thread_mutex);
}
scratch_end(scratch); scratch_end(scratch);
} }
////////////////////////////////
//~ rjf: Cancel Thread
internal void
ac_cancel_thread_entry_point(void *p)
{
for(;;)
{
os_sleep_milliseconds(50);
MutexScope(ac_shared->cancel_thread_mutex)
{
for EachIndex(cache_slot_idx, ac_shared->cache_slots_count)
{
Stripe *cache_stripe = stripe_from_slot_idx(&ac_shared->cache_stripes, cache_slot_idx);
RWMutexScope(cache_stripe->rw_mutex, 0)
{
for EachNode(cache, AC_Cache, ac_shared->cache_slots[cache_slot_idx])
{
Rng1U64 slot_range = lane_range(cache->slots_count);
for EachInRange(slot_idx, slot_range)
{
AC_Slot *slot = &cache->slots[slot_idx];
Stripe *stripe = stripe_from_slot_idx(&cache->stripes, slot_idx);
for(B32 write_mode = 0; write_mode <= 1; write_mode += 1)
{
B32 slot_has_work = 0;
RWMutexScope(stripe->rw_mutex, write_mode)
{
for(AC_Node *n = slot->first, *next = 0; n != 0; n = next)
{
next = n->next;
if(access_pt_is_expired(&n->access_pt, .time = n->evict_threshold_us) && ins_atomic_u64_eval(&n->working_count) > 0)
{
slot_has_work = 1;
if(!write_mode)
{
break;
}
else
{
n->cancelled = 1;
}
}
}
}
if(!slot_has_work)
{
break;
}
}
}
}
}
}
}
}
}
+9 -6
View File
@@ -37,7 +37,6 @@ struct AC_ArtifactParams
U64 gen; U64 gen;
U64 evict_threshold_us; U64 evict_threshold_us;
B32 *stale_out; B32 *stale_out;
B32 *cancel_signal;
AC_Flags flags; AC_Flags flags;
}; };
@@ -127,6 +126,10 @@ struct AC_Shared
// rjf: requests // rjf: requests
AC_RequestBatch req_batches[2]; // 0: high priority, 1: low priority AC_RequestBatch req_batches[2]; // 0: high priority, 1: low priority
// rjf: cancel thread
Thread cancel_thread;
Mutex cancel_thread_mutex;
}; };
//////////////////////////////// ////////////////////////////////
@@ -139,11 +142,6 @@ global AC_Shared *ac_shared = 0;
internal void ac_init(void); internal void ac_init(void);
////////////////////////////////
//~ rjf: Helpers
internal B32 ac_cancelled(void);
//////////////////////////////// ////////////////////////////////
//~ rjf: Cache Lookups //~ rjf: Cache Lookups
@@ -155,4 +153,9 @@ internal AC_Artifact ac_artifact_from_key_(Access *access, String8 key, AC_Artif
internal void ac_async_tick(void); internal void ac_async_tick(void);
////////////////////////////////
//~ rjf: Cancel Thread
internal void ac_cancel_thread_entry_point(void *p);
#endif // ARTIFACT_CACHE_H #endif // ARTIFACT_CACHE_H
+1 -1
View File
@@ -159,7 +159,7 @@
#endif #endif
#if !defined(BUILD_VERSION_PATCH) #if !defined(BUILD_VERSION_PATCH)
# define BUILD_VERSION_PATCH 23 # define BUILD_VERSION_PATCH 24
#endif #endif
#define BUILD_VERSION_STRING_LITERAL Stringify(BUILD_VERSION_MAJOR) "." Stringify(BUILD_VERSION_MINOR) "." Stringify(BUILD_VERSION_PATCH) #define BUILD_VERSION_STRING_LITERAL Stringify(BUILD_VERSION_MAJOR) "." Stringify(BUILD_VERSION_MINOR) "." Stringify(BUILD_VERSION_PATCH)
+6 -1
View File
@@ -108,6 +108,11 @@ main_thread_base_entry_point(int arguments_count, char **arguments)
U64 num_async_threads = os_get_system_info()->logical_processor_count; U64 num_async_threads = os_get_system_info()->logical_processor_count;
U64 num_main_threads_clamped = Min(num_async_threads, num_main_threads); U64 num_main_threads_clamped = Min(num_async_threads, num_main_threads);
num_async_threads -= num_main_threads_clamped; num_async_threads -= num_main_threads_clamped;
String8 num_async_threads_string = cmd_line_string(&cmdline, str8_lit("async_thread_count"));
if(num_async_threads_string.size != 0)
{
try_u64_from_str8_c_rules(num_async_threads_string, &num_async_threads);
}
num_async_threads = Max(1, num_async_threads); num_async_threads = Max(1, num_async_threads);
Barrier barrier = barrier_alloc(num_async_threads); Barrier barrier = barrier_alloc(num_async_threads);
LaneCtx *lane_ctxs = push_array(scratch.arena, LaneCtx, num_async_threads); LaneCtx *lane_ctxs = push_array(scratch.arena, LaneCtx, num_async_threads);
@@ -189,7 +194,7 @@ async_thread_entry_point(void *params)
{ {
if(!ins_atomic_u32_eval(&async_loop_again)) if(!ins_atomic_u32_eval(&async_loop_again))
{ {
MutexScope(async_tick_start_mutex) cond_var_wait(async_tick_start_cond_var, async_tick_start_mutex, os_now_microseconds()+100000); MutexScope(async_tick_start_mutex) cond_var_wait(async_tick_start_cond_var, async_tick_start_mutex, os_now_microseconds()+1000000);
} }
ins_atomic_u32_eval_assign(&async_loop_again, 0); ins_atomic_u32_eval_assign(&async_loop_again, 0);
ins_atomic_u32_eval_assign(&async_loop_again_high_priority, 0); ins_atomic_u32_eval_assign(&async_loop_again_high_priority, 0);
+24 -9
View File
@@ -85,25 +85,40 @@ correct_slash_from_char(U8 c)
internal U64 internal U64
cstring8_length(U8 *c) cstring8_length(U8 *c)
{ {
U8 *p = c; U64 length = 0;
for (;*p != 0; p += 1); if(c)
return (p - c); {
U8 *p = c;
for (;*p != 0; p += 1);
length = (U64)(p - c);
}
return length;
} }
internal U64 internal U64
cstring16_length(U16 *c) cstring16_length(U16 *c)
{ {
U16 *p = c; U64 length = 0;
for (;*p != 0; p += 1); if(c)
return (p - c); {
U16 *p = c;
for (;*p != 0; p += 1);
length = (U64)(p - c);
}
return length;
} }
internal U64 internal U64
cstring32_length(U32 *c) cstring32_length(U32 *c)
{ {
U32 *p = c; U64 length = 0;
for (;*p != 0; p += 1); if(c)
return (p - c); {
U32 *p = c;
for (;*p != 0; p += 1);
length = (U64)(p - c);
}
return length;
} }
//////////////////////////////// ////////////////////////////////
+1 -1
View File
@@ -120,7 +120,7 @@ internal void access_touch(Access *access, AccessPt *pt, CondVar cv);
//- rjf: access points //- rjf: access points
internal B32 access_pt_is_expired_(AccessPt *pt, AccessPtExpireParams *params); internal B32 access_pt_is_expired_(AccessPt *pt, AccessPtExpireParams *params);
#define access_pt_is_expired(pt, ...) access_pt_is_expired_((pt), &(AccessPtExpireParams){.time = 2000000, .update_idxs = 10, __VA_ARGS__}) #define access_pt_is_expired(pt, ...) access_pt_is_expired_((pt), &(AccessPtExpireParams){.time = 2000000, .update_idxs = 2, __VA_ARGS__})
//- rjf: progress counters //- rjf: progress counters
#define set_progress_ptr(ptr) (tctx_selected()->progress_counter_ptr = (ptr)) #define set_progress_ptr(ptr) (tctx_selected()->progress_counter_ptr = (ptr))
+34 -14
View File
@@ -3189,7 +3189,7 @@ ctrl_thread__entry_point(void *p)
CTRL_Entity *module = ctrl_entity_from_handle(entity_ctx, msg->entity); CTRL_Entity *module = ctrl_entity_from_handle(entity_ctx, msg->entity);
CTRL_Entity *debug_info_path = ctrl_entity_child_from_kind(module, CTRL_EntityKind_DebugInfoPath); CTRL_Entity *debug_info_path = ctrl_entity_child_from_kind(module, CTRL_EntityKind_DebugInfoPath);
DI_Key old_dbgi_key = di_key_from_path_timestamp(debug_info_path->string, debug_info_path->timestamp); DI_Key old_dbgi_key = di_key_from_path_timestamp(debug_info_path->string, debug_info_path->timestamp);
di_close(old_dbgi_key); di_close(old_dbgi_key, 0);
MutexScopeW(ctrl_state->ctrl_thread_entity_ctx_rw_mutex) MutexScopeW(ctrl_state->ctrl_thread_entity_ctx_rw_mutex)
{ {
ctrl_entity_equip_string(ctrl_state->ctrl_thread_entity_store, debug_info_path, path_normalized_from_string(scratch.arena, path)); ctrl_entity_equip_string(ctrl_state->ctrl_thread_entity_store, debug_info_path, path_normalized_from_string(scratch.arena, path));
@@ -4112,7 +4112,7 @@ ctrl_thread__next_dmn_event(Arena *arena, DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg,
out_evt->entity = module_handle; out_evt->entity = module_handle;
out_evt->string = module_path; out_evt->string = module_path;
DI_Key dbgi_key = ctrl_dbgi_key_from_module(module_ent); DI_Key dbgi_key = ctrl_dbgi_key_from_module(module_ent);
di_close(dbgi_key); di_close(dbgi_key, 0);
}break; }break;
case DMN_EventKind_DebugString: case DMN_EventKind_DebugString:
{ {
@@ -4274,15 +4274,19 @@ ctrl_thread__eval_scope_begin(Arena *arena, CTRL_UserBreakpointList *user_bps, C
U64 thread_rip_voff = ctrl_voff_from_vaddr(module, thread_rip_vaddr); U64 thread_rip_voff = ctrl_voff_from_vaddr(module, thread_rip_vaddr);
////////////////////////////// //////////////////////////////
//- rjf: gather evaluation modules //- rjf: gather evaluation debug infos & modules
// //
U64 eval_modules_count = Max(1, entity_ctx->entity_kind_counts[CTRL_EntityKind_Module]); U64 eval_modules_count = Max(1, entity_ctx->entity_kind_counts[CTRL_EntityKind_Module]);
E_Module *eval_modules = push_array(arena, E_Module, eval_modules_count); E_Module *eval_modules = push_array(arena, E_Module, eval_modules_count);
E_Module *eval_modules_primary = &eval_modules[0]; E_Module *eval_modules_primary = &eval_modules[0];
eval_modules_primary->rdi = &rdi_parsed_nil;
eval_modules_primary->vaddr_range = r1u64(0, max_U64); eval_modules_primary->vaddr_range = r1u64(0, max_U64);
U64 eval_dbg_infos_count = Max(1, entity_ctx->entity_kind_counts[CTRL_EntityKind_Module]);
E_DbgInfo *eval_dbg_infos = push_array(arena, E_DbgInfo, eval_dbg_infos_count);
E_DbgInfo *eval_dbg_infos_primary = &eval_dbg_infos[0];
MemoryCopyStruct(eval_dbg_infos_primary, &e_dbg_info_nil);
{ {
U64 eval_module_idx = 0; U64 eval_module_idx = 0;
U64 eval_dbg_info_idx = 0;
for(CTRL_Entity *machine = entity_ctx->root->first; for(CTRL_Entity *machine = entity_ctx->root->first;
machine != &ctrl_entity_nil; machine != &ctrl_entity_nil;
machine = machine->next) machine = machine->next)
@@ -4392,10 +4396,18 @@ ctrl_thread__eval_scope_begin(Arena *arena, CTRL_UserBreakpointList *user_bps, C
rdi = di_rdi_from_key(scope->access, dbgi_key, 1, max_U64); rdi = di_rdi_from_key(scope->access, dbgi_key, 1, max_U64);
} }
//- rjf: fill debug info
eval_dbg_infos[eval_dbg_info_idx].dbgi_key = dbgi_key;
eval_dbg_infos[eval_dbg_info_idx].rdi = rdi;
if(mod == module)
{
eval_dbg_infos_primary = &eval_dbg_infos[eval_dbg_info_idx];
}
eval_dbg_info_idx += 1;
//- rjf: fill evaluation module info //- rjf: fill evaluation module info
eval_modules[eval_module_idx].arch = arch; eval_modules[eval_module_idx].arch = arch;
eval_modules[eval_module_idx].dbgi_key = dbgi_key; eval_modules[eval_module_idx].dbg_info_num= (U32)eval_dbg_info_idx;
eval_modules[eval_module_idx].rdi = rdi;
eval_modules[eval_module_idx].vaddr_range = mod->vaddr_range; eval_modules[eval_module_idx].vaddr_range = mod->vaddr_range;
eval_modules[eval_module_idx].space = e_space_make(CTRL_EvalSpaceKind_Entity); eval_modules[eval_module_idx].space = e_space_make(CTRL_EvalSpaceKind_Entity);
eval_modules[eval_module_idx].space.u64_0 = (U64)process; eval_modules[eval_module_idx].space.u64_0 = (U64)process;
@@ -4427,6 +4439,11 @@ ctrl_thread__eval_scope_begin(Arena *arena, CTRL_UserBreakpointList *user_bps, C
ctx->thread_reg_space = e_space_make(CTRL_EvalSpaceKind_Entity); ctx->thread_reg_space = e_space_make(CTRL_EvalSpaceKind_Entity);
ctx->thread_reg_space.u64_0 = (U64)thread; ctx->thread_reg_space.u64_0 = (U64)thread;
//- rjf: fill debug infos
ctx->dbg_infos = eval_dbg_infos;
ctx->dbg_infos_count = eval_dbg_infos_count;
ctx->primary_dbg_info = eval_dbg_infos_primary;
//- rjf: fill modules //- rjf: fill modules
ctx->modules = eval_modules; ctx->modules = eval_modules;
ctx->modules_count = eval_modules_count; ctx->modules_count = eval_modules_count;
@@ -4445,8 +4462,8 @@ ctrl_thread__eval_scope_begin(Arena *arena, CTRL_UserBreakpointList *user_bps, C
E_IRCtx *ctx = &scope->ir_ctx; E_IRCtx *ctx = &scope->ir_ctx;
ctx->regs_map = ctrl_string2reg_from_arch(arch); ctx->regs_map = ctrl_string2reg_from_arch(arch);
ctx->reg_alias_map = ctrl_string2alias_from_arch(arch); ctx->reg_alias_map = ctrl_string2alias_from_arch(arch);
ctx->locals_map = e_push_locals_map_from_rdi_voff(arena, eval_modules_primary->rdi, thread_rip_voff); ctx->locals_map = e_push_locals_map_from_rdi_voff(arena, eval_dbg_infos_primary->rdi, thread_rip_voff);
ctx->member_map = e_push_member_map_from_rdi_voff(arena, eval_modules_primary->rdi, thread_rip_voff); ctx->member_map = e_push_member_map_from_rdi_voff(arena, eval_dbg_infos_primary->rdi, thread_rip_voff);
ctx->macro_map = push_array(arena, E_String2ExprMap, 1); ctx->macro_map = push_array(arena, E_String2ExprMap, 1);
ctx->macro_map[0] = e_string2expr_map_make(arena, 512); ctx->macro_map[0] = e_string2expr_map_make(arena, 512);
ctx->auto_hook_map = push_array(arena, E_AutoHookMap, 1); ctx->auto_hook_map = push_array(arena, E_AutoHookMap, 1);
@@ -4469,7 +4486,7 @@ ctrl_thread__eval_scope_begin(Arena *arena, CTRL_UserBreakpointList *user_bps, C
// TODO(rjf): need to compute this out here somehow... ctx->frame_base[0] = ; // TODO(rjf): need to compute this out here somehow... ctx->frame_base[0] = ;
ctx->tls_base = push_array(arena, U64, 1); ctx->tls_base = push_array(arena, U64, 1);
} }
e_select_interpret_ctx(&scope->interpret_ctx, eval_modules_primary->rdi, thread_rip_voff); e_select_interpret_ctx(&scope->interpret_ctx, eval_dbg_infos_primary->rdi, thread_rip_voff);
ProfEnd(); ProfEnd();
return scope; return scope;
@@ -6485,6 +6502,7 @@ ctrl_call_stack_artifact_create(String8 key, B32 *cancel_signal, B32 *retry_out,
//- rjf: compute call stack //- rjf: compute call stack
CTRL_Entity *thread = ctrl_entity_from_handle(entity_ctx, thread_handle); CTRL_Entity *thread = ctrl_entity_from_handle(entity_ctx, thread_handle);
B32 good = 1; B32 good = 1;
B32 retry = 0;
Arena *arena = 0; Arena *arena = 0;
CTRL_CallStack *call_stack = 0; CTRL_CallStack *call_stack = 0;
if(thread != &ctrl_entity_nil) if(thread != &ctrl_entity_nil)
@@ -6507,12 +6525,17 @@ ctrl_call_stack_artifact_create(String8 key, B32 *cancel_signal, B32 *retry_out,
good = 1; good = 1;
call_stack[0] = ctrl_call_stack_from_unwind(arena, process, &unwind); call_stack[0] = ctrl_call_stack_from_unwind(arena, process, &unwind);
} }
if(unwind.flags & CTRL_UnwindFlag_Stale)
{
retry = 1;
}
post_reg_gen = ctrl_reg_gen(); post_reg_gen = ctrl_reg_gen();
post_mem_gen = ctrl_mem_gen(); post_mem_gen = ctrl_mem_gen();
} }
if(pre_reg_gen != post_reg_gen || pre_mem_gen != post_mem_gen) if(pre_reg_gen != post_reg_gen || pre_mem_gen != post_mem_gen)
{ {
good = 0; good = 0;
retry = 1;
} }
if(!good) if(!good)
{ {
@@ -6533,11 +6556,8 @@ ctrl_call_stack_artifact_create(String8 key, B32 *cancel_signal, B32 *retry_out,
artifact.u64[1] = (U64)call_stack; artifact.u64[1] = (U64)call_stack;
} }
//- rjf: retry on bad //- rjf: mark retry
if(!good) retry_out[0] = retry;
{
retry_out[0] = 1;
}
scratch_end(scratch); scratch_end(scratch);
} }
+10
View File
@@ -1500,6 +1500,16 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
evt->code = event->u64_code; evt->code = event->u64_code;
}break; }break;
case CTRL_EventKind_NewModule:
{
D_EventNode *n = push_array(arena, D_EventNode, 1);
SLLQueuePush(result.first, result.last, n);
result.count += 1;
D_Event *evt = &n->v;
evt->kind = D_EventKind_ModuleLoad;
evt->module = event->entity;
}break;
//- rjf: debug strings //- rjf: debug strings
case CTRL_EventKind_DebugString: case CTRL_EventKind_DebugString:
+2
View File
@@ -86,6 +86,7 @@ struct D_TrapNet
typedef enum D_EventKind typedef enum D_EventKind
{ {
D_EventKind_Null, D_EventKind_Null,
D_EventKind_ModuleLoad,
D_EventKind_ProcessEnd, D_EventKind_ProcessEnd,
D_EventKind_Stop, D_EventKind_Stop,
D_EventKind_COUNT D_EventKind_COUNT
@@ -107,6 +108,7 @@ struct D_Event
{ {
D_EventKind kind; D_EventKind kind;
D_EventCause cause; D_EventCause cause;
CTRL_Handle module;
CTRL_Handle thread; CTRL_Handle thread;
U64 vaddr; U64 vaddr;
U64 code; U64 code;
+156 -84
View File
@@ -313,8 +313,8 @@ di_open(DI_Key key)
} }
internal void internal void
di_close(DI_Key key) di_close(DI_Key key, B32 force_closed)
{ {
//- rjf: unpack key //- rjf: unpack key
U64 hash = u64_hash_from_str8(str8_struct(&key)); U64 hash = u64_hash_from_str8(str8_struct(&key));
U64 slot_idx = hash%di_shared->slots_count; U64 slot_idx = hash%di_shared->slots_count;
@@ -340,8 +340,15 @@ di_close(DI_Key key)
} }
} }
if(node) if(node)
{ {
node->refcount -= 1; if(force_closed)
{
node->refcount = 0;
}
else
{
node->refcount -= 1;
}
if(node->refcount == 0) if(node->refcount == 0)
{ {
for(;;) for(;;)
@@ -377,7 +384,7 @@ di_close(DI_Key key)
{ {
arena_release(arena); arena_release(arena);
} }
} }
} }
//////////////////////////////// ////////////////////////////////
@@ -670,12 +677,12 @@ di_async_tick(void)
} }
} }
//- rjf: analyze O.G. debug info //- rjf: analyze O.G. debug info
if(!t->og_analyzed) if(!t->og_analyzed)
{ {
t->og_analyzed = 1; t->og_analyzed = 1;
OS_Handle file = os_file_open(OS_AccessFlag_ShareRead|OS_AccessFlag_Read, og_path); OS_Handle file = os_file_open(OS_AccessFlag_ShareRead|OS_AccessFlag_Read, og_path);
FileProperties props = os_properties_from_file(file); FileProperties props = os_properties_from_file(file);
t->og_size = props.size; t->og_size = props.size;
U64 rdi_magic_maybe = 0; U64 rdi_magic_maybe = 0;
if(os_file_read_struct(file, 0, &rdi_magic_maybe) == 8 && if(os_file_read_struct(file, 0, &rdi_magic_maybe) == 8 &&
@@ -685,11 +692,12 @@ di_async_tick(void)
} }
os_file_close(file); os_file_close(file);
} }
U64 og_size = t->og_size; U64 og_size = t->og_size;
B32 og_is_rdi = t->og_is_rdi; B32 og_is_rdi = t->og_is_rdi;
B32 og_is_good = (og_size > 0);
//- rjf: compute key's RDI path //- rjf: compute key's RDI path
String8 rdi_path = {0}; String8 rdi_path = {0};
{ {
if(og_is_rdi) if(og_is_rdi)
{ {
@@ -754,8 +762,31 @@ di_async_tick(void)
threads_available = (max_threads >= needed_threads); threads_available = (max_threads >= needed_threads);
} }
//- rjf: if this conversion will overwrite an RDI we already have in cache,
// then we need to evict the old one from the cache.
B32 ready_to_launch_conversion = (threads_available && !og_is_rdi && rdi_is_stale && t->thread_count != 0 && t->status != DI_LoadTaskStatus_Active);
if(ready_to_launch_conversion)
{
U64 path2key_hash = u64_hash_from_str8(og_path);
U64 path2key_slot_idx = path2key_hash%di_shared->path2key_slots_count;
DI_KeySlot *path2key_slot = &di_shared->path2key_slots[path2key_slot_idx];
Stripe *path2key_stripe = stripe_from_slot_idx(&di_shared->path2key_stripes, path2key_slot_idx);
RWMutexScope(path2key_stripe->rw_mutex, 0)
{
// NOTE(rjf): we need to iterate from last -> first, since we want to evict the
// most recent key.
for(DI_KeyPathNode *n = path2key_slot->last; n != 0; n = n->prev)
{
if(str8_match(n->path, og_path, 0) && !di_key_match(key, n->key))
{
di_close(n->key, 1);
}
}
}
}
//- rjf: launch conversion processes //- rjf: launch conversion processes
if(threads_available && !og_is_rdi && rdi_is_stale && t->thread_count != 0 && t->status != DI_LoadTaskStatus_Active) if(og_is_good && ready_to_launch_conversion)
{ {
B32 should_compress = 0; B32 should_compress = 0;
OS_ProcessLaunchParams params = {0}; OS_ProcessLaunchParams params = {0};
@@ -818,7 +849,13 @@ di_async_tick(void)
di_shared->conversion_thread_count -= t->thread_count; di_shared->conversion_thread_count -= t->thread_count;
} }
} }
} }
//- rjf: ready to launch, but bad O.G. file -> just immediately mark as done
if(!og_is_good && ready_to_launch_conversion)
{
t->status = DI_LoadTaskStatus_Done;
}
//- rjf: if the RDI for this task is not stale, then we're already done - mark this //- rjf: if the RDI for this task is not stale, then we're already done - mark this
// task as done & prepped for storing into the cache // task as done & prepped for storing into the cache
@@ -960,8 +997,11 @@ di_async_tick(void)
node->arena = rdi_parsed_arena; node->arena = rdi_parsed_arena;
MemoryCopyStruct(&node->rdi, &rdi_parsed); MemoryCopyStruct(&node->rdi, &rdi_parsed);
node->completion_count += 1; node->completion_count += 1;
node->working_count -= 1; node->working_count -= 1;
ins_atomic_u64_inc_eval(&di_shared->load_gen); if(node->rdi.raw_data_size != 0)
{
ins_atomic_u64_inc_eval(&di_shared->load_gen);
}
ins_atomic_u64_inc_eval(&di_shared->load_count); ins_atomic_u64_inc_eval(&di_shared->load_count);
} }
else else
@@ -1142,9 +1182,10 @@ di_search_artifact_create(String8 key, B32 *cancel_signal, B32 *retry_out, U64 *
Rng1U64 range = lane_range(element_count); Rng1U64 range = lane_range(element_count);
for EachInRange(idx, range) for EachInRange(idx, range)
{ {
//- rjf: every so often, check if we need to cancel, and cancel //- rjf: every so often, check if we need to cancel, and cancel
if(idx%10000 == 0 && !!ins_atomic_u32_eval(cancel_signal))
{ {
// TODO(rjf) break;
} }
//- rjf: get element, map to string; if empty, continue to next element //- rjf: get element, map to string; if empty, continue to next element
@@ -1244,7 +1285,15 @@ di_search_artifact_create(String8 key, B32 *cancel_signal, B32 *retry_out, U64 *
} }
} }
lane_sync(); lane_sync();
//- rjf: decide if we cancelled
B32 cancelled = 0;
if(lane_idx() == 0 && !!ins_atomic_u32_eval(cancel_signal))
{
cancelled = 1;
}
lane_sync_u64(&cancelled, 0);
//- rjf: produce sort records //- rjf: produce sort records
typedef struct SortRecord SortRecord; typedef struct SortRecord SortRecord;
struct SortRecord struct SortRecord
@@ -1255,15 +1304,15 @@ di_search_artifact_create(String8 key, B32 *cancel_signal, B32 *retry_out, U64 *
U64 sort_records_count = all_items->total_count; U64 sort_records_count = all_items->total_count;
SortRecord *sort_records = 0; SortRecord *sort_records = 0;
SortRecord *sort_records__swap = 0; SortRecord *sort_records__swap = 0;
ProfScope("produce sort records") if(!cancelled) ProfScope("produce sort records")
{ {
if(lane_idx() == 0) if(lane_idx() == 0)
{ {
sort_records = push_array(scratch.arena, SortRecord, sort_records_count); sort_records = push_array_no_zero(scratch.arena, SortRecord, sort_records_count);
} }
if(lane_idx() == lane_from_task_idx(1)) if(lane_idx() == lane_from_task_idx(1))
{ {
sort_records__swap = push_array(scratch.arena, SortRecord, sort_records_count); sort_records__swap = push_array_no_zero(scratch.arena, SortRecord, sort_records_count);
} }
lane_sync_u64(&sort_records, 0); lane_sync_u64(&sort_records, 0);
lane_sync_u64(&sort_records__swap, lane_from_task_idx(1)); lane_sync_u64(&sort_records__swap, lane_from_task_idx(1));
@@ -1283,7 +1332,7 @@ di_search_artifact_create(String8 key, B32 *cancel_signal, B32 *retry_out, U64 *
lane_sync(); lane_sync();
//- rjf: sort records //- rjf: sort records
ProfScope("sort records") if(!cancelled) ProfScope("sort records")
{ {
//- rjf: set up common data //- rjf: set up common data
U64 bits_per_digit = 8; U64 bits_per_digit = 8;
@@ -1382,12 +1431,12 @@ di_search_artifact_create(String8 key, B32 *cancel_signal, B32 *retry_out, U64 *
//- rjf: produce final array //- rjf: produce final array
DI_SearchItemArray items = {0}; DI_SearchItemArray items = {0};
ProfScope("produce final array") if(!cancelled) ProfScope("produce final array")
{ {
if(lane_idx() == 0) if(lane_idx() == 0)
{ {
items.count = all_items->total_count; items.count = all_items->total_count;
items.v = push_array(arena, DI_SearchItem, items.count); items.v = push_array_no_zero(arena, DI_SearchItem, items.count);
} }
lane_sync_u64(&items.count, 0); lane_sync_u64(&items.count, 0);
lane_sync_u64(&items.v, 0); lane_sync_u64(&items.v, 0);
@@ -1401,11 +1450,20 @@ di_search_artifact_create(String8 key, B32 *cancel_signal, B32 *retry_out, U64 *
} }
lane_sync(); lane_sync();
//- rjf: bundle as artifact //- rjf: bundle as artifact
artifact.u64[0] = (U64)arenas; if(!cancelled)
artifact.u64[1] = arenas_count; {
artifact.u64[2] = (U64)items.v; artifact.u64[0] = (U64)arenas;
artifact.u64[3] = items.count; artifact.u64[1] = arenas_count;
artifact.u64[2] = (U64)items.v;
artifact.u64[3] = items.count;
}
//- rjf: release results on cancel
else
{
arena_release(arena);
}
} }
scratch_end(scratch); scratch_end(scratch);
access_close(access); access_close(access);
@@ -1446,7 +1504,7 @@ di_search_item_array_from_target_query(Access *access, RDI_SectionKind target, S
String8 key = str8_list_join(scratch.arena, &key_parts, 0); String8 key = str8_list_join(scratch.arena, &key_parts, 0);
// rjf: get artifact // rjf: get artifact
AC_Artifact artifact = ac_artifact_from_key(access, key, di_search_artifact_create, di_search_artifact_destroy, endt_us, .gen = di_load_gen(), .flags = AC_Flag_Wide, .stale_out = stale_out); AC_Artifact artifact = ac_artifact_from_key(access, key, di_search_artifact_create, di_search_artifact_destroy, endt_us, .gen = di_load_gen(), .flags = AC_Flag_Wide, .evict_threshold_us = 100000, .stale_out = stale_out);
// rjf: unpack artifact // rjf: unpack artifact
result.v = (DI_SearchItem *)artifact.u64[2]; result.v = (DI_SearchItem *)artifact.u64[2];
@@ -1481,73 +1539,87 @@ di_match_artifact_create(String8 key, B32 *cancel_signal, B32 *retry_out, U64 *g
//- rjf: get all loaded keys //- rjf: get all loaded keys
DI_KeyArray dbgi_keys = di_push_all_loaded_keys(scratch.arena); DI_KeyArray dbgi_keys = di_push_all_loaded_keys(scratch.arena);
//- rjf: take cancellation signal
B32 cancelled = 0;
if(lane_idx() == 0)
{
cancelled = ins_atomic_u32_eval(cancel_signal);
}
lane_sync_u64(&cancelled, 0);
//- rjf: wide search across all debug infos //- rjf: wide search across all debug infos
DI_Match *lane_matches = 0; DI_Match *lane_matches = 0;
if(lane_idx() == 0) if(!cancelled)
{ {
lane_matches = push_array(scratch.arena, DI_Match, lane_count()); if(lane_idx() == 0)
}
lane_sync_u64(&lane_matches, 0);
{
read_only local_persist RDI_NameMapKind name_map_kinds[] =
{ {
RDI_NameMapKind_GlobalVariables, lane_matches = push_array(scratch.arena, DI_Match, lane_count());
RDI_NameMapKind_ThreadVariables, }
RDI_NameMapKind_Constants, lane_sync_u64(&lane_matches, 0);
RDI_NameMapKind_Procedures,
RDI_NameMapKind_Types,
};
read_only local_persist RDI_SectionKind name_map_section_kinds[] =
{ {
RDI_SectionKind_GlobalVariables, read_only local_persist RDI_NameMapKind name_map_kinds[] =
RDI_SectionKind_ThreadVariables,
RDI_SectionKind_Constants,
RDI_SectionKind_Procedures,
RDI_SectionKind_TypeNodes,
};
Rng1U64 range = lane_range(dbgi_keys.count);
for EachInRange(dbgi_idx, range)
{
Access *access = access_open();
{ {
DI_Key dbgi_key = dbgi_keys.v[dbgi_idx]; RDI_NameMapKind_GlobalVariables,
RDI_Parsed *rdi = di_rdi_from_key(access, dbgi_key, 0, 0); RDI_NameMapKind_ThreadVariables,
for EachElement(name_map_kind_idx, name_map_kinds) RDI_NameMapKind_Constants,
RDI_NameMapKind_Procedures,
RDI_NameMapKind_Types,
};
read_only local_persist RDI_SectionKind name_map_section_kinds[] =
{
RDI_SectionKind_GlobalVariables,
RDI_SectionKind_ThreadVariables,
RDI_SectionKind_Constants,
RDI_SectionKind_Procedures,
RDI_SectionKind_TypeNodes,
};
Rng1U64 range = lane_range(dbgi_keys.count);
for EachInRange(dbgi_idx, range)
{
Access *access = access_open();
{ {
RDI_NameMap *name_map = rdi_element_from_name_idx(rdi, NameMaps, name_map_kinds[name_map_kind_idx]); DI_Key dbgi_key = dbgi_keys.v[dbgi_idx];
RDI_ParsedNameMap parsed_name_map = {0}; RDI_Parsed *rdi = di_rdi_from_key(access, dbgi_key, 0, 0);
rdi_parsed_from_name_map(rdi, name_map, &parsed_name_map); for EachElement(name_map_kind_idx, name_map_kinds)
RDI_NameMapNode *map_node = rdi_name_map_lookup(rdi, &parsed_name_map, name.str, name.size);
U32 num = 0;
U32 *run = rdi_matches_from_map_node(rdi, map_node, &num);
if(num != 0)
{ {
lane_matches[lane_idx()].key = dbgi_key; RDI_NameMap *name_map = rdi_element_from_name_idx(rdi, NameMaps, name_map_kinds[name_map_kind_idx]);
lane_matches[lane_idx()].section_kind = name_map_section_kinds[name_map_kind_idx]; RDI_ParsedNameMap parsed_name_map = {0};
lane_matches[lane_idx()].idx = run[num-1]; rdi_parsed_from_name_map(rdi, name_map, &parsed_name_map);
RDI_NameMapNode *map_node = rdi_name_map_lookup(rdi, &parsed_name_map, name.str, name.size);
U32 num = 0;
U32 *run = rdi_matches_from_map_node(rdi, map_node, &num);
if(num != 0)
{
lane_matches[lane_idx()].key = dbgi_key;
lane_matches[lane_idx()].section_kind = name_map_section_kinds[name_map_kind_idx];
lane_matches[lane_idx()].idx = run[num-1];
}
} }
} }
access_close(access);
} }
access_close(access); }
} }
} lane_sync();
lane_sync();
//- rjf: pick match //- rjf: pick match
DI_Match match = {0}; DI_Match match = {0};
for EachIndex(idx, lane_count()) if(lane_matches != 0)
{ {
if(lane_matches[idx].idx != 0) for EachIndex(idx, lane_count())
{ {
match = lane_matches[idx]; if(lane_matches[idx].idx != 0)
if(di_key_match(di_key_zero(), preferred_key) || di_key_match(match.key, preferred_key)) {
{ match = lane_matches[idx];
break; if(di_key_match(di_key_zero(), preferred_key) || di_key_match(match.key, preferred_key))
} {
break;
}
}
} }
} }
//- rjf: package as artifact //- rjf: package as artifact
AC_Artifact artifact = {0}; AC_Artifact artifact = {0};
{ {
@@ -1579,7 +1651,7 @@ di_match_from_string(String8 string, U64 index, DI_Key preferred_dbgi_key, U64 e
String8 key = str8_list_join(scratch.arena, &key_parts, 0); String8 key = str8_list_join(scratch.arena, &key_parts, 0);
U64 dbgi_count = di_load_count(); U64 dbgi_count = di_load_count();
B32 wide = (dbgi_count > 256); B32 wide = (dbgi_count > 256);
AC_Artifact artifact = ac_artifact_from_key(access, key, di_match_artifact_create, 0, endt_us, .flags = wide ? AC_Flag_Wide : 0, .gen = di_load_gen()); AC_Artifact artifact = ac_artifact_from_key(access, key, di_match_artifact_create, 0, endt_us, .flags = wide ? AC_Flag_Wide : 0, .gen = di_load_gen(), .evict_threshold_us = wide ? 20000000 : 10000000);
result.key.u64[0] = artifact.u64[0]; result.key.u64[0] = artifact.u64[0];
result.key.u64[1] = artifact.u64[1]; result.key.u64[1] = artifact.u64[1];
result.section_kind = artifact.u64[2]; result.section_kind = artifact.u64[2];
+1 -1
View File
@@ -323,7 +323,7 @@ internal DI_Key di_key_from_path_timestamp(String8 path, U64 min_timestamp);
//~ rjf: Debug Info Opening / Closing //~ rjf: Debug Info Opening / Closing
internal void di_open(DI_Key key); internal void di_open(DI_Key key);
internal void di_close(DI_Key key); internal void di_close(DI_Key key, B32 force_closed);
//////////////////////////////// ////////////////////////////////
//~ rjf: Debug Info Lookups //~ rjf: Debug Info Lookups
+31 -3
View File
@@ -676,8 +676,10 @@ internal void
e_select_base_ctx(E_BaseCtx *ctx) e_select_base_ctx(E_BaseCtx *ctx)
{ {
//- rjf: select base context //- rjf: select base context
if(ctx->modules == 0) { ctx->modules = &e_module_nil; } if(ctx->modules == 0) { ctx->modules = &e_module_nil; }
if(ctx->primary_module == 0) { ctx->primary_module = &e_module_nil; } if(ctx->primary_module == 0) { ctx->primary_module = &e_module_nil; }
if(ctx->dbg_infos == 0) { ctx->dbg_infos = &e_dbg_info_nil; }
if(ctx->primary_dbg_info == 0) { ctx->primary_dbg_info = &e_dbg_info_nil; }
e_base_ctx = ctx; e_base_ctx = ctx;
//- rjf: reset the evaluation cache //- rjf: reset the evaluation cache
@@ -718,7 +720,7 @@ e_select_base_ctx(E_BaseCtx *ctx)
.id_from_num = E_TYPE_EXPAND_ID_FROM_NUM_FUNCTION_NAME(folder), .id_from_num = E_TYPE_EXPAND_ID_FROM_NUM_FUNCTION_NAME(folder),
.num_from_id = E_TYPE_EXPAND_NUM_FROM_ID_FUNCTION_NAME(folder), .num_from_id = E_TYPE_EXPAND_NUM_FROM_ID_FUNCTION_NAME(folder),
}); });
e_cache->thread_ip_procedure = rdi_procedure_from_voff(e_base_ctx->primary_module->rdi, e_base_ctx->thread_ip_voff); e_cache->thread_ip_procedure = rdi_procedure_from_voff(e_base_ctx->primary_dbg_info->rdi, e_base_ctx->thread_ip_voff);
e_cache->used_expr_map = push_array(e_cache->arena, E_UsedExprMap, 1); e_cache->used_expr_map = push_array(e_cache->arena, E_UsedExprMap, 1);
e_cache->used_expr_map->slots_count = 64; e_cache->used_expr_map->slots_count = 64;
e_cache->used_expr_map->slots = push_array(e_cache->arena, E_UsedExprSlot, e_cache->used_expr_map->slots_count); e_cache->used_expr_map->slots = push_array(e_cache->arena, E_UsedExprSlot, e_cache->used_expr_map->slots_count);
@@ -744,6 +746,32 @@ e_select_ir_ctx(E_IRCtx *ctx)
e_ir_ctx = ctx; e_ir_ctx = ctx;
} }
////////////////////////////////
//~ rjf: Context Accessors
internal E_DbgInfo *
e_dbg_info_from_module(E_Module *module)
{
E_DbgInfo *result = &e_dbg_info_nil;
if(0 < module->dbg_info_num && module->dbg_info_num <= e_base_ctx->dbg_infos_count)
{
result = &e_base_ctx->dbg_infos[module->dbg_info_num-1];
}
return result;
}
internal E_DbgInfo *
e_dbg_info_from_type_key(E_TypeKey type_key)
{
E_DbgInfo *result = &e_dbg_info_nil;
if(type_key.kind == E_TypeKeyKind_Ext &&
0 < type_key.u32[2] && type_key.u32[2] <= e_base_ctx->dbg_infos_count)
{
result = &e_base_ctx->dbg_infos[type_key.u32[2]-1];
}
return result;
}
//////////////////////////////// ////////////////////////////////
//~ rjf: Cache Accessing Functions //~ rjf: Cache Accessing Functions
+32 -10
View File
@@ -174,8 +174,8 @@ struct E_TypeKey
E_TypeKeyKind kind; E_TypeKeyKind kind;
U32 u32[3]; U32 u32[3];
// [0] -> E_TypeKind (Basic, Cons, Ext); Arch (Reg, RegAlias) // [0] -> E_TypeKind (Basic, Cons, Ext); Arch (Reg, RegAlias)
// [1] -> Type Index In RDI (Ext); Code (Reg, RegAlias); Type Index In Constructed (Cons) // [1] -> Type Index In Debug Info (Ext); Code (Reg, RegAlias); Type Index In Constructed (Cons)
// [2] -> RDI Index (Ext) // [2] -> Debug Info Number (Ext)
}; };
typedef struct E_TypeKeyNode E_TypeKeyNode; typedef struct E_TypeKeyNode E_TypeKeyNode;
@@ -384,11 +384,12 @@ enum
E_TypeFlag_IsCodeText = (1<<4), E_TypeFlag_IsCodeText = (1<<4),
E_TypeFlag_IsPathText = (1<<5), E_TypeFlag_IsPathText = (1<<5),
E_TypeFlag_IsNotText = (1<<6), E_TypeFlag_IsNotText = (1<<6),
E_TypeFlag_EditableChildren = (1<<7), E_TypeFlag_IsNotEditable = (1<<7),
E_TypeFlag_InheritedByMembers = (1<<8), E_TypeFlag_EditableChildren = (1<<8),
E_TypeFlag_InheritedByElements = (1<<9), E_TypeFlag_InheritedByMembers = (1<<9),
E_TypeFlag_ArrayLikeExpansion = (1<<10), E_TypeFlag_InheritedByElements = (1<<10),
E_TypeFlag_StubSingleLineExpansion = (1<<11), E_TypeFlag_ArrayLikeExpansion = (1<<11),
E_TypeFlag_StubSingleLineExpansion = (1<<12),
}; };
typedef struct E_Member E_Member; typedef struct E_Member E_Member;
@@ -564,15 +565,24 @@ struct E_ConsTypeSlot
E_ConsTypeNode *last; E_ConsTypeNode *last;
}; };
////////////////////////////////
//~ rjf: Debug Info
typedef struct E_DbgInfo E_DbgInfo;
struct E_DbgInfo
{
DI_Key dbgi_key;
RDI_Parsed *rdi;
};
//////////////////////////////// ////////////////////////////////
//~ rjf: Modules //~ rjf: Modules
typedef struct E_Module E_Module; typedef struct E_Module E_Module;
struct E_Module struct E_Module
{ {
DI_Key dbgi_key;
RDI_Parsed *rdi;
Rng1U64 vaddr_range; Rng1U64 vaddr_range;
U32 dbg_info_num;
Arch arch; Arch arch;
E_Space space; E_Space space;
}; };
@@ -760,6 +770,11 @@ struct E_BaseCtx
Arch thread_arch; Arch thread_arch;
U64 thread_unwind_count; U64 thread_unwind_count;
// rjf: debug infos
E_DbgInfo *dbg_infos;
U64 dbg_infos_count;
E_DbgInfo *primary_dbg_info;
// rjf: modules // rjf: modules
E_Module *modules; E_Module *modules;
U64 modules_count; U64 modules_count;
@@ -1111,7 +1126,8 @@ read_only global E_String2ExprMap e_string2expr_map_nil = {0};
read_only global E_Expr e_expr_nil = {&e_expr_nil, &e_expr_nil, &e_expr_nil, &e_expr_nil, &e_expr_nil}; read_only global E_Expr e_expr_nil = {&e_expr_nil, &e_expr_nil, &e_expr_nil, &e_expr_nil, &e_expr_nil};
read_only global E_IRNode e_irnode_nil = {&e_irnode_nil, &e_irnode_nil, &e_irnode_nil}; read_only global E_IRNode e_irnode_nil = {&e_irnode_nil, &e_irnode_nil, &e_irnode_nil};
read_only global E_Eval e_eval_nil = {{0}, {0}, {0}, &e_expr_nil, {&e_irnode_nil}}; read_only global E_Eval e_eval_nil = {{0}, {0}, {0}, &e_expr_nil, {&e_irnode_nil}};
read_only global E_Module e_module_nil = {{0}, &rdi_parsed_nil}; read_only global E_DbgInfo e_dbg_info_nil = {{0}, &rdi_parsed_nil};
read_only global E_Module e_module_nil = {0};
read_only global E_CacheBundle e_cache_bundle_nil = {0, {0}, {0}, {0}, {{0}, 0, &e_expr_nil, &e_expr_nil}, {&e_irnode_nil}}; read_only global E_CacheBundle e_cache_bundle_nil = {0, {0}, {0}, {0}, {{0}, 0, &e_expr_nil, &e_expr_nil}, {&e_irnode_nil}};
thread_static E_BaseCtx *e_base_ctx = 0; thread_static E_BaseCtx *e_base_ctx = 0;
thread_static E_IRCtx *e_ir_ctx = 0; thread_static E_IRCtx *e_ir_ctx = 0;
@@ -1203,6 +1219,12 @@ internal void e_select_cache(E_Cache *cache);
internal void e_select_base_ctx(E_BaseCtx *ctx); internal void e_select_base_ctx(E_BaseCtx *ctx);
internal void e_select_ir_ctx(E_IRCtx *ctx); internal void e_select_ir_ctx(E_IRCtx *ctx);
////////////////////////////////
//~ rjf: Context Accessors
internal E_DbgInfo *e_dbg_info_from_module(E_Module *module);
internal E_DbgInfo *e_dbg_info_from_type_key(E_TypeKey type_key);
//////////////////////////////// ////////////////////////////////
//~ rjf: Base Cache Accessing Functions //~ rjf: Base Cache Accessing Functions
// //
+50 -33
View File
@@ -389,7 +389,8 @@ E_TYPE_ACCESS_FUNCTION_DEF(default)
E_TypeKind check_type_kind = l_restype_kind; E_TypeKind check_type_kind = l_restype_kind;
if(l_restype_kind == E_TypeKind_Ptr || if(l_restype_kind == E_TypeKind_Ptr ||
l_restype_kind == E_TypeKind_LRef || l_restype_kind == E_TypeKind_LRef ||
l_restype_kind == E_TypeKind_RRef) l_restype_kind == E_TypeKind_RRef ||
l_restype_kind == E_TypeKind_Array)
{ {
check_type_key = e_type_key_unwrap(l.type_key, E_TypeUnwrapFlag_All); check_type_key = e_type_key_unwrap(l.type_key, E_TypeUnwrapFlag_All);
check_type_kind = e_type_kind_from_key(check_type_key); check_type_kind = e_type_kind_from_key(check_type_key);
@@ -698,6 +699,10 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, E_I
result = new_result_maybe; result = new_result_maybe;
break; break;
} }
else if(new_result_maybe.msgs.count != 0 && result.msgs.count == 0)
{
result = new_result_maybe;
}
} }
if(result.root != &e_irnode_nil) if(result.root != &e_irnode_nil)
{ {
@@ -963,28 +968,27 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, E_I
String8 bytecode = e_bytecode_from_oplist(scratch.arena, &oplist); String8 bytecode = e_bytecode_from_oplist(scratch.arena, &oplist);
E_Interpretation interpretation = e_interpret(bytecode); E_Interpretation interpretation = e_interpret(bytecode);
E_Module *module = &e_module_nil; E_Module *module = &e_module_nil;
U32 rdi_idx = 0;
for EachIndex(idx, e_base_ctx->modules_count) for EachIndex(idx, e_base_ctx->modules_count)
{ {
E_Module *m = &e_base_ctx->modules[idx]; E_Module *m = &e_base_ctx->modules[idx];
if(e_space_match(interpretation.space, m->space) && contains_1u64(m->vaddr_range, interpretation.value.u64)) if(e_space_match(interpretation.space, m->space) && contains_1u64(m->vaddr_range, interpretation.value.u64))
{ {
module = m; module = m;
rdi_idx = (U32)idx;
break; break;
} }
} }
if(module != &e_module_nil) if(module != &e_module_nil)
{ {
E_DbgInfo *dbg_info = e_dbg_info_from_module(module);
U64 voff = interpretation.value.u64 - module->vaddr_range.min; U64 voff = interpretation.value.u64 - module->vaddr_range.min;
U64 new_vaddr = 0; U64 new_vaddr = 0;
RDI_Procedure *p = rdi_procedure_from_voff(module->rdi, voff); RDI_Procedure *p = rdi_procedure_from_voff(dbg_info->rdi, voff);
RDI_GlobalVariable *g = rdi_global_variable_from_voff(module->rdi, voff); RDI_GlobalVariable *g = rdi_global_variable_from_voff(dbg_info->rdi, voff);
U32 type_idx = 0; U32 type_idx = 0;
if(p->name_string_idx != 0) if(p->name_string_idx != 0)
{ {
type_idx = p->type_idx; type_idx = p->type_idx;
new_vaddr = module->vaddr_range.min + rdi_first_voff_from_procedure(module->rdi, p); new_vaddr = module->vaddr_range.min + rdi_first_voff_from_procedure(dbg_info->rdi, p);
} }
else if(g->name_string_idx != 0) else if(g->name_string_idx != 0)
{ {
@@ -993,10 +997,10 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, E_I
} }
if(type_idx != 0) if(type_idx != 0)
{ {
RDI_TypeNode *t = rdi_element_from_name_idx(module->rdi, TypeNodes, type_idx); RDI_TypeNode *t = rdi_element_from_name_idx(dbg_info->rdi, TypeNodes, type_idx);
result.root = e_irtree_const_u(arena, new_vaddr); result.root = e_irtree_const_u(arena, new_vaddr);
result.mode = E_Mode_Value; result.mode = E_Mode_Value;
result.type_key = e_type_key_ext(e_type_kind_from_rdi(t->kind), type_idx, rdi_idx); result.type_key = e_type_key_ext(e_type_kind_from_rdi(t->kind), type_idx, module->dbg_info_num);
} }
} }
}break; }break;
@@ -1792,12 +1796,12 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, E_I
if(!string_mapped && (qualifier.size == 0 || str8_match(qualifier, str8_lit("member"), 0))) if(!string_mapped && (qualifier.size == 0 || str8_match(qualifier, str8_lit("member"), 0)))
{ {
E_Module *module = e_base_ctx->primary_module; E_Module *module = e_base_ctx->primary_module;
U32 module_idx = (U32)(module - e_base_ctx->modules); E_DbgInfo *dbg_info = e_dbg_info_from_module(module);
RDI_Parsed *rdi = module->rdi; RDI_Parsed *rdi = dbg_info->rdi;
RDI_Procedure *procedure = e_cache->thread_ip_procedure; RDI_Procedure *procedure = e_cache->thread_ip_procedure;
RDI_UDT *udt = rdi_container_udt_from_procedure(rdi, procedure); RDI_UDT *udt = rdi_container_udt_from_procedure(rdi, procedure);
RDI_TypeNode *type_node = rdi_element_from_name_idx(rdi, TypeNodes, udt->self_type_idx); RDI_TypeNode *type_node = rdi_element_from_name_idx(rdi, TypeNodes, udt->self_type_idx);
E_TypeKey container_type_key = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), udt->self_type_idx, module_idx); E_TypeKey container_type_key = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), udt->self_type_idx, module->dbg_info_num);
E_Member member = e_type_member_from_key_name__cached(container_type_key, string); E_Member member = e_type_member_from_key_name__cached(container_type_key, string);
if(member.kind != E_MemberKind_Null) if(member.kind != E_MemberKind_Null)
{ {
@@ -1811,8 +1815,8 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, E_I
if(!string_mapped && (qualifier.size == 0 || str8_match(qualifier, str8_lit("local"), 0))) if(!string_mapped && (qualifier.size == 0 || str8_match(qualifier, str8_lit("local"), 0)))
{ {
E_Module *module = e_base_ctx->primary_module; E_Module *module = e_base_ctx->primary_module;
U32 module_idx = (U32)(module - e_base_ctx->modules); E_DbgInfo *dbg_info = e_dbg_info_from_module(module);
RDI_Parsed *rdi = module->rdi; RDI_Parsed *rdi = dbg_info->rdi;
U64 local_num = e_num_from_string(e_ir_ctx->locals_map, string__redirected); U64 local_num = e_num_from_string(e_ir_ctx->locals_map, string__redirected);
if(local_num != 0) if(local_num != 0)
{ {
@@ -1820,7 +1824,7 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, E_I
// rjf: extract local's type key // rjf: extract local's type key
RDI_TypeNode *type_node = rdi_element_from_name_idx(rdi, TypeNodes, local->type_idx); RDI_TypeNode *type_node = rdi_element_from_name_idx(rdi, TypeNodes, local->type_idx);
mapped_type_key = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), local->type_idx, module_idx); mapped_type_key = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), local->type_idx, module->dbg_info_num);
// rjf: extract local's location block // rjf: extract local's location block
B32 got_location_block = 0; B32 got_location_block = 0;
@@ -1887,13 +1891,14 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, E_I
Access *access = access_open(); Access *access = access_open();
// rjf: find match // rjf: find match
DI_Match match = di_match_from_string(string, 0, e_base_ctx->primary_module->dbgi_key, 0); DI_Match match = di_match_from_string(string, 0, e_base_ctx->primary_dbg_info->dbgi_key, 0);
if(match.idx == 0) if(match.idx == 0)
{ {
String8List namespaceified_strings = {0}; String8List namespaceified_strings = {0};
{ {
E_Module *module = e_base_ctx->primary_module; E_Module *module = e_base_ctx->primary_module;
RDI_Parsed *rdi = module->rdi; E_DbgInfo *dbg_info = e_dbg_info_from_module(module);
RDI_Parsed *rdi = dbg_info->rdi;
RDI_Procedure *procedure = e_cache->thread_ip_procedure; RDI_Procedure *procedure = e_cache->thread_ip_procedure;
U64 name_size = 0; U64 name_size = 0;
U8 *name_ptr = rdi_string_from_idx(rdi, procedure->name_string_idx, &name_size); U8 *name_ptr = rdi_string_from_idx(rdi, procedure->name_string_idx, &name_size);
@@ -1916,7 +1921,7 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, E_I
} }
for(String8Node *n = namespaceified_strings.first; n != 0; n = n->next) for(String8Node *n = namespaceified_strings.first; n != 0; n = n->next)
{ {
match = di_match_from_string(n->string, 0, e_base_ctx->primary_module->dbgi_key, 0); match = di_match_from_string(n->string, 0, e_base_ctx->primary_dbg_info->dbgi_key, 0);
if(match.idx != 0) if(match.idx != 0)
{ {
break; break;
@@ -1927,17 +1932,27 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, E_I
// rjf: match -> RDI // rjf: match -> RDI
RDI_Parsed *rdi = di_rdi_from_key(access, match.key, 0, 0); RDI_Parsed *rdi = di_rdi_from_key(access, match.key, 0, 0);
// rjf: find dbg info from rdi
E_DbgInfo *dbg_info = &e_dbg_info_nil;
U32 dbg_info_num = 0;
for EachIndex(idx, e_base_ctx->dbg_infos_count)
{
if(e_base_ctx->dbg_infos[idx].rdi == rdi)
{
dbg_info = &e_base_ctx->dbg_infos[idx];
dbg_info_num = idx+1;
break;
}
}
// rjf: find module from dbgi key // rjf: find module from dbgi key
U32 dbgi_idx = 0;
E_Module *module = &e_module_nil; E_Module *module = &e_module_nil;
for EachIndex(idx, e_base_ctx->modules_count) for EachIndex(idx, e_base_ctx->modules_count)
{ {
if(e_base_ctx->modules[idx].rdi == rdi) if(e_base_ctx->modules[idx].dbg_info_num == dbg_info_num)
{ {
module = &e_base_ctx->modules[idx]; module = &e_base_ctx->modules[idx];
dbgi_idx = (U32)idx; if(module == e_base_ctx->primary_module || e_space_match(module->space, e_base_ctx->primary_module->space))
if(module == e_base_ctx->primary_module ||
e_space_match(module->space, e_base_ctx->primary_module->space))
{ {
break; break;
} }
@@ -1945,7 +1960,7 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, E_I
} }
// rjf: form result // rjf: form result
if(match.idx != 0 && module != &e_module_nil) if(match.idx != 0 && dbg_info != &e_dbg_info_nil)
{ {
switch(match.section_kind) switch(match.section_kind)
{ {
@@ -1958,7 +1973,7 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, E_I
E_OpList oplist = {0}; E_OpList oplist = {0};
e_oplist_push_op(arena, &oplist, RDI_EvalOp_ConstU64, e_value_u64(module->vaddr_range.min + global_var->voff)); e_oplist_push_op(arena, &oplist, RDI_EvalOp_ConstU64, e_value_u64(module->vaddr_range.min + global_var->voff));
string_mapped = 1; string_mapped = 1;
mapped_type_key = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), type_idx, dbgi_idx); mapped_type_key = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), type_idx, dbg_info_num);
mapped_bytecode = e_bytecode_from_oplist(arena, &oplist); mapped_bytecode = e_bytecode_from_oplist(arena, &oplist);
mapped_bytecode_mode = E_Mode_Offset; mapped_bytecode_mode = E_Mode_Offset;
mapped_bytecode_space = module->space; mapped_bytecode_space = module->space;
@@ -1971,7 +1986,7 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, E_I
E_OpList oplist = {0}; E_OpList oplist = {0};
e_oplist_push_op(arena, &oplist, RDI_EvalOp_TLSOff, e_value_u64(thread_var->tls_off)); e_oplist_push_op(arena, &oplist, RDI_EvalOp_TLSOff, e_value_u64(thread_var->tls_off));
string_mapped = 1; string_mapped = 1;
mapped_type_key = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), type_idx, dbgi_idx); mapped_type_key = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), type_idx, dbg_info_num);
mapped_bytecode = e_bytecode_from_oplist(arena, &oplist); mapped_bytecode = e_bytecode_from_oplist(arena, &oplist);
mapped_bytecode_mode = E_Mode_Offset; mapped_bytecode_mode = E_Mode_Offset;
mapped_bytecode_space = module->space; mapped_bytecode_space = module->space;
@@ -1994,7 +2009,7 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, E_I
E_OpList oplist = {0}; E_OpList oplist = {0};
e_oplist_push_op(arena, &oplist, RDI_EvalOp_ConstU64, e_value_u64(value)); e_oplist_push_op(arena, &oplist, RDI_EvalOp_ConstU64, e_value_u64(value));
string_mapped = 1; string_mapped = 1;
mapped_type_key = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), type_idx, dbgi_idx); mapped_type_key = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), type_idx, dbg_info_num);
mapped_bytecode = e_bytecode_from_oplist(arena, &oplist); mapped_bytecode = e_bytecode_from_oplist(arena, &oplist);
mapped_bytecode_mode = E_Mode_Value; mapped_bytecode_mode = E_Mode_Value;
mapped_bytecode_space = module->space; mapped_bytecode_space = module->space;
@@ -2012,7 +2027,7 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, E_I
E_OpList oplist = {0}; E_OpList oplist = {0};
e_oplist_push_op(arena, &oplist, RDI_EvalOp_ConstU64, e_value_u64(module->vaddr_range.min + voff)); e_oplist_push_op(arena, &oplist, RDI_EvalOp_ConstU64, e_value_u64(module->vaddr_range.min + voff));
string_mapped = 1; string_mapped = 1;
mapped_type_key = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), type_idx, dbgi_idx); mapped_type_key = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), type_idx, dbg_info_num);
mapped_bytecode = e_bytecode_from_oplist(arena, &oplist); mapped_bytecode = e_bytecode_from_oplist(arena, &oplist);
mapped_bytecode_mode = E_Mode_Value; mapped_bytecode_mode = E_Mode_Value;
mapped_bytecode_space = module->space; mapped_bytecode_space = module->space;
@@ -2021,7 +2036,7 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, E_I
{ {
U32 type_idx = match.idx; U32 type_idx = match.idx;
RDI_TypeNode *type_node = rdi_element_from_name_idx(rdi, TypeNodes, type_idx); RDI_TypeNode *type_node = rdi_element_from_name_idx(rdi, TypeNodes, type_idx);
mapped_type_key = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), type_idx, dbgi_idx); mapped_type_key = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), type_idx, dbg_info_num);
string_mapped = 1; string_mapped = 1;
}break; }break;
} }
@@ -2106,9 +2121,10 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, E_I
if(!generated && mapped_location_block != 0) if(!generated && mapped_location_block != 0)
{ {
E_Module *module = mapped_location_block_module; E_Module *module = mapped_location_block_module;
E_DbgInfo *dbg_info = e_dbg_info_from_module(module);
E_Space space = module->space; E_Space space = module->space;
Arch arch = module->arch; Arch arch = module->arch;
RDI_Parsed *rdi = module->rdi; RDI_Parsed *rdi = dbg_info->rdi;
RDI_LocationBlock *block = mapped_location_block; RDI_LocationBlock *block = mapped_location_block;
U64 all_location_data_size = 0; U64 all_location_data_size = 0;
U8 *all_location_data = rdi_table_from_name(rdi, LocationData, &all_location_data_size); U8 *all_location_data = rdi_table_from_name(rdi, LocationData, &all_location_data_size);
@@ -2461,17 +2477,18 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, E_I
if(e_space_read(interpret.space, &vtable_vaddr, r1u64(class_base_vaddr, class_base_vaddr+addr_size))) if(e_space_read(interpret.space, &vtable_vaddr, r1u64(class_base_vaddr, class_base_vaddr+addr_size)))
{ {
Arch arch = e_base_ctx->primary_module->arch; Arch arch = e_base_ctx->primary_module->arch;
U32 rdi_idx = 0; U32 dbg_info_num = 0;
RDI_Parsed *rdi = 0; RDI_Parsed *rdi = 0;
U64 module_base = 0; U64 module_base = 0;
for(U64 idx = 0; idx < e_base_ctx->modules_count; idx += 1) for(U64 idx = 0; idx < e_base_ctx->modules_count; idx += 1)
{ {
if(contains_1u64(e_base_ctx->modules[idx].vaddr_range, vtable_vaddr)) if(contains_1u64(e_base_ctx->modules[idx].vaddr_range, vtable_vaddr))
{ {
E_DbgInfo *dbg_info = e_dbg_info_from_module(&e_base_ctx->modules[idx]);
arch = e_base_ctx->modules[idx].arch; arch = e_base_ctx->modules[idx].arch;
rdi_idx = (U32)idx;
rdi = e_base_ctx->modules[idx].rdi;
module_base = e_base_ctx->modules[idx].vaddr_range.min; module_base = e_base_ctx->modules[idx].vaddr_range.min;
dbg_info_num = e_base_ctx->modules[idx].dbg_info_num;
rdi = dbg_info->rdi;
break; break;
} }
} }
@@ -2484,7 +2501,7 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, E_I
{ {
RDI_UDT *udt = rdi_element_from_name_idx(rdi, UDTs, global_var->container_idx); RDI_UDT *udt = rdi_element_from_name_idx(rdi, UDTs, global_var->container_idx);
RDI_TypeNode *type = rdi_element_from_name_idx(rdi, TypeNodes, udt->self_type_idx); RDI_TypeNode *type = rdi_element_from_name_idx(rdi, TypeNodes, udt->self_type_idx);
E_TypeKey derived_type_key = e_type_key_ext(e_type_kind_from_rdi(type->kind), udt->self_type_idx, rdi_idx); E_TypeKey derived_type_key = e_type_key_ext(e_type_kind_from_rdi(type->kind), udt->self_type_idx, dbg_info_num);
E_TypeKey ptr_to_derived_type_key = e_type_key_cons_ptr(arch, derived_type_key, 1, 0); E_TypeKey ptr_to_derived_type_key = e_type_key_cons_ptr(arch, derived_type_key, 1, 0);
result.type_key = ptr_to_derived_type_key; result.type_key = ptr_to_derived_type_key;
} }
+5 -5
View File
@@ -585,19 +585,19 @@ e_leaf_type_key_from_name(String8 name)
E_TypeKey key = e_leaf_builtin_type_key_from_name(name); E_TypeKey key = e_leaf_builtin_type_key_from_name(name);
if(!e_type_key_match(e_type_key_zero(), key)) if(!e_type_key_match(e_type_key_zero(), key))
{ {
DI_Match match = di_match_from_string(name, 0, e_base_ctx->primary_module->dbgi_key, 0); DI_Match match = di_match_from_string(name, 0, e_base_ctx->primary_dbg_info->dbgi_key, 0);
if(match.section_kind == RDI_SectionKind_TypeNodes) if(match.section_kind == RDI_SectionKind_TypeNodes)
{ {
Access *access = access_open(); Access *access = access_open();
RDI_Parsed *rdi = di_rdi_from_key(access, match.key, 0, 0); RDI_Parsed *rdi = di_rdi_from_key(access, match.key, 0, 0);
for EachIndex(idx, e_base_ctx->modules_count) for EachIndex(idx, e_base_ctx->dbg_infos_count)
{ {
E_Module *module = &e_base_ctx->modules[idx]; E_DbgInfo *dbg_info = &e_base_ctx->dbg_infos[idx];
if(module->rdi == rdi) if(dbg_info->rdi == rdi)
{ {
U32 type_idx = match.idx; U32 type_idx = match.idx;
RDI_TypeNode *type_node = rdi_element_from_name_idx(rdi, TypeNodes, type_idx); RDI_TypeNode *type_node = rdi_element_from_name_idx(rdi, TypeNodes, type_idx);
key = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), type_idx, (U32)idx); key = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), type_idx, (U32)idx+1);
break; break;
} }
} }
+307 -290
View File
@@ -271,7 +271,7 @@ e_type_key_basic(E_TypeKind kind)
} }
internal E_TypeKey internal E_TypeKey
e_type_key_ext(E_TypeKind kind, U32 type_idx, U32 rdi_idx) e_type_key_ext(E_TypeKind kind, U32 type_idx, U32 rdi_num)
{ {
E_TypeKey key = {E_TypeKeyKind_Ext}; E_TypeKey key = {E_TypeKeyKind_Ext};
key.u32[0] = (U32)kind; key.u32[0] = (U32)kind;
@@ -282,7 +282,7 @@ e_type_key_ext(E_TypeKind kind, U32 type_idx, U32 rdi_idx)
else else
{ {
key.u32[1] = type_idx; key.u32[1] = type_idx;
key.u32[2] = rdi_idx; key.u32[2] = rdi_num;
} }
return key; return key;
} }
@@ -646,10 +646,13 @@ e_type_byte_size_from_key(E_TypeKey key)
case E_TypeKeyKind_Ext: case E_TypeKeyKind_Ext:
{ {
U64 type_node_idx = key.u32[1]; U64 type_node_idx = key.u32[1];
U32 rdi_idx = key.u32[2]; U32 rdi_num = key.u32[2];
RDI_Parsed *rdi = e_base_ctx->modules[rdi_idx].rdi; if(0 < rdi_num && rdi_num <= e_base_ctx->dbg_infos_count)
RDI_TypeNode *rdi_type = rdi_element_from_name_idx(rdi, TypeNodes, type_node_idx); {
result = rdi_type->byte_size; RDI_Parsed *rdi = e_base_ctx->dbg_infos[rdi_num-1].rdi;
RDI_TypeNode *rdi_type = rdi_element_from_name_idx(rdi, TypeNodes, type_node_idx);
result = rdi_type->byte_size;
}
}break; }break;
case E_TypeKeyKind_Cons: case E_TypeKeyKind_Cons:
{ {
@@ -758,322 +761,327 @@ e_push_type_from_key(Arena *arena, E_TypeKey key)
case E_TypeKeyKind_Ext: case E_TypeKeyKind_Ext:
{ {
U64 type_node_idx = key.u32[1]; U64 type_node_idx = key.u32[1];
U32 rdi_idx = key.u32[2]; U32 rdi_num = key.u32[2];
RDI_Parsed *rdi = e_base_ctx->modules[rdi_idx].rdi; if(0 < rdi_num && rdi_num <= e_base_ctx->dbg_infos_count)
RDI_TypeNode *rdi_type = rdi_element_from_name_idx(rdi, TypeNodes, type_node_idx);
if(rdi_type->kind != RDI_TypeKind_NULL)
{ {
E_TypeKind kind = e_type_kind_from_rdi(rdi_type->kind); RDI_Parsed *rdi = e_base_ctx->dbg_infos[rdi_num-1].rdi;
RDI_TopLevelInfo *tli = rdi_element_from_name_idx(rdi, TopLevelInfo, 0);
//- rjf: record types => unpack name * members & produce Arch arch = arch_from_rdi_arch(tli->arch);
if(RDI_TypeKind_FirstRecord <= rdi_type->kind && rdi_type->kind <= RDI_TypeKind_LastRecord) RDI_TypeNode *rdi_type = rdi_element_from_name_idx(rdi, TypeNodes, type_node_idx);
if(rdi_type->kind != RDI_TypeKind_NULL)
{ {
// rjf: unpack name E_TypeKind kind = e_type_kind_from_rdi(rdi_type->kind);
String8 name = {0};
name.str = rdi_string_from_idx(rdi, rdi_type->user_defined.name_string_idx, &name.size);
// rjf: unpack UDT info //- rjf: record types => unpack name * members & produce
RDI_UDT *udt = rdi_element_from_name_idx(rdi, UDTs, rdi_type->user_defined.udt_idx); if(RDI_TypeKind_FirstRecord <= rdi_type->kind && rdi_type->kind <= RDI_TypeKind_LastRecord)
// rjf: unpack members
E_Member *members = 0;
U32 members_count = 0;
{ {
members_count = udt->member_count; // rjf: unpack name
members = push_array(arena, E_Member, members_count); String8 name = {0};
if(members_count != 0) name.str = rdi_string_from_idx(rdi, rdi_type->user_defined.name_string_idx, &name.size);
// rjf: unpack UDT info
RDI_UDT *udt = rdi_element_from_name_idx(rdi, UDTs, rdi_type->user_defined.udt_idx);
// rjf: unpack members
E_Member *members = 0;
U32 members_count = 0;
{ {
members_count = udt->member_count;
members = push_array(arena, E_Member, members_count);
if(members_count != 0)
{
for(U32 member_idx = udt->member_first;
member_idx < udt->member_first+udt->member_count;
member_idx += 1)
{
RDI_Member *src = rdi_element_from_name_idx(rdi, Members, member_idx);
E_TypeKind member_type_kind = E_TypeKind_Null;
RDI_TypeNode *member_type = rdi_element_from_name_idx(rdi, TypeNodes, src->type_idx);
member_type_kind = e_type_kind_from_rdi(member_type->kind);
E_Member *dst = &members[member_idx-udt->member_first];
dst->kind = e_member_kind_from_rdi(src->kind);
dst->type_key = e_type_key_ext(member_type_kind, src->type_idx, rdi_num);
dst->name.str = rdi_string_from_idx(rdi, src->name_string_idx, &dst->name.size);
dst->off = (U64)src->off;
}
}
}
// rjf: produce
type = push_array(arena, E_Type, 1);
type->kind = kind;
type->name = push_str8_copy(arena, name);
type->byte_size = (U64)rdi_type->byte_size;
type->count = members_count;
type->arch = arch;
type->members = members;
}
//- rjf: enum types => unpack name * values & produce
else if(rdi_type->kind == RDI_TypeKind_Enum)
{
// rjf: unpack name
String8 name = {0};
name.str = rdi_string_from_idx(rdi, rdi_type->user_defined.name_string_idx, &name.size);
// rjf: unpack direct type
E_TypeKey direct_type_key = zero_struct;
if(rdi_type->user_defined.direct_type_idx < type_node_idx)
{
RDI_TypeNode *direct_type_node = rdi_element_from_name_idx(rdi, TypeNodes, rdi_type->user_defined.direct_type_idx);
E_TypeKind direct_type_kind = e_type_kind_from_rdi(direct_type_node->kind);
direct_type_key = e_type_key_ext(direct_type_kind, rdi_type->user_defined.direct_type_idx, rdi_num);
}
// rjf: unpack members
E_EnumVal *enum_vals = 0;
U32 enum_vals_count = 0;
{
U32 udt_idx = rdi_type->user_defined.udt_idx;
RDI_UDT *udt = rdi_element_from_name_idx(rdi, UDTs, udt_idx);
enum_vals_count = udt->member_count;
enum_vals = push_array(arena, E_EnumVal, enum_vals_count);
for(U32 member_idx = udt->member_first; for(U32 member_idx = udt->member_first;
member_idx < udt->member_first+udt->member_count; member_idx < udt->member_first+udt->member_count;
member_idx += 1) member_idx += 1)
{ {
RDI_Member *src = rdi_element_from_name_idx(rdi, Members, member_idx); RDI_EnumMember *src = rdi_element_from_name_idx(rdi, EnumMembers, member_idx);
E_TypeKind member_type_kind = E_TypeKind_Null; E_EnumVal *dst = &enum_vals[member_idx-udt->member_first];
RDI_TypeNode *member_type = rdi_element_from_name_idx(rdi, TypeNodes, src->type_idx);
member_type_kind = e_type_kind_from_rdi(member_type->kind);
E_Member *dst = &members[member_idx-udt->member_first];
dst->kind = e_member_kind_from_rdi(src->kind);
dst->type_key = e_type_key_ext(member_type_kind, src->type_idx, rdi_idx);
dst->name.str = rdi_string_from_idx(rdi, src->name_string_idx, &dst->name.size); dst->name.str = rdi_string_from_idx(rdi, src->name_string_idx, &dst->name.size);
dst->off = (U64)src->off; dst->val = src->val;
} }
} }
}
// rjf: produce
type = push_array(arena, E_Type, 1);
type->kind = kind;
type->name = push_str8_copy(arena, name);
type->byte_size = (U64)rdi_type->byte_size;
type->count = members_count;
type->arch = e_base_ctx->modules[rdi_idx].arch;
type->members = members;
}
//- rjf: enum types => unpack name * values & produce
else if(rdi_type->kind == RDI_TypeKind_Enum)
{
// rjf: unpack name
String8 name = {0};
name.str = rdi_string_from_idx(rdi, rdi_type->user_defined.name_string_idx, &name.size);
// rjf: unpack direct type
E_TypeKey direct_type_key = zero_struct;
if(rdi_type->user_defined.direct_type_idx < type_node_idx)
{
RDI_TypeNode *direct_type_node = rdi_element_from_name_idx(rdi, TypeNodes, rdi_type->user_defined.direct_type_idx);
E_TypeKind direct_type_kind = e_type_kind_from_rdi(direct_type_node->kind);
direct_type_key = e_type_key_ext(direct_type_kind, rdi_type->user_defined.direct_type_idx, rdi_idx);
}
// rjf: unpack members
E_EnumVal *enum_vals = 0;
U32 enum_vals_count = 0;
{
U32 udt_idx = rdi_type->user_defined.udt_idx;
RDI_UDT *udt = rdi_element_from_name_idx(rdi, UDTs, udt_idx);
enum_vals_count = udt->member_count;
enum_vals = push_array(arena, E_EnumVal, enum_vals_count);
for(U32 member_idx = udt->member_first;
member_idx < udt->member_first+udt->member_count;
member_idx += 1)
{
RDI_EnumMember *src = rdi_element_from_name_idx(rdi, EnumMembers, member_idx);
E_EnumVal *dst = &enum_vals[member_idx-udt->member_first];
dst->name.str = rdi_string_from_idx(rdi, src->name_string_idx, &dst->name.size);
dst->val = src->val;
}
}
// rjf: produce
type = push_array(arena, E_Type, 1);
type->kind = kind;
type->name = push_str8_copy(arena, name);
type->byte_size = (U64)rdi_type->byte_size;
type->count = enum_vals_count;
type->arch = e_base_ctx->modules[rdi_idx].arch;
type->enum_vals = enum_vals;
type->direct_type_key = direct_type_key;
}
//- rjf: constructed types
else if(RDI_TypeKind_FirstConstructed <= rdi_type->kind && rdi_type->kind <= RDI_TypeKind_LastConstructed)
{
// rjf: unpack direct type
B32 direct_type_is_good = 0;
E_TypeKey direct_type_key = zero_struct;
U64 direct_type_byte_size = 0;
if(rdi_type->constructed.direct_type_idx < type_node_idx)
{
RDI_TypeNode *direct_type_node = rdi_element_from_name_idx(rdi, TypeNodes, rdi_type->constructed.direct_type_idx);
E_TypeKind direct_type_kind = e_type_kind_from_rdi(direct_type_node->kind);
direct_type_key = e_type_key_ext(direct_type_kind, rdi_type->constructed.direct_type_idx, rdi_idx);
direct_type_is_good = 1;
direct_type_byte_size = (U64)direct_type_node->byte_size;
}
// rjf: construct based on kind
switch(rdi_type->kind)
{
case RDI_TypeKind_Modifier:
{
E_TypeFlags flags = 0;
if(rdi_type->flags & RDI_TypeModifierFlag_Const)
{
flags |= E_TypeFlag_Const;
}
if(rdi_type->flags & RDI_TypeModifierFlag_Volatile)
{
flags |= E_TypeFlag_Volatile;
}
if(rdi_type->flags & RDI_TypeModifierFlag_Restrict)
{
flags |= E_TypeFlag_Restrict;
}
type = push_array(arena, E_Type, 1);
type->kind = kind;
type->direct_type_key = direct_type_key;
type->byte_size = direct_type_byte_size;
type->flags = flags;
type->arch = e_base_ctx->modules[rdi_idx].arch;
}break;
case RDI_TypeKind_Ptr:
case RDI_TypeKind_LRef:
case RDI_TypeKind_RRef:
{
type = push_array(arena, E_Type, 1);
type->kind = kind;
type->direct_type_key = direct_type_key;
type->byte_size = bit_size_from_arch(e_base_ctx->modules[rdi_idx].arch)/8;
type->count = 1;
type->arch = e_base_ctx->modules[rdi_idx].arch;
}break;
case RDI_TypeKind_Array: // rjf: produce
type = push_array(arena, E_Type, 1);
type->kind = kind;
type->name = push_str8_copy(arena, name);
type->byte_size = (U64)rdi_type->byte_size;
type->count = enum_vals_count;
type->arch = arch;
type->enum_vals = enum_vals;
type->direct_type_key = direct_type_key;
}
//- rjf: constructed types
else if(RDI_TypeKind_FirstConstructed <= rdi_type->kind && rdi_type->kind <= RDI_TypeKind_LastConstructed)
{
// rjf: unpack direct type
B32 direct_type_is_good = 0;
E_TypeKey direct_type_key = zero_struct;
U64 direct_type_byte_size = 0;
if(rdi_type->constructed.direct_type_idx < type_node_idx)
{ {
type = push_array(arena, E_Type, 1); RDI_TypeNode *direct_type_node = rdi_element_from_name_idx(rdi, TypeNodes, rdi_type->constructed.direct_type_idx);
type->kind = kind; E_TypeKind direct_type_kind = e_type_kind_from_rdi(direct_type_node->kind);
type->direct_type_key = direct_type_key; direct_type_key = e_type_key_ext(direct_type_kind, rdi_type->constructed.direct_type_idx, rdi_num);
type->count = rdi_type->constructed.count; direct_type_is_good = 1;
type->byte_size = direct_type_byte_size * type->count; direct_type_byte_size = (U64)direct_type_node->byte_size;
type->arch = e_base_ctx->modules[rdi_idx].arch; }
}break;
case RDI_TypeKind_Function: // rjf: construct based on kind
switch(rdi_type->kind)
{ {
U32 count = rdi_type->constructed.count; case RDI_TypeKind_Modifier:
U32 idx_run_first = rdi_type->constructed.param_idx_run_first;
U32 check_count = 0;
U32 *idx_run = rdi_idx_run_from_first_count(rdi, idx_run_first, count, &check_count);
if(check_count == count)
{ {
E_TypeFlags flags = 0;
if(rdi_type->flags & RDI_TypeModifierFlag_Const)
{
flags |= E_TypeFlag_Const;
}
if(rdi_type->flags & RDI_TypeModifierFlag_Volatile)
{
flags |= E_TypeFlag_Volatile;
}
if(rdi_type->flags & RDI_TypeModifierFlag_Restrict)
{
flags |= E_TypeFlag_Restrict;
}
type = push_array(arena, E_Type, 1); type = push_array(arena, E_Type, 1);
type->kind = kind; type->kind = kind;
type->byte_size = bit_size_from_arch(e_base_ctx->modules[rdi_idx].arch)/8;
type->direct_type_key = direct_type_key; type->direct_type_key = direct_type_key;
type->count = count; type->byte_size = direct_type_byte_size;
type->param_type_keys = push_array(arena, E_TypeKey, type->count); type->flags = flags;
type->arch = e_base_ctx->modules[rdi_idx].arch; type->arch = arch;
for(U32 idx = 0; idx < type->count; idx += 1) }break;
{ case RDI_TypeKind_Ptr:
U32 param_type_idx = idx_run[idx]; case RDI_TypeKind_LRef:
if(param_type_idx < type_node_idx) case RDI_TypeKind_RRef:
{
RDI_TypeNode *param_type_node = rdi_element_from_name_idx(rdi, TypeNodes, param_type_idx);
E_TypeKind param_kind = e_type_kind_from_rdi(param_type_node->kind);
type->param_type_keys[idx] = e_type_key_ext(param_kind, param_type_idx, rdi_idx);
}
else
{
break;
}
}
}
}break;
case RDI_TypeKind_Method:
{
// NOTE(rjf): for methods, the `direct` type points at the owner type.
// the return type, instead of being encoded via the `direct` type, is
// encoded via the first parameter.
U32 count = rdi_type->constructed.count;
U32 idx_run_first = rdi_type->constructed.param_idx_run_first;
U32 check_count = 0;
U32 *idx_run = rdi_idx_run_from_first_count(rdi, idx_run_first, count, &check_count);
if(check_count == count)
{ {
type = push_array(arena, E_Type, 1); type = push_array(arena, E_Type, 1);
type->kind = kind; type->kind = kind;
type->byte_size = bit_size_from_arch(e_base_ctx->modules[rdi_idx].arch)/8; type->direct_type_key = direct_type_key;
type->owner_type_key = direct_type_key; type->byte_size = bit_size_from_arch(arch)/8;
type->count = count; type->count = 1;
type->param_type_keys = push_array_no_zero(arena, E_TypeKey, type->count); type->arch = arch;
type->arch = e_base_ctx->modules[rdi_idx].arch; }break;
for(U32 idx = 0; idx < type->count; idx += 1)
{ case RDI_TypeKind_Array:
U32 param_type_idx = idx_run[idx];
if(param_type_idx < type_node_idx)
{
RDI_TypeNode *param_type_node = rdi_element_from_name_idx(rdi, TypeNodes, param_type_idx);
E_TypeKind param_kind = e_type_kind_from_rdi(param_type_node->kind);
type->param_type_keys[idx] = e_type_key_ext(param_kind, param_type_idx, rdi_idx);
}
else
{
break;
}
}
if(type->count > 0)
{
type->direct_type_key = type->param_type_keys[0];
type->count -= 1;
type->param_type_keys += 1;
}
}
}break;
case RDI_TypeKind_MemberPtr:
{
// rjf: unpack owner type
E_TypeKey owner_type_key = zero_struct;
if(rdi_type->constructed.owner_type_idx < type_node_idx)
{ {
RDI_TypeNode *owner_type_node = rdi_element_from_name_idx(rdi, TypeNodes, rdi_type->constructed.owner_type_idx); type = push_array(arena, E_Type, 1);
E_TypeKind owner_type_kind = e_type_kind_from_rdi(owner_type_node->kind); type->kind = kind;
owner_type_key = e_type_key_ext(owner_type_kind, rdi_type->constructed.owner_type_idx, rdi_idx); type->direct_type_key = direct_type_key;
} type->count = rdi_type->constructed.count;
type = push_array(arena, E_Type, 1); type->byte_size = direct_type_byte_size * type->count;
type->kind = kind; type->arch = arch;
type->byte_size = bit_size_from_arch(e_base_ctx->modules[rdi_idx].arch)/8; }break;
type->owner_type_key = owner_type_key; case RDI_TypeKind_Function:
type->direct_type_key = direct_type_key; {
type->arch = e_base_ctx->modules[rdi_idx].arch; U32 count = rdi_type->constructed.count;
}break; U32 idx_run_first = rdi_type->constructed.param_idx_run_first;
U32 check_count = 0;
U32 *idx_run = rdi_idx_run_from_first_count(rdi, idx_run_first, count, &check_count);
if(check_count == count)
{
type = push_array(arena, E_Type, 1);
type->kind = kind;
type->byte_size = bit_size_from_arch(arch)/8;
type->direct_type_key = direct_type_key;
type->count = count;
type->param_type_keys = push_array(arena, E_TypeKey, type->count);
type->arch = arch;
for(U32 idx = 0; idx < type->count; idx += 1)
{
U32 param_type_idx = idx_run[idx];
if(param_type_idx < type_node_idx)
{
RDI_TypeNode *param_type_node = rdi_element_from_name_idx(rdi, TypeNodes, param_type_idx);
E_TypeKind param_kind = e_type_kind_from_rdi(param_type_node->kind);
type->param_type_keys[idx] = e_type_key_ext(param_kind, param_type_idx, rdi_num);
}
else
{
break;
}
}
}
}break;
case RDI_TypeKind_Method:
{
// NOTE(rjf): for methods, the `direct` type points at the owner type.
// the return type, instead of being encoded via the `direct` type, is
// encoded via the first parameter.
U32 count = rdi_type->constructed.count;
U32 idx_run_first = rdi_type->constructed.param_idx_run_first;
U32 check_count = 0;
U32 *idx_run = rdi_idx_run_from_first_count(rdi, idx_run_first, count, &check_count);
if(check_count == count)
{
type = push_array(arena, E_Type, 1);
type->kind = kind;
type->byte_size = bit_size_from_arch(arch)/8;
type->owner_type_key = direct_type_key;
type->count = count;
type->param_type_keys = push_array_no_zero(arena, E_TypeKey, type->count);
type->arch = arch;
for(U32 idx = 0; idx < type->count; idx += 1)
{
U32 param_type_idx = idx_run[idx];
if(param_type_idx < type_node_idx)
{
RDI_TypeNode *param_type_node = rdi_element_from_name_idx(rdi, TypeNodes, param_type_idx);
E_TypeKind param_kind = e_type_kind_from_rdi(param_type_node->kind);
type->param_type_keys[idx] = e_type_key_ext(param_kind, param_type_idx, rdi_num);
}
else
{
break;
}
}
if(type->count > 0)
{
type->direct_type_key = type->param_type_keys[0];
type->count -= 1;
type->param_type_keys += 1;
}
}
}break;
case RDI_TypeKind_MemberPtr:
{
// rjf: unpack owner type
E_TypeKey owner_type_key = zero_struct;
if(rdi_type->constructed.owner_type_idx < type_node_idx)
{
RDI_TypeNode *owner_type_node = rdi_element_from_name_idx(rdi, TypeNodes, rdi_type->constructed.owner_type_idx);
E_TypeKind owner_type_kind = e_type_kind_from_rdi(owner_type_node->kind);
owner_type_key = e_type_key_ext(owner_type_kind, rdi_type->constructed.owner_type_idx, rdi_num);
}
type = push_array(arena, E_Type, 1);
type->kind = kind;
type->byte_size = bit_size_from_arch(arch)/8;
type->owner_type_key = owner_type_key;
type->direct_type_key = direct_type_key;
type->arch = arch;
}break;
}
} }
}
//- rjf: alias types
else if(rdi_type->kind == RDI_TypeKind_Alias)
{
// rjf: unpack name
String8 name = {0};
name.str = rdi_string_from_idx(rdi, rdi_type->user_defined.name_string_idx, &name.size);
// rjf: unpack direct type //- rjf: alias types
E_TypeKey direct_type_key = zero_struct; else if(rdi_type->kind == RDI_TypeKind_Alias)
U64 direct_type_byte_size = 0;
if(rdi_type->user_defined.direct_type_idx < type_node_idx)
{ {
RDI_TypeNode *direct_type_node = rdi_element_from_name_idx(rdi, TypeNodes, rdi_type->user_defined.direct_type_idx); // rjf: unpack name
E_TypeKind direct_type_kind = e_type_kind_from_rdi(direct_type_node->kind); String8 name = {0};
direct_type_key = e_type_key_ext(direct_type_kind, rdi_type->user_defined.direct_type_idx, rdi_idx); name.str = rdi_string_from_idx(rdi, rdi_type->user_defined.name_string_idx, &name.size);
direct_type_byte_size = direct_type_node->byte_size;
// rjf: unpack direct type
E_TypeKey direct_type_key = zero_struct;
U64 direct_type_byte_size = 0;
if(rdi_type->user_defined.direct_type_idx < type_node_idx)
{
RDI_TypeNode *direct_type_node = rdi_element_from_name_idx(rdi, TypeNodes, rdi_type->user_defined.direct_type_idx);
E_TypeKind direct_type_kind = e_type_kind_from_rdi(direct_type_node->kind);
direct_type_key = e_type_key_ext(direct_type_kind, rdi_type->user_defined.direct_type_idx, rdi_num);
direct_type_byte_size = direct_type_node->byte_size;
}
// rjf: produce
type = push_array(arena, E_Type, 1);
type->kind = kind;
type->name = push_str8_copy(arena, name);
type->byte_size = direct_type_byte_size;
type->direct_type_key = direct_type_key;
type->arch = arch;
} }
// rjf: produce //- rjf: bitfields
type = push_array(arena, E_Type, 1); else if(RDI_TypeKind_Bitfield == rdi_type->kind)
type->kind = kind;
type->name = push_str8_copy(arena, name);
type->byte_size = direct_type_byte_size;
type->direct_type_key = direct_type_key;
type->arch = e_base_ctx->modules[rdi_idx].arch;
}
//- rjf: bitfields
else if(RDI_TypeKind_Bitfield == rdi_type->kind)
{
// rjf: unpack direct type
E_TypeKey direct_type_key = zero_struct;
U64 direct_type_byte_size = 0;
if(rdi_type->bitfield.direct_type_idx < type_node_idx)
{ {
RDI_TypeNode *direct_type_node = rdi_element_from_name_idx(rdi, TypeNodes, rdi_type->bitfield.direct_type_idx); // rjf: unpack direct type
E_TypeKind direct_type_kind = e_type_kind_from_rdi(direct_type_node->kind); E_TypeKey direct_type_key = zero_struct;
direct_type_key = e_type_key_ext(direct_type_kind, rdi_type->bitfield.direct_type_idx, rdi_idx); U64 direct_type_byte_size = 0;
direct_type_byte_size = direct_type_node->byte_size; if(rdi_type->bitfield.direct_type_idx < type_node_idx)
{
RDI_TypeNode *direct_type_node = rdi_element_from_name_idx(rdi, TypeNodes, rdi_type->bitfield.direct_type_idx);
E_TypeKind direct_type_kind = e_type_kind_from_rdi(direct_type_node->kind);
direct_type_key = e_type_key_ext(direct_type_kind, rdi_type->bitfield.direct_type_idx, rdi_num);
direct_type_byte_size = direct_type_node->byte_size;
}
// rjf: produce
type = push_array(arena, E_Type, 1);
type->kind = kind;
type->byte_size = direct_type_byte_size;
type->direct_type_key = direct_type_key;
type->off = (U32)rdi_type->bitfield.off;
type->count = (U64)rdi_type->bitfield.size;
type->arch = arch;
} }
// rjf: produce //- rjf: incomplete types
type = push_array(arena, E_Type, 1); else if(RDI_TypeKind_FirstIncomplete <= rdi_type->kind && rdi_type->kind <= RDI_TypeKind_LastIncomplete)
type->kind = kind; {
type->byte_size = direct_type_byte_size; // rjf: unpack name
type->direct_type_key = direct_type_key; String8 name = {0};
type->off = (U32)rdi_type->bitfield.off; name.str = rdi_string_from_idx(rdi, rdi_type->user_defined.name_string_idx, &name.size);
type->count = (U64)rdi_type->bitfield.size;
type->arch = e_base_ctx->modules[rdi_idx].arch; // rjf: produce
} type = push_array(arena, E_Type, 1);
type->kind = kind;
//- rjf: incomplete types type->name = push_str8_copy(arena, name);
else if(RDI_TypeKind_FirstIncomplete <= rdi_type->kind && rdi_type->kind <= RDI_TypeKind_LastIncomplete) type->arch = arch;
{ }
// rjf: unpack name
String8 name = {0};
name.str = rdi_string_from_idx(rdi, rdi_type->user_defined.name_string_idx, &name.size);
// rjf: produce
type = push_array(arena, E_Type, 1);
type->kind = kind;
type->name = push_str8_copy(arena, name);
type->arch = e_base_ctx->modules[rdi_idx].arch;
} }
} }
}break; }break;
@@ -2653,9 +2661,18 @@ e_list_gather_artifact_create(String8 key, B32 *cancel_signal, B32 *retry_out, U
chunk->count += 1; chunk->count += 1;
total_count += 1; total_count += 1;
//- rjf: record this offset in our hit-offset table
{
U64 hash = u64_hash_from_str8(str8_struct(&off));
U64 slot_idx = hash%hit_slots_count;
HitOffsetNode *n = push_array(scratch.arena, HitOffsetNode, 1);
n->off = off;
SLLStackPush(hit_slots[slot_idx], n);
}
//- rjf: read next offset, advance //- rjf: read next offset, advance
B32 read_stale = 0; B32 read_stale = 0;
B32 read_good = ctrl_process_memory_read(process, r1u64(off + member_element_off, off + member_size), &read_stale, &next_off, 0); B32 read_good = ctrl_process_memory_read(process, r1u64(off + member_element_off, off + member_element_off + member_size), &read_stale, &next_off, 0);
if(read_stale) if(read_stale)
{ {
retry = 1; retry = 1;
+1 -1
View File
@@ -70,7 +70,7 @@ internal E_EnumValArray e_enum_val_array_from_list(Arena *arena, E_EnumValList *
//- rjf: basic key constructors //- rjf: basic key constructors
internal E_TypeKey e_type_key_zero(void); internal E_TypeKey e_type_key_zero(void);
internal E_TypeKey e_type_key_basic(E_TypeKind kind); internal E_TypeKey e_type_key_basic(E_TypeKind kind);
internal E_TypeKey e_type_key_ext(E_TypeKind kind, U32 type_idx, U32 rdi_idx); internal E_TypeKey e_type_key_ext(E_TypeKind kind, U32 type_idx, U32 rdi_num);
internal E_TypeKey e_type_key_reg(Arch arch, REGS_RegCode code); internal E_TypeKey e_type_key_reg(Arch arch, REGS_RegCode code);
internal E_TypeKey e_type_key_reg_alias(Arch arch, REGS_AliasCode code); internal E_TypeKey e_type_key_reg_alias(Arch arch, REGS_AliasCode code);
@@ -150,8 +150,14 @@ ev_type_key_is_editable(E_TypeKey type_key)
B32 done = 0; B32 done = 0;
for(E_TypeKey t = type_key; !result && !done; t = e_type_key_direct(t)) for(E_TypeKey t = type_key; !result && !done; t = e_type_key_direct(t))
{ {
E_TypeKind kind = e_type_kind_from_key(t); E_Type *type = e_type_from_key(t);
switch(kind) E_TypeKind kind = type->kind;
if(type->flags & E_TypeFlag_IsNotEditable)
{
result = 0;
done = 1;
}
else switch(kind)
{ {
case E_TypeKind_Null: case E_TypeKind_Null:
case E_TypeKind_Function: case E_TypeKind_Function:
@@ -167,7 +173,6 @@ ev_type_key_is_editable(E_TypeKey type_key)
}break; }break;
case E_TypeKind_Array: case E_TypeKind_Array:
{ {
E_Type *type = e_type_from_key(t);
if(type->flags & E_TypeFlag_IsNotText) if(type->flags & E_TypeFlag_IsNotText)
{ {
result = 0; result = 0;
@@ -1906,17 +1911,25 @@ ev_string_iter_next(Arena *arena, EV_StringIter *it, String8 *out_string)
{ {
U64 vaddr = ptr_data->value_eval.value.u64; U64 vaddr = ptr_data->value_eval.value.u64;
E_Module *module = &e_module_nil; E_Module *module = &e_module_nil;
U32 module_idx = 0;
for EachIndex(idx, e_base_ctx->modules_count) for EachIndex(idx, e_base_ctx->modules_count)
{ {
if(contains_1u64(e_base_ctx->modules[idx].vaddr_range, vaddr)) if(contains_1u64(e_base_ctx->modules[idx].vaddr_range, vaddr))
{ {
module = &e_base_ctx->modules[idx]; module = &e_base_ctx->modules[idx];
module_idx = (U32)idx;
break; break;
} }
} }
RDI_Parsed *rdi = module->rdi; E_DbgInfo *dbg_info = e_dbg_info_from_module(module);
if(dbg_info == &e_dbg_info_nil)
{
dbg_info = e_dbg_info_from_type_key(type_key);
}
U32 dbg_info_num = 0;
if(dbg_info != &e_dbg_info_nil)
{
dbg_info_num = (U32)(dbg_info - e_base_ctx->dbg_infos) + 1;
}
RDI_Parsed *rdi = dbg_info->rdi;
U64 voff = vaddr - module->vaddr_range.min; U64 voff = vaddr - module->vaddr_range.min;
B32 good_symbol_match = 0; B32 good_symbol_match = 0;
@@ -1965,7 +1978,7 @@ ev_string_iter_next(Arena *arena, EV_StringIter *it, String8 *out_string)
if(inline_site != 0) if(inline_site != 0)
{ {
RDI_TypeNode *type_node = rdi_element_from_name_idx(rdi, TypeNodes, inline_site->type_idx); RDI_TypeNode *type_node = rdi_element_from_name_idx(rdi, TypeNodes, inline_site->type_idx);
E_TypeKey type = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), inline_site->type_idx, module_idx); E_TypeKey type = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), inline_site->type_idx, dbg_info_num);
String8 name = {0}; String8 name = {0};
name.str = rdi_string_from_idx(rdi, inline_site->name_string_idx, &name.size); name.str = rdi_string_from_idx(rdi, inline_site->name_string_idx, &name.size);
if(inline_site->type_idx != 0) if(inline_site->type_idx != 0)
@@ -1995,7 +2008,7 @@ ev_string_iter_next(Arena *arena, EV_StringIter *it, String8 *out_string)
U64 proc_idx = scope->proc_idx; U64 proc_idx = scope->proc_idx;
RDI_Procedure *procedure = rdi_element_from_name_idx(rdi, Procedures, proc_idx); RDI_Procedure *procedure = rdi_element_from_name_idx(rdi, Procedures, proc_idx);
RDI_TypeNode *type_node = rdi_element_from_name_idx(rdi, TypeNodes, procedure->type_idx); RDI_TypeNode *type_node = rdi_element_from_name_idx(rdi, TypeNodes, procedure->type_idx);
E_TypeKey type = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), procedure->type_idx, module_idx); E_TypeKey type = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), procedure->type_idx, dbg_info_num);
String8 name = {0}; String8 name = {0};
name.str = rdi_string_from_idx(rdi, procedure->name_string_idx, &name.size); name.str = rdi_string_from_idx(rdi, procedure->name_string_idx, &name.size);
if(procedure->type_idx != 0) if(procedure->type_idx != 0)
+6 -3
View File
@@ -170,7 +170,7 @@ raddbg_decode_utf8(char *str, unsigned __int64 max)
case 2: case 2:
if(2 < max) if(2 < max)
{ {
char cont_byte = str[1]; unsigned char cont_byte = str[1];
if(raddbg_utf8_class[cont_byte >> 3] == 0) if(raddbg_utf8_class[cont_byte >> 3] == 0)
{ {
result.codepoint = (byte & 0x0000001f) << 6; result.codepoint = (byte & 0x0000001f) << 6;
@@ -181,7 +181,7 @@ raddbg_decode_utf8(char *str, unsigned __int64 max)
case 3: case 3:
if(2 < max) if(2 < max)
{ {
char cont_byte[2] = {str[1], str[2]}; unsigned char cont_byte[2] = {(unsigned char)str[1], (unsigned char)str[2]};
if(raddbg_utf8_class[cont_byte[0] >> 3] == 0 && if(raddbg_utf8_class[cont_byte[0] >> 3] == 0 &&
raddbg_utf8_class[cont_byte[1] >> 3] == 0) raddbg_utf8_class[cont_byte[1] >> 3] == 0)
{ {
@@ -194,7 +194,7 @@ raddbg_decode_utf8(char *str, unsigned __int64 max)
case 4: case 4:
if(3 < max) if(3 < max)
{ {
char cont_byte[3] = {str[1], str[2], str[3]}; unsigned char cont_byte[3] = {(unsigned char)str[1], (unsigned char)str[2], (unsigned char)str[3]};
if(raddbg_utf8_class[cont_byte[0] >> 3] == 0 && if(raddbg_utf8_class[cont_byte[0] >> 3] == 0 &&
raddbg_utf8_class[cont_byte[1] >> 3] == 0 && raddbg_utf8_class[cont_byte[1] >> 3] == 0 &&
raddbg_utf8_class[cont_byte[2] >> 3] == 0) raddbg_utf8_class[cont_byte[2] >> 3] == 0)
@@ -431,6 +431,9 @@ raddbg_annotate_vaddr_range__impl(void *ptr, unsigned __int64 size, char *fmt, .
va_list args; va_list args;
va_start(args, fmt); va_start(args, fmt);
buffer_size = RADDBG_MARKUP_VSNPRINTF(buffer, sizeof(buffer), fmt, args); buffer_size = RADDBG_MARKUP_VSNPRINTF(buffer, sizeof(buffer), fmt, args);
buffer_size = ((buffer_size < 0) ? 0 :
(buffer_size > sizeof(buffer)) ? sizeof(buffer) :
buffer_size);
va_end(args); va_end(args);
} }
+6 -1
View File
@@ -52,6 +52,9 @@ union RDI_SHA1 {RDI_U8 u8[20];};
typedef union RDI_SHA256 RDI_SHA256; typedef union RDI_SHA256 RDI_SHA256;
union RDI_SHA256 {RDI_U8 u8[32]; RDI_U64 u64[4];}; union RDI_SHA256 {RDI_U8 u8[32]; RDI_U64 u64[4];};
typedef union RDI_GUID RDI_GUID;
union RDI_GUID {RDI_U8 u8[16]; RDI_U64 u64[2];};
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
//~ Overridable Enabling/Disabling Of Table Index Typechecking //~ Overridable Enabling/Disabling Of Table Index Typechecking
@@ -64,7 +67,7 @@ union RDI_SHA256 {RDI_U8 u8[32]; RDI_U64 u64[4];};
// "raddbg\0\0" // "raddbg\0\0"
#define RDI_MAGIC_CONSTANT 0x0000676264646172 #define RDI_MAGIC_CONSTANT 0x0000676264646172
#define RDI_ENCODING_VERSION 16 #define RDI_ENCODING_VERSION 17
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
//~ Format Types & Functions //~ Format Types & Functions
@@ -807,6 +810,7 @@ X(RDI_Arch, arch)\
X(RDI_U32, exe_name_string_idx)\ X(RDI_U32, exe_name_string_idx)\
X(RDI_U64, exe_hash)\ X(RDI_U64, exe_hash)\
X(RDI_U64, voff_max)\ X(RDI_U64, voff_max)\
X(RDI_GUID, guid)\
X(RDI_U32, producer_name_string_idx)\ X(RDI_U32, producer_name_string_idx)\
#define RDI_BinarySectionFlags_XList \ #define RDI_BinarySectionFlags_XList \
@@ -1283,6 +1287,7 @@ RDI_Arch arch;
RDI_U32 exe_name_string_idx; RDI_U32 exe_name_string_idx;
RDI_U64 exe_hash; RDI_U64 exe_hash;
RDI_U64 voff_max; RDI_U64 voff_max;
RDI_GUID guid;
RDI_U32 producer_name_string_idx; RDI_U32 producer_name_string_idx;
}; };
+5
View File
@@ -1196,6 +1196,11 @@ rdim_bake_params_concat_in_place(RDIM_BakeParams *dst, RDIM_BakeParams *src)
{ {
dst->top_level_info.voff_max = src->top_level_info.voff_max; dst->top_level_info.voff_max = src->top_level_info.voff_max;
} }
if(dst->top_level_info.guid.u64[0] == 0 &&
dst->top_level_info.guid.u64[1] == 0)
{
dst->top_level_info.guid = src->top_level_info.guid;
}
if(dst->top_level_info.producer_name.size == 0) if(dst->top_level_info.producer_name.size == 0)
{ {
dst->top_level_info.producer_name = src->top_level_info.producer_name; dst->top_level_info.producer_name = src->top_level_info.producer_name;
+1
View File
@@ -499,6 +499,7 @@ struct RDIM_TopLevelInfo
RDIM_String8 exe_name; RDIM_String8 exe_name;
RDI_U64 exe_hash; RDI_U64 exe_hash;
RDI_U64 voff_max; RDI_U64 voff_max;
RDI_GUID guid;
RDIM_String8 producer_name; RDIM_String8 producer_name;
}; };
+2
View File
@@ -584,6 +584,8 @@ type_coverage_eval_tests(void)
SLLNode node1 = {0, &node2, 1}; SLLNode node1 = {0, &node2, 1};
raddbg_pin(list(node1, the_real_next_ptr)); raddbg_pin(list(node1, the_real_next_ptr));
node6.next = &node1;
Alias1 a1 = has_enums.kind; Alias1 a1 = has_enums.kind;
Alias2 a2 = has_enums.flags; Alias2 a2 = has_enums.flags;
Alias3 a3 = has_enums; Alias3 a3 = has_enums;
+10 -1
View File
@@ -548,7 +548,14 @@ os_w32_wnd_proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
case WM_DPICHANGED: case WM_DPICHANGED:
{ {
F32 new_dpi = (F32)(wParam & 0xffff); F32 new_dpi = (F32)(wParam & 0xffff);
RECT suggested_new_rect = *(RECT *)lParam;
window->dpi = new_dpi; window->dpi = new_dpi;
SetWindowPos(window->hwnd, 0,
suggested_new_rect.left,
suggested_new_rect.top,
suggested_new_rect.right - suggested_new_rect.left,
suggested_new_rect.bottom - suggested_new_rect.top,
0);
}break; }break;
//- rjf: [file drop] //- rjf: [file drop]
@@ -565,7 +572,9 @@ os_w32_wnd_proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
U64 name_size = DragQueryFile(drop, idx, 0, 0) + 1; U64 name_size = DragQueryFile(drop, idx, 0, 0) + 1;
U8 *name_ptr = push_array(os_w32_event_arena, U8, name_size); U8 *name_ptr = push_array(os_w32_event_arena, U8, name_size);
DragQueryFile(drop, idx, (char *)name_ptr, name_size); DragQueryFile(drop, idx, (char *)name_ptr, name_size);
str8_list_push(os_w32_event_arena, &event->strings, str8(name_ptr, name_size - 1)); String8 path_string = str8(name_ptr, name_size - 1);
String8 path_string__normalized = path_normalized_from_string(os_w32_event_arena, path_string);
str8_list_push(os_w32_event_arena, &event->strings, path_string__normalized);
} }
DragFinish(drop); DragFinish(drop);
}break; }break;
+4 -2
View File
@@ -1143,9 +1143,11 @@ pdb_has_file_ref(String8 msf_data, String8List file_list, MSF_RawStreamTable *st
Temp temp = temp_begin(scratch.arena); Temp temp = temp_begin(scratch.arena);
String8 path = file_n->string; String8 path = file_n->string;
String8 path_pdbstyle = path_convert_slashes(temp.arena, path, PathStyle_WindowsAbsolute); String8 path_pdbstyle = path_convert_slashes(temp.arena, path, PathStyle_WindowsAbsolute);
U32 off = pdb_strtbl_off_from_string(strtbl, path_pdbstyle); String8 path_pdbstyle_lower = lower_from_str8(temp.arena, path_pdbstyle);
U32 off1 = pdb_strtbl_off_from_string(strtbl, path_pdbstyle);
U32 off2 = pdb_strtbl_off_from_string(strtbl, path_pdbstyle_lower);
temp_end(temp); temp_end(temp);
if(off != max_U32) if(off1 != max_U32 || off2 != max_U32)
{ {
has_ref = 1; has_ref = 1;
break; break;
+1 -1
View File
@@ -851,7 +851,7 @@ rb_thread_entry_point(void *p)
{ {
unique_identifier_string = str8f(arena, "%I64x", bake_params->top_level_info.exe_hash); unique_identifier_string = str8f(arena, "%I64x", bake_params->top_level_info.exe_hash);
} }
if(unique_identifier_string.size == 0 && input_files.first != 0 && input_files.first->v->format == RB_FileFormat_PDB) if(unique_identifier_string.size == 0)
{ {
Temp scratch = scratch_begin(&arena, 1); Temp scratch = scratch_begin(&arena, 1);
String8 msf_data = input_files.first->v->data; String8 msf_data = input_files.first->v->data;
File diff suppressed because one or more lines are too long
+8 -4
View File
@@ -252,6 +252,8 @@ RD_CmdKind_ListBreakpoints,
RD_CmdKind_ClearOutput, RD_CmdKind_ClearOutput,
RD_CmdKind_AddWatchPin, RD_CmdKind_AddWatchPin,
RD_CmdKind_ToggleWatchPin, RD_CmdKind_ToggleWatchPin,
RD_CmdKind_LoadDebugInfo,
RD_CmdKind_UnloadDebugInfo,
RD_CmdKind_AddTypeView, RD_CmdKind_AddTypeView,
RD_CmdKind_AddFilePathMap, RD_CmdKind_AddFilePathMap,
RD_CmdKind_EditUserTheme, RD_CmdKind_EditUserTheme,
@@ -292,6 +294,7 @@ RD_CmdKind_OpenCallStack,
RD_CmdKind_OpenTargets, RD_CmdKind_OpenTargets,
RD_CmdKind_OpenBreakpoints, RD_CmdKind_OpenBreakpoints,
RD_CmdKind_OpenWatchPins, RD_CmdKind_OpenWatchPins,
RD_CmdKind_OpenDebugInfos,
RD_CmdKind_OpenThreads, RD_CmdKind_OpenThreads,
RD_CmdKind_OpenProcesses, RD_CmdKind_OpenProcesses,
RD_CmdKind_OpenMachines, RD_CmdKind_OpenMachines,
@@ -525,6 +528,7 @@ X(call_stack) \
X(targets) \ X(targets) \
X(breakpoints) \ X(breakpoints) \
X(watch_pins) \ X(watch_pins) \
X(debug_infos) \
X(threads) \ X(threads) \
X(processes) \ X(processes) \
X(machines) \ X(machines) \
@@ -589,10 +593,10 @@ Z(getting_started)\
.os_event = rd_regs()->os_event,\ .os_event = rd_regs()->os_event,\
C_LINKAGE_BEGIN C_LINKAGE_BEGIN
extern String8 rd_tab_fast_path_view_name_table[24]; extern String8 rd_tab_fast_path_view_name_table[25];
extern String8 rd_tab_fast_path_query_name_table[24]; extern String8 rd_tab_fast_path_query_name_table[25];
extern RD_VocabInfo rd_vocab_info_table[352]; extern RD_VocabInfo rd_vocab_info_table[358];
extern RD_NameSchemaInfo rd_name_schema_info_table[25]; extern RD_NameSchemaInfo rd_name_schema_info_table[26];
extern String8 rd_reg_slot_code_name_table[47]; extern String8 rd_reg_slot_code_name_table[47];
extern Rng1U64 rd_reg_slot_range_table[47]; extern Rng1U64 rd_reg_slot_range_table[47];
extern String8 rd_binding_version_remap_old_name_table[8]; extern String8 rd_binding_version_remap_old_name_table[8];
+23
View File
@@ -33,6 +33,7 @@ RD_WatchTabFastPathTable:
{Targets "Targets" targets 1 Target "Displays, and allows editing of, the list of all targets."} {Targets "Targets" targets 1 Target "Displays, and allows editing of, the list of all targets."}
{Breakpoints "Breakpoints" breakpoints 1 CircleFilled "Displays, and allows editing of, the list of all breakpoints."} {Breakpoints "Breakpoints" breakpoints 1 CircleFilled "Displays, and allows editing of, the list of all breakpoints."}
{WatchPins "Watch Pins" watch_pins 1 Pin "Displays, and allows editing of, the list of all watch pins."} {WatchPins "Watch Pins" watch_pins 1 Pin "Displays, and allows editing of, the list of all watch pins."}
{DebugInfos "Debug Info" debug_infos 1 Module "Displays, and allows editing of, the list of all debug info files that the debugger has loaded."}
{Threads "Threads" threads 1 Threads "Displays the list of all threads in all processes to which the debugger is attached."} {Threads "Threads" threads 1 Threads "Displays the list of all threads in all processes to which the debugger is attached."}
{Processes "Processes" processes 1 Scheduler "Displays the list of all processes to which the debugger is attached."} {Processes "Processes" processes 1 Scheduler "Displays the list of all processes to which the debugger is attached."}
{Machines "Machines" machines 1 Machine "Displays the list of all machines to which the debugger is connected."} {Machines "Machines" machines 1 Machine "Displays the list of all machines to which the debugger is connected."}
@@ -91,6 +92,7 @@ RD_VocabTable:
{type_view _ "Type View" _ Binoculars } {type_view _ "Type View" _ Binoculars }
{file_path_map _ "File Path Map" _ FileOutline } {file_path_map _ "File Path Map" _ FileOutline }
{watch_pin _ "Watch Pin" _ Pin } {watch_pin _ "Watch Pin" _ Pin }
{debug_info _ "Debug Info" "Debug Info" Module }
{watch watches "Watch" "Watches" Binoculars } {watch watches "Watch" "Watches" Binoculars }
{view _ "View" _ Binoculars } {view _ "View" _ Binoculars }
{breakpoint _ "Breakpoint" _ CircleFilled } {breakpoint _ "Breakpoint" _ CircleFilled }
@@ -196,6 +198,8 @@ RD_VocabTable:
{row_height "" "Row Height" "" Null } {row_height "" "Row Height" "" Null }
{tab_height "" "Tab Height" "" Null } {tab_height "" "Tab Height" "" Null }
{rgba "" "RGBA" "" Palette } {rgba "" "RGBA" "" Palette }
{path "" "Path" "" FileOutline }
{guid "" "GUID" "" Null }
} }
@struct RD_VocabInfo: @struct RD_VocabInfo:
@@ -657,6 +661,21 @@ RD_VocabTable:
```, ```,
} }
//- rjf: debug infos
{
debug_info,
```
@row_commands(enable_cfg, duplicate_cfg, remove_cfg)
@collection_commands(load_debug_info)
x:
{
'path': @no_relativize path,
@query 'guid': string,
@no_revert @no_expand @default(1) 'enabled': bool,
}
```,
}
//- rjf: file path maps //- rjf: file path maps
{ {
file_path_map, file_path_map,
@@ -1044,6 +1063,10 @@ RD_CmdTable: // | | | |
{AddWatchPin 1 1 0 0 "" Expr null Nil Null 0 0 0 0 1 1 1 Pin "add_watch_pin" "Add Watch Pin" "Places a watch pin at a given location (file path and line number or address)." "" "$watch_pins," } {AddWatchPin 1 1 0 0 "" Expr null Nil Null 0 0 0 0 1 1 1 Pin "add_watch_pin" "Add Watch Pin" "Places a watch pin at a given location (file path and line number or address)." "" "$watch_pins," }
{ToggleWatchPin 1 0 0 0 "" Expr null Nil Null 0 0 0 0 1 1 1 Pin "toggle_watch_pin" "Toggle Watch Pin" "Places or removes a watch pin at a given location (file path and line number or address)." "" "" } {ToggleWatchPin 1 0 0 0 "" Expr null Nil Null 0 0 0 0 1 1 1 Pin "toggle_watch_pin" "Toggle Watch Pin" "Places or removes a watch pin at a given location (file path and line number or address)." "" "" }
//- rjf: debug infos
{LoadDebugInfo 1 1 0 0 `folder:\\"$input\\"` FilePath null Nil Null 1 0 0 0 0 1 1 Module "load_debug_info" "Load Debug Info" "Loads a debug info file." "" "$debug_infos," }
{UnloadDebugInfo 1 1 0 0 "query:debug_infos" Cfg null Nil Null 0 0 0 0 1 1 1 Module "unload_debug_info" "Unload Debug Info" "Unloads a debug info file." "" "$debug_infos," }
//- rjf: type views //- rjf: type views
{AddTypeView 0 0 0 0 "" String null Nil Null 0 0 0 0 0 0 0 Binoculars "add_type_view" "Add Type View" "Adds a new type view." "" "" } {AddTypeView 0 0 0 0 "" String null Nil Null 0 0 0 0 0 0 0 Binoculars "add_type_view" "Add Type View" "Adds a new type view." "" "" }
+440 -115
View File
@@ -789,7 +789,7 @@ rd_eval_space_read(E_Space space, void *out, Rng1U64 range)
//- rjf: meta-config reads //- rjf: meta-config reads
case RD_EvalSpaceKind_MetaCfg: case RD_EvalSpaceKind_MetaCfg:
{ {
// rjf: unpack cfg //- rjf: unpack cfg
CFG_Node *root_cfg = rd_cfg_from_eval_space(space); CFG_Node *root_cfg = rd_cfg_from_eval_space(space);
String8 child_key = e_string_from_id(space.u64s[1]); String8 child_key = e_string_from_id(space.u64s[1]);
CFG_Node *cfg = root_cfg; CFG_Node *cfg = root_cfg;
@@ -798,54 +798,85 @@ rd_eval_space_read(E_Space space, void *out, Rng1U64 range)
cfg = cfg_node_child_from_string(root_cfg, child_key); cfg = cfg_node_child_from_string(root_cfg, child_key);
} }
// rjf: determine data to read from, depending on child type in schema //- rjf: determine data to read from, depending on child type in schema
String8 read_data = {0}; String8 read_data = {0};
if(child_key.size != 0) if(child_key.size != 0)
{ {
MD_NodePtrList schemas = cfg_schemas_from_name(scratch.arena, rd_state->cfg_schema_table, root_cfg->string); // rjf: get schemas for the accessed child
MD_Node *expr_child_schema = &md_nil_node;
MD_Node *child_schema = &md_nil_node; MD_Node *child_schema = &md_nil_node;
for(MD_NodePtrNode *n = schemas.first; n != 0 && child_schema == &md_nil_node; n = n->next) MD_Node *expr_child_schema = &md_nil_node;
{ {
child_schema = md_child_from_string(n->v, child_key, 0); MD_NodePtrList schemas = cfg_schemas_from_name(scratch.arena, rd_state->cfg_schema_table, root_cfg->string);
if(child_schema != &md_nil_node) for(MD_NodePtrNode *n = schemas.first; n != 0 && child_schema == &md_nil_node; n = n->next)
{ {
expr_child_schema = md_child_from_string(n->v, str8_lit("expression"), 0); child_schema = md_child_from_string(n->v, child_key, 0);
if(child_schema != &md_nil_node)
{
expr_child_schema = md_child_from_string(n->v, str8_lit("expression"), 0);
}
} }
} }
String8 child_type_name = child_schema->first->string; String8 child_type_name = child_schema->first->string;
// rjf: get value string (or default fallback)
String8 value_string = cfg->first->string;
if(value_string.size == 0)
{
value_string = md_tag_from_string(child_schema, str8_lit("default"), 0)->first->string;
}
// rjf: if this is an override child to a parent, fall back on defaults from parents
if(value_string.size == 0 && !md_node_is_nil(md_tag_from_string(child_schema, str8_lit("override"), 0)))
{
for(CFG_Node *parent = root_cfg->parent; parent != &cfg_nil_node; parent = parent->parent)
{
CFG_Node *parent_child_w_key = cfg_node_child_from_string(parent, child_key);
if(parent_child_w_key != &cfg_nil_node)
{
value_string = parent_child_w_key->first->string;
break;
}
value_string = rd_default_setting_from_names(parent->string, child_key);
if(value_string.size != 0)
{
break;
}
}
}
// rjf: if this is a query -> compute the value string based on query path
if(md_node_has_tag(child_schema, str8_lit("query"), 0))
{
// TODO(rjf): this needs to be replaced by hooks
if(str8_match(child_schema->string, str8_lit("guid"), 0))
{
Access *access = access_open();
String8 path = rd_path_from_cfg(root_cfg);
U64 timestamp = 0;
try_u64_from_str8_c_rules(cfg_node_child_from_string(root_cfg, str8_lit("timestamp"))->first->string, &timestamp);
DI_Key key = di_key_from_path_timestamp(path, timestamp);
RDI_Parsed *rdi = di_rdi_from_key(access, key, 0, 0);
RDI_TopLevelInfo *tli = rdi_element_from_name_idx(rdi, TopLevelInfo, 0);
Guid guid = {0};
MemoryCopy(&guid, &tli->guid, Min(sizeof guid, sizeof tli->guid));
value_string = string_from_guid(scratch.arena, guid);
access_close(access);
}
}
// rjf: textual data
if(str8_match(child_type_name, str8_lit("path"), 0) || if(str8_match(child_type_name, str8_lit("path"), 0) ||
str8_match(child_type_name, str8_lit("path_pt"), 0) || str8_match(child_type_name, str8_lit("path_pt"), 0) ||
str8_match(child_type_name, str8_lit("code_string"), 0) || str8_match(child_type_name, str8_lit("code_string"), 0) ||
str8_match(child_type_name, str8_lit("expr_string"), 0) || str8_match(child_type_name, str8_lit("expr_string"), 0) ||
str8_match(child_type_name, str8_lit("string"), 0)) str8_match(child_type_name, str8_lit("string"), 0))
{ {
read_data = cfg->first->string; read_data = value_string;
} }
// rjf: non-textual data
else else
{ {
String8 value_string = cfg->first->string;
if(value_string.size == 0)
{
value_string = md_tag_from_string(child_schema, str8_lit("default"), 0)->first->string;
}
if(value_string.size == 0 && !md_node_is_nil(md_tag_from_string(child_schema, str8_lit("override"), 0)))
{
for(CFG_Node *parent = root_cfg->parent; parent != &cfg_nil_node; parent = parent->parent)
{
CFG_Node *parent_child_w_key = cfg_node_child_from_string(parent, child_key);
if(parent_child_w_key != &cfg_nil_node)
{
value_string = parent_child_w_key->first->string;
break;
}
value_string = rd_default_setting_from_names(parent->string, child_key);
if(value_string.size != 0)
{
break;
}
}
}
E_Key parent_key = {0}; E_Key parent_key = {0};
if(expr_child_schema != &md_nil_node && child_schema != expr_child_schema) if(expr_child_schema != &md_nil_node && child_schema != expr_child_schema)
{ {
@@ -2224,11 +2255,22 @@ rd_view_ui(Rng2F32 rect)
{ {
default: default:
{ {
U64 vaddr = eval.value.u64; U64 voff = 0;
CTRL_Entity *process = rd_ctrl_entity_from_eval_space(eval.space); DI_Key dbgi_key = {0};
CTRL_Entity *module = ctrl_module_from_process_vaddr(process, vaddr); if(eval.space.kind == CTRL_EvalSpaceKind_Entity)
DI_Key dbgi_key = ctrl_dbgi_key_from_module(module); {
U64 voff = ctrl_voff_from_vaddr(module, vaddr); U64 vaddr = eval.value.u64;
CTRL_Entity *process = rd_ctrl_entity_from_eval_space(eval.space);
CTRL_Entity *module = ctrl_module_from_process_vaddr(process, vaddr);
dbgi_key = ctrl_dbgi_key_from_module(module);
voff = ctrl_voff_from_vaddr(module, vaddr);
}
else
{
voff = eval.value.u64;
E_DbgInfo *dbg_info = e_dbg_info_from_type_key(eval.irtree.type_key);
dbgi_key = dbg_info->dbgi_key;
}
{ {
Access *access = access_open(); Access *access = access_open();
RDI_Parsed *rdi = di_rdi_from_key(access, dbgi_key, 0, 0); RDI_Parsed *rdi = di_rdi_from_key(access, dbgi_key, 0, 0);
@@ -3998,7 +4040,9 @@ rd_view_ui(Rng2F32 rect)
// rjf: apply type note // rjf: apply type note
if(!(cell_info.flags & RD_WatchCellFlag_NoEval) && if(!(cell_info.flags & RD_WatchCellFlag_NoEval) &&
cell->eval.space.kind == CTRL_EvalSpaceKind_Entity && e_type_kind_from_key(cell->eval.irtree.type_key) != E_TypeKind_Null &&
(cell->eval.space.kind == E_SpaceKind_Null ||
cell->eval.space.kind == CTRL_EvalSpaceKind_Entity) &&
row_info->callstack_thread == &ctrl_entity_nil && row_info->callstack_thread == &ctrl_entity_nil &&
e_type_kind_from_key(cell->eval.irtree.type_key) != E_TypeKind_Function) e_type_kind_from_key(cell->eval.irtree.type_key) != E_TypeKind_Function)
UI_FontSize(ui_top_font_size()*0.9f) UI_FontSize(ui_top_font_size()*0.9f)
@@ -5176,6 +5220,19 @@ rd_window_frame(void)
cfg_node_release(rd_state->cfg, cfg_node_child_from_string(window, str8_lit("maximized"))); cfg_node_release(rd_state->cfg, cfg_node_child_from_string(window, str8_lit("maximized")));
} }
//- rjf: DPI changes -> xform font size / window size
F32 dpi = os_dpi_from_window(ws->os);
if(dpi != ws->last_dpi)
{
fnt_reset();
F32 current_font_size = rd_font_size();
F32 new_font_size = current_font_size * (dpi / ws->last_dpi);
new_font_size = Clamp(6.f, new_font_size, 72.f);
CFG_Node *font_size_cfg = cfg_node_child_from_string_or_alloc(rd_state->cfg, window, str8_lit("font_size"));
cfg_node_new_replacef(rd_state->cfg, font_size_cfg, "%I64u", (U64)new_font_size);
ws->last_dpi = dpi;
}
//- rjf: commit position //- rjf: commit position
Rng2F32 window_rect = os_rect_from_window(ws->os); Rng2F32 window_rect = os_rect_from_window(ws->os);
if(!is_fullscreen && !is_maximized && !is_minimized) if(!is_fullscreen && !is_maximized && !is_minimized)
@@ -5690,75 +5747,73 @@ rd_window_frame(void)
//////////////////////////// ////////////////////////////
//- rjf: @window_ui_part drop-completion context menu //- rjf: @window_ui_part drop-completion context menu
// //
if(ws->drop_completion_paths.node_count != 0) if(ws->top_drop_completion_task != 0)
{ {
RD_DropCompletionTask *task = ws->top_drop_completion_task;
B32 done = 0;
UI_CtxMenu(rd_state->drop_completion_key) UI_PrefWidth(ui_em(40.f, 1.f)) UI_TagF("implicit") UI_CtxMenu(rd_state->drop_completion_key) UI_PrefWidth(ui_em(40.f, 1.f)) UI_TagF("implicit")
{ {
UI_TagF("weak") // rjf: file names
for(String8Node *n = ws->drop_completion_paths.first; n != 0; n = n->next) UI_TagF("weak") UI_Row UI_Padding(ui_em(1.25f, 1.f))
{ {
UI_Row UI_Padding(ui_em(1.f, 1.f)) String8List strings = {0};
U64 idx = 0;
for(String8Node *n = task->paths.first; n != 0 && idx < 20; n = n->next, idx += 1)
{ {
UI_PrefWidth(ui_em(2.f, 1.f)) RD_Font(RD_FontSlot_Icons) ui_label(rd_icon_kind_text_table[RD_IconKind_FileOutline]); str8_list_push(scratch.arena, &strings, str8_skip_last_slash(n->string));
UI_PrefWidth(ui_text_dim(10, 1)) ui_label(n->string); if(idx+1 == 20)
{
str8_list_push(scratch.arena, &strings, str8_lit("..."));
}
} }
StringJoin join = {.sep = str8_lit(", ")};
String8 string = str8_list_join(scratch.arena, &strings, &join);
UI_PrefWidth(ui_pct(1, 0)) ui_label(string);
} }
ui_divider(ui_em(1.f, 1.f));
if(ui_clicked(rd_icon_buttonf(RD_IconKind_Target, 0, "Add File%s As Target%s", // rjf: option to add EXEs as targets
(ws->drop_completion_paths.node_count > 1) ? "s" : "", if(task->exe)
(ws->drop_completion_paths.node_count > 1) ? "s" : "")))
{ {
for(String8Node *n = ws->drop_completion_paths.first; n != 0; n = n->next) if(ui_clicked(rd_icon_buttonf(RD_IconKind_Target, 0, "Add as target%s", (task->paths.node_count > 1) ? "s" : "")))
{ {
rd_cmd(RD_CmdKind_AddTarget, .file_path = n->string); for(String8Node *n = task->paths.first; n != 0; n = n->next)
}
ui_ctx_menu_close();
}
if(ws->drop_completion_paths.node_count == 1)
{
if(ui_clicked(rd_icon_buttonf(RD_IconKind_Play, 0, "Add File%s As Target%s And Run",
(ws->drop_completion_paths.node_count > 1) ? "s" : "",
(ws->drop_completion_paths.node_count > 1) ? "s" : "")))
{
for(String8Node *n = ws->drop_completion_paths.first; n != 0; n = n->next)
{ {
rd_cmd(RD_CmdKind_AddTarget, .file_path = n->string); rd_cmd(RD_CmdKind_AddTarget, .file_path = n->string);
} }
CTRL_EntityArray processes = ctrl_entity_array_from_kind(&d_state->ctrl_entity_store->ctx, CTRL_EntityKind_Process); done = 1;
if(processes.count != 0)
{
rd_cmd(RD_CmdKind_KillAll);
}
rd_cmd(RD_CmdKind_Run);
ui_ctx_menu_close();
} }
} }
if(ws->drop_completion_paths.node_count == 1)
// rjf: option to load files as debug info
if(task->dbg)
{ {
if(ui_clicked(rd_icon_buttonf(RD_IconKind_StepInto, 0, "Add File%s As Target%s And Step Into", if(ui_clicked(rd_icon_buttonf(RD_IconKind_Module, 0, "Load as debug info")))
(ws->drop_completion_paths.node_count > 1) ? "s" : "",
(ws->drop_completion_paths.node_count > 1) ? "s" : "")))
{ {
for(String8Node *n = ws->drop_completion_paths.first; n != 0; n = n->next) for(String8Node *n = task->paths.first; n != 0; n = n->next)
{ {
rd_cmd(RD_CmdKind_AddTarget, .file_path = n->string); rd_cmd(RD_CmdKind_LoadDebugInfo, .file_path = n->string);
} }
CTRL_EntityArray processes = ctrl_entity_array_from_kind(&d_state->ctrl_entity_store->ctx, CTRL_EntityKind_Process); done = 1;
if(processes.count != 0)
{
rd_cmd(RD_CmdKind_KillAll);
}
rd_cmd(RD_CmdKind_StepInto);
ui_ctx_menu_close();
} }
} }
if(ui_clicked(rd_icon_buttonf(RD_IconKind_Target, 0, "View File%s",
(ws->drop_completion_paths.node_count > 1) ? "s" : ""))) // rjf: option to just open & view the file contents
if(ui_clicked(rd_icon_buttonf(RD_IconKind_FileOutline, 0, "View file%s contents", (task->paths.node_count > 1) ? "s'" : "")))
{ {
for(String8Node *n = ws->drop_completion_paths.first; n != 0; n = n->next) for(String8Node *n = task->paths.first; n != 0; n = n->next)
{ {
rd_cmd(RD_CmdKind_Open, .file_path = n->string); rd_cmd(RD_CmdKind_Open, .file_path = n->string);
} }
done = 1;
}
}
// rjf: pop task, close context menu if needed, when done
if(done)
{
SLLStackPop(ws->top_drop_completion_task);
if(ws->top_drop_completion_task == 0)
{
ui_ctx_menu_close(); ui_ctx_menu_close();
} }
} }
@@ -8292,23 +8347,45 @@ rd_window_frame(void)
{ {
B32 need_drop_completion = 0; B32 need_drop_completion = 0;
arena_clear(ws->drop_completion_arena); arena_clear(ws->drop_completion_arena);
MemoryZeroStruct(&ws->drop_completion_paths); ws->top_drop_completion_task = 0;
ws->drop_completion_panel = panel->cfg->id;
String8List exe_paths = {0};
String8List dbg_paths = {0};
for(String8Node *n = evt->paths.first; n != 0; n = n->next) for(String8Node *n = evt->paths.first; n != 0; n = n->next)
{ {
Temp scratch = scratch_begin(0, 0); Temp scratch = scratch_begin(0, 0);
String8 path = n->string; String8 path = n->string;
if(str8_match(str8_skip_last_dot(path), str8_lit("exe"), StringMatchFlag_CaseInsensitive)) String8 ext = str8_skip_last_dot(path);
if(str8_match(ext, str8_lit("exe"), StringMatchFlag_CaseInsensitive))
{ {
str8_list_push(ws->drop_completion_arena, &ws->drop_completion_paths, push_str8_copy(ws->drop_completion_arena, path)); str8_list_push(ws->drop_completion_arena, &exe_paths, str8_copy(ws->drop_completion_arena, path));
need_drop_completion = 1; }
else if(str8_match(ext, str8_lit("pdb"), StringMatchFlag_CaseInsensitive) ||
str8_match(ext, str8_lit("rdi"), StringMatchFlag_CaseInsensitive))
{
str8_list_push(ws->drop_completion_arena, &dbg_paths, str8_copy(ws->drop_completion_arena, path));
} }
else else
{ {
rd_cmd(RD_CmdKind_Open, .file_path = path); rd_cmd(RD_CmdKind_Open, .file_path = path, .panel = panel->cfg->id);
} }
scratch_end(scratch); scratch_end(scratch);
} }
if(need_drop_completion) if(dbg_paths.node_count != 0)
{
RD_DropCompletionTask *t = push_array(ws->drop_completion_arena, RD_DropCompletionTask, 1);
SLLStackPush(ws->top_drop_completion_task, t);
t->dbg = 1;
t->paths = dbg_paths;
}
if(exe_paths.node_count != 0)
{
RD_DropCompletionTask *t = push_array(ws->drop_completion_arena, RD_DropCompletionTask, 1);
SLLStackPush(ws->top_drop_completion_task, t);
t->exe = 1;
t->paths = exe_paths;
}
if(ws->top_drop_completion_task != 0)
{ {
ui_ctx_menu_open(rd_state->drop_completion_key, ui_key_zero(), evt->pos); ui_ctx_menu_open(rd_state->drop_completion_key, ui_key_zero(), evt->pos);
} }
@@ -8547,7 +8624,7 @@ rd_window_frame(void)
} }
// rjf: soft circle around mouse // rjf: soft circle around mouse
if(box->hot_t > 0.01f) DR_ClipScope(box->rect) if(box->hot_t > 0.01f) DR_ClipScope(intersect_2f32(box->rect, dr_top_clip()))
{ {
Vec4F32 color = hover_color; Vec4F32 color = hover_color;
color.w *= 0.02f; color.w *= 0.02f;
@@ -9297,7 +9374,7 @@ rd_code_color_slot_from_txt_token_kind_lookup_string(TXT_TokenKind kind, String8
// rjf: try to map using asynchronous matching system // rjf: try to map using asynchronous matching system
if(!mapped && kind == TXT_TokenKind_Identifier) if(!mapped && kind == TXT_TokenKind_Identifier)
{ {
DI_Match match = di_match_from_string(string, 0, e_base_ctx->primary_module->dbgi_key, 0); DI_Match match = di_match_from_string(string, 0, di_key_zero(), 0);
RDI_SectionKind section_kind = match.section_kind; RDI_SectionKind section_kind = match.section_kind;
mapped = 1; mapped = 1;
switch(section_kind) switch(section_kind)
@@ -9935,6 +10012,12 @@ rd_init(CmdLine *cmdln)
cfg_node_new(rd_state->cfg, cfg_node_root(), str8_lit("transient")); cfg_node_new(rd_state->cfg, cfg_node_root(), str8_lit("transient"));
} }
// rjf: set up loaded debug info cache
{
rd_state->loaded_dbg_info_slots_count = 4096;
rd_state->loaded_dbg_info_slots = push_array(arena, RD_LoadedDbgInfoSlot, rd_state->loaded_dbg_info_slots_count);
}
// rjf: set up window cache // rjf: set up window cache
{ {
rd_state->window_state_slots_count = 64; rd_state->window_state_slots_count = 64;
@@ -10028,7 +10111,14 @@ rd_init(CmdLine *cmdln)
String8List passthrough_args_list = {0}; String8List passthrough_args_list = {0};
for(String8Node *n = target_args.first->next; n != 0; n = n->next) for(String8Node *n = target_args.first->next; n != 0; n = n->next)
{ {
str8_list_push(scratch.arena, &passthrough_args_list, n->string); if(str8_find_needle(n->string, 0, str8_lit(" "), 0) < n->string.size)
{
str8_list_pushf(scratch.arena, &passthrough_args_list, "\"%S\"", n->string);
}
else
{
str8_list_push(scratch.arena, &passthrough_args_list, n->string);
}
} }
StringJoin join = {str8_lit(""), str8_lit(" "), str8_lit("")}; StringJoin join = {str8_lit(""), str8_lit(" "), str8_lit("")};
arguments_string = str8_list_join(scratch.arena, &passthrough_args_list, &join); arguments_string = str8_list_join(scratch.arena, &passthrough_args_list, &join);
@@ -10290,6 +10380,76 @@ rd_frame(void)
scratch_end(scratch); scratch_end(scratch);
} }
//////////////////////////////
//- rjf: apply debug info config trees -> loaded debug info cache
//
{
U64 current_update_tick_idx = update_tick_idx();
//- rjf: for each debug info config, reflect in cache - open if needed
CFG_NodePtrList dbg_infos = cfg_node_top_level_list_from_string(scratch.arena, str8_lit("debug_info"));
for EachNode(n, CFG_NodePtrNode, dbg_infos.first)
{
// rjf: unpack debug info config
CFG_Node *di = n->v;
String8 path = rd_path_from_cfg(di);
CFG_Node *di_timestamp = cfg_node_child_from_string(di, str8_lit("timestamp"));
U64 timestamp = 0;
try_u64_from_str8_c_rules(di_timestamp->first->string, &timestamp);
DI_Key key = di_key_from_path_timestamp(path, timestamp);
// rjf: touch in cache
U64 hash = u64_hash_from_str8(str8_struct(&key));
U64 slot_idx = hash%rd_state->loaded_dbg_info_slots_count;
RD_LoadedDbgInfoSlot *slot = &rd_state->loaded_dbg_info_slots[slot_idx];
RD_LoadedDbgInfoNode *node = 0;
for(RD_LoadedDbgInfoNode *n = slot->first; n != 0; n = n->hash_next)
{
if(di_key_match(key, n->key))
{
node = n;
break;
}
}
if(node == 0)
{
node = rd_state->free_loaded_dbg_info_node;
if(node)
{
SLLStackPop_N(rd_state->free_loaded_dbg_info_node, hash_next);
}
else
{
node = push_array(rd_state->arena, RD_LoadedDbgInfoNode, 1);
}
DLLPushBack_NP(slot->first, slot->last, node, hash_next, hash_prev);
node->key = key;
di_open(key);
}
node->last_tick_idx_touched = current_update_tick_idx;
DLLRemove_NP(rd_state->loaded_dbg_info_lru_first, rd_state->loaded_dbg_info_lru_last, node, lru_next, lru_prev);
DLLPushBack_NP(rd_state->loaded_dbg_info_lru_first, rd_state->loaded_dbg_info_lru_last, node, lru_next, lru_prev);
}
//- rjf: iterate least-recently-used loaded debug infos - if any have not been updated this tick,
// then evict
for(RD_LoadedDbgInfoNode *n = rd_state->loaded_dbg_info_lru_first, *next = 0; n != 0; n = next)
{
next = n->lru_next;
if(n->last_tick_idx_touched >= current_update_tick_idx)
{
break;
}
U64 hash = u64_hash_from_str8(str8_struct(&n->key));
U64 slot_idx = hash%rd_state->loaded_dbg_info_slots_count;
RD_LoadedDbgInfoSlot *slot = &rd_state->loaded_dbg_info_slots[slot_idx];
DLLRemove_NP(rd_state->loaded_dbg_info_lru_first, rd_state->loaded_dbg_info_lru_last, n, lru_next, lru_prev);
DLLRemove_NP(slot->first, slot->last, n, hash_next, hash_prev);
SLLStackPush_N(rd_state->free_loaded_dbg_info_node, n, hash_next);
di_close(n->key, 0);
}
}
////////////////////////////// //////////////////////////////
//- rjf: garbage collect untouched immediate cfg trees //- rjf: garbage collect untouched immediate cfg trees
// //
@@ -10756,7 +10916,56 @@ rd_frame(void)
ProfScope("loop - consume events in core, tick engine, and repeat") for(U64 cmd_process_loop_idx = 0; cmd_process_loop_idx < 3; cmd_process_loop_idx += 1) ProfScope("loop - consume events in core, tick engine, and repeat") for(U64 cmd_process_loop_idx = 0; cmd_process_loop_idx < 3; cmd_process_loop_idx += 1)
{ {
//////////////////////////// ////////////////////////////
//- rjf: unpack eval-dependent info //- rjf: gather all unique debug info keys, build map
//
typedef struct DbgInfoNode DbgInfoNode;
struct DbgInfoNode
{
DbgInfoNode *hash_next;
DbgInfoNode *order_next;
DI_Key key;
U64 idx;
};
U64 dbg_info_slots_count = 4096;
DbgInfoNode **dbg_info_slots = push_array(scratch.arena, DbgInfoNode *, dbg_info_slots_count);
DbgInfoNode *first_dbg_info = 0;
DbgInfoNode *last_dbg_info = 0;
U64 dbg_infos_count = 0;
{
CFG_NodePtrList dbg_infos = cfg_node_top_level_list_from_string(scratch.arena, str8_lit("debug_info"));
for EachNode(n, CFG_NodePtrNode, dbg_infos.first)
{
CFG_Node *di = n->v;
String8 path = rd_path_from_cfg(di);
CFG_Node *timestamp_node = cfg_node_child_from_string(di, str8_lit("timestamp"));
U64 timestamp = 0;
try_u64_from_str8_c_rules(timestamp_node->first->string, &timestamp);
DI_Key key = di_key_from_path_timestamp(path, timestamp);
U64 hash = u64_hash_from_str8(str8_struct(&key));
U64 slot_idx = hash%dbg_info_slots_count;
DbgInfoNode *node = 0;
for(DbgInfoNode *n = dbg_info_slots[slot_idx]; n != 0; n = n->hash_next)
{
if(di_key_match(n->key, key))
{
node = n;
break;
}
}
if(node == 0)
{
node = push_array(scratch.arena, DbgInfoNode, 1);
SLLStackPush_N(dbg_info_slots[slot_idx], node, hash_next);
SLLQueuePush_N(first_dbg_info, last_dbg_info, node, order_next);
node->key = key;
node->idx = dbg_infos_count;
dbg_infos_count += 1;
}
}
}
////////////////////////////
//- rjf: unpack basic evaluation context
// //
ProfBegin("unpack eval-dependent info"); ProfBegin("unpack eval-dependent info");
CTRL_Entity *process = ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, rd_regs()->process); CTRL_Entity *process = ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, rd_regs()->process);
@@ -10767,32 +10976,67 @@ rd_frame(void)
CTRL_Entity *module = ctrl_module_from_process_vaddr(process, rip_vaddr); CTRL_Entity *module = ctrl_module_from_process_vaddr(process, rip_vaddr);
U64 rip_voff = ctrl_voff_from_vaddr(module, rip_vaddr); U64 rip_voff = ctrl_voff_from_vaddr(module, rip_vaddr);
U64 tls_root_vaddr = ctrl_tls_root_vaddr_from_thread(&d_state->ctrl_entity_store->ctx, thread->handle); U64 tls_root_vaddr = ctrl_tls_root_vaddr_from_thread(&d_state->ctrl_entity_store->ctx, thread->handle);
ProfEnd();
////////////////////////////
//- rjf: produce all debug infos
//
U64 eval_dbg_infos_count = Max(1, dbg_infos_count);
E_DbgInfo *eval_dbg_infos = push_array(scratch.arena, E_DbgInfo, eval_dbg_infos_count);
E_DbgInfo *eval_dbg_infos_primary = &eval_dbg_infos[0];
MemoryCopyStruct(eval_dbg_infos_primary, &e_dbg_info_nil);
{
U64 idx = 0;
for(DbgInfoNode *n = first_dbg_info; n != 0; n = n->order_next)
{
eval_dbg_infos[idx].dbgi_key = n->key;
eval_dbg_infos[idx].rdi = di_rdi_from_key(rd_state->frame_access, n->key, 0, 0);
idx += 1;
}
}
////////////////////////////
//- rjf: produce all eval modules
//
CTRL_EntityArray all_modules = ctrl_entity_array_from_kind(&d_state->ctrl_entity_store->ctx, CTRL_EntityKind_Module); CTRL_EntityArray all_modules = ctrl_entity_array_from_kind(&d_state->ctrl_entity_store->ctx, CTRL_EntityKind_Module);
U64 eval_modules_count = Max(1, all_modules.count); U64 eval_modules_count = Max(1, all_modules.count);
E_Module *eval_modules = push_array(scratch.arena, E_Module, eval_modules_count); E_Module *eval_modules = push_array(scratch.arena, E_Module, eval_modules_count);
E_Module *eval_modules_primary = &eval_modules[0]; E_Module *eval_modules_primary = &eval_modules[0];
eval_modules_primary->rdi = &rdi_parsed_nil;
eval_modules_primary->vaddr_range = r1u64(0, max_U64); eval_modules_primary->vaddr_range = r1u64(0, max_U64);
DI_Key primary_dbgi_key = {0};
ProfScope("produce all eval modules") ProfScope("produce all eval modules")
{ {
for EachIndex(eval_module_idx, all_modules.count) for EachIndex(eval_module_idx, all_modules.count)
{ {
CTRL_Entity *m = all_modules.v[eval_module_idx]; CTRL_Entity *m = all_modules.v[eval_module_idx];
DI_Key dbgi_key = ctrl_dbgi_key_from_module(m); DI_Key dbgi_key = ctrl_dbgi_key_from_module(m);
eval_modules[eval_module_idx].arch = m->arch;
eval_modules[eval_module_idx].dbgi_key = dbgi_key; // rjf: dbgi key -> eval dbg info num
eval_modules[eval_module_idx].rdi = di_rdi_from_key(rd_state->frame_access, dbgi_key, 0, 0); U32 dbg_info_num = 0;
eval_modules[eval_module_idx].vaddr_range = m->vaddr_range; {
eval_modules[eval_module_idx].space = rd_eval_space_from_ctrl_entity(ctrl_entity_ancestor_from_kind(m, CTRL_EntityKind_Process), CTRL_EvalSpaceKind_Entity); U64 hash = u64_hash_from_str8(str8_struct(&dbgi_key));
U64 slot_idx = hash%dbg_info_slots_count;
for(DbgInfoNode *n = dbg_info_slots[slot_idx]; n != 0; n = n->hash_next)
{
if(di_key_match(n->key, dbgi_key))
{
dbg_info_num = n->idx+1;
break;
}
}
}
// rjf: fill
eval_modules[eval_module_idx].vaddr_range = m->vaddr_range;
eval_modules[eval_module_idx].arch = m->arch;
eval_modules[eval_module_idx].dbg_info_num = dbg_info_num;
eval_modules[eval_module_idx].space = rd_eval_space_from_ctrl_entity(ctrl_entity_ancestor_from_kind(m, CTRL_EntityKind_Process), CTRL_EvalSpaceKind_Entity);
if(module == m) if(module == m)
{ {
eval_modules_primary = &eval_modules[eval_module_idx]; eval_modules_primary = &eval_modules[eval_module_idx];
primary_dbgi_key = dbgi_key; eval_dbg_infos_primary = (0 < dbg_info_num && dbg_info_num <= eval_dbg_infos_count) ? &eval_dbg_infos[dbg_info_num-1] : &e_dbg_info_nil;
} }
} }
} }
ProfEnd();
//////////////////////////// ////////////////////////////
//- rjf: begin evaluation //- rjf: begin evaluation
@@ -10813,6 +11057,11 @@ rd_frame(void)
ctx->thread_arch = thread->arch; ctx->thread_arch = thread->arch;
ctx->thread_unwind_count = unwind_count; ctx->thread_unwind_count = unwind_count;
//- rjf: fill debug infos
ctx->dbg_infos = eval_dbg_infos;
ctx->dbg_infos_count = eval_dbg_infos_count;
ctx->primary_dbg_info = eval_dbg_infos_primary;
//- rjf: fill modules //- rjf: fill modules
ctx->modules = eval_modules; ctx->modules = eval_modules;
ctx->modules_count = eval_modules_count; ctx->modules_count = eval_modules_count;
@@ -10939,6 +11188,7 @@ rd_frame(void)
str8_lit("breakpoint"), str8_lit("breakpoint"),
str8_lit("watch_pin"), str8_lit("watch_pin"),
str8_lit("target"), str8_lit("target"),
str8_lit("debug_info"),
str8_lit("file_path_map"), str8_lit("file_path_map"),
str8_lit("type_view"), str8_lit("type_view"),
str8_lit("recent_project"), str8_lit("recent_project"),
@@ -11281,6 +11531,18 @@ rd_frame(void)
.id_from_num = E_TYPE_EXPAND_ID_FROM_NUM_FUNCTION_NAME(cfgs_slice), .id_from_num = E_TYPE_EXPAND_ID_FROM_NUM_FUNCTION_NAME(cfgs_slice),
.num_from_id = E_TYPE_EXPAND_NUM_FROM_ID_FUNCTION_NAME(cfgs_slice), .num_from_id = E_TYPE_EXPAND_NUM_FROM_ID_FUNCTION_NAME(cfgs_slice),
})); }));
e_string2typekey_map_insert(rd_frame_arena(), rd_state->meta_name2type_map, str8_lit("environment"),
e_type_key_cons(.kind = E_TypeKind_Set,
.name = str8_lit("environment"),
.irext = E_TYPE_IREXT_FUNCTION_NAME(environment),
.access = E_TYPE_ACCESS_FUNCTION_NAME(environment),
.expand =
{
.info = E_TYPE_EXPAND_INFO_FUNCTION_NAME(environment),
.range = E_TYPE_EXPAND_RANGE_FUNCTION_NAME(environment),
.id_from_num = E_TYPE_EXPAND_ID_FROM_NUM_FUNCTION_NAME(environment),
.num_from_id = E_TYPE_EXPAND_NUM_FROM_ID_FUNCTION_NAME(environment),
}));
} }
//- rjf: add macro for collections with specific lookup rules (but no unique id rules) //- rjf: add macro for collections with specific lookup rules (but no unique id rules)
@@ -11588,8 +11850,8 @@ rd_frame(void)
E_IRCtx *ctx = ir_ctx; E_IRCtx *ctx = ir_ctx;
ctx->regs_map = ctrl_string2reg_from_arch(eval_base_ctx->primary_module->arch); ctx->regs_map = ctrl_string2reg_from_arch(eval_base_ctx->primary_module->arch);
ctx->reg_alias_map = ctrl_string2alias_from_arch(eval_base_ctx->primary_module->arch); ctx->reg_alias_map = ctrl_string2alias_from_arch(eval_base_ctx->primary_module->arch);
ctx->locals_map = d_query_cached_locals_map_from_dbgi_key_voff(primary_dbgi_key, rip_voff); ctx->locals_map = d_query_cached_locals_map_from_dbgi_key_voff(eval_base_ctx->primary_dbg_info->dbgi_key, rip_voff);
ctx->member_map = d_query_cached_member_map_from_dbgi_key_voff(primary_dbgi_key, rip_voff); ctx->member_map = d_query_cached_member_map_from_dbgi_key_voff(eval_base_ctx->primary_dbg_info->dbgi_key, rip_voff);
ctx->macro_map = macro_map; ctx->macro_map = macro_map;
ctx->auto_hook_map = auto_hook_map; ctx->auto_hook_map = auto_hook_map;
} }
@@ -11611,7 +11873,7 @@ rd_frame(void)
ctx->tls_base = push_array(scratch.arena, U64, 1); ctx->tls_base = push_array(scratch.arena, U64, 1);
ctx->tls_base[0] = d_query_cached_tls_base_vaddr_from_process_root_rip(process, tls_root_vaddr, rip_vaddr); ctx->tls_base[0] = d_query_cached_tls_base_vaddr_from_process_root_rip(process, tls_root_vaddr, rip_vaddr);
} }
e_select_interpret_ctx(interpret_ctx, eval_modules_primary->rdi, rip_voff); e_select_interpret_ctx(interpret_ctx, eval_dbg_infos_primary->rdi, rip_voff);
//////////////////////////// ////////////////////////////
//- rjf: evaluate unpacked settings (must be used earlier than this point in the frame, //- rjf: evaluate unpacked settings (must be used earlier than this point in the frame,
@@ -13663,7 +13925,15 @@ rd_frame(void)
DI_Key voff_dbgi_key = {0}; DI_Key voff_dbgi_key = {0};
if(!name_resolved) if(!name_resolved)
{ {
DI_Match match = di_match_from_string(name, 0, e_base_ctx->primary_module->dbgi_key, 0); DI_Match match = {0};
if(match.idx == 0)
{
match = di_match_from_string(name, 0, e_base_ctx->primary_dbg_info->dbgi_key, rd_state->frame_eval_memread_endt_us);
}
if(match.idx == 0)
{
match = di_match_from_string(name, 0, di_key_zero(), rd_state->frame_eval_memread_endt_us);
}
if(match.section_kind == RDI_SectionKind_Procedures) if(match.section_kind == RDI_SectionKind_Procedures)
{ {
Access *access = access_open(); Access *access = access_open();
@@ -14792,6 +15062,21 @@ rd_frame(void)
} }
}break; }break;
//- rjf: debug infos
case RD_CmdKind_LoadDebugInfo:
{
CFG_Node *project = cfg_node_child_from_string(cfg_node_root(), str8_lit("project"));
CFG_Node *di = cfg_node_new(rd_state->cfg, project, str8_lit("debug_info"));
CFG_Node *path = cfg_node_new(rd_state->cfg, di, str8_lit("path"));
cfg_node_new(rd_state->cfg, path, rd_regs()->file_path);
}break;
case RD_CmdKind_UnloadDebugInfo:
{
CFG_Node *di = cfg_node_from_id(rd_regs()->cfg);
CFG_Node *path = cfg_node_child_from_string(di, str8_lit("path"));
cfg_node_release(rd_state->cfg, di);
}break;
//- rjf: type views //- rjf: type views
case RD_CmdKind_AddTypeView: case RD_CmdKind_AddTypeView:
{ {
@@ -15877,6 +16162,43 @@ rd_frame(void)
switch(evt->kind) switch(evt->kind)
{ {
default:{}break; default:{}break;
case D_EventKind_ModuleLoad:
{
CTRL_Entity *module = ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, evt->module);
CTRL_Entity *debug_info_path = ctrl_entity_child_from_kind(module, CTRL_EntityKind_DebugInfoPath);
String8 new_path = debug_info_path->string;
if(new_path.size != 0 && os_file_path_exists(new_path))
{
CFG_NodePtrList dbg_infos = cfg_node_top_level_list_from_string(scratch.arena, str8_lit("debug_info"));
B32 path_found = 0;
CFG_Node *found_di = &cfg_nil_node;
for EachNode(n, CFG_NodePtrNode, dbg_infos.first)
{
CFG_Node *di = n->v;
String8 path = rd_path_from_cfg(di);
if(str8_match(path, new_path, 0))
{
path_found = 1;
found_di = di;
break;
}
}
if(!path_found)
{
CFG_Node *project = cfg_node_child_from_string(cfg_node_root(), str8_lit("project"));
CFG_Node *di = cfg_node_new(rd_state->cfg, project, str8_lit("debug_info"));
CFG_Node *path_root = cfg_node_new(rd_state->cfg, di, str8_lit("path"));
CFG_Node *timestamp_root = cfg_node_new(rd_state->cfg, di, str8_lit("timestamp"));
cfg_node_new(rd_state->cfg, path_root, new_path);
cfg_node_newf(rd_state->cfg, timestamp_root, "%I64u", debug_info_path->timestamp);
}
else
{
CFG_Node *timestamp_root = cfg_node_child_from_string_or_alloc(rd_state->cfg, found_di, str8_lit("timestamp"));
cfg_node_new_replacef(rd_state->cfg, timestamp_root, "%I64u", debug_info_path->timestamp);
}
}
}break;
case D_EventKind_ProcessEnd: case D_EventKind_ProcessEnd:
if(rd_state->quit_after_success) if(rd_state->quit_after_success)
{ {
@@ -16251,6 +16573,19 @@ rd_frame(void)
U64 frame_time_us = end_time_us-begin_time_us; U64 frame_time_us = end_time_us-begin_time_us;
rd_state->frame_time_us_history[rd_state->frame_index%ArrayCount(rd_state->frame_time_us_history)] = frame_time_us; rd_state->frame_time_us_history[rd_state->frame_index%ArrayCount(rd_state->frame_time_us_history)] = frame_time_us;
//////////////////////////////
//- rjf: [windows] clear pages from working set shortly after startup, many of which will not be needed
//
#if OS_WINDOWS
if(di_load_count() < 50)
{
if(rd_state->frame_index == 15) ProfScope("SetProcessWorkingSetSize")
{
SetProcessWorkingSetSize(GetCurrentProcess(), max_U64, max_U64);
}
}
#endif
////////////////////////////// //////////////////////////////
//- rjf: bump frame time counters //- rjf: bump frame time counters
// //
@@ -16287,16 +16622,6 @@ rd_frame(void)
} }
} }
//////////////////////////////
//- rjf: [windows] clear pages from working set shortly after startup, many of which will not be needed
//
#if OS_WINDOWS
if(rd_state->frame_index == 10)
{
SetProcessWorkingSetSize(GetCurrentProcess(), max_U64, max_U64);
}
#endif
rd_state->frame_depth -= 1; rd_state->frame_depth -= 1;
scratch_end(scratch); scratch_end(scratch);
ProfEnd(); ProfEnd();
+37 -1
View File
@@ -258,6 +258,16 @@ RD_FontSlot;
//////////////////////////////// ////////////////////////////////
//~ rjf: Per-Window State //~ rjf: Per-Window State
typedef struct RD_DropCompletionTask RD_DropCompletionTask;
struct RD_DropCompletionTask
{
RD_DropCompletionTask *next;
B32 exe;
B32 dbg;
B32 cfg;
String8List paths;
};
typedef struct RD_WindowState RD_WindowState; typedef struct RD_WindowState RD_WindowState;
struct RD_WindowState struct RD_WindowState
{ {
@@ -298,7 +308,8 @@ struct RD_WindowState
// rjf: drop-completion state // rjf: drop-completion state
Arena *drop_completion_arena; Arena *drop_completion_arena;
String8List drop_completion_paths; CFG_ID drop_completion_panel;
RD_DropCompletionTask *top_drop_completion_task;
// rjf: query state // rjf: query state
B32 query_is_active; B32 query_is_active;
@@ -343,6 +354,24 @@ struct RD_WindowStateSlot
//////////////////////////////// ////////////////////////////////
//~ rjf: Main Per-Process Graphical State //~ rjf: Main Per-Process Graphical State
typedef struct RD_LoadedDbgInfoNode RD_LoadedDbgInfoNode;
struct RD_LoadedDbgInfoNode
{
RD_LoadedDbgInfoNode *hash_next;
RD_LoadedDbgInfoNode *hash_prev;
RD_LoadedDbgInfoNode *lru_next;
RD_LoadedDbgInfoNode *lru_prev;
DI_Key key;
U64 last_tick_idx_touched;
};
typedef struct RD_LoadedDbgInfoSlot RD_LoadedDbgInfoSlot;
struct RD_LoadedDbgInfoSlot
{
RD_LoadedDbgInfoNode *first;
RD_LoadedDbgInfoNode *last;
};
typedef struct RD_AmbiguousPathNode RD_AmbiguousPathNode; typedef struct RD_AmbiguousPathNode RD_AmbiguousPathNode;
struct RD_AmbiguousPathNode struct RD_AmbiguousPathNode
{ {
@@ -480,6 +509,13 @@ struct RD_State
CFG_State *cfg; CFG_State *cfg;
CFG_SchemaTable *cfg_schema_table; CFG_SchemaTable *cfg_schema_table;
// rjf: loaded debug info cache
U64 loaded_dbg_info_slots_count;
RD_LoadedDbgInfoSlot *loaded_dbg_info_slots;
RD_LoadedDbgInfoNode *loaded_dbg_info_lru_first;
RD_LoadedDbgInfoNode *loaded_dbg_info_lru_last;
RD_LoadedDbgInfoNode *free_loaded_dbg_info_node;
// rjf: window state cache // rjf: window state cache
U64 window_state_slots_count; U64 window_state_slots_count;
RD_WindowStateSlot *window_state_slots; RD_WindowStateSlot *window_state_slots;
+8 -6
View File
@@ -294,38 +294,40 @@ E_TYPE_ACCESS_FUNCTION_DEF(schema)
CFG_Node *child = cfg_node_child_from_string(cfg, child_schema->string); CFG_Node *child = cfg_node_child_from_string(cfg, child_schema->string);
E_TypeKey child_type_key = zero_struct; E_TypeKey child_type_key = zero_struct;
B32 wrap_child_w_meta_expr = 0; B32 wrap_child_w_meta_expr = 0;
B32 is_query_child = md_node_has_tag(child_schema, str8_lit("query"), 0);
E_TypeFlags type_flags = (!!is_query_child * E_TypeFlag_IsNotEditable);
if(0){} if(0){}
//- rjf: ctrl entity members //- rjf: ctrl entity members
else if(entity != &ctrl_entity_nil && str8_match(child_schema->string, str8_lit("label"), 0)) else if(entity != &ctrl_entity_nil && str8_match(child_schema->string, str8_lit("label"), 0))
{ {
child_type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_U8), entity->string.size, E_TypeFlag_IsCodeText); child_type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_U8), entity->string.size, type_flags|E_TypeFlag_IsCodeText);
} }
else if(entity != &ctrl_entity_nil && str8_match(child_schema->string, str8_lit("exe"), 0)) else if(entity != &ctrl_entity_nil && str8_match(child_schema->string, str8_lit("exe"), 0))
{ {
child_type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_U8), entity->string.size, E_TypeFlag_IsPathText); child_type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_U8), entity->string.size, type_flags|E_TypeFlag_IsPathText);
} }
else if(entity != &ctrl_entity_nil && str8_match(child_schema->string, str8_lit("dbg"), 0)) else if(entity != &ctrl_entity_nil && str8_match(child_schema->string, str8_lit("dbg"), 0))
{ {
CTRL_Entity *dbg = ctrl_entity_child_from_kind(entity, CTRL_EntityKind_DebugInfoPath); CTRL_Entity *dbg = ctrl_entity_child_from_kind(entity, CTRL_EntityKind_DebugInfoPath);
child_type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_U8), dbg->string.size, E_TypeFlag_IsPathText); child_type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_U8), dbg->string.size, type_flags|E_TypeFlag_IsPathText);
} }
//- rjf: cfg members //- rjf: cfg members
else if(str8_match(child_schema->first->string, str8_lit("code_string"), 0) || else if(str8_match(child_schema->first->string, str8_lit("code_string"), 0) ||
str8_match(child_schema->first->string, str8_lit("expr_string"), 0)) str8_match(child_schema->first->string, str8_lit("expr_string"), 0))
{ {
child_type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_U8), child->first->string.size, E_TypeFlag_IsCodeText); child_type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_U8), child->first->string.size, type_flags|E_TypeFlag_IsCodeText);
} }
else if(str8_match(child_schema->first->string, str8_lit("path"), 0) || else if(str8_match(child_schema->first->string, str8_lit("path"), 0) ||
str8_match(child_schema->first->string, str8_lit("path_pt"), 0)) str8_match(child_schema->first->string, str8_lit("path_pt"), 0))
{ {
child_type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_U8), child->first->string.size, E_TypeFlag_IsPathText); child_type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_U8), child->first->string.size, type_flags|E_TypeFlag_IsPathText);
} }
else if(str8_match(child_schema->first->string, str8_lit("string"), 0)) else if(str8_match(child_schema->first->string, str8_lit("string"), 0))
{ {
child_type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_U8), child->first->string.size, E_TypeFlag_IsPlainText); child_type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_U8), child->first->string.size, type_flags|E_TypeFlag_IsPlainText);
} }
//- rjf: catchall cases //- rjf: catchall cases
+8 -31
View File
@@ -14,20 +14,19 @@
// [ ] list of all tabs in palette // [ ] list of all tabs in palette
// [ ] u64 + (ptr - ptr) seems to produce unexpected results - double check with C rules? // [ ] u64 + (ptr - ptr) seems to produce unexpected results - double check with C rules?
// //
//- flow notes
// [ ] "skip breakpoint, run to source", when stopped at a non-source location
// [ ] adjust menu bar rendering when not focused
// [ ] treat int 0x29 similarly to int3
// [ ] auto_step, launching terminal, terminal steals focus from debugger...
//
//- memory view //- memory view
// [ ] have smaller visible range than entire memory // [ ] have smaller visible range than entire memory space, within some bounds (e.g. 64KB)
// space, within some bounds (e.g. 64KB) // [ ] dynamically expand memory space, based on scrolling
// [ ] dynamically expand memory space, based on
// scrolling
// [ ] fix clicking through occluded panels etc. // [ ] fix clicking through occluded panels etc.
// [ ] disambiguate . character in ASCII columns // [ ] disambiguate . character in ASCII columns
// [ ] fix type intepretations of cursor in bottom pane // [ ] fix type intepretations of cursor in bottom pane
// //
//- bug fixes
// [x] disassembly sometimes has a problem where source line annotations are
// periodically removed/inserted... maybe updating on fs change when we
// shouldn't, non-deterministic line annotation path?
//
//- watch improvements //- watch improvements
// [ ] *ALL* expressions in watch windows need to be editable. // [ ] *ALL* expressions in watch windows need to be editable.
// //
@@ -113,7 +112,6 @@
// [ ] multidimensional `array` // [ ] multidimensional `array`
// [ ] 2-vector, 3-vector, quaternion // [ ] 2-vector, 3-vector, quaternion
// [ ] audio waveform views // [ ] audio waveform views
// [x] linked list view
// //
//- eval improvements //- eval improvements
// [ ] maybe add extra caching layer to process memory querying? we pay a pretty // [ ] maybe add extra caching layer to process memory querying? we pay a pretty
@@ -149,13 +147,6 @@
// //
//- late-conversion performance improvements //- late-conversion performance improvements
// [ ] live++ investigations - ctrl+alt+f11 in UE? // [ ] live++ investigations - ctrl+alt+f11 in UE?
// [x] investigate wide-conversion performance
// [x] oversubscribing cores?
// [x] conversion crashes?
//
//- memory usage improvements
// [x] "root" concept in hash store, which buckets keys & allows usage code to
// jettison a collection of keys in retained mode fashion
// //
//- short-to-medium term future features //- short-to-medium term future features
// [ ] search-in-all-files // [ ] search-in-all-files
@@ -183,20 +174,6 @@
// [ ] font cache eviction (both for font tags, closing fp handles, and // [ ] font cache eviction (both for font tags, closing fp handles, and
// rasterizations) // rasterizations)
////////////////////////////////
//~ rjf: Recently Completed Task Log
//
// [x] if a breakpoint matches the entry point's starting address, its hit count
// is not correctly incremented.
// [x] output: add option for scroll-to-bottom - ensure this shows up in universal ctx menu
// [x] auto-annotations for non-locals
// [x] []string being sized by [0], due to `.` applying to first ^string
// [x] process memory cache sometimes is not correctly updating - best repro
// case so far is (for some reason?) only hover evaluation - only spotted
// on laptop in debug builds. g0 ctrl_bindings.bindings initialization.
// [x] evaluate `foo.bar` symbol names without escape hatch?
// [x] fastpath lookup to determine debug info relevance?
//////////////////////////////// ////////////////////////////////
//~ rjf: Build Options //~ rjf: Build Options
+3 -6
View File
@@ -1251,9 +1251,6 @@ rd_code_slice(RD_CodeSliceParams *params, TxtPt *cursor, TxtPt *mark, S64 *prefe
CTRL_Entity *selected_thread_process = ctrl_entity_ancestor_from_kind(selected_thread, CTRL_EntityKind_Process); CTRL_Entity *selected_thread_process = ctrl_entity_ancestor_from_kind(selected_thread, CTRL_EntityKind_Process);
U64 selected_thread_rip_unwind_vaddr = d_query_cached_rip_from_thread_unwind(selected_thread, rd_regs()->unwind_count); U64 selected_thread_rip_unwind_vaddr = d_query_cached_rip_from_thread_unwind(selected_thread, rd_regs()->unwind_count);
CTRL_Entity *selected_thread_module = ctrl_module_from_process_vaddr(selected_thread_process, selected_thread_rip_unwind_vaddr); CTRL_Entity *selected_thread_module = ctrl_module_from_process_vaddr(selected_thread_process, selected_thread_rip_unwind_vaddr);
F32 selected_thread_alive_t = ui_anim(ui_key_from_stringf(ui_key_zero(), "###selected_thread_alive_t_%p", selected_thread), 1.f);
F32 selected_thread_module_alive_t = ui_anim(ui_key_from_stringf(ui_key_zero(), "###selected_thread_module_alive_t_%p", selected_thread_module), 1.f);
F32 selected_thread_arch_alive_t = ui_anim(ui_key_from_stringf(ui_key_zero(), "###selected_thread_arch_alive_t_%i", selected_thread->arch), 1.f);
CTRL_Event stop_event = d_ctrl_last_stop_event(); CTRL_Event stop_event = d_ctrl_last_stop_event();
CTRL_Entity *stopper_thread = ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, stop_event.entity); CTRL_Entity *stopper_thread = ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, stop_event.entity);
B32 is_focused = ui_is_focus_active(); B32 is_focused = ui_is_focus_active();
@@ -1552,9 +1549,9 @@ rd_code_slice(RD_CodeSliceParams *params, TxtPt *cursor, TxtPt *mark, S64 *prefe
line_num <= params->line_num_range.max; line_num <= params->line_num_range.max;
line_num += 1, line_idx += 1) line_num += 1, line_idx += 1)
{ {
CTRL_EntityList line_ips = params->line_ips[line_idx]; CTRL_EntityList line_ips = params->line_ips[line_idx];
CFG_NodePtrList line_bps = params->line_bps[line_idx]; CFG_NodePtrList line_bps = params->line_bps[line_idx];
CFG_NodePtrList line_pins = params->line_pins[line_idx]; CFG_NodePtrList line_pins = params->line_pins[line_idx];
ui_set_next_hover_cursor(OS_Cursor_HandPoint); ui_set_next_hover_cursor(OS_Cursor_HandPoint);
ui_set_next_background_color(v4f32(0, 0, 0, 0)); ui_set_next_background_color(v4f32(0, 0, 0, 0));
UI_Box *line_margin_box = ui_build_box_from_stringf(UI_BoxFlag_Clickable*!!(params->flags & RD_CodeSliceFlag_Clickable)|UI_BoxFlag_DrawBackground|UI_BoxFlag_DrawActiveEffects, "line_margin_%I64x", line_num); UI_Box *line_margin_box = ui_build_box_from_stringf(UI_BoxFlag_Clickable*!!(params->flags & RD_CodeSliceFlag_Clickable)|UI_BoxFlag_DrawBackground|UI_BoxFlag_DrawActiveEffects, "line_margin_%I64x", line_num);
+5 -1
View File
@@ -62,6 +62,9 @@
"typedef union RDI_SHA256 RDI_SHA256;"; "typedef union RDI_SHA256 RDI_SHA256;";
"union RDI_SHA256 {RDI_U8 u8[32]; RDI_U64 u64[4];};"; "union RDI_SHA256 {RDI_U8 u8[32]; RDI_U64 u64[4];};";
""; "";
"typedef union RDI_GUID RDI_GUID;";
"union RDI_GUID {RDI_U8 u8[16]; RDI_U64 u64[2];};";
"";
"////////////////////////////////////////////////////////////////"; "////////////////////////////////////////////////////////////////";
"//~ Overridable Enabling/Disabling Of Table Index Typechecking"; "//~ Overridable Enabling/Disabling Of Table Index Typechecking";
""; "";
@@ -74,7 +77,7 @@
""; "";
"// \"raddbg\\0\\0\""; "// \"raddbg\\0\\0\"";
"#define RDI_MAGIC_CONSTANT 0x0000676264646172"; "#define RDI_MAGIC_CONSTANT 0x0000676264646172";
"#define RDI_ENCODING_VERSION 16"; "#define RDI_ENCODING_VERSION 17";
""; "";
"////////////////////////////////////////////////////////////////"; "////////////////////////////////////////////////////////////////";
"//~ Format Types & Functions"; "//~ Format Types & Functions";
@@ -495,6 +498,7 @@ RDI_TopLevelInfoMemberTable:
{exe_name_string_idx RDI_U32 ""} {exe_name_string_idx RDI_U32 ""}
{exe_hash RDI_U64 ""} {exe_hash RDI_U64 ""}
{voff_max RDI_U64 ""} {voff_max RDI_U64 ""}
{guid RDI_GUID ""}
{producer_name_string_idx RDI_U32 ""} {producer_name_string_idx RDI_U32 ""}
} }
+19
View File
@@ -4,6 +4,22 @@
#include "lib_rdi/rdi.c" #include "lib_rdi/rdi.c"
#include "lib_rdi/rdi_parse.c" #include "lib_rdi/rdi_parse.c"
////////////////////////////////
//~ rjf: RDI Enum <=> Base Enum
internal Arch
arch_from_rdi_arch(RDI_Arch arch)
{
Arch result = Arch_Null;
switch((RDI_ArchEnum)arch)
{
case RDI_Arch_NULL:{}break;
case RDI_Arch_X86:{result = Arch_x86;}break;
case RDI_Arch_X64:{result = Arch_x64;}break;
}
return result;
}
//////////////////////////////// ////////////////////////////////
//~ rjf: Lookup Helpers //~ rjf: Lookup Helpers
@@ -571,11 +587,14 @@ lane_sync(); if(flags & RDI_DumpSubsetFlag_##name) ProfScope(#name)
{ {
RDI_TopLevelInfo *tli = rdi_element_from_name_idx(rdi, TopLevelInfo, 0); RDI_TopLevelInfo *tli = rdi_element_from_name_idx(rdi, TopLevelInfo, 0);
Temp scratch = scratch_begin(&arena, 1); Temp scratch = scratch_begin(&arena, 1);
Guid guid = {0};
MemoryCopy(&guid, &tli->guid, Min(sizeof guid, sizeof tli->guid));
dumpf("\n"); dumpf("\n");
dumpf(" arch: %S\n", rdi_string_from_arch(scratch.arena, tli->arch)); dumpf(" arch: %S\n", rdi_string_from_arch(scratch.arena, tli->arch));
dumpf(" exe_name: '%S'\n", str8_from_rdi_string_idx(rdi, tli->exe_name_string_idx)); dumpf(" exe_name: '%S'\n", str8_from_rdi_string_idx(rdi, tli->exe_name_string_idx));
dumpf(" voff_max: %#08llx\n", tli->voff_max); dumpf(" voff_max: %#08llx\n", tli->voff_max);
dumpf(" producer_name: '%S'\n", str8_from_rdi_string_idx(rdi, tli->producer_name_string_idx)); dumpf(" producer_name: '%S'\n", str8_from_rdi_string_idx(rdi, tli->producer_name_string_idx));
dumpf(" guid: %S\n", string_from_guid(scratch.arena, guid));
scratch_end(scratch); scratch_end(scratch);
} }
} }
+5
View File
@@ -64,6 +64,11 @@ read_only global String8 rdi_name_title_from_dump_subset_table[] =
#undef X #undef X
}; };
////////////////////////////////
//~ rjf: RDI Enum <=> Base Enum
internal Arch arch_from_rdi_arch(RDI_Arch arch);
//////////////////////////////// ////////////////////////////////
//~ rjf: Lookup Helpers //~ rjf: Lookup Helpers
+19 -19
View File
@@ -1002,30 +1002,30 @@ p2r_convert(Arena *arena, P2R_ConvertParams *params)
checksum_value.size = Min(checksum->len, checksum_value.size); checksum_value.size = Min(checksum->len, checksum_value.size);
} }
// rjf: file name -> normalized file path // rjf: file name -> sanitized file path
String8 file_path = seq_file_name; String8 file_path = seq_file_name;
String8 file_path_normalized = lower_from_str8(scratch2.arena, str8_skip_chop_whitespace(file_path)); String8 file_path_sanitized = str8_copy(scratch2.arena, str8_skip_chop_whitespace(file_path));
{ {
PathStyle file_path_normalized_style = path_style_from_str8(file_path_normalized); PathStyle file_path_sanitized_style = path_style_from_str8(file_path_sanitized);
String8List file_path_normalized_parts = str8_split_path(scratch2.arena, file_path_normalized); String8List file_path_sanitized_parts = str8_split_path(scratch2.arena, file_path_sanitized);
if(file_path_normalized_style == PathStyle_Relative) if(file_path_sanitized_style == PathStyle_Relative)
{ {
String8List obj_folder_path_parts = str8_split_path(scratch2.arena, obj_folder_path); String8List obj_folder_path_parts = str8_split_path(scratch2.arena, obj_folder_path);
str8_list_concat_in_place(&obj_folder_path_parts, &file_path_normalized_parts); str8_list_concat_in_place(&obj_folder_path_parts, &file_path_sanitized_parts);
file_path_normalized_parts = obj_folder_path_parts; file_path_sanitized_parts = obj_folder_path_parts;
file_path_normalized_style = path_style_from_str8(obj_folder_path); file_path_sanitized_style = path_style_from_str8(obj_folder_path);
} }
str8_path_list_resolve_dots_in_place(&file_path_normalized_parts, file_path_normalized_style); str8_path_list_resolve_dots_in_place(&file_path_sanitized_parts, file_path_sanitized_style);
file_path_normalized = str8_path_list_join_by_style(scratch2.arena, &file_path_normalized_parts, file_path_normalized_style); file_path_sanitized = str8_path_list_join_by_style(scratch2.arena, &file_path_sanitized_parts, file_path_sanitized_style);
} }
// rjf: normalized file path -> source file node // rjf: sanitized file path -> source file node
U64 file_path_normalized_hash = rdi_hash(file_path_normalized.str, file_path_normalized.size); U64 file_path_sanitized_hash = rdi_hash(file_path_sanitized.str, file_path_sanitized.size);
U64 hit_path_slot = file_path_normalized_hash%hit_path_slots_count; U64 hit_path_slot = file_path_sanitized_hash%hit_path_slots_count;
String8Node *hit_path_node = 0; String8Node *hit_path_node = 0;
for(String8Node *n = hit_path_slots[hit_path_slot]; n != 0; n = n->next) for(String8Node *n = hit_path_slots[hit_path_slot]; n != 0; n = n->next)
{ {
if(str8_match(n->string, file_path_normalized, 0)) if(str8_match(n->string, file_path_sanitized, 0))
{ {
hit_path_node = n; hit_path_node = n;
break; break;
@@ -1035,11 +1035,11 @@ p2r_convert(Arena *arena, P2R_ConvertParams *params)
{ {
hit_path_node = push_array(scratch2.arena, String8Node, 1); hit_path_node = push_array(scratch2.arena, String8Node, 1);
SLLStackPush(hit_path_slots[hit_path_slot], hit_path_node); SLLStackPush(hit_path_slots[hit_path_slot], hit_path_node);
hit_path_node->string = file_path_normalized; hit_path_node->string = file_path_sanitized;
P2R_SrcFileStubNode *stub_n = push_array(scratch.arena, P2R_SrcFileStubNode, 1); P2R_SrcFileStubNode *stub_n = push_array(scratch2.arena, P2R_SrcFileStubNode, 1);
SLLQueuePush(first_src_file_stub, last_src_file_stub, stub_n); SLLQueuePush(first_src_file_stub, last_src_file_stub, stub_n);
src_file_stub_count += 1; src_file_stub_count += 1;
stub_n->v.file_path = str8_copy(scratch.arena, file_path_normalized); stub_n->v.file_path = str8_copy(scratch.arena, file_path_sanitized);
stub_n->v.checksum_kind = checksum_kind; stub_n->v.checksum_kind = checksum_kind;
stub_n->v.checksum = str8_copy(scratch.arena, checksum_value); stub_n->v.checksum = str8_copy(scratch.arena, checksum_value);
} }
@@ -1801,7 +1801,6 @@ p2r_convert(Arena *arena, P2R_ConvertParams *params)
for EachInRange(idx, range) for EachInRange(idx, range)
{ {
CV_TypeId itype = (CV_TypeId)idx; CV_TypeId itype = (CV_TypeId)idx;
if(itype < itype_first) { continue; }
//- rjf: push initial itype - should be final-visited-itype for this itype //- rjf: push initial itype - should be final-visited-itype for this itype
{ {
@@ -4396,6 +4395,7 @@ p2r_convert(Arena *arena, P2R_ConvertParams *params)
top_level_info.voff_max = exe_voff_max; top_level_info.voff_max = exe_voff_max;
if(!params->deterministic) if(!params->deterministic)
{ {
MemoryCopy(&top_level_info.guid.u8[0], &pdb_info->auth_guid.v[0], Min(sizeof top_level_info.guid.u8, sizeof pdb_info->auth_guid.v));
top_level_info.producer_name = str8_lit(BUILD_TITLE_STRING_LITERAL); top_level_info.producer_name = str8_lit(BUILD_TITLE_STRING_LITERAL);
} }
} }
+1
View File
@@ -2994,6 +2994,7 @@ rdim_bake(Arena *arena, RDIM_BakeParams *params)
rdim_shared->baked_top_level_info.top_level_info.exe_name_string_idx = rdim_bake_idx_from_string(bake_strings, params->top_level_info.exe_name); rdim_shared->baked_top_level_info.top_level_info.exe_name_string_idx = rdim_bake_idx_from_string(bake_strings, params->top_level_info.exe_name);
rdim_shared->baked_top_level_info.top_level_info.exe_hash = params->top_level_info.exe_hash; rdim_shared->baked_top_level_info.top_level_info.exe_hash = params->top_level_info.exe_hash;
rdim_shared->baked_top_level_info.top_level_info.voff_max = params->top_level_info.voff_max; rdim_shared->baked_top_level_info.top_level_info.voff_max = params->top_level_info.voff_max;
rdim_shared->baked_top_level_info.top_level_info.guid = params->top_level_info.guid;
rdim_shared->baked_top_level_info.top_level_info.producer_name_string_idx = rdim_bake_idx_from_string(bake_strings, params->top_level_info.producer_name); rdim_shared->baked_top_level_info.top_level_info.producer_name_string_idx = rdim_bake_idx_from_string(bake_strings, params->top_level_info.producer_name);
} }
if(lane_idx() == lane_from_task_idx(1)) ProfScope("bake binary sections") if(lane_idx() == lane_from_task_idx(1)) ProfScope("bake binary sections")
+4 -4
View File
@@ -46,9 +46,9 @@ static inline void md5_finish(md5_ctx* ctx, uint8_t digest[MD5_DIGEST_SIZE]);
#endif #endif
#if defined(_MSC_VER) #if defined(_MSC_VER)
# define MD5_GET32LE(ptr) *((const _UNALIGNED uint32_t*)(ptr)) # define MD5_GET32LE(ptr) *((const __unaligned uint32_t*)(ptr))
# define MD5_SET32LE(ptr,x) *((_UNALIGNED uint32_t*)(ptr)) = (x) # define MD5_SET32LE(ptr,x) *((__unaligned uint32_t*)(ptr)) = (x)
# define MD5_SET64LE(ptr,x) *((_UNALIGNED uint64_t*)(ptr)) = (x) # define MD5_SET64LE(ptr,x) *((__unaligned uint64_t*)(ptr)) = (x)
#else #else
# define MD5_GET32LE(ptr) \ # define MD5_GET32LE(ptr) \
( \ ( \
@@ -431,5 +431,5 @@ void md5_finish(md5_ctx* ctx, uint8_t digest[MD5_DIGEST_SIZE])
} }
#if defined(__clang__) #if defined(__clang__)
#pragma clang diagnostic pop # pragma clang diagnostic pop
#endif #endif
+232 -17
View File
@@ -50,9 +50,9 @@ static inline void sha1_finish(sha1_ctx* ctx, uint8_t digest[SHA1_DIGEST_SIZE]);
#if defined(_MSC_VER) #if defined(_MSC_VER)
# include <stdlib.h> # include <stdlib.h>
# define SHA1_GET32BE(ptr) _byteswap_ulong( *((const _UNALIGNED uint32_t*)(ptr)) ) # define SHA1_GET32BE(ptr) _byteswap_ulong( *((const __unaligned uint32_t*)(ptr)) )
# define SHA1_SET32BE(ptr,x) *((_UNALIGNED uint32_t*)(ptr)) = _byteswap_ulong(x) # define SHA1_SET32BE(ptr,x) *((__unaligned uint32_t*)(ptr)) = _byteswap_ulong(x)
# define SHA1_SET64BE(ptr,x) *((_UNALIGNED uint64_t*)(ptr)) = _byteswap_uint64(x) # define SHA1_SET64BE(ptr,x) *((__unaligned uint64_t*)(ptr)) = _byteswap_uint64(x)
#else #else
# define SHA1_GET32BE(ptr) \ # define SHA1_GET32BE(ptr) \
( \ ( \
@@ -137,36 +137,86 @@ static inline int sha1_cpuid(void)
SHA1_TARGET("ssse3,sha") SHA1_TARGET("ssse3,sha")
static void sha1_process_shani(uint32_t* state, const uint8_t* block, size_t count) static void sha1_process_shani(uint32_t* state, const uint8_t* block, size_t count)
{ {
const __m128i* buffer = (const __m128i*)block; // in SHA1 each round has two parts:
// 1) calculate message schedule dwords in w[i]
// 2) do round functions to update a/b/c/d/e state values using w[i]
// for performing two operations in one: // w[i] in first 16 rounds is just loaded from block bytes, as 32-bit big-endian load
// 1) dwords need to be loaded as big-endian
// 2) order of dwords need to be reversed for sha instructions: [0,1,2,3] -> [3,2,1,0] // for next rounds it is done as:
const __m128i bswap = _mm_setr_epi8(15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0); // w[i] = ROL(w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16])
// where ROL(x) = 32-bit rotate left by 1
// this means it is possible to keep just the last 16 of w's in circular buffer
// and every new w calculated will need to update 1 to 3 previous w's
// unrolling round calculations by 4 we get:
// w[i+0] = ROL(w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16])
// w[i+1] = ROL(w[i-2] ^ w[i-7] ^ w[i-13] ^ w[i-15])
// w[i+2] = ROL(w[i-1] ^ w[i-6] ^ w[i-12] ^ w[i-14])
// w[i+3] = ROL(w[i+0] ^ w[i-5] ^ w[i-11] ^ w[i-13])
// now if you store 4 w[..] values in 128-bit SSE register, then
// W(i) = ROL( r0 ^ r1 ^ r2 ^ r3 )
// with caveat that r0 lane 3 depends on W(i) lane 0
// [3] [2] [1] [0] // lanes
// r0 = [ special, w[i-1], w[i-2], w[i-3] ]
// r1 = [ w[i-5], w[i-6], w[i-7], w[i-8] ]
// r2 = [ w[i-11], w[i-12], w[i-13], w[i-14] ]
// r3 = [ w[i-13], w[i-14], w[i-15], w[i-16] ]
// in each 4-round i'th step it is possible to incrementally update new W(..) value when
// keeping W(i) values in 4 xmm element circular buffer
// rounds i>0: W(i-1) = r2 ^ r3 = _mm_sha1msg1_epu32(W(i-1), W(i))
// rounds i>1: W(i-2) = W(i-2) ^ r1 = _mm_xor_si128 (W(i-2), W(i))
// rounds i>2: W(i-3) = ROL(W(i-3) ^ r0) = _mm_sha1msg2_epu32(W(i-3), W(i))
// then the new W(i) can be used in round function calculations
// _mm_sha1msg2_epu32 correctly handles r0 lane 3 dependency on W(i) lane 0
// to perform round functions on two SIMD registers with state as:
// abcd = [a,b,c,d]
// e0 = [e,0,0,0]
// use the following code to get next abcd/e0 state 4 rounds at a time:
// tmp = _mm_sha1nexte_epu32(e0, W(i)) // rotates e0 and adds message dwords
// abcd_next = _mm_sha1rnds4_epu32(abcd, tmp, Fn) // with Fn = 0..3 round function selection
// e0_next = abcd
// sha1nexte is not needed on first round, just regular add32(e0, W(i)) should be used
// after last round need to do extra rotation, which sha1nexte takes care when adding to last_e0
#define W(i) w[(i)%4] #define W(i) w[(i)%4]
// 4 wide round calculations // 4 wide round calculations
#define QROUND(i) do { \ #define QROUND(i) do { \
/* first four rounds loads input message */ \ /* first 4 rounds load input block */ \
if (i < 4) W(i) = _mm_shuffle_epi8(_mm_loadu_si128(&buffer[i]), bswap); \ if (i < 4) W(i) = _mm_shuffle_epi8(_mm_loadu_si128(&buffer[i]), bswap); \
/* update previous message dwords for next rounds */ \ /* update message schedule */ \
if (i > 0 && i < 17) W(i-1) = _mm_sha1msg1_epu32(W(i-1), W(i)); \ if (i > 0 && i < 17) W(i-1) = _mm_sha1msg1_epu32(W(i-1), W(i)); \
if (i > 1 && i < 18) W(i-2) = _mm_xor_si128(W(i-2), W(i)); \ if (i > 1 && i < 18) W(i-2) = _mm_xor_si128 (W(i-2), W(i)); \
if (i > 2 && i < 19) W(i-3) = _mm_sha1msg2_epu32(W(i-3), W(i)); \ if (i > 2 && i < 19) W(i-3) = _mm_sha1msg2_epu32(W(i-3), W(i)); \
/* calculate E from message dwords */ \ /* calculate E plus message schedule */ \
if (i == 0) tmp = _mm_add_epi32(e0, W(i)); \ if (i == 0) tmp = _mm_add_epi32 (e0, W(i)); \
if (i != 0) tmp = _mm_sha1nexte_epu32(e0, W(i)); \ if (i != 0) tmp = _mm_sha1nexte_epu32(e0, W(i)); \
/* round function */ \ /* 4 round functions */ \
e0 = abcd; \ e0 = abcd; \
abcd = _mm_sha1rnds4_epu32(abcd, tmp, (i/5)%4); \ abcd = _mm_sha1rnds4_epu32(abcd, tmp, i/5); \
} while(0) } while(0)
const __m128i* buffer = (const __m128i*)block;
// for performing two operations in one:
// 1) dwords need to be loaded as big-endian
// 2) order of dwords need to be reversed for sha1 instructions: [0,1,2,3] -> [3,2,1,0]
const __m128i bswap = _mm_setr_epi8(15,14,13,12, 11,10,9,8, 7,6,5,4, 3,2,1,0);
// load initial state // load initial state
__m128i abcd = _mm_loadu_si128((const __m128i*)state); // [d,c,b,a] __m128i abcd = _mm_loadu_si128((const __m128i*)state); // [d,c,b,a]
__m128i e0 = _mm_loadu_si32(&state[4]); // [0,0,0,e] __m128i e0 = _mm_loadu_si32(&state[4]); // [0,0,0,e]
// change dword order // flip dword order, to what sha1 instructions use
abcd = _mm_shuffle_epi32(abcd, _MM_SHUFFLE(0,1,2,3)); // [a,b,c,d] where a is in the top lane abcd = _mm_shuffle_epi32(abcd, _MM_SHUFFLE(0,1,2,3)); // [a,b,c,d] where a is in the top lane
e0 = _mm_slli_si128(e0, 12); // [e,0,0,0] where e is in top lane e0 = _mm_slli_si128(e0, 12); // [e,0,0,0] where e is in top lane
@@ -183,16 +233,19 @@ static void sha1_process_shani(uint32_t* state, const uint8_t* block, size_t cou
QROUND(2); QROUND(2);
QROUND(3); QROUND(3);
QROUND(4); QROUND(4);
QROUND(5); QROUND(5);
QROUND(6); QROUND(6);
QROUND(7); QROUND(7);
QROUND(8); QROUND(8);
QROUND(9); QROUND(9);
QROUND(10); QROUND(10);
QROUND(11); QROUND(11);
QROUND(12); QROUND(12);
QROUND(13); QROUND(13);
QROUND(14); QROUND(14);
QROUND(15); QROUND(15);
QROUND(16); QROUND(16);
QROUND(17); QROUND(17);
@@ -221,6 +274,159 @@ static void sha1_process_shani(uint32_t* state, const uint8_t* block, size_t cou
#endif // defined(__x86_64__) || defined(_M_AMD64) #endif // defined(__x86_64__) || defined(_M_AMD64)
#if defined(__aarch64__) || defined(_M_ARM64)
#if defined(__clang__)
# define SHA1_TARGET __attribute__((target("sha2")))
#elif defined(__GNUC__)
# define SHA1_TARGET __attribute__((target("+sha2")))
#elif defined(_MSC_VER)
# define SHA1_TARGET
#endif
#include <arm_neon.h>
#if defined(_WIN32)
# include <windows.h>
#elif defined(__linux__)
# include <sys/auxv.h>
# include <asm/hwcap.h>
#elif defined(__APPLE__)
# include <sys/sysctl.h>
#endif
#define SHA1_CPUID_INIT (1 << 0)
#define SHA1_CPUID_ARM64 (1 << 1)
static inline int sha1_cpuid(void)
{
#if defined(__ARM_FEATURE_CRYPTO) || defined(__ARM_FEATURE_SHA2)
int result = SHA1_CPUID_ARM64;
#else
static int cpuid;
int result = cpuid;
if (result == 0)
{
#if defined(_WIN32)
int has_arm64 = IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE);
#elif defined(__linux__)
unsigned long hwcap = getauxval(AT_HWCAP);
int has_arm64 = hwcap & HWCAP_SHA1;
#elif defined(__APPLE__)
int value = 0;
size_t valuelen = sizeof(value);
int has_arm64 = sysctlbyname("hw.optional.arm.FEAT_SHA1", &value, &valuelen, NULL, 0) == 0 && value != 0;
#else
#error unknown platform
#endif
result |= SHA1_CPUID_INIT;
if (has_arm64)
{
result |= SHA1_CPUID_ARM64;
}
cpuid = result;
}
#endif
#if defined(SHA1_CPUID_MASK)
result &= SHA1_CPUID_MASK;
#endif
return result;
}
SHA1_TARGET
static void sha1_process_arm64(uint32_t* state, const uint8_t* block, size_t count)
{
// code here is similar to x64 shani implementation
// message array is 16 element circular buffer
// each iteration updates 4 rounds at the same time
#define W(i) w[(i)%4]
#define QROUND(i,F,k) do { \
/* update message schedule */ \
if (i >= 4) W(i) = vsha1su0q_u32(W(i), W(i-3), W(i-2)); \
if (i >= 4) W(i) = vsha1su1q_u32(W(i), W(i-1)); \
/* add round constant */ \
uint32x4_t tmp = vaddq_u32(W(i), k); \
/* 4 round functions */ \
uint32_t x = e0; \
e0 = vsha1h_u32(vgetq_lane_u32(abcd, 0)); \
abcd = F(abcd, x, tmp); \
} while (0)
const uint32x4_t k0 = vdupq_n_u32(0x5a827999);
const uint32x4_t k1 = vdupq_n_u32(0x6ed9eba1);
const uint32x4_t k2 = vdupq_n_u32(0x8f1bbcdc);
const uint32x4_t k3 = vdupq_n_u32(0xca62c1d6);
// load state - a,b,c,d,e
uint32x4_t abcd = vld1q_u32(state);
uint32_t e0 = state[4];
do
{
// remember current state
uint32x4_t last_abcd = abcd;
uint32_t last_e0 = e0;
// load 64-byte block and advance pointer to next block
uint8x16x4_t msg = vld1q_u8_x4(block);
block += SHA1_BLOCK_SIZE;
uint32x4_t w[4];
// for first 16 w's reverse the byte order in each 32-bit lane
W(0) = vreinterpretq_u32_u8(vrev32q_u8(msg.val[0]));
W(1) = vreinterpretq_u32_u8(vrev32q_u8(msg.val[1]));
W(2) = vreinterpretq_u32_u8(vrev32q_u8(msg.val[2]));
W(3) = vreinterpretq_u32_u8(vrev32q_u8(msg.val[3]));
QROUND( 0, vsha1cq_u32, k0);
QROUND( 1, vsha1cq_u32, k0);
QROUND( 2, vsha1cq_u32, k0);
QROUND( 3, vsha1cq_u32, k0);
QROUND( 4, vsha1cq_u32, k0);
QROUND( 5, vsha1pq_u32, k1);
QROUND( 6, vsha1pq_u32, k1);
QROUND( 7, vsha1pq_u32, k1);
QROUND( 8, vsha1pq_u32, k1);
QROUND( 9, vsha1pq_u32, k1);
QROUND(10, vsha1mq_u32, k2);
QROUND(11, vsha1mq_u32, k2);
QROUND(12, vsha1mq_u32, k2);
QROUND(13, vsha1mq_u32, k2);
QROUND(14, vsha1mq_u32, k2);
QROUND(15, vsha1pq_u32, k3);
QROUND(16, vsha1pq_u32, k3);
QROUND(17, vsha1pq_u32, k3);
QROUND(18, vsha1pq_u32, k3);
QROUND(19, vsha1pq_u32, k3);
// update next state
abcd = vaddq_u32(abcd, last_abcd);
e0 += last_e0;
}
while (--count);
// save state
vst1q_u32(state, abcd);
state[4] = e0;
#undef QROUND
#undef W
}
#endif // defined(__aarch64__) || defined(_M_ARM64)
static void sha1_process(uint32_t* state, const uint8_t* block, size_t count) static void sha1_process(uint32_t* state, const uint8_t* block, size_t count)
{ {
#if defined(__x86_64__) || defined(_M_AMD64) #if defined(__x86_64__) || defined(_M_AMD64)
@@ -232,12 +438,21 @@ static void sha1_process(uint32_t* state, const uint8_t* block, size_t count)
} }
#endif #endif
#if defined(__aarch64__) || defined(_M_ARM64)
int cpuid = sha1_cpuid();
if (cpuid & SHA1_CPUID_ARM64)
{
sha1_process_arm64(state, block, count);
return;
}
#endif
#define F1(x,y,z) (0x5a827999 + ((x & (y ^ z)) ^ z)) #define F1(x,y,z) (0x5a827999 + ((x & (y ^ z)) ^ z))
#define F2(x,y,z) (0x6ed9eba1 + (x ^ y ^ z)) #define F2(x,y,z) (0x6ed9eba1 + (x ^ y ^ z))
#define F3(x,y,z) (0x8f1bbcdc + ((x & y) | (z & (x | y)))) #define F3(x,y,z) (0x8f1bbcdc + ((x & y) | (z & (x | y))))
#define F4(x,y,z) (0xca62c1d6 + (x ^ y ^ z)) #define F4(x,y,z) (0xca62c1d6 + (x ^ y ^ z))
#define W(i) w[(i+16)%16] #define W(i) w[(i)%16]
#define ROUND(i,a,b,c,d,e,F) do \ #define ROUND(i,a,b,c,d,e,F) do \
{ \ { \
+288 -108
View File
@@ -58,9 +58,9 @@ static inline void sha224_finish(sha224_ctx* ctx, uint8_t digest[SHA224_DIGEST_S
#if defined(_MSC_VER) #if defined(_MSC_VER)
# include <stdlib.h> # include <stdlib.h>
# define SHA256_GET32BE(ptr) _byteswap_ulong( *((const _UNALIGNED uint32_t*)(ptr)) ) # define SHA256_GET32BE(ptr) _byteswap_ulong( *((const __unaligned uint32_t*)(ptr)) )
# define SHA256_SET32BE(ptr,x) *((_UNALIGNED uint32_t*)(ptr)) = _byteswap_ulong(x) # define SHA256_SET32BE(ptr,x) *((__unaligned uint32_t*)(ptr)) = _byteswap_ulong(x)
# define SHA256_SET64BE(ptr,x) *((_UNALIGNED uint64_t*)(ptr)) = _byteswap_uint64(x) # define SHA256_SET64BE(ptr,x) *((__unaligned uint64_t*)(ptr)) = _byteswap_uint64(x)
#else #else
# define SHA256_GET32BE(ptr) \ # define SHA256_GET32BE(ptr) \
( \ ( \
@@ -91,6 +91,26 @@ static inline void sha224_finish(sha224_ctx* ctx, uint8_t digest[SHA224_DIGEST_S
while (0) while (0)
#endif #endif
static const uint32_t SHA256_K[64] =
{
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
};
#if defined(__x86_64__) || defined(_M_AMD64) #if defined(__x86_64__) || defined(_M_AMD64)
#include <tmmintrin.h> // SSSE3 #include <tmmintrin.h> // SSSE3
@@ -145,47 +165,64 @@ static inline int sha256_cpuid(void)
SHA256_TARGET("ssse3,sha") SHA256_TARGET("ssse3,sha")
static void sha256_process_shani(uint32_t* state, const uint8_t* block, size_t count) static void sha256_process_shani(uint32_t* state, const uint8_t* block, size_t count)
{ {
const __m128i* buffer = (const __m128i*)block; // similar way how sha1 works in with shani
// to byteswap when doing big-ending load for message dwords // first 16 rounds loads message schedule dwords as 32-bit big endian values
const __m128i bswap = _mm_setr_epi8(3,2,1,0, 7,6,5,4, 11,10,9,8, 15,14,13,12);
static const uint32_t K[16][4] = // for next rounds message schedule is prepared as:
{ // w[i] = SSig1(w[i-2]) + w[i-7] + SSig0(w[i-15]) + w[i-16]
{ 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5 },
{ 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5 }, // unrolled by 4:
{ 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3 }, // w[i+0] = SSig1(w[i-2]) + w[i-7] + SSig0(w[i-15]) + w[i-16]
{ 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174 }, // w[i+1] = SSig1(w[i-1]) + w[i-6] + SSig0(w[i-14]) + w[i-15]
{ 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc }, // w[i+2] = SSig1(w[i+0]) + w[i-5] + SSig0(w[i-13]) + w[i-14]
{ 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da }, // w[i+3] = SSig1(w[i+1]) + w[i-4] + SSig0(w[i-12]) + w[i-13]
{ 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7 },
{ 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967 }, // there is tricky dependency for lanes 2 and 3 on result of lanes 0 and 1, but sha256msg2 op takes care of that
{ 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13 },
{ 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85 }, // by storing W[i] word in 128-bit simd register, the message schedule becomes:
{ 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3 }, // W(i) = SSig1(r0) + r1 + SSig0(r2) + r3
{ 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070 }, // where + is 32-bit lane addition
{ 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5 },
{ 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3 }, // [3] [2] [1] [0] // lanes
{ 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208 }, // r0 = [ special, special, w[i-1], w[i-2] ]
{ 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 }, // r1 = [ w[i-4], w[i-5], w[i-6], w[i-7] ]
}; // r2 = [ w[i-12], w[i-13], w[i-14], w[i-15] ]
// r3 = [ w[i-13], w[i-14], w[i-15], w[i-16] ]
// rN's can be calculated from previous W(..) values:
// r0 from W(i)
// r1 from _mm_alignr_epi8(W(i), W(i-1), 4)
// r2 from W(i-1) and W(i)
// r3 from W(i-1)
// rounds i>2: W(i-3) = _mm_sha256msg2_epu32(_mm_add_epi32( W(i-3), _mm_alignr_epi8(W(i), W(i-1), 4) ), W(i))
// rounds i>0: W(i-1) = _mm_sha256msg1_epu32(W(i-1), W(i))
// round functions are done with _mm_sha256rnds2_epu32 which performs it for 2 rounds
// thus repeat it two times, as input use W(i) + K(i) - message schedule added with sha256 constants
#define W(i) w[(i)%4] #define W(i) w[(i)%4]
// 4 wide round calculations // 4 wide round calculations
#define QROUND(i) do { \ #define QROUND(i) do { \
/* first four rounds loads input message */ \ /* first 4 rounds load input block */ \
if (i < 4) W(i) = _mm_shuffle_epi8(_mm_loadu_si128(&buffer[i]), bswap); \ if (i < 4) W(i) = _mm_shuffle_epi8(_mm_loadu_si128(&buffer[i]), bswap); \
/* add round constant */ \ /* update message schedule */ \
tmp = _mm_add_epi32(W(i), _mm_loadu_si128((const __m128i*)K[i])); \
/* update previous message dwords for next rounds */ \
if (i > 2 && i < 15) W(i-3) = _mm_sha256msg2_epu32(_mm_add_epi32(W(i-3), _mm_alignr_epi8(W(i), W(i-1), 4)), W(i)); \ if (i > 2 && i < 15) W(i-3) = _mm_sha256msg2_epu32(_mm_add_epi32(W(i-3), _mm_alignr_epi8(W(i), W(i-1), 4)), W(i)); \
if (i > 0 && i < 13) W(i-1) = _mm_sha256msg1_epu32(W(i-1), W(i)); \ if (i > 0 && i < 13) W(i-1) = _mm_sha256msg1_epu32(W(i-1), W(i)); \
/* round functions */ \ /* add round constants */ \
__m128i tmp = _mm_add_epi32(W(i), _mm_loadu_si128((const __m128i*)&SHA256_K[4*i])); \
/* 4 round functions */ \
state1 = _mm_sha256rnds2_epu32(state1, state0, tmp); \ state1 = _mm_sha256rnds2_epu32(state1, state0, tmp); \
state0 = _mm_sha256rnds2_epu32(state0, state1, _mm_shuffle_epi32(tmp, _MM_SHUFFLE(0,0,3,2))); \ state0 = _mm_sha256rnds2_epu32(state0, state1, _mm_shuffle_epi32(tmp, _MM_SHUFFLE(0,0,3,2))); \
} while(0) } while(0)
const __m128i* buffer = (const __m128i*)block;
// to byteswap when doing big-ending load for message dwords
const __m128i bswap = _mm_setr_epi8(3,2,1,0, 7,6,5,4, 11,10,9,8, 15,14,13,12);
// load initial state // load initial state
__m128i abcd = _mm_shuffle_epi32(_mm_loadu_si128((const __m128i*)&state[0]), _MM_SHUFFLE(0,1,2,3)); // [a,b,c,d] __m128i abcd = _mm_shuffle_epi32(_mm_loadu_si128((const __m128i*)&state[0]), _MM_SHUFFLE(0,1,2,3)); // [a,b,c,d]
__m128i efgh = _mm_shuffle_epi32(_mm_loadu_si128((const __m128i*)&state[4]), _MM_SHUFFLE(0,1,2,3)); // [e,f,g,h] __m128i efgh = _mm_shuffle_epi32(_mm_loadu_si128((const __m128i*)&state[4]), _MM_SHUFFLE(0,1,2,3)); // [e,f,g,h]
@@ -200,18 +237,18 @@ static void sha256_process_shani(uint32_t* state, const uint8_t* block, size_t c
__m128i last0 = state0; __m128i last0 = state0;
__m128i last1 = state1; __m128i last1 = state1;
__m128i tmp, w[4]; __m128i w[4];
QROUND(0); QROUND( 0);
QROUND(1); QROUND( 1);
QROUND(2); QROUND( 2);
QROUND(3); QROUND( 3);
QROUND(4); QROUND( 4);
QROUND(5); QROUND( 5);
QROUND(6); QROUND( 6);
QROUND(7); QROUND( 7);
QROUND(8); QROUND( 8);
QROUND(9); QROUND( 9);
QROUND(10); QROUND(10);
QROUND(11); QROUND(11);
QROUND(12); QROUND(12);
@@ -241,6 +278,140 @@ static void sha256_process_shani(uint32_t* state, const uint8_t* block, size_t c
#endif // defined(__x86_64__) || defined(_M_AMD64) #endif // defined(__x86_64__) || defined(_M_AMD64)
#if defined(__aarch64__) || defined(_M_ARM64)
#if defined(__clang__)
# define SHA256_TARGET __attribute__((target("sha2")))
#elif defined(__GNUC__)
# define SHA256_TARGET __attribute__((target("+sha2")))
#elif defined(_MSC_VER)
# define SHA256_TARGET
#endif
#include <arm_neon.h>
#if defined(_WIN32)
# include <windows.h>
#elif defined(__linux__)
# include <sys/auxv.h>
# include <asm/hwcap.h>
#elif defined(__APPLE__)
# include <sys/sysctl.h>
#endif
#define SHA256_CPUID_INIT (1 << 0)
#define SHA256_CPUID_ARM64 (1 << 1)
static inline int sha256_cpuid(void)
{
#if defined(__ARM_FEATURE_CRYPTO) || defined(__ARM_FEATURE_SHA2)
int result = SHA256_CPUID_ARM64;
#else
static int cpuid;
int result = cpuid;
if (result == 0)
{
#if defined(_WIN32)
int has_arm64 = IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE);
#elif defined(__linux__)
unsigned long hwcap = getauxval(AT_HWCAP);
int has_arm64 = hwcap & HWCAP_SHA2;
#elif defined(__APPLE__)
int value = 0;
size_t valuelen = sizeof(value);
int has_arm64 = sysctlbyname("hw.optional.arm.FEAT_SHA256", &value, &valuelen, NULL, 0) == 0 && value != 0;
#else
#error unknown platform
#endif
result |= SHA256_CPUID_INIT;
if (has_arm64)
{
result |= SHA256_CPUID_ARM64;
}
cpuid = result;
}
#endif
#if defined(SHA256_CPUID_MASK)
result &= SHA256_CPUID_MASK;
#endif
return result;
}
SHA256_TARGET
static void sha256_process_arm64(uint32_t* state, const uint8_t* block, size_t count)
{
// code here is similar to x64 shani implementation
#define W(i) w[(i)%4]
#define QROUND(i) do { \
/* load 16 round constants */ \
if ((i % 4) == 0) rk = vld1q_u32_x4(&SHA256_K[4*i]); \
/* first 4 rounds reverse byte order in each 32-bit lane of input block */ \
if (i < 4) W(i) = vreinterpretq_u32_u8(vrev32q_u8(msg.val[i])); \
/* update message schedule */ \
if (i >= 4) W(i) = vsha256su0q_u32(W(i), W(i-3)); \
if (i >= 4) W(i) = vsha256su1q_u32(W(i), W(i-2), W(i-1)); \
/* add round constants */ \
uint32x4_t tmp = vaddq_u32(W(i), rk.val[i%4]); \
/* 4 round functions */ \
uint32x4_t x = vstate.val[0]; \
vstate.val[0] = vsha256hq_u32(vstate.val[0], vstate.val[1], tmp); \
vstate.val[1] = vsha256h2q_u32(vstate.val[1], x, tmp); \
} while (0)
// load initial state
uint32x4x2_t vstate = vld1q_u32_x2(state);
do
{
// remember current state
uint32x4x2_t vlast = vstate;
// load 64-byte block
uint8x16x4_t msg = vld1q_u8_x4(block);
uint32x4x4_t rk;
uint32x4_t w[4];
QROUND( 0);
QROUND( 1);
QROUND( 2);
QROUND( 3);
QROUND( 4);
QROUND( 5);
QROUND( 6);
QROUND( 7);
QROUND( 8);
QROUND( 9);
QROUND(10);
QROUND(11);
QROUND(12);
QROUND(13);
QROUND(14);
QROUND(15);
// update next state
vstate.val[0] = vaddq_u32(vstate.val[0], vlast.val[0]);
vstate.val[1] = vaddq_u32(vstate.val[1], vlast.val[1]);
block += SHA256_BLOCK_SIZE;
}
while (--count);
// save the new state
vst1q_u32_x2(state, vstate);
#undef QROUND
#undef W
}
#endif // defined(__aarch64__) || defined(_M_ARM64)
static void sha256_process(uint32_t* state, const uint8_t* block, size_t count) static void sha256_process(uint32_t* state, const uint8_t* block, size_t count)
{ {
#if defined(__x86_64__) || defined(_M_AMD64) #if defined(__x86_64__) || defined(_M_AMD64)
@@ -252,6 +423,15 @@ static void sha256_process(uint32_t* state, const uint8_t* block, size_t count)
} }
#endif #endif
#if defined(__aarch64__) || defined(_M_ARM64)
int cpuid = sha256_cpuid();
if (cpuid & SHA256_CPUID_ARM64)
{
sha256_process_arm64(state, block, count);
return;
}
#endif
#define Ch(x,y,z) ((x & (y ^ z)) ^ z) #define Ch(x,y,z) ((x & (y ^ z)) ^ z)
#define Maj(x,y,z) ((x & y) | (z & (x | y))) #define Maj(x,y,z) ((x & y) | (z & (x | y)))
@@ -262,13 +442,13 @@ static void sha256_process(uint32_t* state, const uint8_t* block, size_t count)
#define W(i) w[(i+16)%16] #define W(i) w[(i+16)%16]
#define ROUND(i,a,b,c,d,e,f,g,h,K) do \ #define ROUND(i,a,b,c,d,e,f,g,h) do \
{ \ { \
uint32_t w0; \ uint32_t w0; \
if (i < 16) W(i) = w0 = SHA256_GET32BE(block + i*sizeof(uint32_t)); \ if (i < 16) W(i) = w0 = SHA256_GET32BE(block + i*sizeof(uint32_t)); \
if (i >= 16) W(i) = w0 = SSig1(W(i-2)) + W(i-7) + SSig0(W(i-15)) + W(i-16); \ if (i >= 16) W(i) = w0 = SSig1(W(i-2)) + W(i-7) + SSig0(W(i-15)) + W(i-16); \
\ \
uint32_t t1 = h + BSig1(e) + Ch(e,f,g) + K + w0; \ uint32_t t1 = h + BSig1(e) + Ch(e,f,g) + SHA256_K[i] + w0; \
uint32_t t2 = BSig0(a) + Maj(a,b,c); \ uint32_t t2 = BSig0(a) + Maj(a,b,c); \
d += t1; \ d += t1; \
h = t1 + t2; \ h = t1 + t2; \
@@ -287,70 +467,70 @@ static void sha256_process(uint32_t* state, const uint8_t* block, size_t count)
uint32_t w[16]; uint32_t w[16];
ROUND( 0, a, b, c, d, e, f, g, h, 0x428a2f98); ROUND( 0, a, b, c, d, e, f, g, h);
ROUND( 1, h, a, b, c, d, e, f, g, 0x71374491); ROUND( 1, h, a, b, c, d, e, f, g);
ROUND( 2, g, h, a, b, c, d, e, f, 0xb5c0fbcf); ROUND( 2, g, h, a, b, c, d, e, f);
ROUND( 3, f, g, h, a, b, c, d, e, 0xe9b5dba5); ROUND( 3, f, g, h, a, b, c, d, e);
ROUND( 4, e, f, g, h, a, b, c, d, 0x3956c25b); ROUND( 4, e, f, g, h, a, b, c, d);
ROUND( 5, d, e, f, g, h, a, b, c, 0x59f111f1); ROUND( 5, d, e, f, g, h, a, b, c);
ROUND( 6, c, d, e, f, g, h, a, b, 0x923f82a4); ROUND( 6, c, d, e, f, g, h, a, b);
ROUND( 7, b, c, d, e, f, g, h, a, 0xab1c5ed5); ROUND( 7, b, c, d, e, f, g, h, a);
ROUND( 8, a, b, c, d, e, f, g, h, 0xd807aa98); ROUND( 8, a, b, c, d, e, f, g, h);
ROUND( 9, h, a, b, c, d, e, f, g, 0x12835b01); ROUND( 9, h, a, b, c, d, e, f, g);
ROUND(10, g, h, a, b, c, d, e, f, 0x243185be); ROUND(10, g, h, a, b, c, d, e, f);
ROUND(11, f, g, h, a, b, c, d, e, 0x550c7dc3); ROUND(11, f, g, h, a, b, c, d, e);
ROUND(12, e, f, g, h, a, b, c, d, 0x72be5d74); ROUND(12, e, f, g, h, a, b, c, d);
ROUND(13, d, e, f, g, h, a, b, c, 0x80deb1fe); ROUND(13, d, e, f, g, h, a, b, c);
ROUND(14, c, d, e, f, g, h, a, b, 0x9bdc06a7); ROUND(14, c, d, e, f, g, h, a, b);
ROUND(15, b, c, d, e, f, g, h, a, 0xc19bf174); ROUND(15, b, c, d, e, f, g, h, a);
ROUND(16, a, b, c, d, e, f, g, h, 0xe49b69c1); ROUND(16, a, b, c, d, e, f, g, h);
ROUND(17, h, a, b, c, d, e, f, g, 0xefbe4786); ROUND(17, h, a, b, c, d, e, f, g);
ROUND(18, g, h, a, b, c, d, e, f, 0x0fc19dc6); ROUND(18, g, h, a, b, c, d, e, f);
ROUND(19, f, g, h, a, b, c, d, e, 0x240ca1cc); ROUND(19, f, g, h, a, b, c, d, e);
ROUND(20, e, f, g, h, a, b, c, d, 0x2de92c6f); ROUND(20, e, f, g, h, a, b, c, d);
ROUND(21, d, e, f, g, h, a, b, c, 0x4a7484aa); ROUND(21, d, e, f, g, h, a, b, c);
ROUND(22, c, d, e, f, g, h, a, b, 0x5cb0a9dc); ROUND(22, c, d, e, f, g, h, a, b);
ROUND(23, b, c, d, e, f, g, h, a, 0x76f988da); ROUND(23, b, c, d, e, f, g, h, a);
ROUND(24, a, b, c, d, e, f, g, h, 0x983e5152); ROUND(24, a, b, c, d, e, f, g, h);
ROUND(25, h, a, b, c, d, e, f, g, 0xa831c66d); ROUND(25, h, a, b, c, d, e, f, g);
ROUND(26, g, h, a, b, c, d, e, f, 0xb00327c8); ROUND(26, g, h, a, b, c, d, e, f);
ROUND(27, f, g, h, a, b, c, d, e, 0xbf597fc7); ROUND(27, f, g, h, a, b, c, d, e);
ROUND(28, e, f, g, h, a, b, c, d, 0xc6e00bf3); ROUND(28, e, f, g, h, a, b, c, d);
ROUND(29, d, e, f, g, h, a, b, c, 0xd5a79147); ROUND(29, d, e, f, g, h, a, b, c);
ROUND(30, c, d, e, f, g, h, a, b, 0x06ca6351); ROUND(30, c, d, e, f, g, h, a, b);
ROUND(31, b, c, d, e, f, g, h, a, 0x14292967); ROUND(31, b, c, d, e, f, g, h, a);
ROUND(32, a, b, c, d, e, f, g, h, 0x27b70a85); ROUND(32, a, b, c, d, e, f, g, h);
ROUND(33, h, a, b, c, d, e, f, g, 0x2e1b2138); ROUND(33, h, a, b, c, d, e, f, g);
ROUND(34, g, h, a, b, c, d, e, f, 0x4d2c6dfc); ROUND(34, g, h, a, b, c, d, e, f);
ROUND(35, f, g, h, a, b, c, d, e, 0x53380d13); ROUND(35, f, g, h, a, b, c, d, e);
ROUND(36, e, f, g, h, a, b, c, d, 0x650a7354); ROUND(36, e, f, g, h, a, b, c, d);
ROUND(37, d, e, f, g, h, a, b, c, 0x766a0abb); ROUND(37, d, e, f, g, h, a, b, c);
ROUND(38, c, d, e, f, g, h, a, b, 0x81c2c92e); ROUND(38, c, d, e, f, g, h, a, b);
ROUND(39, b, c, d, e, f, g, h, a, 0x92722c85); ROUND(39, b, c, d, e, f, g, h, a);
ROUND(40, a, b, c, d, e, f, g, h, 0xa2bfe8a1); ROUND(40, a, b, c, d, e, f, g, h);
ROUND(41, h, a, b, c, d, e, f, g, 0xa81a664b); ROUND(41, h, a, b, c, d, e, f, g);
ROUND(42, g, h, a, b, c, d, e, f, 0xc24b8b70); ROUND(42, g, h, a, b, c, d, e, f);
ROUND(43, f, g, h, a, b, c, d, e, 0xc76c51a3); ROUND(43, f, g, h, a, b, c, d, e);
ROUND(44, e, f, g, h, a, b, c, d, 0xd192e819); ROUND(44, e, f, g, h, a, b, c, d);
ROUND(45, d, e, f, g, h, a, b, c, 0xd6990624); ROUND(45, d, e, f, g, h, a, b, c);
ROUND(46, c, d, e, f, g, h, a, b, 0xf40e3585); ROUND(46, c, d, e, f, g, h, a, b);
ROUND(47, b, c, d, e, f, g, h, a, 0x106aa070); ROUND(47, b, c, d, e, f, g, h, a);
ROUND(48, a, b, c, d, e, f, g, h, 0x19a4c116); ROUND(48, a, b, c, d, e, f, g, h);
ROUND(49, h, a, b, c, d, e, f, g, 0x1e376c08); ROUND(49, h, a, b, c, d, e, f, g);
ROUND(50, g, h, a, b, c, d, e, f, 0x2748774c); ROUND(50, g, h, a, b, c, d, e, f);
ROUND(51, f, g, h, a, b, c, d, e, 0x34b0bcb5); ROUND(51, f, g, h, a, b, c, d, e);
ROUND(52, e, f, g, h, a, b, c, d, 0x391c0cb3); ROUND(52, e, f, g, h, a, b, c, d);
ROUND(53, d, e, f, g, h, a, b, c, 0x4ed8aa4a); ROUND(53, d, e, f, g, h, a, b, c);
ROUND(54, c, d, e, f, g, h, a, b, 0x5b9cca4f); ROUND(54, c, d, e, f, g, h, a, b);
ROUND(55, b, c, d, e, f, g, h, a, 0x682e6ff3); ROUND(55, b, c, d, e, f, g, h, a);
ROUND(56, a, b, c, d, e, f, g, h, 0x748f82ee); ROUND(56, a, b, c, d, e, f, g, h);
ROUND(57, h, a, b, c, d, e, f, g, 0x78a5636f); ROUND(57, h, a, b, c, d, e, f, g);
ROUND(58, g, h, a, b, c, d, e, f, 0x84c87814); ROUND(58, g, h, a, b, c, d, e, f);
ROUND(59, f, g, h, a, b, c, d, e, 0x8cc70208); ROUND(59, f, g, h, a, b, c, d, e);
ROUND(60, e, f, g, h, a, b, c, d, 0x90befffa); ROUND(60, e, f, g, h, a, b, c, d);
ROUND(61, d, e, f, g, h, a, b, c, 0xa4506ceb); ROUND(61, d, e, f, g, h, a, b, c);
ROUND(62, c, d, e, f, g, h, a, b, 0xbef9a3f7); ROUND(62, c, d, e, f, g, h, a, b);
ROUND(63, b, c, d, e, f, g, h, a, 0xc67178f2); ROUND(63, b, c, d, e, f, g, h, a);
state[0] += a; state[0] += a;
state[1] += b; state[1] += b;
+572 -375
View File
File diff suppressed because it is too large Load Diff