diff --git a/src/df/core/df_core.c b/src/df/core/df_core.c index 23c1b8bb..d44b6cca 100644 --- a/src/df/core/df_core.c +++ b/src/df/core/df_core.c @@ -923,15 +923,15 @@ df_cmd_params_apply_spec_query(Arena *arena, DF_CtrlCtx *ctrl_ctx, DF_CmdParams params->index = u64; df_cmd_params_mark_slot(params, DF_CmdParamSlot_Index); }break; - case DF_CmdParamSlot_BaseUnwindIndex: + case DF_CmdParamSlot_UnwindIndex: { - params->base_unwind_index = u64; - df_cmd_params_mark_slot(params, DF_CmdParamSlot_BaseUnwindIndex); + params->unwind_index = u64; + df_cmd_params_mark_slot(params, DF_CmdParamSlot_UnwindIndex); }break; - case DF_CmdParamSlot_InlineUnwindIndex: + case DF_CmdParamSlot_InlineDepth: { - params->inline_unwind_index = u64; - df_cmd_params_mark_slot(params, DF_CmdParamSlot_InlineUnwindIndex); + params->inline_depth = u64; + df_cmd_params_mark_slot(params, DF_CmdParamSlot_InlineDepth); }break; case DF_CmdParamSlot_ID: { @@ -3241,7 +3241,7 @@ df_lines_from_dbgi_key_voff(Arena *arena, DI_Key *dbgi_key, U64 voff) String8 file_normalized_full_path = {0}; file_normalized_full_path.str = rdi_string_from_idx(rdi, file->normal_full_path_string_idx, &file_normalized_full_path.size); DF_LineNode *n = push_array(arena, DF_LineNode, 1); - SLLQueuePush(result.first, result.last, n); + SLLQueuePushFront(result.first, result.last, n); result.count += 1; if(line->file_idx != 0 && file_normalized_full_path.size != 0) { @@ -3671,80 +3671,44 @@ df_module_from_thread_candidates(DF_Entity *thread, DF_EntityList *candidates) internal DF_Unwind df_unwind_from_ctrl_unwind(Arena *arena, DI_Scope *di_scope, DF_Entity *process, CTRL_Unwind *base_unwind) { - Temp scratch = scratch_begin(&arena, 1); - DF_UnwindFrameList rich_frames_list = {0}; Architecture arch = df_architecture_from_entity(process); - for(U64 base_frame_idx = 0; base_frame_idx < base_unwind->frames.count; base_frame_idx += 1) + DF_Unwind result = {0}; + result.frames.concrete_frame_count = base_unwind->frames.count; + result.frames.total_frame_count = result.frames.concrete_frame_count; + result.frames.v = push_array(arena, DF_UnwindFrame, result.frames.concrete_frame_count); + for(U64 idx = 0; idx < result.frames.concrete_frame_count; idx += 1) { - CTRL_UnwindFrame *base_frame = &base_unwind->frames.v[base_frame_idx]; - U64 rip_vaddr = regs_rip_from_arch_block(arch, base_frame->regs); + CTRL_UnwindFrame *src = &base_unwind->frames.v[idx]; + DF_UnwindFrame *dst = &result.frames.v[idx]; + U64 rip_vaddr = regs_rip_from_arch_block(arch, src->regs); DF_Entity *module = df_module_from_process_vaddr(process, rip_vaddr); U64 rip_voff = df_voff_from_vaddr(module, rip_vaddr); DI_Key dbgi_key = df_dbgi_key_from_module(module); RDI_Parsed *rdi = di_rdi_from_key(di_scope, &dbgi_key, 0); RDI_Scope *scope = rdi_scope_from_voff(rdi, rip_voff); - // rjf: add rich frames for inlines - U64 inline_unwind_idx = 0; - for(RDI_Scope *s = scope; s->inline_site_idx != 0; s = rdi_element_from_name_idx(rdi, Scopes, s->parent_scope_idx)) + // rjf: fill concrete frame info + dst->regs = src->regs; + dst->rdi = rdi; + dst->procedure = rdi_element_from_name_idx(rdi, Procedures, scope->proc_idx); + + // rjf: push inline frames + for(RDI_Scope *s = scope; + s->inline_site_idx != 0; + s = rdi_element_from_name_idx(rdi, Scopes, s->parent_scope_idx)) { RDI_InlineSite *site = rdi_element_from_name_idx(rdi, InlineSites, s->inline_site_idx); - DF_UnwindFrameNode *n = push_array(scratch.arena, DF_UnwindFrameNode, 1); - SLLQueuePush(rich_frames_list.first, rich_frames_list.last, n); - rich_frames_list.count += 1; - n->v.regs = base_frame->regs; - n->v.rdi = rdi; - n->v.procedure = 0; - n->v.inline_site = site; - n->v.base_unwind_idx = base_frame_idx; - n->v.inline_unwind_idx = inline_unwind_idx; - inline_unwind_idx += 1; - } - - // rjf: add frame for concrete frame - DF_UnwindFrameNode *n = push_array(scratch.arena, DF_UnwindFrameNode, 1); - SLLQueuePush(rich_frames_list.first, rich_frames_list.last, n); - rich_frames_list.count += 1; - n->v.regs = base_frame->regs; - n->v.rdi = rdi; - n->v.procedure = rdi_element_from_name_idx(rdi, Procedures, scope->proc_idx); - n->v.inline_site = 0; - n->v.base_unwind_idx = base_frame_idx; - n->v.inline_unwind_idx = inline_unwind_idx; - inline_unwind_idx = 0; - } - DF_Unwind result = {0}; - { - result.frames.count = rich_frames_list.count; - result.frames.v = push_array(arena, DF_UnwindFrame, result.frames.count); - U64 idx = 0; - for(DF_UnwindFrameNode *n = rich_frames_list.first; n != 0; n = n->next, idx += 1) - { - MemoryCopyStruct(&result.frames.v[idx], &n->v); + DF_UnwindInlineFrame *inline_frame = push_array(arena, DF_UnwindInlineFrame, 1); + DLLPushFront(dst->first_inline_frame, dst->last_inline_frame, inline_frame); + inline_frame->inline_site = site; + dst->inline_frame_count += 1; + result.frames.inline_frame_count += 1; + result.frames.total_frame_count += 1; } } - scratch_end(scratch); return result; } -internal DF_UnwindFrame * -df_frame_from_unwind_idxs(DF_Unwind *unwind, U64 base_unwind_idx, U64 inline_unwind_idx) -{ - DF_UnwindFrame *f = 0; - for(U64 idx = 0; idx < unwind->frames.count; idx += 1) - { - if(unwind->frames.v[idx].base_unwind_idx == base_unwind_idx) - { - f = &unwind->frames.v[idx]; - if(unwind->frames.v[idx].inline_unwind_idx == inline_unwind_idx) - { - break; - } - } - } - return f; -} - //////////////////////////////// //~ rjf: Target Controls @@ -3870,7 +3834,7 @@ df_ctrl_run(DF_RunKind run, DF_Entity *run_thread, CTRL_RunFlags flags, CTRL_Tra // rjf: set control context to top unwind df_state->ctrl_ctx.unwind_count = 0; - df_state->ctrl_ctx.inline_unwind_count = 0; + df_state->ctrl_ctx.inline_depth = 0; scratch_end(scratch); } @@ -5731,7 +5695,7 @@ df_ctrl_ctx_apply_overrides(DF_CtrlCtx *ctx, DF_CtrlCtx *overrides) { ctx->thread = overrides->thread; ctx->unwind_count = overrides->unwind_count; - ctx->inline_unwind_count = overrides->inline_unwind_count; + ctx->inline_depth = overrides->inline_depth; } } @@ -6531,8 +6495,8 @@ df_push_cmd__root(DF_CmdParams *params, DF_CmdSpec *spec) if(params->vaddr != 0) { log_infof("vaddr: 0x%I64x\n", params->vaddr); } if(params->voff != 0) { log_infof("voff: 0x%I64x\n", params->voff); } if(params->index != 0) { log_infof("index: 0x%I64x\n", params->index); } - if(params->base_unwind_index != 0) { log_infof("base_unwind_index: 0x%I64x\n", params->base_unwind_index); } - if(params->inline_unwind_index != 0){ log_infof("inline_unwind_index: 0x%I64x\n", params->inline_unwind_index); } + if(params->unwind_index != 0) { log_infof("unwind_index: 0x%I64x\n", params->unwind_index); } + if(params->inline_depth != 0) { log_infof("inline_depth: 0x%I64x\n", params->inline_depth); } if(params->id != 0) { log_infof("id: 0x%I64x\n", params->id); } if(params->os_event != 0) { @@ -7646,17 +7610,23 @@ df_core_begin_frame(Arena *arena, DF_CmdList *cmds, F32 dt) DF_Entity *process = df_entity_ancestor_from_kind(thread, DF_EntityKind_Process); CTRL_Unwind base_unwind = df_query_cached_unwind_from_thread(thread); DF_Unwind rich_unwind = df_unwind_from_ctrl_unwind(scratch.arena, di_scope, process, &base_unwind); - DF_UnwindFrame *frame = df_frame_from_unwind_idxs(&rich_unwind, params.base_unwind_index, params.inline_unwind_index); - if(frame != 0) + if(params.unwind_index < rich_unwind.frames.concrete_frame_count) { - df_state->ctrl_ctx.unwind_count = frame->base_unwind_idx; - df_state->ctrl_ctx.inline_unwind_count = frame->inline_unwind_idx; + DF_UnwindFrame *frame = &rich_unwind.frames.v[params.unwind_index]; + df_state->ctrl_ctx.unwind_count = params.unwind_index; + df_state->ctrl_ctx.inline_depth = 0; + if(params.inline_depth < frame->inline_frame_count) + { + df_state->ctrl_ctx.inline_depth = params.inline_depth; + } } di_scope_close(di_scope); }break; case DF_CoreCmdKind_UpOneFrame: case DF_CoreCmdKind_DownOneFrame: { + // TODO(rjf) +#if 0 DF_CtrlCtx ctrl_ctx = df_ctrl_ctx(); DI_Scope *di_scope = di_scope_open(); DF_Entity *thread = df_entity_from_handle(ctrl_ctx.thread); @@ -7664,6 +7634,10 @@ df_core_begin_frame(Arena *arena, DF_CmdList *cmds, F32 dt) CTRL_Unwind base_unwind = df_query_cached_unwind_from_thread(thread); DF_Unwind rich_unwind = df_unwind_from_ctrl_unwind(scratch.arena, di_scope, process, &base_unwind); DF_UnwindFrame *current_frame = 0; + if(ctrl_ctx.unwind_count < rich_unwind.frames.concrete_frame_count) + { + current_frame = &rich_unwind.frames.v[ctrl_ctx.unwind_count]; + } for(U64 idx = 0; idx < rich_unwind.frames.count; idx += 1) { if(rich_unwind.frames.v[idx].base_unwind_idx == ctrl_ctx.unwind_count && @@ -7702,6 +7676,7 @@ df_core_begin_frame(Arena *arena, DF_CmdList *cmds, F32 dt) df_cmd_list_push(arena, cmds, &p, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_SelectUnwind)); } di_scope_close(di_scope); +#endif }break; case DF_CoreCmdKind_FreezeThread: case DF_CoreCmdKind_ThawThread: @@ -8999,7 +8974,7 @@ df_core_begin_frame(Arena *arena, DF_CmdList *cmds, F32 dt) df_interact_regs()->module = df_handle_from_entity(module); df_interact_regs()->process = df_handle_from_entity(process); df_interact_regs()->unwind_count = df_state->ctrl_ctx.unwind_count; - df_interact_regs()->inline_unwind_count = df_state->ctrl_ctx.inline_unwind_count; + df_interact_regs()->inline_depth = df_state->ctrl_ctx.inline_depth; } ProfEnd(); diff --git a/src/df/core/df_core.h b/src/df/core/df_core.h index 0c938483..0635ead5 100644 --- a/src/df/core/df_core.h +++ b/src/df/core/df_core.h @@ -77,7 +77,7 @@ struct DF_CtrlCtx { DF_Handle thread; U64 unwind_count; - U64 inline_unwind_count; + U64 inline_depth; }; //////////////////////////////// @@ -452,37 +452,32 @@ struct DF_EntityFuzzyItemArray //////////////////////////////// //~ rjf: Rich (Including Inline) Unwind Types +typedef struct DF_UnwindInlineFrame DF_UnwindInlineFrame; +struct DF_UnwindInlineFrame +{ + DF_UnwindInlineFrame *next; + DF_UnwindInlineFrame *prev; + RDI_InlineSite *inline_site; +}; + typedef struct DF_UnwindFrame DF_UnwindFrame; struct DF_UnwindFrame { + DF_UnwindInlineFrame *first_inline_frame; + DF_UnwindInlineFrame *last_inline_frame; + U64 inline_frame_count; void *regs; RDI_Parsed *rdi; RDI_Procedure *procedure; - RDI_InlineSite *inline_site; - U64 base_unwind_idx; - U64 inline_unwind_idx; -}; - -typedef struct DF_UnwindFrameNode DF_UnwindFrameNode; -struct DF_UnwindFrameNode -{ - DF_UnwindFrameNode *next; - DF_UnwindFrame v; -}; - -typedef struct DF_UnwindFrameList DF_UnwindFrameList; -struct DF_UnwindFrameList -{ - DF_UnwindFrameNode *first; - DF_UnwindFrameNode *last; - U64 count; }; typedef struct DF_UnwindFrameArray DF_UnwindFrameArray; struct DF_UnwindFrameArray { DF_UnwindFrame *v; - U64 count; + U64 concrete_frame_count; + U64 inline_frame_count; + U64 total_frame_count; }; typedef struct DF_Unwind DF_Unwind; @@ -598,7 +593,7 @@ struct DF_InteractRegs DF_Handle process; DF_Handle thread; U64 unwind_count; - U64 inline_unwind_count; + U64 inline_depth; DF_Handle window; DF_Handle panel; DF_Handle view; @@ -1609,7 +1604,6 @@ internal EVAL_String2NumMap *df_push_member_map_from_dbgi_key_voff(Arena *arena, internal B32 df_set_thread_rip(DF_Entity *thread, U64 vaddr); internal DF_Entity *df_module_from_thread_candidates(DF_Entity *thread, DF_EntityList *candidates); internal DF_Unwind df_unwind_from_ctrl_unwind(Arena *arena, DI_Scope *di_scope, DF_Entity *process, CTRL_Unwind *base_unwind); -internal DF_UnwindFrame *df_frame_from_unwind_idxs(DF_Unwind *unwind, U64 base_unwind_idx, U64 inline_unwind_idx); //////////////////////////////// //~ rjf: Target Controls diff --git a/src/df/core/df_core.mdesk b/src/df/core/df_core.mdesk index 9649d87f..f36f70d4 100644 --- a/src/df/core/df_core.mdesk +++ b/src/df/core/df_core.mdesk @@ -1,1870 +1,1870 @@ -// Copyright (c) 2024 Epic Games Tools -// Licensed under the MIT license (https://opensource.org/license/mit/) - -//////////////////////////////// -//~ rjf: Config Sources - -@table(string, name, load_cmd, write_cmd, apply_cmd) -DF_CfgSrcTable: -{ - {"user" User OpenUser WriteUserData ApplyUserData } - {"project" Project OpenProject WriteProjectData ApplyProjectData } - {"command_line" CommandLine Null Null Null } - {"transient" Transient Null Null Null } -} - -//////////////////////////////// -//~ rjf: Entity Kind Tables - -@table(name name_lower op_delete op_freeze op_edit op_rename op_enable op_cond op_dup lf_mut_user_cfg tr_mut_user_cfg lf_mut_prof_cfg tr_mut_prof_cfg lf_mut_halt lf_mut_dbg tr_mut_halt tr_mut_dbg name_is_code user_lifetime name_label icon_kind display_string) -DF_EntityKindTable: -{ - {Nil nil 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 "Label" Null "Nil" } - {Root root 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 "Label" Null "Root" } - {Machine machine 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 "Label" Machine "Machine" } - - //- rjf: filesystem modeling - {File file 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 "Label" FileOutline "File" } - {OverrideFileLink override_file_link 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 "Label" FileOutline "Override File Link" } - - //- rjf: auto view rules - {AutoViewRule auto_view_rule 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 "Label" Binoculars "Auto View Rule" } - - //- rjf: watch pins - {WatchPin watch_pin 1 0 0 1 0 0 1 0 0 0 0 0 0 0 0 1 1 "Expression" Pin "Watch Pin" } - - //- rjf: breakpoints - {Breakpoint breakpoint 1 0 0 1 1 1 1 0 0 1 0 1 0 0 0 0 1 "Label" CircleFilled "Breakpoint" } - {Condition condition 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 1 1 "Expression" CircleFilled "Condition" } - - //- rjf: targets - {Target target 1 0 1 1 1 0 1 0 0 1 0 0 0 0 0 0 1 "Label" Target "Target" } - {Executable executable 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 "Executable" Null "Executable" } - {Arguments arguments 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 "Arguments" Null "Arguments" } - {ExecutionPath execution_path 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 "Execution Path" Null "Execution Path" } - {EntryPointName entry_point_name 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 1 "Symbol Name" Null "Entry Point Name" } - - //- rjf: recent projects - {RecentProject recent_project 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 "Path" Briefcase "Recent Project" } - - //- rjf: src -> dst mapping - {Source source 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 "Path" Null "Source" } - {Dest dest 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 "Path" Null "Destination" } - - //- rjf: control system entities - {Process process 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 "Label" Threads "Process" } - {Thread thread 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 "Label" Thread "Thread" } - {Module module 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 "Label" Module "Module" } - {PendingThreadName pending_thread_name 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 "Label" Threads "Pending Thread Name" } - {DebugInfoPath debug_info_path 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 "Label" Module "Debug Info Path" } - - //- rjf: parser task entities - {ConversionTask conversion_task 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 "Label" Null "Conversion Task" } - {ConversionFail conversion_fail 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 "Label" Null "Conversion Failure" } - - //- rjf: history - {EndedProcess ended_process 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 "Label" Null "EndedProcess" } -} - -//////////////////////////////// -//~ rjf: Built-In Command Tables - -@table(name, name_lower, c_type) -DF_CmdParamSlotTable: -{ - {Window window `DF_Handle`} - {Panel panel `DF_Handle`} - {DestPanel dest_panel `DF_Handle`} - {PrevView prev_view `DF_Handle`} - {View view `DF_Handle`} - {Entity entity `DF_Handle`} - {EntityList entity_list `DF_HandleList`} - {String string `String8`} - {FilePath file_path `String8`} - {TextPoint text_point `TxtPt`} - {CmdSpec cmd_spec `struct DF_CmdSpec *`} - {ViewSpec view_spec `struct DF_ViewSpec *`} - {CfgNode cfg_node `struct DF_CfgNode *`} - {OSEvent os_event `struct OS_Event *`} - {VirtualAddr vaddr `U64`} - {VirtualOff voff `U64`} - {Index index `U64`} - {ID id `U64`} - {PreferDisassembly prefer_dasm `B32`} - {ForceConfirm force_confirm `B32`} - {Dir2 dir2 `Dir2`} - {BaseUnwindIndex base_unwind_index `U64`} - {InlineUnwindIndex inline_unwind_index `U64`} -} - -@table(name lister_omit q_slot q_ent_kind q_allow_files q_allow_folders q_keep_oi q_select_oi q_is_code q_required canonical_icon string display_name desc search_tags ) -// / | | \___ ______________________________________________/ | | | | | -// / | | \ / | | | | | -DF_CoreCmdTable:// | | | | | | | | | -{ - {Null 1 Null Nil 0 0 0 0 0 0 Null "" "" "" "" } - - //- rjf: exiting - {Exit 0 Null Nil 0 0 0 0 0 0 X "exit" "Exit" "Exits the debugger." "quit,close,abort" } - - //- rjf: command runner - {RunCommand 0 CmdSpec Nil 0 0 0 0 0 0 Null "run_command" "Run Command" "Runs a command from the command palette." "help,cmd" } - - //- rjf: notifications - {Error 1 Null Nil 0 0 0 0 0 0 Null "error" "Error" "Notifies of an error." "" } - - //- rjf: os event passthrough - {OSEvent 1 Null Nil 0 0 0 0 0 0 Null "os_event" "OS Event" "" "" } - - //- rjf: low-level target control operations - {LaunchAndRun 0 EntityList Target 0 0 0 0 0 1 Play "launch_and_run" "Launch and Run" "Starts debugging a new instance of a target, then runs." "launch,start,run,target" } - {LaunchAndInit 0 EntityList Target 0 0 0 0 0 1 PlayStepForward "launch_and_init" "Launch and Initialize" "Starts debugging a new instance of a target, then stops at the program's entry point." "launch,start,entry,point" } - {Kill 0 EntityList Process 0 0 0 0 0 1 Stop "kill" "Kill" "Kills the specified existing debugged process(es)." "stop,kill" } - {KillAll 0 Null Nil 0 0 0 0 0 0 Stop "kill_all" "Kill All" "Kills all debugged child processes." "stop,kill,all" } - {Detach 0 EntityList Process 0 0 0 0 0 1 Null "detach" "Detach" "Detaches the specified debugged process." "detach" } - {Continue 0 Null Nil 0 0 0 0 0 0 Play "continue" "Continue" "Continues all halted threads." "" } - {StepIntoInst 0 Null Nil 0 0 0 0 0 0 StepInto "step_into_inst" "Step Into (Assembly)" "Performs a step that goes into calls, at the instruction level." "single,step,thread" } - {StepOverInst 0 Null Nil 0 0 0 0 0 0 StepOver "step_over_inst" "Step Over (Assembly)" "Performs a step that skips calls, at the instruction level." "single,step,thread" } - {StepIntoLine 0 Null Nil 0 0 0 0 0 0 StepInto "step_into_line" "Step Into (Line)" "Performs a step that goes into calls, at the source code line level." "step,thread" } - {StepOverLine 0 Null Nil 0 0 0 0 0 0 StepOver "step_over_line" "Step Over (Line)" "Performs a step that skips calls, at the source code line level." "step,thread" } - {StepOut 0 Null Nil 0 0 0 0 0 0 StepOut "step_out" "Step Out" "Runs to the end of the current function and exits it." "" } - {Halt 0 Null Nil 0 0 0 0 0 0 Pause "halt" "Halt" "Halts all running processes." "pause" } - {SoftHaltRefresh 0 Null Nil 0 0 0 0 0 0 Refresh "soft_halt_refresh" "Soft Halt Refresh" "Interrupts all running processes to collect data, and then resumes them." "" } - {SetThreadIP 1 VirtualAddr Nil 0 0 0 0 1 1 Null "set_thread_ip" "Set Thread IP" "Sets the passed thread's instruction pointer at the passed address." "" } - - //- rjf: high-level composite target control operations - {RunToLine 1 Null Nil 0 0 0 0 0 0 Play "run_to_line" "Run To Line" "Runs until a particular source line is hit." "" } - {RunToAddress 0 VirtualAddr Nil 0 0 0 0 1 1 PlayStepForward "run_to_address" "Run To Address" "Runs until a particular address is hit." "" } - {Run 0 Null Nil 0 0 0 0 0 0 Play "run" "Run" "Runs all targets after starting them if they have not been started yet." "play" } - {Restart 0 Null Nil 0 0 0 0 0 0 Redo "restart" "Restart" "Kills all running processes, then restarts the targets which were used to launch all current processes (if any)." "restart,retry" } - {StepInto 0 Null Nil 0 0 0 0 0 0 StepInto "step_into" "Step Into" "Steps once, possibly into function calls, for either line or instructions." "" } - {StepOver 0 Null Nil 0 0 0 0 0 0 StepOver "step_over" "Step Over" "Steps once, always over function calls, for either line or instructions." "" } - {RunToCursor 0 Null Nil 0 0 0 0 0 0 Play "run_to_cursor" "Run To Cursor" "Runs the selected thread to the current cursor." "" } - {SetNextStatement 0 Null Nil 0 0 0 0 0 0 RightArrow "set_next_statement" "Set Next Statement" "Sets the selected thread's instruction pointer to the cursor's position." "" } - - //- rjf: debug control context management operations - {SelectThread 0 Entity Thread 0 0 0 0 0 1 Null "select_thread" "Select Thread" "Selects a thread." "" } - {SelectThreadWindow 0 Entity Thread 0 0 0 0 0 1 Null "select_thread_window" "Select Thread On Window" "Selects a thread for the active window, overriding the global selected thread." "" } - {SelectThreadView 0 Entity Thread 0 0 0 0 0 1 Null "select_thread_view" "Select Thread On View" "Selects a thread for the active view, overriding the global and per-window selected threads." "" } - {SelectUnwind 1 Null Nil 0 0 0 0 0 0 Null "select_unwind" "Select Unwind" "Selects an unwind frame number for the selected thread." "" } - {UpOneFrame 0 Null Nil 0 0 0 0 0 0 UpArrow "up_one_frame" "Up One Frame" "Selects the call stack frame above the currently selected." "" } - {DownOneFrame 0 Null Nil 0 0 0 0 0 0 DownArrow "down_one_frame" "Down One Frame" "Selects the call stack frame below the currently selected." "callstack,unwind" } - {FreezeThread 0 Entity Thread 0 0 0 0 0 1 Locked "freeze_thread" "Freeze Thread" "Freezes the passed thread." "callstack,unwind" } - {ThawThread 0 Entity Thread 0 0 0 0 0 1 Unlocked "thaw_thread" "Thaw Thread" "Thaws the passed thread." "" } - {FreezeProcess 0 Entity Process 0 0 0 0 0 1 Locked "freeze_process" "Freeze Process" "Freezes the passed process." "" } - {ThawProcess 0 Entity Process 0 0 0 0 0 1 Unlocked "thaw_process" "Thaw Process" "Thaws the passed process." "" } - {FreezeMachine 1 Entity Machine 0 0 0 0 0 1 Locked "freeze_machine" "Freeze Machine" "Freezes the passed machine." "" } - {ThawMachine 1 Entity Machine 0 0 0 0 0 1 Unlocked "thaw_machine" "Thaw Machine" "Thaws the passed machine." "" } - {FreezeLocalMachine 0 Null Nil 0 0 0 0 0 0 Machine "freeze_local_machine" "Freeze Local Machine" "Freezes the local machine." "" } - {ThawLocalMachine 0 Null Nil 0 0 0 0 0 0 Machine "thaw_local_machine" "Thaw Local Machine" "Thaws the local machine." "" } - - //- rjf: font sizes - {IncUIFontScale 0 Null Nil 0 0 0 0 0 0 Null "inc_ui_font_scale" "Increase UI Font Scale" "Increases the font size used for UI." "" } - {DecUIFontScale 0 Null Nil 0 0 0 0 0 0 Null "dec_ui_font_scale" "Decrease UI Font Scale" "Decreases the font size used for UI." "" } - {IncCodeFontScale 0 Null Nil 0 0 0 0 0 0 Null "inc_code_font_scale" "Increase Code Font Scale" "Increases the font size used for code." "" } - {DecCodeFontScale 0 Null Nil 0 0 0 0 0 0 Null "dec_code_font_scale" "Decrease Code Font Scale" "Decreases the font size used for code." "" } - - //- rjf: windows - {OpenWindow 0 Null Nil 0 0 0 0 0 0 Window "open_window" "Open New Window" "Opens a new window." "" } - {CloseWindow 0 Null Nil 0 0 0 0 0 0 Window "close_window" "Close Window" "Closes an opened window." "" } - {ToggleFullscreen 0 Null Nil 0 0 0 0 0 0 Window "toggle_fullscreen" "Toggle Fullscreen" "Toggles fullscreen view on the active window." "" } - - //- rjf: confirmations - {ConfirmAccept 1 Null Nil 0 0 0 0 0 0 Null "confirm_accept" "Confirm Accept" "Accepts the active confirmation prompt." "" } - {ConfirmCancel 1 Null Nil 0 0 0 0 0 0 Null "confirm_cancel" "Confirm Cancel" "Cancels the active confirmation prompt." "" } - - //- rjf: panel splitting - {ResetToDefaultPanels 0 Null Nil 0 0 0 0 0 0 Window "reset_to_default_panels" "Reset To Default Panel Layout" "Resets the window to the default panel layout." "panel" } - {ResetToCompactPanels 0 Null Nil 0 0 0 0 0 0 Window "reset_to_compact_panels" "Reset To Compact Panel Layout" "Resets the window to the compact panel layout." "panel" } - {NewPanelLeft 0 Null Nil 0 0 0 0 0 0 XSplit "new_panel_left" "Split Panel Left" "Creates a new panel to the left of the active panel." "panel" } - {NewPanelUp 0 Null Nil 0 0 0 0 0 0 YSplit "new_panel_up" "Split Panel Up" "Creates a new panel at the top of the active panel." "panel" } - {NewPanelRight 0 Null Nil 0 0 0 0 0 0 XSplit "new_panel_right" "Split Panel Right" "Creates a new panel to the right of the active panel." "panel" } - {NewPanelDown 0 Null Nil 0 0 0 0 0 0 YSplit "new_panel_down" "Split Panel Down" "Creates a new panel at the bottom of the active panel." "panel" } - {SplitPanel 1 Null Nil 0 0 0 0 0 0 Null "split_panel" "Split Panel" "Creates a new panel in a given direction, and moves a tab to it, if specified." "" } - - //- rjf: panel rotation - {RotatePanelColumns 0 Null Nil 0 0 0 0 0 0 Null "rotate_panel_columns" "Rotate Panel Columns" "Rotates all panels at the closest column level of the panel hierarchy." "" } - - //- rjf: focused panel changing - {NextPanel 0 Null Nil 0 0 0 0 0 0 RightArrow "next_panel" "Focus Next Panel" "Cycles the active panel forward." "" } - {PrevPanel 0 Null Nil 0 0 0 0 0 0 LeftArrow "prev_panel" "Focus Previous Panel" "Cycles the active panel backwards." "" } - {FocusPanel 1 Null Nil 0 0 0 0 0 0 Null "focus_panel" "Focus Panel" "Focuses a new panel." "" } - {FocusPanelRight 0 Null Nil 0 0 0 0 0 0 RightArrow "focus_panel_right" "Focus Panel Right" "Focuses a panel rightward of the currently focused panel." "" } - {FocusPanelLeft 0 Null Nil 0 0 0 0 0 0 LeftArrow "focus_panel_left" "Focus Panel Left" "Focuses a panel leftward of the currently focused panel." "" } - {FocusPanelUp 0 Null Nil 0 0 0 0 0 0 UpArrow "focus_panel_up" "Focus Panel Up" "Focuses a panel upward of the currently focused panel." "" } - {FocusPanelDown 0 Null Nil 0 0 0 0 0 0 DownArrow "focus_panel_down" "Focus Panel Down" "Focuses a panel downward of the currently focused panel." "" } - - //- rjf: undo/redo - {Undo 1 Null Nil 0 0 0 0 0 0 Undo "undo" "Undo" "Undoes the previous action." "" } - {Redo 1 Null Nil 0 0 0 0 0 0 Redo "redo" "Redo" "Redoes the first previously undone action." "" } - - //- rjf: focus history - {GoBack 1 Null Nil 0 0 0 0 0 0 LeftArrow "go_back" "Go Back" "Returns to the previously selected panel and tab in recorded history." "" } - {GoForward 1 Null Nil 0 0 0 0 0 0 RightArrow "go_forward" "Go Forward" "Returns to the next selected panel and tab in recorded history." "" } - - //- rjf: panel removal - {ClosePanel 0 Null Nil 0 0 0 0 0 0 ClosePanel "close_panel" "Close Panel" "Closes the currently active panel." "" } - - //- rjf: panel tab - {NextTab 0 Null Nil 0 0 0 0 0 0 RightArrow "next_tab" "Focus Next Tab" "Focuses the next tab on the active panel." "" } - {PrevTab 0 Null Nil 0 0 0 0 0 0 LeftArrow "prev_tab" "Focus Previous Tab" "Focuses the previous tab on the active panel." "" } - {MoveTabRight 0 Null Nil 0 0 0 0 0 0 RightArrow "move_tab_right" "Move Tab Right" "Moves the selected tab right one slot." "" } - {MoveTabLeft 0 Null Nil 0 0 0 0 0 0 LeftArrow "move_tab_left" "Move Tab Left" "Moves the selected tab left one slot." "" } - {OpenTab 1 Null Nil 0 0 0 0 0 0 Null "open_tab" "Open Tab" "Opens a new tab with the parameterized view specification." "" } - {CloseTab 0 Null Nil 0 0 0 0 0 0 X "close_tab" "Close Tab" "Closes the currently opened tab." "" } - {MoveTab 1 Null Nil 0 0 0 0 0 0 Null "move_tab" "Move Tab" "Moves a tab to a new panel." "" } - {TabBarTop 0 Null Nil 0 0 0 0 0 0 UpArrow "tab_bar_top" "Anchor Tab Bar To Top" "Anchors a panel's tab bar to the top of the panel." "" } - {TabBarBottom 0 Null Nil 0 0 0 0 0 0 DownArrow "tab_bar_bottom" "Anchor Tab Bar To Bottom" "Anchors a panel's tab bar to the bottom of the panel." "" } - - //- rjf: files - {SetCurrentPath 1 Null Nil 0 0 0 0 0 0 FileOutline "set_current_path" "Set Current Path" "Sets the debugger's current path, which is used as a starting point when browsing for files." "" } - {Open 0 FilePath Nil 1 0 0 0 0 1 FileOutline "open" "Open" "Opens a file." "code,source,file" } - {Switch 0 Entity File 0 0 0 0 0 1 FileOutline "switch" "Switch" "Switches to a loaded file." "code,source,file" } - {SwitchToPartnerFile 0 Null Nil 0 0 0 0 0 0 FileOutline "switch_to_partner_file" "Switch To Partner File" "Switches to the focused file's partner; or from header to implementation or vice versa." "code,source,file" } - - //- rjf: source <-> disasm - {GoToDisassembly 0 Null Nil 0 0 0 0 0 0 Glasses "go_to_disassembly" "Go To Disassembly" "Goes to the disassembly, if any, for a given source code line." "code,source,disassembly,disasm" } - {GoToSource 0 Null Nil 0 0 0 0 0 0 FileOutline "go_to_source" "Go To Source" "Goes to the source code, if any, for a given disassembly line." "code,source,disassembly,disasm" } - - //- rjf: override file links - {SetFileOverrideLinkSrc 1 Null Nil 0 0 0 0 0 0 Null "set_file_override_link_src" "Set File Override Link Source" "Sets the source path for an override file link." "" } - {SetFileOverrideLinkDst 1 Null Nil 0 0 0 0 0 0 Null "set_file_override_link_dst" "Set File Override Link Destination" "Sets the destination path for an override file link." "" } - {SetFileReplacementPath 1 Null Nil 0 0 0 0 0 0 Null "set_file_replacement_path" "Set File Replacement Path" "Sets the path which should be used as the replacement for the passed file." "" } - - //- rjf: auto view rules - {SetAutoViewRuleType 1 Null Nil 0 0 0 0 0 0 Null "set_auto_view_rule_type" "Set Auto View Rule Type" "Sets the type for an auto view rule." "" } - {SetAutoViewRuleViewRule 1 Null Nil 0 0 0 0 0 0 Null "set_auto_view_rule_view_rule""Set Auto View Rule View Rule" "Sets the view rule string for an auto view rule." "" } - - //- rjf: setting config paths - {OpenUser 0 FilePath Nil 1 0 0 0 0 1 Person "open_user" "Open User" "Opens a user file path, immediately loading it, and begins autosaving to it." "load,user,project,layout" } - {OpenProject 0 FilePath Nil 1 0 0 0 0 1 Briefcase "open_project" "Open Project" "Opens a project file path, immediately loading it, and begins autosaving to it." "project,project,session" } - {OpenRecentProject 0 Entity RecentProject 0 0 0 0 0 1 Briefcase "open_recent_project" "Open Recent Project" "Opens a recently used project file." "project,project,session" } - - //- rjf: loading/applying stateful config changes - {ApplyUserData 1 Null Nil 0 0 0 0 0 0 Null "apply_user_data" "Apply User Data" "Applies user data from the active user file." "" } - {ApplyProjectData 1 Null Nil 0 0 0 0 0 0 Null "apply_project_data" "Apply Project Data" "Applies project data from the active project file." "" } - - //- rjf: writing config changes - {WriteUserData 1 Null Nil 0 0 0 0 0 0 Null "write_user_data" "Write User Data" "Writes user data to the active user file." "" } - {WriteProjectData 1 Null Nil 0 0 0 0 0 0 Null "write_project_data" "Write Project Data" "Writes project data to the active project file." "" } - - //- rjf: meta controls - {Edit 0 Null Nil 0 0 0 0 0 0 Pencil "edit" "Edit" "Edits the current selection." "" } - {Accept 0 Null Nil 0 0 0 0 0 0 CheckFilled "accept" "Accept" "Accepts current changes, or answers prompts in the affirmative." "" } - {Cancel 0 Null Nil 0 0 0 0 0 0 X "cancel" "Cancel" "Rejects current changes, exits temporary menus, or answers prompts in the negative." "" } - - //- rjf: directional movement & text controls - {MoveLeft 0 Null Nil 0 0 0 0 0 0 Null "move_left" "Move Left" "Moves the cursor or selection left." "" } - {MoveRight 0 Null Nil 0 0 0 0 0 0 Null "move_right" "Move Right" "Moves the cursor or selection right." "" } - {MoveUp 0 Null Nil 0 0 0 0 0 0 Null "move_up" "Move Up" "Moves the cursor or selection up." "" } - {MoveDown 0 Null Nil 0 0 0 0 0 0 Null "move_down" "Move Down" "Moves the cursor or selection down." "" } - {MoveLeftSelect 0 Null Nil 0 0 0 0 0 0 Null "move_left_select" "Move Left Select" "Moves the cursor or selection left, while selecting." "" } - {MoveRightSelect 0 Null Nil 0 0 0 0 0 0 Null "move_right_select" "Move Right Select" "Moves the cursor or selection right, while selecting." "" } - {MoveUpSelect 0 Null Nil 0 0 0 0 0 0 Null "move_up_select" "Move Up Select" "Moves the cursor or selection up, while selecting." "" } - {MoveDownSelect 0 Null Nil 0 0 0 0 0 0 Null "move_down_select" "Move Down Select" "Moves the cursor or selection down, while selecting." "" } - {MoveLeftChunk 0 Null Nil 0 0 0 0 0 0 Null "move_left_chunk" "Move Left Select" "Moves the cursor or selection left one chunk." "" } - {MoveRightChunk 0 Null Nil 0 0 0 0 0 0 Null "move_right_chunk" "Move Right Select" "Moves the cursor or selection right one chunk." "" } - {MoveUpChunk 0 Null Nil 0 0 0 0 0 0 Null "move_up_chunk" "Move Up Chunk" "Moves the cursor or selection up one chunk." "" } - {MoveDownChunk 0 Null Nil 0 0 0 0 0 0 Null "move_down_chunk" "Move Down Chunk" "Moves the cursor or selection down one chunk." "" } - {MoveUpPage 0 Null Nil 0 0 0 0 0 0 Null "move_up_page" "Move Up Page" "Moves the cursor or selection up one page." "" } - {MoveDownPage 0 Null Nil 0 0 0 0 0 0 Null "move_down_page" "Move Down Page" "Moves the cursor or selection down one page." "" } - {MoveUpWhole 0 Null Nil 0 0 0 0 0 0 Null "move_up_whole" "Move Up Whole" "Moves the cursor or selection to the beginning of the relevant content." "" } - {MoveDownWhole 0 Null Nil 0 0 0 0 0 0 Null "move_down_whole" "Move Down Whole" "Moves the cursor or selection to the end of the relevant content." "" } - {MoveLeftChunkSelect 0 Null Nil 0 0 0 0 0 0 Null "move_left_chunk_select" "Move Left Chunk Select" "Moves the cursor or selection left one chunk." "" } - {MoveRightChunkSelect 0 Null Nil 0 0 0 0 0 0 Null "move_right_chunk_select" "Move Right Chunk Select" "Moves the cursor or selection right one chunk." "" } - {MoveUpChunkSelect 0 Null Nil 0 0 0 0 0 0 Null "move_up_chunk_select" "Move Up Chunk Select" "Moves the cursor or selection up one chunk." "" } - {MoveDownChunkSelect 0 Null Nil 0 0 0 0 0 0 Null "move_down_chunk_select" "Move Down Chunk Select" "Moves the cursor or selection down one chunk." "" } - {MoveUpPageSelect 0 Null Nil 0 0 0 0 0 0 Null "move_up_page_select" "Move Up Page Select" "Moves the cursor or selection up one page, while selecting." "" } - {MoveDownPageSelect 0 Null Nil 0 0 0 0 0 0 Null "move_down_page_select" "Move Down Page Select" "Moves the cursor or selection down one page, while selecting." "" } - {MoveUpWholeSelect 0 Null Nil 0 0 0 0 0 0 Null "move_up_whole_select" "Move Up Whole Select" "Moves the cursor or selection to the beginning of the relevant content, while selecting." "" } - {MoveDownWholeSelect 0 Null Nil 0 0 0 0 0 0 Null "move_down_whole_select" "Move Down Whole Select" "Moves the cursor or selection to the end of the relevant content, while selecting." "" } - {MoveUpReorder 0 Null Nil 0 0 0 0 0 0 Null "move_up_reorder" "Move Up Reorder" "Moves the cursor or selection up, while swapping the currently selected element with that upward." "" } - {MoveDownReorder 0 Null Nil 0 0 0 0 0 0 Null "move_down_reorder" "Move Down Reorder" "Moves the cursor or selection down, while swapping the currently selected element with that downward." "" } - {MoveHome 0 Null Nil 0 0 0 0 0 0 Null "move_home" "Move Home" "Moves the cursor to the beginning of the line." "" } - {MoveEnd 0 Null Nil 0 0 0 0 0 0 Null "move_end" "Move End" "Moves the cursor to the end of the line." "" } - {MoveHomeSelect 0 Null Nil 0 0 0 0 0 0 Null "move_home_select" "Move Home Select" "Moves the cursor to the beginning of the line, while selecting." "" } - {MoveEndSelect 0 Null Nil 0 0 0 0 0 0 Null "move_end_select" "Move End Select" "Moves the cursor to the end of the line, while selecting." "" } - {SelectAll 0 Null Nil 0 0 0 0 0 0 Null "select_all" "Select All" "Selects everything possible." "" } - {DeleteSingle 0 Null Nil 0 0 0 0 0 0 Null "delete_single" "Delete Single" "Deletes a single element to the right of the cursor, or the active selection." "" } - {DeleteChunk 0 Null Nil 0 0 0 0 0 0 Null "delete_chunk" "Delete Chunk" "Deletes a chunk to the right of the cursor, or the active selection." "" } - {BackspaceSingle 0 Null Nil 0 0 0 0 0 0 Null "backspace_single" "Backspace Single" "Deletes a single element to the left of the cursor, or the active selection." "" } - {BackspaceChunk 0 Null Nil 0 0 0 0 0 0 Null "backspace_chunk" "Backspace Chunk" "Deletes a chunk to the left of the cursor, or the active selection." "" } - {Copy 0 Null Nil 0 0 0 0 0 0 Clipboard "copy" "Copy" "Copies the active selection to the clipboard." "" } - {Cut 0 Null Nil 0 0 0 0 0 0 Clipboard "cut" "Cut" "Copies the active selection to the clipboard, then deletes it." "" } - {Paste 0 Null Nil 0 0 0 0 0 0 Clipboard "paste" "Paste" "Pastes the current contents of the clipboard." "" } - {InsertText 1 Null Nil 0 0 0 0 0 0 Null "insert_text" "Insert Text" "Inserts the text that was used to cause this command." "" } - - //- rjf: code navigation - {GoToLine 0 TextPoint Nil 0 0 0 0 1 1 Null "goto_line" "Go To Line" "Jumps to a line number in the current code file." "" } - {GoToAddress 0 VirtualAddr Nil 0 0 0 0 1 1 Null "goto_address" "Go To Address" "Jumps to an address in the current memory or disassembly view." "" } - {CenterCursor 0 Null Nil 0 0 0 0 0 0 Null "center_cursor" "Center Cursor" "Snaps the current code view to center the cursor." "" } - {ContainCursor 0 Null Nil 0 0 0 0 0 0 Null "contain_cursor" "Contain Cursor" "Snaps the current code view to contain the cursor." "" } - {FindTextForward 0 String Nil 0 0 1 1 1 1 Find "find_text_forward" "Find Text (Forward)" "Searches the current code file forward (from the cursor) for a string." "" } - {FindTextBackward 0 String Nil 0 0 1 1 1 1 Find "find_text_backward" "Find Text (Backwards)" "Searches the current code file backwards (from the cursor) for a string." "" } - {FindNext 0 Null Nil 0 0 1 0 0 0 Find "find_next" "Find Next" "Searches the current code file forward (from the cursor) for the last searched string." "" } - {FindPrev 0 Null Nil 0 0 1 0 0 0 Find "find_prev" "Find Previous" "Searches the current code file backwards (from the cursor) for the last searched string." "" } - - //- rjf: thread finding - {FindThread 0 Entity Thread 0 0 0 0 0 1 Find "find_thread" "Find Thread" "Jumps to the passed thread in either source code, disassembly, or both if they're already open." "" } - {FindSelectedThread 0 Null Nil 0 0 0 0 0 0 Find "find_selected_thread" "Find Selected Thread" "Jumps to the selected thread in either source code, disassembly, or both if they're already open." "" } - - //- rjf: name finding - {GoToName 0 String Nil 0 0 0 0 1 1 Null "goto_name" "Go To Name" "Searches for the passed string as a file, a symbol in debug info, and more, then jumps to it if possible." "" } - {GoToNameAtCursor 0 Null Nil 0 0 0 0 0 0 Null "goto_name_at_cursor" "Go To Name At Cursor" "Searches for the text at the cursor as a file, a symbol in debug info, and more, then jumps to it if possible." "" } - - //- rjf: watch expressions - {ToggleWatchExpression 0 Null Nil 0 0 0 0 0 0 Binoculars "toggle_watch_expr" "Toggle Watch Expression" "Adds or removes an expression to an opened watch view." "" } - {ToggleWatchExpressionAtCursor 0 Null Nil 0 0 0 0 0 0 Binoculars "toggle_watch_expr_at_cursor" "Toggle Watch Expression At Cursor" "Adds or removes the expression that the cursor or selection is currently over to an opened watch view." "" } - {ToggleWatchExpressionAtMouse 0 Null Nil 0 0 0 0 0 0 Binoculars "toggle_watch_expr_at_mouse" "Toggle Watch Expression At Mouse" "Adds or removes the expression that the mouse is currently over to an opened watch view." "" } - - //- rjf: memory view parameterization - {SetColumns 0 Index Nil 0 0 0 0 1 1 Thumbnails "set_columns" "Set Columns" "Sets the number of columns for a memory view." "" } - - //- rjf: disassembly view parameterization - {ToggleAddressVisibility 0 Null Nil 0 0 0 0 0 0 Thumbnails "toggle_address_visibility" "Toggle Address Visibility" "Toggles the visibility of addresses in a disassembly view." "" } - {ToggleCodeBytesVisibility 0 Null Nil 0 0 0 0 0 0 Thumbnails "toggle_code_bytes_visibility""Toggle Code Bytes Visibility" "Toggles the visibility of machine code bytes in a disassembly view." "" } - - //- rjf: general entity operations - {EnableEntity 1 Null Nil 0 0 0 0 0 0 Null "enable_entity" "Enable Entity" "Enables an entity." "" } - {DisableEntity 1 Null Nil 0 0 0 0 0 0 Null "disable_entity" "Disable Entity" "Disables an entity." "" } - {FreezeEntity 1 Null Nil 0 0 0 0 0 0 Null "freeze_entity" "Freeze Entity" "Freezes an entity." "" } - {ThawEntity 1 Null Nil 0 0 0 0 0 0 Null "thaw_entity" "Thaw Entity" "Thaws an entity." "" } - {RemoveEntity 1 Null Nil 0 0 0 0 0 0 Null "remove_entity" "Remove Entity" "Removes an entity." "" } - {NameEntity 1 Null Nil 0 0 0 0 0 0 Null "name_entity" "Name Entity" "Equips an entity with a name." "" } - {EditEntity 1 Null Nil 0 0 0 0 0 0 Null "edit_entity" "Edit Entity" "Opens the editor for an entity." "" } - {DuplicateEntity 1 Null Nil 0 0 0 0 0 0 Null "duplicate_entity" "Duplicate Entity" "Duplicates an entity." "" } - - //- rjf: breakpoints - {TextBreakpoint 1 FilePath Nil 0 0 0 0 0 0 CircleFilled "text_breakpoint" "Text Breakpoint" "Places or removes a breakpoint on the specified line of source code." "" } - {AddressBreakpoint 0 VirtualAddr Nil 0 0 0 0 1 1 CircleFilled "address_breakpoint" "Address Breakpoint" "Places or removes a breakpoint on the specified address." "" } - {FunctionBreakpoint 0 String Nil 0 0 0 0 1 1 CircleFilled "function_breakpoint" "Function Breakpoint" "Places or removes a breakpoint on the first address(es) of the specified function." "" } - {ToggleBreakpointAtCursor 0 Null Nil 0 0 0 0 0 0 CircleFilled "toggle_breakpoint_cursor" "Toggle Breakpoint At Cursor" "Places or removes a breakpoint on the line on which the active cursor sits." "" } - {RemoveBreakpoint 0 Entity Breakpoint 0 0 0 0 0 1 Trash "remove_breakpoint" "Remove Breakpoint" "Removes an existing breakpoint." "" } - {EnableBreakpoint 0 Entity Breakpoint 0 0 0 0 0 1 CheckFilled "enable_breakpoint" "Enable Breakpoint" "Enables a breakpoint." "" } - {DisableBreakpoint 0 Entity Breakpoint 0 0 0 0 0 1 CheckHollow "disable_breakpoint" "Disable Breakpoint" "Disables a breakpoint." "" } - - //- rjf: watches - {ToggleWatchPin 1 Null Nil 0 0 0 0 0 0 Binoculars "toggle_watch_pin" "Toggle Watch Pin" "Places or removes a watch pin on a textual location on a particular entity." "" } - {ToggleWatchPinAtCursor 0 String Nil 0 0 0 0 1 1 Binoculars "toggle_watch_pin_at_cursor" "Toggle Watch Pin At Cursor" "Places or removes a watch pin at the cursor on the currently active file." "" } - - //- rjf: targets - {AddTarget 0 FilePath Nil 1 0 0 0 0 1 Target "add_target" "Add Target" "Adds a new target." "application,executable,debug" } - {RemoveTarget 0 Entity Target 0 0 0 0 0 1 Trash "remove_target" "Remove Target" "Removes an existing target." "delete,remove,target" } - {EditTarget 0 Entity Target 0 0 0 0 0 1 Pencil "edit_target" "Edit Target" "Edits an existing target." "" } - {SelectTarget 0 Entity Target 0 0 0 0 0 1 Target "select_target" "Select Target" "Selects a target." "" } - {EnableTarget 0 Entity Target 0 0 0 0 0 1 CheckFilled "enable_target" "Enable Target" "Enables a target, in addition to all targets currently enabled." "" } - {DisableTarget 0 Entity Target 0 0 0 0 0 1 CheckHollow "disable_target" "Disable Target" "Disables a target." "" } - - //- rjf: ended processes - {RetryEndedProcess 1 Entity Process 0 0 0 0 0 0 Null "retry_ended_process" "Retry Ended Process" "Launches a new process with the same options as the passed ended process." "" } - - //- rjf: attaching - {Attach 0 ID Nil 0 0 0 0 0 1 Null "attach" "Attach" "Attaches to a process that is already running on the local machine." "" } - {RegisterAsJITDebugger 0 Null Nil 0 0 0 0 0 0 Null "register_as_jit_debugger" "Register As Just-In-Time (JIT) Debugger" "Registers the RAD debugger as the just-in-time (JIT) debugger used by the operating system." "" } - - //- rjf: catchall general entity activation paths (drag/drop, clicking) - {EntityRefFastPath 1 Null Nil 0 0 0 0 0 0 Null "entity_ref_fast_path" "Entity Reference Fast Path" "Activates the default behavior when clicking an entity reference." "" } - {SpawnEntityView 1 Null Nil 0 0 0 0 0 0 Null "spawn_entity_view" "Spawn Entity View" "Spawns a new view, given an entity and other parameterizations." "" } - {FindCodeLocation 1 FilePath Nil 0 0 0 0 0 1 FileOutline "find_code_location" "Find Code Location" "Finds a specific source code location given file, line, and column coordinates. Opens the file if necessary." "" } - - //- rjf: general-purpose view filtering - {Filter 0 Null Nil 0 0 0 0 0 0 Find "filter" "Filter" "Begins filtering the active view." "sort,search,filter,find" } - {ApplyFilter 0 Null Nil 0 0 0 0 0 0 Find "apply_filter" "Apply Filter" "Applies the typed filter to the active view." "sort,search,filter,find,apply" } - {ClearFilter 0 Null Nil 0 0 0 0 0 0 Find "clear_filter" "Clear Filter" "Clears the filter applied to the active view." "sort,search,filter,find,clear" } - - //- rjf: view drivers - {GettingStarted 0 Null Nil 0 0 0 0 0 0 QuestionMark "getting_started" "Getting Started" "Opens the menu for information on getting started." "tutorial,help" } - {Commands 1 Null Nil 0 0 0 0 0 0 List "commands" "Commands" "Opens the list of all commands." "" } - {Target 1 Null Nil 0 0 0 0 0 0 Target "target" "Target" "Opens the editor for a target." "" } - {Targets 0 Null Nil 0 0 0 0 0 0 Target "targets" "Targets" "Opens the list of all targets." "" } - {FilePathMap 0 Null Nil 0 0 0 0 0 0 FileOutline "file_path_map" "File Path Map" "Opens the file path mapping editor." "" } - {AutoViewRules 0 Null Nil 0 0 0 0 0 0 Binoculars "auto_view_rules" "Auto View Rules" "Opens the auto view rule editor." "" } - {Scheduler 0 Null Nil 0 0 0 0 0 0 Scheduler "scheduler" "Scheduler" "Opens the scheduler view, for process and thread controls." "threads,processes,targets" } - {CallStack 0 Null Nil 0 0 0 0 0 0 Thread "call_stack" "Call Stack" "Opens the call stack view." "callstack,thread,unwind" } - {Modules 0 Null Nil 0 0 0 0 0 0 Module "modules" "Modules" "Opens the modules view." "" } - {PendingEntity 1 Null Nil 0 0 0 0 0 0 FileOutline "pending_entity" "Pending Entity" "Opens a view which waits for the passed entity to be completely loaded, then replaces itself with a new view." "" } - {Code 1 Null Nil 0 0 0 0 0 0 FileOutline "code" "Code" "Opens the code view for an already-loaded file." "" } - {Watch 0 Null Nil 0 0 0 0 0 0 Binoculars "watch" "Watch" "Opens a watch view." "" } - {Locals 0 Null Nil 0 0 0 0 0 0 Binoculars "locals" "Locals" "Opens a locals view." "" } - {Registers 0 Null Nil 0 0 0 0 0 0 Binoculars "registers" "Registers" "Opens a registers view." "" } - {Globals 0 Null Nil 0 0 0 0 0 0 Binoculars "globals" "Globals" "Opens a globals view." "" } - {ThreadLocals 0 Null Nil 0 0 0 0 0 0 Binoculars "thread_locals" "Thread Locals" "Opens a thread locals view." "" } - {Types 0 Null Nil 0 0 0 0 0 0 Binoculars "types" "Types" "Opens a types view." "" } - {Procedures 0 Null Nil 0 0 0 0 0 0 Binoculars "procedures" "Procedures" "Opens a procedures view." "" } - {Output 0 Null Nil 0 0 0 0 0 0 List "output" "Output" "Opens an output view." "" } - {Memory 0 Null Nil 0 0 0 0 0 0 Grid "memory" "Memory" "Opens a memory view." "" } - {Disassembly 0 Null Nil 0 0 0 0 0 0 Glasses "disassembly" "Disassembly" "Opens the disassembly view." "disasm" } - {Breakpoints 0 Null Nil 0 0 0 0 0 0 CircleFilled "breakpoints" "Breakpoints" "Opens the breakpoints view." "" } - {WatchPins 0 Null Nil 0 0 0 0 0 0 Pin "watch_pins" "Watch Pins" "Opens the watch pins view." "" } - {ExceptionFilters 0 Null Nil 0 0 0 0 0 0 Gear "exception_filters" "Exception Filters" "Opens the exception filters view." "exceptions,filters" } - {Settings 0 Null Nil 0 0 0 0 0 0 Gear "settings" "Settings" "Opens the settings view." "theme,color,scheme,options" } - {PickFile 1 FilePath Nil 1 0 0 0 0 1 FileOutline "pick_file" "Pick File" "Opens the file browser to pick a file." "" } - {PickFolder 1 FilePath Nil 0 1 0 0 0 1 FolderOpenFilled "pick_folder" "Pick Folder" "Opens the file browser to pick a folder." "" } - {PickFileOrFolder 1 FilePath Nil 1 1 0 0 0 1 FileOutline "pick_file_or_folder" "Pick File/Folder" "Opens the file browser to pick a file or folder." "" } - - //- rjf: query completion - {CompleteQuery 1 Null Nil 0 0 0 0 0 0 Null "complete_query" "Complete Query" "Completes a query." "" } - {CancelQuery 1 Null Nil 0 0 0 0 0 0 Null "cancel_query" "Cancel Query" "Cancels a query." "" } - - //- rjf: developer commands - {ToggleDevMenu 0 Null Nil 0 0 0 0 0 0 Null "toggle_dev_menu" "Toggle Developer Menu" "Opens and closes the developer menu." "" } - {LogMarker 0 Null Nil 0 0 0 0 0 0 Null "log_marker" "Log Marker" "Logs a marker in the application log, to denote specific points in time within the log." "" } -} - -//////////////////////////////// -//~ rjf: Built-In View Rules -// -// @view_rule_info -// -// NOTE(rjf): View rules are subtle in that they may impact any subset of the -// eval visualization pipeline. The "array" view rule, for example, functions -// by tweaking the type of an eval from `X *` to `X (*)[N]` (where N is -// computed from whatever expression is specified by the view rule). The "list" -// view rule, on the other hand, does not require any changes to the actual -// eval nor its type - instead, it follows an alternative path in constructing -// "viz blocks", and then constructing "viz rows" from those blocks. Compare -// these to the simpler 'dec', 'bin', or 'oct' rules, which simply tweak the -// radix used when stringizing numbers, which is something that only occurs in -// single-line eval stringization building. -// -// As such, each view rule specification has a mask, which determines which -// stages it may be used for. For a given view rule specification, if the bit -// corresponding to a particular eval stage is set, then that view rule spec- -// -ification also includes a hook which can be called from that stage. -// -// Below is a list of the stages in the eval visualization pipeline, as well as -// abbreviations which are used in the tables. -// -// eval resolution, "er" -> provides a chance for a view rule to impact an eval -// value or type, before the rest of the eval visual -// pipeline continues. -// -// viz block prod, "vb" -> given a resolved eval, produce a list of non- -// windowed "viz blocks", which correspond to one or -// many contiguous rows in a watch-window-style UI. -// one level of expanded struct members, with no sub- -// expansions, would be one viz block. if one of those -// members - in the middle - were expanded too, then -// it would require three viz blocks - one for the -// members before the sub-expansion, one for the -// sub expansion members, and one for the members -// after, and so on. this is done recursively. -// -// viz row prod, "vr" -> given a list of viz blocks, a windowed list of viz -// rows may be produced. each of these rows has info -// for building actual UI in e.g. a watch window - -// whether or not the row can be expanded, whether or -// not the row's value can be edited, what the edit- -// able string is for a row, what the display string -// is for a row, what the expression string is for a -// row, what the type is for a row, and so on. -// -// line stringize, "ls" -> this is the stage used to produce display strings -// in the "viz row prod" stage, as well as basically -// any time UI needs to display the result of an eval -// in a single line. this also occurs recursively, -// descending into members & elements as needed, -// constrained by # of available pixels and font size -// and so on. -// -// row ui build, "ru" -> finally, after the previous stages are completed, -// ui can finally be built according to all of the -// per-row information produced. this is the stage -// where view rules can insert their own arbitrary ui -// on a per-row basis. -// -// block ui build, "bu" -> sometimes, view rules want to take over an entire -// viz block. while those viz blocks will still be -// used to size a collapsed region in terms of #-of- -// rows, this stage offers the ability to build a ui -// stretching over all of the rows. -// -// tab ui build, "tu" -> when a view rule also wants to implement ui for a -// dedicated tab, it can supply hooks for that as well -// in which case an eval/view-rule can be opened in a -// fully fledged, dedicated ui -// -// A few other bits are included for various ways in which a view rule may be -// applied throughout the eval visualization pipeline. A list follows: -// -// inherited, "ih" -> is this view rule included, or not included, in -// child expansions? -// -// expandable, "ex" -> does this view rule force the ability to expand -// an expression, even if traditional analysis of type -// info would not allow expansion? -// -// Not all of these stages are specified at this layer, however, since the -// "df_core" layer is for the non-graphical core debugger features. So the -// information pertaining to the eval visualization pipeline stages which -// do require graphical subsystems (e.g. UI, fonts, rendering) are specified -// in the "df_gfx" layer. -// -// For any view rules in this layer which also have graphical features, they -// are specified in both tables under the same name. - -@table(name name_lower string ih ex er vb display_name docs schema description) -DF_CoreViewRuleTable: -{ - {Null null "" - - - - "" - "" "" } - {Array array "array" - - x - "Array" x "x:{expr}" "Specifies that a pointer points to N elements, rather than only 1." } - {Slice slice "slice" - - x - "Slice" x "" "Specifies that a pointer within a struct, also containing an integer, points to the number of elements encoded by the integer." } - {List list "list" - - - x "List" x "x:{member}" "Specifies that some struct, union, or class forms the top of a linked list, and the member which points at the following element in the list." } - {ByteSwap bswap "bswap" x - x - "Byte Swap" x "" "Specifies that all integer primitives should be byte-swapped, such that their endianness is reversed." } - {BaseDec base_dec "dec" x - - - "Decimal Base (Base 10)" x "" "Specifies that all integral evaluations should appear in base-10 form." } - {BaseBin base_bin "bin" x - - - "Binary Base (Base 2)" x "" "Specifies that all integral evaluations should appear in base-2 form." } - {BaseOct base_oct "oct" x - - - "Octal Base (Base 8)" x "" "Specifies that all integral evaluations should appear in base-8 form." } - {BaseHex base_hex "hex" x - - - "Hexadecimal Base (Base 16)" x "" "Specifies that all integral evaluations should appear in base-16 form." } - {Only only "only" x - - x "Only Specified Members" x "x:{member}" "Specifies that only the specified members should appear in struct, union, or class evaluations." } - {Omit omit "omit" x - - x "Omit Specified Members" x "x:{member}" "Omits a list of member names from appearing in struct, union, or class evaluations." } - {NoAddr no_addr "no_addr" x - - - "Disable Address Values" x "" "Displays only what pointers point to, if possible, without the pointer's address value." } - {RGBA rgba "rgba" - x - x "Color (RGBA)" x "" "Displays as a color, interpreting the data as encoding R, G, B, and A values." } - {Text text "text" - x - x "Text" x "x:{'lang':lang, 'size':expr}" "Displays as text." } - {Disasm disasm "disasm" - x - x "Disassembly" x "x:{'arch':arch, 'size':expr}" "Displays as disassembled instructions, interpreting the data as raw machine code." } - {Graph graph "graph" - x - x "Graph" x "" "Displays as a pointer graph, visualizing nodes and edges formed by pointers directly." } - {Bitmap bitmap "bitmap" - x - x "Bitmap" x "x:{'w':expr, 'h':expr, 'fmt':tex2dformat}" "Displays as a bitmap, interpreting the data as raw pixel data." } - {Geo geo "geo" - x - x "Geometry" x "x:{'count':expr, 'vertices_base':expr, 'vertices_size':expr}" "Displays as geometry, interpreting the data as vertex data." } -} - -//////////////////////////////// -//~ rjf: Icons (TODO(rjf): this needs to move to the df_gfx graphical layer) - -@table(name, text) -DF_IconTable: -{ - (Null "") - (FolderOpenOutline "b") - (FolderClosedOutline "c") - (FolderOpenFilled "B") - (FolderClosedFilled "C") - (FileOutline "f") - (FileFilled "F") - (Play "g") - (PlayStepForward "h") - (Pause "r") - (Stop "s") - (Info "i") - (WarningSmall "w") - (WarningBig "W") - (Unlocked "k") - (Locked "K") - (LeftArrow "L") - (RightArrow "R") - (UpArrow "U") - (DownArrow "D") - (Gear "G") - (Pencil "P") - (Trash "3") - (Pin "p") - (RadioHollow "O") - (RadioFilled "o") - (CheckHollow "!") - (CheckFilled "1") - (LeftCaret "<") - (RightCaret ">") - (UpCaret "^") - (DownCaret "v") - (UpScroll "9") - (DownScroll "0") - (LeftScroll "7") - (RightScroll "8") - (Add "+") - (Minus "-") - (Thread "'") - (Threads '\\"') - (Machine "M") - (CircleFilled ".") - (X "x") - (Refresh "q") - (Undo "j") - (Redo "u") - (Save "m") - (Window "n") - (Target "l") - (Clipboard "a") - (Scheduler "z") - (Module "y") - (XSplit "X") - (YSplit "Y") - (ClosePanel "S") - (StepInto "T") - (StepOver "Z") - (StepOut "d") - (Find "N") - (Palette "E") - (Thumbnails "H") - (Glasses "e") - (Binoculars "I") - (List "J") - (Grid "A") - (QuestionMark "?") - (Person "4") - (Briefcase "5") - (Dot "c") -} - -//////////////////////////////// -//~ rjf: X64 Instruction Table - -@table(name summary) -DF_InstTableX64: -{ - - //- rjf: core - {AAA "ASCII Adjust After Addition" } - {AAD "ASCII Adjust AX Before Division" } - {AAM "ASCII Adjust AX After Multiply" } - {AAS "ASCII Adjust AL After Subtraction" } - {ADC "Add with Carry" } - {ADCX "Unsigned Integer Addition of Two Operands with Carry Flag" } - {ADD "Add" } - {ADDPD "Add Packed Double-Precision Floating-Point Values" } - {ADDPS "Add Packed Single-Precision Floating-Point Values" } - {ADDSD "Add Scalar Double-Precision Floating-Point Values" } - {ADDSS "Add Scalar Single-Precision Floating-Point Values" } - {ADDSUBPD "Packed Double-FP Add/Subtract" } - {ADDSUBPS "Packed Single-FP Add/Subtract" } - {ADOX "Unsigned Integer Addition of Two Operands with Overflow Flag" } - {AESDEC "Perform One Round of an AES Decryption Flow" } - {AESDEC128KL "Perform Ten Rounds of AES Decryption Flow with Key Locker Using 128-Bit Key" } - {AESDEC256KL "Perform 14 Rounds of AES Decryption Flow with Key Locker Using 256-Bit Key" } - {AESDECLAST "Perform Last Round of an AES Decryption Flow" } - {AESDECWIDE128KL "Perform Ten Rounds of AES Decryption Flow with Key Locker on 8 Blocks Using 128-Bit Key" } - {AESDECWIDE256KL "Perform 14 Rounds of AES Decryption Flow with Key Locker on 8 Blocks Using 256-Bit Key" } - {AESENC "Perform One Round of an AES Encryption Flow" } - {AESENC128KL "Perform Ten Rounds of AES Encryption Flow with Key Locker Using 128-Bit Key" } - {AESENC256KL "Perform 14 Rounds of AES Encryption Flow with Key Locker Using 256-Bit Key" } - {AESENCLAST "Perform Last Round of an AES Encryption Flow" } - {AESENCWIDE128KL "Perform Ten Rounds of AES Encryption Flow with Key Locker on 8 Blocks Using 128-Bit Key" } - {AESENCWIDE256KL "Perform 14 Rounds of AES Encryption Flow with Key Locker on 8 Blocks Using 256-Bit Key" } - {AESIMC "Perform the AES InvMixColumn Transformation" } - {AESKEYGENASSIST "AES Round Key Generation Assist" } - {AND "Logical AND" } - {ANDN "Logical AND NOT" } - {ANDNPD "Bitwise Logical AND NOT of Packed Double Precision Floating-Point Values" } - {ANDNPS "Bitwise Logical AND NOT of Packed Single Precision Floating-Point Values" } - {ANDPD "Bitwise Logical AND of Packed Double Precision Floating-Point Values" } - {ANDPS "Bitwise Logical AND of Packed Single Precision Floating-Point Values" } - {ARPL "Adjust RPL Field of Segment Selector" } - {BEXTR "Bit Field Extract" } - {BLENDPD "Blend Packed Double Precision Floating-Point Values" } - {BLENDPS "Blend Packed Single Precision Floating-Point Values" } - {BLENDVPD "Variable Blend Packed Double Precision Floating-Point Values" } - {BLENDVPS "Variable Blend Packed Single Precision Floating-Point Values" } - {BLSI "Extract Lowest Set Isolated Bit" } - {BLSMSK "Get Mask Up to Lowest Set Bit" } - {BLSR "Reset Lowest Set Bit" } - {BNDCL "Check Lower Bound" } - {BNDCN "Check Upper Bound" } - {BNDCU "Check Upper Bound" } - {BNDLDX "Load Extended Bounds Using Address Translation" } - {BNDMK "Make Bounds" } - {BNDMOV "Move Bounds" } - {BNDSTX "Store Extended Bounds Using Address Translation" } - {BOUND "Check Array Index Against Bounds" } - {BSF "Bit Scan Forward" } - {BSR "Bit Scan Reverse" } - {BSWAP "Byte Swap" } - {BT "Bit Test" } - {BTC "Bit Test and Complement" } - {BTR "Bit Test and Reset" } - {BTS "Bit Test and Set" } - {BZHI "Zero High Bits Starting with Specified Bit Position" } - {CALL "Call Procedure" } - {CBW "Convert Byte to Word/Convert Word to Doubleword/Convert Doubleword to Quadword" } - {CDQ "Convert Word to Doubleword/Convert Doubleword to Quadword" } - {CDQE "Convert Byte to Word/Convert Word to Doubleword/Convert Doubleword to Quadword" } - {CLAC "Clear AC Flag in EFLAGS Register" } - {CLC "Clear Carry Flag" } - {CLD "Clear Direction Flag" } - {CLDEMOTE "Cache Line Demote" } - {CLFLUSH "Flush Cache Line" } - {CLFLUSHOPT "Flush Cache Line Optimized" } - {CLI "Clear Interrupt Flag" } - {CLRSSBSY "Clear Busy Flag in a Supervisor Shadow Stack Token" } - {CLTS "Clear Task-Switched Flag in CR0" } - {CLWB "Cache Line Write Back" } - {CMC "Complement Carry Flag" } - {CMOVcc "Conditional Move" } - {CMP "Compare Two Operands" } - {CMPPD "Compare Packed Double-Precision Floating-Point Values" } - {CMPPS "Compare Packed Single-Precision Floating-Point Values" } - {CMPS "Compare String Operands" } - {CMPSB "Compare String Operands" } - {CMPSD "Compare String Operands" } - {CMPSQ "Compare String Operands" } - {CMPSS "Compare Scalar Single-Precision Floating-Point Value" } - {CMPSW "Compare String Operands" } - {CMPXCHG "Compare and Exchange" } - {CMPXCHG16B "Compare and Exchange Bytes" } - {CMPXCHG8B "Compare and Exchange Bytes" } - {COMISD "Compare Scalar Ordered Double-Precision Floating-Point Values and Set EFLAGS" } - {COMISS "Compare Scalar Ordered Single-Precision Floating-Point Values and Set EFLAGS" } - {CPUID "CPU Identification" } - {CQO "Convert Word to Doubleword/Convert Doubleword to Quadword" } - {CRC32 "Accumulate CRC32 Value" } - {CVTDQ2PD "Convert Packed Doubleword Integers to Packed Double-Precision Floating-Point Values" } - {CVTDQ2PS "Convert Packed Doubleword Integers to Packed Single-Precision Floating-Point Values" } - {CVTPD2DQ "Convert Packed Double-Precision Floating-Point Values to Packed Doubleword Integers" } - {CVTPD2PI "Convert Packed Double-Precision FP Values to Packed Dword Integers" } - {CVTPD2PS "Convert Packed Double-Precision Floating-Point Values to Packed Single-Precision Floating-Point Values" } - {CVTPI2PD "Convert Packed Dword Integers to Packed Double-Precision FP Values" } - {CVTPI2PS "Convert Packed Dword Integers to Packed Single-Precision FP Values" } - {CVTPS2DQ "Convert Packed Single-Precision Floating-Point Values to Packed Signed Doubleword Integer Values" } - {CVTPS2PD "Convert Packed Single-Precision Floating-Point Values to Packed Double-Precision Floating-Point Values" } - {CVTPS2PI "Convert Packed Single-Precision FP Values to Packed Dword Integers" } - {CVTSD2SI "Convert Scalar Double-Precision Floating-Point Value to Doubleword Integer" } - {CVTSD2SS "Convert Scalar Double-Precision Floating-Point Value to Scalar Single-Precision Floating-Point Value" } - {CVTSI2SD "Convert Doubleword Integer to Scalar Double-Precision Floating-Point Value" } - {CVTSI2SS "Convert Doubleword Integer to Scalar Single-Precision Floating-Point Value" } - {CVTSS2SD "Convert Scalar Single-Precision Floating-Point Value to Scalar Double-Precision Floating-Point Value" } - {CVTSS2SI "Convert Scalar Single-Precision Floating-Point Value to Doubleword Integer" } - {CVTTPD2DQ "Convert with Truncation Packed Double-Precision Floating-Point Values to Packed Doubleword Integers" } - {CVTTPD2PI "Convert with Truncation Packed Double-Precision FP Values to Packed Dword Integers" } - {CVTTPS2DQ "Convert with Truncation Packed Single-Precision Floating-Point Values to Packed Signed Doubleword Integer Values" } - {CVTTPS2PI "Convert with Truncation Packed Single-Precision FP Values to Packed Dword Integers" } - {CVTTSD2SI "Convert with Truncation Scalar Double-Precision Floating-Point Value to Signed Integer" } - {CVTTSS2SI "Convert with Truncation Scalar Single-Precision Floating-Point Value to Integer" } - {CWD "Convert Word to Doubleword/Convert Doubleword to Quadword" } - {CWDE "Convert Byte to Word/Convert Word to Doubleword/Convert Doubleword to Quadword" } - {DAA "Decimal Adjust AL after Addition" } - {DAS "Decimal Adjust AL after Subtraction" } - {DEC "Decrement by 1" } - {DIV "Unsigned Divide" } - {DIVPD "Divide Packed Double-Precision Floating-Point Values" } - {DIVPS "Divide Packed Single-Precision Floating-Point Values" } - {DIVSD "Divide Scalar Double-Precision Floating-Point Value" } - {DIVSS "Divide Scalar Single-Precision Floating-Point Values" } - {DPPD "Dot Product of Packed Double Precision Floating-Point Values" } - {DPPS "Dot Product of Packed Single Precision Floating-Point Values" } - {EMMS "Empty MMX Technology State" } - {ENCODEKEY128 "Encode 128-Bit Key with Key Locker" } - {ENCODEKEY256 "Encode 256-Bit Key with Key Locker" } - {ENDBR32 "Terminate an Indirect Branch in 32-bit and Compatibility Mode" } - {ENDBR64 "Terminate an Indirect Branch in 64-bit Mode" } - {ENTER "Make Stack Frame for Procedure Parameters" } - {EXTRACTPS "Extract Packed Floating-Point Values" } - {F2XM1 "Compute 2x–1" } - {FABS "Absolute Value" } - {FADD "Add" } - {FADDP "Add" } - {FBLD "Load Binary Coded Decimal" } - {FBSTP "Store BCD Integer and Pop" } - {FCHS "Change Sign" } - {FCLEX "Clear Exceptions" } - {FCMOVcc "Floating-Point Conditional Move" } - {FCOM "Compare Floating Point Values" } - {FCOMI "Compare Floating Point Values and Set EFLAGS" } - {FCOMIP "Compare Floating Point Values and Set EFLAGS" } - {FCOMP "Compare Floating Point Values" } - {FCOMPP "Compare Floating Point Values" } - {FCOS "Cosine" } - {FDECSTP "Decrement Stack-Top Pointer" } - {FDIV "Divide" } - {FDIVP "Divide" } - {FDIVR "Reverse Divide" } - {FDIVRP "Reverse Divide" } - {FFREE "Free Floating-Point Register" } - {FIADD "Add" } - {FICOM "Compare Integer" } - {FICOMP "Compare Integer" } - {FIDIV "Divide" } - {FIDIVR "Reverse Divide" } - {FILD "Load Integer" } - {FIMUL "Multiply" } - {FINCSTP "Increment Stack-Top Pointer" } - {FINIT "Initialize Floating-Point Unit" } - {FIST "Store Integer" } - {FISTP "Store Integer" } - {FISTTP "Store Integer with Truncation" } - {FISUB "Subtract" } - {FISUBR "Reverse Subtract" } - {FLD "Load Floating Point Value" } - {FLD1 "Load Constant" } - {FLDCW "Load x87 FPU Control Word" } - {FLDENV "Load x87 FPU Environment" } - {FLDL2E "Load Constant" } - {FLDL2T "Load Constant" } - {FLDLG2 "Load Constant" } - {FLDLN2 "Load Constant" } - {FLDPI "Load Constant" } - {FLDZ "Load Constant" } - {FMUL "Multiply" } - {FMULP "Multiply" } - {FNCLEX "Clear Exceptions" } - {FNINIT "Initialize Floating-Point Unit" } - {FNOP "No Operation" } - {FNSAVE "Store x87 FPU State" } - {FNSTCW "Store x87 FPU Control Word" } - {FNSTENV "Store x87 FPU Environment" } - {FNSTSW "Store x87 FPU Status Word" } - {FPATAN "Partial Arctangent" } - {FPREM "Partial Remainder" } - {FPREM1 "Partial Remainder" } - {FPTAN "Partial Tangent" } - {FRNDINT "Round to Integer" } - {FRSTOR "Restore x87 FPU State" } - {FSAVE "Store x87 FPU State" } - {FSCALE "Scale" } - {FSIN "Sine" } - {FSINCOS "Sine and Cosine" } - {FSQRT "Square Root" } - {FST "Store Floating Point Value" } - {FSTCW "Store x87 FPU Control Word" } - {FSTENV "Store x87 FPU Environment" } - {FSTP "Store Floating Point Value" } - {FSTSW "Store x87 FPU Status Word" } - {FSUB "Subtract" } - {FSUBP "Subtract" } - {FSUBR "Reverse Subtract" } - {FSUBRP "Reverse Subtract" } - {FTST "TEST" } - {FUCOM "Unordered Compare Floating Point Values" } - {FUCOMI "Compare Floating Point Values and Set EFLAGS" } - {FUCOMIP "Compare Floating Point Values and Set EFLAGS" } - {FUCOMP "Unordered Compare Floating Point Values" } - {FUCOMPP "Unordered Compare Floating Point Values" } - {FWAIT "Wait" } - {FXAM "Examine Floating-Point" } - {FXCH "Exchange Register Contents" } - {FXRSTOR "Restore x87 FPU, MMX, XMM, and MXCSR State" } - {FXSAVE "Save x87 FPU, MMX Technology, and SSE State" } - {FXTRACT "Extract Exponent and Significand" } - {FYL2X "Compute y * log2x" } - {FYL2XP1 "Compute y * log2(x +1)" } - {GF2P8AFFINEINVQB "Galois Field Affine Transformation Inverse" } - {GF2P8AFFINEQB "Galois Field Affine Transformation" } - {GF2P8MULB "Galois Field Multiply Bytes" } - {HADDPD "Packed Double-FP Horizontal Add" } - {HADDPS "Packed Single-FP Horizontal Add" } - {HLT "Halt" } - {HRESET "History Reset" } - {HSUBPD "Packed Double-FP Horizontal Subtract" } - {HSUBPS "Packed Single-FP Horizontal Subtract" } - {IDIV "Signed Divide" } - {IMUL "Signed Multiply" } - {IN "Input from Port" } - {INC "Increment by 1" } - {INCSSPD "Increment Shadow Stack Pointer" } - {INCSSPQ "Increment Shadow Stack Pointer" } - {INS "Input from Port to String" } - {INSB "Input from Port to String" } - {INSD "Input from Port to String" } - {INSERTPS "Insert Scalar Single-Precision Floating-Point Value" } - {INSW "Input from Port to String" } - {INT "Call to Interrupt Procedure" } - {INT1 "Call to Interrupt Procedure" } - {INT3 "Call to Interrupt Procedure" } - {INTO "Call to Interrupt Procedure" } - {INVD "Invalidate Internal Caches" } - {INVLPG "Invalidate TLB Entries" } - {INVPCID "Invalidate Process-Context Identifier" } - {IRET "Interrupt Return" } - {IRETD "Interrupt Return" } - {IRETQ "Interrupt Return" } - {JMP "Jump" } - {Jcc "Jump if Condition Is Met" } - {KADDB "ADD Two Masks" } - {KADDD "ADD Two Masks" } - {KADDQ "ADD Two Masks" } - {KADDW "ADD Two Masks" } - {KANDB "Bitwise Logical AND Masks" } - {KANDD "Bitwise Logical AND Masks" } - {KANDNB "Bitwise Logical AND NOT Masks" } - {KANDND "Bitwise Logical AND NOT Masks" } - {KANDNQ "Bitwise Logical AND NOT Masks" } - {KANDNW "Bitwise Logical AND NOT Masks" } - {KANDQ "Bitwise Logical AND Masks" } - {KANDW "Bitwise Logical AND Masks" } - {KMOVB "Move from and to Mask Registers" } - {KMOVD "Move from and to Mask Registers" } - {KMOVQ "Move from and to Mask Registers" } - {KMOVW "Move from and to Mask Registers" } - {KNOTB "NOT Mask Register" } - {KNOTD "NOT Mask Register" } - {KNOTQ "NOT Mask Register" } - {KNOTW "NOT Mask Register" } - {KORB "Bitwise Logical OR Masks" } - {KORD "Bitwise Logical OR Masks" } - {KORQ "Bitwise Logical OR Masks" } - {KORTESTB "OR Masks And Set Flags" } - {KORTESTD "OR Masks And Set Flags" } - {KORTESTQ "OR Masks And Set Flags" } - {KORTESTW "OR Masks And Set Flags" } - {KORW "Bitwise Logical OR Masks" } - {KSHIFTLB "Shift Left Mask Registers" } - {KSHIFTLD "Shift Left Mask Registers" } - {KSHIFTLQ "Shift Left Mask Registers" } - {KSHIFTLW "Shift Left Mask Registers" } - {KSHIFTRB "Shift Right Mask Registers" } - {KSHIFTRD "Shift Right Mask Registers" } - {KSHIFTRQ "Shift Right Mask Registers" } - {KSHIFTRW "Shift Right Mask Registers" } - {KTESTB "Packed Bit Test Masks and Set Flags" } - {KTESTD "Packed Bit Test Masks and Set Flags" } - {KTESTQ "Packed Bit Test Masks and Set Flags" } - {KTESTW "Packed Bit Test Masks and Set Flags" } - {KUNPCKBW "Unpack for Mask Registers" } - {KUNPCKDQ "Unpack for Mask Registers" } - {KUNPCKWD "Unpack for Mask Registers" } - {KXNORB "Bitwise Logical XNOR Masks" } - {KXNORD "Bitwise Logical XNOR Masks" } - {KXNORQ "Bitwise Logical XNOR Masks" } - {KXNORW "Bitwise Logical XNOR Masks" } - {KXORB "Bitwise Logical XOR Masks" } - {KXORD "Bitwise Logical XOR Masks" } - {KXORQ "Bitwise Logical XOR Masks" } - {KXORW "Bitwise Logical XOR Masks" } - {LAHF "Load Status Flags into AH Register" } - {LAR "Load Access Rights Byte" } - {LDDQU "Load Unaligned Integer 128 Bits" } - {LDMXCSR "Load MXCSR Register" } - {LDS "Load Far Pointer" } - {LEA "Load Effective Address" } - {LEAVE "High Level Procedure Exit" } - {LES "Load Far Pointer" } - {LFENCE "Load Fence" } - {LFS "Load Far Pointer" } - {LGDT "Load Global/Interrupt Descriptor Table Register" } - {LGS "Load Far Pointer" } - {LIDT "Load Global/Interrupt Descriptor Table Register" } - {LLDT "Load Local Descriptor Table Register" } - {LMSW "Load Machine Status Word" } - {LOADIWKEY "Load Internal Wrapping Key with Key Locker" } - {LOCK "Assert LOCK# Signal Prefix" } - {LODS "Load String" } - {LODSB "Load String" } - {LODSD "Load String" } - {LODSQ "Load String" } - {LODSW "Load String" } - {LOOP "Loop According to ECX Counter" } - {LOOPcc "Loop According to ECX Counter" } - {LSL "Load Segment Limit" } - {LSS "Load Far Pointer" } - {LTR "Load Task Register" } - {LZCNT "Count the Number of Leading Zero Bits" } - {MASKMOVDQU "Store Selected Bytes of Double Quadword" } - {MASKMOVQ "Store Selected Bytes of Quadword" } - {MAXPD "Maximum of Packed Double-Precision Floating-Point Values" } - {MAXPS "Maximum of Packed Single-Precision Floating-Point Values" } - {MAXSD "Return Maximum Scalar Double-Precision Floating-Point Value" } - {MAXSS "Return Maximum Scalar Single-Precision Floating-Point Value" } - {MFENCE "Memory Fence" } - {MINPD "Minimum of Packed Double-Precision Floating-Point Values" } - {MINPS "Minimum of Packed Single-Precision Floating-Point Values" } - {MINSD "Return Minimum Scalar Double-Precision Floating-Point Value" } - {MINSS "Return Minimum Scalar Single-Precision Floating-Point Value" } - {MONITOR "Set Up Monitor Address" } - {MOV "Move" } - {MOVAPD "Move Aligned Packed Double-Precision Floating-Point Values" } - {MOVAPS "Move Aligned Packed Single-Precision Floating-Point Values" } - {MOVBE "Move Data After Swapping Bytes" } - {MOVD "Move Doubleword/Move Quadword" } - {MOVDDUP "Replicate Double FP Values" } - {MOVDIR64B "Move 64 Bytes as Direct Store" } - {MOVDIRI "Move Doubleword as Direct Store" } - {MOVDQ2Q "Move Quadword from XMM to MMX Technology Register" } - {MOVDQA "Move Aligned Packed Integer Values" } - {MOVDQU "Move Unaligned Packed Integer Values" } - {MOVHLPS "Move Packed Single-Precision Floating-Point Values High to Low" } - {MOVHPD "Move High Packed Double-Precision Floating-Point Value" } - {MOVHPS "Move High Packed Single-Precision Floating-Point Values" } - {MOVLHPS "Move Packed Single-Precision Floating-Point Values Low to High" } - {MOVLPD "Move Low Packed Double-Precision Floating-Point Value" } - {MOVLPS "Move Low Packed Single-Precision Floating-Point Values" } - {MOVMSKPD "Extract Packed Double-Precision Floating-Point Sign Mask" } - {MOVMSKPS "Extract Packed Single-Precision Floating-Point Sign Mask" } - {MOVNTDQ "Store Packed Integers Using Non-Temporal Hint" } - {MOVNTDQA "Load Double Quadword Non-Temporal Aligned Hint" } - {MOVNTI "Store Doubleword Using Non-Temporal Hint" } - {MOVNTPD "Store Packed Double-Precision Floating-Point Values Using Non-Temporal Hint" } - {MOVNTPS "Store Packed Single-Precision Floating-Point Values Using Non-Temporal Hint" } - {MOVNTQ "Store of Quadword Using Non-Temporal Hint" } - {MOVQ "Move Doubleword/Move Quadword" } - {MOVQ2DQ "Move Quadword from MMX Technology to XMM Register" } - {MOVS "Move Data from String to String" } - {MOVSB "Move Data from String to String" } - {MOVSD "Move Data from String to String" } - {MOVSHDUP "Replicate Single FP Values" } - {MOVSLDUP "Replicate Single FP Values" } - {MOVSQ "Move Data from String to String" } - {MOVSS "Move or Merge Scalar Single-Precision Floating-Point Value" } - {MOVSW "Move Data from String to String" } - {MOVSX "Move with Sign-Extension" } - {MOVSXD "Move with Sign-Extension" } - {MOVUPD "Move Unaligned Packed Double-Precision Floating-Point Values" } - {MOVUPS "Move Unaligned Packed Single-Precision Floating-Point Values" } - {MOVZX "Move with Zero-Extend" } - {MPSADBW "Compute Multiple Packed Sums of Absolute Difference" } - {MUL "Unsigned Multiply" } - {MULPD "Multiply Packed Double-Precision Floating-Point Values" } - {MULPS "Multiply Packed Single-Precision Floating-Point Values" } - {MULSD "Multiply Scalar Double-Precision Floating-Point Value" } - {MULSS "Multiply Scalar Single-Precision Floating-Point Values" } - {MULX "Unsigned Multiply Without Affecting Flags" } - {MWAIT "Monitor Wait" } - {NEG "Two's Complement Negation" } - {NOP "No Operation" } - {NOT "One's Complement Negation" } - {OR "Logical Inclusive OR" } - {ORPD "Bitwise Logical OR of Packed Double Precision Floating-Point Values" } - {ORPS "Bitwise Logical OR of Packed Single Precision Floating-Point Values" } - {OUT "Output to Port" } - {OUTS "Output String to Port" } - {OUTSB "Output String to Port" } - {OUTSD "Output String to Port" } - {OUTSW "Output String to Port" } - {PABSB "Packed Absolute Value" } - {PABSD "Packed Absolute Value" } - {PABSQ "Packed Absolute Value" } - {PABSW "Packed Absolute Value" } - {PACKSSDW "Pack with Signed Saturation" } - {PACKSSWB "Pack with Signed Saturation" } - {PACKUSDW "Pack with Unsigned Saturation" } - {PACKUSWB "Pack with Unsigned Saturation" } - {PADDB "Add Packed Integers" } - {PADDD "Add Packed Integers" } - {PADDQ "Add Packed Integers" } - {PADDSB "Add Packed Signed Integers with Signed Saturation" } - {PADDSW "Add Packed Signed Integers with Signed Saturation" } - {PADDUSB "Add Packed Unsigned Integers with Unsigned Saturation" } - {PADDUSW "Add Packed Unsigned Integers with Unsigned Saturation" } - {PADDW "Add Packed Integers" } - {PALIGNR "Packed Align Right" } - {PAND "Logical AND" } - {PANDN "Logical AND NOT" } - {PAUSE "Spin Loop Hint" } - {PAVGB "Average Packed Integers" } - {PAVGW "Average Packed Integers" } - {PBLENDVB "Variable Blend Packed Bytes" } - {PBLENDW "Blend Packed Words" } - {PCLMULQDQ "Carry-Less Multiplication Quadword" } - {PCMPEQB "Compare Packed Data for Equal" } - {PCMPEQD "Compare Packed Data for Equal" } - {PCMPEQQ "Compare Packed Qword Data for Equal" } - {PCMPEQW "Compare Packed Data for Equal" } - {PCMPESTRI "Packed Compare Explicit Length Strings, Return Index" } - {PCMPESTRM "Packed Compare Explicit Length Strings, Return Mask" } - {PCMPGTB "Compare Packed Signed Integers for Greater Than" } - {PCMPGTD "Compare Packed Signed Integers for Greater Than" } - {PCMPGTQ "Compare Packed Data for Greater Than" } - {PCMPGTW "Compare Packed Signed Integers for Greater Than" } - {PCMPISTRI "Packed Compare Implicit Length Strings, Return Index" } - {PCMPISTRM "Packed Compare Implicit Length Strings, Return Mask" } - {PCONFIG "Platform Configuration" } - {PDEP "Parallel Bits Deposit" } - {PEXT "Parallel Bits Extract" } - {PEXTRB "Extract Byte/Dword/Qword" } - {PEXTRD "Extract Byte/Dword/Qword" } - {PEXTRQ "Extract Byte/Dword/Qword" } - {PEXTRW "Extract Word" } - {PHADDD "Packed Horizontal Add" } - {PHADDSW "Packed Horizontal Add and Saturate" } - {PHADDW "Packed Horizontal Add" } - {PHMINPOSUW "Packed Horizontal Word Minimum" } - {PHSUBD "Packed Horizontal Subtract" } - {PHSUBSW "Packed Horizontal Subtract and Saturate" } - {PHSUBW "Packed Horizontal Subtract" } - {PINSRB "Insert Byte/Dword/Qword" } - {PINSRD "Insert Byte/Dword/Qword" } - {PINSRQ "Insert Byte/Dword/Qword" } - {PINSRW "Insert Word" } - {PMADDUBSW "Multiply and Add Packed Signed and Unsigned Bytes" } - {PMADDWD "Multiply and Add Packed Integers" } - {PMAXSB "Maximum of Packed Signed Integers" } - {PMAXSD "Maximum of Packed Signed Integers" } - {PMAXSQ "Maximum of Packed Signed Integers" } - {PMAXSW "Maximum of Packed Signed Integers" } - {PMAXUB "Maximum of Packed Unsigned Integers" } - {PMAXUD "Maximum of Packed Unsigned Integers" } - {PMAXUQ "Maximum of Packed Unsigned Integers" } - {PMAXUW "Maximum of Packed Unsigned Integers" } - {PMINSB "Minimum of Packed Signed Integers" } - {PMINSD "Minimum of Packed Signed Integers" } - {PMINSQ "Minimum of Packed Signed Integers" } - {PMINSW "Minimum of Packed Signed Integers" } - {PMINUB "Minimum of Packed Unsigned Integers" } - {PMINUD "Minimum of Packed Unsigned Integers" } - {PMINUQ "Minimum of Packed Unsigned Integers" } - {PMINUW "Minimum of Packed Unsigned Integers" } - {PMOVMSKB "Move Byte Mask" } - {PMOVSX "Packed Move with Sign Extend" } - {PMOVZX "Packed Move with Zero Extend" } - {PMULDQ "Multiply Packed Doubleword Integers" } - {PMULHRSW "Packed Multiply High with Round and Scale" } - {PMULHUW "Multiply Packed Unsigned Integers and Store High Result" } - {PMULHW "Multiply Packed Signed Integers and Store High Result" } - {PMULLD "Multiply Packed Integers and Store Low Result" } - {PMULLQ "Multiply Packed Integers and Store Low Result" } - {PMULLW "Multiply Packed Signed Integers and Store Low Result" } - {PMULUDQ "Multiply Packed Unsigned Doubleword Integers" } - {POP "Pop a Value from the Stack" } - {POPA "Pop All General-Purpose Registers" } - {POPAD "Pop All General-Purpose Registers" } - {POPCNT "Return the Count of Number of Bits Set to 1" } - {POPF "Pop Stack into EFLAGS Register" } - {POPFD "Pop Stack into EFLAGS Register" } - {POPFQ "Pop Stack into EFLAGS Register" } - {POR "Bitwise Logical OR" } - {PREFETCHW "Prefetch Data into Caches in Anticipation of a Write" } - {PREFETCHh "Prefetch Data Into Caches" } - {PSADBW "Compute Sum of Absolute Differences" } - {PSHUFB "Packed Shuffle Bytes" } - {PSHUFD "Shuffle Packed Doublewords" } - {PSHUFHW "Shuffle Packed High Words" } - {PSHUFLW "Shuffle Packed Low Words" } - {PSHUFW "Shuffle Packed Words" } - {PSIGNB "Packed SIGN" } - {PSIGND "Packed SIGN" } - {PSIGNW "Packed SIGN" } - {PSLLD "Shift Packed Data Left Logical" } - {PSLLDQ "Shift Double Quadword Left Logical" } - {PSLLQ "Shift Packed Data Left Logical" } - {PSLLW "Shift Packed Data Left Logical" } - {PSRAD "Shift Packed Data Right Arithmetic" } - {PSRAQ "Shift Packed Data Right Arithmetic" } - {PSRAW "Shift Packed Data Right Arithmetic" } - {PSRLD "Shift Packed Data Right Logical" } - {PSRLDQ "Shift Double Quadword Right Logical" } - {PSRLQ "Shift Packed Data Right Logical" } - {PSRLW "Shift Packed Data Right Logical" } - {PSUBB "Subtract Packed Integers" } - {PSUBD "Subtract Packed Integers" } - {PSUBQ "Subtract Packed Quadword Integers" } - {PSUBSB "Subtract Packed Signed Integers with Signed Saturation" } - {PSUBSW "Subtract Packed Signed Integers with Signed Saturation" } - {PSUBUSB "Subtract Packed Unsigned Integers with Unsigned Saturation" } - {PSUBUSW "Subtract Packed Unsigned Integers with Unsigned Saturation" } - {PSUBW "Subtract Packed Integers" } - {PTEST "Logical Compare" } - {PTWRITE "Write Data to a Processor Trace Packet" } - {PUNPCKHBW "Unpack High Data" } - {PUNPCKHDQ "Unpack High Data" } - {PUNPCKHQDQ "Unpack High Data" } - {PUNPCKHWD "Unpack High Data" } - {PUNPCKLBW "Unpack Low Data" } - {PUNPCKLDQ "Unpack Low Data" } - {PUNPCKLQDQ "Unpack Low Data" } - {PUNPCKLWD "Unpack Low Data" } - {PUSH "Push Word, Doubleword or Quadword Onto the Stack" } - {PUSHA "Push All General-Purpose Registers" } - {PUSHAD "Push All General-Purpose Registers" } - {PUSHF "Push EFLAGS Register onto the Stack" } - {PUSHFD "Push EFLAGS Register onto the Stack" } - {PUSHFQ "Push EFLAGS Register onto the Stack" } - {PXOR "Logical Exclusive OR" } - {RCL "Rotate" } - {RCPPS "Compute Reciprocals of Packed Single-Precision Floating-Point Values" } - {RCPSS "Compute Reciprocal of Scalar Single-Precision Floating-Point Values" } - {RCR "Rotate" } - {RDFSBASE "Read FS/GS Segment Base" } - {RDGSBASE "Read FS/GS Segment Base" } - {RDMSR "Read from Model Specific Register" } - {RDPID "Read Processor ID" } - {RDPKRU "Read Protection Key Rights for User Pages" } - {RDPMC "Read Performance-Monitoring Counters" } - {RDRAND "Read Random Number" } - {RDSEED "Read Random SEED" } - {RDSSPD "Read Shadow Stack Pointer" } - {RDSSPQ "Read Shadow Stack Pointer" } - {RDTSC "Read Time-Stamp Counter" } - {RDTSCP "Read Time-Stamp Counter and Processor ID" } - {REP "Repeat String Operation Prefix" } - {REPE "Repeat String Operation Prefix" } - {REPNE "Repeat String Operation Prefix" } - {REPNZ "Repeat String Operation Prefix" } - {REPZ "Repeat String Operation Prefix" } - {RET "Return from Procedure" } - {ROL "Rotate" } - {ROR "Rotate" } - {RORX "Rotate Right Logical Without Affecting Flags" } - {ROUNDPD "Round Packed Double Precision Floating-Point Values" } - {ROUNDPS "Round Packed Single Precision Floating-Point Values" } - {ROUNDSD "Round Scalar Double Precision Floating-Point Values" } - {ROUNDSS "Round Scalar Single Precision Floating-Point Values" } - {RSM "Resume from System Management Mode" } - {RSQRTPS "Compute Reciprocals of Square Roots of Packed Single-Precision Floating-Point Values" } - {RSQRTSS "Compute Reciprocal of Square Root of Scalar Single-Precision Floating-Point Value" } - {RSTORSSP "Restore Saved Shadow Stack Pointer" } - {SAHF "Store AH into Flags" } - {SAL "Shift" } - {SAR "Shift" } - {SARX "Shift Without Affecting Flags" } - {SAVEPREVSSP "Save Previous Shadow Stack Pointer" } - {SBB "Integer Subtraction with Borrow" } - {SCAS "Scan String" } - {SCASB "Scan String" } - {SCASD "Scan String" } - {SCASW "Scan String" } - {SERIALIZE "Serialize Instruction Execution" } - {SETSSBSY "Mark Shadow Stack Busy" } - {SETcc "Set Byte on Condition" } - {SFENCE "Store Fence" } - {SGDT "Store Global Descriptor Table Register" } - {SHA1MSG1 "Perform an Intermediate Calculation for the Next Four SHA1 Message Dwords" } - {SHA1MSG2 "Perform a Final Calculation for the Next Four SHA1 Message Dwords" } - {SHA1NEXTE "Calculate SHA1 State Variable E after Four Rounds" } - {SHA1RNDS4 "Perform Four Rounds of SHA1 Operation" } - {SHA256MSG1 "Perform an Intermediate Calculation for the Next Four SHA256 Message Dwords" } - {SHA256MSG2 "Perform a Final Calculation for the Next Four SHA256 Message Dwords" } - {SHA256RNDS2 "Perform Two Rounds of SHA256 Operation" } - {SHL "Shift" } - {SHLD "Double Precision Shift Left" } - {SHLX "Shift Without Affecting Flags" } - {SHR "Shift" } - {SHRD "Double Precision Shift Right" } - {SHRX "Shift Without Affecting Flags" } - {SHUFPD "Packed Interleave Shuffle of Pairs of Double-Precision Floating-Point Values" } - {SHUFPS "Packed Interleave Shuffle of Quadruplets of Single-Precision Floating-Point Values" } - {SIDT "Store Interrupt Descriptor Table Register" } - {SLDT "Store Local Descriptor Table Register" } - {SMSW "Store Machine Status Word" } - {SQRTPD "Square Root of Double-Precision Floating-Point Values" } - {SQRTPS "Square Root of Single-Precision Floating-Point Values" } - {SQRTSD "Compute Square Root of Scalar Double-Precision Floating-Point Value" } - {SQRTSS "Compute Square Root of Scalar Single-Precision Value" } - {STAC "Set AC Flag in EFLAGS Register" } - {STC "Set Carry Flag" } - {STD "Set Direction Flag" } - {STI "Set Interrupt Flag" } - {STMXCSR "Store MXCSR Register State" } - {STOS "Store String" } - {STOSB "Store String" } - {STOSD "Store String" } - {STOSQ "Store String" } - {STOSW "Store String" } - {STR "Store Task Register" } - {SUB "Subtract" } - {SUBPD "Subtract Packed Double-Precision Floating-Point Values" } - {SUBPS "Subtract Packed Single-Precision Floating-Point Values" } - {SUBSD "Subtract Scalar Double-Precision Floating-Point Value" } - {SUBSS "Subtract Scalar Single-Precision Floating-Point Value" } - {SWAPGS "Swap GS Base Register" } - {SYSCALL "Fast System Call" } - {SYSENTER "Fast System Call" } - {SYSEXIT "Fast Return from Fast System Call" } - {SYSRET "Return From Fast System Call" } - {TEST "Logical Compare" } - {TPAUSE "Timed PAUSE" } - {TZCNT "Count the Number of Trailing Zero Bits" } - {UCOMISD "Unordered Compare Scalar Double-Precision Floating-Point Values and Set EFLAGS" } - {UCOMISS "Unordered Compare Scalar Single-Precision Floating-Point Values and Set EFLAGS" } - {UD "Undefined Instruction" } - {UMONITOR "User Level Set Up Monitor Address" } - {UMWAIT "User Level Monitor Wait" } - {UNPCKHPD "Unpack and Interleave High Packed Double-Precision Floating-Point Values" } - {UNPCKHPS "Unpack and Interleave High Packed Single-Precision Floating-Point Values" } - {UNPCKLPD "Unpack and Interleave Low Packed Double-Precision Floating-Point Values" } - {UNPCKLPS "Unpack and Interleave Low Packed Single-Precision Floating-Point Values" } - {VALIGND "Align Doubleword/Quadword Vectors" } - {VALIGNQ "Align Doubleword/Quadword Vectors" } - {VBLENDMPD "Blend Float64/Float32 Vectors Using an OpMask Control" } - {VBLENDMPS "Blend Float64/Float32 Vectors Using an OpMask Control" } - {VBROADCAST "Load with Broadcast Floating-Point Data" } - {VCOMPRESSPD "Store Sparse Packed Double-Precision Floating-Point Values into Dense Memory" } - {VCOMPRESSPS "Store Sparse Packed Single-Precision Floating-Point Values into Dense Memory" } - {VCOMPRESSW "Store Sparse Packed Byte/Word Integer Values into Dense Memory/Register" } - {VCVTNE2PS2BF16 "Convert Two Packed Single Data to One Packed BF16 Data" } - {VCVTNEPS2BF16 "Convert Packed Single Data to Packed BF16 Data" } - {VCVTPD2QQ "Convert Packed Double-Precision Floating-Point Values to Packed Quadword Integers" } - {VCVTPD2UDQ "Convert Packed Double-Precision Floating-Point Values to Packed Unsigned Doubleword Integers" } - {VCVTPD2UQQ "Convert Packed Double-Precision Floating-Point Values to Packed Unsigned Quadword Integers" } - {VCVTPH2PS "Convert 16-bit FP values to Single-Precision FP values" } - {VCVTPS2PH "Convert Single-Precision FP value to 16-bit FP value" } - {VCVTPS2QQ "Convert Packed Single Precision Floating-Point Values to Packed Signed Quadword Integer Values" } - {VCVTPS2UDQ "Convert Packed Single-Precision Floating-Point Values to Packed Unsigned Doubleword Integer Values" } - {VCVTPS2UQQ "Convert Packed Single Precision Floating-Point Values to Packed Unsigned Quadword Integer Values" } - {VCVTQQ2PD "Convert Packed Quadword Integers to Packed Double-Precision Floating-Point Values" } - {VCVTQQ2PS "Convert Packed Quadword Integers to Packed Single-Precision Floating-Point Values" } - {VCVTSD2USI "Convert Scalar Double-Precision Floating-Point Value to Unsigned Doubleword Integer" } - {VCVTSS2USI "Convert Scalar Single-Precision Floating-Point Value to Unsigned Doubleword Integer" } - {VCVTTPD2QQ "Convert with Truncation Packed Double-Precision Floating-Point Values to Packed Quadword Integers" } - {VCVTTPD2UDQ "Convert with Truncation Packed Double-Precision Floating-Point Values to Packed Unsigned Doubleword Integers" } - {VCVTTPD2UQQ "Convert with Truncation Packed Double-Precision Floating-Point Values to Packed Unsigned Quadword Integers" } - {VCVTTPS2QQ "Convert with Truncation Packed Single Precision Floating-Point Values to Packed Signed Quadword Integer Values" } - {VCVTTPS2UDQ "Convert with Truncation Packed Single-Precision Floating-Point Values to Packed Unsigned Doubleword Integer Values" } - {VCVTTPS2UQQ "Convert with Truncation Packed Single Precision Floating-Point Values to Packed Unsigned Quadword Integer Values" } - {VCVTTSD2USI "Convert with Truncation Scalar Double-Precision Floating-Point Value to Unsigned Integer" } - {VCVTTSS2USI "Convert with Truncation Scalar Single-Precision Floating-Point Value to Unsigned Integer" } - {VCVTUDQ2PD "Convert Packed Unsigned Doubleword Integers to Packed Double-Precision Floating-Point Values" } - {VCVTUDQ2PS "Convert Packed Unsigned Doubleword Integers to Packed Single-Precision Floating-Point Values" } - {VCVTUQQ2PD "Convert Packed Unsigned Quadword Integers to Packed Double-Precision Floating-Point Values" } - {VCVTUQQ2PS "Convert Packed Unsigned Quadword Integers to Packed Single-Precision Floating-Point Values" } - {VCVTUSI2SD "Convert Unsigned Integer to Scalar Double-Precision Floating-Point Value" } - {VCVTUSI2SS "Convert Unsigned Integer to Scalar Single-Precision Floating-Point Value" } - {VDBPSADBW "Double Block Packed Sum-Absolute-Differences (SAD) on Unsigned Bytes" } - {VDPBF16PS "Dot Product of BF16 Pairs Accumulated into Packed Single Precision" } - {VERR "Verify a Segment for Reading or Writing" } - {VERW "Verify a Segment for Reading or Writing" } - {VEXPANDPD "Load Sparse Packed Double-Precision Floating-Point Values from Dense Memory" } - {VEXPANDPS "Load Sparse Packed Single-Precision Floating-Point Values from Dense Memory" } - {VEXTRACTF128 "Extr act Packed Floating-Point Values" } - {VEXTRACTF32x4 "Extr act Packed Floating-Point Values" } - {VEXTRACTF32x8 "Extr act Packed Floating-Point Values" } - {VEXTRACTF64x2 "Extr act Packed Floating-Point Values" } - {VEXTRACTF64x4 "Extr act Packed Floating-Point Values" } - {VEXTRACTI128 "Extract packed Integer Values" } - {VEXTRACTI32x4 "Extract packed Integer Values" } - {VEXTRACTI32x8 "Extract packed Integer Values" } - {VEXTRACTI64x2 "Extract packed Integer Values" } - {VEXTRACTI64x4 "Extract packed Integer Values" } - {VFIXUPIMMPD "Fix Up Special Packed Float64 Values" } - {VFIXUPIMMPS "Fix Up Special Packed Float32 Values" } - {VFIXUPIMMSD "Fix Up Special Scalar Float64 Value" } - {VFIXUPIMMSS "Fix Up Special Scalar Float32 Value" } - {VFMADD132PD "Fused Multiply-Add of Packed Double- Precision Floating-Point Values" } - {VFMADD132PS "Fused Multiply-Add of Packed Single- Precision Floating-Point Values" } - {VFMADD132SD "Fused Multiply-Add of Scalar Double- Precision Floating-Point Values" } - {VFMADD132SS "Fused Multiply-Add of Scalar Single-Precision Floating-Point Values" } - {VFMADD213PD "Fused Multiply-Add of Packed Double- Precision Floating-Point Values" } - {VFMADD213PS "Fused Multiply-Add of Packed Single- Precision Floating-Point Values" } - {VFMADD213SD "Fused Multiply-Add of Scalar Double- Precision Floating-Point Values" } - {VFMADD213SS "Fused Multiply-Add of Scalar Single-Precision Floating-Point Values" } - {VFMADD231PD "Fused Multiply-Add of Packed Double- Precision Floating-Point Values" } - {VFMADD231PS "Fused Multiply-Add of Packed Single- Precision Floating-Point Values" } - {VFMADD231SD "Fused Multiply-Add of Scalar Double- Precision Floating-Point Values" } - {VFMADD231SS "Fused Multiply-Add of Scalar Single-Precision Floating-Point Values" } - {VFMADDSUB132PD "Fused Multiply-Alternating Add/Subtract of Packed Double-Precision Floating-Point Values" } - {VFMADDSUB132PS "Fused Multiply-Alternating Add/Subtract of Packed Single-Precision Floating-Point Values" } - {VFMADDSUB213PD "Fused Multiply-Alternating Add/Subtract of Packed Double-Precision Floating-Point Values" } - {VFMADDSUB213PS "Fused Multiply-Alternating Add/Subtract of Packed Single-Precision Floating-Point Values" } - {VFMADDSUB231PD "Fused Multiply-Alternating Add/Subtract of Packed Double-Precision Floating-Point Values" } - {VFMADDSUB231PS "Fused Multiply-Alternating Add/Subtract of Packed Single-Precision Floating-Point Values" } - {VFMSUB132PD "Fused Multiply-Subtract of Packed Double- Precision Floating-Point Values" } - {VFMSUB132PS "Fused Multiply-Subtract of Packed Single- Precision Floating-Point Values" } - {VFMSUB132SD "Fused Multiply-Subtract of Scalar Double- Precision Floating-Point Values" } - {VFMSUB132SS "Fused Multiply-Subtract of Scalar Single- Precision Floating-Point Values" } - {VFMSUB213PD "Fused Multiply-Subtract of Packed Double- Precision Floating-Point Values" } - {VFMSUB213PS "Fused Multiply-Subtract of Packed Single- Precision Floating-Point Values" } - {VFMSUB213SD "Fused Multiply-Subtract of Scalar Double- Precision Floating-Point Values" } - {VFMSUB213SS "Fused Multiply-Subtract of Scalar Single- Precision Floating-Point Values" } - {VFMSUB231PD "Fused Multiply-Subtract of Packed Double- Precision Floating-Point Values" } - {VFMSUB231PS "Fused Multiply-Subtract of Packed Single- Precision Floating-Point Values" } - {VFMSUB231SD "Fused Multiply-Subtract of Scalar Double- Precision Floating-Point Values" } - {VFMSUB231SS "Fused Multiply-Subtract of Scalar Single- Precision Floating-Point Values" } - {VFMSUBADD132PD "Fused Multiply-Alternating Subtract/Add of Packed Double-Precision Floating-Point Values" } - {VFMSUBADD132PS "Fused Multiply-Alternating Subtract/Add of Packed Single-Precision Floating-Point Values" } - {VFMSUBADD213PD "Fused Multiply-Alternating Subtract/Add of Packed Double-Precision Floating-Point Values" } - {VFMSUBADD213PS "Fused Multiply-Alternating Subtract/Add of Packed Single-Precision Floating-Point Values" } - {VFMSUBADD231PD "Fused Multiply-Alternating Subtract/Add of Packed Double-Precision Floating-Point Values" } - {VFMSUBADD231PS "Fused Multiply-Alternating Subtract/Add of Packed Single-Precision Floating-Point Values" } - {VFNMADD132PD "Fused Negative Multiply-Add of Packed Double-Precision Floating-Point Values" } - {VFNMADD132PS "Fused Negative Multiply-Add of Packed Single-Precision Floating-Point Values" } - {VFNMADD132SD "Fused Negative Multiply-Add of Scalar Double-Precision Floating-Point Values" } - {VFNMADD132SS "Fused Negative Multiply-Add of Scalar Single-Precision Floating-Point Values" } - {VFNMADD213PD "Fused Negative Multiply-Add of Packed Double-Precision Floating-Point Values" } - {VFNMADD213PS "Fused Negative Multiply-Add of Packed Single-Precision Floating-Point Values" } - {VFNMADD213SD "Fused Negative Multiply-Add of Scalar Double-Precision Floating-Point Values" } - {VFNMADD213SS "Fused Negative Multiply-Add of Scalar Single-Precision Floating-Point Values" } - {VFNMADD231PD "Fused Negative Multiply-Add of Packed Double-Precision Floating-Point Values" } - {VFNMADD231PS "Fused Negative Multiply-Add of Packed Single-Precision Floating-Point Values" } - {VFNMADD231SD "Fused Negative Multiply-Add of Scalar Double-Precision Floating-Point Values" } - {VFNMADD231SS "Fused Negative Multiply-Add of Scalar Single-Precision Floating-Point Values" } - {VFNMSUB132PD "Fused Negative Multiply-Subtract of Packed Double-Precision Floating-Point Values" } - {VFNMSUB132PS "Fused Negative Multiply-Subtract of Packed Single-Precision Floating-Point Values" } - {VFNMSUB132SD "Fused Negative Multiply-Subtract of Scalar Double-Precision Floating-Point Values" } - {VFNMSUB132SS "Fused Negative Multiply-Subtract of Scalar Single-Precision Floating-Point Values" } - {VFNMSUB213PD "Fused Negative Multiply-Subtract of Packed Double-Precision Floating-Point Values" } - {VFNMSUB213PS "Fused Negative Multiply-Subtract of Packed Single-Precision Floating-Point Values" } - {VFNMSUB213SD "Fused Negative Multiply-Subtract of Scalar Double-Precision Floating-Point Values" } - {VFNMSUB213SS "Fused Negative Multiply-Subtract of Scalar Single-Precision Floating-Point Values" } - {VFNMSUB231PD "Fused Negative Multiply-Subtract of Packed Double-Precision Floating-Point Values" } - {VFNMSUB231PS "Fused Negative Multiply-Subtract of Packed Single-Precision Floating-Point Values" } - {VFNMSUB231SD "Fused Negative Multiply-Subtract of Scalar Double-Precision Floating-Point Values" } - {VFNMSUB231SS "Fused Negative Multiply-Subtract of Scalar Single-Precision Floating-Point Values" } - {VFPCLASSPD "Tests Types Of a Packed Float64 Values" } - {VFPCLASSPS "Tests Types Of a Packed Float32 Values" } - {VFPCLASSSD "Tests Types Of a Scalar Float64 Values" } - {VFPCLASSSS "Tests Types Of a Scalar Float32 Values" } - {VGATHERDPD "Gather Packed DP FP Values Using Signed Dword/Qword Indices" } - {VGATHERDPS "Gather Packed SP FP values Using Signed Dword/Qword Indices" } - {VGATHERQPD "Gather Packed DP FP Values Using Signed Dword/Qword Indices" } - {VGATHERQPS "Gather Packed SP FP values Using Signed Dword/Qword Indices" } - {VGETEXPPD "Convert Exponents of Packed DP FP Values to DP FP Values" } - {VGETEXPPS "Convert Exponents of Packed SP FP Values to SP FP Values" } - {VGETEXPSD "Convert Exponents of Scalar DP FP Values to DP FP Value" } - {VGETEXPSS "Convert Exponents of Scalar SP FP Values to SP FP Value" } - {VGETMANTPD "Extract Float64 Vector of Normalized Mantissas from Float64 Vector" } - {VGETMANTPS "Extract Float32 Vector of Normalized Mantissas from Float32 Vector" } - {VGETMANTSD "Extract Float64 of Normalized Mantissas from Float64 Scalar" } - {VGETMANTSS "Extract Float32 Vector of Normalized Mantissa from Float32 Vector" } - {VINSERTF128 "Insert Packed Floating-Point Values" } - {VINSERTF32x4 "Insert Packed Floating-Point Values" } - {VINSERTF32x8 "Insert Packed Floating-Point Values" } - {VINSERTF64x2 "Insert Packed Floating-Point Values" } - {VINSERTF64x4 "Insert Packed Floating-Point Values" } - {VINSERTI128 "Insert Packed Integer Values" } - {VINSERTI32x4 "Insert Packed Integer Values" } - {VINSERTI32x8 "Insert Packed Integer Values" } - {VINSERTI64x2 "Insert Packed Integer Values" } - {VINSERTI64x4 "Insert Packed Integer Values" } - {VMASKMOV "Conditional SIMD Packed Loads and Stores" } - {VMOVDQA32 "Move Aligned Packed Integer Values" } - {VMOVDQA64 "Move Aligned Packed Integer Values" } - {VMOVDQU16 "Move Unaligned Packed Integer Values" } - {VMOVDQU32 "Move Unaligned Packed Integer Values" } - {VMOVDQU64 "Move Unaligned Packed Integer Values" } - {VMOVDQU8 "Move Unaligned Packed Integer Values" } - {VP2INTERSECTD "Compute Intersection Between DWORDS/QUADWORDS to a Pair of Mask Registers" } - {VP2INTERSECTQ "Compute Intersection Between DWORDS/QUADWORDS to a Pair of Mask Registers" } - {VPBLENDD "Blend Packed Dwords" } - {VPBLENDMB "Blend Byte/Word Vectors Using an Opmask Control" } - {VPBLENDMD "Blend Int32/Int64 Vectors Using an OpMask Control" } - {VPBLENDMQ "Blend Int32/Int64 Vectors Using an OpMask Control" } - {VPBLENDMW "Blend Byte/Word Vectors Using an Opmask Control" } - {VPBROADCAST "Load Integer and Broadcast" } - {VPBROADCASTB "Load with Broadcast Integer Data from General Purpose Register" } - {VPBROADCASTD "Load with Broadcast Integer Data from General Purpose Register" } - {VPBROADCASTM "Broadcast Mask to Vector Register" } - {VPBROADCASTQ "Load with Broadcast Integer Data from General Purpose Register" } - {VPBROADCASTW "Load with Broadcast Integer Data from General Purpose Register" } - {VPCMPB "Compare Packed Byte Values Into Mask" } - {VPCMPD "Compare Packed Integer Values into Mask" } - {VPCMPQ "Compare Packed Integer Values into Mask" } - {VPCMPUB "Compare Packed Byte Values Into Mask" } - {VPCMPUD "Compare Packed Integer Values into Mask" } - {VPCMPUQ "Compare Packed Integer Values into Mask" } - {VPCMPUW "Compare Packed Word Values Into Mask" } - {VPCMPW "Compare Packed Word Values Into Mask" } - {VPCOMPRESSB "Store Sparse Packed Byte/Word Integer Values into Dense Memory/Register" } - {VPCOMPRESSD "Store Sparse Packed Doubleword Integer Values into Dense Memory/Register" } - {VPCOMPRESSQ "Store Sparse Packed Quadword Integer Values into Dense Memory/Register" } - {VPCONFLICTD "Detect Conflicts Within a Vector of Packed Dword/Qword Values into Dense Memory/ Register" } - {VPCONFLICTQ "Detect Conflicts Within a Vector of Packed Dword/Qword Values into Dense Memory/ Register" } - {VPDPBUSD "Multiply and Add Unsigned and Signed Bytes" } - {VPDPBUSDS "Multiply and Add Unsigned and Signed Bytes with Saturation" } - {VPDPWSSD "Multiply and Add Signed Word Integers" } - {VPDPWSSDS "Multiply and Add Signed Word Integers with Saturation" } - {VPERM2F128 "Permute Floating-Point Values" } - {VPERM2I128 "Permute Integer Values" } - {VPERMB "Permute Packed Bytes Elements" } - {VPERMD "Permute Packed Doublewords/Words Elements" } - {VPERMI2B "Full Permute of Bytes from Two Tables Overwriting the Index" } - {VPERMI2D "Full Permute From Two Tables Overwriting the Index" } - {VPERMI2PD "Full Permute From Two Tables Overwriting the Index" } - {VPERMI2PS "Full Permute From Two Tables Overwriting the Index" } - {VPERMI2Q "Full Permute From Two Tables Overwriting the Index" } - {VPERMI2W "Full Permute From Two Tables Overwriting the Index" } - {VPERMILPD "Permute In-Lane of Pairs of Double-Precision Floating-Point Values" } - {VPERMILPS "Permute In-Lane of Quadruples of Single-Precision Floating-Point Values" } - {VPERMPD "Permute Double-Precision Floating-Point Elements" } - {VPERMPS "Permute Single-Precision Floating-Point Elements" } - {VPERMQ "Qwords Element Permutation" } - {VPERMT2B "Full Permute of Bytes from Two Tables Overwriting a Table" } - {VPERMT2D "Full Permute from Two Tables Overwriting one Table" } - {VPERMT2PD "Full Permute from Two Tables Overwriting one Table" } - {VPERMT2PS "Full Permute from Two Tables Overwriting one Table" } - {VPERMT2Q "Full Permute from Two Tables Overwriting one Table" } - {VPERMT2W "Full Permute from Two Tables Overwriting one Table" } - {VPERMW "Permute Packed Doublewords/Words Elements" } - {VPEXPANDB "Expand Byte/Word Values" } - {VPEXPANDD "Load Sparse Packed Doubleword Integer Values from Dense Memory / Register" } - {VPEXPANDQ "Load Sparse Packed Quadword Integer Values from Dense Memory / Register" } - {VPEXPANDW "Expand Byte/Word Values" } - {VPGATHERDD "Gather Packed Dword Values Using Signed Dword/Qword Indices" } - {VPGATHERDQ "Gather Packed Dword, Packed Qword with Signed Dword Indices" } - {VPGATHERQD "Gather Packed Dword Values Using Signed Dword/Qword Indices" } - {VPGATHERQQ "Gather Packed Qword Values Using Signed Dword/Qword Indices" } - {VPLZCNTD "Count the Number of Leading Zero Bits for Packed Dword, Packed Qword Values" } - {VPLZCNTQ "Count the Number of Leading Zero Bits for Packed Dword, Packed Qword Values" } - {VPMADD52HUQ "Packed Multiply of Unsigned 52-bit Unsigned Integers and Add High 52-bit Products to 64-bit Accumulators" } - {VPMADD52LUQ "Packed Multiply of Unsigned 52-bit Integers and Add the Low 52-bit Products to Qword Accumulators" } - {VPMASKMOV "Conditional SIMD Integer Packed Loads and Stores" } - {VPMOVB2M "Convert a Vector Register to a Mask" } - {VPMOVD2M "Convert a Vector Register to a Mask" } - {VPMOVDB "Down Convert DWord to Byte" } - {VPMOVDW "Down Convert DWord to Word" } - {VPMOVM2B "Convert a Mask Register to a Vector Register" } - {VPMOVM2D "Convert a Mask Register to a Vector Register" } - {VPMOVM2Q "Convert a Mask Register to a Vector Register" } - {VPMOVM2W "Convert a Mask Register to a Vector Register" } - {VPMOVQ2M "Convert a Vector Register to a Mask" } - {VPMOVQB "Down Convert QWord to Byte" } - {VPMOVQD "Down Convert QWord to DWord" } - {VPMOVQW "Down Convert QWord to Word" } - {VPMOVSDB "Down Convert DWord to Byte" } - {VPMOVSDW "Down Convert DWord to Word" } - {VPMOVSQB "Down Convert QWord to Byte" } - {VPMOVSQD "Down Convert QWord to DWord" } - {VPMOVSQW "Down Convert QWord to Word" } - {VPMOVSWB "Down Convert Word to Byte" } - {VPMOVUSDB "Down Convert DWord to Byte" } - {VPMOVUSDW "Down Convert DWord to Word" } - {VPMOVUSQB "Down Convert QWord to Byte" } - {VPMOVUSQD "Down Convert QWord to DWord" } - {VPMOVUSQW "Down Convert QWord to Word" } - {VPMOVUSWB "Down Convert Word to Byte" } - {VPMOVW2M "Convert a Vector Register to a Mask" } - {VPMOVWB "Down Convert Word to Byte" } - {VPMULTISHIFTQB "Select Packed Unaligned Bytes from Quadword Sources" } - {VPOPCNT "Return the Count of Number of Bits Set to 1 in BYTE/WORD/DWORD/QWORD" } - {VPROLD "Bit Rotate Left" } - {VPROLQ "Bit Rotate Left" } - {VPROLVD "Bit Rotate Left" } - {VPROLVQ "Bit Rotate Left" } - {VPRORD "Bit Rotate Right" } - {VPRORQ "Bit Rotate Right" } - {VPRORVD "Bit Rotate Right" } - {VPRORVQ "Bit Rotate Right" } - {VPSCATTERDD "Scatter Packed Dword, Packed Qword with Signed Dword, Signed Qword Indices" } - {VPSCATTERDQ "Scatter Packed Dword, Packed Qword with Signed Dword, Signed Qword Indices" } - {VPSCATTERQD "Scatter Packed Dword, Packed Qword with Signed Dword, Signed Qword Indices" } - {VPSCATTERQQ "Scatter Packed Dword, Packed Qword with Signed Dword, Signed Qword Indices" } - {VPSHLD "Concatenate and Shift Packed Data Left Logical" } - {VPSHLDV "Concatenate and Variable Shift Packed Data Left Logical" } - {VPSHRD "Concatenate and Shift Packed Data Right Logical" } - {VPSHRDV "Concatenate and Variable Shift Packed Data Right Logical" } - {VPSHUFBITQMB "Shuffle Bits from Quadword Elements Using Byte Indexes into Mask" } - {VPSLLVD "Variable Bit Shift Left Logical" } - {VPSLLVQ "Variable Bit Shift Left Logical" } - {VPSLLVW "Variable Bit Shift Left Logical" } - {VPSRAVD "Variable Bit Shift Right Arithmetic" } - {VPSRAVQ "Variable Bit Shift Right Arithmetic" } - {VPSRAVW "Variable Bit Shift Right Arithmetic" } - {VPSRLVD "Variable Bit Shift Right Logical" } - {VPSRLVQ "Variable Bit Shift Right Logical" } - {VPSRLVW "Variable Bit Shift Right Logical" } - {VPTERNLOGD "Bitwise Ternary Logic" } - {VPTERNLOGQ "Bitwise Ternary Logic" } - {VPTESTMB "Logical AND and Set Mask" } - {VPTESTMD "Logical AND and Set Mask" } - {VPTESTMQ "Logical AND and Set Mask" } - {VPTESTMW "Logical AND and Set Mask" } - {VPTESTNMB "Logical NAND and Set" } - {VPTESTNMD "Logical NAND and Set" } - {VPTESTNMQ "Logical NAND and Set" } - {VPTESTNMW "Logical NAND and Set" } - {VRANGEPD "Range Restriction Calculation For Packed Pairs of Float64 Values" } - {VRANGEPS "Range Restriction Calculation For Packed Pairs of Float32 Values" } - {VRANGESD "Range Restriction Calculation From a pair of Scalar Float64 Values" } - {VRANGESS "Range Restriction Calculation From a Pair of Scalar Float32 Values" } - {VRCP14PD "Compute Approximate Reciprocals of Packed Float64 Values" } - {VRCP14PS "Compute Approximate Reciprocals of Packed Float32 Values" } - {VRCP14SD "Compute Approximate Reciprocal of Scalar Float64 Value" } - {VRCP14SS "Compute Approximate Reciprocal of Scalar Float32 Value" } - {VREDUCEPD "Perform Reduction Transformation on Packed Float64 Values" } - {VREDUCEPS "Perform Reduction Transformation on Packed Float32 Values" } - {VREDUCESD "Perform a Reduction Transformation on a Scalar Float64 Value" } - {VREDUCESS "Perform a Reduction Transformation on a Scalar Float32 Value" } - {VRNDSCALEPD "Round Packed Float64 Values To Include A Given Number Of Fraction Bits" } - {VRNDSCALEPS "Round Packed Float32 Values To Include A Given Number Of Fraction Bits" } - {VRNDSCALESD "Round Scalar Float64 Value To Include A Given Number Of Fraction Bits" } - {VRNDSCALESS "Round Scalar Float32 Value To Include A Given Number Of Fraction Bits" } - {VRSQRT14PD "Compute Approximate Reciprocals of Square Roots of Packed Float64 Values" } - {VRSQRT14PS "Compute Approximate Reciprocals of Square Roots of Packed Float32 Values" } - {VRSQRT14SD "Compute Approximate Reciprocal of Square Root of Scalar Float64 Value" } - {VRSQRT14SS "Compute Approximate Reciprocal of Square Root of Scalar Float32 Value" } - {VSCALEFPD "Scale Packed Float64 Values With Float64 Values" } - {VSCALEFPS "Scale Packed Float32 Values With Float32 Values" } - {VSCALEFSD "Scale Scalar Float64 Values With Float64 Values" } - {VSCALEFSS "Scale Scalar Float32 Value With Float32 Value" } - {VSCATTERDPD "Scatter Packed Single, Packed Double with Signed Dword and Qword Indices" } - {VSCATTERDPS "Scatter Packed Single, Packed Double with Signed Dword and Qword Indices" } - {VSCATTERQPD "Scatter Packed Single, Packed Double with Signed Dword and Qword Indices" } - {VSCATTERQPS "Scatter Packed Single, Packed Double with Signed Dword and Qword Indices" } - {VSHUFF32x4 "Shuffle Packed Values at 128-bit Granularity" } - {VSHUFF64x2 "Shuffle Packed Values at 128-bit Granularity" } - {VSHUFI32x4 "Shuffle Packed Values at 128-bit Granularity" } - {VSHUFI64x2 "Shuffle Packed Values at 128-bit Granularity" } - {VTESTPD "Packed Bit Test" } - {VTESTPS "Packed Bit Test" } - {VZEROALL "Zero XMM, YMM and ZMM Registers" } - {VZEROUPPER "Zero Upper Bits of YMM and ZMM Registers" } - {WAIT "Wait" } - {WBINVD "Write Back and Invalidate Cache" } - {WBNOINVD "Write Back and Do Not Invalidate Cache" } - {WRFSBASE "Write FS/GS Segment Base" } - {WRGSBASE "Write FS/GS Segment Base" } - {WRMSR "Write to Model Specific Register" } - {WRPKRU "Write Data to User Page Key Register" } - {WRSSD "Write to Shadow Stack" } - {WRSSQ "Write to Shadow Stack" } - {WRUSSD "Write to User Shadow Stack" } - {WRUSSQ "Write to User Shadow Stack" } - {XABORT "Transactional Abort" } - {XACQUIRE "Hardware Lock Elision Prefix Hints" } - {XADD "Exchange and Add" } - {XBEGIN "Transactional Begin" } - {XCHG "Exchange Register/Memory with Register" } - {XEND "Transactional End" } - {XGETBV "Get Value of Extended Control Register" } - {XLAT "Table Look-up Translation" } - {XLATB "Table Look-up Translation" } - {XOR "Logical Exclusive OR" } - {XORPD "Bitwise Logical XOR of Packed Double Precision Floating-Point Values" } - {XORPS "Bitwise Logical XOR of Packed Single Precision Floating-Point Values" } - {XRELEASE "Hardware Lock Elision Prefix Hints" } - {XRSTOR "Restore Processor Extended States" } - {XRSTORS "Restore Processor Extended States Supervisor" } - {XSAVE "Save Processor Extended States" } - {XSAVEC "Save Processor Extended States with Compaction" } - {XSAVEOPT "Save Processor Extended States Optimized" } - {XSAVES "Save Processor Extended States Supervisor" } - {XSETBV "Set Extended Control Register" } - {XTEST "Test If In Transactional Execution" } - - //- rjf: sgx - {ENCLS "Execute an Enclave System Function of Specified Leaf Number" } - {ENCLS "[EADD] Add a Page to an Uninitialized Enclave" } - {ENCLS "[EAUG] Add a Page to an Initialized Enclave" } - {ENCLS "[EBLOCK] Mark a page in EPC as Blocked" } - {ENCLS "[ECREATE] Create an SECS page in the Enclave Page Cache" } - {ENCLS "[EDBGRD] Read From a Debug Enclave" } - {ENCLS "[EDBGWR] Write to a Debug Enclave" } - {ENCLS "[EEXTEND] Extend Uninitialized Enclave Measurement by 256 Bytes" } - {ENCLS "[EINIT] Initialize an Enclave for Execution" } - {ENCLS "[ELDBC] Load an EPC Page and Mark its State" } - {ENCLS "[ELDB] Load an EPC Page and Mark its State" } - {ENCLS "[ELDUC] Load an EPC Page and Mark its State" } - {ENCLS "[ELDU] Load an EPC Page and Mark its State" } - {ENCLS "[EMODPR] Restrict the Permissions of an EPC Page" } - {ENCLS "[EMODT] Change the Type of an EPC Page" } - {ENCLS "[EPA] Add Version Array" } - {ENCLS "[ERDINFO] Read Type and Status Information About an EPC Page" } - {ENCLS "[EREMOVE] Remove a page from the EPC" } - {ENCLS "[ETRACKC] Activates EBLOCK Checks" } - {ENCLS "[ETRACK] Activates EBLOCK Checks" } - {ENCLS "[EWB] Invalidate an EPC Page and Write out to Main Memory" } - {ENCLU "Execute an Enclave User Function of Specified Leaf Number" } - {ENCLU "[EACCEPTCOPY] Initialize a Pending Page" } - {ENCLU "[EACCEPT] Accept Changes to an EPC Page" } - {ENCLU "[EENTER] Enters an Enclave" } - {ENCLU "[EEXIT] Exits an Enclave" } - {ENCLU "[EGETKEY] Retrieves a Cryptographic Key" } - {ENCLU "[EMODPE] Extend an EPC Page Permissions" } - {ENCLU "[EREPORT] Create a Cryptographic Report of the Enclave" } - {ENCLU "[ERESUME] Re-Enters an Enclave" } - {ENCLV "Execute an Enclave VMM Function of Specified Leaf Number" } - - //- rjf: vmx - {INVEPT "Invalidate Translations Derived from EPT" } - {INVVPID "Invalidate Translations Based on VPID" } - {VMCALL "Call to VM Monitor" } - {VMCLEAR "Clear Virtual-Machine Control Structure" } - {VMFUNC "Invoke VM function" } - {VMLAUNCH "Launch/Resume Virtual Machine" } - {VMPTRLD "Load Pointer to Virtual-Machine Control Structure" } - {VMPTRST "Store Pointer to Virtual-Machine Control Structure" } - {VMREAD "Read Field from Virtual-Machine Control Structure" } - {VMRESUME "Launch/Resume Virtual Machine" } - {VMWRITE "Write Field to Virtual-Machine Control Structure" } - {VMXOFF "Leave VMX Operation" } - {VMXON "Enter VMX Operation" } - - //- rjf: xeon phi - {PREFETCHWT1 "Prefetch Vector Data Into Caches with Intent to Write and T1 Hint" } - {V4FMADDPS "Packed Single-Precision Floating-Point Fused Multiply-Add (4-iterations)" } - {V4FMADDSS "Scalar Single-Precision Floating-Point Fused Multiply-Add (4-iterations)" } - {V4FNMADDPS "Packed Single-Precision Floating-Point Fused Multiply-Add (4-iterations)" } - {V4FNMADDSS "Scalar Single-Precision Floating-Point Fused Multiply-Add (4-iterations)" } - {VEXP2PD "Approximation to the Exponential 2^x of Packed Double-Precision Floating-Point Values with Less Than 2^-23 Relative Error"} - {VEXP2PS "Approximation to the Exponential 2^x of Packed Single-Precision Floating-Point Values with Less Than 2^-23 Relative Error"} - {VGATHERPF0DPD "Sparse Prefetch Packed SP/DP Data Values with Signed Dword, Signed Qword Indices Using T0 Hint" } - {VGATHERPF0DPS "Sparse Prefetch Packed SP/DP Data Values with Signed Dword, Signed Qword Indices Using T0 Hint" } - {VGATHERPF0QPD "Sparse Prefetch Packed SP/DP Data Values with Signed Dword, Signed Qword Indices Using T0 Hint" } - {VGATHERPF0QPS "Sparse Prefetch Packed SP/DP Data Values with Signed Dword, Signed Qword Indices Using T0 Hint" } - {VGATHERPF1DPD "Sparse Prefetch Packed SP/DP Data Values with Signed Dword, Signed Qword Indices Using T1 Hint" } - {VGATHERPF1DPS "Sparse Prefetch Packed SP/DP Data Values with Signed Dword, Signed Qword Indices Using T1 Hint" } - {VGATHERPF1QPD "Sparse Prefetch Packed SP/DP Data Values with Signed Dword, Signed Qword Indices Using T1 Hint" } - {VGATHERPF1QPS "Sparse Prefetch Packed SP/DP Data Values with Signed Dword, Signed Qword Indices Using T1 Hint" } - {VP4DPWSSD "Dot Product of Signed Words with Dword Accumulation (4-iterations)" } - {VP4DPWSSDS "Dot Product of Signed Words with Dword Accumulation and Saturation (4-iterations)" } - {VRCP28PD "Approximation to the Reciprocal of Packed Double-Precision Floating-Point Values with Less Than 2^-28 Relative Error" } - {VRCP28PS "Approximation to the Reciprocal of Packed Single-Precision Floating-Point Values with Less Than 2^-28 Relative Error" } - {VRCP28SD "Approximation to the Reciprocal of Scalar Double-Precision Floating-Point Value with Less Than 2^-28 Relative Error" } - {VRCP28SS "Approximation to the Reciprocal of Scalar Single-Precision Floating-Point Value with Less Than 2^-28 Relative Error" } - {VRSQRT28PD "Approximation to the Reciprocal Square Root of Packed Double-Precision Floating-Point Values with Less Than 2^-28 Relative Error"} - {VRSQRT28PS "Approximation to the Reciprocal Square Root of Packed Single-Precision Floating-Point Values with Less Than 2^-28 Relative Error"} - {VRSQRT28SD "Approximation to the Reciprocal Square Root of Scalar Double-Precision Floating-Point Value with Less Than 2^-28 Relative Error"} - {VRSQRT28SS "Approximation to the Reciprocal Square Root of Scalar Single-Precision Floating- Point Value with Less Than 2^-28 Relative Error"} - {VSCATTERPF0DPD "Sparse Prefetch Packed SP/DP Data Values with Signed Dword, Signed Qword Indices Using T0 Hint with Intent to Write" } - {VSCATTERPF0DPS "Sparse Prefetch Packed SP/DP Data Values with Signed Dword, Signed Qword Indices Using T0 Hint with Intent to Write" } - {VSCATTERPF0QPD "Sparse Prefetch Packed SP/DP Data Values with Signed Dword, Signed Qword Indices Using T0 Hint with Intent to Write" } - {VSCATTERPF0QPS "Sparse Prefetch Packed SP/DP Data Values with Signed Dword, Signed Qword Indices Using T0 Hint with Intent to Write" } - {VSCATTERPF1DPD "Sparse Prefetch Packed SP/DP Data Values with Signed Dword, Signed Qword Indices Using T1 Hint with Intent to Write" } - {VSCATTERPF1DPS "Sparse Prefetch Packed SP/DP Data Values with Signed Dword, Signed Qword Indices Using T1 Hint with Intent to Write" } - {VSCATTERPF1QPD "Sparse Prefetch Packed SP/DP Data Values with Signed Dword, Signed Qword Indices Using T1 Hint with Intent to Write" } - {VSCATTERPF1QPS "Sparse Prefetch Packed SP/DP Data Values with Signed Dword, Signed Qword Indices Using T1 Hint with Intent to Write" } - -} - -//////////////////////////////// -//~ rjf: Developer Toggles - -@table(name) -DF_DevToggleTable: -{ - {telemetry_capture} - {simulate_lag} - {draw_ui_text_pos} - {draw_ui_focus_debug} - {draw_ui_box_heatmap} - {eval_compiler_tooltips} - {eval_watch_key_tooltips} - {cmd_context_tooltips} - {scratch_mouse_draw} - {updating_indicator} -} - -//////////////////////////////// -//~ rjf: Generators - -//- rjf: enums - -@enum DF_CfgSrc: -{ - @expand(DF_CfgSrcTable a) `$(a.name)`, - COUNT, -} - -@enum DF_EntityKind: -{ - @expand(DF_EntityKindTable a) `$(a.name)`, - COUNT, -} - -@enum DF_CoreCmdKind: -{ - @expand(DF_CoreCmdTable, a) `$(a.name)`, - COUNT, -} - -@enum DF_IconKind: -{ - @expand(DF_IconTable a) `$(a.name)`, - COUNT, -} - -@enum DF_CoreViewRuleKind: -{ - @expand(DF_CoreViewRuleTable a) `$(a.name)`, - COUNT, -} - -//- rjf: command params - -@enum DF_CmdParamSlot: -{ - Null, - @expand(DF_CmdParamSlotTable a) `$(a.name)`, - COUNT, -} - -@struct DF_CmdParams: -{ - `U64 slot_props[(DF_CmdParamSlot_COUNT + 63) / 64]`; - @expand(DF_CmdParamSlotTable a) `$(a.c_type) $(a.name_lower)`; -} - -@data(Rng1U64) df_g_cmd_param_slot_range_table: -{ - `{0}`, - @expand(DF_CmdParamSlotTable a) `{OffsetOf(DF_CmdParams, $(a.name_lower)), OffsetOf(DF_CmdParams, $(a.name_lower)) + sizeof($(a.c_type))}`, -} - -//- rjf: entity kind tables - -@data(DF_IconKind) df_g_entity_kind_icon_kind_table: -{ - @expand(DF_EntityKindTable a) `DF_IconKind_$(a.icon_kind)`, -} - -@data(String8) df_g_entity_kind_display_string_table: -{ - @expand(DF_EntityKindTable a) `str8_lit_comp("$(a.display_string)")`, -} - -@data(String8) df_g_entity_kind_name_label_table: -{ - @expand(DF_EntityKindTable a) `str8_lit_comp("$(a.name_label)")`, -} - -@data(DF_EntityKindFlags) df_g_entity_kind_flags_table: -{ - @expand(DF_EntityKindTable a) `($(a.lf_mut_user_cfg)*DF_EntityKindFlag_LeafMutationUserConfig | $(a.lf_mut_prof_cfg)*DF_EntityKindFlag_LeafMutationProjectConfig | $(a.lf_mut_halt)*DF_EntityKindFlag_LeafMutationSoftHalt | $(a.lf_mut_dbg)*DF_EntityKindFlag_LeafMutationDebugInfoMap | $(a.tr_mut_user_cfg)*DF_EntityKindFlag_TreeMutationUserConfig | $(a.tr_mut_prof_cfg)*DF_EntityKindFlag_TreeMutationProjectConfig | $(a.tr_mut_halt)*DF_EntityKindFlag_TreeMutationSoftHalt | $(a.tr_mut_dbg)*DF_EntityKindFlag_TreeMutationDebugInfoMap | $(a.name_is_code)*DF_EntityKindFlag_NameIsCode | $(a.user_lifetime)*DF_EntityKindFlag_UserDefinedLifetime)`, -} - -@data(DF_EntityOpFlags) df_g_entity_kind_op_flags_table: -{ - @expand(DF_EntityKindTable a) `($(a.op_delete)*DF_EntityOpFlag_Delete) | ($(a.op_freeze)*DF_EntityOpFlag_Freeze) | ($(a.op_edit)*DF_EntityOpFlag_Edit) | ($(a.op_rename)*DF_EntityOpFlag_Rename) | ($(a.op_enable)*DF_EntityOpFlag_Enable) | ($(a.op_cond)*DF_EntityOpFlag_Condition) | ($(a.op_dup)*DF_EntityOpFlag_Duplicate)`, -} - -//- rjf: config source tables - -@data(String8) df_g_cfg_src_string_table: -{ - @expand(DF_CfgSrcTable a) `str8_lit_comp("$(a.string)")`, -} - -@data(DF_CoreCmdKind) df_g_cfg_src_load_cmd_kind_table: -{ - @expand(DF_CfgSrcTable a) `DF_CoreCmdKind_$(a.load_cmd)`, -} - -@data(DF_CoreCmdKind) df_g_cfg_src_write_cmd_kind_table: -{ - @expand(DF_CfgSrcTable a) `DF_CoreCmdKind_$(a.write_cmd)`, -} - -@data(DF_CoreCmdKind) df_g_cfg_src_apply_cmd_kind_table: -{ - @expand(DF_CfgSrcTable a) `DF_CoreCmdKind_$(a.apply_cmd)`; -} - -//- rjf: core view rule function prototypes - -@gen -{ - @expand(DF_CoreViewRuleTable a) `$(a.er == "x" -> "DF_CORE_VIEW_RULE_EVAL_RESOLUTION_FUNCTION_DEF(" .. a.name_lower .. ");")`; - @expand(DF_CoreViewRuleTable a) `$(a.vb == "x" -> "DF_CORE_VIEW_RULE_VIZ_BLOCK_PROD_FUNCTION_DEF(" .. a.name_lower .. ");")`; -} - -//- rjf: core command kind tables - -@data(DF_CmdSpecInfo) @c_file df_g_core_cmd_kind_spec_info_table: -{ - @expand(DF_CoreCmdTable, a) - ```{ str8_lit_comp("$(a.string)"), str8_lit_comp("$(a.desc)"), str8_lit_comp("$(a.search_tags)"), str8_lit_comp("$(a.display_name)"), (DF_CmdSpecFlag_OmitFromLists*$(a.lister_omit)), {DF_CmdParamSlot_$(a.q_slot), DF_EntityKind_$(a.q_ent_kind), (DF_CmdQueryFlag_AllowFiles*$(a.q_allow_files))|(DF_CmdQueryFlag_AllowFolders*$(a.q_allow_folders))|(DF_CmdQueryFlag_CodeInput*$(a.q_is_code))|(DF_CmdQueryFlag_KeepOldInput*$(a.q_keep_oi))|(DF_CmdQueryFlag_SelectOldInput*$(a.q_select_oi))|(DF_CmdQueryFlag_Required*$(a.q_required))}, DF_IconKind_$(a.canonical_icon)}```; -} - -//- rjf: core view rule tables - -@data(DF_CoreViewRuleSpecInfo) @c_file df_g_core_view_rule_spec_info_table: -{ - @expand(DF_CoreViewRuleTable a) - ```{str8_lit_comp("$(a.string)"), str8_lit_comp("$(a.display_name)"), str8_lit_comp("$(a.schema)"), str8_lit_comp("$(a.description)"), (DF_CoreViewRuleSpecInfoFlag_Inherited*$(a.ih == "x"))|(DF_CoreViewRuleSpecInfoFlag_Expandable*$(a.ex == "x"))|(DF_CoreViewRuleSpecInfoFlag_EvalResolution*$(a.er == "x"))|(DF_CoreViewRuleSpecInfoFlag_VizBlockProd*$(a.vb == "x")), $(a.er == "x" -> "DF_CORE_VIEW_RULE_EVAL_RESOLUTION_FUNCTION_NAME("..a.name_lower..")") $(a.er != "x" -> 0), $(a.vb == "x" -> "DF_CORE_VIEW_RULE_VIZ_BLOCK_PROD_FUNCTION_NAME("..a.name_lower..")") $(a.vb != "x" -> 0), }```; -} - -//- rjf: icon kinds - -@data(String8) df_g_icon_kind_text_table: -{ - @expand(DF_IconTable a) `str8_lit_comp("$(a.text)")`; -} - -//- rjf: instruction metadata table - -@gen -{ - ``; - `struct{String8 mnemonic; String8 summary;} df_g_inst_table_x64[] =`; - `{`; - @expand(DF_InstTableX64 a) `{str8_lit_comp("$(a.name)"), str8_lit_comp("$(a.summary)")},`; - `};`; - ``; -} - -//- rjf: developer toggles - -@gen -{ - @expand(DF_DevToggleTable a) `global B32 DEV_$(a.name) = 0;` -} - -@gen -{ - `struct {B32 *value_ptr; String8 name;} DEV_toggle_table[] =`; - `{`; - @expand(DF_DevToggleTable a) `{&DEV_$(a.name), str8_lit_comp("$(a.name)")},` - `};`; -} +// Copyright (c) 2024 Epic Games Tools +// Licensed under the MIT license (https://opensource.org/license/mit/) + +//////////////////////////////// +//~ rjf: Config Sources + +@table(string, name, load_cmd, write_cmd, apply_cmd) +DF_CfgSrcTable: +{ + {"user" User OpenUser WriteUserData ApplyUserData } + {"project" Project OpenProject WriteProjectData ApplyProjectData } + {"command_line" CommandLine Null Null Null } + {"transient" Transient Null Null Null } +} + +//////////////////////////////// +//~ rjf: Entity Kind Tables + +@table(name name_lower op_delete op_freeze op_edit op_rename op_enable op_cond op_dup lf_mut_user_cfg tr_mut_user_cfg lf_mut_prof_cfg tr_mut_prof_cfg lf_mut_halt lf_mut_dbg tr_mut_halt tr_mut_dbg name_is_code user_lifetime name_label icon_kind display_string) +DF_EntityKindTable: +{ + {Nil nil 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 "Label" Null "Nil" } + {Root root 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 "Label" Null "Root" } + {Machine machine 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 "Label" Machine "Machine" } + + //- rjf: filesystem modeling + {File file 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 "Label" FileOutline "File" } + {OverrideFileLink override_file_link 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 "Label" FileOutline "Override File Link" } + + //- rjf: auto view rules + {AutoViewRule auto_view_rule 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 "Label" Binoculars "Auto View Rule" } + + //- rjf: watch pins + {WatchPin watch_pin 1 0 0 1 0 0 1 0 0 0 0 0 0 0 0 1 1 "Expression" Pin "Watch Pin" } + + //- rjf: breakpoints + {Breakpoint breakpoint 1 0 0 1 1 1 1 0 0 1 0 1 0 0 0 0 1 "Label" CircleFilled "Breakpoint" } + {Condition condition 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 1 1 "Expression" CircleFilled "Condition" } + + //- rjf: targets + {Target target 1 0 1 1 1 0 1 0 0 1 0 0 0 0 0 0 1 "Label" Target "Target" } + {Executable executable 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 "Executable" Null "Executable" } + {Arguments arguments 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 "Arguments" Null "Arguments" } + {ExecutionPath execution_path 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 "Execution Path" Null "Execution Path" } + {EntryPointName entry_point_name 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 1 "Symbol Name" Null "Entry Point Name" } + + //- rjf: recent projects + {RecentProject recent_project 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 "Path" Briefcase "Recent Project" } + + //- rjf: src -> dst mapping + {Source source 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 "Path" Null "Source" } + {Dest dest 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 "Path" Null "Destination" } + + //- rjf: control system entities + {Process process 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 "Label" Threads "Process" } + {Thread thread 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 "Label" Thread "Thread" } + {Module module 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 "Label" Module "Module" } + {PendingThreadName pending_thread_name 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 "Label" Threads "Pending Thread Name" } + {DebugInfoPath debug_info_path 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 "Label" Module "Debug Info Path" } + + //- rjf: parser task entities + {ConversionTask conversion_task 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 "Label" Null "Conversion Task" } + {ConversionFail conversion_fail 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 "Label" Null "Conversion Failure" } + + //- rjf: history + {EndedProcess ended_process 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 "Label" Null "EndedProcess" } +} + +//////////////////////////////// +//~ rjf: Built-In Command Tables + +@table(name, name_lower, c_type) +DF_CmdParamSlotTable: +{ + {Window window `DF_Handle`} + {Panel panel `DF_Handle`} + {DestPanel dest_panel `DF_Handle`} + {PrevView prev_view `DF_Handle`} + {View view `DF_Handle`} + {Entity entity `DF_Handle`} + {EntityList entity_list `DF_HandleList`} + {String string `String8`} + {FilePath file_path `String8`} + {TextPoint text_point `TxtPt`} + {CmdSpec cmd_spec `struct DF_CmdSpec *`} + {ViewSpec view_spec `struct DF_ViewSpec *`} + {CfgNode cfg_node `struct DF_CfgNode *`} + {OSEvent os_event `struct OS_Event *`} + {VirtualAddr vaddr `U64`} + {VirtualOff voff `U64`} + {Index index `U64`} + {ID id `U64`} + {PreferDisassembly prefer_dasm `B32`} + {ForceConfirm force_confirm `B32`} + {Dir2 dir2 `Dir2`} + {UnwindIndex unwind_index `U64`} + {InlineDepth inline_depth `U64`} +} + +@table(name lister_omit q_slot q_ent_kind q_allow_files q_allow_folders q_keep_oi q_select_oi q_is_code q_required canonical_icon string display_name desc search_tags ) +// / | | \___ ______________________________________________/ | | | | | +// / | | \ / | | | | | +DF_CoreCmdTable:// | | | | | | | | | +{ + {Null 1 Null Nil 0 0 0 0 0 0 Null "" "" "" "" } + + //- rjf: exiting + {Exit 0 Null Nil 0 0 0 0 0 0 X "exit" "Exit" "Exits the debugger." "quit,close,abort" } + + //- rjf: command runner + {RunCommand 0 CmdSpec Nil 0 0 0 0 0 0 Null "run_command" "Run Command" "Runs a command from the command palette." "help,cmd" } + + //- rjf: notifications + {Error 1 Null Nil 0 0 0 0 0 0 Null "error" "Error" "Notifies of an error." "" } + + //- rjf: os event passthrough + {OSEvent 1 Null Nil 0 0 0 0 0 0 Null "os_event" "OS Event" "" "" } + + //- rjf: low-level target control operations + {LaunchAndRun 0 EntityList Target 0 0 0 0 0 1 Play "launch_and_run" "Launch and Run" "Starts debugging a new instance of a target, then runs." "launch,start,run,target" } + {LaunchAndInit 0 EntityList Target 0 0 0 0 0 1 PlayStepForward "launch_and_init" "Launch and Initialize" "Starts debugging a new instance of a target, then stops at the program's entry point." "launch,start,entry,point" } + {Kill 0 EntityList Process 0 0 0 0 0 1 Stop "kill" "Kill" "Kills the specified existing debugged process(es)." "stop,kill" } + {KillAll 0 Null Nil 0 0 0 0 0 0 Stop "kill_all" "Kill All" "Kills all debugged child processes." "stop,kill,all" } + {Detach 0 EntityList Process 0 0 0 0 0 1 Null "detach" "Detach" "Detaches the specified debugged process." "detach" } + {Continue 0 Null Nil 0 0 0 0 0 0 Play "continue" "Continue" "Continues all halted threads." "" } + {StepIntoInst 0 Null Nil 0 0 0 0 0 0 StepInto "step_into_inst" "Step Into (Assembly)" "Performs a step that goes into calls, at the instruction level." "single,step,thread" } + {StepOverInst 0 Null Nil 0 0 0 0 0 0 StepOver "step_over_inst" "Step Over (Assembly)" "Performs a step that skips calls, at the instruction level." "single,step,thread" } + {StepIntoLine 0 Null Nil 0 0 0 0 0 0 StepInto "step_into_line" "Step Into (Line)" "Performs a step that goes into calls, at the source code line level." "step,thread" } + {StepOverLine 0 Null Nil 0 0 0 0 0 0 StepOver "step_over_line" "Step Over (Line)" "Performs a step that skips calls, at the source code line level." "step,thread" } + {StepOut 0 Null Nil 0 0 0 0 0 0 StepOut "step_out" "Step Out" "Runs to the end of the current function and exits it." "" } + {Halt 0 Null Nil 0 0 0 0 0 0 Pause "halt" "Halt" "Halts all running processes." "pause" } + {SoftHaltRefresh 0 Null Nil 0 0 0 0 0 0 Refresh "soft_halt_refresh" "Soft Halt Refresh" "Interrupts all running processes to collect data, and then resumes them." "" } + {SetThreadIP 1 VirtualAddr Nil 0 0 0 0 1 1 Null "set_thread_ip" "Set Thread IP" "Sets the passed thread's instruction pointer at the passed address." "" } + + //- rjf: high-level composite target control operations + {RunToLine 1 Null Nil 0 0 0 0 0 0 Play "run_to_line" "Run To Line" "Runs until a particular source line is hit." "" } + {RunToAddress 0 VirtualAddr Nil 0 0 0 0 1 1 PlayStepForward "run_to_address" "Run To Address" "Runs until a particular address is hit." "" } + {Run 0 Null Nil 0 0 0 0 0 0 Play "run" "Run" "Runs all targets after starting them if they have not been started yet." "play" } + {Restart 0 Null Nil 0 0 0 0 0 0 Redo "restart" "Restart" "Kills all running processes, then restarts the targets which were used to launch all current processes (if any)." "restart,retry" } + {StepInto 0 Null Nil 0 0 0 0 0 0 StepInto "step_into" "Step Into" "Steps once, possibly into function calls, for either line or instructions." "" } + {StepOver 0 Null Nil 0 0 0 0 0 0 StepOver "step_over" "Step Over" "Steps once, always over function calls, for either line or instructions." "" } + {RunToCursor 0 Null Nil 0 0 0 0 0 0 Play "run_to_cursor" "Run To Cursor" "Runs the selected thread to the current cursor." "" } + {SetNextStatement 0 Null Nil 0 0 0 0 0 0 RightArrow "set_next_statement" "Set Next Statement" "Sets the selected thread's instruction pointer to the cursor's position." "" } + + //- rjf: debug control context management operations + {SelectThread 0 Entity Thread 0 0 0 0 0 1 Null "select_thread" "Select Thread" "Selects a thread." "" } + {SelectThreadWindow 0 Entity Thread 0 0 0 0 0 1 Null "select_thread_window" "Select Thread On Window" "Selects a thread for the active window, overriding the global selected thread." "" } + {SelectThreadView 0 Entity Thread 0 0 0 0 0 1 Null "select_thread_view" "Select Thread On View" "Selects a thread for the active view, overriding the global and per-window selected threads." "" } + {SelectUnwind 1 Null Nil 0 0 0 0 0 0 Null "select_unwind" "Select Unwind" "Selects an unwind frame number for the selected thread." "" } + {UpOneFrame 0 Null Nil 0 0 0 0 0 0 UpArrow "up_one_frame" "Up One Frame" "Selects the call stack frame above the currently selected." "" } + {DownOneFrame 0 Null Nil 0 0 0 0 0 0 DownArrow "down_one_frame" "Down One Frame" "Selects the call stack frame below the currently selected." "callstack,unwind" } + {FreezeThread 0 Entity Thread 0 0 0 0 0 1 Locked "freeze_thread" "Freeze Thread" "Freezes the passed thread." "callstack,unwind" } + {ThawThread 0 Entity Thread 0 0 0 0 0 1 Unlocked "thaw_thread" "Thaw Thread" "Thaws the passed thread." "" } + {FreezeProcess 0 Entity Process 0 0 0 0 0 1 Locked "freeze_process" "Freeze Process" "Freezes the passed process." "" } + {ThawProcess 0 Entity Process 0 0 0 0 0 1 Unlocked "thaw_process" "Thaw Process" "Thaws the passed process." "" } + {FreezeMachine 1 Entity Machine 0 0 0 0 0 1 Locked "freeze_machine" "Freeze Machine" "Freezes the passed machine." "" } + {ThawMachine 1 Entity Machine 0 0 0 0 0 1 Unlocked "thaw_machine" "Thaw Machine" "Thaws the passed machine." "" } + {FreezeLocalMachine 0 Null Nil 0 0 0 0 0 0 Machine "freeze_local_machine" "Freeze Local Machine" "Freezes the local machine." "" } + {ThawLocalMachine 0 Null Nil 0 0 0 0 0 0 Machine "thaw_local_machine" "Thaw Local Machine" "Thaws the local machine." "" } + + //- rjf: font sizes + {IncUIFontScale 0 Null Nil 0 0 0 0 0 0 Null "inc_ui_font_scale" "Increase UI Font Scale" "Increases the font size used for UI." "" } + {DecUIFontScale 0 Null Nil 0 0 0 0 0 0 Null "dec_ui_font_scale" "Decrease UI Font Scale" "Decreases the font size used for UI." "" } + {IncCodeFontScale 0 Null Nil 0 0 0 0 0 0 Null "inc_code_font_scale" "Increase Code Font Scale" "Increases the font size used for code." "" } + {DecCodeFontScale 0 Null Nil 0 0 0 0 0 0 Null "dec_code_font_scale" "Decrease Code Font Scale" "Decreases the font size used for code." "" } + + //- rjf: windows + {OpenWindow 0 Null Nil 0 0 0 0 0 0 Window "open_window" "Open New Window" "Opens a new window." "" } + {CloseWindow 0 Null Nil 0 0 0 0 0 0 Window "close_window" "Close Window" "Closes an opened window." "" } + {ToggleFullscreen 0 Null Nil 0 0 0 0 0 0 Window "toggle_fullscreen" "Toggle Fullscreen" "Toggles fullscreen view on the active window." "" } + + //- rjf: confirmations + {ConfirmAccept 1 Null Nil 0 0 0 0 0 0 Null "confirm_accept" "Confirm Accept" "Accepts the active confirmation prompt." "" } + {ConfirmCancel 1 Null Nil 0 0 0 0 0 0 Null "confirm_cancel" "Confirm Cancel" "Cancels the active confirmation prompt." "" } + + //- rjf: panel splitting + {ResetToDefaultPanels 0 Null Nil 0 0 0 0 0 0 Window "reset_to_default_panels" "Reset To Default Panel Layout" "Resets the window to the default panel layout." "panel" } + {ResetToCompactPanels 0 Null Nil 0 0 0 0 0 0 Window "reset_to_compact_panels" "Reset To Compact Panel Layout" "Resets the window to the compact panel layout." "panel" } + {NewPanelLeft 0 Null Nil 0 0 0 0 0 0 XSplit "new_panel_left" "Split Panel Left" "Creates a new panel to the left of the active panel." "panel" } + {NewPanelUp 0 Null Nil 0 0 0 0 0 0 YSplit "new_panel_up" "Split Panel Up" "Creates a new panel at the top of the active panel." "panel" } + {NewPanelRight 0 Null Nil 0 0 0 0 0 0 XSplit "new_panel_right" "Split Panel Right" "Creates a new panel to the right of the active panel." "panel" } + {NewPanelDown 0 Null Nil 0 0 0 0 0 0 YSplit "new_panel_down" "Split Panel Down" "Creates a new panel at the bottom of the active panel." "panel" } + {SplitPanel 1 Null Nil 0 0 0 0 0 0 Null "split_panel" "Split Panel" "Creates a new panel in a given direction, and moves a tab to it, if specified." "" } + + //- rjf: panel rotation + {RotatePanelColumns 0 Null Nil 0 0 0 0 0 0 Null "rotate_panel_columns" "Rotate Panel Columns" "Rotates all panels at the closest column level of the panel hierarchy." "" } + + //- rjf: focused panel changing + {NextPanel 0 Null Nil 0 0 0 0 0 0 RightArrow "next_panel" "Focus Next Panel" "Cycles the active panel forward." "" } + {PrevPanel 0 Null Nil 0 0 0 0 0 0 LeftArrow "prev_panel" "Focus Previous Panel" "Cycles the active panel backwards." "" } + {FocusPanel 1 Null Nil 0 0 0 0 0 0 Null "focus_panel" "Focus Panel" "Focuses a new panel." "" } + {FocusPanelRight 0 Null Nil 0 0 0 0 0 0 RightArrow "focus_panel_right" "Focus Panel Right" "Focuses a panel rightward of the currently focused panel." "" } + {FocusPanelLeft 0 Null Nil 0 0 0 0 0 0 LeftArrow "focus_panel_left" "Focus Panel Left" "Focuses a panel leftward of the currently focused panel." "" } + {FocusPanelUp 0 Null Nil 0 0 0 0 0 0 UpArrow "focus_panel_up" "Focus Panel Up" "Focuses a panel upward of the currently focused panel." "" } + {FocusPanelDown 0 Null Nil 0 0 0 0 0 0 DownArrow "focus_panel_down" "Focus Panel Down" "Focuses a panel downward of the currently focused panel." "" } + + //- rjf: undo/redo + {Undo 1 Null Nil 0 0 0 0 0 0 Undo "undo" "Undo" "Undoes the previous action." "" } + {Redo 1 Null Nil 0 0 0 0 0 0 Redo "redo" "Redo" "Redoes the first previously undone action." "" } + + //- rjf: focus history + {GoBack 1 Null Nil 0 0 0 0 0 0 LeftArrow "go_back" "Go Back" "Returns to the previously selected panel and tab in recorded history." "" } + {GoForward 1 Null Nil 0 0 0 0 0 0 RightArrow "go_forward" "Go Forward" "Returns to the next selected panel and tab in recorded history." "" } + + //- rjf: panel removal + {ClosePanel 0 Null Nil 0 0 0 0 0 0 ClosePanel "close_panel" "Close Panel" "Closes the currently active panel." "" } + + //- rjf: panel tab + {NextTab 0 Null Nil 0 0 0 0 0 0 RightArrow "next_tab" "Focus Next Tab" "Focuses the next tab on the active panel." "" } + {PrevTab 0 Null Nil 0 0 0 0 0 0 LeftArrow "prev_tab" "Focus Previous Tab" "Focuses the previous tab on the active panel." "" } + {MoveTabRight 0 Null Nil 0 0 0 0 0 0 RightArrow "move_tab_right" "Move Tab Right" "Moves the selected tab right one slot." "" } + {MoveTabLeft 0 Null Nil 0 0 0 0 0 0 LeftArrow "move_tab_left" "Move Tab Left" "Moves the selected tab left one slot." "" } + {OpenTab 1 Null Nil 0 0 0 0 0 0 Null "open_tab" "Open Tab" "Opens a new tab with the parameterized view specification." "" } + {CloseTab 0 Null Nil 0 0 0 0 0 0 X "close_tab" "Close Tab" "Closes the currently opened tab." "" } + {MoveTab 1 Null Nil 0 0 0 0 0 0 Null "move_tab" "Move Tab" "Moves a tab to a new panel." "" } + {TabBarTop 0 Null Nil 0 0 0 0 0 0 UpArrow "tab_bar_top" "Anchor Tab Bar To Top" "Anchors a panel's tab bar to the top of the panel." "" } + {TabBarBottom 0 Null Nil 0 0 0 0 0 0 DownArrow "tab_bar_bottom" "Anchor Tab Bar To Bottom" "Anchors a panel's tab bar to the bottom of the panel." "" } + + //- rjf: files + {SetCurrentPath 1 Null Nil 0 0 0 0 0 0 FileOutline "set_current_path" "Set Current Path" "Sets the debugger's current path, which is used as a starting point when browsing for files." "" } + {Open 0 FilePath Nil 1 0 0 0 0 1 FileOutline "open" "Open" "Opens a file." "code,source,file" } + {Switch 0 Entity File 0 0 0 0 0 1 FileOutline "switch" "Switch" "Switches to a loaded file." "code,source,file" } + {SwitchToPartnerFile 0 Null Nil 0 0 0 0 0 0 FileOutline "switch_to_partner_file" "Switch To Partner File" "Switches to the focused file's partner; or from header to implementation or vice versa." "code,source,file" } + + //- rjf: source <-> disasm + {GoToDisassembly 0 Null Nil 0 0 0 0 0 0 Glasses "go_to_disassembly" "Go To Disassembly" "Goes to the disassembly, if any, for a given source code line." "code,source,disassembly,disasm" } + {GoToSource 0 Null Nil 0 0 0 0 0 0 FileOutline "go_to_source" "Go To Source" "Goes to the source code, if any, for a given disassembly line." "code,source,disassembly,disasm" } + + //- rjf: override file links + {SetFileOverrideLinkSrc 1 Null Nil 0 0 0 0 0 0 Null "set_file_override_link_src" "Set File Override Link Source" "Sets the source path for an override file link." "" } + {SetFileOverrideLinkDst 1 Null Nil 0 0 0 0 0 0 Null "set_file_override_link_dst" "Set File Override Link Destination" "Sets the destination path for an override file link." "" } + {SetFileReplacementPath 1 Null Nil 0 0 0 0 0 0 Null "set_file_replacement_path" "Set File Replacement Path" "Sets the path which should be used as the replacement for the passed file." "" } + + //- rjf: auto view rules + {SetAutoViewRuleType 1 Null Nil 0 0 0 0 0 0 Null "set_auto_view_rule_type" "Set Auto View Rule Type" "Sets the type for an auto view rule." "" } + {SetAutoViewRuleViewRule 1 Null Nil 0 0 0 0 0 0 Null "set_auto_view_rule_view_rule""Set Auto View Rule View Rule" "Sets the view rule string for an auto view rule." "" } + + //- rjf: setting config paths + {OpenUser 0 FilePath Nil 1 0 0 0 0 1 Person "open_user" "Open User" "Opens a user file path, immediately loading it, and begins autosaving to it." "load,user,project,layout" } + {OpenProject 0 FilePath Nil 1 0 0 0 0 1 Briefcase "open_project" "Open Project" "Opens a project file path, immediately loading it, and begins autosaving to it." "project,project,session" } + {OpenRecentProject 0 Entity RecentProject 0 0 0 0 0 1 Briefcase "open_recent_project" "Open Recent Project" "Opens a recently used project file." "project,project,session" } + + //- rjf: loading/applying stateful config changes + {ApplyUserData 1 Null Nil 0 0 0 0 0 0 Null "apply_user_data" "Apply User Data" "Applies user data from the active user file." "" } + {ApplyProjectData 1 Null Nil 0 0 0 0 0 0 Null "apply_project_data" "Apply Project Data" "Applies project data from the active project file." "" } + + //- rjf: writing config changes + {WriteUserData 1 Null Nil 0 0 0 0 0 0 Null "write_user_data" "Write User Data" "Writes user data to the active user file." "" } + {WriteProjectData 1 Null Nil 0 0 0 0 0 0 Null "write_project_data" "Write Project Data" "Writes project data to the active project file." "" } + + //- rjf: meta controls + {Edit 0 Null Nil 0 0 0 0 0 0 Pencil "edit" "Edit" "Edits the current selection." "" } + {Accept 0 Null Nil 0 0 0 0 0 0 CheckFilled "accept" "Accept" "Accepts current changes, or answers prompts in the affirmative." "" } + {Cancel 0 Null Nil 0 0 0 0 0 0 X "cancel" "Cancel" "Rejects current changes, exits temporary menus, or answers prompts in the negative." "" } + + //- rjf: directional movement & text controls + {MoveLeft 0 Null Nil 0 0 0 0 0 0 Null "move_left" "Move Left" "Moves the cursor or selection left." "" } + {MoveRight 0 Null Nil 0 0 0 0 0 0 Null "move_right" "Move Right" "Moves the cursor or selection right." "" } + {MoveUp 0 Null Nil 0 0 0 0 0 0 Null "move_up" "Move Up" "Moves the cursor or selection up." "" } + {MoveDown 0 Null Nil 0 0 0 0 0 0 Null "move_down" "Move Down" "Moves the cursor or selection down." "" } + {MoveLeftSelect 0 Null Nil 0 0 0 0 0 0 Null "move_left_select" "Move Left Select" "Moves the cursor or selection left, while selecting." "" } + {MoveRightSelect 0 Null Nil 0 0 0 0 0 0 Null "move_right_select" "Move Right Select" "Moves the cursor or selection right, while selecting." "" } + {MoveUpSelect 0 Null Nil 0 0 0 0 0 0 Null "move_up_select" "Move Up Select" "Moves the cursor or selection up, while selecting." "" } + {MoveDownSelect 0 Null Nil 0 0 0 0 0 0 Null "move_down_select" "Move Down Select" "Moves the cursor or selection down, while selecting." "" } + {MoveLeftChunk 0 Null Nil 0 0 0 0 0 0 Null "move_left_chunk" "Move Left Select" "Moves the cursor or selection left one chunk." "" } + {MoveRightChunk 0 Null Nil 0 0 0 0 0 0 Null "move_right_chunk" "Move Right Select" "Moves the cursor or selection right one chunk." "" } + {MoveUpChunk 0 Null Nil 0 0 0 0 0 0 Null "move_up_chunk" "Move Up Chunk" "Moves the cursor or selection up one chunk." "" } + {MoveDownChunk 0 Null Nil 0 0 0 0 0 0 Null "move_down_chunk" "Move Down Chunk" "Moves the cursor or selection down one chunk." "" } + {MoveUpPage 0 Null Nil 0 0 0 0 0 0 Null "move_up_page" "Move Up Page" "Moves the cursor or selection up one page." "" } + {MoveDownPage 0 Null Nil 0 0 0 0 0 0 Null "move_down_page" "Move Down Page" "Moves the cursor or selection down one page." "" } + {MoveUpWhole 0 Null Nil 0 0 0 0 0 0 Null "move_up_whole" "Move Up Whole" "Moves the cursor or selection to the beginning of the relevant content." "" } + {MoveDownWhole 0 Null Nil 0 0 0 0 0 0 Null "move_down_whole" "Move Down Whole" "Moves the cursor or selection to the end of the relevant content." "" } + {MoveLeftChunkSelect 0 Null Nil 0 0 0 0 0 0 Null "move_left_chunk_select" "Move Left Chunk Select" "Moves the cursor or selection left one chunk." "" } + {MoveRightChunkSelect 0 Null Nil 0 0 0 0 0 0 Null "move_right_chunk_select" "Move Right Chunk Select" "Moves the cursor or selection right one chunk." "" } + {MoveUpChunkSelect 0 Null Nil 0 0 0 0 0 0 Null "move_up_chunk_select" "Move Up Chunk Select" "Moves the cursor or selection up one chunk." "" } + {MoveDownChunkSelect 0 Null Nil 0 0 0 0 0 0 Null "move_down_chunk_select" "Move Down Chunk Select" "Moves the cursor or selection down one chunk." "" } + {MoveUpPageSelect 0 Null Nil 0 0 0 0 0 0 Null "move_up_page_select" "Move Up Page Select" "Moves the cursor or selection up one page, while selecting." "" } + {MoveDownPageSelect 0 Null Nil 0 0 0 0 0 0 Null "move_down_page_select" "Move Down Page Select" "Moves the cursor or selection down one page, while selecting." "" } + {MoveUpWholeSelect 0 Null Nil 0 0 0 0 0 0 Null "move_up_whole_select" "Move Up Whole Select" "Moves the cursor or selection to the beginning of the relevant content, while selecting." "" } + {MoveDownWholeSelect 0 Null Nil 0 0 0 0 0 0 Null "move_down_whole_select" "Move Down Whole Select" "Moves the cursor or selection to the end of the relevant content, while selecting." "" } + {MoveUpReorder 0 Null Nil 0 0 0 0 0 0 Null "move_up_reorder" "Move Up Reorder" "Moves the cursor or selection up, while swapping the currently selected element with that upward." "" } + {MoveDownReorder 0 Null Nil 0 0 0 0 0 0 Null "move_down_reorder" "Move Down Reorder" "Moves the cursor or selection down, while swapping the currently selected element with that downward." "" } + {MoveHome 0 Null Nil 0 0 0 0 0 0 Null "move_home" "Move Home" "Moves the cursor to the beginning of the line." "" } + {MoveEnd 0 Null Nil 0 0 0 0 0 0 Null "move_end" "Move End" "Moves the cursor to the end of the line." "" } + {MoveHomeSelect 0 Null Nil 0 0 0 0 0 0 Null "move_home_select" "Move Home Select" "Moves the cursor to the beginning of the line, while selecting." "" } + {MoveEndSelect 0 Null Nil 0 0 0 0 0 0 Null "move_end_select" "Move End Select" "Moves the cursor to the end of the line, while selecting." "" } + {SelectAll 0 Null Nil 0 0 0 0 0 0 Null "select_all" "Select All" "Selects everything possible." "" } + {DeleteSingle 0 Null Nil 0 0 0 0 0 0 Null "delete_single" "Delete Single" "Deletes a single element to the right of the cursor, or the active selection." "" } + {DeleteChunk 0 Null Nil 0 0 0 0 0 0 Null "delete_chunk" "Delete Chunk" "Deletes a chunk to the right of the cursor, or the active selection." "" } + {BackspaceSingle 0 Null Nil 0 0 0 0 0 0 Null "backspace_single" "Backspace Single" "Deletes a single element to the left of the cursor, or the active selection." "" } + {BackspaceChunk 0 Null Nil 0 0 0 0 0 0 Null "backspace_chunk" "Backspace Chunk" "Deletes a chunk to the left of the cursor, or the active selection." "" } + {Copy 0 Null Nil 0 0 0 0 0 0 Clipboard "copy" "Copy" "Copies the active selection to the clipboard." "" } + {Cut 0 Null Nil 0 0 0 0 0 0 Clipboard "cut" "Cut" "Copies the active selection to the clipboard, then deletes it." "" } + {Paste 0 Null Nil 0 0 0 0 0 0 Clipboard "paste" "Paste" "Pastes the current contents of the clipboard." "" } + {InsertText 1 Null Nil 0 0 0 0 0 0 Null "insert_text" "Insert Text" "Inserts the text that was used to cause this command." "" } + + //- rjf: code navigation + {GoToLine 0 TextPoint Nil 0 0 0 0 1 1 Null "goto_line" "Go To Line" "Jumps to a line number in the current code file." "" } + {GoToAddress 0 VirtualAddr Nil 0 0 0 0 1 1 Null "goto_address" "Go To Address" "Jumps to an address in the current memory or disassembly view." "" } + {CenterCursor 0 Null Nil 0 0 0 0 0 0 Null "center_cursor" "Center Cursor" "Snaps the current code view to center the cursor." "" } + {ContainCursor 0 Null Nil 0 0 0 0 0 0 Null "contain_cursor" "Contain Cursor" "Snaps the current code view to contain the cursor." "" } + {FindTextForward 0 String Nil 0 0 1 1 1 1 Find "find_text_forward" "Find Text (Forward)" "Searches the current code file forward (from the cursor) for a string." "" } + {FindTextBackward 0 String Nil 0 0 1 1 1 1 Find "find_text_backward" "Find Text (Backwards)" "Searches the current code file backwards (from the cursor) for a string." "" } + {FindNext 0 Null Nil 0 0 1 0 0 0 Find "find_next" "Find Next" "Searches the current code file forward (from the cursor) for the last searched string." "" } + {FindPrev 0 Null Nil 0 0 1 0 0 0 Find "find_prev" "Find Previous" "Searches the current code file backwards (from the cursor) for the last searched string." "" } + + //- rjf: thread finding + {FindThread 0 Entity Thread 0 0 0 0 0 1 Find "find_thread" "Find Thread" "Jumps to the passed thread in either source code, disassembly, or both if they're already open." "" } + {FindSelectedThread 0 Null Nil 0 0 0 0 0 0 Find "find_selected_thread" "Find Selected Thread" "Jumps to the selected thread in either source code, disassembly, or both if they're already open." "" } + + //- rjf: name finding + {GoToName 0 String Nil 0 0 0 0 1 1 Null "goto_name" "Go To Name" "Searches for the passed string as a file, a symbol in debug info, and more, then jumps to it if possible." "" } + {GoToNameAtCursor 0 Null Nil 0 0 0 0 0 0 Null "goto_name_at_cursor" "Go To Name At Cursor" "Searches for the text at the cursor as a file, a symbol in debug info, and more, then jumps to it if possible." "" } + + //- rjf: watch expressions + {ToggleWatchExpression 0 Null Nil 0 0 0 0 0 0 Binoculars "toggle_watch_expr" "Toggle Watch Expression" "Adds or removes an expression to an opened watch view." "" } + {ToggleWatchExpressionAtCursor 0 Null Nil 0 0 0 0 0 0 Binoculars "toggle_watch_expr_at_cursor" "Toggle Watch Expression At Cursor" "Adds or removes the expression that the cursor or selection is currently over to an opened watch view." "" } + {ToggleWatchExpressionAtMouse 0 Null Nil 0 0 0 0 0 0 Binoculars "toggle_watch_expr_at_mouse" "Toggle Watch Expression At Mouse" "Adds or removes the expression that the mouse is currently over to an opened watch view." "" } + + //- rjf: memory view parameterization + {SetColumns 0 Index Nil 0 0 0 0 1 1 Thumbnails "set_columns" "Set Columns" "Sets the number of columns for a memory view." "" } + + //- rjf: disassembly view parameterization + {ToggleAddressVisibility 0 Null Nil 0 0 0 0 0 0 Thumbnails "toggle_address_visibility" "Toggle Address Visibility" "Toggles the visibility of addresses in a disassembly view." "" } + {ToggleCodeBytesVisibility 0 Null Nil 0 0 0 0 0 0 Thumbnails "toggle_code_bytes_visibility""Toggle Code Bytes Visibility" "Toggles the visibility of machine code bytes in a disassembly view." "" } + + //- rjf: general entity operations + {EnableEntity 1 Null Nil 0 0 0 0 0 0 Null "enable_entity" "Enable Entity" "Enables an entity." "" } + {DisableEntity 1 Null Nil 0 0 0 0 0 0 Null "disable_entity" "Disable Entity" "Disables an entity." "" } + {FreezeEntity 1 Null Nil 0 0 0 0 0 0 Null "freeze_entity" "Freeze Entity" "Freezes an entity." "" } + {ThawEntity 1 Null Nil 0 0 0 0 0 0 Null "thaw_entity" "Thaw Entity" "Thaws an entity." "" } + {RemoveEntity 1 Null Nil 0 0 0 0 0 0 Null "remove_entity" "Remove Entity" "Removes an entity." "" } + {NameEntity 1 Null Nil 0 0 0 0 0 0 Null "name_entity" "Name Entity" "Equips an entity with a name." "" } + {EditEntity 1 Null Nil 0 0 0 0 0 0 Null "edit_entity" "Edit Entity" "Opens the editor for an entity." "" } + {DuplicateEntity 1 Null Nil 0 0 0 0 0 0 Null "duplicate_entity" "Duplicate Entity" "Duplicates an entity." "" } + + //- rjf: breakpoints + {TextBreakpoint 1 FilePath Nil 0 0 0 0 0 0 CircleFilled "text_breakpoint" "Text Breakpoint" "Places or removes a breakpoint on the specified line of source code." "" } + {AddressBreakpoint 0 VirtualAddr Nil 0 0 0 0 1 1 CircleFilled "address_breakpoint" "Address Breakpoint" "Places or removes a breakpoint on the specified address." "" } + {FunctionBreakpoint 0 String Nil 0 0 0 0 1 1 CircleFilled "function_breakpoint" "Function Breakpoint" "Places or removes a breakpoint on the first address(es) of the specified function." "" } + {ToggleBreakpointAtCursor 0 Null Nil 0 0 0 0 0 0 CircleFilled "toggle_breakpoint_cursor" "Toggle Breakpoint At Cursor" "Places or removes a breakpoint on the line on which the active cursor sits." "" } + {RemoveBreakpoint 0 Entity Breakpoint 0 0 0 0 0 1 Trash "remove_breakpoint" "Remove Breakpoint" "Removes an existing breakpoint." "" } + {EnableBreakpoint 0 Entity Breakpoint 0 0 0 0 0 1 CheckFilled "enable_breakpoint" "Enable Breakpoint" "Enables a breakpoint." "" } + {DisableBreakpoint 0 Entity Breakpoint 0 0 0 0 0 1 CheckHollow "disable_breakpoint" "Disable Breakpoint" "Disables a breakpoint." "" } + + //- rjf: watches + {ToggleWatchPin 1 Null Nil 0 0 0 0 0 0 Binoculars "toggle_watch_pin" "Toggle Watch Pin" "Places or removes a watch pin on a textual location on a particular entity." "" } + {ToggleWatchPinAtCursor 0 String Nil 0 0 0 0 1 1 Binoculars "toggle_watch_pin_at_cursor" "Toggle Watch Pin At Cursor" "Places or removes a watch pin at the cursor on the currently active file." "" } + + //- rjf: targets + {AddTarget 0 FilePath Nil 1 0 0 0 0 1 Target "add_target" "Add Target" "Adds a new target." "application,executable,debug" } + {RemoveTarget 0 Entity Target 0 0 0 0 0 1 Trash "remove_target" "Remove Target" "Removes an existing target." "delete,remove,target" } + {EditTarget 0 Entity Target 0 0 0 0 0 1 Pencil "edit_target" "Edit Target" "Edits an existing target." "" } + {SelectTarget 0 Entity Target 0 0 0 0 0 1 Target "select_target" "Select Target" "Selects a target." "" } + {EnableTarget 0 Entity Target 0 0 0 0 0 1 CheckFilled "enable_target" "Enable Target" "Enables a target, in addition to all targets currently enabled." "" } + {DisableTarget 0 Entity Target 0 0 0 0 0 1 CheckHollow "disable_target" "Disable Target" "Disables a target." "" } + + //- rjf: ended processes + {RetryEndedProcess 1 Entity Process 0 0 0 0 0 0 Null "retry_ended_process" "Retry Ended Process" "Launches a new process with the same options as the passed ended process." "" } + + //- rjf: attaching + {Attach 0 ID Nil 0 0 0 0 0 1 Null "attach" "Attach" "Attaches to a process that is already running on the local machine." "" } + {RegisterAsJITDebugger 0 Null Nil 0 0 0 0 0 0 Null "register_as_jit_debugger" "Register As Just-In-Time (JIT) Debugger" "Registers the RAD debugger as the just-in-time (JIT) debugger used by the operating system." "" } + + //- rjf: catchall general entity activation paths (drag/drop, clicking) + {EntityRefFastPath 1 Null Nil 0 0 0 0 0 0 Null "entity_ref_fast_path" "Entity Reference Fast Path" "Activates the default behavior when clicking an entity reference." "" } + {SpawnEntityView 1 Null Nil 0 0 0 0 0 0 Null "spawn_entity_view" "Spawn Entity View" "Spawns a new view, given an entity and other parameterizations." "" } + {FindCodeLocation 1 FilePath Nil 0 0 0 0 0 1 FileOutline "find_code_location" "Find Code Location" "Finds a specific source code location given file, line, and column coordinates. Opens the file if necessary." "" } + + //- rjf: general-purpose view filtering + {Filter 0 Null Nil 0 0 0 0 0 0 Find "filter" "Filter" "Begins filtering the active view." "sort,search,filter,find" } + {ApplyFilter 0 Null Nil 0 0 0 0 0 0 Find "apply_filter" "Apply Filter" "Applies the typed filter to the active view." "sort,search,filter,find,apply" } + {ClearFilter 0 Null Nil 0 0 0 0 0 0 Find "clear_filter" "Clear Filter" "Clears the filter applied to the active view." "sort,search,filter,find,clear" } + + //- rjf: view drivers + {GettingStarted 0 Null Nil 0 0 0 0 0 0 QuestionMark "getting_started" "Getting Started" "Opens the menu for information on getting started." "tutorial,help" } + {Commands 1 Null Nil 0 0 0 0 0 0 List "commands" "Commands" "Opens the list of all commands." "" } + {Target 1 Null Nil 0 0 0 0 0 0 Target "target" "Target" "Opens the editor for a target." "" } + {Targets 0 Null Nil 0 0 0 0 0 0 Target "targets" "Targets" "Opens the list of all targets." "" } + {FilePathMap 0 Null Nil 0 0 0 0 0 0 FileOutline "file_path_map" "File Path Map" "Opens the file path mapping editor." "" } + {AutoViewRules 0 Null Nil 0 0 0 0 0 0 Binoculars "auto_view_rules" "Auto View Rules" "Opens the auto view rule editor." "" } + {Scheduler 0 Null Nil 0 0 0 0 0 0 Scheduler "scheduler" "Scheduler" "Opens the scheduler view, for process and thread controls." "threads,processes,targets" } + {CallStack 0 Null Nil 0 0 0 0 0 0 Thread "call_stack" "Call Stack" "Opens the call stack view." "callstack,thread,unwind" } + {Modules 0 Null Nil 0 0 0 0 0 0 Module "modules" "Modules" "Opens the modules view." "" } + {PendingEntity 1 Null Nil 0 0 0 0 0 0 FileOutline "pending_entity" "Pending Entity" "Opens a view which waits for the passed entity to be completely loaded, then replaces itself with a new view." "" } + {Code 1 Null Nil 0 0 0 0 0 0 FileOutline "code" "Code" "Opens the code view for an already-loaded file." "" } + {Watch 0 Null Nil 0 0 0 0 0 0 Binoculars "watch" "Watch" "Opens a watch view." "" } + {Locals 0 Null Nil 0 0 0 0 0 0 Binoculars "locals" "Locals" "Opens a locals view." "" } + {Registers 0 Null Nil 0 0 0 0 0 0 Binoculars "registers" "Registers" "Opens a registers view." "" } + {Globals 0 Null Nil 0 0 0 0 0 0 Binoculars "globals" "Globals" "Opens a globals view." "" } + {ThreadLocals 0 Null Nil 0 0 0 0 0 0 Binoculars "thread_locals" "Thread Locals" "Opens a thread locals view." "" } + {Types 0 Null Nil 0 0 0 0 0 0 Binoculars "types" "Types" "Opens a types view." "" } + {Procedures 0 Null Nil 0 0 0 0 0 0 Binoculars "procedures" "Procedures" "Opens a procedures view." "" } + {Output 0 Null Nil 0 0 0 0 0 0 List "output" "Output" "Opens an output view." "" } + {Memory 0 Null Nil 0 0 0 0 0 0 Grid "memory" "Memory" "Opens a memory view." "" } + {Disassembly 0 Null Nil 0 0 0 0 0 0 Glasses "disassembly" "Disassembly" "Opens the disassembly view." "disasm" } + {Breakpoints 0 Null Nil 0 0 0 0 0 0 CircleFilled "breakpoints" "Breakpoints" "Opens the breakpoints view." "" } + {WatchPins 0 Null Nil 0 0 0 0 0 0 Pin "watch_pins" "Watch Pins" "Opens the watch pins view." "" } + {ExceptionFilters 0 Null Nil 0 0 0 0 0 0 Gear "exception_filters" "Exception Filters" "Opens the exception filters view." "exceptions,filters" } + {Settings 0 Null Nil 0 0 0 0 0 0 Gear "settings" "Settings" "Opens the settings view." "theme,color,scheme,options" } + {PickFile 1 FilePath Nil 1 0 0 0 0 1 FileOutline "pick_file" "Pick File" "Opens the file browser to pick a file." "" } + {PickFolder 1 FilePath Nil 0 1 0 0 0 1 FolderOpenFilled "pick_folder" "Pick Folder" "Opens the file browser to pick a folder." "" } + {PickFileOrFolder 1 FilePath Nil 1 1 0 0 0 1 FileOutline "pick_file_or_folder" "Pick File/Folder" "Opens the file browser to pick a file or folder." "" } + + //- rjf: query completion + {CompleteQuery 1 Null Nil 0 0 0 0 0 0 Null "complete_query" "Complete Query" "Completes a query." "" } + {CancelQuery 1 Null Nil 0 0 0 0 0 0 Null "cancel_query" "Cancel Query" "Cancels a query." "" } + + //- rjf: developer commands + {ToggleDevMenu 0 Null Nil 0 0 0 0 0 0 Null "toggle_dev_menu" "Toggle Developer Menu" "Opens and closes the developer menu." "" } + {LogMarker 0 Null Nil 0 0 0 0 0 0 Null "log_marker" "Log Marker" "Logs a marker in the application log, to denote specific points in time within the log." "" } +} + +//////////////////////////////// +//~ rjf: Built-In View Rules +// +// @view_rule_info +// +// NOTE(rjf): View rules are subtle in that they may impact any subset of the +// eval visualization pipeline. The "array" view rule, for example, functions +// by tweaking the type of an eval from `X *` to `X (*)[N]` (where N is +// computed from whatever expression is specified by the view rule). The "list" +// view rule, on the other hand, does not require any changes to the actual +// eval nor its type - instead, it follows an alternative path in constructing +// "viz blocks", and then constructing "viz rows" from those blocks. Compare +// these to the simpler 'dec', 'bin', or 'oct' rules, which simply tweak the +// radix used when stringizing numbers, which is something that only occurs in +// single-line eval stringization building. +// +// As such, each view rule specification has a mask, which determines which +// stages it may be used for. For a given view rule specification, if the bit +// corresponding to a particular eval stage is set, then that view rule spec- +// -ification also includes a hook which can be called from that stage. +// +// Below is a list of the stages in the eval visualization pipeline, as well as +// abbreviations which are used in the tables. +// +// eval resolution, "er" -> provides a chance for a view rule to impact an eval +// value or type, before the rest of the eval visual +// pipeline continues. +// +// viz block prod, "vb" -> given a resolved eval, produce a list of non- +// windowed "viz blocks", which correspond to one or +// many contiguous rows in a watch-window-style UI. +// one level of expanded struct members, with no sub- +// expansions, would be one viz block. if one of those +// members - in the middle - were expanded too, then +// it would require three viz blocks - one for the +// members before the sub-expansion, one for the +// sub expansion members, and one for the members +// after, and so on. this is done recursively. +// +// viz row prod, "vr" -> given a list of viz blocks, a windowed list of viz +// rows may be produced. each of these rows has info +// for building actual UI in e.g. a watch window - +// whether or not the row can be expanded, whether or +// not the row's value can be edited, what the edit- +// able string is for a row, what the display string +// is for a row, what the expression string is for a +// row, what the type is for a row, and so on. +// +// line stringize, "ls" -> this is the stage used to produce display strings +// in the "viz row prod" stage, as well as basically +// any time UI needs to display the result of an eval +// in a single line. this also occurs recursively, +// descending into members & elements as needed, +// constrained by # of available pixels and font size +// and so on. +// +// row ui build, "ru" -> finally, after the previous stages are completed, +// ui can finally be built according to all of the +// per-row information produced. this is the stage +// where view rules can insert their own arbitrary ui +// on a per-row basis. +// +// block ui build, "bu" -> sometimes, view rules want to take over an entire +// viz block. while those viz blocks will still be +// used to size a collapsed region in terms of #-of- +// rows, this stage offers the ability to build a ui +// stretching over all of the rows. +// +// tab ui build, "tu" -> when a view rule also wants to implement ui for a +// dedicated tab, it can supply hooks for that as well +// in which case an eval/view-rule can be opened in a +// fully fledged, dedicated ui +// +// A few other bits are included for various ways in which a view rule may be +// applied throughout the eval visualization pipeline. A list follows: +// +// inherited, "ih" -> is this view rule included, or not included, in +// child expansions? +// +// expandable, "ex" -> does this view rule force the ability to expand +// an expression, even if traditional analysis of type +// info would not allow expansion? +// +// Not all of these stages are specified at this layer, however, since the +// "df_core" layer is for the non-graphical core debugger features. So the +// information pertaining to the eval visualization pipeline stages which +// do require graphical subsystems (e.g. UI, fonts, rendering) are specified +// in the "df_gfx" layer. +// +// For any view rules in this layer which also have graphical features, they +// are specified in both tables under the same name. + +@table(name name_lower string ih ex er vb display_name docs schema description) +DF_CoreViewRuleTable: +{ + {Null null "" - - - - "" - "" "" } + {Array array "array" - - x - "Array" x "x:{expr}" "Specifies that a pointer points to N elements, rather than only 1." } + {Slice slice "slice" - - x - "Slice" x "" "Specifies that a pointer within a struct, also containing an integer, points to the number of elements encoded by the integer." } + {List list "list" - - - x "List" x "x:{member}" "Specifies that some struct, union, or class forms the top of a linked list, and the member which points at the following element in the list." } + {ByteSwap bswap "bswap" x - x - "Byte Swap" x "" "Specifies that all integer primitives should be byte-swapped, such that their endianness is reversed." } + {BaseDec base_dec "dec" x - - - "Decimal Base (Base 10)" x "" "Specifies that all integral evaluations should appear in base-10 form." } + {BaseBin base_bin "bin" x - - - "Binary Base (Base 2)" x "" "Specifies that all integral evaluations should appear in base-2 form." } + {BaseOct base_oct "oct" x - - - "Octal Base (Base 8)" x "" "Specifies that all integral evaluations should appear in base-8 form." } + {BaseHex base_hex "hex" x - - - "Hexadecimal Base (Base 16)" x "" "Specifies that all integral evaluations should appear in base-16 form." } + {Only only "only" x - - x "Only Specified Members" x "x:{member}" "Specifies that only the specified members should appear in struct, union, or class evaluations." } + {Omit omit "omit" x - - x "Omit Specified Members" x "x:{member}" "Omits a list of member names from appearing in struct, union, or class evaluations." } + {NoAddr no_addr "no_addr" x - - - "Disable Address Values" x "" "Displays only what pointers point to, if possible, without the pointer's address value." } + {RGBA rgba "rgba" - x - x "Color (RGBA)" x "" "Displays as a color, interpreting the data as encoding R, G, B, and A values." } + {Text text "text" - x - x "Text" x "x:{'lang':lang, 'size':expr}" "Displays as text." } + {Disasm disasm "disasm" - x - x "Disassembly" x "x:{'arch':arch, 'size':expr}" "Displays as disassembled instructions, interpreting the data as raw machine code." } + {Graph graph "graph" - x - x "Graph" x "" "Displays as a pointer graph, visualizing nodes and edges formed by pointers directly." } + {Bitmap bitmap "bitmap" - x - x "Bitmap" x "x:{'w':expr, 'h':expr, 'fmt':tex2dformat}" "Displays as a bitmap, interpreting the data as raw pixel data." } + {Geo geo "geo" - x - x "Geometry" x "x:{'count':expr, 'vertices_base':expr, 'vertices_size':expr}" "Displays as geometry, interpreting the data as vertex data." } +} + +//////////////////////////////// +//~ rjf: Icons (TODO(rjf): this needs to move to the df_gfx graphical layer) + +@table(name, text) +DF_IconTable: +{ + (Null "") + (FolderOpenOutline "b") + (FolderClosedOutline "c") + (FolderOpenFilled "B") + (FolderClosedFilled "C") + (FileOutline "f") + (FileFilled "F") + (Play "g") + (PlayStepForward "h") + (Pause "r") + (Stop "s") + (Info "i") + (WarningSmall "w") + (WarningBig "W") + (Unlocked "k") + (Locked "K") + (LeftArrow "L") + (RightArrow "R") + (UpArrow "U") + (DownArrow "D") + (Gear "G") + (Pencil "P") + (Trash "3") + (Pin "p") + (RadioHollow "O") + (RadioFilled "o") + (CheckHollow "!") + (CheckFilled "1") + (LeftCaret "<") + (RightCaret ">") + (UpCaret "^") + (DownCaret "v") + (UpScroll "9") + (DownScroll "0") + (LeftScroll "7") + (RightScroll "8") + (Add "+") + (Minus "-") + (Thread "'") + (Threads '\\"') + (Machine "M") + (CircleFilled ".") + (X "x") + (Refresh "q") + (Undo "j") + (Redo "u") + (Save "m") + (Window "n") + (Target "l") + (Clipboard "a") + (Scheduler "z") + (Module "y") + (XSplit "X") + (YSplit "Y") + (ClosePanel "S") + (StepInto "T") + (StepOver "Z") + (StepOut "d") + (Find "N") + (Palette "E") + (Thumbnails "H") + (Glasses "e") + (Binoculars "I") + (List "J") + (Grid "A") + (QuestionMark "?") + (Person "4") + (Briefcase "5") + (Dot "c") +} + +//////////////////////////////// +//~ rjf: X64 Instruction Table + +@table(name summary) +DF_InstTableX64: +{ + + //- rjf: core + {AAA "ASCII Adjust After Addition" } + {AAD "ASCII Adjust AX Before Division" } + {AAM "ASCII Adjust AX After Multiply" } + {AAS "ASCII Adjust AL After Subtraction" } + {ADC "Add with Carry" } + {ADCX "Unsigned Integer Addition of Two Operands with Carry Flag" } + {ADD "Add" } + {ADDPD "Add Packed Double-Precision Floating-Point Values" } + {ADDPS "Add Packed Single-Precision Floating-Point Values" } + {ADDSD "Add Scalar Double-Precision Floating-Point Values" } + {ADDSS "Add Scalar Single-Precision Floating-Point Values" } + {ADDSUBPD "Packed Double-FP Add/Subtract" } + {ADDSUBPS "Packed Single-FP Add/Subtract" } + {ADOX "Unsigned Integer Addition of Two Operands with Overflow Flag" } + {AESDEC "Perform One Round of an AES Decryption Flow" } + {AESDEC128KL "Perform Ten Rounds of AES Decryption Flow with Key Locker Using 128-Bit Key" } + {AESDEC256KL "Perform 14 Rounds of AES Decryption Flow with Key Locker Using 256-Bit Key" } + {AESDECLAST "Perform Last Round of an AES Decryption Flow" } + {AESDECWIDE128KL "Perform Ten Rounds of AES Decryption Flow with Key Locker on 8 Blocks Using 128-Bit Key" } + {AESDECWIDE256KL "Perform 14 Rounds of AES Decryption Flow with Key Locker on 8 Blocks Using 256-Bit Key" } + {AESENC "Perform One Round of an AES Encryption Flow" } + {AESENC128KL "Perform Ten Rounds of AES Encryption Flow with Key Locker Using 128-Bit Key" } + {AESENC256KL "Perform 14 Rounds of AES Encryption Flow with Key Locker Using 256-Bit Key" } + {AESENCLAST "Perform Last Round of an AES Encryption Flow" } + {AESENCWIDE128KL "Perform Ten Rounds of AES Encryption Flow with Key Locker on 8 Blocks Using 128-Bit Key" } + {AESENCWIDE256KL "Perform 14 Rounds of AES Encryption Flow with Key Locker on 8 Blocks Using 256-Bit Key" } + {AESIMC "Perform the AES InvMixColumn Transformation" } + {AESKEYGENASSIST "AES Round Key Generation Assist" } + {AND "Logical AND" } + {ANDN "Logical AND NOT" } + {ANDNPD "Bitwise Logical AND NOT of Packed Double Precision Floating-Point Values" } + {ANDNPS "Bitwise Logical AND NOT of Packed Single Precision Floating-Point Values" } + {ANDPD "Bitwise Logical AND of Packed Double Precision Floating-Point Values" } + {ANDPS "Bitwise Logical AND of Packed Single Precision Floating-Point Values" } + {ARPL "Adjust RPL Field of Segment Selector" } + {BEXTR "Bit Field Extract" } + {BLENDPD "Blend Packed Double Precision Floating-Point Values" } + {BLENDPS "Blend Packed Single Precision Floating-Point Values" } + {BLENDVPD "Variable Blend Packed Double Precision Floating-Point Values" } + {BLENDVPS "Variable Blend Packed Single Precision Floating-Point Values" } + {BLSI "Extract Lowest Set Isolated Bit" } + {BLSMSK "Get Mask Up to Lowest Set Bit" } + {BLSR "Reset Lowest Set Bit" } + {BNDCL "Check Lower Bound" } + {BNDCN "Check Upper Bound" } + {BNDCU "Check Upper Bound" } + {BNDLDX "Load Extended Bounds Using Address Translation" } + {BNDMK "Make Bounds" } + {BNDMOV "Move Bounds" } + {BNDSTX "Store Extended Bounds Using Address Translation" } + {BOUND "Check Array Index Against Bounds" } + {BSF "Bit Scan Forward" } + {BSR "Bit Scan Reverse" } + {BSWAP "Byte Swap" } + {BT "Bit Test" } + {BTC "Bit Test and Complement" } + {BTR "Bit Test and Reset" } + {BTS "Bit Test and Set" } + {BZHI "Zero High Bits Starting with Specified Bit Position" } + {CALL "Call Procedure" } + {CBW "Convert Byte to Word/Convert Word to Doubleword/Convert Doubleword to Quadword" } + {CDQ "Convert Word to Doubleword/Convert Doubleword to Quadword" } + {CDQE "Convert Byte to Word/Convert Word to Doubleword/Convert Doubleword to Quadword" } + {CLAC "Clear AC Flag in EFLAGS Register" } + {CLC "Clear Carry Flag" } + {CLD "Clear Direction Flag" } + {CLDEMOTE "Cache Line Demote" } + {CLFLUSH "Flush Cache Line" } + {CLFLUSHOPT "Flush Cache Line Optimized" } + {CLI "Clear Interrupt Flag" } + {CLRSSBSY "Clear Busy Flag in a Supervisor Shadow Stack Token" } + {CLTS "Clear Task-Switched Flag in CR0" } + {CLWB "Cache Line Write Back" } + {CMC "Complement Carry Flag" } + {CMOVcc "Conditional Move" } + {CMP "Compare Two Operands" } + {CMPPD "Compare Packed Double-Precision Floating-Point Values" } + {CMPPS "Compare Packed Single-Precision Floating-Point Values" } + {CMPS "Compare String Operands" } + {CMPSB "Compare String Operands" } + {CMPSD "Compare String Operands" } + {CMPSQ "Compare String Operands" } + {CMPSS "Compare Scalar Single-Precision Floating-Point Value" } + {CMPSW "Compare String Operands" } + {CMPXCHG "Compare and Exchange" } + {CMPXCHG16B "Compare and Exchange Bytes" } + {CMPXCHG8B "Compare and Exchange Bytes" } + {COMISD "Compare Scalar Ordered Double-Precision Floating-Point Values and Set EFLAGS" } + {COMISS "Compare Scalar Ordered Single-Precision Floating-Point Values and Set EFLAGS" } + {CPUID "CPU Identification" } + {CQO "Convert Word to Doubleword/Convert Doubleword to Quadword" } + {CRC32 "Accumulate CRC32 Value" } + {CVTDQ2PD "Convert Packed Doubleword Integers to Packed Double-Precision Floating-Point Values" } + {CVTDQ2PS "Convert Packed Doubleword Integers to Packed Single-Precision Floating-Point Values" } + {CVTPD2DQ "Convert Packed Double-Precision Floating-Point Values to Packed Doubleword Integers" } + {CVTPD2PI "Convert Packed Double-Precision FP Values to Packed Dword Integers" } + {CVTPD2PS "Convert Packed Double-Precision Floating-Point Values to Packed Single-Precision Floating-Point Values" } + {CVTPI2PD "Convert Packed Dword Integers to Packed Double-Precision FP Values" } + {CVTPI2PS "Convert Packed Dword Integers to Packed Single-Precision FP Values" } + {CVTPS2DQ "Convert Packed Single-Precision Floating-Point Values to Packed Signed Doubleword Integer Values" } + {CVTPS2PD "Convert Packed Single-Precision Floating-Point Values to Packed Double-Precision Floating-Point Values" } + {CVTPS2PI "Convert Packed Single-Precision FP Values to Packed Dword Integers" } + {CVTSD2SI "Convert Scalar Double-Precision Floating-Point Value to Doubleword Integer" } + {CVTSD2SS "Convert Scalar Double-Precision Floating-Point Value to Scalar Single-Precision Floating-Point Value" } + {CVTSI2SD "Convert Doubleword Integer to Scalar Double-Precision Floating-Point Value" } + {CVTSI2SS "Convert Doubleword Integer to Scalar Single-Precision Floating-Point Value" } + {CVTSS2SD "Convert Scalar Single-Precision Floating-Point Value to Scalar Double-Precision Floating-Point Value" } + {CVTSS2SI "Convert Scalar Single-Precision Floating-Point Value to Doubleword Integer" } + {CVTTPD2DQ "Convert with Truncation Packed Double-Precision Floating-Point Values to Packed Doubleword Integers" } + {CVTTPD2PI "Convert with Truncation Packed Double-Precision FP Values to Packed Dword Integers" } + {CVTTPS2DQ "Convert with Truncation Packed Single-Precision Floating-Point Values to Packed Signed Doubleword Integer Values" } + {CVTTPS2PI "Convert with Truncation Packed Single-Precision FP Values to Packed Dword Integers" } + {CVTTSD2SI "Convert with Truncation Scalar Double-Precision Floating-Point Value to Signed Integer" } + {CVTTSS2SI "Convert with Truncation Scalar Single-Precision Floating-Point Value to Integer" } + {CWD "Convert Word to Doubleword/Convert Doubleword to Quadword" } + {CWDE "Convert Byte to Word/Convert Word to Doubleword/Convert Doubleword to Quadword" } + {DAA "Decimal Adjust AL after Addition" } + {DAS "Decimal Adjust AL after Subtraction" } + {DEC "Decrement by 1" } + {DIV "Unsigned Divide" } + {DIVPD "Divide Packed Double-Precision Floating-Point Values" } + {DIVPS "Divide Packed Single-Precision Floating-Point Values" } + {DIVSD "Divide Scalar Double-Precision Floating-Point Value" } + {DIVSS "Divide Scalar Single-Precision Floating-Point Values" } + {DPPD "Dot Product of Packed Double Precision Floating-Point Values" } + {DPPS "Dot Product of Packed Single Precision Floating-Point Values" } + {EMMS "Empty MMX Technology State" } + {ENCODEKEY128 "Encode 128-Bit Key with Key Locker" } + {ENCODEKEY256 "Encode 256-Bit Key with Key Locker" } + {ENDBR32 "Terminate an Indirect Branch in 32-bit and Compatibility Mode" } + {ENDBR64 "Terminate an Indirect Branch in 64-bit Mode" } + {ENTER "Make Stack Frame for Procedure Parameters" } + {EXTRACTPS "Extract Packed Floating-Point Values" } + {F2XM1 "Compute 2x–1" } + {FABS "Absolute Value" } + {FADD "Add" } + {FADDP "Add" } + {FBLD "Load Binary Coded Decimal" } + {FBSTP "Store BCD Integer and Pop" } + {FCHS "Change Sign" } + {FCLEX "Clear Exceptions" } + {FCMOVcc "Floating-Point Conditional Move" } + {FCOM "Compare Floating Point Values" } + {FCOMI "Compare Floating Point Values and Set EFLAGS" } + {FCOMIP "Compare Floating Point Values and Set EFLAGS" } + {FCOMP "Compare Floating Point Values" } + {FCOMPP "Compare Floating Point Values" } + {FCOS "Cosine" } + {FDECSTP "Decrement Stack-Top Pointer" } + {FDIV "Divide" } + {FDIVP "Divide" } + {FDIVR "Reverse Divide" } + {FDIVRP "Reverse Divide" } + {FFREE "Free Floating-Point Register" } + {FIADD "Add" } + {FICOM "Compare Integer" } + {FICOMP "Compare Integer" } + {FIDIV "Divide" } + {FIDIVR "Reverse Divide" } + {FILD "Load Integer" } + {FIMUL "Multiply" } + {FINCSTP "Increment Stack-Top Pointer" } + {FINIT "Initialize Floating-Point Unit" } + {FIST "Store Integer" } + {FISTP "Store Integer" } + {FISTTP "Store Integer with Truncation" } + {FISUB "Subtract" } + {FISUBR "Reverse Subtract" } + {FLD "Load Floating Point Value" } + {FLD1 "Load Constant" } + {FLDCW "Load x87 FPU Control Word" } + {FLDENV "Load x87 FPU Environment" } + {FLDL2E "Load Constant" } + {FLDL2T "Load Constant" } + {FLDLG2 "Load Constant" } + {FLDLN2 "Load Constant" } + {FLDPI "Load Constant" } + {FLDZ "Load Constant" } + {FMUL "Multiply" } + {FMULP "Multiply" } + {FNCLEX "Clear Exceptions" } + {FNINIT "Initialize Floating-Point Unit" } + {FNOP "No Operation" } + {FNSAVE "Store x87 FPU State" } + {FNSTCW "Store x87 FPU Control Word" } + {FNSTENV "Store x87 FPU Environment" } + {FNSTSW "Store x87 FPU Status Word" } + {FPATAN "Partial Arctangent" } + {FPREM "Partial Remainder" } + {FPREM1 "Partial Remainder" } + {FPTAN "Partial Tangent" } + {FRNDINT "Round to Integer" } + {FRSTOR "Restore x87 FPU State" } + {FSAVE "Store x87 FPU State" } + {FSCALE "Scale" } + {FSIN "Sine" } + {FSINCOS "Sine and Cosine" } + {FSQRT "Square Root" } + {FST "Store Floating Point Value" } + {FSTCW "Store x87 FPU Control Word" } + {FSTENV "Store x87 FPU Environment" } + {FSTP "Store Floating Point Value" } + {FSTSW "Store x87 FPU Status Word" } + {FSUB "Subtract" } + {FSUBP "Subtract" } + {FSUBR "Reverse Subtract" } + {FSUBRP "Reverse Subtract" } + {FTST "TEST" } + {FUCOM "Unordered Compare Floating Point Values" } + {FUCOMI "Compare Floating Point Values and Set EFLAGS" } + {FUCOMIP "Compare Floating Point Values and Set EFLAGS" } + {FUCOMP "Unordered Compare Floating Point Values" } + {FUCOMPP "Unordered Compare Floating Point Values" } + {FWAIT "Wait" } + {FXAM "Examine Floating-Point" } + {FXCH "Exchange Register Contents" } + {FXRSTOR "Restore x87 FPU, MMX, XMM, and MXCSR State" } + {FXSAVE "Save x87 FPU, MMX Technology, and SSE State" } + {FXTRACT "Extract Exponent and Significand" } + {FYL2X "Compute y * log2x" } + {FYL2XP1 "Compute y * log2(x +1)" } + {GF2P8AFFINEINVQB "Galois Field Affine Transformation Inverse" } + {GF2P8AFFINEQB "Galois Field Affine Transformation" } + {GF2P8MULB "Galois Field Multiply Bytes" } + {HADDPD "Packed Double-FP Horizontal Add" } + {HADDPS "Packed Single-FP Horizontal Add" } + {HLT "Halt" } + {HRESET "History Reset" } + {HSUBPD "Packed Double-FP Horizontal Subtract" } + {HSUBPS "Packed Single-FP Horizontal Subtract" } + {IDIV "Signed Divide" } + {IMUL "Signed Multiply" } + {IN "Input from Port" } + {INC "Increment by 1" } + {INCSSPD "Increment Shadow Stack Pointer" } + {INCSSPQ "Increment Shadow Stack Pointer" } + {INS "Input from Port to String" } + {INSB "Input from Port to String" } + {INSD "Input from Port to String" } + {INSERTPS "Insert Scalar Single-Precision Floating-Point Value" } + {INSW "Input from Port to String" } + {INT "Call to Interrupt Procedure" } + {INT1 "Call to Interrupt Procedure" } + {INT3 "Call to Interrupt Procedure" } + {INTO "Call to Interrupt Procedure" } + {INVD "Invalidate Internal Caches" } + {INVLPG "Invalidate TLB Entries" } + {INVPCID "Invalidate Process-Context Identifier" } + {IRET "Interrupt Return" } + {IRETD "Interrupt Return" } + {IRETQ "Interrupt Return" } + {JMP "Jump" } + {Jcc "Jump if Condition Is Met" } + {KADDB "ADD Two Masks" } + {KADDD "ADD Two Masks" } + {KADDQ "ADD Two Masks" } + {KADDW "ADD Two Masks" } + {KANDB "Bitwise Logical AND Masks" } + {KANDD "Bitwise Logical AND Masks" } + {KANDNB "Bitwise Logical AND NOT Masks" } + {KANDND "Bitwise Logical AND NOT Masks" } + {KANDNQ "Bitwise Logical AND NOT Masks" } + {KANDNW "Bitwise Logical AND NOT Masks" } + {KANDQ "Bitwise Logical AND Masks" } + {KANDW "Bitwise Logical AND Masks" } + {KMOVB "Move from and to Mask Registers" } + {KMOVD "Move from and to Mask Registers" } + {KMOVQ "Move from and to Mask Registers" } + {KMOVW "Move from and to Mask Registers" } + {KNOTB "NOT Mask Register" } + {KNOTD "NOT Mask Register" } + {KNOTQ "NOT Mask Register" } + {KNOTW "NOT Mask Register" } + {KORB "Bitwise Logical OR Masks" } + {KORD "Bitwise Logical OR Masks" } + {KORQ "Bitwise Logical OR Masks" } + {KORTESTB "OR Masks And Set Flags" } + {KORTESTD "OR Masks And Set Flags" } + {KORTESTQ "OR Masks And Set Flags" } + {KORTESTW "OR Masks And Set Flags" } + {KORW "Bitwise Logical OR Masks" } + {KSHIFTLB "Shift Left Mask Registers" } + {KSHIFTLD "Shift Left Mask Registers" } + {KSHIFTLQ "Shift Left Mask Registers" } + {KSHIFTLW "Shift Left Mask Registers" } + {KSHIFTRB "Shift Right Mask Registers" } + {KSHIFTRD "Shift Right Mask Registers" } + {KSHIFTRQ "Shift Right Mask Registers" } + {KSHIFTRW "Shift Right Mask Registers" } + {KTESTB "Packed Bit Test Masks and Set Flags" } + {KTESTD "Packed Bit Test Masks and Set Flags" } + {KTESTQ "Packed Bit Test Masks and Set Flags" } + {KTESTW "Packed Bit Test Masks and Set Flags" } + {KUNPCKBW "Unpack for Mask Registers" } + {KUNPCKDQ "Unpack for Mask Registers" } + {KUNPCKWD "Unpack for Mask Registers" } + {KXNORB "Bitwise Logical XNOR Masks" } + {KXNORD "Bitwise Logical XNOR Masks" } + {KXNORQ "Bitwise Logical XNOR Masks" } + {KXNORW "Bitwise Logical XNOR Masks" } + {KXORB "Bitwise Logical XOR Masks" } + {KXORD "Bitwise Logical XOR Masks" } + {KXORQ "Bitwise Logical XOR Masks" } + {KXORW "Bitwise Logical XOR Masks" } + {LAHF "Load Status Flags into AH Register" } + {LAR "Load Access Rights Byte" } + {LDDQU "Load Unaligned Integer 128 Bits" } + {LDMXCSR "Load MXCSR Register" } + {LDS "Load Far Pointer" } + {LEA "Load Effective Address" } + {LEAVE "High Level Procedure Exit" } + {LES "Load Far Pointer" } + {LFENCE "Load Fence" } + {LFS "Load Far Pointer" } + {LGDT "Load Global/Interrupt Descriptor Table Register" } + {LGS "Load Far Pointer" } + {LIDT "Load Global/Interrupt Descriptor Table Register" } + {LLDT "Load Local Descriptor Table Register" } + {LMSW "Load Machine Status Word" } + {LOADIWKEY "Load Internal Wrapping Key with Key Locker" } + {LOCK "Assert LOCK# Signal Prefix" } + {LODS "Load String" } + {LODSB "Load String" } + {LODSD "Load String" } + {LODSQ "Load String" } + {LODSW "Load String" } + {LOOP "Loop According to ECX Counter" } + {LOOPcc "Loop According to ECX Counter" } + {LSL "Load Segment Limit" } + {LSS "Load Far Pointer" } + {LTR "Load Task Register" } + {LZCNT "Count the Number of Leading Zero Bits" } + {MASKMOVDQU "Store Selected Bytes of Double Quadword" } + {MASKMOVQ "Store Selected Bytes of Quadword" } + {MAXPD "Maximum of Packed Double-Precision Floating-Point Values" } + {MAXPS "Maximum of Packed Single-Precision Floating-Point Values" } + {MAXSD "Return Maximum Scalar Double-Precision Floating-Point Value" } + {MAXSS "Return Maximum Scalar Single-Precision Floating-Point Value" } + {MFENCE "Memory Fence" } + {MINPD "Minimum of Packed Double-Precision Floating-Point Values" } + {MINPS "Minimum of Packed Single-Precision Floating-Point Values" } + {MINSD "Return Minimum Scalar Double-Precision Floating-Point Value" } + {MINSS "Return Minimum Scalar Single-Precision Floating-Point Value" } + {MONITOR "Set Up Monitor Address" } + {MOV "Move" } + {MOVAPD "Move Aligned Packed Double-Precision Floating-Point Values" } + {MOVAPS "Move Aligned Packed Single-Precision Floating-Point Values" } + {MOVBE "Move Data After Swapping Bytes" } + {MOVD "Move Doubleword/Move Quadword" } + {MOVDDUP "Replicate Double FP Values" } + {MOVDIR64B "Move 64 Bytes as Direct Store" } + {MOVDIRI "Move Doubleword as Direct Store" } + {MOVDQ2Q "Move Quadword from XMM to MMX Technology Register" } + {MOVDQA "Move Aligned Packed Integer Values" } + {MOVDQU "Move Unaligned Packed Integer Values" } + {MOVHLPS "Move Packed Single-Precision Floating-Point Values High to Low" } + {MOVHPD "Move High Packed Double-Precision Floating-Point Value" } + {MOVHPS "Move High Packed Single-Precision Floating-Point Values" } + {MOVLHPS "Move Packed Single-Precision Floating-Point Values Low to High" } + {MOVLPD "Move Low Packed Double-Precision Floating-Point Value" } + {MOVLPS "Move Low Packed Single-Precision Floating-Point Values" } + {MOVMSKPD "Extract Packed Double-Precision Floating-Point Sign Mask" } + {MOVMSKPS "Extract Packed Single-Precision Floating-Point Sign Mask" } + {MOVNTDQ "Store Packed Integers Using Non-Temporal Hint" } + {MOVNTDQA "Load Double Quadword Non-Temporal Aligned Hint" } + {MOVNTI "Store Doubleword Using Non-Temporal Hint" } + {MOVNTPD "Store Packed Double-Precision Floating-Point Values Using Non-Temporal Hint" } + {MOVNTPS "Store Packed Single-Precision Floating-Point Values Using Non-Temporal Hint" } + {MOVNTQ "Store of Quadword Using Non-Temporal Hint" } + {MOVQ "Move Doubleword/Move Quadword" } + {MOVQ2DQ "Move Quadword from MMX Technology to XMM Register" } + {MOVS "Move Data from String to String" } + {MOVSB "Move Data from String to String" } + {MOVSD "Move Data from String to String" } + {MOVSHDUP "Replicate Single FP Values" } + {MOVSLDUP "Replicate Single FP Values" } + {MOVSQ "Move Data from String to String" } + {MOVSS "Move or Merge Scalar Single-Precision Floating-Point Value" } + {MOVSW "Move Data from String to String" } + {MOVSX "Move with Sign-Extension" } + {MOVSXD "Move with Sign-Extension" } + {MOVUPD "Move Unaligned Packed Double-Precision Floating-Point Values" } + {MOVUPS "Move Unaligned Packed Single-Precision Floating-Point Values" } + {MOVZX "Move with Zero-Extend" } + {MPSADBW "Compute Multiple Packed Sums of Absolute Difference" } + {MUL "Unsigned Multiply" } + {MULPD "Multiply Packed Double-Precision Floating-Point Values" } + {MULPS "Multiply Packed Single-Precision Floating-Point Values" } + {MULSD "Multiply Scalar Double-Precision Floating-Point Value" } + {MULSS "Multiply Scalar Single-Precision Floating-Point Values" } + {MULX "Unsigned Multiply Without Affecting Flags" } + {MWAIT "Monitor Wait" } + {NEG "Two's Complement Negation" } + {NOP "No Operation" } + {NOT "One's Complement Negation" } + {OR "Logical Inclusive OR" } + {ORPD "Bitwise Logical OR of Packed Double Precision Floating-Point Values" } + {ORPS "Bitwise Logical OR of Packed Single Precision Floating-Point Values" } + {OUT "Output to Port" } + {OUTS "Output String to Port" } + {OUTSB "Output String to Port" } + {OUTSD "Output String to Port" } + {OUTSW "Output String to Port" } + {PABSB "Packed Absolute Value" } + {PABSD "Packed Absolute Value" } + {PABSQ "Packed Absolute Value" } + {PABSW "Packed Absolute Value" } + {PACKSSDW "Pack with Signed Saturation" } + {PACKSSWB "Pack with Signed Saturation" } + {PACKUSDW "Pack with Unsigned Saturation" } + {PACKUSWB "Pack with Unsigned Saturation" } + {PADDB "Add Packed Integers" } + {PADDD "Add Packed Integers" } + {PADDQ "Add Packed Integers" } + {PADDSB "Add Packed Signed Integers with Signed Saturation" } + {PADDSW "Add Packed Signed Integers with Signed Saturation" } + {PADDUSB "Add Packed Unsigned Integers with Unsigned Saturation" } + {PADDUSW "Add Packed Unsigned Integers with Unsigned Saturation" } + {PADDW "Add Packed Integers" } + {PALIGNR "Packed Align Right" } + {PAND "Logical AND" } + {PANDN "Logical AND NOT" } + {PAUSE "Spin Loop Hint" } + {PAVGB "Average Packed Integers" } + {PAVGW "Average Packed Integers" } + {PBLENDVB "Variable Blend Packed Bytes" } + {PBLENDW "Blend Packed Words" } + {PCLMULQDQ "Carry-Less Multiplication Quadword" } + {PCMPEQB "Compare Packed Data for Equal" } + {PCMPEQD "Compare Packed Data for Equal" } + {PCMPEQQ "Compare Packed Qword Data for Equal" } + {PCMPEQW "Compare Packed Data for Equal" } + {PCMPESTRI "Packed Compare Explicit Length Strings, Return Index" } + {PCMPESTRM "Packed Compare Explicit Length Strings, Return Mask" } + {PCMPGTB "Compare Packed Signed Integers for Greater Than" } + {PCMPGTD "Compare Packed Signed Integers for Greater Than" } + {PCMPGTQ "Compare Packed Data for Greater Than" } + {PCMPGTW "Compare Packed Signed Integers for Greater Than" } + {PCMPISTRI "Packed Compare Implicit Length Strings, Return Index" } + {PCMPISTRM "Packed Compare Implicit Length Strings, Return Mask" } + {PCONFIG "Platform Configuration" } + {PDEP "Parallel Bits Deposit" } + {PEXT "Parallel Bits Extract" } + {PEXTRB "Extract Byte/Dword/Qword" } + {PEXTRD "Extract Byte/Dword/Qword" } + {PEXTRQ "Extract Byte/Dword/Qword" } + {PEXTRW "Extract Word" } + {PHADDD "Packed Horizontal Add" } + {PHADDSW "Packed Horizontal Add and Saturate" } + {PHADDW "Packed Horizontal Add" } + {PHMINPOSUW "Packed Horizontal Word Minimum" } + {PHSUBD "Packed Horizontal Subtract" } + {PHSUBSW "Packed Horizontal Subtract and Saturate" } + {PHSUBW "Packed Horizontal Subtract" } + {PINSRB "Insert Byte/Dword/Qword" } + {PINSRD "Insert Byte/Dword/Qword" } + {PINSRQ "Insert Byte/Dword/Qword" } + {PINSRW "Insert Word" } + {PMADDUBSW "Multiply and Add Packed Signed and Unsigned Bytes" } + {PMADDWD "Multiply and Add Packed Integers" } + {PMAXSB "Maximum of Packed Signed Integers" } + {PMAXSD "Maximum of Packed Signed Integers" } + {PMAXSQ "Maximum of Packed Signed Integers" } + {PMAXSW "Maximum of Packed Signed Integers" } + {PMAXUB "Maximum of Packed Unsigned Integers" } + {PMAXUD "Maximum of Packed Unsigned Integers" } + {PMAXUQ "Maximum of Packed Unsigned Integers" } + {PMAXUW "Maximum of Packed Unsigned Integers" } + {PMINSB "Minimum of Packed Signed Integers" } + {PMINSD "Minimum of Packed Signed Integers" } + {PMINSQ "Minimum of Packed Signed Integers" } + {PMINSW "Minimum of Packed Signed Integers" } + {PMINUB "Minimum of Packed Unsigned Integers" } + {PMINUD "Minimum of Packed Unsigned Integers" } + {PMINUQ "Minimum of Packed Unsigned Integers" } + {PMINUW "Minimum of Packed Unsigned Integers" } + {PMOVMSKB "Move Byte Mask" } + {PMOVSX "Packed Move with Sign Extend" } + {PMOVZX "Packed Move with Zero Extend" } + {PMULDQ "Multiply Packed Doubleword Integers" } + {PMULHRSW "Packed Multiply High with Round and Scale" } + {PMULHUW "Multiply Packed Unsigned Integers and Store High Result" } + {PMULHW "Multiply Packed Signed Integers and Store High Result" } + {PMULLD "Multiply Packed Integers and Store Low Result" } + {PMULLQ "Multiply Packed Integers and Store Low Result" } + {PMULLW "Multiply Packed Signed Integers and Store Low Result" } + {PMULUDQ "Multiply Packed Unsigned Doubleword Integers" } + {POP "Pop a Value from the Stack" } + {POPA "Pop All General-Purpose Registers" } + {POPAD "Pop All General-Purpose Registers" } + {POPCNT "Return the Count of Number of Bits Set to 1" } + {POPF "Pop Stack into EFLAGS Register" } + {POPFD "Pop Stack into EFLAGS Register" } + {POPFQ "Pop Stack into EFLAGS Register" } + {POR "Bitwise Logical OR" } + {PREFETCHW "Prefetch Data into Caches in Anticipation of a Write" } + {PREFETCHh "Prefetch Data Into Caches" } + {PSADBW "Compute Sum of Absolute Differences" } + {PSHUFB "Packed Shuffle Bytes" } + {PSHUFD "Shuffle Packed Doublewords" } + {PSHUFHW "Shuffle Packed High Words" } + {PSHUFLW "Shuffle Packed Low Words" } + {PSHUFW "Shuffle Packed Words" } + {PSIGNB "Packed SIGN" } + {PSIGND "Packed SIGN" } + {PSIGNW "Packed SIGN" } + {PSLLD "Shift Packed Data Left Logical" } + {PSLLDQ "Shift Double Quadword Left Logical" } + {PSLLQ "Shift Packed Data Left Logical" } + {PSLLW "Shift Packed Data Left Logical" } + {PSRAD "Shift Packed Data Right Arithmetic" } + {PSRAQ "Shift Packed Data Right Arithmetic" } + {PSRAW "Shift Packed Data Right Arithmetic" } + {PSRLD "Shift Packed Data Right Logical" } + {PSRLDQ "Shift Double Quadword Right Logical" } + {PSRLQ "Shift Packed Data Right Logical" } + {PSRLW "Shift Packed Data Right Logical" } + {PSUBB "Subtract Packed Integers" } + {PSUBD "Subtract Packed Integers" } + {PSUBQ "Subtract Packed Quadword Integers" } + {PSUBSB "Subtract Packed Signed Integers with Signed Saturation" } + {PSUBSW "Subtract Packed Signed Integers with Signed Saturation" } + {PSUBUSB "Subtract Packed Unsigned Integers with Unsigned Saturation" } + {PSUBUSW "Subtract Packed Unsigned Integers with Unsigned Saturation" } + {PSUBW "Subtract Packed Integers" } + {PTEST "Logical Compare" } + {PTWRITE "Write Data to a Processor Trace Packet" } + {PUNPCKHBW "Unpack High Data" } + {PUNPCKHDQ "Unpack High Data" } + {PUNPCKHQDQ "Unpack High Data" } + {PUNPCKHWD "Unpack High Data" } + {PUNPCKLBW "Unpack Low Data" } + {PUNPCKLDQ "Unpack Low Data" } + {PUNPCKLQDQ "Unpack Low Data" } + {PUNPCKLWD "Unpack Low Data" } + {PUSH "Push Word, Doubleword or Quadword Onto the Stack" } + {PUSHA "Push All General-Purpose Registers" } + {PUSHAD "Push All General-Purpose Registers" } + {PUSHF "Push EFLAGS Register onto the Stack" } + {PUSHFD "Push EFLAGS Register onto the Stack" } + {PUSHFQ "Push EFLAGS Register onto the Stack" } + {PXOR "Logical Exclusive OR" } + {RCL "Rotate" } + {RCPPS "Compute Reciprocals of Packed Single-Precision Floating-Point Values" } + {RCPSS "Compute Reciprocal of Scalar Single-Precision Floating-Point Values" } + {RCR "Rotate" } + {RDFSBASE "Read FS/GS Segment Base" } + {RDGSBASE "Read FS/GS Segment Base" } + {RDMSR "Read from Model Specific Register" } + {RDPID "Read Processor ID" } + {RDPKRU "Read Protection Key Rights for User Pages" } + {RDPMC "Read Performance-Monitoring Counters" } + {RDRAND "Read Random Number" } + {RDSEED "Read Random SEED" } + {RDSSPD "Read Shadow Stack Pointer" } + {RDSSPQ "Read Shadow Stack Pointer" } + {RDTSC "Read Time-Stamp Counter" } + {RDTSCP "Read Time-Stamp Counter and Processor ID" } + {REP "Repeat String Operation Prefix" } + {REPE "Repeat String Operation Prefix" } + {REPNE "Repeat String Operation Prefix" } + {REPNZ "Repeat String Operation Prefix" } + {REPZ "Repeat String Operation Prefix" } + {RET "Return from Procedure" } + {ROL "Rotate" } + {ROR "Rotate" } + {RORX "Rotate Right Logical Without Affecting Flags" } + {ROUNDPD "Round Packed Double Precision Floating-Point Values" } + {ROUNDPS "Round Packed Single Precision Floating-Point Values" } + {ROUNDSD "Round Scalar Double Precision Floating-Point Values" } + {ROUNDSS "Round Scalar Single Precision Floating-Point Values" } + {RSM "Resume from System Management Mode" } + {RSQRTPS "Compute Reciprocals of Square Roots of Packed Single-Precision Floating-Point Values" } + {RSQRTSS "Compute Reciprocal of Square Root of Scalar Single-Precision Floating-Point Value" } + {RSTORSSP "Restore Saved Shadow Stack Pointer" } + {SAHF "Store AH into Flags" } + {SAL "Shift" } + {SAR "Shift" } + {SARX "Shift Without Affecting Flags" } + {SAVEPREVSSP "Save Previous Shadow Stack Pointer" } + {SBB "Integer Subtraction with Borrow" } + {SCAS "Scan String" } + {SCASB "Scan String" } + {SCASD "Scan String" } + {SCASW "Scan String" } + {SERIALIZE "Serialize Instruction Execution" } + {SETSSBSY "Mark Shadow Stack Busy" } + {SETcc "Set Byte on Condition" } + {SFENCE "Store Fence" } + {SGDT "Store Global Descriptor Table Register" } + {SHA1MSG1 "Perform an Intermediate Calculation for the Next Four SHA1 Message Dwords" } + {SHA1MSG2 "Perform a Final Calculation for the Next Four SHA1 Message Dwords" } + {SHA1NEXTE "Calculate SHA1 State Variable E after Four Rounds" } + {SHA1RNDS4 "Perform Four Rounds of SHA1 Operation" } + {SHA256MSG1 "Perform an Intermediate Calculation for the Next Four SHA256 Message Dwords" } + {SHA256MSG2 "Perform a Final Calculation for the Next Four SHA256 Message Dwords" } + {SHA256RNDS2 "Perform Two Rounds of SHA256 Operation" } + {SHL "Shift" } + {SHLD "Double Precision Shift Left" } + {SHLX "Shift Without Affecting Flags" } + {SHR "Shift" } + {SHRD "Double Precision Shift Right" } + {SHRX "Shift Without Affecting Flags" } + {SHUFPD "Packed Interleave Shuffle of Pairs of Double-Precision Floating-Point Values" } + {SHUFPS "Packed Interleave Shuffle of Quadruplets of Single-Precision Floating-Point Values" } + {SIDT "Store Interrupt Descriptor Table Register" } + {SLDT "Store Local Descriptor Table Register" } + {SMSW "Store Machine Status Word" } + {SQRTPD "Square Root of Double-Precision Floating-Point Values" } + {SQRTPS "Square Root of Single-Precision Floating-Point Values" } + {SQRTSD "Compute Square Root of Scalar Double-Precision Floating-Point Value" } + {SQRTSS "Compute Square Root of Scalar Single-Precision Value" } + {STAC "Set AC Flag in EFLAGS Register" } + {STC "Set Carry Flag" } + {STD "Set Direction Flag" } + {STI "Set Interrupt Flag" } + {STMXCSR "Store MXCSR Register State" } + {STOS "Store String" } + {STOSB "Store String" } + {STOSD "Store String" } + {STOSQ "Store String" } + {STOSW "Store String" } + {STR "Store Task Register" } + {SUB "Subtract" } + {SUBPD "Subtract Packed Double-Precision Floating-Point Values" } + {SUBPS "Subtract Packed Single-Precision Floating-Point Values" } + {SUBSD "Subtract Scalar Double-Precision Floating-Point Value" } + {SUBSS "Subtract Scalar Single-Precision Floating-Point Value" } + {SWAPGS "Swap GS Base Register" } + {SYSCALL "Fast System Call" } + {SYSENTER "Fast System Call" } + {SYSEXIT "Fast Return from Fast System Call" } + {SYSRET "Return From Fast System Call" } + {TEST "Logical Compare" } + {TPAUSE "Timed PAUSE" } + {TZCNT "Count the Number of Trailing Zero Bits" } + {UCOMISD "Unordered Compare Scalar Double-Precision Floating-Point Values and Set EFLAGS" } + {UCOMISS "Unordered Compare Scalar Single-Precision Floating-Point Values and Set EFLAGS" } + {UD "Undefined Instruction" } + {UMONITOR "User Level Set Up Monitor Address" } + {UMWAIT "User Level Monitor Wait" } + {UNPCKHPD "Unpack and Interleave High Packed Double-Precision Floating-Point Values" } + {UNPCKHPS "Unpack and Interleave High Packed Single-Precision Floating-Point Values" } + {UNPCKLPD "Unpack and Interleave Low Packed Double-Precision Floating-Point Values" } + {UNPCKLPS "Unpack and Interleave Low Packed Single-Precision Floating-Point Values" } + {VALIGND "Align Doubleword/Quadword Vectors" } + {VALIGNQ "Align Doubleword/Quadword Vectors" } + {VBLENDMPD "Blend Float64/Float32 Vectors Using an OpMask Control" } + {VBLENDMPS "Blend Float64/Float32 Vectors Using an OpMask Control" } + {VBROADCAST "Load with Broadcast Floating-Point Data" } + {VCOMPRESSPD "Store Sparse Packed Double-Precision Floating-Point Values into Dense Memory" } + {VCOMPRESSPS "Store Sparse Packed Single-Precision Floating-Point Values into Dense Memory" } + {VCOMPRESSW "Store Sparse Packed Byte/Word Integer Values into Dense Memory/Register" } + {VCVTNE2PS2BF16 "Convert Two Packed Single Data to One Packed BF16 Data" } + {VCVTNEPS2BF16 "Convert Packed Single Data to Packed BF16 Data" } + {VCVTPD2QQ "Convert Packed Double-Precision Floating-Point Values to Packed Quadword Integers" } + {VCVTPD2UDQ "Convert Packed Double-Precision Floating-Point Values to Packed Unsigned Doubleword Integers" } + {VCVTPD2UQQ "Convert Packed Double-Precision Floating-Point Values to Packed Unsigned Quadword Integers" } + {VCVTPH2PS "Convert 16-bit FP values to Single-Precision FP values" } + {VCVTPS2PH "Convert Single-Precision FP value to 16-bit FP value" } + {VCVTPS2QQ "Convert Packed Single Precision Floating-Point Values to Packed Signed Quadword Integer Values" } + {VCVTPS2UDQ "Convert Packed Single-Precision Floating-Point Values to Packed Unsigned Doubleword Integer Values" } + {VCVTPS2UQQ "Convert Packed Single Precision Floating-Point Values to Packed Unsigned Quadword Integer Values" } + {VCVTQQ2PD "Convert Packed Quadword Integers to Packed Double-Precision Floating-Point Values" } + {VCVTQQ2PS "Convert Packed Quadword Integers to Packed Single-Precision Floating-Point Values" } + {VCVTSD2USI "Convert Scalar Double-Precision Floating-Point Value to Unsigned Doubleword Integer" } + {VCVTSS2USI "Convert Scalar Single-Precision Floating-Point Value to Unsigned Doubleword Integer" } + {VCVTTPD2QQ "Convert with Truncation Packed Double-Precision Floating-Point Values to Packed Quadword Integers" } + {VCVTTPD2UDQ "Convert with Truncation Packed Double-Precision Floating-Point Values to Packed Unsigned Doubleword Integers" } + {VCVTTPD2UQQ "Convert with Truncation Packed Double-Precision Floating-Point Values to Packed Unsigned Quadword Integers" } + {VCVTTPS2QQ "Convert with Truncation Packed Single Precision Floating-Point Values to Packed Signed Quadword Integer Values" } + {VCVTTPS2UDQ "Convert with Truncation Packed Single-Precision Floating-Point Values to Packed Unsigned Doubleword Integer Values" } + {VCVTTPS2UQQ "Convert with Truncation Packed Single Precision Floating-Point Values to Packed Unsigned Quadword Integer Values" } + {VCVTTSD2USI "Convert with Truncation Scalar Double-Precision Floating-Point Value to Unsigned Integer" } + {VCVTTSS2USI "Convert with Truncation Scalar Single-Precision Floating-Point Value to Unsigned Integer" } + {VCVTUDQ2PD "Convert Packed Unsigned Doubleword Integers to Packed Double-Precision Floating-Point Values" } + {VCVTUDQ2PS "Convert Packed Unsigned Doubleword Integers to Packed Single-Precision Floating-Point Values" } + {VCVTUQQ2PD "Convert Packed Unsigned Quadword Integers to Packed Double-Precision Floating-Point Values" } + {VCVTUQQ2PS "Convert Packed Unsigned Quadword Integers to Packed Single-Precision Floating-Point Values" } + {VCVTUSI2SD "Convert Unsigned Integer to Scalar Double-Precision Floating-Point Value" } + {VCVTUSI2SS "Convert Unsigned Integer to Scalar Single-Precision Floating-Point Value" } + {VDBPSADBW "Double Block Packed Sum-Absolute-Differences (SAD) on Unsigned Bytes" } + {VDPBF16PS "Dot Product of BF16 Pairs Accumulated into Packed Single Precision" } + {VERR "Verify a Segment for Reading or Writing" } + {VERW "Verify a Segment for Reading or Writing" } + {VEXPANDPD "Load Sparse Packed Double-Precision Floating-Point Values from Dense Memory" } + {VEXPANDPS "Load Sparse Packed Single-Precision Floating-Point Values from Dense Memory" } + {VEXTRACTF128 "Extr act Packed Floating-Point Values" } + {VEXTRACTF32x4 "Extr act Packed Floating-Point Values" } + {VEXTRACTF32x8 "Extr act Packed Floating-Point Values" } + {VEXTRACTF64x2 "Extr act Packed Floating-Point Values" } + {VEXTRACTF64x4 "Extr act Packed Floating-Point Values" } + {VEXTRACTI128 "Extract packed Integer Values" } + {VEXTRACTI32x4 "Extract packed Integer Values" } + {VEXTRACTI32x8 "Extract packed Integer Values" } + {VEXTRACTI64x2 "Extract packed Integer Values" } + {VEXTRACTI64x4 "Extract packed Integer Values" } + {VFIXUPIMMPD "Fix Up Special Packed Float64 Values" } + {VFIXUPIMMPS "Fix Up Special Packed Float32 Values" } + {VFIXUPIMMSD "Fix Up Special Scalar Float64 Value" } + {VFIXUPIMMSS "Fix Up Special Scalar Float32 Value" } + {VFMADD132PD "Fused Multiply-Add of Packed Double- Precision Floating-Point Values" } + {VFMADD132PS "Fused Multiply-Add of Packed Single- Precision Floating-Point Values" } + {VFMADD132SD "Fused Multiply-Add of Scalar Double- Precision Floating-Point Values" } + {VFMADD132SS "Fused Multiply-Add of Scalar Single-Precision Floating-Point Values" } + {VFMADD213PD "Fused Multiply-Add of Packed Double- Precision Floating-Point Values" } + {VFMADD213PS "Fused Multiply-Add of Packed Single- Precision Floating-Point Values" } + {VFMADD213SD "Fused Multiply-Add of Scalar Double- Precision Floating-Point Values" } + {VFMADD213SS "Fused Multiply-Add of Scalar Single-Precision Floating-Point Values" } + {VFMADD231PD "Fused Multiply-Add of Packed Double- Precision Floating-Point Values" } + {VFMADD231PS "Fused Multiply-Add of Packed Single- Precision Floating-Point Values" } + {VFMADD231SD "Fused Multiply-Add of Scalar Double- Precision Floating-Point Values" } + {VFMADD231SS "Fused Multiply-Add of Scalar Single-Precision Floating-Point Values" } + {VFMADDSUB132PD "Fused Multiply-Alternating Add/Subtract of Packed Double-Precision Floating-Point Values" } + {VFMADDSUB132PS "Fused Multiply-Alternating Add/Subtract of Packed Single-Precision Floating-Point Values" } + {VFMADDSUB213PD "Fused Multiply-Alternating Add/Subtract of Packed Double-Precision Floating-Point Values" } + {VFMADDSUB213PS "Fused Multiply-Alternating Add/Subtract of Packed Single-Precision Floating-Point Values" } + {VFMADDSUB231PD "Fused Multiply-Alternating Add/Subtract of Packed Double-Precision Floating-Point Values" } + {VFMADDSUB231PS "Fused Multiply-Alternating Add/Subtract of Packed Single-Precision Floating-Point Values" } + {VFMSUB132PD "Fused Multiply-Subtract of Packed Double- Precision Floating-Point Values" } + {VFMSUB132PS "Fused Multiply-Subtract of Packed Single- Precision Floating-Point Values" } + {VFMSUB132SD "Fused Multiply-Subtract of Scalar Double- Precision Floating-Point Values" } + {VFMSUB132SS "Fused Multiply-Subtract of Scalar Single- Precision Floating-Point Values" } + {VFMSUB213PD "Fused Multiply-Subtract of Packed Double- Precision Floating-Point Values" } + {VFMSUB213PS "Fused Multiply-Subtract of Packed Single- Precision Floating-Point Values" } + {VFMSUB213SD "Fused Multiply-Subtract of Scalar Double- Precision Floating-Point Values" } + {VFMSUB213SS "Fused Multiply-Subtract of Scalar Single- Precision Floating-Point Values" } + {VFMSUB231PD "Fused Multiply-Subtract of Packed Double- Precision Floating-Point Values" } + {VFMSUB231PS "Fused Multiply-Subtract of Packed Single- Precision Floating-Point Values" } + {VFMSUB231SD "Fused Multiply-Subtract of Scalar Double- Precision Floating-Point Values" } + {VFMSUB231SS "Fused Multiply-Subtract of Scalar Single- Precision Floating-Point Values" } + {VFMSUBADD132PD "Fused Multiply-Alternating Subtract/Add of Packed Double-Precision Floating-Point Values" } + {VFMSUBADD132PS "Fused Multiply-Alternating Subtract/Add of Packed Single-Precision Floating-Point Values" } + {VFMSUBADD213PD "Fused Multiply-Alternating Subtract/Add of Packed Double-Precision Floating-Point Values" } + {VFMSUBADD213PS "Fused Multiply-Alternating Subtract/Add of Packed Single-Precision Floating-Point Values" } + {VFMSUBADD231PD "Fused Multiply-Alternating Subtract/Add of Packed Double-Precision Floating-Point Values" } + {VFMSUBADD231PS "Fused Multiply-Alternating Subtract/Add of Packed Single-Precision Floating-Point Values" } + {VFNMADD132PD "Fused Negative Multiply-Add of Packed Double-Precision Floating-Point Values" } + {VFNMADD132PS "Fused Negative Multiply-Add of Packed Single-Precision Floating-Point Values" } + {VFNMADD132SD "Fused Negative Multiply-Add of Scalar Double-Precision Floating-Point Values" } + {VFNMADD132SS "Fused Negative Multiply-Add of Scalar Single-Precision Floating-Point Values" } + {VFNMADD213PD "Fused Negative Multiply-Add of Packed Double-Precision Floating-Point Values" } + {VFNMADD213PS "Fused Negative Multiply-Add of Packed Single-Precision Floating-Point Values" } + {VFNMADD213SD "Fused Negative Multiply-Add of Scalar Double-Precision Floating-Point Values" } + {VFNMADD213SS "Fused Negative Multiply-Add of Scalar Single-Precision Floating-Point Values" } + {VFNMADD231PD "Fused Negative Multiply-Add of Packed Double-Precision Floating-Point Values" } + {VFNMADD231PS "Fused Negative Multiply-Add of Packed Single-Precision Floating-Point Values" } + {VFNMADD231SD "Fused Negative Multiply-Add of Scalar Double-Precision Floating-Point Values" } + {VFNMADD231SS "Fused Negative Multiply-Add of Scalar Single-Precision Floating-Point Values" } + {VFNMSUB132PD "Fused Negative Multiply-Subtract of Packed Double-Precision Floating-Point Values" } + {VFNMSUB132PS "Fused Negative Multiply-Subtract of Packed Single-Precision Floating-Point Values" } + {VFNMSUB132SD "Fused Negative Multiply-Subtract of Scalar Double-Precision Floating-Point Values" } + {VFNMSUB132SS "Fused Negative Multiply-Subtract of Scalar Single-Precision Floating-Point Values" } + {VFNMSUB213PD "Fused Negative Multiply-Subtract of Packed Double-Precision Floating-Point Values" } + {VFNMSUB213PS "Fused Negative Multiply-Subtract of Packed Single-Precision Floating-Point Values" } + {VFNMSUB213SD "Fused Negative Multiply-Subtract of Scalar Double-Precision Floating-Point Values" } + {VFNMSUB213SS "Fused Negative Multiply-Subtract of Scalar Single-Precision Floating-Point Values" } + {VFNMSUB231PD "Fused Negative Multiply-Subtract of Packed Double-Precision Floating-Point Values" } + {VFNMSUB231PS "Fused Negative Multiply-Subtract of Packed Single-Precision Floating-Point Values" } + {VFNMSUB231SD "Fused Negative Multiply-Subtract of Scalar Double-Precision Floating-Point Values" } + {VFNMSUB231SS "Fused Negative Multiply-Subtract of Scalar Single-Precision Floating-Point Values" } + {VFPCLASSPD "Tests Types Of a Packed Float64 Values" } + {VFPCLASSPS "Tests Types Of a Packed Float32 Values" } + {VFPCLASSSD "Tests Types Of a Scalar Float64 Values" } + {VFPCLASSSS "Tests Types Of a Scalar Float32 Values" } + {VGATHERDPD "Gather Packed DP FP Values Using Signed Dword/Qword Indices" } + {VGATHERDPS "Gather Packed SP FP values Using Signed Dword/Qword Indices" } + {VGATHERQPD "Gather Packed DP FP Values Using Signed Dword/Qword Indices" } + {VGATHERQPS "Gather Packed SP FP values Using Signed Dword/Qword Indices" } + {VGETEXPPD "Convert Exponents of Packed DP FP Values to DP FP Values" } + {VGETEXPPS "Convert Exponents of Packed SP FP Values to SP FP Values" } + {VGETEXPSD "Convert Exponents of Scalar DP FP Values to DP FP Value" } + {VGETEXPSS "Convert Exponents of Scalar SP FP Values to SP FP Value" } + {VGETMANTPD "Extract Float64 Vector of Normalized Mantissas from Float64 Vector" } + {VGETMANTPS "Extract Float32 Vector of Normalized Mantissas from Float32 Vector" } + {VGETMANTSD "Extract Float64 of Normalized Mantissas from Float64 Scalar" } + {VGETMANTSS "Extract Float32 Vector of Normalized Mantissa from Float32 Vector" } + {VINSERTF128 "Insert Packed Floating-Point Values" } + {VINSERTF32x4 "Insert Packed Floating-Point Values" } + {VINSERTF32x8 "Insert Packed Floating-Point Values" } + {VINSERTF64x2 "Insert Packed Floating-Point Values" } + {VINSERTF64x4 "Insert Packed Floating-Point Values" } + {VINSERTI128 "Insert Packed Integer Values" } + {VINSERTI32x4 "Insert Packed Integer Values" } + {VINSERTI32x8 "Insert Packed Integer Values" } + {VINSERTI64x2 "Insert Packed Integer Values" } + {VINSERTI64x4 "Insert Packed Integer Values" } + {VMASKMOV "Conditional SIMD Packed Loads and Stores" } + {VMOVDQA32 "Move Aligned Packed Integer Values" } + {VMOVDQA64 "Move Aligned Packed Integer Values" } + {VMOVDQU16 "Move Unaligned Packed Integer Values" } + {VMOVDQU32 "Move Unaligned Packed Integer Values" } + {VMOVDQU64 "Move Unaligned Packed Integer Values" } + {VMOVDQU8 "Move Unaligned Packed Integer Values" } + {VP2INTERSECTD "Compute Intersection Between DWORDS/QUADWORDS to a Pair of Mask Registers" } + {VP2INTERSECTQ "Compute Intersection Between DWORDS/QUADWORDS to a Pair of Mask Registers" } + {VPBLENDD "Blend Packed Dwords" } + {VPBLENDMB "Blend Byte/Word Vectors Using an Opmask Control" } + {VPBLENDMD "Blend Int32/Int64 Vectors Using an OpMask Control" } + {VPBLENDMQ "Blend Int32/Int64 Vectors Using an OpMask Control" } + {VPBLENDMW "Blend Byte/Word Vectors Using an Opmask Control" } + {VPBROADCAST "Load Integer and Broadcast" } + {VPBROADCASTB "Load with Broadcast Integer Data from General Purpose Register" } + {VPBROADCASTD "Load with Broadcast Integer Data from General Purpose Register" } + {VPBROADCASTM "Broadcast Mask to Vector Register" } + {VPBROADCASTQ "Load with Broadcast Integer Data from General Purpose Register" } + {VPBROADCASTW "Load with Broadcast Integer Data from General Purpose Register" } + {VPCMPB "Compare Packed Byte Values Into Mask" } + {VPCMPD "Compare Packed Integer Values into Mask" } + {VPCMPQ "Compare Packed Integer Values into Mask" } + {VPCMPUB "Compare Packed Byte Values Into Mask" } + {VPCMPUD "Compare Packed Integer Values into Mask" } + {VPCMPUQ "Compare Packed Integer Values into Mask" } + {VPCMPUW "Compare Packed Word Values Into Mask" } + {VPCMPW "Compare Packed Word Values Into Mask" } + {VPCOMPRESSB "Store Sparse Packed Byte/Word Integer Values into Dense Memory/Register" } + {VPCOMPRESSD "Store Sparse Packed Doubleword Integer Values into Dense Memory/Register" } + {VPCOMPRESSQ "Store Sparse Packed Quadword Integer Values into Dense Memory/Register" } + {VPCONFLICTD "Detect Conflicts Within a Vector of Packed Dword/Qword Values into Dense Memory/ Register" } + {VPCONFLICTQ "Detect Conflicts Within a Vector of Packed Dword/Qword Values into Dense Memory/ Register" } + {VPDPBUSD "Multiply and Add Unsigned and Signed Bytes" } + {VPDPBUSDS "Multiply and Add Unsigned and Signed Bytes with Saturation" } + {VPDPWSSD "Multiply and Add Signed Word Integers" } + {VPDPWSSDS "Multiply and Add Signed Word Integers with Saturation" } + {VPERM2F128 "Permute Floating-Point Values" } + {VPERM2I128 "Permute Integer Values" } + {VPERMB "Permute Packed Bytes Elements" } + {VPERMD "Permute Packed Doublewords/Words Elements" } + {VPERMI2B "Full Permute of Bytes from Two Tables Overwriting the Index" } + {VPERMI2D "Full Permute From Two Tables Overwriting the Index" } + {VPERMI2PD "Full Permute From Two Tables Overwriting the Index" } + {VPERMI2PS "Full Permute From Two Tables Overwriting the Index" } + {VPERMI2Q "Full Permute From Two Tables Overwriting the Index" } + {VPERMI2W "Full Permute From Two Tables Overwriting the Index" } + {VPERMILPD "Permute In-Lane of Pairs of Double-Precision Floating-Point Values" } + {VPERMILPS "Permute In-Lane of Quadruples of Single-Precision Floating-Point Values" } + {VPERMPD "Permute Double-Precision Floating-Point Elements" } + {VPERMPS "Permute Single-Precision Floating-Point Elements" } + {VPERMQ "Qwords Element Permutation" } + {VPERMT2B "Full Permute of Bytes from Two Tables Overwriting a Table" } + {VPERMT2D "Full Permute from Two Tables Overwriting one Table" } + {VPERMT2PD "Full Permute from Two Tables Overwriting one Table" } + {VPERMT2PS "Full Permute from Two Tables Overwriting one Table" } + {VPERMT2Q "Full Permute from Two Tables Overwriting one Table" } + {VPERMT2W "Full Permute from Two Tables Overwriting one Table" } + {VPERMW "Permute Packed Doublewords/Words Elements" } + {VPEXPANDB "Expand Byte/Word Values" } + {VPEXPANDD "Load Sparse Packed Doubleword Integer Values from Dense Memory / Register" } + {VPEXPANDQ "Load Sparse Packed Quadword Integer Values from Dense Memory / Register" } + {VPEXPANDW "Expand Byte/Word Values" } + {VPGATHERDD "Gather Packed Dword Values Using Signed Dword/Qword Indices" } + {VPGATHERDQ "Gather Packed Dword, Packed Qword with Signed Dword Indices" } + {VPGATHERQD "Gather Packed Dword Values Using Signed Dword/Qword Indices" } + {VPGATHERQQ "Gather Packed Qword Values Using Signed Dword/Qword Indices" } + {VPLZCNTD "Count the Number of Leading Zero Bits for Packed Dword, Packed Qword Values" } + {VPLZCNTQ "Count the Number of Leading Zero Bits for Packed Dword, Packed Qword Values" } + {VPMADD52HUQ "Packed Multiply of Unsigned 52-bit Unsigned Integers and Add High 52-bit Products to 64-bit Accumulators" } + {VPMADD52LUQ "Packed Multiply of Unsigned 52-bit Integers and Add the Low 52-bit Products to Qword Accumulators" } + {VPMASKMOV "Conditional SIMD Integer Packed Loads and Stores" } + {VPMOVB2M "Convert a Vector Register to a Mask" } + {VPMOVD2M "Convert a Vector Register to a Mask" } + {VPMOVDB "Down Convert DWord to Byte" } + {VPMOVDW "Down Convert DWord to Word" } + {VPMOVM2B "Convert a Mask Register to a Vector Register" } + {VPMOVM2D "Convert a Mask Register to a Vector Register" } + {VPMOVM2Q "Convert a Mask Register to a Vector Register" } + {VPMOVM2W "Convert a Mask Register to a Vector Register" } + {VPMOVQ2M "Convert a Vector Register to a Mask" } + {VPMOVQB "Down Convert QWord to Byte" } + {VPMOVQD "Down Convert QWord to DWord" } + {VPMOVQW "Down Convert QWord to Word" } + {VPMOVSDB "Down Convert DWord to Byte" } + {VPMOVSDW "Down Convert DWord to Word" } + {VPMOVSQB "Down Convert QWord to Byte" } + {VPMOVSQD "Down Convert QWord to DWord" } + {VPMOVSQW "Down Convert QWord to Word" } + {VPMOVSWB "Down Convert Word to Byte" } + {VPMOVUSDB "Down Convert DWord to Byte" } + {VPMOVUSDW "Down Convert DWord to Word" } + {VPMOVUSQB "Down Convert QWord to Byte" } + {VPMOVUSQD "Down Convert QWord to DWord" } + {VPMOVUSQW "Down Convert QWord to Word" } + {VPMOVUSWB "Down Convert Word to Byte" } + {VPMOVW2M "Convert a Vector Register to a Mask" } + {VPMOVWB "Down Convert Word to Byte" } + {VPMULTISHIFTQB "Select Packed Unaligned Bytes from Quadword Sources" } + {VPOPCNT "Return the Count of Number of Bits Set to 1 in BYTE/WORD/DWORD/QWORD" } + {VPROLD "Bit Rotate Left" } + {VPROLQ "Bit Rotate Left" } + {VPROLVD "Bit Rotate Left" } + {VPROLVQ "Bit Rotate Left" } + {VPRORD "Bit Rotate Right" } + {VPRORQ "Bit Rotate Right" } + {VPRORVD "Bit Rotate Right" } + {VPRORVQ "Bit Rotate Right" } + {VPSCATTERDD "Scatter Packed Dword, Packed Qword with Signed Dword, Signed Qword Indices" } + {VPSCATTERDQ "Scatter Packed Dword, Packed Qword with Signed Dword, Signed Qword Indices" } + {VPSCATTERQD "Scatter Packed Dword, Packed Qword with Signed Dword, Signed Qword Indices" } + {VPSCATTERQQ "Scatter Packed Dword, Packed Qword with Signed Dword, Signed Qword Indices" } + {VPSHLD "Concatenate and Shift Packed Data Left Logical" } + {VPSHLDV "Concatenate and Variable Shift Packed Data Left Logical" } + {VPSHRD "Concatenate and Shift Packed Data Right Logical" } + {VPSHRDV "Concatenate and Variable Shift Packed Data Right Logical" } + {VPSHUFBITQMB "Shuffle Bits from Quadword Elements Using Byte Indexes into Mask" } + {VPSLLVD "Variable Bit Shift Left Logical" } + {VPSLLVQ "Variable Bit Shift Left Logical" } + {VPSLLVW "Variable Bit Shift Left Logical" } + {VPSRAVD "Variable Bit Shift Right Arithmetic" } + {VPSRAVQ "Variable Bit Shift Right Arithmetic" } + {VPSRAVW "Variable Bit Shift Right Arithmetic" } + {VPSRLVD "Variable Bit Shift Right Logical" } + {VPSRLVQ "Variable Bit Shift Right Logical" } + {VPSRLVW "Variable Bit Shift Right Logical" } + {VPTERNLOGD "Bitwise Ternary Logic" } + {VPTERNLOGQ "Bitwise Ternary Logic" } + {VPTESTMB "Logical AND and Set Mask" } + {VPTESTMD "Logical AND and Set Mask" } + {VPTESTMQ "Logical AND and Set Mask" } + {VPTESTMW "Logical AND and Set Mask" } + {VPTESTNMB "Logical NAND and Set" } + {VPTESTNMD "Logical NAND and Set" } + {VPTESTNMQ "Logical NAND and Set" } + {VPTESTNMW "Logical NAND and Set" } + {VRANGEPD "Range Restriction Calculation For Packed Pairs of Float64 Values" } + {VRANGEPS "Range Restriction Calculation For Packed Pairs of Float32 Values" } + {VRANGESD "Range Restriction Calculation From a pair of Scalar Float64 Values" } + {VRANGESS "Range Restriction Calculation From a Pair of Scalar Float32 Values" } + {VRCP14PD "Compute Approximate Reciprocals of Packed Float64 Values" } + {VRCP14PS "Compute Approximate Reciprocals of Packed Float32 Values" } + {VRCP14SD "Compute Approximate Reciprocal of Scalar Float64 Value" } + {VRCP14SS "Compute Approximate Reciprocal of Scalar Float32 Value" } + {VREDUCEPD "Perform Reduction Transformation on Packed Float64 Values" } + {VREDUCEPS "Perform Reduction Transformation on Packed Float32 Values" } + {VREDUCESD "Perform a Reduction Transformation on a Scalar Float64 Value" } + {VREDUCESS "Perform a Reduction Transformation on a Scalar Float32 Value" } + {VRNDSCALEPD "Round Packed Float64 Values To Include A Given Number Of Fraction Bits" } + {VRNDSCALEPS "Round Packed Float32 Values To Include A Given Number Of Fraction Bits" } + {VRNDSCALESD "Round Scalar Float64 Value To Include A Given Number Of Fraction Bits" } + {VRNDSCALESS "Round Scalar Float32 Value To Include A Given Number Of Fraction Bits" } + {VRSQRT14PD "Compute Approximate Reciprocals of Square Roots of Packed Float64 Values" } + {VRSQRT14PS "Compute Approximate Reciprocals of Square Roots of Packed Float32 Values" } + {VRSQRT14SD "Compute Approximate Reciprocal of Square Root of Scalar Float64 Value" } + {VRSQRT14SS "Compute Approximate Reciprocal of Square Root of Scalar Float32 Value" } + {VSCALEFPD "Scale Packed Float64 Values With Float64 Values" } + {VSCALEFPS "Scale Packed Float32 Values With Float32 Values" } + {VSCALEFSD "Scale Scalar Float64 Values With Float64 Values" } + {VSCALEFSS "Scale Scalar Float32 Value With Float32 Value" } + {VSCATTERDPD "Scatter Packed Single, Packed Double with Signed Dword and Qword Indices" } + {VSCATTERDPS "Scatter Packed Single, Packed Double with Signed Dword and Qword Indices" } + {VSCATTERQPD "Scatter Packed Single, Packed Double with Signed Dword and Qword Indices" } + {VSCATTERQPS "Scatter Packed Single, Packed Double with Signed Dword and Qword Indices" } + {VSHUFF32x4 "Shuffle Packed Values at 128-bit Granularity" } + {VSHUFF64x2 "Shuffle Packed Values at 128-bit Granularity" } + {VSHUFI32x4 "Shuffle Packed Values at 128-bit Granularity" } + {VSHUFI64x2 "Shuffle Packed Values at 128-bit Granularity" } + {VTESTPD "Packed Bit Test" } + {VTESTPS "Packed Bit Test" } + {VZEROALL "Zero XMM, YMM and ZMM Registers" } + {VZEROUPPER "Zero Upper Bits of YMM and ZMM Registers" } + {WAIT "Wait" } + {WBINVD "Write Back and Invalidate Cache" } + {WBNOINVD "Write Back and Do Not Invalidate Cache" } + {WRFSBASE "Write FS/GS Segment Base" } + {WRGSBASE "Write FS/GS Segment Base" } + {WRMSR "Write to Model Specific Register" } + {WRPKRU "Write Data to User Page Key Register" } + {WRSSD "Write to Shadow Stack" } + {WRSSQ "Write to Shadow Stack" } + {WRUSSD "Write to User Shadow Stack" } + {WRUSSQ "Write to User Shadow Stack" } + {XABORT "Transactional Abort" } + {XACQUIRE "Hardware Lock Elision Prefix Hints" } + {XADD "Exchange and Add" } + {XBEGIN "Transactional Begin" } + {XCHG "Exchange Register/Memory with Register" } + {XEND "Transactional End" } + {XGETBV "Get Value of Extended Control Register" } + {XLAT "Table Look-up Translation" } + {XLATB "Table Look-up Translation" } + {XOR "Logical Exclusive OR" } + {XORPD "Bitwise Logical XOR of Packed Double Precision Floating-Point Values" } + {XORPS "Bitwise Logical XOR of Packed Single Precision Floating-Point Values" } + {XRELEASE "Hardware Lock Elision Prefix Hints" } + {XRSTOR "Restore Processor Extended States" } + {XRSTORS "Restore Processor Extended States Supervisor" } + {XSAVE "Save Processor Extended States" } + {XSAVEC "Save Processor Extended States with Compaction" } + {XSAVEOPT "Save Processor Extended States Optimized" } + {XSAVES "Save Processor Extended States Supervisor" } + {XSETBV "Set Extended Control Register" } + {XTEST "Test If In Transactional Execution" } + + //- rjf: sgx + {ENCLS "Execute an Enclave System Function of Specified Leaf Number" } + {ENCLS "[EADD] Add a Page to an Uninitialized Enclave" } + {ENCLS "[EAUG] Add a Page to an Initialized Enclave" } + {ENCLS "[EBLOCK] Mark a page in EPC as Blocked" } + {ENCLS "[ECREATE] Create an SECS page in the Enclave Page Cache" } + {ENCLS "[EDBGRD] Read From a Debug Enclave" } + {ENCLS "[EDBGWR] Write to a Debug Enclave" } + {ENCLS "[EEXTEND] Extend Uninitialized Enclave Measurement by 256 Bytes" } + {ENCLS "[EINIT] Initialize an Enclave for Execution" } + {ENCLS "[ELDBC] Load an EPC Page and Mark its State" } + {ENCLS "[ELDB] Load an EPC Page and Mark its State" } + {ENCLS "[ELDUC] Load an EPC Page and Mark its State" } + {ENCLS "[ELDU] Load an EPC Page and Mark its State" } + {ENCLS "[EMODPR] Restrict the Permissions of an EPC Page" } + {ENCLS "[EMODT] Change the Type of an EPC Page" } + {ENCLS "[EPA] Add Version Array" } + {ENCLS "[ERDINFO] Read Type and Status Information About an EPC Page" } + {ENCLS "[EREMOVE] Remove a page from the EPC" } + {ENCLS "[ETRACKC] Activates EBLOCK Checks" } + {ENCLS "[ETRACK] Activates EBLOCK Checks" } + {ENCLS "[EWB] Invalidate an EPC Page and Write out to Main Memory" } + {ENCLU "Execute an Enclave User Function of Specified Leaf Number" } + {ENCLU "[EACCEPTCOPY] Initialize a Pending Page" } + {ENCLU "[EACCEPT] Accept Changes to an EPC Page" } + {ENCLU "[EENTER] Enters an Enclave" } + {ENCLU "[EEXIT] Exits an Enclave" } + {ENCLU "[EGETKEY] Retrieves a Cryptographic Key" } + {ENCLU "[EMODPE] Extend an EPC Page Permissions" } + {ENCLU "[EREPORT] Create a Cryptographic Report of the Enclave" } + {ENCLU "[ERESUME] Re-Enters an Enclave" } + {ENCLV "Execute an Enclave VMM Function of Specified Leaf Number" } + + //- rjf: vmx + {INVEPT "Invalidate Translations Derived from EPT" } + {INVVPID "Invalidate Translations Based on VPID" } + {VMCALL "Call to VM Monitor" } + {VMCLEAR "Clear Virtual-Machine Control Structure" } + {VMFUNC "Invoke VM function" } + {VMLAUNCH "Launch/Resume Virtual Machine" } + {VMPTRLD "Load Pointer to Virtual-Machine Control Structure" } + {VMPTRST "Store Pointer to Virtual-Machine Control Structure" } + {VMREAD "Read Field from Virtual-Machine Control Structure" } + {VMRESUME "Launch/Resume Virtual Machine" } + {VMWRITE "Write Field to Virtual-Machine Control Structure" } + {VMXOFF "Leave VMX Operation" } + {VMXON "Enter VMX Operation" } + + //- rjf: xeon phi + {PREFETCHWT1 "Prefetch Vector Data Into Caches with Intent to Write and T1 Hint" } + {V4FMADDPS "Packed Single-Precision Floating-Point Fused Multiply-Add (4-iterations)" } + {V4FMADDSS "Scalar Single-Precision Floating-Point Fused Multiply-Add (4-iterations)" } + {V4FNMADDPS "Packed Single-Precision Floating-Point Fused Multiply-Add (4-iterations)" } + {V4FNMADDSS "Scalar Single-Precision Floating-Point Fused Multiply-Add (4-iterations)" } + {VEXP2PD "Approximation to the Exponential 2^x of Packed Double-Precision Floating-Point Values with Less Than 2^-23 Relative Error"} + {VEXP2PS "Approximation to the Exponential 2^x of Packed Single-Precision Floating-Point Values with Less Than 2^-23 Relative Error"} + {VGATHERPF0DPD "Sparse Prefetch Packed SP/DP Data Values with Signed Dword, Signed Qword Indices Using T0 Hint" } + {VGATHERPF0DPS "Sparse Prefetch Packed SP/DP Data Values with Signed Dword, Signed Qword Indices Using T0 Hint" } + {VGATHERPF0QPD "Sparse Prefetch Packed SP/DP Data Values with Signed Dword, Signed Qword Indices Using T0 Hint" } + {VGATHERPF0QPS "Sparse Prefetch Packed SP/DP Data Values with Signed Dword, Signed Qword Indices Using T0 Hint" } + {VGATHERPF1DPD "Sparse Prefetch Packed SP/DP Data Values with Signed Dword, Signed Qword Indices Using T1 Hint" } + {VGATHERPF1DPS "Sparse Prefetch Packed SP/DP Data Values with Signed Dword, Signed Qword Indices Using T1 Hint" } + {VGATHERPF1QPD "Sparse Prefetch Packed SP/DP Data Values with Signed Dword, Signed Qword Indices Using T1 Hint" } + {VGATHERPF1QPS "Sparse Prefetch Packed SP/DP Data Values with Signed Dword, Signed Qword Indices Using T1 Hint" } + {VP4DPWSSD "Dot Product of Signed Words with Dword Accumulation (4-iterations)" } + {VP4DPWSSDS "Dot Product of Signed Words with Dword Accumulation and Saturation (4-iterations)" } + {VRCP28PD "Approximation to the Reciprocal of Packed Double-Precision Floating-Point Values with Less Than 2^-28 Relative Error" } + {VRCP28PS "Approximation to the Reciprocal of Packed Single-Precision Floating-Point Values with Less Than 2^-28 Relative Error" } + {VRCP28SD "Approximation to the Reciprocal of Scalar Double-Precision Floating-Point Value with Less Than 2^-28 Relative Error" } + {VRCP28SS "Approximation to the Reciprocal of Scalar Single-Precision Floating-Point Value with Less Than 2^-28 Relative Error" } + {VRSQRT28PD "Approximation to the Reciprocal Square Root of Packed Double-Precision Floating-Point Values with Less Than 2^-28 Relative Error"} + {VRSQRT28PS "Approximation to the Reciprocal Square Root of Packed Single-Precision Floating-Point Values with Less Than 2^-28 Relative Error"} + {VRSQRT28SD "Approximation to the Reciprocal Square Root of Scalar Double-Precision Floating-Point Value with Less Than 2^-28 Relative Error"} + {VRSQRT28SS "Approximation to the Reciprocal Square Root of Scalar Single-Precision Floating- Point Value with Less Than 2^-28 Relative Error"} + {VSCATTERPF0DPD "Sparse Prefetch Packed SP/DP Data Values with Signed Dword, Signed Qword Indices Using T0 Hint with Intent to Write" } + {VSCATTERPF0DPS "Sparse Prefetch Packed SP/DP Data Values with Signed Dword, Signed Qword Indices Using T0 Hint with Intent to Write" } + {VSCATTERPF0QPD "Sparse Prefetch Packed SP/DP Data Values with Signed Dword, Signed Qword Indices Using T0 Hint with Intent to Write" } + {VSCATTERPF0QPS "Sparse Prefetch Packed SP/DP Data Values with Signed Dword, Signed Qword Indices Using T0 Hint with Intent to Write" } + {VSCATTERPF1DPD "Sparse Prefetch Packed SP/DP Data Values with Signed Dword, Signed Qword Indices Using T1 Hint with Intent to Write" } + {VSCATTERPF1DPS "Sparse Prefetch Packed SP/DP Data Values with Signed Dword, Signed Qword Indices Using T1 Hint with Intent to Write" } + {VSCATTERPF1QPD "Sparse Prefetch Packed SP/DP Data Values with Signed Dword, Signed Qword Indices Using T1 Hint with Intent to Write" } + {VSCATTERPF1QPS "Sparse Prefetch Packed SP/DP Data Values with Signed Dword, Signed Qword Indices Using T1 Hint with Intent to Write" } + +} + +//////////////////////////////// +//~ rjf: Developer Toggles + +@table(name) +DF_DevToggleTable: +{ + {telemetry_capture} + {simulate_lag} + {draw_ui_text_pos} + {draw_ui_focus_debug} + {draw_ui_box_heatmap} + {eval_compiler_tooltips} + {eval_watch_key_tooltips} + {cmd_context_tooltips} + {scratch_mouse_draw} + {updating_indicator} +} + +//////////////////////////////// +//~ rjf: Generators + +//- rjf: enums + +@enum DF_CfgSrc: +{ + @expand(DF_CfgSrcTable a) `$(a.name)`, + COUNT, +} + +@enum DF_EntityKind: +{ + @expand(DF_EntityKindTable a) `$(a.name)`, + COUNT, +} + +@enum DF_CoreCmdKind: +{ + @expand(DF_CoreCmdTable, a) `$(a.name)`, + COUNT, +} + +@enum DF_IconKind: +{ + @expand(DF_IconTable a) `$(a.name)`, + COUNT, +} + +@enum DF_CoreViewRuleKind: +{ + @expand(DF_CoreViewRuleTable a) `$(a.name)`, + COUNT, +} + +//- rjf: command params + +@enum DF_CmdParamSlot: +{ + Null, + @expand(DF_CmdParamSlotTable a) `$(a.name)`, + COUNT, +} + +@struct DF_CmdParams: +{ + `U64 slot_props[(DF_CmdParamSlot_COUNT + 63) / 64]`; + @expand(DF_CmdParamSlotTable a) `$(a.c_type) $(a.name_lower)`; +} + +@data(Rng1U64) df_g_cmd_param_slot_range_table: +{ + `{0}`, + @expand(DF_CmdParamSlotTable a) `{OffsetOf(DF_CmdParams, $(a.name_lower)), OffsetOf(DF_CmdParams, $(a.name_lower)) + sizeof($(a.c_type))}`, +} + +//- rjf: entity kind tables + +@data(DF_IconKind) df_g_entity_kind_icon_kind_table: +{ + @expand(DF_EntityKindTable a) `DF_IconKind_$(a.icon_kind)`, +} + +@data(String8) df_g_entity_kind_display_string_table: +{ + @expand(DF_EntityKindTable a) `str8_lit_comp("$(a.display_string)")`, +} + +@data(String8) df_g_entity_kind_name_label_table: +{ + @expand(DF_EntityKindTable a) `str8_lit_comp("$(a.name_label)")`, +} + +@data(DF_EntityKindFlags) df_g_entity_kind_flags_table: +{ + @expand(DF_EntityKindTable a) `($(a.lf_mut_user_cfg)*DF_EntityKindFlag_LeafMutationUserConfig | $(a.lf_mut_prof_cfg)*DF_EntityKindFlag_LeafMutationProjectConfig | $(a.lf_mut_halt)*DF_EntityKindFlag_LeafMutationSoftHalt | $(a.lf_mut_dbg)*DF_EntityKindFlag_LeafMutationDebugInfoMap | $(a.tr_mut_user_cfg)*DF_EntityKindFlag_TreeMutationUserConfig | $(a.tr_mut_prof_cfg)*DF_EntityKindFlag_TreeMutationProjectConfig | $(a.tr_mut_halt)*DF_EntityKindFlag_TreeMutationSoftHalt | $(a.tr_mut_dbg)*DF_EntityKindFlag_TreeMutationDebugInfoMap | $(a.name_is_code)*DF_EntityKindFlag_NameIsCode | $(a.user_lifetime)*DF_EntityKindFlag_UserDefinedLifetime)`, +} + +@data(DF_EntityOpFlags) df_g_entity_kind_op_flags_table: +{ + @expand(DF_EntityKindTable a) `($(a.op_delete)*DF_EntityOpFlag_Delete) | ($(a.op_freeze)*DF_EntityOpFlag_Freeze) | ($(a.op_edit)*DF_EntityOpFlag_Edit) | ($(a.op_rename)*DF_EntityOpFlag_Rename) | ($(a.op_enable)*DF_EntityOpFlag_Enable) | ($(a.op_cond)*DF_EntityOpFlag_Condition) | ($(a.op_dup)*DF_EntityOpFlag_Duplicate)`, +} + +//- rjf: config source tables + +@data(String8) df_g_cfg_src_string_table: +{ + @expand(DF_CfgSrcTable a) `str8_lit_comp("$(a.string)")`, +} + +@data(DF_CoreCmdKind) df_g_cfg_src_load_cmd_kind_table: +{ + @expand(DF_CfgSrcTable a) `DF_CoreCmdKind_$(a.load_cmd)`, +} + +@data(DF_CoreCmdKind) df_g_cfg_src_write_cmd_kind_table: +{ + @expand(DF_CfgSrcTable a) `DF_CoreCmdKind_$(a.write_cmd)`, +} + +@data(DF_CoreCmdKind) df_g_cfg_src_apply_cmd_kind_table: +{ + @expand(DF_CfgSrcTable a) `DF_CoreCmdKind_$(a.apply_cmd)`; +} + +//- rjf: core view rule function prototypes + +@gen +{ + @expand(DF_CoreViewRuleTable a) `$(a.er == "x" -> "DF_CORE_VIEW_RULE_EVAL_RESOLUTION_FUNCTION_DEF(" .. a.name_lower .. ");")`; + @expand(DF_CoreViewRuleTable a) `$(a.vb == "x" -> "DF_CORE_VIEW_RULE_VIZ_BLOCK_PROD_FUNCTION_DEF(" .. a.name_lower .. ");")`; +} + +//- rjf: core command kind tables + +@data(DF_CmdSpecInfo) @c_file df_g_core_cmd_kind_spec_info_table: +{ + @expand(DF_CoreCmdTable, a) + ```{ str8_lit_comp("$(a.string)"), str8_lit_comp("$(a.desc)"), str8_lit_comp("$(a.search_tags)"), str8_lit_comp("$(a.display_name)"), (DF_CmdSpecFlag_OmitFromLists*$(a.lister_omit)), {DF_CmdParamSlot_$(a.q_slot), DF_EntityKind_$(a.q_ent_kind), (DF_CmdQueryFlag_AllowFiles*$(a.q_allow_files))|(DF_CmdQueryFlag_AllowFolders*$(a.q_allow_folders))|(DF_CmdQueryFlag_CodeInput*$(a.q_is_code))|(DF_CmdQueryFlag_KeepOldInput*$(a.q_keep_oi))|(DF_CmdQueryFlag_SelectOldInput*$(a.q_select_oi))|(DF_CmdQueryFlag_Required*$(a.q_required))}, DF_IconKind_$(a.canonical_icon)}```; +} + +//- rjf: core view rule tables + +@data(DF_CoreViewRuleSpecInfo) @c_file df_g_core_view_rule_spec_info_table: +{ + @expand(DF_CoreViewRuleTable a) + ```{str8_lit_comp("$(a.string)"), str8_lit_comp("$(a.display_name)"), str8_lit_comp("$(a.schema)"), str8_lit_comp("$(a.description)"), (DF_CoreViewRuleSpecInfoFlag_Inherited*$(a.ih == "x"))|(DF_CoreViewRuleSpecInfoFlag_Expandable*$(a.ex == "x"))|(DF_CoreViewRuleSpecInfoFlag_EvalResolution*$(a.er == "x"))|(DF_CoreViewRuleSpecInfoFlag_VizBlockProd*$(a.vb == "x")), $(a.er == "x" -> "DF_CORE_VIEW_RULE_EVAL_RESOLUTION_FUNCTION_NAME("..a.name_lower..")") $(a.er != "x" -> 0), $(a.vb == "x" -> "DF_CORE_VIEW_RULE_VIZ_BLOCK_PROD_FUNCTION_NAME("..a.name_lower..")") $(a.vb != "x" -> 0), }```; +} + +//- rjf: icon kinds + +@data(String8) df_g_icon_kind_text_table: +{ + @expand(DF_IconTable a) `str8_lit_comp("$(a.text)")`; +} + +//- rjf: instruction metadata table + +@gen +{ + ``; + `struct{String8 mnemonic; String8 summary;} df_g_inst_table_x64[] =`; + `{`; + @expand(DF_InstTableX64 a) `{str8_lit_comp("$(a.name)"), str8_lit_comp("$(a.summary)")},`; + `};`; + ``; +} + +//- rjf: developer toggles + +@gen +{ + @expand(DF_DevToggleTable a) `global B32 DEV_$(a.name) = 0;` +} + +@gen +{ + `struct {B32 *value_ptr; String8 name;} DEV_toggle_table[] =`; + `{`; + @expand(DF_DevToggleTable a) `{&DEV_$(a.name), str8_lit_comp("$(a.name)")},` + `};`; +} diff --git a/src/df/core/generated/df_core.meta.c b/src/df/core/generated/df_core.meta.c index 0fb27408..13135a5e 100644 --- a/src/df/core/generated/df_core.meta.c +++ b/src/df/core/generated/df_core.meta.c @@ -28,8 +28,8 @@ Rng1U64 df_g_cmd_param_slot_range_table[24] = {OffsetOf(DF_CmdParams, prefer_dasm), OffsetOf(DF_CmdParams, prefer_dasm) + sizeof(B32)}, {OffsetOf(DF_CmdParams, force_confirm), OffsetOf(DF_CmdParams, force_confirm) + sizeof(B32)}, {OffsetOf(DF_CmdParams, dir2), OffsetOf(DF_CmdParams, dir2) + sizeof(Dir2)}, -{OffsetOf(DF_CmdParams, base_unwind_index), OffsetOf(DF_CmdParams, base_unwind_index) + sizeof(U64)}, -{OffsetOf(DF_CmdParams, inline_unwind_index), OffsetOf(DF_CmdParams, inline_unwind_index) + sizeof(U64)}, +{OffsetOf(DF_CmdParams, unwind_index), OffsetOf(DF_CmdParams, unwind_index) + sizeof(U64)}, +{OffsetOf(DF_CmdParams, inline_depth), OffsetOf(DF_CmdParams, inline_depth) + sizeof(U64)}, }; DF_IconKind df_g_entity_kind_icon_kind_table[25] = diff --git a/src/df/core/generated/df_core.meta.h b/src/df/core/generated/df_core.meta.h index f107c023..fe612058 100644 --- a/src/df/core/generated/df_core.meta.h +++ b/src/df/core/generated/df_core.meta.h @@ -392,8 +392,8 @@ DF_CmdParamSlot_ID, DF_CmdParamSlot_PreferDisassembly, DF_CmdParamSlot_ForceConfirm, DF_CmdParamSlot_Dir2, -DF_CmdParamSlot_BaseUnwindIndex, -DF_CmdParamSlot_InlineUnwindIndex, +DF_CmdParamSlot_UnwindIndex, +DF_CmdParamSlot_InlineDepth, DF_CmdParamSlot_COUNT, } DF_CmdParamSlot; @@ -422,8 +422,8 @@ U64 id; B32 prefer_dasm; B32 force_confirm; Dir2 dir2; -U64 base_unwind_index; -U64 inline_unwind_index; +U64 unwind_index; +U64 inline_depth; }; DF_CORE_VIEW_RULE_EVAL_RESOLUTION_FUNCTION_DEF(array); diff --git a/src/df/gfx/df_gfx.c b/src/df/gfx/df_gfx.c index 5b67d4c9..d1ed40a2 100644 --- a/src/df/gfx/df_gfx.c +++ b/src/df/gfx/df_gfx.c @@ -522,15 +522,15 @@ df_cmd_params_from_window(DF_Window *window) df_cmd_params_mark_slot(&p, DF_CmdParamSlot_View); df_cmd_params_mark_slot(&p, DF_CmdParamSlot_PreferDisassembly); df_cmd_params_mark_slot(&p, DF_CmdParamSlot_Entity); - df_cmd_params_mark_slot(&p, DF_CmdParamSlot_BaseUnwindIndex); - df_cmd_params_mark_slot(&p, DF_CmdParamSlot_InlineUnwindIndex); + df_cmd_params_mark_slot(&p, DF_CmdParamSlot_UnwindIndex); + df_cmd_params_mark_slot(&p, DF_CmdParamSlot_InlineDepth); p.window = df_handle_from_window(window); p.panel = df_handle_from_panel(window->focused_panel); p.view = df_handle_from_view(df_selected_tab_from_panel(window->focused_panel)); p.prefer_dasm = df_prefer_dasm_from_window(window); p.entity = ctrl_ctx.thread; - p.base_unwind_index = ctrl_ctx.unwind_count; - p.inline_unwind_index = ctrl_ctx.inline_unwind_count; + p.unwind_index = ctrl_ctx.unwind_count; + p.inline_depth = ctrl_ctx.inline_depth; return p; } @@ -544,15 +544,15 @@ df_cmd_params_from_panel(DF_Window *window, DF_Panel *panel) df_cmd_params_mark_slot(&p, DF_CmdParamSlot_View); df_cmd_params_mark_slot(&p, DF_CmdParamSlot_PreferDisassembly); df_cmd_params_mark_slot(&p, DF_CmdParamSlot_Entity); - df_cmd_params_mark_slot(&p, DF_CmdParamSlot_BaseUnwindIndex); - df_cmd_params_mark_slot(&p, DF_CmdParamSlot_InlineUnwindIndex); + df_cmd_params_mark_slot(&p, DF_CmdParamSlot_UnwindIndex); + df_cmd_params_mark_slot(&p, DF_CmdParamSlot_InlineDepth); p.window = df_handle_from_window(window); p.panel = df_handle_from_panel(panel); p.view = df_handle_from_view(df_selected_tab_from_panel(panel)); p.prefer_dasm = df_prefer_dasm_from_window(window); p.entity = ctrl_ctx.thread; - p.base_unwind_index = ctrl_ctx.unwind_count; - p.inline_unwind_index = ctrl_ctx.inline_unwind_count; + p.unwind_index = ctrl_ctx.unwind_count; + p.inline_depth = ctrl_ctx.inline_depth; return p; } @@ -566,15 +566,15 @@ df_cmd_params_from_view(DF_Window *window, DF_Panel *panel, DF_View *view) df_cmd_params_mark_slot(&p, DF_CmdParamSlot_View); df_cmd_params_mark_slot(&p, DF_CmdParamSlot_PreferDisassembly); df_cmd_params_mark_slot(&p, DF_CmdParamSlot_Entity); - df_cmd_params_mark_slot(&p, DF_CmdParamSlot_BaseUnwindIndex); - df_cmd_params_mark_slot(&p, DF_CmdParamSlot_InlineUnwindIndex); + df_cmd_params_mark_slot(&p, DF_CmdParamSlot_UnwindIndex); + df_cmd_params_mark_slot(&p, DF_CmdParamSlot_InlineDepth); p.window = df_handle_from_window(window); p.panel = df_handle_from_panel(panel); p.view = df_handle_from_view(view); p.prefer_dasm = df_prefer_dasm_from_window(window); p.entity = ctrl_ctx.thread; - p.base_unwind_index = ctrl_ctx.unwind_count; - p.inline_unwind_index = ctrl_ctx.inline_unwind_count; + p.unwind_index = ctrl_ctx.unwind_count; + p.inline_depth = ctrl_ctx.inline_depth; return p; } @@ -2585,12 +2585,12 @@ df_window_update_and_render(Arena *arena, DF_Window *ws, DF_CmdList *cmds) { DI_Scope *scope = di_scope_open(); DF_Entity *thread = df_entity_from_handle(params.entity); - U64 base_unwind_index = params.base_unwind_index; - U64 inline_unwind_index = params.inline_unwind_index; + U64 unwind_index = params.unwind_index; + U64 inline_depth = params.inline_depth; if(thread->kind == DF_EntityKind_Thread) { // rjf: grab rip - U64 rip_vaddr = df_query_cached_rip_from_thread_unwind(thread, base_unwind_index); + U64 rip_vaddr = df_query_cached_rip_from_thread_unwind(thread, unwind_index); // rjf: extract thread/rip info DF_Entity *process = df_entity_ancestor_from_kind(thread, DF_EntityKind_Process); @@ -2605,7 +2605,7 @@ df_window_update_and_render(Arena *arena, DF_Window *ws, DF_CmdList *cmds) for(DF_LineNode *n = lines.first; n != 0; n = n->next, idx += 1) { line = n->v; - if(idx == inline_unwind_index) + if(idx == inline_depth) { break; } @@ -2632,12 +2632,13 @@ df_window_update_and_render(Arena *arena, DF_Window *ws, DF_CmdList *cmds) params.entity = df_handle_from_entity(thread); params.voff = rip_voff; params.vaddr = rip_vaddr; - params.base_unwind_index = base_unwind_index; - params.inline_unwind_index = inline_unwind_index; + params.unwind_index = unwind_index; + params.inline_depth = inline_depth; df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_Entity); df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_VirtualOff); df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_VirtualAddr); - df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_BaseUnwindIndex); + df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_UnwindIndex); + df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_InlineDepth); df_cmd_list_push(arena, cmds, ¶ms, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_FindCodeLocation)); } @@ -2648,12 +2649,13 @@ df_window_update_and_render(Arena *arena, DF_Window *ws, DF_CmdList *cmds) params.entity = df_handle_from_entity(thread); params.voff = rip_voff; params.vaddr = rip_vaddr; - params.base_unwind_index = base_unwind_index; - params.inline_unwind_index = inline_unwind_index; + params.unwind_index = unwind_index; + params.inline_depth = inline_depth; df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_Entity); df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_VirtualOff); df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_VirtualAddr); - df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_Index); + df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_UnwindIndex); + df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_InlineDepth); df_cmd_list_push(arena, cmds, ¶ms, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_FindCodeLocation)); } @@ -2671,11 +2673,11 @@ df_window_update_and_render(Arena *arena, DF_Window *ws, DF_CmdList *cmds) DF_Entity *selected_thread = df_entity_from_handle(ctrl_ctx.thread); DF_CmdParams params = df_cmd_params_from_window(ws); params.entity = df_handle_from_entity(selected_thread); - params.base_unwind_index = ctrl_ctx.unwind_count; - params.inline_unwind_index = ctrl_ctx.inline_unwind_count; + params.unwind_index = ctrl_ctx.unwind_count; + params.inline_depth = ctrl_ctx.inline_depth; df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_Entity); - df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_BaseUnwindIndex); - df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_InlineUnwindIndex); + df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_UnwindIndex); + df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_InlineDepth); df_cmd_list_push(arena, cmds, ¶ms, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_FindThread)); }break; @@ -3732,7 +3734,7 @@ df_window_update_and_render(Arena *arena, DF_Window *ws, DF_CmdList *cmds) ui_labelf("cursor: (L:%I64d, C:%I64d)", regs->cursor.line, regs->cursor.column); ui_labelf("mark: (L:%I64d, C:%I64d)", regs->mark.line, regs->mark.column); ui_labelf("unwind_count: %I64u", regs->unwind_count); - ui_labelf("inline_unwind_count: %I64u", regs->inline_unwind_count); + ui_labelf("inline_depth: %I64u", regs->inline_depth); ui_labelf("text_key: [0x%I64x, 0x%I64x]", regs->text_key.u64[0], regs->text_key.u64[1]); ui_labelf("lang_kind: '%S'", txt_extension_from_lang_kind(regs->lang_kind)); ui_labelf("vaddr_range: [0x%I64x, 0x%I64x)", regs->vaddr_range.min, regs->vaddr_range.max); @@ -4339,34 +4341,37 @@ df_window_update_and_render(Arena *arena, DF_Window *ws, DF_CmdList *cmds) DF_Entity *process = df_entity_ancestor_from_kind(entity, DF_EntityKind_Process); CTRL_Unwind base_unwind = df_query_cached_unwind_from_thread(entity); DF_Unwind rich_unwind = df_unwind_from_ctrl_unwind(scratch.arena, di_scope, process, &base_unwind); - String8List lines = {0}; - for(U64 frame_idx = 0; frame_idx < rich_unwind.frames.count; frame_idx += 1) - { - U64 rip_vaddr = regs_rip_from_arch_block(entity->arch, rich_unwind.frames.v[frame_idx].regs); + String8List lines = {0}; + for(U64 frame_idx = 0; frame_idx < rich_unwind.frames.concrete_frame_count; frame_idx += 1) + { + DF_UnwindFrame *concrete_frame = &rich_unwind.frames.v[frame_idx]; + U64 rip_vaddr = regs_rip_from_arch_block(entity->arch, concrete_frame->regs); DF_Entity *module = df_module_from_process_vaddr(process, rip_vaddr); - RDI_Parsed *rdi = rich_unwind.frames.v[frame_idx].rdi; - RDI_Procedure *procedure = rich_unwind.frames.v[frame_idx].procedure; - RDI_InlineSite *inline_site = rich_unwind.frames.v[frame_idx].inline_site; - if(procedure != 0) - { - String8 name = {0}; - name.str = rdi_name_from_procedure(rdi, procedure, &name.size); - str8_list_pushf(scratch.arena, &lines, "0x%I64x: \"%S\"%s%S", rip_vaddr, name, df_entity_is_nil(module) ? "" : " in ", module->name); - } - else if(inline_site != 0) - { + RDI_Parsed *rdi = concrete_frame->rdi; + RDI_Procedure *procedure = concrete_frame->procedure; + for(DF_UnwindInlineFrame *inline_frame = concrete_frame->last_inline_frame; + inline_frame != 0; + inline_frame = inline_frame->prev) + { + RDI_InlineSite *inline_site = inline_frame->inline_site; String8 name = {0}; name.str = rdi_string_from_idx(rdi, inline_site->name_string_idx, &name.size); - str8_list_pushf(scratch.arena, &lines, "0x%I64x: [inlined] \"%S\"%s%S", rip_vaddr, name, df_entity_is_nil(module) ? "" : " in ", module->name); - } - else if(!df_entity_is_nil(module)) - { - str8_list_pushf(scratch.arena, &lines, "0x%I64x: [??? in %S]", rip_vaddr, module->name); - } - else - { - str8_list_pushf(scratch.arena, &lines, "0x%I64x: [??? in ???]", rip_vaddr); - } + str8_list_pushf(scratch.arena, &lines, "0x%I64x: [inlined] \"%S\"%s%S", rip_vaddr, name, df_entity_is_nil(module) ? "" : " in ", module->name); + } + if(procedure != 0) + { + String8 name = {0}; + name.str = rdi_name_from_procedure(rdi, procedure, &name.size); + str8_list_pushf(scratch.arena, &lines, "0x%I64x: \"%S\"%s%S", rip_vaddr, name, df_entity_is_nil(module) ? "" : " in ", module->name); + } + else if(!df_entity_is_nil(module)) + { + str8_list_pushf(scratch.arena, &lines, "0x%I64x: [??? in %S]", rip_vaddr, module->name); + } + else + { + str8_list_pushf(scratch.arena, &lines, "0x%I64x: [??? in ???]", rip_vaddr); + } } StringJoin join = {0}; join.sep = join.post = str8_lit("\n"); @@ -10623,34 +10628,24 @@ df_entity_tooltips(DF_Window *ws, DF_Entity *entity) DI_Scope *di_scope = di_scope_open(); DF_Entity *process = df_entity_ancestor_from_kind(entity, DF_EntityKind_Process); CTRL_Unwind base_unwind = df_query_cached_unwind_from_thread(entity); - DF_Unwind rich_unwind = df_unwind_from_ctrl_unwind(scratch.arena, di_scope, process, &base_unwind); - for(U64 idx = 0; idx < rich_unwind.frames.count; idx += 1) - { - DF_UnwindFrame *f = &rich_unwind.frames.v[idx]; + DF_Unwind rich_unwind = df_unwind_from_ctrl_unwind(scratch.arena, di_scope, process, &base_unwind); + for(U64 idx = 0; idx < rich_unwind.frames.concrete_frame_count; idx += 1) + { + DF_UnwindFrame *f = &rich_unwind.frames.v[idx]; RDI_Parsed *rdi = f->rdi; - RDI_Procedure *procedure = f->procedure; - RDI_InlineSite *inline_site = f->inline_site; + RDI_Procedure *procedure = f->procedure; U64 rip_vaddr = regs_rip_from_arch_block(entity->arch, f->regs); DF_Entity *module = df_module_from_process_vaddr(process, rip_vaddr); - String8 module_name = df_entity_is_nil(module) ? str8_lit("???") : str8_skip_last_slash(module->name); - String8 name = {0}; - String8 info = {0}; - if(procedure != 0) - { - name.str = rdi_name_from_procedure(rdi, procedure, &name.size); - } - else if(inline_site != 0) - { - name.str = rdi_string_from_idx(rdi, inline_site->name_string_idx, &name.size); - info = str8_lit("[inlined]"); - } - UI_PrefWidth(ui_children_sum(1)) UI_Row - { - DF_Font(ws, DF_FontSlot_Code) UI_PrefWidth(ui_em(18.f, 1.f)) UI_FlagsAdd(UI_BoxFlag_DrawTextWeak) ui_labelf("0x%I64x", rip_vaddr); - if(info.size != 0) - { - DF_Font(ws, DF_FontSlot_Code)UI_FlagsAdd(UI_BoxFlag_DrawTextWeak) UI_PrefWidth(ui_text_dim(10, 1)) ui_label(info); - } + String8 module_name = df_entity_is_nil(module) ? str8_lit("???") : str8_skip_last_slash(module->name); + + // rjf: inline frames + for(DF_UnwindInlineFrame *fin = f->last_inline_frame; fin != 0; fin = fin->prev) + UI_PrefWidth(ui_children_sum(1)) UI_Row + { + String8 name = {0}; + name.str = rdi_string_from_idx(rdi, fin->inline_site->name_string_idx, &name.size); + DF_Font(ws, DF_FontSlot_Code) UI_PrefWidth(ui_em(18.f, 1.f)) UI_FlagsAdd(UI_BoxFlag_DrawTextWeak) ui_labelf("0x%I64x", rip_vaddr); + DF_Font(ws, DF_FontSlot_Code) UI_FlagsAdd(UI_BoxFlag_DrawTextWeak) UI_PrefWidth(ui_text_dim(10, 1)) ui_label(str8_lit("[inlined]")); if(name.size != 0) { DF_Font(ws, DF_FontSlot_Code) UI_PrefWidth(ui_text_dim(10, 1)) @@ -10661,8 +10656,27 @@ df_entity_tooltips(DF_Window *ws, DF_Entity *entity) else { DF_Font(ws, DF_FontSlot_Code) UI_FlagsAdd(UI_BoxFlag_DrawTextWeak) UI_PrefWidth(ui_text_dim(10, 1)) ui_labelf("[??? in %S]", module_name); + } + } + + // rjf: concrete frame + UI_PrefWidth(ui_children_sum(1)) UI_Row + { + String8 name = {0}; + name.str = rdi_name_from_procedure(rdi, procedure, &name.size); + DF_Font(ws, DF_FontSlot_Code) UI_PrefWidth(ui_em(18.f, 1.f)) UI_FlagsAdd(UI_BoxFlag_DrawTextWeak) ui_labelf("0x%I64x", rip_vaddr); + if(name.size != 0) + { + DF_Font(ws, DF_FontSlot_Code) UI_PrefWidth(ui_text_dim(10, 1)) + { + df_code_label(1.f, 0, df_rgba_from_theme_color(DF_ThemeColor_CodeSymbol), name); + } } - } + else + { + DF_Font(ws, DF_FontSlot_Code) UI_FlagsAdd(UI_BoxFlag_DrawTextWeak) UI_PrefWidth(ui_text_dim(10, 1)) ui_labelf("[??? in %S]", module_name); + } + } } di_scope_close(di_scope); }break; @@ -12513,7 +12527,7 @@ df_code_slice(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_ { if((n->v.pt.line == line_num || df_entity_is_nil(df_entity_from_handle(df_interact_regs()->file))) && ((di_key_match(&n->v.dbgi_key, &rich_hover.dbgi_key) && - n->v.voff_range.min <= rich_hover_voff_range.min && rich_hover_voff_range.min <= n->v.voff_range.max) || + n->v.voff_range.min <= rich_hover_voff_range.min && rich_hover_voff_range.min < n->v.voff_range.max) || (params->line_vaddrs[line_idx] == rich_hover.vaddr_range.min && rich_hover.vaddr_range.min != 0))) { matches = 1; diff --git a/src/df/gfx/df_views.c b/src/df/gfx/df_views.c index 2b8e3f11..02addbd9 100644 --- a/src/df/gfx/df_views.c +++ b/src/df/gfx/df_views.c @@ -622,8 +622,8 @@ df_code_view_build(Arena *arena, DF_Window *ws, DF_Panel *panel, DF_View *view, { DF_Entity *thread = thread_n->entity; DF_Entity *process = df_entity_ancestor_from_kind(thread, DF_EntityKind_Process); - U64 base_unwind_count = (thread == selected_thread) ? ctrl_ctx.unwind_count : 0; - U64 inline_unwind_count = (thread == selected_thread) ? ctrl_ctx.inline_unwind_count : 0; + U64 unwind_count = (thread == selected_thread) ? ctrl_ctx.unwind_count : 0; + U64 inline_depth = (thread == selected_thread) ? ctrl_ctx.inline_depth : 0; U64 rip_vaddr = df_query_cached_rip_from_thread_unwind(thread, unwind_count); U64 last_inst_on_unwound_rip_vaddr = rip_vaddr - !!unwind_count; DF_Entity *module = df_module_from_process_vaddr(process, last_inst_on_unwound_rip_vaddr); @@ -4230,7 +4230,7 @@ DF_VIEW_UI_FUNCTION_DEF(SymbolLister) UI_BoxFlag_DrawHotEffects| UI_BoxFlag_DrawActiveEffects, "###procedure_%I64x", item->idx); - UI_Parent(box) UI_PrefWidth(ui_text_dim(10, 1)) + UI_Parent(box) UI_PrefWidth(ui_text_dim(10, 1)) DF_Font(ws, DF_FontSlot_Code) { UI_Box *box = df_code_label(1.f, 0, df_rgba_from_theme_color(DF_ThemeColor_CodeSymbol), name); ui_box_equip_fuzzy_match_ranges(box, &item->match_ranges); @@ -5684,6 +5684,49 @@ DF_VIEW_UI_FUNCTION_DEF(CallStack) CTRL_Unwind base_unwind = df_query_cached_unwind_from_thread(thread); DF_Unwind rich_unwind = df_unwind_from_ctrl_unwind(scratch.arena, scope, process, &base_unwind); + //- rjf: build per-row information + typedef struct FrameRow FrameRow; + struct FrameRow + { + void *regs; + RDI_Parsed *rdi; + RDI_Procedure *procedure; + RDI_InlineSite *inline_site; + U64 unwind_idx; + U64 inline_depth; + }; + U64 rows_count = rich_unwind.frames.total_frame_count; + FrameRow *rows = push_array(scratch.arena, FrameRow, rows_count); + { + U64 concrete_frame_idx = 0; + U64 row_idx = 0; + for(;concrete_frame_idx < rich_unwind.frames.concrete_frame_count; concrete_frame_idx += 1, row_idx += 1) + { + DF_UnwindFrame *f = &rich_unwind.frames.v[concrete_frame_idx]; + + // rjf: fill rows for inline frames + { + U64 inline_unwind_idx = 0; + for(DF_UnwindInlineFrame *fin = f->last_inline_frame; fin != 0; fin = fin->prev, row_idx += 1, inline_unwind_idx += 1) + { + rows[row_idx].regs = f->regs; + rows[row_idx].rdi = f->rdi; + rows[row_idx].inline_site = fin->inline_site; + rows[row_idx].unwind_idx = concrete_frame_idx; + rows[row_idx].inline_depth = f->inline_frame_count - inline_unwind_idx; + } + } + + // rjf: fill row for concrete frame + { + rows[row_idx].regs = f->regs; + rows[row_idx].rdi = f->rdi; + rows[row_idx].procedure = f->procedure; + rows[row_idx].unwind_idx= concrete_frame_idx; + } + } + } + //- rjf: grab state typedef struct DF_CallStackViewState DF_CallStackViewState; struct DF_CallStackViewState @@ -5713,8 +5756,8 @@ DF_VIEW_UI_FUNCTION_DEF(CallStack) scroll_list_params.flags = UI_ScrollListFlag_All; scroll_list_params.row_height_px = floor_f32(ui_top_font_size()*2.5f); scroll_list_params.dim_px = dim_2f32(rect); - scroll_list_params.cursor_range = r2s64(v2s64(0, 0), v2s64(3, rich_unwind.frames.count)); - scroll_list_params.item_range = r1s64(0, rich_unwind.frames.count+1); + scroll_list_params.cursor_range = r2s64(v2s64(0, 0), v2s64(3, rich_unwind.frames.total_frame_count)); + scroll_list_params.item_range = r1s64(0, rich_unwind.frames.total_frame_count+1); scroll_list_params.cursor_min_is_empty_selection[Axis2_Y] = 1; } UI_ScrollListSignal scroll_list_sig = {0}; @@ -5754,7 +5797,7 @@ DF_VIEW_UI_FUNCTION_DEF(CallStack) //- rjf: frame rows for(S64 row_num = visible_row_range.min; - row_num <= visible_row_range.max && row_num <= rich_unwind.frames.count; + row_num <= visible_row_range.max && row_num <= rows_count; row_num += 1) { if(row_num == 0) @@ -5764,29 +5807,29 @@ DF_VIEW_UI_FUNCTION_DEF(CallStack) B32 row_selected = (cs->cursor.y == row_num); // rjf: unpack frame - U64 frame_idx = row_num-1; - DF_UnwindFrame *frame = &rich_unwind.frames.v[frame_idx]; - U64 rip_vaddr = regs_rip_from_arch_block(thread->arch, frame->regs); + U64 row_idx = row_num-1; + FrameRow *row = &rows[row_idx]; + U64 rip_vaddr = regs_rip_from_arch_block(thread->arch, row->regs); DF_Entity *module = df_module_from_process_vaddr(process, rip_vaddr); B32 frame_valid = (rip_vaddr != 0); TG_Graph *graph = tg_graph_begin(bit_size_from_arch(thread->arch)/8, 256); String8 symbol_name = {0}; String8 symbol_type_string = {0}; - if(frame->procedure != 0) + if(row->procedure != 0) { - symbol_name.str = rdi_name_from_procedure(frame->rdi, frame->procedure, &symbol_name.size); - RDI_TypeNode *type = rdi_element_from_name_idx(frame->rdi, TypeNodes, frame->procedure->type_idx); - symbol_type_string = tg_string_from_key(scratch.arena, graph, frame->rdi, tg_key_ext(tg_kind_from_rdi_type_kind(type->kind), frame->procedure->type_idx)); + symbol_name.str = rdi_name_from_procedure(row->rdi, row->procedure, &symbol_name.size); + RDI_TypeNode *type = rdi_element_from_name_idx(row->rdi, TypeNodes, row->procedure->type_idx); + symbol_type_string = tg_string_from_key(scratch.arena, graph, row->rdi, tg_key_ext(tg_kind_from_rdi_type_kind(type->kind), row->procedure->type_idx)); } - if(frame->inline_site != 0) + if(row->inline_site != 0) { - symbol_name.str = rdi_string_from_idx(frame->rdi, frame->inline_site->name_string_idx, &symbol_name.size); - RDI_TypeNode *type = rdi_element_from_name_idx(frame->rdi, TypeNodes, frame->inline_site->type_idx); - symbol_type_string = tg_string_from_key(scratch.arena, graph, frame->rdi, tg_key_ext(tg_kind_from_rdi_type_kind(type->kind), frame->inline_site->type_idx)); + symbol_name.str = rdi_string_from_idx(row->rdi, row->inline_site->name_string_idx, &symbol_name.size); + RDI_TypeNode *type = rdi_element_from_name_idx(row->rdi, TypeNodes, row->inline_site->type_idx); + symbol_type_string = tg_string_from_key(scratch.arena, graph, row->rdi, tg_key_ext(tg_kind_from_rdi_type_kind(type->kind), row->inline_site->type_idx)); } // rjf: build row - if(frame_valid) UI_NamedTableVectorF("###callstack_%p_%I64x", view, frame_idx) + if(frame_valid) UI_NamedTableVectorF("###callstack_%p_%I64x", view, row_idx) { // rjf: build cell for selection UI_TableCell @@ -5797,28 +5840,27 @@ DF_VIEW_UI_FUNCTION_DEF(CallStack) UI_FocusHot((row_selected && cs->cursor.x == 0) ? UI_FocusKind_On : UI_FocusKind_Off) { String8 selected_string = {0}; - if(ctrl_ctx.unwind_count == frame->base_unwind_idx && - ctrl_ctx.inline_unwind_count == frame->inline_unwind_idx) + if(ctrl_ctx.unwind_count == row->unwind_idx && + ctrl_ctx.inline_depth == row->inline_depth) { selected_string = df_g_icon_kind_text_table[DF_IconKind_RightArrow]; ui_set_next_palette(ui_build_palette(ui_top_palette(), .text = thread_color)); } - UI_Box *box = ui_build_box_from_stringf(UI_BoxFlag_Clickable|UI_BoxFlag_DrawText, "%S###selection_%i", selected_string, - (int)frame_idx); + UI_Box *box = ui_build_box_from_stringf(UI_BoxFlag_Clickable|UI_BoxFlag_DrawText, "%S###selection_%I64u", selected_string, row_idx); UI_Signal sig = ui_signal_from_box(box); if(ui_pressed(sig)) { - next_cursor = v2s64(0, (S64)frame_idx+1); + next_cursor = v2s64(0, row_num); DF_CmdParams p = df_cmd_params_from_panel(ws, panel); df_push_cmd__root(&p, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_FocusPanel)); } if(ui_double_clicked(sig) || sig.f&UI_SignalFlag_KeyboardPressed) { DF_CmdParams params = df_cmd_params_from_view(ws, panel, view); - df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_BaseUnwindIndex); - df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_InlineUnwindIndex); - params.base_unwind_index = frame->base_unwind_idx; - params.inline_unwind_index = frame->inline_unwind_idx; + df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_UnwindIndex); + df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_InlineDepth); + params.unwind_index = row->unwind_idx; + params.inline_depth = row->inline_depth; df_push_cmd__root(¶ms, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_SelectUnwind)); } } @@ -5828,10 +5870,10 @@ DF_VIEW_UI_FUNCTION_DEF(CallStack) UI_FocusHot((row_selected && cs->cursor.x == 1) ? UI_FocusKind_On : UI_FocusKind_Off) { ui_set_next_child_layout_axis(Axis2_X); - UI_Box *box = ui_build_box_from_stringf(UI_BoxFlag_Clickable|UI_BoxFlag_Clip, "frame_%I64x", frame_idx); + UI_Box *box = ui_build_box_from_stringf(UI_BoxFlag_Clickable|UI_BoxFlag_Clip, "row_%I64x", row_idx); UI_Parent(box) { - if(frame->inline_site != 0) + if(row->inline_site != 0) { UI_PrefWidth(ui_text_dim(10, 1)) UI_FlagsAdd(UI_BoxFlag_DrawTextWeak) { @@ -5858,17 +5900,17 @@ DF_VIEW_UI_FUNCTION_DEF(CallStack) UI_Signal sig = ui_signal_from_box(box); if(ui_pressed(sig)) { - next_cursor = v2s64(1, (S64)frame_idx+1); + next_cursor = v2s64(1, row_num); DF_CmdParams p = df_cmd_params_from_panel(ws, panel); df_push_cmd__root(&p, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_FocusPanel)); } if(ui_double_clicked(sig) || sig.f&UI_SignalFlag_KeyboardPressed) { DF_CmdParams params = df_cmd_params_from_view(ws, panel, view); - df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_BaseUnwindIndex); - df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_InlineUnwindIndex); - params.base_unwind_index = frame->base_unwind_idx; - params.inline_unwind_index = frame->inline_unwind_idx; + df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_UnwindIndex); + df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_InlineDepth); + params.unwind_index = row->unwind_idx; + params.inline_depth = row->inline_depth; df_push_cmd__root(¶ms, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_SelectUnwind)); } } @@ -5881,17 +5923,17 @@ DF_VIEW_UI_FUNCTION_DEF(CallStack) UI_Signal sig = ui_signal_from_box(box); if(ui_pressed(sig)) { - next_cursor = v2s64(2, (S64)frame_idx+1); + next_cursor = v2s64(2, row_num); DF_CmdParams p = df_cmd_params_from_panel(ws, panel); df_push_cmd__root(&p, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_FocusPanel)); } if(ui_double_clicked(sig) || sig.f&UI_SignalFlag_KeyboardPressed) { DF_CmdParams params = df_cmd_params_from_view(ws, panel, view); - df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_BaseUnwindIndex); - df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_InlineUnwindIndex); - params.base_unwind_index = frame->base_unwind_idx; - params.inline_unwind_index = frame->inline_unwind_idx; + df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_UnwindIndex); + df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_InlineDepth); + params.unwind_index = row->unwind_idx; + params.inline_depth = row->inline_depth; df_push_cmd__root(¶ms, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_SelectUnwind)); } } @@ -5902,7 +5944,7 @@ DF_VIEW_UI_FUNCTION_DEF(CallStack) UI_Signal sig = {0}; if(df_entity_is_nil(module)) UI_FlagsAdd(UI_BoxFlag_DrawTextWeak) { - UI_Box *box = ui_build_box_from_stringf(UI_BoxFlag_DrawText|UI_BoxFlag_Clickable, "(No Module)###moduleless_frame_%I64x", frame_idx); + UI_Box *box = ui_build_box_from_stringf(UI_BoxFlag_DrawText|UI_BoxFlag_Clickable, "(No Module)###moduleless_frame_%I64x", row_idx); sig = ui_signal_from_box(box); } else @@ -5911,17 +5953,17 @@ DF_VIEW_UI_FUNCTION_DEF(CallStack) } if(ui_pressed(sig)) { - next_cursor = v2s64(3, (S64)frame_idx+1); + next_cursor = v2s64(3, row_num); DF_CmdParams p = df_cmd_params_from_panel(ws, panel); df_push_cmd__root(&p, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_FocusPanel)); } if(ui_double_clicked(sig) || sig.f&UI_SignalFlag_KeyboardPressed) { DF_CmdParams params = df_cmd_params_from_view(ws, panel, view); - df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_BaseUnwindIndex); - df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_InlineUnwindIndex); - params.base_unwind_index = frame->base_unwind_idx; - params.inline_unwind_index = frame->inline_unwind_idx; + df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_UnwindIndex); + df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_InlineDepth); + params.unwind_index = row->unwind_idx; + params.inline_depth = row->inline_depth; df_push_cmd__root(¶ms, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_SelectUnwind)); } } @@ -6525,6 +6567,7 @@ DF_VIEW_UI_FUNCTION_DEF(Code) UI_PrefWidth(ui_text_dim(10, 1)) UI_Focus(UI_FocusKind_On) DF_Palette(ws, DF_PaletteCode_NeutralPopButton) + UI_TextAlignment(UI_TextAlign_Center) if(ui_clicked(ui_buttonf("Find alternative..."))) { DF_CmdParams params = df_cmd_params_from_view(ws, panel, view); diff --git a/src/lib_rdi_make/rdi_make.c b/src/lib_rdi_make/rdi_make.c index e5832efe..5c08e298 100644 --- a/src/lib_rdi_make/rdi_make.c +++ b/src/lib_rdi_make/rdi_make.c @@ -1,3680 +1,3680 @@ -// Copyright (c) 2024 Epic Games Tools -// Licensed under the MIT license (https://opensource.org/license/mit/) - -//////////////////////////////// -//~ rjf: API Implementation Helper Macros - -#define rdim_require(root, b32, else_code, error_msg) do { if(!(b32)) {rdim_push_msg((root), (error_msg)); else_code;} }while(0) -#define rdim_requiref(root, b32, else_code, fmt, ...) do { if(!(b32)) {rdim_push_msgf((root), (fmt), __VA_ARGS__); else_code;} }while(0) - -//////////////////////////////// -//~ rjf: Basic Helpers - -//- rjf: memory set - -#if !defined(RDIM_MEMSET_OVERRIDE) -RDI_PROC void * -rdim_memset_fallback(void *dst, RDI_U8 c, RDI_U64 size) -{ - for(RDI_U64 idx = 0; idx < size; idx += 1) - { - ((RDI_U8 *)dst)[idx] = c; - } - return dst; -} -#endif - -#if !defined(RDIM_MEMCPY_OVERRIDE) -RDI_PROC void * -rdim_memcpy_fallback(void *dst, void *src, RDI_U64 size) -{ - for(RDI_U64 idx = 0; idx < size; idx += 1) - { - ((RDI_U8 *)dst)[idx] = ((RDI_U8 *)src)[idx]; - } - return dst; -} -#endif - -//- rjf: arenas - -#if !defined (RDIM_ARENA_OVERRIDE) - -RDI_PROC RDIM_Arena * -rdim_arena_alloc_fallback(void) -{ - RDIM_Arena *arena = 0; - // TODO(rjf) - return arena; -} - -RDI_PROC void -rdim_arena_release_fallback(RDIM_Arena *arena) -{ - // TODO(rjf) -} - -RDI_PROC RDI_U64 -rdim_arena_pos_fallback(RDIM_Arena *arena) -{ - // TODO(rjf) - return 0; -} - -RDI_PROC void * -rdim_arena_push_fallback(RDIM_Arena *arena, RDI_U64 size) -{ - // TODO(rjf) - return 0; -} - -RDI_PROC void -rdim_arena_pop_to_fallback(RDIM_Arena *arena, RDI_U64 pos) -{ - // TODO(rjf) -} - -#endif - -//- rjf: thread-local scratch arenas - -#if !defined (RDIM_SCRATCH_OVERRIDE) -static RDIM_THREAD_LOCAL RDIM_Arena *rdim_thread_scratches[2]; - -RDI_PROC RDIM_Temp -rdim_scratch_begin_fallback(RDIM_Arena **conflicts, RDI_U64 conflicts_count) -{ - if(rdim_thread_scratches[0] == 0) - { - rdim_thread_scratches[0] = rdim_arena_alloc(); - rdim_thread_scratches[1] = rdim_arena_alloc(); - } - RDIM_Arena *arena = 0; - for(RDI_U64 scratch_idx = 0; - scratch_idx < sizeof(rdim_thread_scratches)/sizeof(rdim_thread_scratches[0]); - scratch_idx += 1) - { - RDI_S32 scratch_conflicts = 0; - for(RDI_U64 conflict_idx = 0; conflict_idx < conflicts_count; conflict_idx += 1) - { - if(conflicts[conflict_idx] == rdim_thread_scratches[scratch_idx]) - { - scratch_conflicts = 1; - break; - } - } - if(!scratch_conflicts) - { - arena = rdim_thread_scratches[scratch_idx]; - } - } - RDIM_Temp temp; - temp.arena = arena; - temp.pos = rdim_arena_pos(arena); - return temp; -} - -RDI_PROC void -rdim_scratch_end_fallback(RDIM_Temp temp) -{ - rdim_arena_pop_to(temp.arena, temp.pos); -} - -#endif - -//- rjf: strings - -RDI_PROC RDIM_String8 -rdim_str8(RDI_U8 *str, RDI_U64 size) -{ - RDIM_String8 result; - result.RDIM_String8_BaseMember = str; - result.RDIM_String8_SizeMember = size; - return result; -} - -RDI_PROC RDIM_String8 -rdim_str8_copy(RDIM_Arena *arena, RDIM_String8 src) -{ - RDIM_String8 dst; - dst.RDIM_String8_SizeMember = src.RDIM_String8_SizeMember; - dst.RDIM_String8_BaseMember = rdim_push_array_no_zero(arena, RDI_U8, dst.RDIM_String8_SizeMember+1); - rdim_memcpy(dst.RDIM_String8_BaseMember, src.RDIM_String8_BaseMember, src.RDIM_String8_SizeMember); - dst.RDIM_String8_BaseMember[dst.RDIM_String8_SizeMember] = 0; - return dst; -} - -RDI_PROC RDIM_String8 -rdim_str8f(RDIM_Arena *arena, char *fmt, ...) -{ - va_list args; - va_start(args, fmt); - RDIM_String8 result = rdim_str8fv(arena, fmt, args); - va_end(args); - return(result); -} - -RDI_PROC RDIM_String8 -rdim_str8fv(RDIM_Arena *arena, char *fmt, va_list args) -{ - va_list args2; - va_copy(args2, args); - RDI_U32 needed_bytes = rdim_vsnprintf(0, 0, fmt, args) + 1; - RDIM_String8 result = {0}; - result.RDIM_String8_BaseMember = rdim_push_array_no_zero(arena, RDI_U8, needed_bytes); - result.RDIM_String8_SizeMember = rdim_vsnprintf((char*)result.str, needed_bytes, fmt, args2); - result.RDIM_String8_BaseMember[result.RDIM_String8_SizeMember] = 0; - va_end(args2); - return(result); -} - -RDI_PROC RDI_S32 -rdim_str8_match(RDIM_String8 a, RDIM_String8 b, RDIM_StringMatchFlags flags) -{ - RDI_S32 result = 0; - if(a.RDIM_String8_SizeMember == b.RDIM_String8_SizeMember) - { - RDI_S32 case_insensitive = (flags & RDIM_StringMatchFlag_CaseInsensitive); - RDI_U64 size = a.RDIM_String8_SizeMember; - result = 1; - for(RDI_U64 idx = 0; idx < size; idx += 1) - { - RDI_U8 at = a.RDIM_String8_BaseMember[idx]; - RDI_U8 bt = b.RDIM_String8_BaseMember[idx]; - if(case_insensitive) - { - at = ('a' <= at && at <= 'z') ? at-('a'-'A') : at; - bt = ('a' <= bt && bt <= 'z') ? bt-('a'-'A') : bt; - } - if(at != bt) - { - result = 0; - break; - } - } - } - return result; -} - -//- rjf: string lists - -RDI_PROC void -rdim_str8_list_push(RDIM_Arena *arena, RDIM_String8List *list, RDIM_String8 string) -{ - RDIM_String8Node *n = rdim_push_array(arena, RDIM_String8Node, 1); - n->RDIM_String8Node_StringMember = string; - RDIM_SLLQueuePush_N(list->RDIM_String8List_FirstMember, list->RDIM_String8List_LastMember, n, RDIM_String8Node_NextPtrMember); - list->RDIM_String8List_NodeCountMember += 1; - list->RDIM_String8List_TotalSizeMember += string.RDIM_String8_SizeMember; -} - -RDI_PROC void -rdim_str8_list_push_front(RDIM_Arena *arena, RDIM_String8List *list, RDIM_String8 string) -{ - RDIM_String8Node *n = rdim_push_array(arena, RDIM_String8Node, 1); - n->RDIM_String8Node_StringMember = string; - RDIM_SLLQueuePushFront_N(list->RDIM_String8List_FirstMember, list->RDIM_String8List_LastMember, n, RDIM_String8Node_NextPtrMember); - list->RDIM_String8List_NodeCountMember += 1; - list->RDIM_String8List_TotalSizeMember += string.RDIM_String8_SizeMember; -} - -RDI_PROC void -rdim_str8_list_push_align(RDIM_Arena *arena, RDIM_String8List *list, RDI_U64 align) -{ - RDI_U64 total_size_pre_align = list->total_size; - RDI_U64 total_size_post_align = (total_size_pre_align + (align-1))&(~(align-1)); - RDI_U64 needed_size = total_size_post_align - total_size_pre_align; - if(needed_size != 0) - { - RDI_U8 *padding = rdim_push_array(arena, RDI_U8, needed_size); - rdim_str8_list_push(arena, list, rdim_str8(padding, needed_size)); - } -} - -RDI_PROC RDIM_String8 -rdim_str8_list_join(RDIM_Arena *arena, RDIM_String8List *list, RDIM_String8 sep) -{ - RDIM_String8 result; - rdim_memzero_struct(&result); - RDI_U64 sep_count = (list->RDIM_String8List_NodeCountMember > 1) ? (list->RDIM_String8List_NodeCountMember-1) : 0; - result.RDIM_String8_SizeMember = list->RDIM_String8List_TotalSizeMember+sep_count*sep.RDIM_String8_SizeMember; - result.RDIM_String8_BaseMember = rdim_push_array_no_zero(arena, RDI_U8, result.RDIM_String8_SizeMember+1); - RDI_U64 off = 0; - for(RDIM_String8Node *node = list->RDIM_String8List_FirstMember; - node != 0; - node = node->RDIM_String8Node_NextPtrMember) - { - rdim_memcpy((RDI_U8*)result.RDIM_String8_BaseMember+off, - node->RDIM_String8Node_StringMember.RDIM_String8_BaseMember, - node->RDIM_String8Node_StringMember.RDIM_String8_SizeMember); - off += node->RDIM_String8Node_StringMember.RDIM_String8_SizeMember; - if(sep.RDIM_String8_SizeMember != 0 && node->RDIM_String8Node_NextPtrMember != 0) - { - rdim_memcpy((RDI_U8*)result.RDIM_String8_BaseMember+off, - sep.RDIM_String8_BaseMember, - sep.RDIM_String8_SizeMember); - off += sep.RDIM_String8_SizeMember; - } - } - result.RDIM_String8_BaseMember[off] = 0; - return result; -} - -//- rjf: sortable range sorting - -RDI_PROC RDIM_SortKey * -rdim_sort_key_array(RDIM_Arena *arena, RDIM_SortKey *keys, RDI_U64 count) -{ - // This sort is designed to take advantage of lots of pre-existing sorted ranges. - // Most line info is already sorted or close to already sorted. - // Similarly most vmap data has lots of pre-sorted ranges. etc. etc. - // Also - this sort should be a "stable" sort. In the use case of sorting vmap - // ranges, we want to be able to rely on order, so it needs to be preserved here. - - RDIM_Temp scratch = rdim_scratch_begin(&arena, 1); - RDIM_SortKey *result = 0; - - if(count <= 1) - { - result = keys; - } - else - { - RDIM_OrderedRange *ranges_first = 0; - RDIM_OrderedRange *ranges_last = 0; - RDI_U64 range_count = 0; - { - RDI_U64 pos = 0; - for(;pos < count;) - { - // identify ordered range - RDI_U64 first = pos; - RDI_U64 opl = pos + 1; - for(; opl < count && keys[opl - 1].key <= keys[opl].key; opl += 1); - - // generate an ordered range node - RDIM_OrderedRange *new_range = rdim_push_array(rdim_temp_arena(scratch), RDIM_OrderedRange, 1); - SLLQueuePush(ranges_first, ranges_last, new_range); - range_count += 1; - new_range->first = first; - new_range->opl = opl; - - // update pos - pos = opl; - } - } - - if(range_count == 1) - { - result = keys; - } - else - { - RDIM_SortKey *keys_swap = rdim_push_array_no_zero(arena, RDIM_SortKey, count); - RDIM_SortKey *src = keys; - RDIM_SortKey *dst = keys_swap; - RDIM_OrderedRange *src_ranges = ranges_first; - RDIM_OrderedRange *dst_ranges = 0; - RDIM_OrderedRange *dst_ranges_last = 0; - - for(;;) - { - // begin a pass - for(;;) - { - // end pass when out of ranges - if(src_ranges == 0) - { - break; - } - - // get first range - RDIM_OrderedRange *range1 = src_ranges; - SLLStackPop(src_ranges); - - // if this range is the whole array, we are done - if(range1->first == 0 && range1->opl == count) - { - result = src; - goto sort_done; - } - - // if there is not a second range, save this range for next time and end this pass - if(src_ranges == 0) - { - RDI_U64 first = range1->first; - rdim_memcpy(dst + first, src + first, sizeof(*src)*(range1->opl - first)); - SLLQueuePush(dst_ranges, dst_ranges_last, range1); - break; - } - - // get second range - RDIM_OrderedRange *range2 = src_ranges; - SLLStackPop(src_ranges); - - rdim_assert(range1->opl == range2->first); - - // merge these ranges - RDI_U64 jd = range1->first; - RDI_U64 j1 = range1->first; - RDI_U64 j1_opl = range1->opl; - RDI_U64 j2 = range2->first; - RDI_U64 j2_opl = range2->opl; - for(;;) - { - if(src[j1].key <= src[j2].key) - { - rdim_memcpy(dst + jd, src + j1, sizeof(*src)); - j1 += 1; - jd += 1; - if(j1 >= j1_opl) - { - break; - } - } - else - { - rdim_memcpy(dst + jd, src + j2, sizeof(*src)); - j2 += 1; - jd += 1; - if(j2 >= j2_opl) - { - break; - } - } - } - if(j1 < j1_opl) - { - rdim_memcpy(dst + jd, src + j1, sizeof(*src)*(j1_opl - j1)); - } - else - { - rdim_memcpy(dst + jd, src + j2, sizeof(*src)*(j2_opl - j2)); - } - - // save this as one range - range1->opl = range2->opl; - SLLQueuePush(dst_ranges, dst_ranges_last, range1); - } - - // end pass by swapping buffers and range nodes - { - RDIM_SortKey *temp = src; - src = dst; - dst = temp; - } - src_ranges = dst_ranges; - dst_ranges = 0; - dst_ranges_last = 0; - } - } - } - sort_done:; - -#if 0 - // assert sortedness - for(RDI_U64 i = 1; i < count; i += 1) - { - rdim_assert(result[i - 1].key <= result[i].key); - } -#endif - - scratch_end(scratch); - return result; -} - -//- rjf: rng1u64 list - -RDI_PROC void -rdim_rng1u64_list_push(RDIM_Arena *arena, RDIM_Rng1U64List *list, RDIM_Rng1U64 r) -{ - RDIM_Rng1U64Node *n = rdim_push_array(arena, RDIM_Rng1U64Node, 1); - n->v = r; - RDIM_SLLQueuePush(list->first, list->last, n); - list->count += 1; - if(list->count == 1 || r.min < list->min) - { - list->min = r.min; - } -} - -//////////////////////////////// -//~ rjf: [Building] Binary Section List Building - -RDI_PROC RDIM_BinarySection * -rdim_binary_section_list_push(RDIM_Arena *arena, RDIM_BinarySectionList *list) -{ - RDIM_BinarySectionNode *n = rdim_push_array(arena, RDIM_BinarySectionNode, 1); - RDIM_SLLQueuePush(list->first, list->last, n); - list->count += 1; - RDIM_BinarySection *result = &n->v; - return result; -} - -//////////////////////////////// -//~ rjf: [Building] Source File Info Building - -RDI_PROC RDIM_SrcFile * -rdim_src_file_chunk_list_push(RDIM_Arena *arena, RDIM_SrcFileChunkList *list, RDI_U64 cap) -{ - RDIM_SrcFileChunkNode *n = list->last; - if(n == 0 || n->count >= n->cap) - { - n = rdim_push_array(arena, RDIM_SrcFileChunkNode, 1); - n->cap = cap; - n->base_idx = list->total_count; - n->v = rdim_push_array(arena, RDIM_SrcFile, n->cap); - RDIM_SLLQueuePush(list->first, list->last, n); - list->chunk_count += 1; - } - RDIM_SrcFile *src_file = &n->v[n->count]; - src_file->chunk = n; - n->count += 1; - list->total_count += 1; - return src_file; -} - -RDI_PROC RDI_U64 -rdim_idx_from_src_file(RDIM_SrcFile *src_file) -{ - RDI_U64 idx = 0; - if(src_file != 0 && src_file->chunk != 0) - { - idx = (src_file->chunk->base_idx + (src_file - src_file->chunk->v) + 1); - } - return idx; -} - -RDI_PROC void -rdim_src_file_chunk_list_concat_in_place(RDIM_SrcFileChunkList *dst, RDIM_SrcFileChunkList *to_push) -{ - for(RDIM_SrcFileChunkNode *n = to_push->first; n != 0; n = n->next) - { - n->base_idx += dst->total_count; - } - if(dst->last != 0 && to_push->first != 0) - { - dst->last->next = to_push->first; - dst->last = to_push->last; - dst->chunk_count += to_push->chunk_count; - dst->total_count += to_push->total_count; - } - else if(dst->first == 0) - { - rdim_memcpy_struct(dst, to_push); - } - rdim_memzero_struct(to_push); -} - -RDI_PROC void -rdim_src_file_push_line_sequence(RDIM_Arena *arena, RDIM_SrcFileChunkList *src_files, RDIM_SrcFile *src_file, RDIM_LineSequence *seq) -{ - if(src_file->first_line_map_fragment == 0) - { - src_files->source_line_map_count += 1; - } - RDIM_SrcFileLineMapFragment *fragment = rdim_push_array(arena, RDIM_SrcFileLineMapFragment, 1); - fragment->seq = seq; - RDIM_SLLQueuePush(src_file->first_line_map_fragment, src_file->last_line_map_fragment, fragment); - src_files->total_line_count += seq->line_count; -} - -//////////////////////////////// -//~ rjf: [Building] Line Info Building - -RDI_PROC RDIM_LineTable * -rdim_line_table_chunk_list_push(RDIM_Arena *arena, RDIM_LineTableChunkList *list, RDI_U64 cap) -{ - RDIM_LineTableChunkNode *n = list->last; - if(n == 0 || n->count >= n->cap) - { - n = rdim_push_array(arena, RDIM_LineTableChunkNode, 1); - n->cap = cap; - n->base_idx = list->total_count; - n->v = rdim_push_array(arena, RDIM_LineTable, n->cap); - RDIM_SLLQueuePush(list->first, list->last, n); - list->chunk_count += 1; - } - RDIM_LineTable *line_table = &n->v[n->count]; - line_table->chunk = n; - n->count += 1; - list->total_count += 1; - return line_table; -} - -RDI_PROC RDI_U64 -rdim_idx_from_line_table(RDIM_LineTable *line_table) -{ - RDI_U64 idx = 0; - if(line_table != 0 && line_table->chunk != 0) - { - idx = line_table->chunk->base_idx + (line_table - line_table->chunk->v) + 1; - } - return idx; -} - -RDI_PROC void -rdim_line_table_chunk_list_concat_in_place(RDIM_LineTableChunkList *dst, RDIM_LineTableChunkList *to_push) -{ - for(RDIM_LineTableChunkNode *n = to_push->first; n != 0; n = n->next) - { - n->base_idx += dst->total_count; - } - if(dst->last != 0 && to_push->first != 0) - { - dst->last->next = to_push->first; - dst->last = to_push->last; - dst->chunk_count += to_push->chunk_count; - dst->total_count += to_push->total_count; - dst->total_line_count += to_push->total_line_count; - } - else if(dst->first == 0) - { - rdim_memcpy_struct(dst, to_push); - } - rdim_memzero_struct(to_push); -} - -RDI_PROC RDIM_LineSequence * -rdim_line_table_push_sequence(RDIM_Arena *arena, RDIM_LineTableChunkList *line_tables, RDIM_LineTable *line_table, RDIM_SrcFile *src_file, RDI_U64 *voffs, RDI_U32 *line_nums, RDI_U16 *col_nums, RDI_U64 line_count) -{ - RDIM_LineSequenceNode *n = push_array(arena, RDIM_LineSequenceNode, 1); - n->v.src_file = src_file; - n->v.voffs = voffs; - n->v.line_nums = line_nums; - n->v.col_nums = col_nums; - n->v.line_count = line_count; - SLLQueuePush(line_table->first_seq, line_table->last_seq, n); - line_table->seq_count += 1; - line_table->line_count += line_count; - line_table->col_count += line_count*2*(col_nums != 0); - line_tables->total_seq_count += 1; - line_tables->total_line_count += line_count; - line_tables->total_col_count += line_count*2*(col_nums != 0); - return &n->v; -} - -//////////////////////////////// -//~ rjf: [Building] Unit List Building - -RDI_PROC RDIM_Unit * -rdim_unit_chunk_list_push(RDIM_Arena *arena, RDIM_UnitChunkList *list, RDI_U64 cap) -{ - RDIM_UnitChunkNode *n = list->last; - if(n == 0 || n->count >= n->cap) - { - n = rdim_push_array(arena, RDIM_UnitChunkNode, 1); - n->cap = cap; - n->base_idx = list->total_count; - n->v = rdim_push_array(arena, RDIM_Unit, n->cap); - RDIM_SLLQueuePush(list->first, list->last, n); - list->chunk_count += 1; - } - RDIM_Unit *unit = &n->v[n->count]; - unit->chunk = n; - n->count += 1; - list->total_count += 1; - return unit; -} - -RDI_PROC RDI_U64 -rdim_idx_from_unit(RDIM_Unit *unit) -{ - RDI_U64 idx = 0; - if(unit != 0 && unit->chunk != 0) - { - idx = unit->chunk->base_idx + (unit - unit->chunk->v) + 1; - } - return idx; -} - -RDI_PROC void -rdim_unit_chunk_list_concat_in_place(RDIM_UnitChunkList *dst, RDIM_UnitChunkList *to_push) -{ - for(RDIM_UnitChunkNode *n = to_push->first; n != 0; n = n->next) - { - n->base_idx += dst->total_count; - } - if(dst->last != 0 && to_push->first != 0) - { - dst->last->next = to_push->first; - dst->last = to_push->last; - dst->chunk_count += to_push->chunk_count; - dst->total_count += to_push->total_count; - } - else if(dst->first == 0) - { - rdim_memcpy_struct(dst, to_push); - } - rdim_memzero_struct(to_push); -} - -//////////////////////////////// -//~ rjf: [Building] Type Info Building - -RDI_PROC RDIM_Type * -rdim_type_chunk_list_push(RDIM_Arena *arena, RDIM_TypeChunkList *list, RDI_U64 cap) -{ - RDIM_TypeChunkNode *n = list->last; - if(n == 0 || n->count >= n->cap) - { - n = rdim_push_array(arena, RDIM_TypeChunkNode, 1); - n->cap = cap; - n->base_idx = list->total_count; - n->v = rdim_push_array(arena, RDIM_Type, n->cap); - RDIM_SLLQueuePush(list->first, list->last, n); - list->chunk_count += 1; - } - RDIM_Type *result = &n->v[n->count]; - result->chunk = n; - n->count += 1; - list->total_count += 1; - return result; -} - -RDI_PROC RDI_U64 -rdim_idx_from_type(RDIM_Type *type) -{ - RDI_U64 idx = 0; - if(type != 0 && type->chunk != 0) - { - idx = type->chunk->base_idx + (type - type->chunk->v) + 1; - } - return idx; -} - -RDI_PROC void -rdim_type_chunk_list_concat_in_place(RDIM_TypeChunkList *dst, RDIM_TypeChunkList *to_push) -{ - for(RDIM_TypeChunkNode *n = to_push->first; n != 0; n = n->next) - { - n->base_idx += dst->total_count; - } - if(dst->last != 0 && to_push->first != 0) - { - dst->last->next = to_push->first; - dst->last = to_push->last; - dst->chunk_count += to_push->chunk_count; - dst->total_count += to_push->total_count; - } - else if(dst->first == 0) - { - rdim_memcpy_struct(dst, to_push); - } - rdim_memzero_struct(to_push); -} - -RDI_PROC RDIM_UDT * -rdim_udt_chunk_list_push(RDIM_Arena *arena, RDIM_UDTChunkList *list, RDI_U64 cap) -{ - RDIM_UDTChunkNode *n = list->last; - if(n == 0 || n->count >= n->cap) - { - n = rdim_push_array(arena, RDIM_UDTChunkNode, 1); - n->cap = cap; - n->base_idx = list->total_count; - n->v = rdim_push_array(arena, RDIM_UDT, n->cap); - RDIM_SLLQueuePush(list->first, list->last, n); - list->chunk_count += 1; - } - RDIM_UDT *result = &n->v[n->count]; - result->chunk = n; - n->count += 1; - list->total_count += 1; - return result; -} - -RDI_PROC RDI_U64 -rdim_idx_from_udt(RDIM_UDT *udt) -{ - RDI_U64 idx = 0; - if(udt != 0 && udt->chunk != 0) - { - idx = udt->chunk->base_idx + (udt - udt->chunk->v) + 1; - } - return idx; -} - -RDI_PROC void -rdim_udt_chunk_list_concat_in_place(RDIM_UDTChunkList *dst, RDIM_UDTChunkList *to_push) -{ - for(RDIM_UDTChunkNode *n = to_push->first; n != 0; n = n->next) - { - n->base_idx += dst->total_count; - } - if(dst->last != 0 && to_push->first != 0) - { - dst->last->next = to_push->first; - dst->last = to_push->last; - dst->chunk_count += to_push->chunk_count; - dst->total_count += to_push->total_count; - dst->total_member_count += to_push->total_member_count; - dst->total_enum_val_count += to_push->total_enum_val_count; - } - else if(dst->first == 0) - { - rdim_memcpy_struct(dst, to_push); - } - rdim_memzero_struct(to_push); -} - -RDI_PROC RDIM_UDTMember * -rdim_udt_push_member(RDIM_Arena *arena, RDIM_UDTChunkList *list, RDIM_UDT *udt) -{ - RDIM_UDTMember *mem = rdim_push_array(arena, RDIM_UDTMember, 1); - RDIM_SLLQueuePush(udt->first_member, udt->last_member, mem); - udt->member_count += 1; - list->total_member_count += 1; - return mem; -} - -RDI_PROC RDIM_UDTEnumVal * -rdim_udt_push_enum_val(RDIM_Arena *arena, RDIM_UDTChunkList *list, RDIM_UDT *udt) -{ - RDIM_UDTEnumVal *mem = rdim_push_array(arena, RDIM_UDTEnumVal, 1); - RDIM_SLLQueuePush(udt->first_enum_val, udt->last_enum_val, mem); - udt->enum_val_count += 1; - list->total_enum_val_count += 1; - return mem; -} - -//////////////////////////////// -//~ rjf: [Building] Symbol Info Building - -RDI_PROC RDIM_Symbol * -rdim_symbol_chunk_list_push(RDIM_Arena *arena, RDIM_SymbolChunkList *list, RDI_U64 cap) -{ - RDIM_SymbolChunkNode *n = list->last; - if(n == 0 || n->count >= n->cap) - { - n = rdim_push_array(arena, RDIM_SymbolChunkNode, 1); - n->cap = cap; - n->base_idx = list->total_count; - n->v = rdim_push_array(arena, RDIM_Symbol, n->cap); - RDIM_SLLQueuePush(list->first, list->last, n); - list->chunk_count += 1; - } - RDIM_Symbol *result = &n->v[n->count]; - result->chunk = n; - n->count += 1; - list->total_count += 1; - return result; -} - -RDI_PROC RDI_U64 -rdim_idx_from_symbol(RDIM_Symbol *symbol) -{ - RDI_U64 idx = 0; - if(symbol != 0 && symbol->chunk != 0) - { - idx = symbol->chunk->base_idx + (symbol - symbol->chunk->v) + 1; - } - return idx; -} - -RDI_PROC void -rdim_symbol_chunk_list_concat_in_place(RDIM_SymbolChunkList *dst, RDIM_SymbolChunkList *to_push) -{ - for(RDIM_SymbolChunkNode *n = to_push->first; n != 0; n = n->next) - { - n->base_idx += dst->total_count; - } - if(dst->last != 0 && to_push->first != 0) - { - dst->last->next = to_push->first; - dst->last = to_push->last; - dst->chunk_count += to_push->chunk_count; - dst->total_count += to_push->total_count; - } - else if(dst->first == 0) - { - rdim_memcpy_struct(dst, to_push); - } - rdim_memzero_struct(to_push); -} - -//////////////////////////////// -//~ rjf: [Building] Inline Site Info Building - -RDI_PROC RDIM_InlineSite * -rdim_inline_site_chunk_list_push(RDIM_Arena *arena, RDIM_InlineSiteChunkList *list, RDI_U64 cap) -{ - RDIM_InlineSiteChunkNode *n = list->last; - if(n == 0 || n->count >= n->cap) - { - n = rdim_push_array(arena, RDIM_InlineSiteChunkNode, 1); - n->cap = cap; - n->base_idx = list->total_count; - n->v = rdim_push_array(arena, RDIM_InlineSite, n->cap); - RDIM_SLLQueuePush(list->first, list->last, n); - list->chunk_count += 1; - } - RDIM_InlineSite *result = &n->v[n->count]; - result->chunk = n; - n->count += 1; - list->total_count += 1; - return result; -} - -RDI_PROC RDI_U64 -rdim_idx_from_inline_site(RDIM_InlineSite *inline_site) -{ - RDI_U64 idx = 0; - if(inline_site != 0 && inline_site->chunk != 0) - { - idx = inline_site->chunk->base_idx + (inline_site - inline_site->chunk->v) + 1; - } - return idx; -} - -RDI_PROC void -rdim_inline_site_chunk_list_concat_in_place(RDIM_InlineSiteChunkList *dst, RDIM_InlineSiteChunkList *to_push) -{ - for(RDIM_InlineSiteChunkNode *n = to_push->first; n != 0; n = n->next) - { - n->base_idx += dst->total_count; - } - if(dst->last != 0 && to_push->first != 0) - { - dst->last->next = to_push->first; - dst->last = to_push->last; - dst->chunk_count += to_push->chunk_count; - dst->total_count += to_push->total_count; - } - else if(dst->first == 0) - { - rdim_memcpy_struct(dst, to_push); - } - rdim_memzero_struct(to_push); -} - -//////////////////////////////// -//~ rjf: [Building] Scope Info Building - -//- rjf: scopes - -RDI_PROC RDIM_Scope * -rdim_scope_chunk_list_push(RDIM_Arena *arena, RDIM_ScopeChunkList *list, RDI_U64 cap) -{ - RDIM_ScopeChunkNode *n = list->last; - if(n == 0 || n->count >= n->cap) - { - n = rdim_push_array(arena, RDIM_ScopeChunkNode, 1); - n->cap = cap; - n->base_idx = list->total_count; - n->v = rdim_push_array(arena, RDIM_Scope, n->cap); - RDIM_SLLQueuePush(list->first, list->last, n); - list->chunk_count += 1; - } - RDIM_Scope *result = &n->v[n->count]; - result->chunk = n; - n->count += 1; - list->total_count += 1; - return result; -} - -RDI_PROC RDI_U64 -rdim_idx_from_scope(RDIM_Scope *scope) -{ - RDI_U64 idx = 0; - if(scope != 0 && scope->chunk != 0) - { - idx = scope->chunk->base_idx + (scope - scope->chunk->v) + 1; - } - return idx; -} - -RDI_PROC void -rdim_scope_chunk_list_concat_in_place(RDIM_ScopeChunkList *dst, RDIM_ScopeChunkList *to_push) -{ - for(RDIM_ScopeChunkNode *n = to_push->first; n != 0; n = n->next) - { - n->base_idx += dst->total_count; - } - if(dst->last != 0 && to_push->first != 0) - { - dst->last->next = to_push->first; - dst->last = to_push->last; - dst->chunk_count += to_push->chunk_count; - dst->total_count += to_push->total_count; - dst->scope_voff_count += to_push->scope_voff_count; - dst->local_count += to_push->local_count; - dst->location_count += to_push->location_count; - } - else if(dst->first == 0) - { - rdim_memcpy_struct(dst, to_push); - } - rdim_memzero_struct(to_push); -} - -RDI_PROC void -rdim_scope_push_voff_range(RDIM_Arena *arena, RDIM_ScopeChunkList *list, RDIM_Scope *scope, RDIM_Rng1U64 range) -{ - rdim_rng1u64_list_push(arena, &scope->voff_ranges, range); - list->scope_voff_count += 2; -} - -RDI_PROC RDIM_Local * -rdim_scope_push_local(RDIM_Arena *arena, RDIM_ScopeChunkList *scopes, RDIM_Scope *scope) -{ - RDIM_Local *local = rdim_push_array(arena, RDIM_Local, 1); - RDIM_SLLQueuePush(scope->first_local, scope->last_local, local); - scope->local_count += 1; - scopes->local_count += 1; - return local; -} - -//- rjf: bytecode - -RDI_PROC void -rdim_bytecode_push_op(RDIM_Arena *arena, RDIM_EvalBytecode *bytecode, RDI_EvalOp op, RDI_U64 p) -{ - RDI_U8 ctrlbits = rdi_eval_op_ctrlbits_table[op]; - RDI_U32 p_size = RDI_DECODEN_FROM_CTRLBITS(ctrlbits); - - RDIM_EvalBytecodeOp *node = rdim_push_array(arena, RDIM_EvalBytecodeOp, 1); - node->op = op; - node->p_size = p_size; - node->p = p; - - RDIM_SLLQueuePush(bytecode->first_op, bytecode->last_op, node); - bytecode->op_count += 1; - bytecode->encoded_size += 1 + p_size; -} - -RDI_PROC void -rdim_bytecode_push_uconst(RDIM_Arena *arena, RDIM_EvalBytecode *bytecode, RDI_U64 x) -{ - if(x <= 0xFF) - { - rdim_bytecode_push_op(arena, bytecode, RDI_EvalOp_ConstU8, x); - } - else if(x <= 0xFFFF) - { - rdim_bytecode_push_op(arena, bytecode, RDI_EvalOp_ConstU16, x); - } - else if(x <= 0xFFFFFFFF) - { - rdim_bytecode_push_op(arena, bytecode, RDI_EvalOp_ConstU32, x); - } - else - { - rdim_bytecode_push_op(arena, bytecode, RDI_EvalOp_ConstU64, x); - } -} - -RDI_PROC void -rdim_bytecode_push_sconst(RDIM_Arena *arena, RDIM_EvalBytecode *bytecode, RDI_S64 x) -{ - if(-0x80 <= x && x <= 0x7F) - { - rdim_bytecode_push_op(arena, bytecode, RDI_EvalOp_ConstU8, (RDI_U64)x); - rdim_bytecode_push_op(arena, bytecode, RDI_EvalOp_TruncSigned, 8); - } - else if(-0x8000 <= x && x <= 0x7FFF) - { - rdim_bytecode_push_op(arena, bytecode, RDI_EvalOp_ConstU16, (RDI_U64)x); - rdim_bytecode_push_op(arena, bytecode, RDI_EvalOp_TruncSigned, 16); - } - else if(-0x80000000ll <= x && x <= 0x7FFFFFFFll) - { - rdim_bytecode_push_op(arena, bytecode, RDI_EvalOp_ConstU32, (RDI_U64)x); - rdim_bytecode_push_op(arena, bytecode, RDI_EvalOp_TruncSigned, 32); - } - else - { - rdim_bytecode_push_op(arena, bytecode, RDI_EvalOp_ConstU64, (RDI_U64)x); - } -} - -RDI_PROC void -rdim_bytecode_concat_in_place(RDIM_EvalBytecode *left_dst, RDIM_EvalBytecode *right_destroyed) -{ - if(right_destroyed->first_op != 0) - { - if(left_dst->first_op == 0) - { - rdim_memcpy_struct(left_dst, right_destroyed); - } - else - { - left_dst->last_op = right_destroyed->last_op; - left_dst->op_count += right_destroyed->op_count; - left_dst->encoded_size += right_destroyed->encoded_size; - } - rdim_memzero_struct(right_destroyed); - } -} - -//- rjf: individual locations - -RDI_PROC RDIM_Location * -rdim_push_location_addr_bytecode_stream(RDIM_Arena *arena, RDIM_EvalBytecode *bytecode) -{ - RDIM_Location *result = rdim_push_array(arena, RDIM_Location, 1); - result->kind = RDI_LocationKind_AddrBytecodeStream; - result->bytecode = *bytecode; - return result; -} - -RDI_PROC RDIM_Location * -rdim_push_location_val_bytecode_stream(RDIM_Arena *arena, RDIM_EvalBytecode *bytecode) -{ - RDIM_Location *result = rdim_push_array(arena, RDIM_Location, 1); - result->kind = RDI_LocationKind_ValBytecodeStream; - result->bytecode = *bytecode; - return result; -} - -RDI_PROC RDIM_Location * -rdim_push_location_addr_reg_plus_u16(RDIM_Arena *arena, RDI_U8 reg_code, RDI_U16 offset) -{ - RDIM_Location *result = rdim_push_array(arena, RDIM_Location, 1); - result->kind = RDI_LocationKind_AddrRegPlusU16; - result->reg_code = reg_code; - result->offset = offset; - return result; -} - -RDI_PROC RDIM_Location * -rdim_push_location_addr_addr_reg_plus_u16(RDIM_Arena *arena, RDI_U8 reg_code, RDI_U16 offset) -{ - RDIM_Location *result = rdim_push_array(arena, RDIM_Location, 1); - result->kind = RDI_LocationKind_AddrAddrRegPlusU16; - result->reg_code = reg_code; - result->offset = offset; - return result; -} - -RDI_PROC RDIM_Location * -rdim_push_location_val_reg(RDIM_Arena *arena, RDI_U8 reg_code) -{ - RDIM_Location *result = rdim_push_array(arena, RDIM_Location, 1); - result->kind = RDI_LocationKind_ValReg; - result->reg_code = reg_code; - return result; -} - -//- rjf: location sets - -RDI_PROC void -rdim_location_set_push_case(RDIM_Arena *arena, RDIM_ScopeChunkList *scopes, RDIM_LocationSet *locset, RDIM_Rng1U64 voff_range, RDIM_Location *location) -{ - RDIM_LocationCase *location_case = rdim_push_array(arena, RDIM_LocationCase, 1); - SLLQueuePush(locset->first_location_case, locset->last_location_case, location_case); - locset->location_case_count += 1; - location_case->voff_range = voff_range; - location_case->location = location; - scopes->location_count +=1; -} - -//////////////////////////////// -//~ rjf: [Baking Helpers] Baked VMap Building - -RDI_PROC RDIM_BakeVMap -rdim_bake_vmap_from_markers(RDIM_Arena *arena, RDIM_VMapMarker *markers, RDIM_SortKey *keys, RDI_U64 marker_count) -{ - RDIM_Temp scratch = rdim_scratch_begin(&arena, 1); - - //- rjf: sort markers - RDIM_SortKey *sorted_keys = rdim_sort_key_array(scratch.arena, keys, marker_count); - - //- rjf: determine if an extra vmap entry for zero is needed - RDI_U32 extra_vmap_entry = 0; - if(marker_count > 0 && sorted_keys[0].key != 0) - { - extra_vmap_entry = 1; - } - - //- rjf: fill output vmap entries - RDI_U32 vmap_count_raw = marker_count - 1 + extra_vmap_entry; - RDI_VMapEntry *vmap = rdim_push_array_no_zero(arena, RDI_VMapEntry, vmap_count_raw + 1); - RDI_U32 vmap_entry_count_pass_1 = 0; - { - typedef struct RDIM_VMapRangeTracker RDIM_VMapRangeTracker; - struct RDIM_VMapRangeTracker - { - RDIM_VMapRangeTracker *next; - RDI_U32 idx; - }; - RDI_VMapEntry *vmap_ptr = vmap; - if(extra_vmap_entry) - { - vmap_ptr->voff = 0; - vmap_ptr->idx = 0; - vmap_ptr += 1; - } - RDIM_VMapRangeTracker *tracker_stack = 0; - RDIM_VMapRangeTracker *tracker_free = 0; - RDIM_SortKey *key_ptr = sorted_keys; - RDIM_SortKey *key_opl = sorted_keys + marker_count; - for(;key_ptr < key_opl;) - { - // rjf: get initial map state from tracker stack - RDI_U32 initial_idx = (RDI_U32)0xffffffff; - if(tracker_stack != 0) - { - initial_idx = tracker_stack->idx; - } - - // rjf: update tracker stack - // - // * we must process _all_ of the changes that apply at this voff before moving on - // - RDI_U64 voff = key_ptr->key; - - for(;key_ptr < key_opl && key_ptr->key == voff; key_ptr += 1) - { - RDIM_VMapMarker *marker = (RDIM_VMapMarker*)key_ptr->val; - RDI_U32 idx = marker->idx; - - // rjf: range begin -> push to stack - if(marker->begin_range) - { - RDIM_VMapRangeTracker *new_tracker = tracker_free; - if(new_tracker != 0) - { - RDIM_SLLStackPop(tracker_free); - } - else - { - new_tracker = rdim_push_array(scratch.arena, RDIM_VMapRangeTracker, 1); - } - RDIM_SLLStackPush(tracker_stack, new_tracker); - new_tracker->idx = idx; - } - - // rjf: range ending -> pop matching node from stack (not always the top) - else - { - RDIM_VMapRangeTracker **ptr_in = &tracker_stack; - RDIM_VMapRangeTracker *match = 0; - for(RDIM_VMapRangeTracker *node = tracker_stack; node != 0;) - { - if(node->idx == idx) - { - match = node; - break; - } - ptr_in = &node->next; - node = node->next; - } - if(match != 0) - { - *ptr_in = match->next; - RDIM_SLLStackPush(tracker_free, match); - } - } - } - - // rjf: get final map state from tracker stack - RDI_U32 final_idx = 0; - if(tracker_stack != 0) - { - final_idx = tracker_stack->idx; - } - - // rjf: if final is different from initial - emit new vmap entry - if(final_idx != initial_idx) - { - vmap_ptr->voff = voff; - vmap_ptr->idx = final_idx; - vmap_ptr += 1; - } - } - - vmap_entry_count_pass_1 = (RDI_U32)(vmap_ptr - vmap); // TODO(rjf): @u64_to_u32 - } - - //- rjf: combine duplicate neighbors - RDI_U32 vmap_entry_count = 0; - { - RDI_VMapEntry *vmap_ptr = vmap; - RDI_VMapEntry *vmap_opl = vmap + vmap_entry_count_pass_1; - RDI_VMapEntry *vmap_out = vmap; - for(;vmap_ptr < vmap_opl;) - { - RDI_VMapEntry *vmap_range_first = vmap_ptr; - RDI_U64 idx = vmap_ptr->idx; - vmap_ptr += 1; - for(;vmap_ptr < vmap_opl && vmap_ptr->idx == idx;) vmap_ptr += 1; - rdim_memcpy_struct(vmap_out, vmap_range_first); - vmap_out += 1; - } - vmap_entry_count = (RDI_U32)(vmap_out - vmap); // TODO(rjf): @u64_to_u32 - } - - //- rjf: fill result - RDIM_BakeVMap result = {0}; - result.vmap = vmap; - result.count = vmap_entry_count-1; - rdim_scratch_end(scratch); - return result; -} - -//////////////////////////////// -//~ rjf: [Baking Helpers] Interned / Deduplicated Blob Data Structure Helpers - -//- rjf: bake string chunk lists - -RDI_PROC RDIM_BakeString * -rdim_bake_string_chunk_list_push(RDIM_Arena *arena, RDIM_BakeStringChunkList *list, RDI_U64 cap) -{ - RDIM_BakeStringChunkNode *n = list->last; - if(n == 0 || n->count >= n->cap) - { - n = rdim_push_array(arena, RDIM_BakeStringChunkNode, 1); - n->cap = cap; - n->v = rdim_push_array(arena, RDIM_BakeString, n->cap); - RDIM_SLLQueuePush(list->first, list->last, n); - list->chunk_count += 1; - } - RDIM_BakeString *s = &n->v[n->count]; - n->count += 1; - list->total_count += 1; - return s; -} - -RDI_PROC void -rdim_bake_string_chunk_list_concat_in_place(RDIM_BakeStringChunkList *dst, RDIM_BakeStringChunkList *to_push) -{ - for(RDIM_BakeStringChunkNode *n = to_push->first; n != 0; n = n->next) - { - n->base_idx += dst->total_count; - } - if(dst->last != 0 && to_push->first != 0) - { - dst->last->next = to_push->first; - dst->last = to_push->last; - dst->chunk_count += to_push->chunk_count; - dst->total_count += to_push->total_count; - } - else if(dst->first == 0) - { - rdim_memcpy_struct(dst, to_push); - } - rdim_memzero_struct(to_push); -} - -RDI_PROC RDIM_BakeStringChunkList -rdim_bake_string_chunk_list_sorted_from_unsorted(RDIM_Arena *arena, RDIM_BakeStringChunkList *src) -{ - //- rjf: produce unsorted destination list with single chunk node - RDIM_BakeStringChunkList dst = {0}; - for(RDIM_BakeStringChunkNode *n = src->first; n != 0; n = n->next) - { - for(RDI_U64 idx = 0; idx < n->count; idx += 1) - { - RDIM_BakeString *src_str = &n->v[idx]; - RDIM_BakeString *dst_str = rdim_bake_string_chunk_list_push(arena, &dst, src->total_count); - rdim_memcpy_struct(dst_str, src_str); - } - } - - //- rjf: sort chunk node - if(dst.first != 0) - { - RDIM_Temp scratch = rdim_scratch_begin(&arena, 1); - typedef struct SortTask SortTask; - struct SortTask - { - SortTask *next; - RDI_U64 string_off; - RDIM_BakeString *v; - RDI_U64 count; - }; - SortTask start_task = {0, 0, dst.first->v, dst.first->count}; - SortTask *first_task = &start_task; - SortTask *last_task = &start_task; - - //- rjf: for each sort task range: - for(SortTask *t = first_task; t != 0; t = t->next) - { - //- rjf: loop through range, drop each element into bucket according to byte in string at task offset - RDIM_BakeStringChunkList *buckets = rdim_push_array(scratch.arena, RDIM_BakeStringChunkList, 256); - for(RDI_U64 idx = 0; idx < t->count; idx += 1) - { - U8 byte = t->string_off < t->v[idx].string.size ? t->v[idx].string.str[t->string_off] : 0; - RDIM_BakeStringChunkList *bucket = &buckets[byte]; - RDIM_BakeString *bstr = rdim_bake_string_chunk_list_push(scratch.arena, bucket, 8); - rdim_memcpy_struct(bstr, &t->v[idx]); - } - - //- rjf: in-place mutate the original source array to reflect the order per the buckets. - // build new sort tasks for buckets with many elements - { - RDI_U64 write_idx = 0; - for(U64 bucket_idx = 0; bucket_idx < 256; bucket_idx += 1) - { - // rjf: write each chunk node's array into original array, detect if there is size left to sort - RDI_U64 bucket_base_idx = write_idx; - RDI_U64 max_size_left_to_sort = 0; - for(RDIM_BakeStringChunkNode *n = buckets[bucket_idx].first; n != 0; n = n->next) - { - rdim_memcpy(t->v+write_idx, n->v, sizeof(n->v[0])*n->count); - write_idx += n->count; - for(RDI_U64 idx = 0; idx < n->count; idx += 1) - { - if(n->v[idx].string.size > t->string_off+1) - { - max_size_left_to_sort = Max(max_size_left_to_sort, (n->v[idx].string.size - t->string_off+1)); - } - } - } - - // rjf: if any bucket has >1 element & has some amount of size left to sort, push new task for this - // bucket's region in the array, and for remainder of keys - if(buckets[bucket_idx].total_count > 1 && max_size_left_to_sort > 0) - { - SortTask *new_task = rdim_push_array(scratch.arena, SortTask, 1); - RDIM_SLLQueuePush(first_task, last_task, new_task); - new_task->string_off = t->string_off+1; - new_task->v = t->v + bucket_base_idx; - new_task->count = write_idx-bucket_base_idx; - } - } - } - } - scratch_end(scratch); - } - - return dst; -} - -//- rjf: bake string chunk list maps - -RDI_PROC RDIM_BakeStringMapLoose * -rdim_bake_string_map_loose_make(RDIM_Arena *arena, RDIM_BakeStringMapTopology *top) -{ - RDIM_BakeStringMapLoose *map = rdim_push_array(arena, RDIM_BakeStringMapLoose, 1); - map->slots = rdim_push_array(arena, RDIM_BakeStringChunkList *, top->slots_count); - return map; -} - -RDI_PROC void -rdim_bake_string_map_loose_insert(RDIM_Arena *arena, RDIM_BakeStringMapTopology *map_topology, RDIM_BakeStringMapLoose *map, RDI_U64 chunk_cap, RDIM_String8 string) -{ - RDI_U64 hash = rdi_hash(string.RDIM_String8_BaseMember, string.RDIM_String8_SizeMember); - RDI_U64 slot_idx = hash%map_topology->slots_count; - RDIM_BakeStringChunkList *slot = map->slots[slot_idx]; - if(slot == 0) - { - slot = map->slots[slot_idx] = rdim_push_array(arena, RDIM_BakeStringChunkList, 1); - } - RDI_S32 is_duplicate = 0; - for(RDIM_BakeStringChunkNode *n = slot->first; n != 0; n = n->next) - { - for(RDI_U64 idx = 0; idx < n->count; idx += 1) - { - if(rdim_str8_match(n->v[idx].string, string, 0)) - { - is_duplicate = 1; - goto break_all; - } - } - } - break_all:; - if(!is_duplicate) - { - RDIM_BakeString *bstr = rdim_bake_string_chunk_list_push(arena, slot, chunk_cap); - bstr->string = string; - bstr->hash = hash; - } -} - -RDI_PROC void -rdim_bake_string_map_loose_join_in_place(RDIM_BakeStringMapTopology *map_topology, RDIM_BakeStringMapLoose *dst, RDIM_BakeStringMapLoose *src) -{ - for(RDI_U64 idx = 0; idx < map_topology->slots_count; idx += 1) - { - if(dst->slots[idx] == 0) - { - dst->slots[idx] = src->slots[idx]; - } - else if(src->slots[idx] != 0) - { - rdim_bake_string_chunk_list_concat_in_place(dst->slots[idx], src->slots[idx]); - } - } - rdim_memzero_struct(src); -} - -RDI_PROC RDIM_BakeStringMapBaseIndices -rdim_bake_string_map_base_indices_from_map_loose(RDIM_Arena *arena, RDIM_BakeStringMapTopology *map_topology, RDIM_BakeStringMapLoose *map) -{ - RDIM_BakeStringMapBaseIndices indices = {0}; - indices.slots_base_idxs = rdim_push_array(arena, RDI_U64, map_topology->slots_count+1); - RDI_U64 total_count = 0; - for(RDI_U64 idx = 0; idx < map_topology->slots_count; idx += 1) - { - indices.slots_base_idxs[idx] += total_count; - if(map->slots[idx] != 0) - { - total_count += map->slots[idx]->total_count; - } - } - indices.slots_base_idxs[map_topology->slots_count] = total_count; - return indices; -} - -//- rjf: finalized bake string map - -RDI_PROC RDIM_BakeStringMapTight -rdim_bake_string_map_tight_from_loose(RDIM_Arena *arena, RDIM_BakeStringMapTopology *map_topology, RDIM_BakeStringMapBaseIndices *map_base_indices, RDIM_BakeStringMapLoose *map) -{ - RDIM_BakeStringMapTight m = {0}; - m.slots_count = map_topology->slots_count; - m.slots = rdim_push_array(arena, RDIM_BakeStringChunkList, m.slots_count); - m.slots_base_idxs = map_base_indices->slots_base_idxs; - for(RDI_U64 idx = 0; idx < m.slots_count; idx += 1) - { - if(map->slots[idx] != 0) - { - rdim_memcpy_struct(&m.slots[idx], map->slots[idx]); - } - } - m.total_count = m.slots_base_idxs[m.slots_count]; - return m; -} - -RDI_PROC RDI_U32 -rdim_bake_idx_from_string(RDIM_BakeStringMapTight *map, RDIM_String8 string) -{ - RDI_U32 idx = 0; - if(string.RDIM_String8_SizeMember != 0) - { - RDI_U64 hash = rdi_hash(string.RDIM_String8_BaseMember, string.RDIM_String8_SizeMember); - RDI_U64 slot_idx = hash%map->slots_count; - for(RDIM_BakeStringChunkNode *n = map->slots[slot_idx].first; n != 0; n = n->next) - { - for(RDI_U64 chunk_idx = 0; chunk_idx < n->count; chunk_idx += 1) - { - if(n->v[chunk_idx].hash == hash && rdim_str8_match(n->v[chunk_idx].string, string, 0)) - { - idx = map->slots_base_idxs[slot_idx] + n->base_idx + chunk_idx + 1; - break; - } - } - } - } - return idx; -} - -//- rjf: bake idx run map reading/writing - -RDI_PROC RDI_U64 -rdim_hash_from_idx_run(RDI_U32 *idx_run, RDI_U32 count) -{ - RDI_U64 hash = 5381; - RDI_U32 *ptr = idx_run; - RDI_U32 *opl = idx_run + count; - for(;ptr < opl; ptr += 1) - { - hash = ((hash << 5) + hash) + (*ptr); - } - return hash; -} - -RDI_PROC RDI_U32 -rdim_bake_idx_from_idx_run(RDIM_BakeIdxRunMap *map, RDI_U32 *idx_run, RDI_U32 count) -{ - RDI_U64 hash = rdim_hash_from_idx_run(idx_run, count); - RDI_U64 slot_idx = hash%map->slots_count; - - // rjf: find existing node - RDIM_BakeIdxRunNode *node = 0; - for(RDIM_BakeIdxRunNode *n = map->slots[slot_idx]; n != 0; n = n->hash_next) - { - if(n->hash == hash) - { - RDI_S32 is_match = 1; - RDI_U32 *n_idx = n->idx_run; - for(RDI_U32 i = 0; i < count; i += 1) - { - if(n_idx[i] != idx_run[i]) - { - is_match = 0; - break; - } - } - if(is_match) - { - node = n; - break; - } - } - } - - // rjf: node -> index - RDI_U32 result = node ? node->first_idx : 0; - return result; -} - -RDI_PROC RDI_U32 -rdim_bake_idx_run_map_insert(RDIM_Arena *arena, RDIM_BakeIdxRunMap *map, RDI_U32 *idx_run, RDI_U32 count) -{ - RDI_U64 hash = rdim_hash_from_idx_run(idx_run, count); - RDI_U64 slot_idx = hash%map->slots_count; - - // rjf: find existing node - RDIM_BakeIdxRunNode *node = 0; - for(RDIM_BakeIdxRunNode *n = map->slots[slot_idx]; n != 0; n = n->hash_next) - { - if(n->hash == hash) - { - RDI_S32 is_match = 1; - RDI_U32 *n_idx = n->idx_run; - for(RDI_U32 i = 0; i < count; i += 1) - { - if(n_idx[i] != idx_run[i]) - { - is_match = 0; - break; - } - } - if(is_match) - { - node = n; - break; - } - } - } - - // rjf: no node -> make new node - if(node == 0) - { - node = rdim_push_array_no_zero(arena, RDIM_BakeIdxRunNode, 1); - RDI_U32 *idx_run_copy = rdim_push_array_no_zero(arena, RDI_U32, count); - for(RDI_U32 i = 0; i < count; i += 1) - { - idx_run_copy[i] = idx_run[i]; - } - node->idx_run = idx_run_copy; - node->hash = hash; - node->count = count; - node->first_idx = map->idx_count; - map->count += 1; - map->idx_count += count; - RDIM_SLLQueuePush_N(map->order_first, map->order_last, node, order_next); - RDIM_SLLStackPush_N(map->slots[slot_idx], node, hash_next); - map->slot_collision_count += (node->hash_next != 0); - } - - // rjf: node -> index - RDI_U32 result = node->first_idx; - return result; -} - -//- rjf: bake path tree reading/writing - -RDI_PROC RDIM_BakePathNode * -rdim_bake_path_node_from_string(RDIM_BakePathTree *tree, RDIM_String8 string) -{ - RDIM_BakePathNode *node = &tree->root; - RDI_U8 *ptr = string.str; - RDI_U8 *opl = string.str + string.size; - for(;ptr < opl && node != 0;) - { - // rjf: skip past slashes - for(;ptr < opl && (*ptr == '/' || *ptr == '\\'); ptr += 1); - - // rjf: save beginning of non-slash range - RDI_U8 *range_first = ptr; - - // rjf: skip past non-slashes - for(;ptr < opl && !(*ptr == '/' || *ptr == '\\'); ptr += 1); - - // rjf: empty range -> continue - if(range_first >= ptr) - { - continue; - } - - // rjf: range -> sub-directory string - RDIM_String8 sub_dir = rdim_str8(range_first, (RDI_U64)(ptr-range_first)); - - // rjf: sub-directory string -> find child of node - RDIM_BakePathNode *sub_dir_node = 0; - for(RDIM_BakePathNode *child = node->first_child; child != 0; child = child->next_sibling) - { - if(rdim_str8_match(child->name, sub_dir, RDIM_StringMatchFlag_CaseInsensitive)) - { - sub_dir_node = child; - } - } - - // rjf: descend to child - node = sub_dir_node; - } - return node; -} - -RDI_PROC RDI_U32 -rdim_bake_path_node_idx_from_string(RDIM_BakePathTree *tree, RDIM_String8 string) -{ - RDIM_BakePathNode *path_node = rdim_bake_path_node_from_string(tree, string); - RDI_U32 result = 0; - if(path_node != 0) - { - result = path_node->idx; - } - return result; -} - -RDI_PROC RDIM_BakePathNode * -rdim_bake_path_tree_insert(RDIM_Arena *arena, RDIM_BakePathTree *tree, RDIM_String8 string) -{ - RDIM_BakePathNode *node = &tree->root; - RDI_U8 *ptr = string.str; - RDI_U8 *opl = string.str + string.size; - for(;ptr < opl;) - { - // rjf: skip past slashes - for(;ptr < opl && (*ptr == '/' || *ptr == '\\'); ptr += 1); - - // rjf: save beginning of non-slash range - RDI_U8 *range_first = ptr; - - // rjf: skip past non-slashes - for(;ptr < opl && !(*ptr == '/' || *ptr == '\\'); ptr += 1); - - // rjf: empty range -> continue - if(range_first >= ptr) - { - continue; - } - - // rjf: range -> sub-directory string - RDIM_String8 sub_dir = rdim_str8(range_first, (RDI_U64)(ptr-range_first)); - - // rjf: sub-directory string -> find child of node - RDIM_BakePathNode *sub_dir_node = 0; - for(RDIM_BakePathNode *child = node->first_child; child != 0; child = child->next_sibling) - { - if(rdim_str8_match(child->name, sub_dir, RDIM_StringMatchFlag_CaseInsensitive)) - { - sub_dir_node = child; - } - } - - // rjf: no child -> make one - if(sub_dir_node == 0) - { - sub_dir_node = rdim_push_array(arena, RDIM_BakePathNode, 1); - RDIM_SLLQueuePush_N(tree->first, tree->last, sub_dir_node, next_order); - sub_dir_node->parent = node; - RDIM_SLLQueuePush_N(node->first_child, node->last_child, sub_dir_node, next_sibling); - sub_dir_node->name = rdim_str8_copy(arena, sub_dir); - sub_dir_node->idx = tree->count; - tree->count += 1; - } - - // rjf: descend to child - node = sub_dir_node; - } - return node; -} - -//- rjf: bake name maps writing - -RDI_PROC void -rdim_bake_name_map_push(RDIM_Arena *arena, RDIM_BakeNameMap *map, RDIM_String8 string, RDI_U32 idx) -{ - if(string.size == 0) {return;} - - // rjf: hash - RDI_U64 hash = rdi_hash(string.RDIM_String8_BaseMember, string.RDIM_String8_SizeMember); - RDI_U64 slot_idx = hash%map->slots_count; - - // rjf: find existing node - RDIM_BakeNameMapNode *node = 0; - for(RDIM_BakeNameMapNode *n = map->slots[slot_idx]; n != 0; n = n->slot_next) - { - if(rdim_str8_match(string, n->string, 0)) - { - node = n; - break; - } - } - - // rjf: make node if necessary - if(node == 0) - { - node = rdim_push_array(arena, RDIM_BakeNameMapNode, 1); - node->string = string; - RDIM_SLLStackPush_N(map->slots[slot_idx], node, slot_next); - RDIM_SLLQueuePush_N(map->first, map->last, node, order_next); - map->name_count += 1; - map->slot_collision_count += (node->slot_next != 0); - } - - // rjf: find existing idx - RDI_S32 existing_idx = 0; - for(RDIM_BakeNameMapValNode *n = node->val_first; n != 0; n = n->next) - { - for(RDI_U32 i = 0; i < sizeof(n->val)/sizeof(n->val[0]); i += 1) - { - if(n->val[i] == 0) - { - break; - } - if(n->val[i] == idx) - { - existing_idx = 1; - break; - } - } - } - - // rjf: insert new idx if necessary - if(!existing_idx) - { - RDIM_BakeNameMapValNode *val_node = node->val_last; - RDI_U32 insert_i = node->val_count%(sizeof(val_node->val)/sizeof(val_node->val[0])); - if(insert_i == 0) - { - val_node = rdim_push_array(arena, RDIM_BakeNameMapValNode, 1); - SLLQueuePush(node->val_first, node->val_last, val_node); - } - val_node->val[insert_i] = idx; - node->val_count += 1; - } -} - -//////////////////////////////// -//~ rjf: [Baking Helpers] Data Section List Building Helpers - -RDI_PROC RDIM_BakeSection * -rdim_bake_section_list_push(RDIM_Arena *arena, RDIM_BakeSectionList *list) -{ - RDIM_BakeSectionNode *n = rdim_push_array(arena, RDIM_BakeSectionNode, 1); - RDIM_SLLQueuePush(list->first, list->last, n); - list->count += 1; - RDIM_BakeSection *result = &n->v; - return result; -} - -RDI_PROC RDIM_BakeSection * -rdim_bake_section_list_push_new_unpacked(RDIM_Arena *arena, RDIM_BakeSectionList *list, void *data, RDI_U64 size, RDI_SectionKind tag, RDI_U64 tag_idx) -{ - RDIM_BakeSection *section = rdim_bake_section_list_push(arena, list); - section->data = data; - section->encoding = RDI_SectionEncoding_Unpacked; - section->encoded_size = size; - section->unpacked_size = size; - section->tag = tag; - section->tag_idx = tag_idx; - return section; -} - -RDI_PROC void -rdim_bake_section_list_concat_in_place(RDIM_BakeSectionList *dst, RDIM_BakeSectionList *to_push) -{ - if(dst->last != 0 && to_push->first != 0) - { - dst->last->next = to_push->first; - dst->last = to_push->last; - dst->count += to_push->count; - } - else if(to_push->first != 0) - { - rdim_memcpy_struct(dst, to_push); - } - rdim_memzero_struct(to_push); -} - -//////////////////////////////// -//~ rjf: [Baking] Build Artifacts -> Interned/Deduplicated Data Structures - -//- rjf: basic bake string gathering passes - -RDI_PROC void -rdim_bake_string_map_loose_push_top_level_info(RDIM_Arena *arena, RDIM_BakeStringMapTopology *top, RDIM_BakeStringMapLoose *map, RDIM_TopLevelInfo *tli) -{ - rdim_bake_string_map_loose_insert(arena, top, map, 1, tli->exe_name); - rdim_bake_string_map_loose_insert(arena, top, map, 1, tli->producer_name); -} - -RDI_PROC void -rdim_bake_string_map_loose_push_binary_sections(RDIM_Arena *arena, RDIM_BakeStringMapTopology *top, RDIM_BakeStringMapLoose *map, RDIM_BinarySectionList *secs) -{ - for(RDIM_BinarySectionNode *n = secs->first; n != 0; n = n->next) - { - rdim_bake_string_map_loose_insert(arena, top, map, 1, n->v.name); - } -} - -RDI_PROC void -rdim_bake_string_map_loose_push_path_tree(RDIM_Arena *arena, RDIM_BakeStringMapTopology *top, RDIM_BakeStringMapLoose *map, RDIM_BakePathTree *path_tree) -{ - for(RDIM_BakePathNode *n = path_tree->first; n != 0; n = n->next_order) - { - rdim_bake_string_map_loose_insert(arena, top, map, 1, n->name); - } -} - -//- rjf: chunk-granularity bake string gathering passes - -RDI_PROC void -rdim_bake_string_map_loose_push_src_file_slice(RDIM_Arena *arena, RDIM_BakeStringMapTopology *top, RDIM_BakeStringMapLoose *map, RDIM_SrcFile *v, RDI_U64 count) -{ - for(RDI_U64 idx = 0; idx < count; idx += 1) - { - rdim_bake_string_map_loose_insert(arena, top, map, 1, v[idx].normal_full_path); - } -} - -RDI_PROC void -rdim_bake_string_map_loose_push_unit_slice(RDIM_Arena *arena, RDIM_BakeStringMapTopology *top, RDIM_BakeStringMapLoose *map, RDIM_Unit *v, RDI_U64 count) -{ - for(RDI_U64 idx = 0; idx < count; idx += 1) - { - rdim_bake_string_map_loose_insert(arena, top, map, 4, v[idx].unit_name); - rdim_bake_string_map_loose_insert(arena, top, map, 4, v[idx].compiler_name); - rdim_bake_string_map_loose_insert(arena, top, map, 4, v[idx].source_file); - rdim_bake_string_map_loose_insert(arena, top, map, 4, v[idx].object_file); - rdim_bake_string_map_loose_insert(arena, top, map, 4, v[idx].archive_file); - rdim_bake_string_map_loose_insert(arena, top, map, 4, v[idx].build_path); - } -} - -RDI_PROC void -rdim_bake_string_map_loose_push_type_slice(RDIM_Arena *arena, RDIM_BakeStringMapTopology *top, RDIM_BakeStringMapLoose *map, RDIM_Type *v, RDI_U64 count) -{ - for(RDI_U64 idx = 0; idx < count; idx += 1) - { - rdim_bake_string_map_loose_insert(arena, top, map, 4, v[idx].name); - } -} - -RDI_PROC void -rdim_bake_string_map_loose_push_udt_slice(RDIM_Arena *arena, RDIM_BakeStringMapTopology *top, RDIM_BakeStringMapLoose *map, RDIM_UDT *v, RDI_U64 count) -{ - for(RDI_U64 idx = 0; idx < count; idx += 1) - { - for(RDIM_UDTMember *mem = v[idx].first_member; mem != 0; mem = mem->next) - { - rdim_bake_string_map_loose_insert(arena, top, map, 4, mem->name); - } - for(RDIM_UDTEnumVal *mem = v[idx].first_enum_val; mem != 0; mem = mem->next) - { - rdim_bake_string_map_loose_insert(arena, top, map, 4, mem->name); - } - } -} - -RDI_PROC void -rdim_bake_string_map_loose_push_symbol_slice(RDIM_Arena *arena, RDIM_BakeStringMapTopology *top, RDIM_BakeStringMapLoose *map, RDIM_Symbol *v, RDI_U64 count) -{ - for(RDI_U64 idx = 0; idx < count; idx += 1) - { - rdim_bake_string_map_loose_insert(arena, top, map, 4, v[idx].name); - rdim_bake_string_map_loose_insert(arena, top, map, 4, v[idx].link_name); - } -} - -RDI_PROC void -rdim_bake_string_map_loose_push_scope_slice(RDIM_Arena *arena, RDIM_BakeStringMapTopology *top, RDIM_BakeStringMapLoose *map, RDIM_Scope *v, RDI_U64 count) -{ - for(RDI_U64 idx = 0; idx < count; idx += 1) - { - for(RDIM_Local *local = v[idx].first_local; local != 0; local = local->next) - { - rdim_bake_string_map_loose_insert(arena, top, map, 4, local->name); - } - } -} - -//- rjf: list-granularity bake string gathering passes - -RDI_PROC void -rdim_bake_string_map_loose_push_src_files(RDIM_Arena *arena, RDIM_BakeStringMapTopology *top, RDIM_BakeStringMapLoose *map, RDIM_SrcFileChunkList *list) -{ - for(RDIM_SrcFileChunkNode *n = list->first; n != 0; n = n->next) - { - rdim_bake_string_map_loose_push_src_file_slice(arena, top, map, n->v, n->count); - } -} - -RDI_PROC void -rdim_bake_string_map_loose_push_units(RDIM_Arena *arena, RDIM_BakeStringMapTopology *top, RDIM_BakeStringMapLoose *map, RDIM_UnitChunkList *list) -{ - for(RDIM_UnitChunkNode *n = list->first; n != 0; n = n->next) - { - rdim_bake_string_map_loose_push_unit_slice(arena, top, map, n->v, n->count); - } -} - -RDI_PROC void -rdim_bake_string_map_loose_push_types(RDIM_Arena *arena, RDIM_BakeStringMapTopology *top, RDIM_BakeStringMapLoose *map, RDIM_TypeChunkList *list) -{ - for(RDIM_TypeChunkNode *n = list->first; n != 0; n = n->next) - { - rdim_bake_string_map_loose_push_type_slice(arena, top, map, n->v, n->count); - } -} - -RDI_PROC void -rdim_bake_string_map_loose_push_udts(RDIM_Arena *arena, RDIM_BakeStringMapTopology *top, RDIM_BakeStringMapLoose *map, RDIM_UDTChunkList *list) -{ - for(RDIM_UDTChunkNode *n = list->first; n != 0; n = n->next) - { - rdim_bake_string_map_loose_push_udt_slice(arena, top, map, n->v, n->count); - } -} - -RDI_PROC void -rdim_bake_string_map_loose_push_symbols(RDIM_Arena *arena, RDIM_BakeStringMapTopology *top, RDIM_BakeStringMapLoose *map, RDIM_SymbolChunkList *list) -{ - for(RDIM_SymbolChunkNode *n = list->first; n != 0; n = n->next) - { - rdim_bake_string_map_loose_push_symbol_slice(arena, top, map, n->v, n->count); - } -} - -RDI_PROC void -rdim_bake_string_map_loose_push_scopes(RDIM_Arena *arena, RDIM_BakeStringMapTopology *top, RDIM_BakeStringMapLoose *map, RDIM_ScopeChunkList *list) -{ - for(RDIM_ScopeChunkNode *n = list->first; n != 0; n = n->next) - { - rdim_bake_string_map_loose_push_scope_slice(arena, top, map, n->v, n->count); - } -} - -//- rjf: bake name map building - -RDI_PROC RDIM_BakeNameMap * -rdim_bake_name_map_from_kind_params(RDIM_Arena *arena, RDI_NameMapKind kind, RDIM_BakeParams *params) -{ - RDIM_BakeNameMap *map = rdim_push_array(arena, RDIM_BakeNameMap, 1); - switch(kind) - { - default:{}break; - case RDI_NameMapKind_GlobalVariables: - { - map->slots_count = params->global_variables.total_count*2; - map->slots = rdim_push_array(arena, RDIM_BakeNameMapNode *, map->slots_count); - for(RDIM_SymbolChunkNode *n = params->global_variables.first; n != 0; n = n->next) - { - for(RDI_U64 idx = 0; idx < n->count; idx += 1) - { - RDI_U32 symbol_idx = (RDI_U32)rdim_idx_from_symbol(&n->v[idx]); // TODO(rjf): @u64_to_u32 - rdim_bake_name_map_push(arena, map, n->v[idx].name, symbol_idx); - } - } - }break; - case RDI_NameMapKind_ThreadVariables: - { - map->slots_count = params->thread_variables.total_count*2; - map->slots = rdim_push_array(arena, RDIM_BakeNameMapNode *, map->slots_count); - for(RDIM_SymbolChunkNode *n = params->thread_variables.first; n != 0; n = n->next) - { - for(RDI_U64 idx = 0; idx < n->count; idx += 1) - { - RDI_U32 symbol_idx = (RDI_U32)rdim_idx_from_symbol(&n->v[idx]); // TODO(rjf): @u64_to_u32 - rdim_bake_name_map_push(arena, map, n->v[idx].name, symbol_idx); - } - } - }break; - case RDI_NameMapKind_Procedures: - { - map->slots_count = params->procedures.total_count*2; - map->slots = rdim_push_array(arena, RDIM_BakeNameMapNode *, map->slots_count); - for(RDIM_SymbolChunkNode *n = params->procedures.first; n != 0; n = n->next) - { - for(RDI_U64 idx = 0; idx < n->count; idx += 1) - { - RDI_U32 symbol_idx = (RDI_U32)rdim_idx_from_symbol(&n->v[idx]); // TODO(rjf): @u64_to_u32 - rdim_bake_name_map_push(arena, map, n->v[idx].name, symbol_idx); - } - } - }break; - case RDI_NameMapKind_Types: - { - map->slots_count = params->types.total_count; - map->slots = rdim_push_array(arena, RDIM_BakeNameMapNode *, map->slots_count); - for(RDIM_TypeChunkNode *n = params->types.first; n != 0; n = n->next) - { - for(RDI_U64 idx = 0; idx < n->count; idx += 1) - { - RDI_U32 type_idx = (RDI_U32)rdim_idx_from_type(&n->v[idx]); // TODO(rjf): @u64_to_u32 - rdim_bake_name_map_push(arena, map, n->v[idx].name, type_idx); - } - } - }break; - case RDI_NameMapKind_LinkNameProcedures: - { - map->slots_count = params->procedures.total_count*2; - map->slots = rdim_push_array(arena, RDIM_BakeNameMapNode *, map->slots_count); - for(RDIM_SymbolChunkNode *n = params->procedures.first; n != 0; n = n->next) - { - for(RDI_U64 idx = 0; idx < n->count; idx += 1) - { - if(n->v[idx].link_name.size == 0) {continue;} - RDI_U32 symbol_idx = (RDI_U32)rdim_idx_from_symbol(&n->v[idx]); // TODO(rjf): @u64_to_u32 - rdim_bake_name_map_push(arena, map, n->v[idx].link_name, symbol_idx); - } - } - }break; - case RDI_NameMapKind_NormalSourcePaths: - { - map->slots_count = params->src_files.total_count*2; - map->slots = rdim_push_array(arena, RDIM_BakeNameMapNode *, map->slots_count); - for(RDIM_SrcFileChunkNode *n = params->src_files.first; n != 0; n = n->next) - { - for(RDI_U64 idx = 0; idx < n->count; idx += 1) - { - RDI_U64 src_file_idx = rdim_idx_from_src_file(&n->v[idx]); - rdim_bake_name_map_push(arena, map, n->v[idx].normal_full_path, (RDI_U32)src_file_idx); // TODO(rjf): @u64_to_u32 - } - } - }break; - } - return map; -} - -//- rjf: idx run map building - -RDI_PROC RDIM_BakeIdxRunMap * -rdim_bake_idx_run_map_from_params(RDIM_Arena *arena, RDIM_BakeNameMap *name_maps[RDI_NameMapKind_COUNT], RDIM_BakeParams *params) -{ - //- rjf: set up map - RDIM_BakeIdxRunMap *idx_runs = rdim_push_array(arena, RDIM_BakeIdxRunMap, 1); - idx_runs->slots_count = params->procedures.total_count*2 + params->global_variables.total_count*2 + params->thread_variables.total_count*2 + params->types.total_count*2; - idx_runs->slots = rdim_push_array(arena, RDIM_BakeIdxRunNode *, idx_runs->slots_count); - rdim_bake_idx_run_map_insert(arena, idx_runs, 0, 0); - - //- rjf: bake runs of function-type parameter lists - for(RDIM_TypeChunkNode *n = params->types.first; n != 0; n = n->next) - { - for(RDI_U64 chunk_idx = 0; chunk_idx < n->count; chunk_idx += 1) - { - RDIM_Type *type = &n->v[chunk_idx]; - if(type->kind == RDI_TypeKind_Function || type->kind == RDI_TypeKind_Method) - { - RDI_U32 param_idx_run_count = type->count; - RDI_U32 *param_idx_run = rdim_push_array_no_zero(arena, RDI_U32, param_idx_run_count); - for(RDI_U32 idx = 0; idx < param_idx_run_count; idx += 1) - { - param_idx_run[idx] = (RDI_U32)rdim_idx_from_type(type->param_types[idx]); // TODO(rjf): @u64_to_u32 - } - rdim_bake_idx_run_map_insert(arena, idx_runs, param_idx_run, param_idx_run_count); - } - } - } - - //- rjf: bake runs of name map match lists - for(RDI_NameMapKind k = (RDI_NameMapKind)(RDI_NameMapKind_NULL+1); - k < RDI_NameMapKind_COUNT; - k = (RDI_NameMapKind)(k+1)) - { - RDIM_BakeNameMap *name_map = name_maps[k]; - if(name_map != 0 && name_map->name_count != 0) - { - for(RDIM_BakeNameMapNode *n = name_map->first; n != 0; n = n->order_next) - { - if(n->val_count > 1) - { - RDI_U32 *idx_run = rdim_push_array(arena, RDI_U32, n->val_count); - RDI_U64 val_idx = 0; - for(RDIM_BakeNameMapValNode *idxnode = n->val_first; - idxnode != 0; - idxnode = idxnode->next) - { - for(RDI_U32 i = 0; i < sizeof(idxnode->val)/sizeof(idxnode->val[0]); i += 1) - { - if(idxnode->val[i] == 0) - { - goto dblbreak; - } - idx_run[val_idx] = idxnode->val[i]; - val_idx += 1; - } - } - dblbreak:; - rdim_bake_idx_run_map_insert(arena, idx_runs, idx_run, (RDI_U32)n->val_count); // TODO(rjf): @u64_to_u32 - } - } - } - } - - return idx_runs; -} - -//- rjf: bake path tree building - -RDI_PROC RDIM_BakePathTree * -rdim_bake_path_tree_from_params(RDIM_Arena *arena, RDIM_BakeParams *params) -{ - //- rjf: set up tree - RDIM_BakePathTree *tree = rdim_push_array(arena, RDIM_BakePathTree, 1); - rdim_bake_path_tree_insert(arena, tree, rdim_str8_lit("")); - - //- rjf: bake unit file paths - RDIM_ProfScope("bake unit file paths") - { - for(RDIM_UnitChunkNode *n = params->units.first; n != 0; n = n->next) - { - for(RDI_U64 idx = 0; idx < n->count; idx += 1) - { - rdim_bake_path_tree_insert(arena, tree, n->v[idx].source_file); - rdim_bake_path_tree_insert(arena, tree, n->v[idx].object_file); - rdim_bake_path_tree_insert(arena, tree, n->v[idx].archive_file); - rdim_bake_path_tree_insert(arena, tree, n->v[idx].build_path); - } - } - } - - //- rjf: bake source file paths - RDIM_ProfScope("bake source file paths") - { - for(RDIM_SrcFileChunkNode *n = params->src_files.first; n != 0; n = n->next) - { - for(RDI_U64 idx = 0; idx < n->count; idx += 1) - { - RDIM_BakePathNode *node = rdim_bake_path_tree_insert(arena, tree, n->v[idx].normal_full_path); - node->src_file = &n->v[idx]; - } - } - } - - return tree; -} - -//////////////////////////////// -//~ rjf: [Baking] Build Artifacts -> Baked Versions - -//- rjf: partial/joinable baking functions - -RDI_PROC RDIM_NameMapBakeResult -rdim_bake_name_map(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakeIdxRunMap *idx_runs, RDIM_BakeNameMap *src) -{ - RDIM_NameMapBakeResult result = {0}; - if(src->name_count != 0) - { - RDI_U32 baked_buckets_count = src->name_count; - RDI_U32 baked_nodes_count = src->name_count; - RDI_NameMapBucket *baked_buckets = rdim_push_array(arena, RDI_NameMapBucket, baked_buckets_count); - RDI_NameMapNode *baked_nodes = rdim_push_array_no_zero(arena, RDI_NameMapNode, baked_nodes_count); - { - RDIM_Temp scratch = rdim_scratch_begin(&arena, 1); - - // rjf: setup the final bucket layouts - typedef struct RDIM_NameMapSemiNode RDIM_NameMapSemiNode; - struct RDIM_NameMapSemiNode - { - RDIM_NameMapSemiNode *next; - RDIM_BakeNameMapNode *node; - }; - typedef struct RDIM_NameMapSemiBucket RDIM_NameMapSemiBucket; - struct RDIM_NameMapSemiBucket - { - RDIM_NameMapSemiNode *first; - RDIM_NameMapSemiNode *last; - RDI_U64 count; - }; - RDIM_NameMapSemiBucket *sbuckets = rdim_push_array(scratch.arena, RDIM_NameMapSemiBucket, baked_buckets_count); - for(RDIM_BakeNameMapNode *node = src->first; - node != 0; - node = node->order_next) - { - RDI_U64 hash = rdi_hash(node->string.str, node->string.size); - RDI_U64 bi = hash%baked_buckets_count; - RDIM_NameMapSemiNode *snode = rdim_push_array(scratch.arena, RDIM_NameMapSemiNode, 1); - SLLQueuePush(sbuckets[bi].first, sbuckets[bi].last, snode); - snode->node = node; - sbuckets[bi].count += 1; - } - - // rjf: convert to serialized buckets & nodes - { - RDI_NameMapBucket *bucket_ptr = baked_buckets; - RDI_NameMapNode *node_ptr = baked_nodes; - for(RDI_U32 i = 0; i < baked_buckets_count; i += 1, bucket_ptr += 1) - { - bucket_ptr->first_node = (RDI_U32)((RDI_U64)(node_ptr - baked_nodes)); - bucket_ptr->node_count = sbuckets[i].count; - for(RDIM_NameMapSemiNode *snode = sbuckets[i].first; - snode != 0; - snode = snode->next) - { - RDIM_BakeNameMapNode *node = snode->node; - - // rjf: cons name and index(es) - RDI_U32 string_idx = rdim_bake_idx_from_string(strings, node->string); - RDI_U32 match_count = node->val_count; - RDI_U32 idx = 0; - if(match_count == 1) - { - idx = node->val_first->val[0]; - } - else - { - RDI_U64 temp_pos = rdim_arena_pos(scratch.arena); - RDI_U32 *idx_run = rdim_push_array_no_zero(scratch.arena, RDI_U32, match_count); - RDI_U32 *idx_ptr = idx_run; - for(RDIM_BakeNameMapValNode *idxnode = node->val_first; - idxnode != 0; - idxnode = idxnode->next) - { - for(RDI_U32 i = 0; i < sizeof(idxnode->val)/sizeof(idxnode->val[0]); i += 1) - { - if(idxnode->val[i] == 0) - { - goto dblbreak; - } - *idx_ptr = idxnode->val[i]; - idx_ptr += 1; - } - } - dblbreak:; - idx = rdim_bake_idx_from_idx_run(idx_runs, idx_run, match_count); - rdim_arena_pop_to(scratch.arena, temp_pos); - } - - // rjf: write to node - node_ptr->string_idx = string_idx; - node_ptr->match_count = match_count; - node_ptr->match_idx_or_idx_run_first = idx; - node_ptr += 1; - } - } - } - rdim_scratch_end(scratch); - } - - // rjf: sections for buckets/nodes - result.buckets = baked_buckets; - result.buckets_count = baked_buckets_count; - result.nodes = baked_nodes; - result.nodes_count = baked_nodes_count; - } - return result; -} - -//- rjf: partial bakes -> final bake functions - -RDI_PROC RDIM_NameMapBakeResult -rdim_name_map_bake_results_combine(RDIM_Arena *arena, RDIM_NameMapBakeResult *results, RDI_U64 results_count) -{ - RDIM_NameMapBakeResult result = {0}; - { - //- rjf: count needed # of buckets/nodes - RDI_U64 all_buckets_count = 0; - RDI_U64 all_nodes_count = 0; - for(RDI_U64 idx = 0; idx < results_count; idx += 1) - { - all_buckets_count += results[idx].buckets_count; - all_nodes_count += results[idx].nodes_count; - } - - //- rjf: allocate outputs - result.buckets_count = all_buckets_count; - result.buckets = rdim_push_array_no_zero(arena, RDI_NameMapBucket, result.buckets_count); - result.nodes_count = all_nodes_count; - result.nodes = rdim_push_array_no_zero(arena, RDI_NameMapNode, result.nodes_count); - - //- rjf: fill outputs - { - RDI_U64 buckets_off = 0; - RDI_U64 nodes_off = 0; - for(RDI_U64 idx = 0; idx < results_count; idx += 1) - { - rdim_memcpy(result.buckets + buckets_off, results[idx].buckets, sizeof(result.buckets[0])*results[idx].buckets_count); - rdim_memcpy(result.nodes + nodes_off, results[idx].nodes, sizeof(result.nodes[0])*results[idx].nodes_count); - buckets_off += results[idx].buckets_count; - nodes_off += results[idx].nodes_count; - } - } - } - return result; -} - -//- rjf: independent (top-level, global) baking functions - -RDI_PROC RDIM_TopLevelInfoBakeResult -rdim_bake_top_level_info(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_TopLevelInfo *src) -{ - RDIM_TopLevelInfoBakeResult result = {0}; - { - result.top_level_info = rdim_push_array(arena, RDI_TopLevelInfo, 1); - result.top_level_info->arch = src->arch; - result.top_level_info->exe_name_string_idx = rdim_bake_idx_from_string(strings, src->exe_name); - result.top_level_info->exe_hash = src->exe_hash; - result.top_level_info->voff_max = src->voff_max; - result.top_level_info->producer_name_string_idx = rdim_bake_idx_from_string(strings, src->producer_name); - } - return result; -} - -RDI_PROC RDIM_BinarySectionBakeResult -rdim_bake_binary_sections(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BinarySectionList *src) -{ - RDIM_BinarySectionBakeResult result = {0}; - { - RDI_BinarySection *dst_base = rdim_push_array(arena, RDI_BinarySection, src->count+1); - U64 dst_idx = 1; - for(RDIM_BinarySectionNode *src_n = src->first; src_n != 0; src_n = src_n->next, dst_idx += 1) - { - RDIM_BinarySection *src = &src_n->v; - RDI_BinarySection *dst = &dst_base[dst_idx]; - dst->name_string_idx = rdim_bake_idx_from_string(strings, src->name); - dst->flags = src->flags; - dst->voff_first = src->voff_first; - dst->voff_opl = src->voff_opl; - dst->foff_first = src->foff_first; - dst->foff_opl = src->foff_opl; - } - result.binary_sections = dst_base; - result.binary_sections_count = dst_idx; - } - return result; -} - -RDI_PROC RDIM_UnitBakeResult -rdim_bake_units(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakePathTree *path_tree, RDIM_UnitChunkList *src) -{ - RDIM_UnitBakeResult result = {0}; - { - RDI_Unit *dst_base = rdim_push_array(arena, RDI_Unit, src->total_count+1); - RDI_U64 dst_idx = 1; - for(RDIM_UnitChunkNode *src_n = src->first; src_n != 0; src_n = src_n->next) - { - for(RDI_U64 src_chunk_idx = 0; src_chunk_idx < src_n->count; src_chunk_idx += 1, dst_idx += 1) - { - RDIM_Unit *src = &src_n->v[src_chunk_idx]; - RDI_Unit *dst = &dst_base[dst_idx]; - dst->unit_name_string_idx = rdim_bake_idx_from_string(strings, src->unit_name); - dst->compiler_name_string_idx = rdim_bake_idx_from_string(strings, src->compiler_name); - dst->source_file_path_node = rdim_bake_path_node_idx_from_string(path_tree, src->source_file); - dst->object_file_path_node = rdim_bake_path_node_idx_from_string(path_tree, src->object_file); - dst->archive_file_path_node = rdim_bake_path_node_idx_from_string(path_tree, src->archive_file); - dst->build_path_node = rdim_bake_path_node_idx_from_string(path_tree, src->build_path); - dst->language = src->language; - dst->line_table_idx = (RDI_U32)rdim_idx_from_line_table(src->line_table); // TODO(rjf): @u64_to_u32 - } - } - result.units = dst_base; - result.units_count = dst_idx; - } - return result; -} - -RDI_PROC RDIM_UnitVMapBakeResult -rdim_bake_unit_vmap(RDIM_Arena *arena, RDIM_UnitChunkList *units) -{ - //- rjf: build vmap from unit voff ranges - RDIM_BakeVMap unit_vmap = {0}; - { - RDIM_Temp scratch = rdim_scratch_begin(&arena, 1); - - // rjf: count voff ranges - RDI_U64 voff_range_count = 0; - for(RDIM_UnitChunkNode *n = units->first; n != 0; n = n->next) - { - for(RDI_U64 idx = 0; idx < n->count; idx += 1) - { - RDIM_Unit *unit = &n->v[idx]; - voff_range_count += unit->voff_ranges.count; - } - } - - // rjf: count necessary markers - RDI_U64 marker_count = voff_range_count*2; - - // rjf: build keys/markers arrays - RDIM_SortKey *keys = rdim_push_array_no_zero(scratch.arena, RDIM_SortKey, marker_count); - RDIM_VMapMarker *markers = rdim_push_array_no_zero(scratch.arena, RDIM_VMapMarker, marker_count); - { - RDIM_SortKey *key_ptr = keys; - RDIM_VMapMarker *marker_ptr = markers; - RDI_U32 unit_idx = 1; - for(RDIM_UnitChunkNode *unit_chunk_n = units->first; - unit_chunk_n != 0; - unit_chunk_n = unit_chunk_n->next) - { - for(RDI_U64 idx = 0; idx < unit_chunk_n->count; idx += 1) - { - RDIM_Unit *unit = &unit_chunk_n->v[idx]; - for(RDIM_Rng1U64Node *n = unit->voff_ranges.first; n != 0; n = n->next) - { - RDIM_Rng1U64 range = n->v; - if(range.min < range.max) - { - key_ptr->key = range.min; - key_ptr->val = marker_ptr; - marker_ptr->idx = unit_idx; - marker_ptr->begin_range = 1; - key_ptr += 1; - marker_ptr += 1; - - key_ptr->key = range.max; - key_ptr->val = marker_ptr; - marker_ptr->idx = unit_idx; - marker_ptr->begin_range = 0; - key_ptr += 1; - marker_ptr += 1; - } - } - unit_idx += 1; - } - } - } - - // rjf: keys/markers -> unit vmap - unit_vmap = rdim_bake_vmap_from_markers(arena, markers, keys, marker_count); - rdim_scratch_end(scratch); - } - - //- rjf: fill result - RDIM_UnitVMapBakeResult result = {unit_vmap}; - return result; -} - -RDI_PROC RDIM_SrcFileBakeResult -rdim_bake_src_files(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakePathTree *path_tree, RDIM_SrcFileChunkList *src) -{ - RDIM_Temp scratch = rdim_scratch_begin(&arena, 1); - - //////////////////////////// - //- rjf: iterate all source files, fill serialized version, fill line maps, fill line map tables - // - typedef struct RDIM_DataNode RDIM_DataNode; - struct RDIM_DataNode - { - RDIM_DataNode *next; - void *data; - RDI_U64 size; - }; - RDI_U32 dst_files_count = src->total_count + 1; - RDI_U32 dst_maps_count = src->source_line_map_count + 1; - RDI_SourceFile *dst_files = rdim_push_array(arena, RDI_SourceFile, dst_files_count); - RDI_SourceLineMap *dst_maps = rdim_push_array(arena, RDI_SourceLineMap, dst_maps_count); - RDIM_DataNode *first_dst_nums_node = 0; - RDIM_DataNode *last_dst_nums_node = 0; - RDIM_DataNode *first_dst_rngs_node = 0; - RDIM_DataNode *last_dst_rngs_node = 0; - RDIM_DataNode *first_dst_voffs_node = 0; - RDIM_DataNode *last_dst_voffs_node = 0; - RDI_U64 dst_nums_idx = 0; - RDI_U64 dst_rngs_idx = 0; - RDI_U64 dst_voffs_idx = 0; - RDI_U32 dst_file_idx = 1; - RDI_U32 dst_map_idx = 1; - for(RDIM_SrcFileChunkNode *chunk_n = src->first; - chunk_n != 0; - chunk_n = chunk_n->next) - { - for(RDI_U64 idx = 0; idx < chunk_n->count; idx += 1, dst_file_idx += 1) - { - RDIM_SrcFile *src_file = &chunk_n->v[idx]; - RDI_SourceFile *dst_file = &dst_files[dst_file_idx]; - - //////////////////////// - //- rjf: produce combined source file line info - // - RDI_U32 *src_file_line_nums = 0; - RDI_U32 *src_file_line_ranges = 0; - RDI_U64 *src_file_voffs = 0; - RDI_U32 src_file_line_count = 0; - RDI_U32 src_file_voff_count = 0; - { - //- rjf: gather line number map - typedef struct RDIM_SrcLineMapVoffBlock RDIM_SrcLineMapVoffBlock; - struct RDIM_SrcLineMapVoffBlock - { - RDIM_SrcLineMapVoffBlock *next; - RDI_U64 voff; - }; - typedef struct RDIM_SrcLineMapBucket RDIM_SrcLineMapBucket; - struct RDIM_SrcLineMapBucket - { - RDIM_SrcLineMapBucket *order_next; - RDIM_SrcLineMapBucket *hash_next; - RDI_U32 line_num; - RDIM_SrcLineMapVoffBlock *first_voff_block; - RDIM_SrcLineMapVoffBlock *last_voff_block; - RDI_U64 voff_count; - }; - RDIM_SrcLineMapBucket *first_bucket = 0; - RDIM_SrcLineMapBucket *last_bucket = 0; - RDI_U64 line_hash_slots_count = 2048; - RDIM_SrcLineMapBucket **line_hash_slots = rdim_push_array(scratch.arena, RDIM_SrcLineMapBucket *, line_hash_slots_count); - RDI_U64 line_count = 0; - RDI_U64 voff_count = 0; - RDI_U64 max_line_num = 0; - { - for(RDIM_SrcFileLineMapFragment *map_fragment = src_file->first_line_map_fragment; - map_fragment != 0; - map_fragment = map_fragment->next) - { - RDIM_LineSequence *sequence = map_fragment->seq; - RDI_U64 *seq_voffs = sequence->voffs; - RDI_U32 *seq_line_nums = sequence->line_nums; - RDI_U64 seq_line_count = sequence->line_count; - for(RDI_U64 i = 0; i < seq_line_count; i += 1) - { - RDI_U32 line_num = seq_line_nums[i]; - RDI_U64 voff = seq_voffs[i]; - RDI_U64 line_hash_slot_idx = line_num%line_hash_slots_count; - - // rjf: update unique voff counter & max line number - voff_count += 1; - max_line_num = Max(max_line_num, line_num); - - // rjf: find match - RDIM_SrcLineMapBucket *match = 0; - { - for(RDIM_SrcLineMapBucket *node = line_hash_slots[line_hash_slot_idx]; - node != 0; - node = node->hash_next) - { - if(node->line_num == line_num) - { - match = node; - break; - } - } - } - - // rjf: introduce new map if no match - if(match == 0) - { - match = rdim_push_array(scratch.arena, RDIM_SrcLineMapBucket, 1); - RDIM_SLLQueuePush_N(first_bucket, last_bucket, match, order_next); - RDIM_SLLStackPush_N(line_hash_slots[line_hash_slot_idx], match, hash_next); - match->line_num = line_num; - line_count += 1; - } - - // rjf: insert new voff - { - RDIM_SrcLineMapVoffBlock *block = rdim_push_array(scratch.arena, RDIM_SrcLineMapVoffBlock, 1); - RDIM_SLLQueuePush(match->first_voff_block, match->last_voff_block, block); - match->voff_count += 1; - block->voff = voff; - } - } - } - } - - //- rjf: bake sortable keys array - RDIM_SortKey *keys = rdim_push_array_no_zero(scratch.arena, RDIM_SortKey, line_count); - { - RDIM_SortKey *key_ptr = keys; - for(RDIM_SrcLineMapBucket *node = first_bucket; - node != 0; - node = node->order_next, key_ptr += 1){ - key_ptr->key = node->line_num; - key_ptr->val = node; - } - } - - //- rjf: sort keys array - RDIM_SortKey *sorted_keys = rdim_sort_key_array(scratch.arena, keys, line_count); - - //- rjf: bake result - RDI_U32 *line_nums = rdim_push_array_no_zero(scratch.arena, RDI_U32, line_count); - RDI_U32 *line_ranges = rdim_push_array_no_zero(scratch.arena, RDI_U32, line_count + 1); - RDI_U64 *voffs = rdim_push_array_no_zero(scratch.arena, RDI_U64, voff_count); - { - RDI_U64 *voff_ptr = voffs; - for(RDI_U32 i = 0; i < line_count; i += 1) - { - line_nums[i] = sorted_keys[i].key; - line_ranges[i] = (RDI_U32)(voff_ptr - voffs); // TODO(rjf): @u64_to_u32 - RDIM_SrcLineMapBucket *bucket = (RDIM_SrcLineMapBucket*)sorted_keys[i].val; - for(RDIM_SrcLineMapVoffBlock *node = bucket->first_voff_block; node != 0; node = node->next) - { - *voff_ptr = node->voff; - voff_ptr += 1; - } - } - line_ranges[line_count] = voff_count; - } - - //- rjf: fill output - src_file_line_nums = line_nums; - src_file_line_ranges = line_ranges; - src_file_line_count = line_count; - src_file_voffs = voffs; - src_file_voff_count = voff_count; - } - - //////////////////////// - //- rjf: grab & fill the next line map, if this file has one - // - RDI_SourceLineMap *dst_map = 0; - if(src_file->first_line_map_fragment != 0) - { - dst_map = &dst_maps[dst_map_idx]; - dst_map_idx += 1; - dst_map->line_count = (RDI_U32)src_file_line_count; // TODO(rjf): @u64_to_u32 - dst_map->voff_count = (RDI_U32)src_file_voff_count; // TODO(rjf): @u64_to_u32 - dst_map->line_map_nums_base_idx = (RDI_U32)dst_nums_idx; // TODO(rjf): @u64_to_u32 - dst_map->line_map_range_base_idx = (RDI_U32)dst_rngs_idx; // TODO(rjf): @u64_to_u32 - dst_map->line_map_voff_base_idx = (RDI_U32)dst_voffs_idx; // TODO(rjf): @u64_to_u32 - } - - //////////////////////// - //- rjf: gather line map data chunks for later collation & storage into their own top-level sections - // - { - RDIM_DataNode *dst_num_node = rdim_push_array(scratch.arena, RDIM_DataNode, 1); - RDIM_SLLQueuePush(first_dst_nums_node, last_dst_nums_node, dst_num_node); - dst_num_node->data = src_file_line_nums; - dst_num_node->size = sizeof(RDI_U32)*src_file_line_count; - RDIM_DataNode *dst_rng_node = rdim_push_array(scratch.arena, RDIM_DataNode, 1); - RDIM_SLLQueuePush(first_dst_rngs_node, last_dst_rngs_node, dst_rng_node); - dst_rng_node->data = src_file_line_ranges; - dst_rng_node->size = sizeof(RDI_U32)*(src_file_line_count+1); - RDIM_DataNode *dst_voff_node = rdim_push_array(scratch.arena, RDIM_DataNode, 1); - RDIM_SLLQueuePush(first_dst_voffs_node, last_dst_voffs_node, dst_voff_node); - dst_voff_node->data = src_file_voffs; - dst_voff_node->size = sizeof(RDI_U64)*(src_file_voff_count); - dst_nums_idx += src_file_line_count; - dst_rngs_idx += src_file_line_count+1; - dst_voffs_idx+= src_file_voff_count; - } - - //////////////////////// - //- rjf: fill file info - // - dst_file->file_path_node_idx = rdim_bake_path_node_idx_from_string(path_tree, src_file->normal_full_path); - dst_file->normal_full_path_string_idx = rdim_bake_idx_from_string(strings, src_file->normal_full_path); - dst_file->source_line_map_idx = (RDI_U32)(dst_map ? (dst_map - dst_maps) : 0); - } - } - - //////////////////////////// - //- rjf: coalesce source line map data blobs - // - RDI_U32 *source_line_map_nums = rdim_push_array_no_zero(arena, RDI_U32, dst_nums_idx); - RDI_U32 *source_line_map_rngs = rdim_push_array_no_zero(arena, RDI_U32, dst_rngs_idx); - RDI_U64 *source_line_map_voffs= rdim_push_array_no_zero(arena, RDI_U64, dst_voffs_idx); - { - RDI_U64 num_idx = 0; - RDI_U64 rng_idx = 0; - RDI_U64 voff_idx= 0; - for(RDIM_DataNode *num_n = first_dst_nums_node; num_n != 0; num_n = num_n->next) - { - rdim_memcpy(source_line_map_nums+num_idx, num_n->data, num_n->size); - num_idx += num_n->size/sizeof(RDI_U32); - } - for(RDIM_DataNode *rng_n = first_dst_rngs_node; rng_n != 0; rng_n = rng_n->next) - { - rdim_memcpy(source_line_map_rngs+rng_idx, rng_n->data, rng_n->size); - rng_idx += rng_n->size/sizeof(RDI_U32); - } - for(RDIM_DataNode *voff_n = first_dst_voffs_node; voff_n != 0; voff_n = voff_n->next) - { - rdim_memcpy(source_line_map_voffs+voff_idx, voff_n->data, voff_n->size); - voff_idx += voff_n->size/sizeof(RDI_U64); - } - } - - //////////////////////////// - //- rjf: fill result - // - RDIM_SrcFileBakeResult result = {0}; - result.source_files = dst_files; - result.source_files_count = dst_files_count; - result.source_line_maps = dst_maps; - result.source_line_maps_count = dst_maps_count; - result.source_line_map_nums = source_line_map_nums; - result.source_line_map_nums_count = dst_nums_idx; - result.source_line_map_rngs = source_line_map_rngs; - result.source_line_map_rngs_count = dst_rngs_idx; - result.source_line_map_voffs = source_line_map_voffs; - result.source_line_map_voffs_count= dst_voffs_idx; - - rdim_scratch_end(scratch); - return result; -} - -RDI_PROC RDIM_LineTableBakeResult -rdim_bake_line_tables(RDIM_Arena *arena, RDIM_LineTableChunkList *src) -{ - ////////////////////////////// - //- rjf: build all combined line info - // - RDI_LineTable *dst_line_tables = push_array(arena, RDI_LineTable, src->total_count+1); - RDI_U64 *dst_line_voffs = push_array(arena, RDI_U64, src->total_line_count + 2*src->total_seq_count); - RDI_Line *dst_lines = push_array(arena, RDI_Line, src->total_line_count + src->total_seq_count); - RDI_Column *dst_cols = push_array(arena, RDI_Column, 1); - { - RDI_U64 dst_table_idx = 1; - RDI_U64 dst_voff_idx = 0; - RDI_U64 dst_line_idx = 0; - RDI_U64 dst_col_idx = 0; - for(RDIM_LineTableChunkNode *src_n = src->first; src_n != 0; src_n = src_n->next) - { - for(RDI_U64 chunk_idx = 0; chunk_idx < src_n->count; chunk_idx += 1) - { - RDIM_LineTable *src_line_table = &src_n->v[chunk_idx]; - RDI_LineTable *dst_line_table = &dst_line_tables[dst_table_idx]; - - //- rjf: fill combined line table info - { - RDIM_Temp scratch = rdim_scratch_begin(&arena, 1); - - //- rjf: gather up all line info into two arrays: - // - // [1] keys: sortable array; pairs voffs with line info records; null records are sequence enders - // [2] recs: contains all the source coordinates for a range of voffs - // - typedef struct RDIM_LineRec RDIM_LineRec; - struct RDIM_LineRec - { - RDI_U32 file_id; - RDI_U32 line_num; - RDI_U16 col_first; - RDI_U16 col_opl; - }; - RDI_U64 line_count = src_line_table->line_count; - RDI_U64 seq_count = src_line_table->seq_count; - RDI_U64 key_count = line_count + seq_count; - RDIM_SortKey *line_keys = rdim_push_array_no_zero(scratch.arena, RDIM_SortKey, key_count); - RDIM_LineRec *line_recs = rdim_push_array_no_zero(scratch.arena, RDIM_LineRec, line_count); - { - RDIM_SortKey *key_ptr = line_keys; - RDIM_LineRec *rec_ptr = line_recs; - for(RDIM_LineSequenceNode *seq_n = src_line_table->first_seq; seq_n != 0; seq_n = seq_n->next) - { - RDIM_LineSequence *seq = &seq_n->v; - for(RDI_U64 line_idx = 0; line_idx < seq->line_count; line_idx += 1) - { - key_ptr->key = seq->voffs[line_idx]; - key_ptr->val = rec_ptr; - key_ptr += 1; - rec_ptr->file_id = (RDI_U32)rdim_idx_from_src_file(seq->src_file); // TODO(rjf): @u64_to_u32 - rec_ptr->line_num = seq->line_nums[line_idx]; - if(seq->col_nums != 0) - { - rec_ptr->col_first = seq->col_nums[line_idx*2]; - rec_ptr->col_opl = seq->col_nums[line_idx*2 + 1]; - } - rec_ptr += 1; - } - key_ptr->key = seq->voffs[seq->line_count]; - key_ptr->val = 0; - key_ptr += 1; - } - } - - //- rjf: sort - RDIM_SortKey *sorted_line_keys = 0; - { - sorted_line_keys = rdim_sort_key_array(scratch.arena, line_keys, key_count); - } - - // TODO(rjf): do a pass over sorted keys to make sure duplicate keys - // are sorted with null record first, and no more than one null - // record and one non-null record - - //- rjf: arrange output - RDI_U64 *arranged_voffs = dst_line_voffs + dst_voff_idx; - RDI_Line *arranged_lines = dst_lines + dst_line_idx; - { - for(RDI_U64 i = 0; i < key_count; i += 1) - { - arranged_voffs[i] = sorted_line_keys[i].key; - } - arranged_voffs[key_count] = ~0ull; - for(RDI_U64 i = 0; i < key_count; i += 1) - { - RDIM_LineRec *rec = (RDIM_LineRec*)sorted_line_keys[i].val; - if(rec != 0) - { - arranged_lines[i].file_idx = rec->file_id; - arranged_lines[i].line_num = rec->line_num; - } - else - { - arranged_lines[i].file_idx = 0; - arranged_lines[i].line_num = 0; - } - } - } - - rdim_scratch_end(scratch); - } - - //- rjf: fill destination table - dst_line_table->voffs_base_idx = (RDI_U32)dst_voff_idx; // TODO(rjf): @u64_to_u32 - dst_line_table->lines_base_idx = (RDI_U32)dst_line_idx; // TODO(rjf): @u64_to_u32 - dst_line_table->cols_base_idx = (RDI_U32)dst_col_idx; // TODO(rjf): @u64_to_u32 - dst_line_table->lines_count = (RDI_U32)src_line_table->line_count + src_line_table->seq_count; // TODO(rjf): @u64_to_u32 - - //- rjf: increment - dst_table_idx += 1; - dst_voff_idx += src_line_table->line_count + 2*src_line_table->seq_count; - dst_line_idx += src_line_table->line_count + src_line_table->seq_count; - } - } - } - - ////////////////////////////// - //- rjf: fill result - // - RDIM_LineTableBakeResult result = {0}; - { - result.line_tables = dst_line_tables; - result.line_tables_count = src->total_count+1; - result.line_table_voffs = dst_line_voffs; - result.line_table_voffs_count = (src->total_line_count + src->total_seq_count); - result.line_table_lines = dst_lines; - result.line_table_lines_count = (src->total_line_count + src->total_seq_count); - result.line_table_columns = dst_cols; - result.line_table_columns_count = src->total_col_count; - } - return result; -} - -RDI_PROC RDIM_TypeNodeBakeResult -rdim_bake_types(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakeIdxRunMap *idx_runs, RDIM_TypeChunkList *src) -{ - RDI_TypeNode *type_nodes = push_array(arena, RDI_TypeNode, src->total_count+1); - RDI_U32 dst_idx = 1; - for(RDIM_TypeChunkNode *n = src->first; n != 0; n = n->next) - { - for(RDI_U64 chunk_idx = 0; chunk_idx < n->count; chunk_idx += 1, dst_idx += 1) - { - RDIM_Type *src = &n->v[chunk_idx]; - RDI_TypeNode *dst = &type_nodes[dst_idx]; - - //- rjf: fill shared type node info - dst->kind = src->kind; - dst->flags = (RDI_U16)src->flags; // TODO(rjf): @u32_to_u16 - dst->byte_size = src->byte_size; - - //- rjf: fill built-in-only type node info - if(RDI_TypeKind_FirstBuiltIn <= dst->kind && dst->kind <= RDI_TypeKind_LastBuiltIn) - { - dst->built_in.name_string_idx = rdim_bake_idx_from_string(strings, src->name); - } - - //- rjf: fill constructed type node info - else if(RDI_TypeKind_FirstConstructed <= dst->kind && dst->kind <= RDI_TypeKind_LastConstructed) - { - dst->constructed.direct_type_idx = (RDI_U32)rdim_idx_from_type(src->direct_type); // TODO(rjf): @u64_to_u32 - dst->constructed.count = src->count; - if(dst->kind == RDI_TypeKind_Function || dst->kind == RDI_TypeKind_Method) - { - RDI_U32 param_idx_run_count = src->count; - RDI_U32 *param_idx_run = rdim_push_array_no_zero(arena, RDI_U32, param_idx_run_count); - for(RDI_U32 idx = 0; idx < param_idx_run_count; idx += 1) - { - param_idx_run[idx] = (RDI_U32)rdim_idx_from_type(src->param_types[idx]); // TODO(rjf): @u64_to_u32 - } - dst->constructed.param_idx_run_first = rdim_bake_idx_from_idx_run(idx_runs, param_idx_run, param_idx_run_count); - } - else if(dst->kind == RDI_TypeKind_MemberPtr) - { - // TODO(rjf): member pointers not currently supported. - } - } - - //- rjf: fill user-defined-type info - else if(RDI_TypeKind_FirstUserDefined <= dst->kind && dst->kind <= RDI_TypeKind_LastUserDefined) - { - dst->user_defined.name_string_idx = rdim_bake_idx_from_string(strings, src->name); - dst->user_defined.udt_idx = (RDI_U32)rdim_idx_from_udt(src->udt); // TODO(rjf): @u64_to_u32 - dst->user_defined.direct_type_idx = (RDI_U32)rdim_idx_from_type(src->direct_type); // TODO(rjf): @u64_to_u32 - } - - //- rjf: fill bitfield info - else if(dst->kind == RDI_TypeKind_Bitfield) - { - dst->bitfield.direct_type_idx = (RDI_U32)rdim_idx_from_type(src->direct_type); // TODO(rjf): @u64_to_u32 - dst->bitfield.off = src->off; - dst->bitfield.size = src->count; - } - } - } - RDIM_TypeNodeBakeResult result = {0}; - result.type_nodes = type_nodes; - result.type_nodes_count = (src->total_count+1); - return result; -} - -RDI_PROC RDIM_UDTBakeResult -rdim_bake_udts(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_UDTChunkList *src) -{ - //- rjf: build tables - RDI_UDT * udts = push_array(arena, RDI_UDT, src->total_count+1); - RDI_Member * members = push_array(arena, RDI_Member, src->total_member_count+1); - RDI_EnumMember *enum_members = push_array(arena, RDI_EnumMember, src->total_enum_val_count+1); - { - RDI_U32 dst_udt_idx = 1; - RDI_U32 dst_member_idx = 1; - RDI_U32 dst_enum_member_idx = 1; - for(RDIM_UDTChunkNode *n = src->first; n != 0; n = n->next) - { - for(RDI_U64 chunk_idx = 0; chunk_idx < n->count; chunk_idx += 1, dst_udt_idx += 1) - { - RDIM_UDT *src_udt = &n->v[chunk_idx]; - RDI_UDT *dst_udt = &udts[dst_udt_idx]; - - //- rjf: fill basics - dst_udt->self_type_idx = (RDI_U32)rdim_idx_from_type(src_udt->self_type); // TODO(rjf): @u64_to_u32 - dst_udt->file_idx = (RDI_U32)rdim_idx_from_src_file(src_udt->src_file); // TODO(rjf): @u64_to_u32 - dst_udt->line = src_udt->line; - dst_udt->col = src_udt->col; - - //- rjf: fill members - if(src_udt->member_count != 0) - { - dst_udt->member_first = dst_member_idx; - dst_udt->member_count = src_udt->member_count; - for(RDIM_UDTMember *src_member = src_udt->first_member; - src_member != 0; - src_member = src_member->next, dst_member_idx += 1) - { - RDI_Member *dst_member = &members[dst_member_idx]; - dst_member->kind = src_member->kind; - dst_member->name_string_idx = rdim_bake_idx_from_string(strings, src_member->name); - dst_member->type_idx = (RDI_U32)rdim_idx_from_type(src_member->type); // TODO(rjf): @u64_to_u32 - dst_member->off = src_member->off; - } - } - - //- rjf: fill enum members - else if(src_udt->enum_val_count != 0) - { - dst_udt->flags |= RDI_UDTFlag_EnumMembers; - dst_udt->member_first = dst_enum_member_idx; - dst_udt->member_count = src_udt->enum_val_count; - for(RDIM_UDTEnumVal *src_member = src_udt->first_enum_val; - src_member != 0; - src_member = src_member->next, dst_enum_member_idx += 1) - { - RDI_EnumMember *dst_member = &enum_members[dst_enum_member_idx]; - dst_member->name_string_idx = rdim_bake_idx_from_string(strings, src_member->name); - dst_member->val = src_member->val; - } - } - } - } - } - - //- rjf: fill result - RDIM_UDTBakeResult result = {0}; - { - result.udts = udts; - result.udts_count = src->total_count+1; - result.members = members; - result.members_count = src->total_member_count+1; - result.enum_members = enum_members; - result.enum_members_count = src->total_enum_val_count+1; - } - return result; -} - -RDI_PROC RDIM_GlobalVariableBakeResult -rdim_bake_global_variables(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_SymbolChunkList *src) -{ - RDI_GlobalVariable *global_variables = push_array(arena, RDI_GlobalVariable, src->total_count+1); - RDI_U32 dst_idx = 1; - for(RDIM_SymbolChunkNode *n = src->first; n != 0; n = n->next) - { - for(RDI_U64 chunk_idx = 0; chunk_idx < n->count; chunk_idx += 1, dst_idx += 1) - { - RDIM_Symbol *src = &n->v[chunk_idx]; - RDI_GlobalVariable *dst = &global_variables[dst_idx]; - dst->name_string_idx = rdim_bake_idx_from_string(strings, src->name); - dst->voff = src->offset; - dst->type_idx = (RDI_U32)rdim_idx_from_type(src->type); // TODO(rjf): @u64_to_u32 - if(src->is_extern) - { - dst->link_flags |= RDI_LinkFlag_External; - } - if(src->container_type != 0) - { - dst->link_flags |= RDI_LinkFlag_TypeScoped; - dst->container_idx = src->container_type ? (RDI_U32)rdim_idx_from_udt(src->container_type->udt) : 0; // TODO(rjf): @u64_to_u32 - } - else if(src->container_symbol != 0) - { - dst->link_flags |= RDI_LinkFlag_ProcScoped; - dst->container_idx = (RDI_U32)rdim_idx_from_symbol(src->container_symbol); // TODO(rjf): @u64_to_u32 - } - } - } - RDIM_GlobalVariableBakeResult result = {0}; - result.global_variables = global_variables; - result.global_variables_count = (src->total_count+1); - return result; -} - -RDI_PROC RDIM_GlobalVMapBakeResult -rdim_bake_global_vmap(RDIM_Arena *arena, RDIM_SymbolChunkList *src) -{ - //- rjf: build global vmap - RDIM_BakeVMap global_vmap = {0}; - { - RDIM_Temp scratch = rdim_scratch_begin(&arena, 1); - - //- rjf: allocate keys/markers - RDI_U64 marker_count = src->total_count*2; - RDIM_SortKey *keys = rdim_push_array_no_zero(scratch.arena, RDIM_SortKey, marker_count); - RDIM_VMapMarker *markers = rdim_push_array_no_zero(scratch.arena, RDIM_VMapMarker, marker_count); - - //- rjf: fill - { - RDIM_SortKey *key_ptr = keys; - RDIM_VMapMarker *marker_ptr = markers; - - // rjf: fill actual globals - for(RDIM_SymbolChunkNode *n = src->first; n != 0; n = n->next) - { - for(RDI_U64 chunk_idx = 0; chunk_idx < n->count; chunk_idx += 1) - { - RDIM_Symbol *global_var = &n->v[chunk_idx]; - RDI_U32 global_var_idx = (RDI_U32)rdim_idx_from_symbol(global_var); // TODO(rjf): @u64_to_u32 - RDI_U64 global_var_size = global_var->type ? global_var->type->byte_size : 1; - - RDI_U64 first = global_var->offset; - RDI_U64 opl = first + global_var_size; - - key_ptr->key = first; - key_ptr->val = marker_ptr; - marker_ptr->idx = global_var_idx; - marker_ptr->begin_range = 1; - key_ptr += 1; - marker_ptr += 1; - - key_ptr->key = opl; - key_ptr->val = marker_ptr; - marker_ptr->idx = global_var_idx; - marker_ptr->begin_range = 0; - key_ptr += 1; - marker_ptr += 1; - } - } - - // rjf: fill nil global - { - RDI_U32 global_idx = 0; - RDI_U64 first = 0; - RDI_U64 opl = 0xffffffffffffffffull; - key_ptr->key = first; - key_ptr->val = marker_ptr; - marker_ptr->idx = global_idx; - marker_ptr->begin_range = 1; - key_ptr += 1; - marker_ptr += 1; - key_ptr->key = opl; - key_ptr->val = marker_ptr; - marker_ptr->idx = global_idx; - marker_ptr->begin_range = 0; - key_ptr += 1; - marker_ptr += 1; - } - } - - // rjf: construct vmap - global_vmap = rdim_bake_vmap_from_markers(arena, markers, keys, marker_count); - - rdim_scratch_end(scratch); - } - - //- rjf: fill result - RDIM_GlobalVMapBakeResult result = {global_vmap}; - return result; -} - -RDI_PROC RDIM_ThreadVariableBakeResult -rdim_bake_thread_variables(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_SymbolChunkList *src) -{ - RDI_ThreadVariable *thread_variables = push_array(arena, RDI_ThreadVariable, src->total_count+1); - RDI_U32 dst_idx = 1; - for(RDIM_SymbolChunkNode *n = src->first; n != 0; n = n->next) - { - for(RDI_U64 chunk_idx = 0; chunk_idx < n->count; chunk_idx += 1, dst_idx += 1) - { - RDIM_Symbol *src = &n->v[chunk_idx]; - RDI_ThreadVariable *dst = &thread_variables[dst_idx]; - dst->name_string_idx = rdim_bake_idx_from_string(strings, src->name); - dst->tls_off = (RDI_U32)src->offset; // TODO(rjf): @u64_to_u32 - dst->type_idx = (RDI_U32)rdim_idx_from_type(src->type); - if(src->is_extern) - { - dst->link_flags |= RDI_LinkFlag_External; - } - if(src->container_type != 0) - { - dst->link_flags |= RDI_LinkFlag_TypeScoped; - dst->container_idx = src->container_type ? (RDI_U32)rdim_idx_from_udt(src->container_type->udt) : 0; // TODO(rjf): @u64_to_u32 - } - else if(src->container_symbol != 0) - { - dst->link_flags |= RDI_LinkFlag_ProcScoped; - dst->container_idx = (RDI_U32)rdim_idx_from_symbol(src->container_symbol); // TODO(rjf): @u64_to_u32 - } - } - } - RDIM_ThreadVariableBakeResult result = {0}; - result.thread_variables = thread_variables; - result.thread_variables_count = src->total_count+1; - return result; -} - -RDI_PROC RDIM_ProcedureBakeResult -rdim_bake_procedures(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_SymbolChunkList *src) -{ - RDI_Procedure *procedures = push_array(arena, RDI_Procedure, src->total_count+1); - RDI_U32 dst_idx = 1; - for(RDIM_SymbolChunkNode *n = src->first; n != 0; n = n->next) - { - for(RDI_U64 chunk_idx = 0; chunk_idx < n->count; chunk_idx += 1, dst_idx += 1) - { - RDIM_Symbol *src = &n->v[chunk_idx]; - RDI_Procedure *dst = &procedures[dst_idx]; - dst->name_string_idx = rdim_bake_idx_from_string(strings, src->name); - dst->link_name_string_idx = rdim_bake_idx_from_string(strings, src->link_name); - if(src->is_extern) - { - dst->link_flags |= RDI_LinkFlag_External; - } - if(src->container_type != 0) - { - dst->link_flags |= RDI_LinkFlag_TypeScoped; - dst->container_idx = src->container_type ? (RDI_U32)rdim_idx_from_udt(src->container_type->udt) : 0; // TODO(rjf): @u64_to_u32 - } - else if(src->container_symbol != 0) - { - dst->link_flags |= RDI_LinkFlag_ProcScoped; - dst->container_idx = (RDI_U32)rdim_idx_from_symbol(src->container_symbol); // TODO(rjf): @u64_to_u32 - } - dst->type_idx = (RDI_U32)rdim_idx_from_type(src->type); // TODO(rjf): @u64_to_u32 - dst->root_scope_idx = (RDI_U32)rdim_idx_from_scope(src->root_scope); // TODO(rjf): @u64_to_u32 - } - } - RDIM_ProcedureBakeResult result = {0}; - result.procedures = procedures; - result.procedures_count = src->total_count+1; - return result; -} - -RDI_PROC RDIM_ScopeBakeResult -rdim_bake_scopes(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_ScopeChunkList *src) -{ - RDIM_Temp scratch = rdim_scratch_begin(&arena, 1); - - //////////////////////////// - //- rjf: build all scopes, scope voffs, locals, and location blocks - // - RDI_Scope * scopes = rdim_push_array(arena, RDI_Scope, src->total_count+1); - RDI_U64 * scope_voffs = rdim_push_array(arena, RDI_U64, src->scope_voff_count+1); - RDI_Local * locals = rdim_push_array(arena, RDI_Local, src->local_count+1); - RDI_LocationBlock * location_blocks = rdim_push_array(arena, RDI_LocationBlock, src->location_count+1); - RDIM_String8List location_data_blobs = {0}; - RDIM_ProfScope("build all scopes, scope voffs, locals, and location blocks") - { - RDI_U64 dst_scope_idx = 1; - RDI_U64 dst_scope_voff_idx = 1; - RDI_U64 dst_local_idx = 1; - RDI_U64 dst_location_block_idx = 1; - for(RDIM_ScopeChunkNode *chunk_n = src->first; chunk_n != 0; chunk_n = chunk_n->next) - { - for(RDI_U64 chunk_idx = 0; chunk_idx < chunk_n->count; chunk_idx += 1, dst_scope_idx += 1) - { - RDIM_Scope *src_scope = &chunk_n->v[chunk_idx]; - RDI_Scope *dst_scope = &scopes[dst_scope_idx]; - - //- rjf: push scope's voffs - RDI_U64 voff_idx_first = dst_scope_voff_idx; - { - for(RDIM_Rng1U64Node *n = src_scope->voff_ranges.first; n != 0; n = n->next) - { - scope_voffs[dst_scope_voff_idx] = n->v.min; - dst_scope_voff_idx += 1; - scope_voffs[dst_scope_voff_idx] = n->v.max; - dst_scope_voff_idx += 1; - } - } - RDI_U64 voff_idx_opl = dst_scope_voff_idx; - - //- rjf: push locals - RDI_U64 local_idx_first = dst_local_idx; - for(RDIM_Local *src_local = src_scope->first_local; - src_local != 0; - src_local = src_local->next, dst_local_idx += 1) - { - //- rjf: push local's locations - RDI_U64 location_block_idx_first = dst_location_block_idx; - for(RDIM_LocationCase *loccase = src_local->locset.first_location_case; - loccase != 0; - loccase = loccase->next, dst_location_block_idx += 1) - { - // rjf: fill location block - RDI_LocationBlock *dst_locblock = &location_blocks[dst_location_block_idx]; - dst_locblock->scope_off_first = loccase->voff_range.min; - dst_locblock->scope_off_opl = loccase->voff_range.max; - dst_locblock->location_data_off = location_data_blobs.total_size; - - // rjf: serialize location into location data - RDIM_Location *src_location = loccase->location; - { - // rjf: nil location - if(src_location == 0) - { - rdim_str8_list_push_align(scratch.arena, &location_data_blobs, 8); - rdim_str8_list_push(scratch.arena, &location_data_blobs, rdim_str8_lit("\0")); - } - - // rjf: valid location - else switch(src_location->kind) - { - // rjf: catchall unsupported case - default: - { - rdim_str8_list_push_align(scratch.arena, &location_data_blobs, 8); - rdim_str8_list_push(scratch.arena, &location_data_blobs, rdim_str8_lit("\0")); - }break; - - // rjf: bytecode streams - case RDI_LocationKind_AddrBytecodeStream: - case RDI_LocationKind_ValBytecodeStream: - { - rdim_str8_list_push(scratch.arena, &location_data_blobs, rdim_str8_copy(scratch.arena, rdim_str8_struct(&src_location->kind))); - for(RDIM_EvalBytecodeOp *op_node = src_location->bytecode.first_op; - op_node != 0; - op_node = op_node->next) - { - RDI_U8 op_data[9]; - op_data[0] = op_node->op; - rdim_memcpy(op_data + 1, &op_node->p, op_node->p_size); - RDIM_String8 op_data_str = rdim_str8(op_data, 1 + op_node->p_size); - rdim_str8_list_push(scratch.arena, &location_data_blobs, rdim_str8_copy(scratch.arena, op_data_str)); - } - { - RDI_U64 data = 0; - RDIM_String8 data_str = rdim_str8((RDI_U8 *)&data, 1); - rdim_str8_list_push(scratch.arena, &location_data_blobs, rdim_str8_copy(scratch.arena, data_str)); - } - }break; - - // rjf: simple addr+off cases - case RDI_LocationKind_AddrRegPlusU16: - case RDI_LocationKind_AddrAddrRegPlusU16: - { - RDI_LocationRegPlusU16 loc = {0}; - loc.kind = src_location->kind; - loc.reg_code = src_location->reg_code; - loc.offset = src_location->offset; - rdim_str8_list_push(scratch.arena, &location_data_blobs, rdim_str8_copy(scratch.arena, rdim_str8_struct(&loc))); - }break; - - // rjf: register cases - case RDI_LocationKind_ValReg: - { - RDI_LocationReg loc = {0}; - loc.kind = src_location->kind; - loc.reg_code = src_location->reg_code; - rdim_str8_list_push(scratch.arena, &location_data_blobs, rdim_str8_copy(scratch.arena, rdim_str8_struct(&loc))); - }break; - } - } - } - RDI_U64 location_block_idx_opl = dst_location_block_idx; - - //- rjf: fill local - RDI_Local *dst_local = &locals[dst_local_idx]; - dst_local->kind = src_local->kind; - dst_local->name_string_idx = rdim_bake_idx_from_string(strings, src_local->name); - dst_local->type_idx = (RDI_U32)rdim_idx_from_type(src_local->type); // TODO(rjf): @u64_to_u32 - dst_local->location_first = (RDI_U32)location_block_idx_first; // TODO(rjf): @u64_to_u32 - dst_local->location_opl = (RDI_U32)location_block_idx_opl; // TODO(rjf): @u64_to_u32 - } - RDI_U64 local_idx_opl = dst_local_idx; - - //- rjf: fill scope - dst_scope->proc_idx = (RDI_U32)rdim_idx_from_symbol(src_scope->symbol); // TODO(rjf): @u64_to_u32 - dst_scope->parent_scope_idx = (RDI_U32)rdim_idx_from_scope(src_scope->parent_scope); // TODO(rjf): @u64_to_u32 - dst_scope->first_child_scope_idx = (RDI_U32)rdim_idx_from_scope(src_scope->first_child); // TODO(rjf): @u64_to_u32 - dst_scope->next_sibling_scope_idx = (RDI_U32)rdim_idx_from_scope(src_scope->next_sibling); // TODO(rjf): @u64_to_u32 - dst_scope->voff_range_first = (RDI_U32)voff_idx_first; // TODO(rjf): @u64_to_u32 - dst_scope->voff_range_opl = (RDI_U32)voff_idx_opl; // TODO(rjf): @u64_to_u32 - dst_scope->local_first = (RDI_U32)local_idx_first; // TODO(rjf): @u64_to_u32 - dst_scope->local_count = (RDI_U32)(local_idx_opl - local_idx_first); // TODO(rjf): @u64_to_u32 - dst_scope->inline_site_idx = (RDI_U32)rdim_idx_from_inline_site(src_scope->inline_site); // TODO(rjf): @u64_to_u32 - } - } - } - - //////////////////////////// - //- rjf: build flattened location data - // - RDIM_String8 location_data_blob = {0}; - RDIM_ProfScope("build flattened location data") - { - location_data_blob = rdim_str8_list_join(arena, &location_data_blobs, rdim_str8_lit("")); - } - - //////////////////////////// - //- rjf: fill result - // - RDIM_ScopeBakeResult result = {0}; - result.scopes = scopes; - result.scopes_count = src->total_count+1; - result.scope_voffs = scope_voffs; - result.scope_voffs_count = src->scope_voff_count+1; - result.locals = locals; - result.locals_count = src->local_count+1; - result.location_blocks = location_blocks; - result.location_blocks_count = src->location_count+1; - result.location_data = location_data_blob.str; - result.location_data_size = location_data_blob.size; - rdim_scratch_end(scratch); - return result; -} - -RDI_PROC RDIM_ScopeVMapBakeResult -rdim_bake_scope_vmap(RDIM_Arena *arena, RDIM_ScopeChunkList *src) -{ - RDIM_BakeVMap scope_vmap = {0}; - { - RDIM_Temp scratch = rdim_scratch_begin(&arena, 1); - - // rjf: allocate keys/markers - RDI_U64 marker_count = src->scope_voff_count; - RDIM_SortKey *keys = rdim_push_array_no_zero(scratch.arena, RDIM_SortKey, marker_count); - RDIM_VMapMarker *markers = rdim_push_array_no_zero(scratch.arena, RDIM_VMapMarker, marker_count); - - // rjf: fill - { - RDIM_SortKey *key_ptr = keys; - RDIM_VMapMarker *marker_ptr = markers; - for(RDIM_ScopeChunkNode *chunk_n = src->first; chunk_n != 0; chunk_n = chunk_n->next) - { - for(RDI_U64 chunk_idx = 0; chunk_idx < chunk_n->count; chunk_idx += 1) - { - RDIM_Scope *src_scope = &chunk_n->v[chunk_idx]; - RDI_U32 scope_idx = (RDI_U32)rdim_idx_from_scope(src_scope); // TODO(rjf): @u64_to_u32 - for(RDIM_Rng1U64Node *n = src_scope->voff_ranges.first; n != 0; n = n->next) - { - key_ptr->key = n->v.min; - key_ptr->val = marker_ptr; - marker_ptr->idx = scope_idx; - marker_ptr->begin_range = 1; - key_ptr += 1; - marker_ptr += 1; - - key_ptr->key = n->v.max; - key_ptr->val = marker_ptr; - marker_ptr->idx = scope_idx; - marker_ptr->begin_range = 0; - key_ptr += 1; - marker_ptr += 1; - } - } - } - } - - // rjf: produce vmap - scope_vmap = rdim_bake_vmap_from_markers(arena, markers, keys, marker_count); - rdim_scratch_end(scratch); - } - RDIM_ScopeVMapBakeResult result = {scope_vmap}; - return result; -} - -RDI_PROC RDIM_InlineSiteBakeResult -rdim_bake_inline_sites(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_InlineSiteChunkList *src) -{ - RDIM_InlineSiteBakeResult result = {0}; - { - result.inline_sites_count = src->total_count; - result.inline_sites = rdim_push_array(arena, RDI_InlineSite, result.inline_sites_count+1); - RDI_U64 dst_idx = 1; - for(RDIM_InlineSiteChunkNode *n = src->first; n != 0; n = n->next) - { - for(RDI_U64 chunk_idx = 0; chunk_idx < n->count; chunk_idx += 1, dst_idx += 1) - { - RDI_InlineSite *dst = &result.inline_sites[dst_idx]; - RDIM_InlineSite *src = &n->v[chunk_idx]; - dst->name_string_idx = rdim_bake_idx_from_string(strings, src->name); - dst->type_idx = (RDI_U32)rdim_idx_from_type(src->type); // TODO(rjf): @u64_to_u32 - dst->owner_type_idx = (RDI_U32)rdim_idx_from_type(src->owner); // TODO(rjf): @u64_to_u32 - dst->line_table_idx = (RDI_U32)rdim_idx_from_line_table(src->line_table); // TODO(rjf): @u64_to_u32 - } - } - } - return result; -} - -RDI_PROC RDIM_TopLevelNameMapBakeResult -rdim_bake_name_maps_top_level(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakeIdxRunMap *idx_runs, RDIM_BakeNameMap *name_maps[RDI_NameMapKind_COUNT]) -{ - RDI_NameMap *dst_maps = rdim_push_array(arena, RDI_NameMap, RDI_NameMapKind_COUNT); - { - RDI_U64 dst_map_bucket_idx = 0; - RDI_U64 dst_map_node_idx = 0; - for(RDI_NameMapKind k = (RDI_NameMapKind)(RDI_NameMapKind_NULL+1); - k < RDI_NameMapKind_COUNT; - k = (RDI_NameMapKind)(k+1)) - { - RDI_NameMap *dst_map = &dst_maps[k]; - RDIM_BakeNameMap *src_map = name_maps[k]; - dst_map->bucket_base_idx = (RDI_U32)dst_map_bucket_idx; // TODO(rjf): @u64_to_u32 - dst_map->node_base_idx = (RDI_U32)dst_map_node_idx; // TODO(rjf): @u64_to_u32 - dst_map->bucket_count = (RDI_U32)src_map->name_count; // TODO(rjf): @u64_to_u32 - dst_map->node_count = (RDI_U32)src_map->name_count; // TODO(rjf): @u64_to_u32 - dst_map_bucket_idx += dst_map->bucket_count; - dst_map_node_idx += dst_map->node_count; - } - } - RDIM_TopLevelNameMapBakeResult result = {0}; - result.name_maps = dst_maps; - result.name_maps_count = RDI_NameMapKind_COUNT; - return result; -} - -RDI_PROC RDIM_FilePathBakeResult -rdim_bake_file_paths(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakePathTree *path_tree) -{ - RDI_U32 dst_nodes_count = path_tree->count; - RDI_FilePathNode *dst_nodes = rdim_push_array(arena, RDI_FilePathNode, dst_nodes_count); - { - RDI_U32 dst_node_idx = 0; - for(RDIM_BakePathNode *src_node = path_tree->first; - src_node != 0; - src_node = src_node->next_order, dst_node_idx += 1) - { - RDI_FilePathNode *dst_node = &dst_nodes[dst_node_idx]; - dst_node->name_string_idx = rdim_bake_idx_from_string(strings, src_node->name); - dst_node->source_file_idx = rdim_idx_from_src_file(src_node->src_file); - if(src_node->parent != 0) - { - dst_node->parent_path_node = src_node->parent->idx; - } - if(src_node->first_child != 0) - { - dst_node->first_child = src_node->first_child->idx; - } - if(src_node->next_sibling != 0) - { - dst_node->next_sibling = src_node->next_sibling->idx; - } - } - } - RDIM_FilePathBakeResult result = {0}; - result.nodes = dst_nodes; - result.nodes_count = dst_nodes_count; - return result; -} - -RDI_PROC RDIM_StringBakeResult -rdim_bake_strings(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings) -{ - RDIM_BakeSectionList sections = {0}; - RDI_U32 *str_offs = rdim_push_array_no_zero(arena, RDI_U32, strings->total_count + 1); - RDI_U32 off_cursor = 0; - { - RDI_U32 *off_ptr = str_offs; - *off_ptr = 0; - off_ptr += 1; - for(RDI_U64 slot_idx = 0; slot_idx < strings->slots_count; slot_idx += 1) - { - for(RDIM_BakeStringChunkNode *n = strings->slots[slot_idx].first; n != 0; n = n->next) - { - for(RDI_U64 chunk_idx = 0; chunk_idx < n->count; chunk_idx += 1) - { - RDIM_BakeString *bake_string = &n->v[chunk_idx]; - *off_ptr = off_cursor; - off_cursor += bake_string->string.size; - off_ptr += 1; - } - } - } - } - RDI_U8 *buf = rdim_push_array(arena, RDI_U8, off_cursor); - { - RDI_U8 *ptr = buf; - for(RDI_U64 slot_idx = 0; slot_idx < strings->slots_count; slot_idx += 1) - { - for(RDIM_BakeStringChunkNode *n = strings->slots[slot_idx].first; n != 0; n = n->next) - { - for(RDI_U64 chunk_idx = 0; chunk_idx < n->count; chunk_idx += 1) - { - RDIM_BakeString *bake_string = &n->v[chunk_idx]; - rdim_memcpy(ptr, bake_string->string.str, bake_string->string.size); - ptr += bake_string->string.size; - } - } - } - } - RDIM_StringBakeResult result = {0}; - result.string_offs = str_offs; - result.string_offs_count = strings->total_count+1; - result.string_data = buf; - result.string_data_size = off_cursor; - return result; -} - -RDI_PROC RDIM_IndexRunBakeResult -rdim_bake_index_runs(RDIM_Arena *arena, RDIM_BakeIdxRunMap *idx_runs) -{ - RDI_U32 *idx_data = rdim_push_array_no_zero(arena, RDI_U32, idx_runs->idx_count); - { - RDI_U32 *out_ptr = idx_data; - RDI_U32 *opl = out_ptr + idx_runs->idx_count; - for(RDIM_BakeIdxRunNode *node = idx_runs->order_first; - node != 0 && out_ptr < opl; - node = node->order_next) - { - rdim_memcpy(out_ptr, node->idx_run, sizeof(*node->idx_run)*node->count); - out_ptr += node->count; - } - } - RDIM_IndexRunBakeResult result = {0}; - result.idx_runs = idx_data; - result.idx_count = idx_runs->idx_count; - return result; -} - -//////////////////////////////// -//~ rjf: [Serializing] Bake Results -> String Blobs - -RDI_PROC RDIM_SerializedSection -rdim_serialized_section_make_unpacked(void *data, RDI_U64 size) -{ - RDIM_SerializedSection s; - rdim_memzero_struct(&s); - s.data = data; - s.encoded_size = s.unpacked_size = size; - s.encoding = RDI_SectionEncoding_Unpacked; - return s; -} - -RDI_PROC RDIM_SerializedSectionBundle -rdim_serialized_section_bundle_from_bake_results(RDIM_BakeResults *results) -{ - RDIM_SerializedSectionBundle bundle; - rdim_memzero_struct(&bundle); - bundle.sections[RDI_SectionKind_TopLevelInfo] = rdim_serialized_section_make_unpacked_struct(results->top_level_info.top_level_info); - bundle.sections[RDI_SectionKind_StringData] = rdim_serialized_section_make_unpacked_array(results->strings.string_data, results->strings.string_data_size); - bundle.sections[RDI_SectionKind_StringTable] = rdim_serialized_section_make_unpacked_array(results->strings.string_offs, results->strings.string_offs_count); - bundle.sections[RDI_SectionKind_IndexRuns] = rdim_serialized_section_make_unpacked_array(results->idx_runs.idx_runs, results->idx_runs.idx_count); - bundle.sections[RDI_SectionKind_BinarySections] = rdim_serialized_section_make_unpacked_array(results->binary_sections.binary_sections, results->binary_sections.binary_sections_count); - bundle.sections[RDI_SectionKind_FilePathNodes] = rdim_serialized_section_make_unpacked_array(results->file_paths.nodes, results->file_paths.nodes_count); - bundle.sections[RDI_SectionKind_SourceFiles] = rdim_serialized_section_make_unpacked_array(results->src_files.source_files, results->src_files.source_files_count); - bundle.sections[RDI_SectionKind_LineTables] = rdim_serialized_section_make_unpacked_array(results->line_tables.line_tables, results->line_tables.line_tables_count); - bundle.sections[RDI_SectionKind_LineInfoVOffs] = rdim_serialized_section_make_unpacked_array(results->line_tables.line_table_voffs, results->line_tables.line_table_voffs_count); - bundle.sections[RDI_SectionKind_LineInfoLines] = rdim_serialized_section_make_unpacked_array(results->line_tables.line_table_lines, results->line_tables.line_table_lines_count); - bundle.sections[RDI_SectionKind_LineInfoColumns] = rdim_serialized_section_make_unpacked_array(results->line_tables.line_table_columns, results->line_tables.line_table_columns_count); - bundle.sections[RDI_SectionKind_SourceLineMaps] = rdim_serialized_section_make_unpacked_array(results->src_files.source_line_maps, results->src_files.source_line_maps_count); - bundle.sections[RDI_SectionKind_SourceLineMapNumbers] = rdim_serialized_section_make_unpacked_array(results->src_files.source_line_map_nums, results->src_files.source_line_map_nums_count); - bundle.sections[RDI_SectionKind_SourceLineMapRanges] = rdim_serialized_section_make_unpacked_array(results->src_files.source_line_map_rngs, results->src_files.source_line_map_rngs_count); - bundle.sections[RDI_SectionKind_SourceLineMapVOffs] = rdim_serialized_section_make_unpacked_array(results->src_files.source_line_map_voffs, results->src_files.source_line_map_voffs_count); - bundle.sections[RDI_SectionKind_Units] = rdim_serialized_section_make_unpacked_array(results->units.units, results->units.units_count); - bundle.sections[RDI_SectionKind_UnitVMap] = rdim_serialized_section_make_unpacked_array(results->unit_vmap.vmap.vmap, results->unit_vmap.vmap.count+1); - bundle.sections[RDI_SectionKind_TypeNodes] = rdim_serialized_section_make_unpacked_array(results->type_nodes.type_nodes, results->type_nodes.type_nodes_count); - bundle.sections[RDI_SectionKind_UDTs] = rdim_serialized_section_make_unpacked_array(results->udts.udts, results->udts.udts_count); - bundle.sections[RDI_SectionKind_Members] = rdim_serialized_section_make_unpacked_array(results->udts.members, results->udts.members_count); - bundle.sections[RDI_SectionKind_EnumMembers] = rdim_serialized_section_make_unpacked_array(results->udts.enum_members, results->udts.enum_members_count); - bundle.sections[RDI_SectionKind_GlobalVariables] = rdim_serialized_section_make_unpacked_array(results->global_variables.global_variables, results->global_variables.global_variables_count); - bundle.sections[RDI_SectionKind_GlobalVMap] = rdim_serialized_section_make_unpacked_array(results->global_vmap.vmap.vmap, results->global_vmap.vmap.count+1); - bundle.sections[RDI_SectionKind_ThreadVariables] = rdim_serialized_section_make_unpacked_array(results->thread_variables.thread_variables, results->thread_variables.thread_variables_count); - bundle.sections[RDI_SectionKind_Procedures] = rdim_serialized_section_make_unpacked_array(results->procedures.procedures, results->procedures.procedures_count); - bundle.sections[RDI_SectionKind_Scopes] = rdim_serialized_section_make_unpacked_array(results->scopes.scopes, results->scopes.scopes_count); - bundle.sections[RDI_SectionKind_ScopeVOffData] = rdim_serialized_section_make_unpacked_array(results->scopes.scope_voffs, results->scopes.scope_voffs_count); - bundle.sections[RDI_SectionKind_ScopeVMap] = rdim_serialized_section_make_unpacked_array(results->scope_vmap.vmap.vmap, results->scope_vmap.vmap.count+1); - bundle.sections[RDI_SectionKind_InlineSites] = rdim_serialized_section_make_unpacked_array(results->inline_sites.inline_sites, results->inline_sites.inline_sites_count); - bundle.sections[RDI_SectionKind_Locals] = rdim_serialized_section_make_unpacked_array(results->scopes.locals, results->scopes.locals_count); - bundle.sections[RDI_SectionKind_LocationBlocks] = rdim_serialized_section_make_unpacked_array(results->scopes.location_blocks, results->scopes.location_blocks_count); - bundle.sections[RDI_SectionKind_LocationData] = rdim_serialized_section_make_unpacked_array(results->scopes.location_data, results->scopes.location_data_size); - bundle.sections[RDI_SectionKind_NameMaps] = rdim_serialized_section_make_unpacked_array(results->top_level_name_maps.name_maps, results->top_level_name_maps.name_maps_count); - bundle.sections[RDI_SectionKind_NameMapBuckets] = rdim_serialized_section_make_unpacked_array(results->name_maps.buckets, results->name_maps.buckets_count); - bundle.sections[RDI_SectionKind_NameMapNodes] = rdim_serialized_section_make_unpacked_array(results->name_maps.nodes, results->name_maps.nodes_count); - return bundle; -} - -RDI_PROC RDIM_String8List -rdim_file_blobs_from_section_bundle(RDIM_Arena *arena, RDIM_SerializedSectionBundle *bundle) -{ - RDIM_String8List strings; - rdim_memzero_struct(&strings); - { - RDIM_Temp scratch = rdim_scratch_begin(&arena, 1); - - // rjf: push empty header & data section table - RDI_Header *rdi_header = rdim_push_array(arena, RDI_Header, 1); - RDI_Section *rdi_sections = rdim_push_array(arena, RDI_Section, RDI_SectionKind_COUNT); - rdim_str8_list_push(arena, &strings, rdim_str8_struct(rdi_header)); - rdim_str8_list_push_align(arena, &strings, 8); - U32 data_section_off = (U32)strings.total_size; - rdim_str8_list_push(arena, &strings, rdim_str8((RDI_U8 *)rdi_sections, sizeof(RDI_Section)*RDI_SectionKind_COUNT)); - - // rjf: fill baked header - { - rdi_header->magic = RDI_MAGIC_CONSTANT; - rdi_header->encoding_version = RDI_ENCODING_VERSION; - rdi_header->data_section_off = data_section_off; - rdi_header->data_section_count = RDI_SectionKind_COUNT; - } - - // rjf: fill baked data section table - for(RDI_SectionKind k = RDI_SectionKind_NULL; k < RDI_SectionKind_COUNT; k += 1) - { - RDI_Section *dst = rdi_sections+k; - U64 data_section_off = 0; - if(bundle->sections[k].encoded_size != 0) - { - rdim_str8_list_push_align(arena, &strings, 8); - data_section_off = strings.total_size; - rdim_str8_list_push(arena, &strings, rdim_str8((RDI_U8 *)bundle->sections[k].data, bundle->sections[k].encoded_size)); - } - dst->encoding = bundle->sections[k].encoding; - dst->off = data_section_off; - dst->encoded_size = bundle->sections[k].encoded_size; - dst->unpacked_size = bundle->sections[k].unpacked_size; - } - - rdim_scratch_end(scratch); - } - return strings; -} +// Copyright (c) 2024 Epic Games Tools +// Licensed under the MIT license (https://opensource.org/license/mit/) + +//////////////////////////////// +//~ rjf: API Implementation Helper Macros + +#define rdim_require(root, b32, else_code, error_msg) do { if(!(b32)) {rdim_push_msg((root), (error_msg)); else_code;} }while(0) +#define rdim_requiref(root, b32, else_code, fmt, ...) do { if(!(b32)) {rdim_push_msgf((root), (fmt), __VA_ARGS__); else_code;} }while(0) + +//////////////////////////////// +//~ rjf: Basic Helpers + +//- rjf: memory set + +#if !defined(RDIM_MEMSET_OVERRIDE) +RDI_PROC void * +rdim_memset_fallback(void *dst, RDI_U8 c, RDI_U64 size) +{ + for(RDI_U64 idx = 0; idx < size; idx += 1) + { + ((RDI_U8 *)dst)[idx] = c; + } + return dst; +} +#endif + +#if !defined(RDIM_MEMCPY_OVERRIDE) +RDI_PROC void * +rdim_memcpy_fallback(void *dst, void *src, RDI_U64 size) +{ + for(RDI_U64 idx = 0; idx < size; idx += 1) + { + ((RDI_U8 *)dst)[idx] = ((RDI_U8 *)src)[idx]; + } + return dst; +} +#endif + +//- rjf: arenas + +#if !defined (RDIM_ARENA_OVERRIDE) + +RDI_PROC RDIM_Arena * +rdim_arena_alloc_fallback(void) +{ + RDIM_Arena *arena = 0; + // TODO(rjf) + return arena; +} + +RDI_PROC void +rdim_arena_release_fallback(RDIM_Arena *arena) +{ + // TODO(rjf) +} + +RDI_PROC RDI_U64 +rdim_arena_pos_fallback(RDIM_Arena *arena) +{ + // TODO(rjf) + return 0; +} + +RDI_PROC void * +rdim_arena_push_fallback(RDIM_Arena *arena, RDI_U64 size) +{ + // TODO(rjf) + return 0; +} + +RDI_PROC void +rdim_arena_pop_to_fallback(RDIM_Arena *arena, RDI_U64 pos) +{ + // TODO(rjf) +} + +#endif + +//- rjf: thread-local scratch arenas + +#if !defined (RDIM_SCRATCH_OVERRIDE) +static RDIM_THREAD_LOCAL RDIM_Arena *rdim_thread_scratches[2]; + +RDI_PROC RDIM_Temp +rdim_scratch_begin_fallback(RDIM_Arena **conflicts, RDI_U64 conflicts_count) +{ + if(rdim_thread_scratches[0] == 0) + { + rdim_thread_scratches[0] = rdim_arena_alloc(); + rdim_thread_scratches[1] = rdim_arena_alloc(); + } + RDIM_Arena *arena = 0; + for(RDI_U64 scratch_idx = 0; + scratch_idx < sizeof(rdim_thread_scratches)/sizeof(rdim_thread_scratches[0]); + scratch_idx += 1) + { + RDI_S32 scratch_conflicts = 0; + for(RDI_U64 conflict_idx = 0; conflict_idx < conflicts_count; conflict_idx += 1) + { + if(conflicts[conflict_idx] == rdim_thread_scratches[scratch_idx]) + { + scratch_conflicts = 1; + break; + } + } + if(!scratch_conflicts) + { + arena = rdim_thread_scratches[scratch_idx]; + } + } + RDIM_Temp temp; + temp.arena = arena; + temp.pos = rdim_arena_pos(arena); + return temp; +} + +RDI_PROC void +rdim_scratch_end_fallback(RDIM_Temp temp) +{ + rdim_arena_pop_to(temp.arena, temp.pos); +} + +#endif + +//- rjf: strings + +RDI_PROC RDIM_String8 +rdim_str8(RDI_U8 *str, RDI_U64 size) +{ + RDIM_String8 result; + result.RDIM_String8_BaseMember = str; + result.RDIM_String8_SizeMember = size; + return result; +} + +RDI_PROC RDIM_String8 +rdim_str8_copy(RDIM_Arena *arena, RDIM_String8 src) +{ + RDIM_String8 dst; + dst.RDIM_String8_SizeMember = src.RDIM_String8_SizeMember; + dst.RDIM_String8_BaseMember = rdim_push_array_no_zero(arena, RDI_U8, dst.RDIM_String8_SizeMember+1); + rdim_memcpy(dst.RDIM_String8_BaseMember, src.RDIM_String8_BaseMember, src.RDIM_String8_SizeMember); + dst.RDIM_String8_BaseMember[dst.RDIM_String8_SizeMember] = 0; + return dst; +} + +RDI_PROC RDIM_String8 +rdim_str8f(RDIM_Arena *arena, char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + RDIM_String8 result = rdim_str8fv(arena, fmt, args); + va_end(args); + return(result); +} + +RDI_PROC RDIM_String8 +rdim_str8fv(RDIM_Arena *arena, char *fmt, va_list args) +{ + va_list args2; + va_copy(args2, args); + RDI_U32 needed_bytes = rdim_vsnprintf(0, 0, fmt, args) + 1; + RDIM_String8 result = {0}; + result.RDIM_String8_BaseMember = rdim_push_array_no_zero(arena, RDI_U8, needed_bytes); + result.RDIM_String8_SizeMember = rdim_vsnprintf((char*)result.str, needed_bytes, fmt, args2); + result.RDIM_String8_BaseMember[result.RDIM_String8_SizeMember] = 0; + va_end(args2); + return(result); +} + +RDI_PROC RDI_S32 +rdim_str8_match(RDIM_String8 a, RDIM_String8 b, RDIM_StringMatchFlags flags) +{ + RDI_S32 result = 0; + if(a.RDIM_String8_SizeMember == b.RDIM_String8_SizeMember) + { + RDI_S32 case_insensitive = (flags & RDIM_StringMatchFlag_CaseInsensitive); + RDI_U64 size = a.RDIM_String8_SizeMember; + result = 1; + for(RDI_U64 idx = 0; idx < size; idx += 1) + { + RDI_U8 at = a.RDIM_String8_BaseMember[idx]; + RDI_U8 bt = b.RDIM_String8_BaseMember[idx]; + if(case_insensitive) + { + at = ('a' <= at && at <= 'z') ? at-('a'-'A') : at; + bt = ('a' <= bt && bt <= 'z') ? bt-('a'-'A') : bt; + } + if(at != bt) + { + result = 0; + break; + } + } + } + return result; +} + +//- rjf: string lists + +RDI_PROC void +rdim_str8_list_push(RDIM_Arena *arena, RDIM_String8List *list, RDIM_String8 string) +{ + RDIM_String8Node *n = rdim_push_array(arena, RDIM_String8Node, 1); + n->RDIM_String8Node_StringMember = string; + RDIM_SLLQueuePush_N(list->RDIM_String8List_FirstMember, list->RDIM_String8List_LastMember, n, RDIM_String8Node_NextPtrMember); + list->RDIM_String8List_NodeCountMember += 1; + list->RDIM_String8List_TotalSizeMember += string.RDIM_String8_SizeMember; +} + +RDI_PROC void +rdim_str8_list_push_front(RDIM_Arena *arena, RDIM_String8List *list, RDIM_String8 string) +{ + RDIM_String8Node *n = rdim_push_array(arena, RDIM_String8Node, 1); + n->RDIM_String8Node_StringMember = string; + RDIM_SLLQueuePushFront_N(list->RDIM_String8List_FirstMember, list->RDIM_String8List_LastMember, n, RDIM_String8Node_NextPtrMember); + list->RDIM_String8List_NodeCountMember += 1; + list->RDIM_String8List_TotalSizeMember += string.RDIM_String8_SizeMember; +} + +RDI_PROC void +rdim_str8_list_push_align(RDIM_Arena *arena, RDIM_String8List *list, RDI_U64 align) +{ + RDI_U64 total_size_pre_align = list->total_size; + RDI_U64 total_size_post_align = (total_size_pre_align + (align-1))&(~(align-1)); + RDI_U64 needed_size = total_size_post_align - total_size_pre_align; + if(needed_size != 0) + { + RDI_U8 *padding = rdim_push_array(arena, RDI_U8, needed_size); + rdim_str8_list_push(arena, list, rdim_str8(padding, needed_size)); + } +} + +RDI_PROC RDIM_String8 +rdim_str8_list_join(RDIM_Arena *arena, RDIM_String8List *list, RDIM_String8 sep) +{ + RDIM_String8 result; + rdim_memzero_struct(&result); + RDI_U64 sep_count = (list->RDIM_String8List_NodeCountMember > 1) ? (list->RDIM_String8List_NodeCountMember-1) : 0; + result.RDIM_String8_SizeMember = list->RDIM_String8List_TotalSizeMember+sep_count*sep.RDIM_String8_SizeMember; + result.RDIM_String8_BaseMember = rdim_push_array_no_zero(arena, RDI_U8, result.RDIM_String8_SizeMember+1); + RDI_U64 off = 0; + for(RDIM_String8Node *node = list->RDIM_String8List_FirstMember; + node != 0; + node = node->RDIM_String8Node_NextPtrMember) + { + rdim_memcpy((RDI_U8*)result.RDIM_String8_BaseMember+off, + node->RDIM_String8Node_StringMember.RDIM_String8_BaseMember, + node->RDIM_String8Node_StringMember.RDIM_String8_SizeMember); + off += node->RDIM_String8Node_StringMember.RDIM_String8_SizeMember; + if(sep.RDIM_String8_SizeMember != 0 && node->RDIM_String8Node_NextPtrMember != 0) + { + rdim_memcpy((RDI_U8*)result.RDIM_String8_BaseMember+off, + sep.RDIM_String8_BaseMember, + sep.RDIM_String8_SizeMember); + off += sep.RDIM_String8_SizeMember; + } + } + result.RDIM_String8_BaseMember[off] = 0; + return result; +} + +//- rjf: sortable range sorting + +RDI_PROC RDIM_SortKey * +rdim_sort_key_array(RDIM_Arena *arena, RDIM_SortKey *keys, RDI_U64 count) +{ + // This sort is designed to take advantage of lots of pre-existing sorted ranges. + // Most line info is already sorted or close to already sorted. + // Similarly most vmap data has lots of pre-sorted ranges. etc. etc. + // Also - this sort should be a "stable" sort. In the use case of sorting vmap + // ranges, we want to be able to rely on order, so it needs to be preserved here. + + RDIM_Temp scratch = rdim_scratch_begin(&arena, 1); + RDIM_SortKey *result = 0; + + if(count <= 1) + { + result = keys; + } + else + { + RDIM_OrderedRange *ranges_first = 0; + RDIM_OrderedRange *ranges_last = 0; + RDI_U64 range_count = 0; + { + RDI_U64 pos = 0; + for(;pos < count;) + { + // identify ordered range + RDI_U64 first = pos; + RDI_U64 opl = pos + 1; + for(; opl < count && keys[opl - 1].key <= keys[opl].key; opl += 1); + + // generate an ordered range node + RDIM_OrderedRange *new_range = rdim_push_array(rdim_temp_arena(scratch), RDIM_OrderedRange, 1); + SLLQueuePush(ranges_first, ranges_last, new_range); + range_count += 1; + new_range->first = first; + new_range->opl = opl; + + // update pos + pos = opl; + } + } + + if(range_count == 1) + { + result = keys; + } + else + { + RDIM_SortKey *keys_swap = rdim_push_array_no_zero(arena, RDIM_SortKey, count); + RDIM_SortKey *src = keys; + RDIM_SortKey *dst = keys_swap; + RDIM_OrderedRange *src_ranges = ranges_first; + RDIM_OrderedRange *dst_ranges = 0; + RDIM_OrderedRange *dst_ranges_last = 0; + + for(;;) + { + // begin a pass + for(;;) + { + // end pass when out of ranges + if(src_ranges == 0) + { + break; + } + + // get first range + RDIM_OrderedRange *range1 = src_ranges; + SLLStackPop(src_ranges); + + // if this range is the whole array, we are done + if(range1->first == 0 && range1->opl == count) + { + result = src; + goto sort_done; + } + + // if there is not a second range, save this range for next time and end this pass + if(src_ranges == 0) + { + RDI_U64 first = range1->first; + rdim_memcpy(dst + first, src + first, sizeof(*src)*(range1->opl - first)); + SLLQueuePush(dst_ranges, dst_ranges_last, range1); + break; + } + + // get second range + RDIM_OrderedRange *range2 = src_ranges; + SLLStackPop(src_ranges); + + rdim_assert(range1->opl == range2->first); + + // merge these ranges + RDI_U64 jd = range1->first; + RDI_U64 j1 = range1->first; + RDI_U64 j1_opl = range1->opl; + RDI_U64 j2 = range2->first; + RDI_U64 j2_opl = range2->opl; + for(;;) + { + if(src[j1].key <= src[j2].key) + { + rdim_memcpy(dst + jd, src + j1, sizeof(*src)); + j1 += 1; + jd += 1; + if(j1 >= j1_opl) + { + break; + } + } + else + { + rdim_memcpy(dst + jd, src + j2, sizeof(*src)); + j2 += 1; + jd += 1; + if(j2 >= j2_opl) + { + break; + } + } + } + if(j1 < j1_opl) + { + rdim_memcpy(dst + jd, src + j1, sizeof(*src)*(j1_opl - j1)); + } + else + { + rdim_memcpy(dst + jd, src + j2, sizeof(*src)*(j2_opl - j2)); + } + + // save this as one range + range1->opl = range2->opl; + SLLQueuePush(dst_ranges, dst_ranges_last, range1); + } + + // end pass by swapping buffers and range nodes + { + RDIM_SortKey *temp = src; + src = dst; + dst = temp; + } + src_ranges = dst_ranges; + dst_ranges = 0; + dst_ranges_last = 0; + } + } + } + sort_done:; + +#if 0 + // assert sortedness + for(RDI_U64 i = 1; i < count; i += 1) + { + rdim_assert(result[i - 1].key <= result[i].key); + } +#endif + + scratch_end(scratch); + return result; +} + +//- rjf: rng1u64 list + +RDI_PROC void +rdim_rng1u64_list_push(RDIM_Arena *arena, RDIM_Rng1U64List *list, RDIM_Rng1U64 r) +{ + RDIM_Rng1U64Node *n = rdim_push_array(arena, RDIM_Rng1U64Node, 1); + n->v = r; + RDIM_SLLQueuePush(list->first, list->last, n); + list->count += 1; + if(list->count == 1 || r.min < list->min) + { + list->min = r.min; + } +} + +//////////////////////////////// +//~ rjf: [Building] Binary Section List Building + +RDI_PROC RDIM_BinarySection * +rdim_binary_section_list_push(RDIM_Arena *arena, RDIM_BinarySectionList *list) +{ + RDIM_BinarySectionNode *n = rdim_push_array(arena, RDIM_BinarySectionNode, 1); + RDIM_SLLQueuePush(list->first, list->last, n); + list->count += 1; + RDIM_BinarySection *result = &n->v; + return result; +} + +//////////////////////////////// +//~ rjf: [Building] Source File Info Building + +RDI_PROC RDIM_SrcFile * +rdim_src_file_chunk_list_push(RDIM_Arena *arena, RDIM_SrcFileChunkList *list, RDI_U64 cap) +{ + RDIM_SrcFileChunkNode *n = list->last; + if(n == 0 || n->count >= n->cap) + { + n = rdim_push_array(arena, RDIM_SrcFileChunkNode, 1); + n->cap = cap; + n->base_idx = list->total_count; + n->v = rdim_push_array(arena, RDIM_SrcFile, n->cap); + RDIM_SLLQueuePush(list->first, list->last, n); + list->chunk_count += 1; + } + RDIM_SrcFile *src_file = &n->v[n->count]; + src_file->chunk = n; + n->count += 1; + list->total_count += 1; + return src_file; +} + +RDI_PROC RDI_U64 +rdim_idx_from_src_file(RDIM_SrcFile *src_file) +{ + RDI_U64 idx = 0; + if(src_file != 0 && src_file->chunk != 0) + { + idx = (src_file->chunk->base_idx + (src_file - src_file->chunk->v) + 1); + } + return idx; +} + +RDI_PROC void +rdim_src_file_chunk_list_concat_in_place(RDIM_SrcFileChunkList *dst, RDIM_SrcFileChunkList *to_push) +{ + for(RDIM_SrcFileChunkNode *n = to_push->first; n != 0; n = n->next) + { + n->base_idx += dst->total_count; + } + if(dst->last != 0 && to_push->first != 0) + { + dst->last->next = to_push->first; + dst->last = to_push->last; + dst->chunk_count += to_push->chunk_count; + dst->total_count += to_push->total_count; + } + else if(dst->first == 0) + { + rdim_memcpy_struct(dst, to_push); + } + rdim_memzero_struct(to_push); +} + +RDI_PROC void +rdim_src_file_push_line_sequence(RDIM_Arena *arena, RDIM_SrcFileChunkList *src_files, RDIM_SrcFile *src_file, RDIM_LineSequence *seq) +{ + if(src_file->first_line_map_fragment == 0) + { + src_files->source_line_map_count += 1; + } + RDIM_SrcFileLineMapFragment *fragment = rdim_push_array(arena, RDIM_SrcFileLineMapFragment, 1); + fragment->seq = seq; + RDIM_SLLQueuePush(src_file->first_line_map_fragment, src_file->last_line_map_fragment, fragment); + src_files->total_line_count += seq->line_count; +} + +//////////////////////////////// +//~ rjf: [Building] Line Info Building + +RDI_PROC RDIM_LineTable * +rdim_line_table_chunk_list_push(RDIM_Arena *arena, RDIM_LineTableChunkList *list, RDI_U64 cap) +{ + RDIM_LineTableChunkNode *n = list->last; + if(n == 0 || n->count >= n->cap) + { + n = rdim_push_array(arena, RDIM_LineTableChunkNode, 1); + n->cap = cap; + n->base_idx = list->total_count; + n->v = rdim_push_array(arena, RDIM_LineTable, n->cap); + RDIM_SLLQueuePush(list->first, list->last, n); + list->chunk_count += 1; + } + RDIM_LineTable *line_table = &n->v[n->count]; + line_table->chunk = n; + n->count += 1; + list->total_count += 1; + return line_table; +} + +RDI_PROC RDI_U64 +rdim_idx_from_line_table(RDIM_LineTable *line_table) +{ + RDI_U64 idx = 0; + if(line_table != 0 && line_table->chunk != 0) + { + idx = line_table->chunk->base_idx + (line_table - line_table->chunk->v) + 1; + } + return idx; +} + +RDI_PROC void +rdim_line_table_chunk_list_concat_in_place(RDIM_LineTableChunkList *dst, RDIM_LineTableChunkList *to_push) +{ + for(RDIM_LineTableChunkNode *n = to_push->first; n != 0; n = n->next) + { + n->base_idx += dst->total_count; + } + if(dst->last != 0 && to_push->first != 0) + { + dst->last->next = to_push->first; + dst->last = to_push->last; + dst->chunk_count += to_push->chunk_count; + dst->total_count += to_push->total_count; + dst->total_line_count += to_push->total_line_count; + } + else if(dst->first == 0) + { + rdim_memcpy_struct(dst, to_push); + } + rdim_memzero_struct(to_push); +} + +RDI_PROC RDIM_LineSequence * +rdim_line_table_push_sequence(RDIM_Arena *arena, RDIM_LineTableChunkList *line_tables, RDIM_LineTable *line_table, RDIM_SrcFile *src_file, RDI_U64 *voffs, RDI_U32 *line_nums, RDI_U16 *col_nums, RDI_U64 line_count) +{ + RDIM_LineSequenceNode *n = push_array(arena, RDIM_LineSequenceNode, 1); + n->v.src_file = src_file; + n->v.voffs = voffs; + n->v.line_nums = line_nums; + n->v.col_nums = col_nums; + n->v.line_count = line_count; + SLLQueuePush(line_table->first_seq, line_table->last_seq, n); + line_table->seq_count += 1; + line_table->line_count += line_count; + line_table->col_count += line_count*2*(col_nums != 0); + line_tables->total_seq_count += 1; + line_tables->total_line_count += line_count; + line_tables->total_col_count += line_count*2*(col_nums != 0); + return &n->v; +} + +//////////////////////////////// +//~ rjf: [Building] Unit List Building + +RDI_PROC RDIM_Unit * +rdim_unit_chunk_list_push(RDIM_Arena *arena, RDIM_UnitChunkList *list, RDI_U64 cap) +{ + RDIM_UnitChunkNode *n = list->last; + if(n == 0 || n->count >= n->cap) + { + n = rdim_push_array(arena, RDIM_UnitChunkNode, 1); + n->cap = cap; + n->base_idx = list->total_count; + n->v = rdim_push_array(arena, RDIM_Unit, n->cap); + RDIM_SLLQueuePush(list->first, list->last, n); + list->chunk_count += 1; + } + RDIM_Unit *unit = &n->v[n->count]; + unit->chunk = n; + n->count += 1; + list->total_count += 1; + return unit; +} + +RDI_PROC RDI_U64 +rdim_idx_from_unit(RDIM_Unit *unit) +{ + RDI_U64 idx = 0; + if(unit != 0 && unit->chunk != 0) + { + idx = unit->chunk->base_idx + (unit - unit->chunk->v) + 1; + } + return idx; +} + +RDI_PROC void +rdim_unit_chunk_list_concat_in_place(RDIM_UnitChunkList *dst, RDIM_UnitChunkList *to_push) +{ + for(RDIM_UnitChunkNode *n = to_push->first; n != 0; n = n->next) + { + n->base_idx += dst->total_count; + } + if(dst->last != 0 && to_push->first != 0) + { + dst->last->next = to_push->first; + dst->last = to_push->last; + dst->chunk_count += to_push->chunk_count; + dst->total_count += to_push->total_count; + } + else if(dst->first == 0) + { + rdim_memcpy_struct(dst, to_push); + } + rdim_memzero_struct(to_push); +} + +//////////////////////////////// +//~ rjf: [Building] Type Info Building + +RDI_PROC RDIM_Type * +rdim_type_chunk_list_push(RDIM_Arena *arena, RDIM_TypeChunkList *list, RDI_U64 cap) +{ + RDIM_TypeChunkNode *n = list->last; + if(n == 0 || n->count >= n->cap) + { + n = rdim_push_array(arena, RDIM_TypeChunkNode, 1); + n->cap = cap; + n->base_idx = list->total_count; + n->v = rdim_push_array(arena, RDIM_Type, n->cap); + RDIM_SLLQueuePush(list->first, list->last, n); + list->chunk_count += 1; + } + RDIM_Type *result = &n->v[n->count]; + result->chunk = n; + n->count += 1; + list->total_count += 1; + return result; +} + +RDI_PROC RDI_U64 +rdim_idx_from_type(RDIM_Type *type) +{ + RDI_U64 idx = 0; + if(type != 0 && type->chunk != 0) + { + idx = type->chunk->base_idx + (type - type->chunk->v) + 1; + } + return idx; +} + +RDI_PROC void +rdim_type_chunk_list_concat_in_place(RDIM_TypeChunkList *dst, RDIM_TypeChunkList *to_push) +{ + for(RDIM_TypeChunkNode *n = to_push->first; n != 0; n = n->next) + { + n->base_idx += dst->total_count; + } + if(dst->last != 0 && to_push->first != 0) + { + dst->last->next = to_push->first; + dst->last = to_push->last; + dst->chunk_count += to_push->chunk_count; + dst->total_count += to_push->total_count; + } + else if(dst->first == 0) + { + rdim_memcpy_struct(dst, to_push); + } + rdim_memzero_struct(to_push); +} + +RDI_PROC RDIM_UDT * +rdim_udt_chunk_list_push(RDIM_Arena *arena, RDIM_UDTChunkList *list, RDI_U64 cap) +{ + RDIM_UDTChunkNode *n = list->last; + if(n == 0 || n->count >= n->cap) + { + n = rdim_push_array(arena, RDIM_UDTChunkNode, 1); + n->cap = cap; + n->base_idx = list->total_count; + n->v = rdim_push_array(arena, RDIM_UDT, n->cap); + RDIM_SLLQueuePush(list->first, list->last, n); + list->chunk_count += 1; + } + RDIM_UDT *result = &n->v[n->count]; + result->chunk = n; + n->count += 1; + list->total_count += 1; + return result; +} + +RDI_PROC RDI_U64 +rdim_idx_from_udt(RDIM_UDT *udt) +{ + RDI_U64 idx = 0; + if(udt != 0 && udt->chunk != 0) + { + idx = udt->chunk->base_idx + (udt - udt->chunk->v) + 1; + } + return idx; +} + +RDI_PROC void +rdim_udt_chunk_list_concat_in_place(RDIM_UDTChunkList *dst, RDIM_UDTChunkList *to_push) +{ + for(RDIM_UDTChunkNode *n = to_push->first; n != 0; n = n->next) + { + n->base_idx += dst->total_count; + } + if(dst->last != 0 && to_push->first != 0) + { + dst->last->next = to_push->first; + dst->last = to_push->last; + dst->chunk_count += to_push->chunk_count; + dst->total_count += to_push->total_count; + dst->total_member_count += to_push->total_member_count; + dst->total_enum_val_count += to_push->total_enum_val_count; + } + else if(dst->first == 0) + { + rdim_memcpy_struct(dst, to_push); + } + rdim_memzero_struct(to_push); +} + +RDI_PROC RDIM_UDTMember * +rdim_udt_push_member(RDIM_Arena *arena, RDIM_UDTChunkList *list, RDIM_UDT *udt) +{ + RDIM_UDTMember *mem = rdim_push_array(arena, RDIM_UDTMember, 1); + RDIM_SLLQueuePush(udt->first_member, udt->last_member, mem); + udt->member_count += 1; + list->total_member_count += 1; + return mem; +} + +RDI_PROC RDIM_UDTEnumVal * +rdim_udt_push_enum_val(RDIM_Arena *arena, RDIM_UDTChunkList *list, RDIM_UDT *udt) +{ + RDIM_UDTEnumVal *mem = rdim_push_array(arena, RDIM_UDTEnumVal, 1); + RDIM_SLLQueuePush(udt->first_enum_val, udt->last_enum_val, mem); + udt->enum_val_count += 1; + list->total_enum_val_count += 1; + return mem; +} + +//////////////////////////////// +//~ rjf: [Building] Symbol Info Building + +RDI_PROC RDIM_Symbol * +rdim_symbol_chunk_list_push(RDIM_Arena *arena, RDIM_SymbolChunkList *list, RDI_U64 cap) +{ + RDIM_SymbolChunkNode *n = list->last; + if(n == 0 || n->count >= n->cap) + { + n = rdim_push_array(arena, RDIM_SymbolChunkNode, 1); + n->cap = cap; + n->base_idx = list->total_count; + n->v = rdim_push_array(arena, RDIM_Symbol, n->cap); + RDIM_SLLQueuePush(list->first, list->last, n); + list->chunk_count += 1; + } + RDIM_Symbol *result = &n->v[n->count]; + result->chunk = n; + n->count += 1; + list->total_count += 1; + return result; +} + +RDI_PROC RDI_U64 +rdim_idx_from_symbol(RDIM_Symbol *symbol) +{ + RDI_U64 idx = 0; + if(symbol != 0 && symbol->chunk != 0) + { + idx = symbol->chunk->base_idx + (symbol - symbol->chunk->v) + 1; + } + return idx; +} + +RDI_PROC void +rdim_symbol_chunk_list_concat_in_place(RDIM_SymbolChunkList *dst, RDIM_SymbolChunkList *to_push) +{ + for(RDIM_SymbolChunkNode *n = to_push->first; n != 0; n = n->next) + { + n->base_idx += dst->total_count; + } + if(dst->last != 0 && to_push->first != 0) + { + dst->last->next = to_push->first; + dst->last = to_push->last; + dst->chunk_count += to_push->chunk_count; + dst->total_count += to_push->total_count; + } + else if(dst->first == 0) + { + rdim_memcpy_struct(dst, to_push); + } + rdim_memzero_struct(to_push); +} + +//////////////////////////////// +//~ rjf: [Building] Inline Site Info Building + +RDI_PROC RDIM_InlineSite * +rdim_inline_site_chunk_list_push(RDIM_Arena *arena, RDIM_InlineSiteChunkList *list, RDI_U64 cap) +{ + RDIM_InlineSiteChunkNode *n = list->last; + if(n == 0 || n->count >= n->cap) + { + n = rdim_push_array(arena, RDIM_InlineSiteChunkNode, 1); + n->cap = cap; + n->base_idx = list->total_count; + n->v = rdim_push_array(arena, RDIM_InlineSite, n->cap); + RDIM_SLLQueuePush(list->first, list->last, n); + list->chunk_count += 1; + } + RDIM_InlineSite *result = &n->v[n->count]; + result->chunk = n; + n->count += 1; + list->total_count += 1; + return result; +} + +RDI_PROC RDI_U64 +rdim_idx_from_inline_site(RDIM_InlineSite *inline_site) +{ + RDI_U64 idx = 0; + if(inline_site != 0 && inline_site->chunk != 0) + { + idx = inline_site->chunk->base_idx + (inline_site - inline_site->chunk->v) + 1; + } + return idx; +} + +RDI_PROC void +rdim_inline_site_chunk_list_concat_in_place(RDIM_InlineSiteChunkList *dst, RDIM_InlineSiteChunkList *to_push) +{ + for(RDIM_InlineSiteChunkNode *n = to_push->first; n != 0; n = n->next) + { + n->base_idx += dst->total_count; + } + if(dst->last != 0 && to_push->first != 0) + { + dst->last->next = to_push->first; + dst->last = to_push->last; + dst->chunk_count += to_push->chunk_count; + dst->total_count += to_push->total_count; + } + else if(dst->first == 0) + { + rdim_memcpy_struct(dst, to_push); + } + rdim_memzero_struct(to_push); +} + +//////////////////////////////// +//~ rjf: [Building] Scope Info Building + +//- rjf: scopes + +RDI_PROC RDIM_Scope * +rdim_scope_chunk_list_push(RDIM_Arena *arena, RDIM_ScopeChunkList *list, RDI_U64 cap) +{ + RDIM_ScopeChunkNode *n = list->last; + if(n == 0 || n->count >= n->cap) + { + n = rdim_push_array(arena, RDIM_ScopeChunkNode, 1); + n->cap = cap; + n->base_idx = list->total_count; + n->v = rdim_push_array(arena, RDIM_Scope, n->cap); + RDIM_SLLQueuePush(list->first, list->last, n); + list->chunk_count += 1; + } + RDIM_Scope *result = &n->v[n->count]; + result->chunk = n; + n->count += 1; + list->total_count += 1; + return result; +} + +RDI_PROC RDI_U64 +rdim_idx_from_scope(RDIM_Scope *scope) +{ + RDI_U64 idx = 0; + if(scope != 0 && scope->chunk != 0) + { + idx = scope->chunk->base_idx + (scope - scope->chunk->v) + 1; + } + return idx; +} + +RDI_PROC void +rdim_scope_chunk_list_concat_in_place(RDIM_ScopeChunkList *dst, RDIM_ScopeChunkList *to_push) +{ + for(RDIM_ScopeChunkNode *n = to_push->first; n != 0; n = n->next) + { + n->base_idx += dst->total_count; + } + if(dst->last != 0 && to_push->first != 0) + { + dst->last->next = to_push->first; + dst->last = to_push->last; + dst->chunk_count += to_push->chunk_count; + dst->total_count += to_push->total_count; + dst->scope_voff_count += to_push->scope_voff_count; + dst->local_count += to_push->local_count; + dst->location_count += to_push->location_count; + } + else if(dst->first == 0) + { + rdim_memcpy_struct(dst, to_push); + } + rdim_memzero_struct(to_push); +} + +RDI_PROC void +rdim_scope_push_voff_range(RDIM_Arena *arena, RDIM_ScopeChunkList *list, RDIM_Scope *scope, RDIM_Rng1U64 range) +{ + rdim_rng1u64_list_push(arena, &scope->voff_ranges, range); + list->scope_voff_count += 2; +} + +RDI_PROC RDIM_Local * +rdim_scope_push_local(RDIM_Arena *arena, RDIM_ScopeChunkList *scopes, RDIM_Scope *scope) +{ + RDIM_Local *local = rdim_push_array(arena, RDIM_Local, 1); + RDIM_SLLQueuePush(scope->first_local, scope->last_local, local); + scope->local_count += 1; + scopes->local_count += 1; + return local; +} + +//- rjf: bytecode + +RDI_PROC void +rdim_bytecode_push_op(RDIM_Arena *arena, RDIM_EvalBytecode *bytecode, RDI_EvalOp op, RDI_U64 p) +{ + RDI_U8 ctrlbits = rdi_eval_op_ctrlbits_table[op]; + RDI_U32 p_size = RDI_DECODEN_FROM_CTRLBITS(ctrlbits); + + RDIM_EvalBytecodeOp *node = rdim_push_array(arena, RDIM_EvalBytecodeOp, 1); + node->op = op; + node->p_size = p_size; + node->p = p; + + RDIM_SLLQueuePush(bytecode->first_op, bytecode->last_op, node); + bytecode->op_count += 1; + bytecode->encoded_size += 1 + p_size; +} + +RDI_PROC void +rdim_bytecode_push_uconst(RDIM_Arena *arena, RDIM_EvalBytecode *bytecode, RDI_U64 x) +{ + if(x <= 0xFF) + { + rdim_bytecode_push_op(arena, bytecode, RDI_EvalOp_ConstU8, x); + } + else if(x <= 0xFFFF) + { + rdim_bytecode_push_op(arena, bytecode, RDI_EvalOp_ConstU16, x); + } + else if(x <= 0xFFFFFFFF) + { + rdim_bytecode_push_op(arena, bytecode, RDI_EvalOp_ConstU32, x); + } + else + { + rdim_bytecode_push_op(arena, bytecode, RDI_EvalOp_ConstU64, x); + } +} + +RDI_PROC void +rdim_bytecode_push_sconst(RDIM_Arena *arena, RDIM_EvalBytecode *bytecode, RDI_S64 x) +{ + if(-0x80 <= x && x <= 0x7F) + { + rdim_bytecode_push_op(arena, bytecode, RDI_EvalOp_ConstU8, (RDI_U64)x); + rdim_bytecode_push_op(arena, bytecode, RDI_EvalOp_TruncSigned, 8); + } + else if(-0x8000 <= x && x <= 0x7FFF) + { + rdim_bytecode_push_op(arena, bytecode, RDI_EvalOp_ConstU16, (RDI_U64)x); + rdim_bytecode_push_op(arena, bytecode, RDI_EvalOp_TruncSigned, 16); + } + else if(-0x80000000ll <= x && x <= 0x7FFFFFFFll) + { + rdim_bytecode_push_op(arena, bytecode, RDI_EvalOp_ConstU32, (RDI_U64)x); + rdim_bytecode_push_op(arena, bytecode, RDI_EvalOp_TruncSigned, 32); + } + else + { + rdim_bytecode_push_op(arena, bytecode, RDI_EvalOp_ConstU64, (RDI_U64)x); + } +} + +RDI_PROC void +rdim_bytecode_concat_in_place(RDIM_EvalBytecode *left_dst, RDIM_EvalBytecode *right_destroyed) +{ + if(right_destroyed->first_op != 0) + { + if(left_dst->first_op == 0) + { + rdim_memcpy_struct(left_dst, right_destroyed); + } + else + { + left_dst->last_op = right_destroyed->last_op; + left_dst->op_count += right_destroyed->op_count; + left_dst->encoded_size += right_destroyed->encoded_size; + } + rdim_memzero_struct(right_destroyed); + } +} + +//- rjf: individual locations + +RDI_PROC RDIM_Location * +rdim_push_location_addr_bytecode_stream(RDIM_Arena *arena, RDIM_EvalBytecode *bytecode) +{ + RDIM_Location *result = rdim_push_array(arena, RDIM_Location, 1); + result->kind = RDI_LocationKind_AddrBytecodeStream; + result->bytecode = *bytecode; + return result; +} + +RDI_PROC RDIM_Location * +rdim_push_location_val_bytecode_stream(RDIM_Arena *arena, RDIM_EvalBytecode *bytecode) +{ + RDIM_Location *result = rdim_push_array(arena, RDIM_Location, 1); + result->kind = RDI_LocationKind_ValBytecodeStream; + result->bytecode = *bytecode; + return result; +} + +RDI_PROC RDIM_Location * +rdim_push_location_addr_reg_plus_u16(RDIM_Arena *arena, RDI_U8 reg_code, RDI_U16 offset) +{ + RDIM_Location *result = rdim_push_array(arena, RDIM_Location, 1); + result->kind = RDI_LocationKind_AddrRegPlusU16; + result->reg_code = reg_code; + result->offset = offset; + return result; +} + +RDI_PROC RDIM_Location * +rdim_push_location_addr_addr_reg_plus_u16(RDIM_Arena *arena, RDI_U8 reg_code, RDI_U16 offset) +{ + RDIM_Location *result = rdim_push_array(arena, RDIM_Location, 1); + result->kind = RDI_LocationKind_AddrAddrRegPlusU16; + result->reg_code = reg_code; + result->offset = offset; + return result; +} + +RDI_PROC RDIM_Location * +rdim_push_location_val_reg(RDIM_Arena *arena, RDI_U8 reg_code) +{ + RDIM_Location *result = rdim_push_array(arena, RDIM_Location, 1); + result->kind = RDI_LocationKind_ValReg; + result->reg_code = reg_code; + return result; +} + +//- rjf: location sets + +RDI_PROC void +rdim_location_set_push_case(RDIM_Arena *arena, RDIM_ScopeChunkList *scopes, RDIM_LocationSet *locset, RDIM_Rng1U64 voff_range, RDIM_Location *location) +{ + RDIM_LocationCase *location_case = rdim_push_array(arena, RDIM_LocationCase, 1); + SLLQueuePush(locset->first_location_case, locset->last_location_case, location_case); + locset->location_case_count += 1; + location_case->voff_range = voff_range; + location_case->location = location; + scopes->location_count +=1; +} + +//////////////////////////////// +//~ rjf: [Baking Helpers] Baked VMap Building + +RDI_PROC RDIM_BakeVMap +rdim_bake_vmap_from_markers(RDIM_Arena *arena, RDIM_VMapMarker *markers, RDIM_SortKey *keys, RDI_U64 marker_count) +{ + RDIM_Temp scratch = rdim_scratch_begin(&arena, 1); + + //- rjf: sort markers + RDIM_SortKey *sorted_keys = rdim_sort_key_array(scratch.arena, keys, marker_count); + + //- rjf: determine if an extra vmap entry for zero is needed + RDI_U32 extra_vmap_entry = 0; + if(marker_count > 0 && sorted_keys[0].key != 0) + { + extra_vmap_entry = 1; + } + + //- rjf: fill output vmap entries + RDI_U32 vmap_count_raw = marker_count - 1 + extra_vmap_entry; + RDI_VMapEntry *vmap = rdim_push_array_no_zero(arena, RDI_VMapEntry, vmap_count_raw + 1); + RDI_U32 vmap_entry_count_pass_1 = 0; + { + typedef struct RDIM_VMapRangeTracker RDIM_VMapRangeTracker; + struct RDIM_VMapRangeTracker + { + RDIM_VMapRangeTracker *next; + RDI_U32 idx; + }; + RDI_VMapEntry *vmap_ptr = vmap; + if(extra_vmap_entry) + { + vmap_ptr->voff = 0; + vmap_ptr->idx = 0; + vmap_ptr += 1; + } + RDIM_VMapRangeTracker *tracker_stack = 0; + RDIM_VMapRangeTracker *tracker_free = 0; + RDIM_SortKey *key_ptr = sorted_keys; + RDIM_SortKey *key_opl = sorted_keys + marker_count; + for(;key_ptr < key_opl;) + { + // rjf: get initial map state from tracker stack + RDI_U32 initial_idx = (RDI_U32)0xffffffff; + if(tracker_stack != 0) + { + initial_idx = tracker_stack->idx; + } + + // rjf: update tracker stack + // + // * we must process _all_ of the changes that apply at this voff before moving on + // + RDI_U64 voff = key_ptr->key; + + for(;key_ptr < key_opl && key_ptr->key == voff; key_ptr += 1) + { + RDIM_VMapMarker *marker = (RDIM_VMapMarker*)key_ptr->val; + RDI_U32 idx = marker->idx; + + // rjf: range begin -> push to stack + if(marker->begin_range) + { + RDIM_VMapRangeTracker *new_tracker = tracker_free; + if(new_tracker != 0) + { + RDIM_SLLStackPop(tracker_free); + } + else + { + new_tracker = rdim_push_array(scratch.arena, RDIM_VMapRangeTracker, 1); + } + RDIM_SLLStackPush(tracker_stack, new_tracker); + new_tracker->idx = idx; + } + + // rjf: range ending -> pop matching node from stack (not always the top) + else + { + RDIM_VMapRangeTracker **ptr_in = &tracker_stack; + RDIM_VMapRangeTracker *match = 0; + for(RDIM_VMapRangeTracker *node = tracker_stack; node != 0;) + { + if(node->idx == idx) + { + match = node; + break; + } + ptr_in = &node->next; + node = node->next; + } + if(match != 0) + { + *ptr_in = match->next; + RDIM_SLLStackPush(tracker_free, match); + } + } + } + + // rjf: get final map state from tracker stack + RDI_U32 final_idx = 0; + if(tracker_stack != 0) + { + final_idx = tracker_stack->idx; + } + + // rjf: if final is different from initial - emit new vmap entry + if(final_idx != initial_idx) + { + vmap_ptr->voff = voff; + vmap_ptr->idx = final_idx; + vmap_ptr += 1; + } + } + + vmap_entry_count_pass_1 = (RDI_U32)(vmap_ptr - vmap); // TODO(rjf): @u64_to_u32 + } + + //- rjf: combine duplicate neighbors + RDI_U32 vmap_entry_count = 0; + { + RDI_VMapEntry *vmap_ptr = vmap; + RDI_VMapEntry *vmap_opl = vmap + vmap_entry_count_pass_1; + RDI_VMapEntry *vmap_out = vmap; + for(;vmap_ptr < vmap_opl;) + { + RDI_VMapEntry *vmap_range_first = vmap_ptr; + RDI_U64 idx = vmap_ptr->idx; + vmap_ptr += 1; + for(;vmap_ptr < vmap_opl && vmap_ptr->idx == idx;) vmap_ptr += 1; + rdim_memcpy_struct(vmap_out, vmap_range_first); + vmap_out += 1; + } + vmap_entry_count = (RDI_U32)(vmap_out - vmap); // TODO(rjf): @u64_to_u32 + } + + //- rjf: fill result + RDIM_BakeVMap result = {0}; + result.vmap = vmap; + result.count = vmap_entry_count-1; + rdim_scratch_end(scratch); + return result; +} + +//////////////////////////////// +//~ rjf: [Baking Helpers] Interned / Deduplicated Blob Data Structure Helpers + +//- rjf: bake string chunk lists + +RDI_PROC RDIM_BakeString * +rdim_bake_string_chunk_list_push(RDIM_Arena *arena, RDIM_BakeStringChunkList *list, RDI_U64 cap) +{ + RDIM_BakeStringChunkNode *n = list->last; + if(n == 0 || n->count >= n->cap) + { + n = rdim_push_array(arena, RDIM_BakeStringChunkNode, 1); + n->cap = cap; + n->v = rdim_push_array(arena, RDIM_BakeString, n->cap); + RDIM_SLLQueuePush(list->first, list->last, n); + list->chunk_count += 1; + } + RDIM_BakeString *s = &n->v[n->count]; + n->count += 1; + list->total_count += 1; + return s; +} + +RDI_PROC void +rdim_bake_string_chunk_list_concat_in_place(RDIM_BakeStringChunkList *dst, RDIM_BakeStringChunkList *to_push) +{ + for(RDIM_BakeStringChunkNode *n = to_push->first; n != 0; n = n->next) + { + n->base_idx += dst->total_count; + } + if(dst->last != 0 && to_push->first != 0) + { + dst->last->next = to_push->first; + dst->last = to_push->last; + dst->chunk_count += to_push->chunk_count; + dst->total_count += to_push->total_count; + } + else if(dst->first == 0) + { + rdim_memcpy_struct(dst, to_push); + } + rdim_memzero_struct(to_push); +} + +RDI_PROC RDIM_BakeStringChunkList +rdim_bake_string_chunk_list_sorted_from_unsorted(RDIM_Arena *arena, RDIM_BakeStringChunkList *src) +{ + //- rjf: produce unsorted destination list with single chunk node + RDIM_BakeStringChunkList dst = {0}; + for(RDIM_BakeStringChunkNode *n = src->first; n != 0; n = n->next) + { + for(RDI_U64 idx = 0; idx < n->count; idx += 1) + { + RDIM_BakeString *src_str = &n->v[idx]; + RDIM_BakeString *dst_str = rdim_bake_string_chunk_list_push(arena, &dst, src->total_count); + rdim_memcpy_struct(dst_str, src_str); + } + } + + //- rjf: sort chunk node + if(dst.first != 0) + { + RDIM_Temp scratch = rdim_scratch_begin(&arena, 1); + typedef struct SortTask SortTask; + struct SortTask + { + SortTask *next; + RDI_U64 string_off; + RDIM_BakeString *v; + RDI_U64 count; + }; + SortTask start_task = {0, 0, dst.first->v, dst.first->count}; + SortTask *first_task = &start_task; + SortTask *last_task = &start_task; + + //- rjf: for each sort task range: + for(SortTask *t = first_task; t != 0; t = t->next) + { + //- rjf: loop through range, drop each element into bucket according to byte in string at task offset + RDIM_BakeStringChunkList *buckets = rdim_push_array(scratch.arena, RDIM_BakeStringChunkList, 256); + for(RDI_U64 idx = 0; idx < t->count; idx += 1) + { + U8 byte = t->string_off < t->v[idx].string.size ? t->v[idx].string.str[t->string_off] : 0; + RDIM_BakeStringChunkList *bucket = &buckets[byte]; + RDIM_BakeString *bstr = rdim_bake_string_chunk_list_push(scratch.arena, bucket, 8); + rdim_memcpy_struct(bstr, &t->v[idx]); + } + + //- rjf: in-place mutate the original source array to reflect the order per the buckets. + // build new sort tasks for buckets with many elements + { + RDI_U64 write_idx = 0; + for(U64 bucket_idx = 0; bucket_idx < 256; bucket_idx += 1) + { + // rjf: write each chunk node's array into original array, detect if there is size left to sort + RDI_U64 bucket_base_idx = write_idx; + RDI_U64 max_size_left_to_sort = 0; + for(RDIM_BakeStringChunkNode *n = buckets[bucket_idx].first; n != 0; n = n->next) + { + rdim_memcpy(t->v+write_idx, n->v, sizeof(n->v[0])*n->count); + write_idx += n->count; + for(RDI_U64 idx = 0; idx < n->count; idx += 1) + { + if(n->v[idx].string.size > t->string_off+1) + { + max_size_left_to_sort = Max(max_size_left_to_sort, (n->v[idx].string.size - t->string_off+1)); + } + } + } + + // rjf: if any bucket has >1 element & has some amount of size left to sort, push new task for this + // bucket's region in the array, and for remainder of keys + if(buckets[bucket_idx].total_count > 1 && max_size_left_to_sort > 0) + { + SortTask *new_task = rdim_push_array(scratch.arena, SortTask, 1); + RDIM_SLLQueuePush(first_task, last_task, new_task); + new_task->string_off = t->string_off+1; + new_task->v = t->v + bucket_base_idx; + new_task->count = write_idx-bucket_base_idx; + } + } + } + } + scratch_end(scratch); + } + + return dst; +} + +//- rjf: bake string chunk list maps + +RDI_PROC RDIM_BakeStringMapLoose * +rdim_bake_string_map_loose_make(RDIM_Arena *arena, RDIM_BakeStringMapTopology *top) +{ + RDIM_BakeStringMapLoose *map = rdim_push_array(arena, RDIM_BakeStringMapLoose, 1); + map->slots = rdim_push_array(arena, RDIM_BakeStringChunkList *, top->slots_count); + return map; +} + +RDI_PROC void +rdim_bake_string_map_loose_insert(RDIM_Arena *arena, RDIM_BakeStringMapTopology *map_topology, RDIM_BakeStringMapLoose *map, RDI_U64 chunk_cap, RDIM_String8 string) +{ + RDI_U64 hash = rdi_hash(string.RDIM_String8_BaseMember, string.RDIM_String8_SizeMember); + RDI_U64 slot_idx = hash%map_topology->slots_count; + RDIM_BakeStringChunkList *slot = map->slots[slot_idx]; + if(slot == 0) + { + slot = map->slots[slot_idx] = rdim_push_array(arena, RDIM_BakeStringChunkList, 1); + } + RDI_S32 is_duplicate = 0; + for(RDIM_BakeStringChunkNode *n = slot->first; n != 0; n = n->next) + { + for(RDI_U64 idx = 0; idx < n->count; idx += 1) + { + if(rdim_str8_match(n->v[idx].string, string, 0)) + { + is_duplicate = 1; + goto break_all; + } + } + } + break_all:; + if(!is_duplicate) + { + RDIM_BakeString *bstr = rdim_bake_string_chunk_list_push(arena, slot, chunk_cap); + bstr->string = string; + bstr->hash = hash; + } +} + +RDI_PROC void +rdim_bake_string_map_loose_join_in_place(RDIM_BakeStringMapTopology *map_topology, RDIM_BakeStringMapLoose *dst, RDIM_BakeStringMapLoose *src) +{ + for(RDI_U64 idx = 0; idx < map_topology->slots_count; idx += 1) + { + if(dst->slots[idx] == 0) + { + dst->slots[idx] = src->slots[idx]; + } + else if(src->slots[idx] != 0) + { + rdim_bake_string_chunk_list_concat_in_place(dst->slots[idx], src->slots[idx]); + } + } + rdim_memzero_struct(src); +} + +RDI_PROC RDIM_BakeStringMapBaseIndices +rdim_bake_string_map_base_indices_from_map_loose(RDIM_Arena *arena, RDIM_BakeStringMapTopology *map_topology, RDIM_BakeStringMapLoose *map) +{ + RDIM_BakeStringMapBaseIndices indices = {0}; + indices.slots_base_idxs = rdim_push_array(arena, RDI_U64, map_topology->slots_count+1); + RDI_U64 total_count = 0; + for(RDI_U64 idx = 0; idx < map_topology->slots_count; idx += 1) + { + indices.slots_base_idxs[idx] += total_count; + if(map->slots[idx] != 0) + { + total_count += map->slots[idx]->total_count; + } + } + indices.slots_base_idxs[map_topology->slots_count] = total_count; + return indices; +} + +//- rjf: finalized bake string map + +RDI_PROC RDIM_BakeStringMapTight +rdim_bake_string_map_tight_from_loose(RDIM_Arena *arena, RDIM_BakeStringMapTopology *map_topology, RDIM_BakeStringMapBaseIndices *map_base_indices, RDIM_BakeStringMapLoose *map) +{ + RDIM_BakeStringMapTight m = {0}; + m.slots_count = map_topology->slots_count; + m.slots = rdim_push_array(arena, RDIM_BakeStringChunkList, m.slots_count); + m.slots_base_idxs = map_base_indices->slots_base_idxs; + for(RDI_U64 idx = 0; idx < m.slots_count; idx += 1) + { + if(map->slots[idx] != 0) + { + rdim_memcpy_struct(&m.slots[idx], map->slots[idx]); + } + } + m.total_count = m.slots_base_idxs[m.slots_count]; + return m; +} + +RDI_PROC RDI_U32 +rdim_bake_idx_from_string(RDIM_BakeStringMapTight *map, RDIM_String8 string) +{ + RDI_U32 idx = 0; + if(string.RDIM_String8_SizeMember != 0) + { + RDI_U64 hash = rdi_hash(string.RDIM_String8_BaseMember, string.RDIM_String8_SizeMember); + RDI_U64 slot_idx = hash%map->slots_count; + for(RDIM_BakeStringChunkNode *n = map->slots[slot_idx].first; n != 0; n = n->next) + { + for(RDI_U64 chunk_idx = 0; chunk_idx < n->count; chunk_idx += 1) + { + if(n->v[chunk_idx].hash == hash && rdim_str8_match(n->v[chunk_idx].string, string, 0)) + { + idx = map->slots_base_idxs[slot_idx] + n->base_idx + chunk_idx + 1; + break; + } + } + } + } + return idx; +} + +//- rjf: bake idx run map reading/writing + +RDI_PROC RDI_U64 +rdim_hash_from_idx_run(RDI_U32 *idx_run, RDI_U32 count) +{ + RDI_U64 hash = 5381; + RDI_U32 *ptr = idx_run; + RDI_U32 *opl = idx_run + count; + for(;ptr < opl; ptr += 1) + { + hash = ((hash << 5) + hash) + (*ptr); + } + return hash; +} + +RDI_PROC RDI_U32 +rdim_bake_idx_from_idx_run(RDIM_BakeIdxRunMap *map, RDI_U32 *idx_run, RDI_U32 count) +{ + RDI_U64 hash = rdim_hash_from_idx_run(idx_run, count); + RDI_U64 slot_idx = hash%map->slots_count; + + // rjf: find existing node + RDIM_BakeIdxRunNode *node = 0; + for(RDIM_BakeIdxRunNode *n = map->slots[slot_idx]; n != 0; n = n->hash_next) + { + if(n->hash == hash) + { + RDI_S32 is_match = 1; + RDI_U32 *n_idx = n->idx_run; + for(RDI_U32 i = 0; i < count; i += 1) + { + if(n_idx[i] != idx_run[i]) + { + is_match = 0; + break; + } + } + if(is_match) + { + node = n; + break; + } + } + } + + // rjf: node -> index + RDI_U32 result = node ? node->first_idx : 0; + return result; +} + +RDI_PROC RDI_U32 +rdim_bake_idx_run_map_insert(RDIM_Arena *arena, RDIM_BakeIdxRunMap *map, RDI_U32 *idx_run, RDI_U32 count) +{ + RDI_U64 hash = rdim_hash_from_idx_run(idx_run, count); + RDI_U64 slot_idx = hash%map->slots_count; + + // rjf: find existing node + RDIM_BakeIdxRunNode *node = 0; + for(RDIM_BakeIdxRunNode *n = map->slots[slot_idx]; n != 0; n = n->hash_next) + { + if(n->hash == hash) + { + RDI_S32 is_match = 1; + RDI_U32 *n_idx = n->idx_run; + for(RDI_U32 i = 0; i < count; i += 1) + { + if(n_idx[i] != idx_run[i]) + { + is_match = 0; + break; + } + } + if(is_match) + { + node = n; + break; + } + } + } + + // rjf: no node -> make new node + if(node == 0) + { + node = rdim_push_array_no_zero(arena, RDIM_BakeIdxRunNode, 1); + RDI_U32 *idx_run_copy = rdim_push_array_no_zero(arena, RDI_U32, count); + for(RDI_U32 i = 0; i < count; i += 1) + { + idx_run_copy[i] = idx_run[i]; + } + node->idx_run = idx_run_copy; + node->hash = hash; + node->count = count; + node->first_idx = map->idx_count; + map->count += 1; + map->idx_count += count; + RDIM_SLLQueuePush_N(map->order_first, map->order_last, node, order_next); + RDIM_SLLStackPush_N(map->slots[slot_idx], node, hash_next); + map->slot_collision_count += (node->hash_next != 0); + } + + // rjf: node -> index + RDI_U32 result = node->first_idx; + return result; +} + +//- rjf: bake path tree reading/writing + +RDI_PROC RDIM_BakePathNode * +rdim_bake_path_node_from_string(RDIM_BakePathTree *tree, RDIM_String8 string) +{ + RDIM_BakePathNode *node = &tree->root; + RDI_U8 *ptr = string.str; + RDI_U8 *opl = string.str + string.size; + for(;ptr < opl && node != 0;) + { + // rjf: skip past slashes + for(;ptr < opl && (*ptr == '/' || *ptr == '\\'); ptr += 1); + + // rjf: save beginning of non-slash range + RDI_U8 *range_first = ptr; + + // rjf: skip past non-slashes + for(;ptr < opl && !(*ptr == '/' || *ptr == '\\'); ptr += 1); + + // rjf: empty range -> continue + if(range_first >= ptr) + { + continue; + } + + // rjf: range -> sub-directory string + RDIM_String8 sub_dir = rdim_str8(range_first, (RDI_U64)(ptr-range_first)); + + // rjf: sub-directory string -> find child of node + RDIM_BakePathNode *sub_dir_node = 0; + for(RDIM_BakePathNode *child = node->first_child; child != 0; child = child->next_sibling) + { + if(rdim_str8_match(child->name, sub_dir, RDIM_StringMatchFlag_CaseInsensitive)) + { + sub_dir_node = child; + } + } + + // rjf: descend to child + node = sub_dir_node; + } + return node; +} + +RDI_PROC RDI_U32 +rdim_bake_path_node_idx_from_string(RDIM_BakePathTree *tree, RDIM_String8 string) +{ + RDIM_BakePathNode *path_node = rdim_bake_path_node_from_string(tree, string); + RDI_U32 result = 0; + if(path_node != 0) + { + result = path_node->idx; + } + return result; +} + +RDI_PROC RDIM_BakePathNode * +rdim_bake_path_tree_insert(RDIM_Arena *arena, RDIM_BakePathTree *tree, RDIM_String8 string) +{ + RDIM_BakePathNode *node = &tree->root; + RDI_U8 *ptr = string.str; + RDI_U8 *opl = string.str + string.size; + for(;ptr < opl;) + { + // rjf: skip past slashes + for(;ptr < opl && (*ptr == '/' || *ptr == '\\'); ptr += 1); + + // rjf: save beginning of non-slash range + RDI_U8 *range_first = ptr; + + // rjf: skip past non-slashes + for(;ptr < opl && !(*ptr == '/' || *ptr == '\\'); ptr += 1); + + // rjf: empty range -> continue + if(range_first >= ptr) + { + continue; + } + + // rjf: range -> sub-directory string + RDIM_String8 sub_dir = rdim_str8(range_first, (RDI_U64)(ptr-range_first)); + + // rjf: sub-directory string -> find child of node + RDIM_BakePathNode *sub_dir_node = 0; + for(RDIM_BakePathNode *child = node->first_child; child != 0; child = child->next_sibling) + { + if(rdim_str8_match(child->name, sub_dir, RDIM_StringMatchFlag_CaseInsensitive)) + { + sub_dir_node = child; + } + } + + // rjf: no child -> make one + if(sub_dir_node == 0) + { + sub_dir_node = rdim_push_array(arena, RDIM_BakePathNode, 1); + RDIM_SLLQueuePush_N(tree->first, tree->last, sub_dir_node, next_order); + sub_dir_node->parent = node; + RDIM_SLLQueuePush_N(node->first_child, node->last_child, sub_dir_node, next_sibling); + sub_dir_node->name = rdim_str8_copy(arena, sub_dir); + sub_dir_node->idx = tree->count; + tree->count += 1; + } + + // rjf: descend to child + node = sub_dir_node; + } + return node; +} + +//- rjf: bake name maps writing + +RDI_PROC void +rdim_bake_name_map_push(RDIM_Arena *arena, RDIM_BakeNameMap *map, RDIM_String8 string, RDI_U32 idx) +{ + if(string.size == 0) {return;} + + // rjf: hash + RDI_U64 hash = rdi_hash(string.RDIM_String8_BaseMember, string.RDIM_String8_SizeMember); + RDI_U64 slot_idx = hash%map->slots_count; + + // rjf: find existing node + RDIM_BakeNameMapNode *node = 0; + for(RDIM_BakeNameMapNode *n = map->slots[slot_idx]; n != 0; n = n->slot_next) + { + if(rdim_str8_match(string, n->string, 0)) + { + node = n; + break; + } + } + + // rjf: make node if necessary + if(node == 0) + { + node = rdim_push_array(arena, RDIM_BakeNameMapNode, 1); + node->string = string; + RDIM_SLLStackPush_N(map->slots[slot_idx], node, slot_next); + RDIM_SLLQueuePush_N(map->first, map->last, node, order_next); + map->name_count += 1; + map->slot_collision_count += (node->slot_next != 0); + } + + // rjf: find existing idx + RDI_S32 existing_idx = 0; + for(RDIM_BakeNameMapValNode *n = node->val_first; n != 0; n = n->next) + { + for(RDI_U32 i = 0; i < sizeof(n->val)/sizeof(n->val[0]); i += 1) + { + if(n->val[i] == 0) + { + break; + } + if(n->val[i] == idx) + { + existing_idx = 1; + break; + } + } + } + + // rjf: insert new idx if necessary + if(!existing_idx) + { + RDIM_BakeNameMapValNode *val_node = node->val_last; + RDI_U32 insert_i = node->val_count%(sizeof(val_node->val)/sizeof(val_node->val[0])); + if(insert_i == 0) + { + val_node = rdim_push_array(arena, RDIM_BakeNameMapValNode, 1); + SLLQueuePush(node->val_first, node->val_last, val_node); + } + val_node->val[insert_i] = idx; + node->val_count += 1; + } +} + +//////////////////////////////// +//~ rjf: [Baking Helpers] Data Section List Building Helpers + +RDI_PROC RDIM_BakeSection * +rdim_bake_section_list_push(RDIM_Arena *arena, RDIM_BakeSectionList *list) +{ + RDIM_BakeSectionNode *n = rdim_push_array(arena, RDIM_BakeSectionNode, 1); + RDIM_SLLQueuePush(list->first, list->last, n); + list->count += 1; + RDIM_BakeSection *result = &n->v; + return result; +} + +RDI_PROC RDIM_BakeSection * +rdim_bake_section_list_push_new_unpacked(RDIM_Arena *arena, RDIM_BakeSectionList *list, void *data, RDI_U64 size, RDI_SectionKind tag, RDI_U64 tag_idx) +{ + RDIM_BakeSection *section = rdim_bake_section_list_push(arena, list); + section->data = data; + section->encoding = RDI_SectionEncoding_Unpacked; + section->encoded_size = size; + section->unpacked_size = size; + section->tag = tag; + section->tag_idx = tag_idx; + return section; +} + +RDI_PROC void +rdim_bake_section_list_concat_in_place(RDIM_BakeSectionList *dst, RDIM_BakeSectionList *to_push) +{ + if(dst->last != 0 && to_push->first != 0) + { + dst->last->next = to_push->first; + dst->last = to_push->last; + dst->count += to_push->count; + } + else if(to_push->first != 0) + { + rdim_memcpy_struct(dst, to_push); + } + rdim_memzero_struct(to_push); +} + +//////////////////////////////// +//~ rjf: [Baking] Build Artifacts -> Interned/Deduplicated Data Structures + +//- rjf: basic bake string gathering passes + +RDI_PROC void +rdim_bake_string_map_loose_push_top_level_info(RDIM_Arena *arena, RDIM_BakeStringMapTopology *top, RDIM_BakeStringMapLoose *map, RDIM_TopLevelInfo *tli) +{ + rdim_bake_string_map_loose_insert(arena, top, map, 1, tli->exe_name); + rdim_bake_string_map_loose_insert(arena, top, map, 1, tli->producer_name); +} + +RDI_PROC void +rdim_bake_string_map_loose_push_binary_sections(RDIM_Arena *arena, RDIM_BakeStringMapTopology *top, RDIM_BakeStringMapLoose *map, RDIM_BinarySectionList *secs) +{ + for(RDIM_BinarySectionNode *n = secs->first; n != 0; n = n->next) + { + rdim_bake_string_map_loose_insert(arena, top, map, 1, n->v.name); + } +} + +RDI_PROC void +rdim_bake_string_map_loose_push_path_tree(RDIM_Arena *arena, RDIM_BakeStringMapTopology *top, RDIM_BakeStringMapLoose *map, RDIM_BakePathTree *path_tree) +{ + for(RDIM_BakePathNode *n = path_tree->first; n != 0; n = n->next_order) + { + rdim_bake_string_map_loose_insert(arena, top, map, 1, n->name); + } +} + +//- rjf: chunk-granularity bake string gathering passes + +RDI_PROC void +rdim_bake_string_map_loose_push_src_file_slice(RDIM_Arena *arena, RDIM_BakeStringMapTopology *top, RDIM_BakeStringMapLoose *map, RDIM_SrcFile *v, RDI_U64 count) +{ + for(RDI_U64 idx = 0; idx < count; idx += 1) + { + rdim_bake_string_map_loose_insert(arena, top, map, 1, v[idx].normal_full_path); + } +} + +RDI_PROC void +rdim_bake_string_map_loose_push_unit_slice(RDIM_Arena *arena, RDIM_BakeStringMapTopology *top, RDIM_BakeStringMapLoose *map, RDIM_Unit *v, RDI_U64 count) +{ + for(RDI_U64 idx = 0; idx < count; idx += 1) + { + rdim_bake_string_map_loose_insert(arena, top, map, 4, v[idx].unit_name); + rdim_bake_string_map_loose_insert(arena, top, map, 4, v[idx].compiler_name); + rdim_bake_string_map_loose_insert(arena, top, map, 4, v[idx].source_file); + rdim_bake_string_map_loose_insert(arena, top, map, 4, v[idx].object_file); + rdim_bake_string_map_loose_insert(arena, top, map, 4, v[idx].archive_file); + rdim_bake_string_map_loose_insert(arena, top, map, 4, v[idx].build_path); + } +} + +RDI_PROC void +rdim_bake_string_map_loose_push_type_slice(RDIM_Arena *arena, RDIM_BakeStringMapTopology *top, RDIM_BakeStringMapLoose *map, RDIM_Type *v, RDI_U64 count) +{ + for(RDI_U64 idx = 0; idx < count; idx += 1) + { + rdim_bake_string_map_loose_insert(arena, top, map, 4, v[idx].name); + } +} + +RDI_PROC void +rdim_bake_string_map_loose_push_udt_slice(RDIM_Arena *arena, RDIM_BakeStringMapTopology *top, RDIM_BakeStringMapLoose *map, RDIM_UDT *v, RDI_U64 count) +{ + for(RDI_U64 idx = 0; idx < count; idx += 1) + { + for(RDIM_UDTMember *mem = v[idx].first_member; mem != 0; mem = mem->next) + { + rdim_bake_string_map_loose_insert(arena, top, map, 4, mem->name); + } + for(RDIM_UDTEnumVal *mem = v[idx].first_enum_val; mem != 0; mem = mem->next) + { + rdim_bake_string_map_loose_insert(arena, top, map, 4, mem->name); + } + } +} + +RDI_PROC void +rdim_bake_string_map_loose_push_symbol_slice(RDIM_Arena *arena, RDIM_BakeStringMapTopology *top, RDIM_BakeStringMapLoose *map, RDIM_Symbol *v, RDI_U64 count) +{ + for(RDI_U64 idx = 0; idx < count; idx += 1) + { + rdim_bake_string_map_loose_insert(arena, top, map, 4, v[idx].name); + rdim_bake_string_map_loose_insert(arena, top, map, 4, v[idx].link_name); + } +} + +RDI_PROC void +rdim_bake_string_map_loose_push_scope_slice(RDIM_Arena *arena, RDIM_BakeStringMapTopology *top, RDIM_BakeStringMapLoose *map, RDIM_Scope *v, RDI_U64 count) +{ + for(RDI_U64 idx = 0; idx < count; idx += 1) + { + for(RDIM_Local *local = v[idx].first_local; local != 0; local = local->next) + { + rdim_bake_string_map_loose_insert(arena, top, map, 4, local->name); + } + } +} + +//- rjf: list-granularity bake string gathering passes + +RDI_PROC void +rdim_bake_string_map_loose_push_src_files(RDIM_Arena *arena, RDIM_BakeStringMapTopology *top, RDIM_BakeStringMapLoose *map, RDIM_SrcFileChunkList *list) +{ + for(RDIM_SrcFileChunkNode *n = list->first; n != 0; n = n->next) + { + rdim_bake_string_map_loose_push_src_file_slice(arena, top, map, n->v, n->count); + } +} + +RDI_PROC void +rdim_bake_string_map_loose_push_units(RDIM_Arena *arena, RDIM_BakeStringMapTopology *top, RDIM_BakeStringMapLoose *map, RDIM_UnitChunkList *list) +{ + for(RDIM_UnitChunkNode *n = list->first; n != 0; n = n->next) + { + rdim_bake_string_map_loose_push_unit_slice(arena, top, map, n->v, n->count); + } +} + +RDI_PROC void +rdim_bake_string_map_loose_push_types(RDIM_Arena *arena, RDIM_BakeStringMapTopology *top, RDIM_BakeStringMapLoose *map, RDIM_TypeChunkList *list) +{ + for(RDIM_TypeChunkNode *n = list->first; n != 0; n = n->next) + { + rdim_bake_string_map_loose_push_type_slice(arena, top, map, n->v, n->count); + } +} + +RDI_PROC void +rdim_bake_string_map_loose_push_udts(RDIM_Arena *arena, RDIM_BakeStringMapTopology *top, RDIM_BakeStringMapLoose *map, RDIM_UDTChunkList *list) +{ + for(RDIM_UDTChunkNode *n = list->first; n != 0; n = n->next) + { + rdim_bake_string_map_loose_push_udt_slice(arena, top, map, n->v, n->count); + } +} + +RDI_PROC void +rdim_bake_string_map_loose_push_symbols(RDIM_Arena *arena, RDIM_BakeStringMapTopology *top, RDIM_BakeStringMapLoose *map, RDIM_SymbolChunkList *list) +{ + for(RDIM_SymbolChunkNode *n = list->first; n != 0; n = n->next) + { + rdim_bake_string_map_loose_push_symbol_slice(arena, top, map, n->v, n->count); + } +} + +RDI_PROC void +rdim_bake_string_map_loose_push_scopes(RDIM_Arena *arena, RDIM_BakeStringMapTopology *top, RDIM_BakeStringMapLoose *map, RDIM_ScopeChunkList *list) +{ + for(RDIM_ScopeChunkNode *n = list->first; n != 0; n = n->next) + { + rdim_bake_string_map_loose_push_scope_slice(arena, top, map, n->v, n->count); + } +} + +//- rjf: bake name map building + +RDI_PROC RDIM_BakeNameMap * +rdim_bake_name_map_from_kind_params(RDIM_Arena *arena, RDI_NameMapKind kind, RDIM_BakeParams *params) +{ + RDIM_BakeNameMap *map = rdim_push_array(arena, RDIM_BakeNameMap, 1); + switch(kind) + { + default:{}break; + case RDI_NameMapKind_GlobalVariables: + { + map->slots_count = params->global_variables.total_count*2; + map->slots = rdim_push_array(arena, RDIM_BakeNameMapNode *, map->slots_count); + for(RDIM_SymbolChunkNode *n = params->global_variables.first; n != 0; n = n->next) + { + for(RDI_U64 idx = 0; idx < n->count; idx += 1) + { + RDI_U32 symbol_idx = (RDI_U32)rdim_idx_from_symbol(&n->v[idx]); // TODO(rjf): @u64_to_u32 + rdim_bake_name_map_push(arena, map, n->v[idx].name, symbol_idx); + } + } + }break; + case RDI_NameMapKind_ThreadVariables: + { + map->slots_count = params->thread_variables.total_count*2; + map->slots = rdim_push_array(arena, RDIM_BakeNameMapNode *, map->slots_count); + for(RDIM_SymbolChunkNode *n = params->thread_variables.first; n != 0; n = n->next) + { + for(RDI_U64 idx = 0; idx < n->count; idx += 1) + { + RDI_U32 symbol_idx = (RDI_U32)rdim_idx_from_symbol(&n->v[idx]); // TODO(rjf): @u64_to_u32 + rdim_bake_name_map_push(arena, map, n->v[idx].name, symbol_idx); + } + } + }break; + case RDI_NameMapKind_Procedures: + { + map->slots_count = params->procedures.total_count*2; + map->slots = rdim_push_array(arena, RDIM_BakeNameMapNode *, map->slots_count); + for(RDIM_SymbolChunkNode *n = params->procedures.first; n != 0; n = n->next) + { + for(RDI_U64 idx = 0; idx < n->count; idx += 1) + { + RDI_U32 symbol_idx = (RDI_U32)rdim_idx_from_symbol(&n->v[idx]); // TODO(rjf): @u64_to_u32 + rdim_bake_name_map_push(arena, map, n->v[idx].name, symbol_idx); + } + } + }break; + case RDI_NameMapKind_Types: + { + map->slots_count = params->types.total_count; + map->slots = rdim_push_array(arena, RDIM_BakeNameMapNode *, map->slots_count); + for(RDIM_TypeChunkNode *n = params->types.first; n != 0; n = n->next) + { + for(RDI_U64 idx = 0; idx < n->count; idx += 1) + { + RDI_U32 type_idx = (RDI_U32)rdim_idx_from_type(&n->v[idx]); // TODO(rjf): @u64_to_u32 + rdim_bake_name_map_push(arena, map, n->v[idx].name, type_idx); + } + } + }break; + case RDI_NameMapKind_LinkNameProcedures: + { + map->slots_count = params->procedures.total_count*2; + map->slots = rdim_push_array(arena, RDIM_BakeNameMapNode *, map->slots_count); + for(RDIM_SymbolChunkNode *n = params->procedures.first; n != 0; n = n->next) + { + for(RDI_U64 idx = 0; idx < n->count; idx += 1) + { + if(n->v[idx].link_name.size == 0) {continue;} + RDI_U32 symbol_idx = (RDI_U32)rdim_idx_from_symbol(&n->v[idx]); // TODO(rjf): @u64_to_u32 + rdim_bake_name_map_push(arena, map, n->v[idx].link_name, symbol_idx); + } + } + }break; + case RDI_NameMapKind_NormalSourcePaths: + { + map->slots_count = params->src_files.total_count*2; + map->slots = rdim_push_array(arena, RDIM_BakeNameMapNode *, map->slots_count); + for(RDIM_SrcFileChunkNode *n = params->src_files.first; n != 0; n = n->next) + { + for(RDI_U64 idx = 0; idx < n->count; idx += 1) + { + RDI_U64 src_file_idx = rdim_idx_from_src_file(&n->v[idx]); + rdim_bake_name_map_push(arena, map, n->v[idx].normal_full_path, (RDI_U32)src_file_idx); // TODO(rjf): @u64_to_u32 + } + } + }break; + } + return map; +} + +//- rjf: idx run map building + +RDI_PROC RDIM_BakeIdxRunMap * +rdim_bake_idx_run_map_from_params(RDIM_Arena *arena, RDIM_BakeNameMap *name_maps[RDI_NameMapKind_COUNT], RDIM_BakeParams *params) +{ + //- rjf: set up map + RDIM_BakeIdxRunMap *idx_runs = rdim_push_array(arena, RDIM_BakeIdxRunMap, 1); + idx_runs->slots_count = params->procedures.total_count*2 + params->global_variables.total_count*2 + params->thread_variables.total_count*2 + params->types.total_count*2; + idx_runs->slots = rdim_push_array(arena, RDIM_BakeIdxRunNode *, idx_runs->slots_count); + rdim_bake_idx_run_map_insert(arena, idx_runs, 0, 0); + + //- rjf: bake runs of function-type parameter lists + for(RDIM_TypeChunkNode *n = params->types.first; n != 0; n = n->next) + { + for(RDI_U64 chunk_idx = 0; chunk_idx < n->count; chunk_idx += 1) + { + RDIM_Type *type = &n->v[chunk_idx]; + if(type->kind == RDI_TypeKind_Function || type->kind == RDI_TypeKind_Method) + { + RDI_U32 param_idx_run_count = type->count; + RDI_U32 *param_idx_run = rdim_push_array_no_zero(arena, RDI_U32, param_idx_run_count); + for(RDI_U32 idx = 0; idx < param_idx_run_count; idx += 1) + { + param_idx_run[idx] = (RDI_U32)rdim_idx_from_type(type->param_types[idx]); // TODO(rjf): @u64_to_u32 + } + rdim_bake_idx_run_map_insert(arena, idx_runs, param_idx_run, param_idx_run_count); + } + } + } + + //- rjf: bake runs of name map match lists + for(RDI_NameMapKind k = (RDI_NameMapKind)(RDI_NameMapKind_NULL+1); + k < RDI_NameMapKind_COUNT; + k = (RDI_NameMapKind)(k+1)) + { + RDIM_BakeNameMap *name_map = name_maps[k]; + if(name_map != 0 && name_map->name_count != 0) + { + for(RDIM_BakeNameMapNode *n = name_map->first; n != 0; n = n->order_next) + { + if(n->val_count > 1) + { + RDI_U32 *idx_run = rdim_push_array(arena, RDI_U32, n->val_count); + RDI_U64 val_idx = 0; + for(RDIM_BakeNameMapValNode *idxnode = n->val_first; + idxnode != 0; + idxnode = idxnode->next) + { + for(RDI_U32 i = 0; i < sizeof(idxnode->val)/sizeof(idxnode->val[0]); i += 1) + { + if(idxnode->val[i] == 0) + { + goto dblbreak; + } + idx_run[val_idx] = idxnode->val[i]; + val_idx += 1; + } + } + dblbreak:; + rdim_bake_idx_run_map_insert(arena, idx_runs, idx_run, (RDI_U32)n->val_count); // TODO(rjf): @u64_to_u32 + } + } + } + } + + return idx_runs; +} + +//- rjf: bake path tree building + +RDI_PROC RDIM_BakePathTree * +rdim_bake_path_tree_from_params(RDIM_Arena *arena, RDIM_BakeParams *params) +{ + //- rjf: set up tree + RDIM_BakePathTree *tree = rdim_push_array(arena, RDIM_BakePathTree, 1); + rdim_bake_path_tree_insert(arena, tree, rdim_str8_lit("")); + + //- rjf: bake unit file paths + RDIM_ProfScope("bake unit file paths") + { + for(RDIM_UnitChunkNode *n = params->units.first; n != 0; n = n->next) + { + for(RDI_U64 idx = 0; idx < n->count; idx += 1) + { + rdim_bake_path_tree_insert(arena, tree, n->v[idx].source_file); + rdim_bake_path_tree_insert(arena, tree, n->v[idx].object_file); + rdim_bake_path_tree_insert(arena, tree, n->v[idx].archive_file); + rdim_bake_path_tree_insert(arena, tree, n->v[idx].build_path); + } + } + } + + //- rjf: bake source file paths + RDIM_ProfScope("bake source file paths") + { + for(RDIM_SrcFileChunkNode *n = params->src_files.first; n != 0; n = n->next) + { + for(RDI_U64 idx = 0; idx < n->count; idx += 1) + { + RDIM_BakePathNode *node = rdim_bake_path_tree_insert(arena, tree, n->v[idx].normal_full_path); + node->src_file = &n->v[idx]; + } + } + } + + return tree; +} + +//////////////////////////////// +//~ rjf: [Baking] Build Artifacts -> Baked Versions + +//- rjf: partial/joinable baking functions + +RDI_PROC RDIM_NameMapBakeResult +rdim_bake_name_map(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakeIdxRunMap *idx_runs, RDIM_BakeNameMap *src) +{ + RDIM_NameMapBakeResult result = {0}; + if(src->name_count != 0) + { + RDI_U32 baked_buckets_count = src->name_count; + RDI_U32 baked_nodes_count = src->name_count; + RDI_NameMapBucket *baked_buckets = rdim_push_array(arena, RDI_NameMapBucket, baked_buckets_count); + RDI_NameMapNode *baked_nodes = rdim_push_array_no_zero(arena, RDI_NameMapNode, baked_nodes_count); + { + RDIM_Temp scratch = rdim_scratch_begin(&arena, 1); + + // rjf: setup the final bucket layouts + typedef struct RDIM_NameMapSemiNode RDIM_NameMapSemiNode; + struct RDIM_NameMapSemiNode + { + RDIM_NameMapSemiNode *next; + RDIM_BakeNameMapNode *node; + }; + typedef struct RDIM_NameMapSemiBucket RDIM_NameMapSemiBucket; + struct RDIM_NameMapSemiBucket + { + RDIM_NameMapSemiNode *first; + RDIM_NameMapSemiNode *last; + RDI_U64 count; + }; + RDIM_NameMapSemiBucket *sbuckets = rdim_push_array(scratch.arena, RDIM_NameMapSemiBucket, baked_buckets_count); + for(RDIM_BakeNameMapNode *node = src->first; + node != 0; + node = node->order_next) + { + RDI_U64 hash = rdi_hash(node->string.str, node->string.size); + RDI_U64 bi = hash%baked_buckets_count; + RDIM_NameMapSemiNode *snode = rdim_push_array(scratch.arena, RDIM_NameMapSemiNode, 1); + SLLQueuePush(sbuckets[bi].first, sbuckets[bi].last, snode); + snode->node = node; + sbuckets[bi].count += 1; + } + + // rjf: convert to serialized buckets & nodes + { + RDI_NameMapBucket *bucket_ptr = baked_buckets; + RDI_NameMapNode *node_ptr = baked_nodes; + for(RDI_U32 i = 0; i < baked_buckets_count; i += 1, bucket_ptr += 1) + { + bucket_ptr->first_node = (RDI_U32)((RDI_U64)(node_ptr - baked_nodes)); + bucket_ptr->node_count = sbuckets[i].count; + for(RDIM_NameMapSemiNode *snode = sbuckets[i].first; + snode != 0; + snode = snode->next) + { + RDIM_BakeNameMapNode *node = snode->node; + + // rjf: cons name and index(es) + RDI_U32 string_idx = rdim_bake_idx_from_string(strings, node->string); + RDI_U32 match_count = node->val_count; + RDI_U32 idx = 0; + if(match_count == 1) + { + idx = node->val_first->val[0]; + } + else + { + RDI_U64 temp_pos = rdim_arena_pos(scratch.arena); + RDI_U32 *idx_run = rdim_push_array_no_zero(scratch.arena, RDI_U32, match_count); + RDI_U32 *idx_ptr = idx_run; + for(RDIM_BakeNameMapValNode *idxnode = node->val_first; + idxnode != 0; + idxnode = idxnode->next) + { + for(RDI_U32 i = 0; i < sizeof(idxnode->val)/sizeof(idxnode->val[0]); i += 1) + { + if(idxnode->val[i] == 0) + { + goto dblbreak; + } + *idx_ptr = idxnode->val[i]; + idx_ptr += 1; + } + } + dblbreak:; + idx = rdim_bake_idx_from_idx_run(idx_runs, idx_run, match_count); + rdim_arena_pop_to(scratch.arena, temp_pos); + } + + // rjf: write to node + node_ptr->string_idx = string_idx; + node_ptr->match_count = match_count; + node_ptr->match_idx_or_idx_run_first = idx; + node_ptr += 1; + } + } + } + rdim_scratch_end(scratch); + } + + // rjf: sections for buckets/nodes + result.buckets = baked_buckets; + result.buckets_count = baked_buckets_count; + result.nodes = baked_nodes; + result.nodes_count = baked_nodes_count; + } + return result; +} + +//- rjf: partial bakes -> final bake functions + +RDI_PROC RDIM_NameMapBakeResult +rdim_name_map_bake_results_combine(RDIM_Arena *arena, RDIM_NameMapBakeResult *results, RDI_U64 results_count) +{ + RDIM_NameMapBakeResult result = {0}; + { + //- rjf: count needed # of buckets/nodes + RDI_U64 all_buckets_count = 0; + RDI_U64 all_nodes_count = 0; + for(RDI_U64 idx = 0; idx < results_count; idx += 1) + { + all_buckets_count += results[idx].buckets_count; + all_nodes_count += results[idx].nodes_count; + } + + //- rjf: allocate outputs + result.buckets_count = all_buckets_count; + result.buckets = rdim_push_array_no_zero(arena, RDI_NameMapBucket, result.buckets_count); + result.nodes_count = all_nodes_count; + result.nodes = rdim_push_array_no_zero(arena, RDI_NameMapNode, result.nodes_count); + + //- rjf: fill outputs + { + RDI_U64 buckets_off = 0; + RDI_U64 nodes_off = 0; + for(RDI_U64 idx = 0; idx < results_count; idx += 1) + { + rdim_memcpy(result.buckets + buckets_off, results[idx].buckets, sizeof(result.buckets[0])*results[idx].buckets_count); + rdim_memcpy(result.nodes + nodes_off, results[idx].nodes, sizeof(result.nodes[0])*results[idx].nodes_count); + buckets_off += results[idx].buckets_count; + nodes_off += results[idx].nodes_count; + } + } + } + return result; +} + +//- rjf: independent (top-level, global) baking functions + +RDI_PROC RDIM_TopLevelInfoBakeResult +rdim_bake_top_level_info(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_TopLevelInfo *src) +{ + RDIM_TopLevelInfoBakeResult result = {0}; + { + result.top_level_info = rdim_push_array(arena, RDI_TopLevelInfo, 1); + result.top_level_info->arch = src->arch; + result.top_level_info->exe_name_string_idx = rdim_bake_idx_from_string(strings, src->exe_name); + result.top_level_info->exe_hash = src->exe_hash; + result.top_level_info->voff_max = src->voff_max; + result.top_level_info->producer_name_string_idx = rdim_bake_idx_from_string(strings, src->producer_name); + } + return result; +} + +RDI_PROC RDIM_BinarySectionBakeResult +rdim_bake_binary_sections(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BinarySectionList *src) +{ + RDIM_BinarySectionBakeResult result = {0}; + { + RDI_BinarySection *dst_base = rdim_push_array(arena, RDI_BinarySection, src->count+1); + U64 dst_idx = 1; + for(RDIM_BinarySectionNode *src_n = src->first; src_n != 0; src_n = src_n->next, dst_idx += 1) + { + RDIM_BinarySection *src = &src_n->v; + RDI_BinarySection *dst = &dst_base[dst_idx]; + dst->name_string_idx = rdim_bake_idx_from_string(strings, src->name); + dst->flags = src->flags; + dst->voff_first = src->voff_first; + dst->voff_opl = src->voff_opl; + dst->foff_first = src->foff_first; + dst->foff_opl = src->foff_opl; + } + result.binary_sections = dst_base; + result.binary_sections_count = dst_idx; + } + return result; +} + +RDI_PROC RDIM_UnitBakeResult +rdim_bake_units(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakePathTree *path_tree, RDIM_UnitChunkList *src) +{ + RDIM_UnitBakeResult result = {0}; + { + RDI_Unit *dst_base = rdim_push_array(arena, RDI_Unit, src->total_count+1); + RDI_U64 dst_idx = 1; + for(RDIM_UnitChunkNode *src_n = src->first; src_n != 0; src_n = src_n->next) + { + for(RDI_U64 src_chunk_idx = 0; src_chunk_idx < src_n->count; src_chunk_idx += 1, dst_idx += 1) + { + RDIM_Unit *src = &src_n->v[src_chunk_idx]; + RDI_Unit *dst = &dst_base[dst_idx]; + dst->unit_name_string_idx = rdim_bake_idx_from_string(strings, src->unit_name); + dst->compiler_name_string_idx = rdim_bake_idx_from_string(strings, src->compiler_name); + dst->source_file_path_node = rdim_bake_path_node_idx_from_string(path_tree, src->source_file); + dst->object_file_path_node = rdim_bake_path_node_idx_from_string(path_tree, src->object_file); + dst->archive_file_path_node = rdim_bake_path_node_idx_from_string(path_tree, src->archive_file); + dst->build_path_node = rdim_bake_path_node_idx_from_string(path_tree, src->build_path); + dst->language = src->language; + dst->line_table_idx = (RDI_U32)rdim_idx_from_line_table(src->line_table); // TODO(rjf): @u64_to_u32 + } + } + result.units = dst_base; + result.units_count = dst_idx; + } + return result; +} + +RDI_PROC RDIM_UnitVMapBakeResult +rdim_bake_unit_vmap(RDIM_Arena *arena, RDIM_UnitChunkList *units) +{ + //- rjf: build vmap from unit voff ranges + RDIM_BakeVMap unit_vmap = {0}; + { + RDIM_Temp scratch = rdim_scratch_begin(&arena, 1); + + // rjf: count voff ranges + RDI_U64 voff_range_count = 0; + for(RDIM_UnitChunkNode *n = units->first; n != 0; n = n->next) + { + for(RDI_U64 idx = 0; idx < n->count; idx += 1) + { + RDIM_Unit *unit = &n->v[idx]; + voff_range_count += unit->voff_ranges.count; + } + } + + // rjf: count necessary markers + RDI_U64 marker_count = voff_range_count*2; + + // rjf: build keys/markers arrays + RDIM_SortKey *keys = rdim_push_array_no_zero(scratch.arena, RDIM_SortKey, marker_count); + RDIM_VMapMarker *markers = rdim_push_array_no_zero(scratch.arena, RDIM_VMapMarker, marker_count); + { + RDIM_SortKey *key_ptr = keys; + RDIM_VMapMarker *marker_ptr = markers; + RDI_U32 unit_idx = 1; + for(RDIM_UnitChunkNode *unit_chunk_n = units->first; + unit_chunk_n != 0; + unit_chunk_n = unit_chunk_n->next) + { + for(RDI_U64 idx = 0; idx < unit_chunk_n->count; idx += 1) + { + RDIM_Unit *unit = &unit_chunk_n->v[idx]; + for(RDIM_Rng1U64Node *n = unit->voff_ranges.first; n != 0; n = n->next) + { + RDIM_Rng1U64 range = n->v; + if(range.min < range.max) + { + key_ptr->key = range.min; + key_ptr->val = marker_ptr; + marker_ptr->idx = unit_idx; + marker_ptr->begin_range = 1; + key_ptr += 1; + marker_ptr += 1; + + key_ptr->key = range.max; + key_ptr->val = marker_ptr; + marker_ptr->idx = unit_idx; + marker_ptr->begin_range = 0; + key_ptr += 1; + marker_ptr += 1; + } + } + unit_idx += 1; + } + } + } + + // rjf: keys/markers -> unit vmap + unit_vmap = rdim_bake_vmap_from_markers(arena, markers, keys, marker_count); + rdim_scratch_end(scratch); + } + + //- rjf: fill result + RDIM_UnitVMapBakeResult result = {unit_vmap}; + return result; +} + +RDI_PROC RDIM_SrcFileBakeResult +rdim_bake_src_files(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakePathTree *path_tree, RDIM_SrcFileChunkList *src) +{ + RDIM_Temp scratch = rdim_scratch_begin(&arena, 1); + + //////////////////////////// + //- rjf: iterate all source files, fill serialized version, fill line maps, fill line map tables + // + typedef struct RDIM_DataNode RDIM_DataNode; + struct RDIM_DataNode + { + RDIM_DataNode *next; + void *data; + RDI_U64 size; + }; + RDI_U32 dst_files_count = src->total_count + 1; + RDI_U32 dst_maps_count = src->source_line_map_count + 1; + RDI_SourceFile *dst_files = rdim_push_array(arena, RDI_SourceFile, dst_files_count); + RDI_SourceLineMap *dst_maps = rdim_push_array(arena, RDI_SourceLineMap, dst_maps_count); + RDIM_DataNode *first_dst_nums_node = 0; + RDIM_DataNode *last_dst_nums_node = 0; + RDIM_DataNode *first_dst_rngs_node = 0; + RDIM_DataNode *last_dst_rngs_node = 0; + RDIM_DataNode *first_dst_voffs_node = 0; + RDIM_DataNode *last_dst_voffs_node = 0; + RDI_U64 dst_nums_idx = 0; + RDI_U64 dst_rngs_idx = 0; + RDI_U64 dst_voffs_idx = 0; + RDI_U32 dst_file_idx = 1; + RDI_U32 dst_map_idx = 1; + for(RDIM_SrcFileChunkNode *chunk_n = src->first; + chunk_n != 0; + chunk_n = chunk_n->next) + { + for(RDI_U64 idx = 0; idx < chunk_n->count; idx += 1, dst_file_idx += 1) + { + RDIM_SrcFile *src_file = &chunk_n->v[idx]; + RDI_SourceFile *dst_file = &dst_files[dst_file_idx]; + + //////////////////////// + //- rjf: produce combined source file line info + // + RDI_U32 *src_file_line_nums = 0; + RDI_U32 *src_file_line_ranges = 0; + RDI_U64 *src_file_voffs = 0; + RDI_U32 src_file_line_count = 0; + RDI_U32 src_file_voff_count = 0; + { + //- rjf: gather line number map + typedef struct RDIM_SrcLineMapVoffBlock RDIM_SrcLineMapVoffBlock; + struct RDIM_SrcLineMapVoffBlock + { + RDIM_SrcLineMapVoffBlock *next; + RDI_U64 voff; + }; + typedef struct RDIM_SrcLineMapBucket RDIM_SrcLineMapBucket; + struct RDIM_SrcLineMapBucket + { + RDIM_SrcLineMapBucket *order_next; + RDIM_SrcLineMapBucket *hash_next; + RDI_U32 line_num; + RDIM_SrcLineMapVoffBlock *first_voff_block; + RDIM_SrcLineMapVoffBlock *last_voff_block; + RDI_U64 voff_count; + }; + RDIM_SrcLineMapBucket *first_bucket = 0; + RDIM_SrcLineMapBucket *last_bucket = 0; + RDI_U64 line_hash_slots_count = 2048; + RDIM_SrcLineMapBucket **line_hash_slots = rdim_push_array(scratch.arena, RDIM_SrcLineMapBucket *, line_hash_slots_count); + RDI_U64 line_count = 0; + RDI_U64 voff_count = 0; + RDI_U64 max_line_num = 0; + { + for(RDIM_SrcFileLineMapFragment *map_fragment = src_file->first_line_map_fragment; + map_fragment != 0; + map_fragment = map_fragment->next) + { + RDIM_LineSequence *sequence = map_fragment->seq; + RDI_U64 *seq_voffs = sequence->voffs; + RDI_U32 *seq_line_nums = sequence->line_nums; + RDI_U64 seq_line_count = sequence->line_count; + for(RDI_U64 i = 0; i < seq_line_count; i += 1) + { + RDI_U32 line_num = seq_line_nums[i]; + RDI_U64 voff = seq_voffs[i]; + RDI_U64 line_hash_slot_idx = line_num%line_hash_slots_count; + + // rjf: update unique voff counter & max line number + voff_count += 1; + max_line_num = Max(max_line_num, line_num); + + // rjf: find match + RDIM_SrcLineMapBucket *match = 0; + { + for(RDIM_SrcLineMapBucket *node = line_hash_slots[line_hash_slot_idx]; + node != 0; + node = node->hash_next) + { + if(node->line_num == line_num) + { + match = node; + break; + } + } + } + + // rjf: introduce new map if no match + if(match == 0) + { + match = rdim_push_array(scratch.arena, RDIM_SrcLineMapBucket, 1); + RDIM_SLLQueuePush_N(first_bucket, last_bucket, match, order_next); + RDIM_SLLStackPush_N(line_hash_slots[line_hash_slot_idx], match, hash_next); + match->line_num = line_num; + line_count += 1; + } + + // rjf: insert new voff + { + RDIM_SrcLineMapVoffBlock *block = rdim_push_array(scratch.arena, RDIM_SrcLineMapVoffBlock, 1); + RDIM_SLLQueuePush(match->first_voff_block, match->last_voff_block, block); + match->voff_count += 1; + block->voff = voff; + } + } + } + } + + //- rjf: bake sortable keys array + RDIM_SortKey *keys = rdim_push_array_no_zero(scratch.arena, RDIM_SortKey, line_count); + { + RDIM_SortKey *key_ptr = keys; + for(RDIM_SrcLineMapBucket *node = first_bucket; + node != 0; + node = node->order_next, key_ptr += 1){ + key_ptr->key = node->line_num; + key_ptr->val = node; + } + } + + //- rjf: sort keys array + RDIM_SortKey *sorted_keys = rdim_sort_key_array(scratch.arena, keys, line_count); + + //- rjf: bake result + RDI_U32 *line_nums = rdim_push_array_no_zero(scratch.arena, RDI_U32, line_count); + RDI_U32 *line_ranges = rdim_push_array_no_zero(scratch.arena, RDI_U32, line_count + 1); + RDI_U64 *voffs = rdim_push_array_no_zero(scratch.arena, RDI_U64, voff_count); + { + RDI_U64 *voff_ptr = voffs; + for(RDI_U32 i = 0; i < line_count; i += 1) + { + line_nums[i] = sorted_keys[i].key; + line_ranges[i] = (RDI_U32)(voff_ptr - voffs); // TODO(rjf): @u64_to_u32 + RDIM_SrcLineMapBucket *bucket = (RDIM_SrcLineMapBucket*)sorted_keys[i].val; + for(RDIM_SrcLineMapVoffBlock *node = bucket->first_voff_block; node != 0; node = node->next) + { + *voff_ptr = node->voff; + voff_ptr += 1; + } + } + line_ranges[line_count] = voff_count; + } + + //- rjf: fill output + src_file_line_nums = line_nums; + src_file_line_ranges = line_ranges; + src_file_line_count = line_count; + src_file_voffs = voffs; + src_file_voff_count = voff_count; + } + + //////////////////////// + //- rjf: grab & fill the next line map, if this file has one + // + RDI_SourceLineMap *dst_map = 0; + if(src_file->first_line_map_fragment != 0) + { + dst_map = &dst_maps[dst_map_idx]; + dst_map_idx += 1; + dst_map->line_count = (RDI_U32)src_file_line_count; // TODO(rjf): @u64_to_u32 + dst_map->voff_count = (RDI_U32)src_file_voff_count; // TODO(rjf): @u64_to_u32 + dst_map->line_map_nums_base_idx = (RDI_U32)dst_nums_idx; // TODO(rjf): @u64_to_u32 + dst_map->line_map_range_base_idx = (RDI_U32)dst_rngs_idx; // TODO(rjf): @u64_to_u32 + dst_map->line_map_voff_base_idx = (RDI_U32)dst_voffs_idx; // TODO(rjf): @u64_to_u32 + } + + //////////////////////// + //- rjf: gather line map data chunks for later collation & storage into their own top-level sections + // + { + RDIM_DataNode *dst_num_node = rdim_push_array(scratch.arena, RDIM_DataNode, 1); + RDIM_SLLQueuePush(first_dst_nums_node, last_dst_nums_node, dst_num_node); + dst_num_node->data = src_file_line_nums; + dst_num_node->size = sizeof(RDI_U32)*src_file_line_count; + RDIM_DataNode *dst_rng_node = rdim_push_array(scratch.arena, RDIM_DataNode, 1); + RDIM_SLLQueuePush(first_dst_rngs_node, last_dst_rngs_node, dst_rng_node); + dst_rng_node->data = src_file_line_ranges; + dst_rng_node->size = sizeof(RDI_U32)*(src_file_line_count+1); + RDIM_DataNode *dst_voff_node = rdim_push_array(scratch.arena, RDIM_DataNode, 1); + RDIM_SLLQueuePush(first_dst_voffs_node, last_dst_voffs_node, dst_voff_node); + dst_voff_node->data = src_file_voffs; + dst_voff_node->size = sizeof(RDI_U64)*(src_file_voff_count); + dst_nums_idx += src_file_line_count; + dst_rngs_idx += src_file_line_count+1; + dst_voffs_idx+= src_file_voff_count; + } + + //////////////////////// + //- rjf: fill file info + // + dst_file->file_path_node_idx = rdim_bake_path_node_idx_from_string(path_tree, src_file->normal_full_path); + dst_file->normal_full_path_string_idx = rdim_bake_idx_from_string(strings, src_file->normal_full_path); + dst_file->source_line_map_idx = (RDI_U32)(dst_map ? (dst_map - dst_maps) : 0); + } + } + + //////////////////////////// + //- rjf: coalesce source line map data blobs + // + RDI_U32 *source_line_map_nums = rdim_push_array_no_zero(arena, RDI_U32, dst_nums_idx); + RDI_U32 *source_line_map_rngs = rdim_push_array_no_zero(arena, RDI_U32, dst_rngs_idx); + RDI_U64 *source_line_map_voffs= rdim_push_array_no_zero(arena, RDI_U64, dst_voffs_idx); + { + RDI_U64 num_idx = 0; + RDI_U64 rng_idx = 0; + RDI_U64 voff_idx= 0; + for(RDIM_DataNode *num_n = first_dst_nums_node; num_n != 0; num_n = num_n->next) + { + rdim_memcpy(source_line_map_nums+num_idx, num_n->data, num_n->size); + num_idx += num_n->size/sizeof(RDI_U32); + } + for(RDIM_DataNode *rng_n = first_dst_rngs_node; rng_n != 0; rng_n = rng_n->next) + { + rdim_memcpy(source_line_map_rngs+rng_idx, rng_n->data, rng_n->size); + rng_idx += rng_n->size/sizeof(RDI_U32); + } + for(RDIM_DataNode *voff_n = first_dst_voffs_node; voff_n != 0; voff_n = voff_n->next) + { + rdim_memcpy(source_line_map_voffs+voff_idx, voff_n->data, voff_n->size); + voff_idx += voff_n->size/sizeof(RDI_U64); + } + } + + //////////////////////////// + //- rjf: fill result + // + RDIM_SrcFileBakeResult result = {0}; + result.source_files = dst_files; + result.source_files_count = dst_files_count; + result.source_line_maps = dst_maps; + result.source_line_maps_count = dst_maps_count; + result.source_line_map_nums = source_line_map_nums; + result.source_line_map_nums_count = dst_nums_idx; + result.source_line_map_rngs = source_line_map_rngs; + result.source_line_map_rngs_count = dst_rngs_idx; + result.source_line_map_voffs = source_line_map_voffs; + result.source_line_map_voffs_count= dst_voffs_idx; + + rdim_scratch_end(scratch); + return result; +} + +RDI_PROC RDIM_LineTableBakeResult +rdim_bake_line_tables(RDIM_Arena *arena, RDIM_LineTableChunkList *src) +{ + ////////////////////////////// + //- rjf: build all combined line info + // + RDI_LineTable *dst_line_tables = push_array(arena, RDI_LineTable, src->total_count+1); + RDI_U64 *dst_line_voffs = push_array(arena, RDI_U64, src->total_line_count + 2*src->total_seq_count); + RDI_Line *dst_lines = push_array(arena, RDI_Line, src->total_line_count + src->total_seq_count); + RDI_Column *dst_cols = push_array(arena, RDI_Column, 1); + { + RDI_U64 dst_table_idx = 1; + RDI_U64 dst_voff_idx = 0; + RDI_U64 dst_line_idx = 0; + RDI_U64 dst_col_idx = 0; + for(RDIM_LineTableChunkNode *src_n = src->first; src_n != 0; src_n = src_n->next) + { + for(RDI_U64 chunk_idx = 0; chunk_idx < src_n->count; chunk_idx += 1) + { + RDIM_LineTable *src_line_table = &src_n->v[chunk_idx]; + RDI_LineTable *dst_line_table = &dst_line_tables[dst_table_idx]; + + //- rjf: fill combined line table info + { + RDIM_Temp scratch = rdim_scratch_begin(&arena, 1); + + //- rjf: gather up all line info into two arrays: + // + // [1] keys: sortable array; pairs voffs with line info records; null records are sequence enders + // [2] recs: contains all the source coordinates for a range of voffs + // + typedef struct RDIM_LineRec RDIM_LineRec; + struct RDIM_LineRec + { + RDI_U32 file_id; + RDI_U32 line_num; + RDI_U16 col_first; + RDI_U16 col_opl; + }; + RDI_U64 line_count = src_line_table->line_count; + RDI_U64 seq_count = src_line_table->seq_count; + RDI_U64 key_count = line_count + seq_count; + RDIM_SortKey *line_keys = rdim_push_array_no_zero(scratch.arena, RDIM_SortKey, key_count); + RDIM_LineRec *line_recs = rdim_push_array_no_zero(scratch.arena, RDIM_LineRec, line_count); + { + RDIM_SortKey *key_ptr = line_keys; + RDIM_LineRec *rec_ptr = line_recs; + for(RDIM_LineSequenceNode *seq_n = src_line_table->first_seq; seq_n != 0; seq_n = seq_n->next) + { + RDIM_LineSequence *seq = &seq_n->v; + for(RDI_U64 line_idx = 0; line_idx < seq->line_count; line_idx += 1) + { + key_ptr->key = seq->voffs[line_idx]; + key_ptr->val = rec_ptr; + key_ptr += 1; + rec_ptr->file_id = (RDI_U32)rdim_idx_from_src_file(seq->src_file); // TODO(rjf): @u64_to_u32 + rec_ptr->line_num = seq->line_nums[line_idx]; + if(seq->col_nums != 0) + { + rec_ptr->col_first = seq->col_nums[line_idx*2]; + rec_ptr->col_opl = seq->col_nums[line_idx*2 + 1]; + } + rec_ptr += 1; + } + key_ptr->key = seq->voffs[seq->line_count]; + key_ptr->val = 0; + key_ptr += 1; + } + } + + //- rjf: sort + RDIM_SortKey *sorted_line_keys = 0; + { + sorted_line_keys = rdim_sort_key_array(scratch.arena, line_keys, key_count); + } + + // TODO(rjf): do a pass over sorted keys to make sure duplicate keys + // are sorted with null record first, and no more than one null + // record and one non-null record + + //- rjf: arrange output + RDI_U64 *arranged_voffs = dst_line_voffs + dst_voff_idx; + RDI_Line *arranged_lines = dst_lines + dst_line_idx; + { + for(RDI_U64 i = 0; i < key_count; i += 1) + { + arranged_voffs[i] = sorted_line_keys[i].key; + } + arranged_voffs[key_count] = ~0ull; + for(RDI_U64 i = 0; i < key_count; i += 1) + { + RDIM_LineRec *rec = (RDIM_LineRec*)sorted_line_keys[i].val; + if(rec != 0) + { + arranged_lines[i].file_idx = rec->file_id; + arranged_lines[i].line_num = rec->line_num; + } + else + { + arranged_lines[i].file_idx = 0; + arranged_lines[i].line_num = 0; + } + } + } + + rdim_scratch_end(scratch); + } + + //- rjf: fill destination table + dst_line_table->voffs_base_idx = (RDI_U32)dst_voff_idx; // TODO(rjf): @u64_to_u32 + dst_line_table->lines_base_idx = (RDI_U32)dst_line_idx; // TODO(rjf): @u64_to_u32 + dst_line_table->cols_base_idx = (RDI_U32)dst_col_idx; // TODO(rjf): @u64_to_u32 + dst_line_table->lines_count = (RDI_U32)src_line_table->line_count + src_line_table->seq_count; // TODO(rjf): @u64_to_u32 + + //- rjf: increment + dst_table_idx += 1; + dst_voff_idx += src_line_table->line_count + 2*src_line_table->seq_count; + dst_line_idx += src_line_table->line_count + src_line_table->seq_count; + } + } + } + + ////////////////////////////// + //- rjf: fill result + // + RDIM_LineTableBakeResult result = {0}; + { + result.line_tables = dst_line_tables; + result.line_tables_count = src->total_count+1; + result.line_table_voffs = dst_line_voffs; + result.line_table_voffs_count = (src->total_line_count + 2*src->total_seq_count); + result.line_table_lines = dst_lines; + result.line_table_lines_count = (src->total_line_count + src->total_seq_count); + result.line_table_columns = dst_cols; + result.line_table_columns_count = src->total_col_count; + } + return result; +} + +RDI_PROC RDIM_TypeNodeBakeResult +rdim_bake_types(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakeIdxRunMap *idx_runs, RDIM_TypeChunkList *src) +{ + RDI_TypeNode *type_nodes = push_array(arena, RDI_TypeNode, src->total_count+1); + RDI_U32 dst_idx = 1; + for(RDIM_TypeChunkNode *n = src->first; n != 0; n = n->next) + { + for(RDI_U64 chunk_idx = 0; chunk_idx < n->count; chunk_idx += 1, dst_idx += 1) + { + RDIM_Type *src = &n->v[chunk_idx]; + RDI_TypeNode *dst = &type_nodes[dst_idx]; + + //- rjf: fill shared type node info + dst->kind = src->kind; + dst->flags = (RDI_U16)src->flags; // TODO(rjf): @u32_to_u16 + dst->byte_size = src->byte_size; + + //- rjf: fill built-in-only type node info + if(RDI_TypeKind_FirstBuiltIn <= dst->kind && dst->kind <= RDI_TypeKind_LastBuiltIn) + { + dst->built_in.name_string_idx = rdim_bake_idx_from_string(strings, src->name); + } + + //- rjf: fill constructed type node info + else if(RDI_TypeKind_FirstConstructed <= dst->kind && dst->kind <= RDI_TypeKind_LastConstructed) + { + dst->constructed.direct_type_idx = (RDI_U32)rdim_idx_from_type(src->direct_type); // TODO(rjf): @u64_to_u32 + dst->constructed.count = src->count; + if(dst->kind == RDI_TypeKind_Function || dst->kind == RDI_TypeKind_Method) + { + RDI_U32 param_idx_run_count = src->count; + RDI_U32 *param_idx_run = rdim_push_array_no_zero(arena, RDI_U32, param_idx_run_count); + for(RDI_U32 idx = 0; idx < param_idx_run_count; idx += 1) + { + param_idx_run[idx] = (RDI_U32)rdim_idx_from_type(src->param_types[idx]); // TODO(rjf): @u64_to_u32 + } + dst->constructed.param_idx_run_first = rdim_bake_idx_from_idx_run(idx_runs, param_idx_run, param_idx_run_count); + } + else if(dst->kind == RDI_TypeKind_MemberPtr) + { + // TODO(rjf): member pointers not currently supported. + } + } + + //- rjf: fill user-defined-type info + else if(RDI_TypeKind_FirstUserDefined <= dst->kind && dst->kind <= RDI_TypeKind_LastUserDefined) + { + dst->user_defined.name_string_idx = rdim_bake_idx_from_string(strings, src->name); + dst->user_defined.udt_idx = (RDI_U32)rdim_idx_from_udt(src->udt); // TODO(rjf): @u64_to_u32 + dst->user_defined.direct_type_idx = (RDI_U32)rdim_idx_from_type(src->direct_type); // TODO(rjf): @u64_to_u32 + } + + //- rjf: fill bitfield info + else if(dst->kind == RDI_TypeKind_Bitfield) + { + dst->bitfield.direct_type_idx = (RDI_U32)rdim_idx_from_type(src->direct_type); // TODO(rjf): @u64_to_u32 + dst->bitfield.off = src->off; + dst->bitfield.size = src->count; + } + } + } + RDIM_TypeNodeBakeResult result = {0}; + result.type_nodes = type_nodes; + result.type_nodes_count = (src->total_count+1); + return result; +} + +RDI_PROC RDIM_UDTBakeResult +rdim_bake_udts(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_UDTChunkList *src) +{ + //- rjf: build tables + RDI_UDT * udts = push_array(arena, RDI_UDT, src->total_count+1); + RDI_Member * members = push_array(arena, RDI_Member, src->total_member_count+1); + RDI_EnumMember *enum_members = push_array(arena, RDI_EnumMember, src->total_enum_val_count+1); + { + RDI_U32 dst_udt_idx = 1; + RDI_U32 dst_member_idx = 1; + RDI_U32 dst_enum_member_idx = 1; + for(RDIM_UDTChunkNode *n = src->first; n != 0; n = n->next) + { + for(RDI_U64 chunk_idx = 0; chunk_idx < n->count; chunk_idx += 1, dst_udt_idx += 1) + { + RDIM_UDT *src_udt = &n->v[chunk_idx]; + RDI_UDT *dst_udt = &udts[dst_udt_idx]; + + //- rjf: fill basics + dst_udt->self_type_idx = (RDI_U32)rdim_idx_from_type(src_udt->self_type); // TODO(rjf): @u64_to_u32 + dst_udt->file_idx = (RDI_U32)rdim_idx_from_src_file(src_udt->src_file); // TODO(rjf): @u64_to_u32 + dst_udt->line = src_udt->line; + dst_udt->col = src_udt->col; + + //- rjf: fill members + if(src_udt->member_count != 0) + { + dst_udt->member_first = dst_member_idx; + dst_udt->member_count = src_udt->member_count; + for(RDIM_UDTMember *src_member = src_udt->first_member; + src_member != 0; + src_member = src_member->next, dst_member_idx += 1) + { + RDI_Member *dst_member = &members[dst_member_idx]; + dst_member->kind = src_member->kind; + dst_member->name_string_idx = rdim_bake_idx_from_string(strings, src_member->name); + dst_member->type_idx = (RDI_U32)rdim_idx_from_type(src_member->type); // TODO(rjf): @u64_to_u32 + dst_member->off = src_member->off; + } + } + + //- rjf: fill enum members + else if(src_udt->enum_val_count != 0) + { + dst_udt->flags |= RDI_UDTFlag_EnumMembers; + dst_udt->member_first = dst_enum_member_idx; + dst_udt->member_count = src_udt->enum_val_count; + for(RDIM_UDTEnumVal *src_member = src_udt->first_enum_val; + src_member != 0; + src_member = src_member->next, dst_enum_member_idx += 1) + { + RDI_EnumMember *dst_member = &enum_members[dst_enum_member_idx]; + dst_member->name_string_idx = rdim_bake_idx_from_string(strings, src_member->name); + dst_member->val = src_member->val; + } + } + } + } + } + + //- rjf: fill result + RDIM_UDTBakeResult result = {0}; + { + result.udts = udts; + result.udts_count = src->total_count+1; + result.members = members; + result.members_count = src->total_member_count+1; + result.enum_members = enum_members; + result.enum_members_count = src->total_enum_val_count+1; + } + return result; +} + +RDI_PROC RDIM_GlobalVariableBakeResult +rdim_bake_global_variables(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_SymbolChunkList *src) +{ + RDI_GlobalVariable *global_variables = push_array(arena, RDI_GlobalVariable, src->total_count+1); + RDI_U32 dst_idx = 1; + for(RDIM_SymbolChunkNode *n = src->first; n != 0; n = n->next) + { + for(RDI_U64 chunk_idx = 0; chunk_idx < n->count; chunk_idx += 1, dst_idx += 1) + { + RDIM_Symbol *src = &n->v[chunk_idx]; + RDI_GlobalVariable *dst = &global_variables[dst_idx]; + dst->name_string_idx = rdim_bake_idx_from_string(strings, src->name); + dst->voff = src->offset; + dst->type_idx = (RDI_U32)rdim_idx_from_type(src->type); // TODO(rjf): @u64_to_u32 + if(src->is_extern) + { + dst->link_flags |= RDI_LinkFlag_External; + } + if(src->container_type != 0) + { + dst->link_flags |= RDI_LinkFlag_TypeScoped; + dst->container_idx = src->container_type ? (RDI_U32)rdim_idx_from_udt(src->container_type->udt) : 0; // TODO(rjf): @u64_to_u32 + } + else if(src->container_symbol != 0) + { + dst->link_flags |= RDI_LinkFlag_ProcScoped; + dst->container_idx = (RDI_U32)rdim_idx_from_symbol(src->container_symbol); // TODO(rjf): @u64_to_u32 + } + } + } + RDIM_GlobalVariableBakeResult result = {0}; + result.global_variables = global_variables; + result.global_variables_count = (src->total_count+1); + return result; +} + +RDI_PROC RDIM_GlobalVMapBakeResult +rdim_bake_global_vmap(RDIM_Arena *arena, RDIM_SymbolChunkList *src) +{ + //- rjf: build global vmap + RDIM_BakeVMap global_vmap = {0}; + { + RDIM_Temp scratch = rdim_scratch_begin(&arena, 1); + + //- rjf: allocate keys/markers + RDI_U64 marker_count = src->total_count*2; + RDIM_SortKey *keys = rdim_push_array_no_zero(scratch.arena, RDIM_SortKey, marker_count); + RDIM_VMapMarker *markers = rdim_push_array_no_zero(scratch.arena, RDIM_VMapMarker, marker_count); + + //- rjf: fill + { + RDIM_SortKey *key_ptr = keys; + RDIM_VMapMarker *marker_ptr = markers; + + // rjf: fill actual globals + for(RDIM_SymbolChunkNode *n = src->first; n != 0; n = n->next) + { + for(RDI_U64 chunk_idx = 0; chunk_idx < n->count; chunk_idx += 1) + { + RDIM_Symbol *global_var = &n->v[chunk_idx]; + RDI_U32 global_var_idx = (RDI_U32)rdim_idx_from_symbol(global_var); // TODO(rjf): @u64_to_u32 + RDI_U64 global_var_size = global_var->type ? global_var->type->byte_size : 1; + + RDI_U64 first = global_var->offset; + RDI_U64 opl = first + global_var_size; + + key_ptr->key = first; + key_ptr->val = marker_ptr; + marker_ptr->idx = global_var_idx; + marker_ptr->begin_range = 1; + key_ptr += 1; + marker_ptr += 1; + + key_ptr->key = opl; + key_ptr->val = marker_ptr; + marker_ptr->idx = global_var_idx; + marker_ptr->begin_range = 0; + key_ptr += 1; + marker_ptr += 1; + } + } + + // rjf: fill nil global + { + RDI_U32 global_idx = 0; + RDI_U64 first = 0; + RDI_U64 opl = 0xffffffffffffffffull; + key_ptr->key = first; + key_ptr->val = marker_ptr; + marker_ptr->idx = global_idx; + marker_ptr->begin_range = 1; + key_ptr += 1; + marker_ptr += 1; + key_ptr->key = opl; + key_ptr->val = marker_ptr; + marker_ptr->idx = global_idx; + marker_ptr->begin_range = 0; + key_ptr += 1; + marker_ptr += 1; + } + } + + // rjf: construct vmap + global_vmap = rdim_bake_vmap_from_markers(arena, markers, keys, marker_count); + + rdim_scratch_end(scratch); + } + + //- rjf: fill result + RDIM_GlobalVMapBakeResult result = {global_vmap}; + return result; +} + +RDI_PROC RDIM_ThreadVariableBakeResult +rdim_bake_thread_variables(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_SymbolChunkList *src) +{ + RDI_ThreadVariable *thread_variables = push_array(arena, RDI_ThreadVariable, src->total_count+1); + RDI_U32 dst_idx = 1; + for(RDIM_SymbolChunkNode *n = src->first; n != 0; n = n->next) + { + for(RDI_U64 chunk_idx = 0; chunk_idx < n->count; chunk_idx += 1, dst_idx += 1) + { + RDIM_Symbol *src = &n->v[chunk_idx]; + RDI_ThreadVariable *dst = &thread_variables[dst_idx]; + dst->name_string_idx = rdim_bake_idx_from_string(strings, src->name); + dst->tls_off = (RDI_U32)src->offset; // TODO(rjf): @u64_to_u32 + dst->type_idx = (RDI_U32)rdim_idx_from_type(src->type); + if(src->is_extern) + { + dst->link_flags |= RDI_LinkFlag_External; + } + if(src->container_type != 0) + { + dst->link_flags |= RDI_LinkFlag_TypeScoped; + dst->container_idx = src->container_type ? (RDI_U32)rdim_idx_from_udt(src->container_type->udt) : 0; // TODO(rjf): @u64_to_u32 + } + else if(src->container_symbol != 0) + { + dst->link_flags |= RDI_LinkFlag_ProcScoped; + dst->container_idx = (RDI_U32)rdim_idx_from_symbol(src->container_symbol); // TODO(rjf): @u64_to_u32 + } + } + } + RDIM_ThreadVariableBakeResult result = {0}; + result.thread_variables = thread_variables; + result.thread_variables_count = src->total_count+1; + return result; +} + +RDI_PROC RDIM_ProcedureBakeResult +rdim_bake_procedures(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_SymbolChunkList *src) +{ + RDI_Procedure *procedures = push_array(arena, RDI_Procedure, src->total_count+1); + RDI_U32 dst_idx = 1; + for(RDIM_SymbolChunkNode *n = src->first; n != 0; n = n->next) + { + for(RDI_U64 chunk_idx = 0; chunk_idx < n->count; chunk_idx += 1, dst_idx += 1) + { + RDIM_Symbol *src = &n->v[chunk_idx]; + RDI_Procedure *dst = &procedures[dst_idx]; + dst->name_string_idx = rdim_bake_idx_from_string(strings, src->name); + dst->link_name_string_idx = rdim_bake_idx_from_string(strings, src->link_name); + if(src->is_extern) + { + dst->link_flags |= RDI_LinkFlag_External; + } + if(src->container_type != 0) + { + dst->link_flags |= RDI_LinkFlag_TypeScoped; + dst->container_idx = src->container_type ? (RDI_U32)rdim_idx_from_udt(src->container_type->udt) : 0; // TODO(rjf): @u64_to_u32 + } + else if(src->container_symbol != 0) + { + dst->link_flags |= RDI_LinkFlag_ProcScoped; + dst->container_idx = (RDI_U32)rdim_idx_from_symbol(src->container_symbol); // TODO(rjf): @u64_to_u32 + } + dst->type_idx = (RDI_U32)rdim_idx_from_type(src->type); // TODO(rjf): @u64_to_u32 + dst->root_scope_idx = (RDI_U32)rdim_idx_from_scope(src->root_scope); // TODO(rjf): @u64_to_u32 + } + } + RDIM_ProcedureBakeResult result = {0}; + result.procedures = procedures; + result.procedures_count = src->total_count+1; + return result; +} + +RDI_PROC RDIM_ScopeBakeResult +rdim_bake_scopes(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_ScopeChunkList *src) +{ + RDIM_Temp scratch = rdim_scratch_begin(&arena, 1); + + //////////////////////////// + //- rjf: build all scopes, scope voffs, locals, and location blocks + // + RDI_Scope * scopes = rdim_push_array(arena, RDI_Scope, src->total_count+1); + RDI_U64 * scope_voffs = rdim_push_array(arena, RDI_U64, src->scope_voff_count+1); + RDI_Local * locals = rdim_push_array(arena, RDI_Local, src->local_count+1); + RDI_LocationBlock * location_blocks = rdim_push_array(arena, RDI_LocationBlock, src->location_count+1); + RDIM_String8List location_data_blobs = {0}; + RDIM_ProfScope("build all scopes, scope voffs, locals, and location blocks") + { + RDI_U64 dst_scope_idx = 1; + RDI_U64 dst_scope_voff_idx = 1; + RDI_U64 dst_local_idx = 1; + RDI_U64 dst_location_block_idx = 1; + for(RDIM_ScopeChunkNode *chunk_n = src->first; chunk_n != 0; chunk_n = chunk_n->next) + { + for(RDI_U64 chunk_idx = 0; chunk_idx < chunk_n->count; chunk_idx += 1, dst_scope_idx += 1) + { + RDIM_Scope *src_scope = &chunk_n->v[chunk_idx]; + RDI_Scope *dst_scope = &scopes[dst_scope_idx]; + + //- rjf: push scope's voffs + RDI_U64 voff_idx_first = dst_scope_voff_idx; + { + for(RDIM_Rng1U64Node *n = src_scope->voff_ranges.first; n != 0; n = n->next) + { + scope_voffs[dst_scope_voff_idx] = n->v.min; + dst_scope_voff_idx += 1; + scope_voffs[dst_scope_voff_idx] = n->v.max; + dst_scope_voff_idx += 1; + } + } + RDI_U64 voff_idx_opl = dst_scope_voff_idx; + + //- rjf: push locals + RDI_U64 local_idx_first = dst_local_idx; + for(RDIM_Local *src_local = src_scope->first_local; + src_local != 0; + src_local = src_local->next, dst_local_idx += 1) + { + //- rjf: push local's locations + RDI_U64 location_block_idx_first = dst_location_block_idx; + for(RDIM_LocationCase *loccase = src_local->locset.first_location_case; + loccase != 0; + loccase = loccase->next, dst_location_block_idx += 1) + { + // rjf: fill location block + RDI_LocationBlock *dst_locblock = &location_blocks[dst_location_block_idx]; + dst_locblock->scope_off_first = loccase->voff_range.min; + dst_locblock->scope_off_opl = loccase->voff_range.max; + dst_locblock->location_data_off = location_data_blobs.total_size; + + // rjf: serialize location into location data + RDIM_Location *src_location = loccase->location; + { + // rjf: nil location + if(src_location == 0) + { + rdim_str8_list_push_align(scratch.arena, &location_data_blobs, 8); + rdim_str8_list_push(scratch.arena, &location_data_blobs, rdim_str8_lit("\0")); + } + + // rjf: valid location + else switch(src_location->kind) + { + // rjf: catchall unsupported case + default: + { + rdim_str8_list_push_align(scratch.arena, &location_data_blobs, 8); + rdim_str8_list_push(scratch.arena, &location_data_blobs, rdim_str8_lit("\0")); + }break; + + // rjf: bytecode streams + case RDI_LocationKind_AddrBytecodeStream: + case RDI_LocationKind_ValBytecodeStream: + { + rdim_str8_list_push(scratch.arena, &location_data_blobs, rdim_str8_copy(scratch.arena, rdim_str8_struct(&src_location->kind))); + for(RDIM_EvalBytecodeOp *op_node = src_location->bytecode.first_op; + op_node != 0; + op_node = op_node->next) + { + RDI_U8 op_data[9]; + op_data[0] = op_node->op; + rdim_memcpy(op_data + 1, &op_node->p, op_node->p_size); + RDIM_String8 op_data_str = rdim_str8(op_data, 1 + op_node->p_size); + rdim_str8_list_push(scratch.arena, &location_data_blobs, rdim_str8_copy(scratch.arena, op_data_str)); + } + { + RDI_U64 data = 0; + RDIM_String8 data_str = rdim_str8((RDI_U8 *)&data, 1); + rdim_str8_list_push(scratch.arena, &location_data_blobs, rdim_str8_copy(scratch.arena, data_str)); + } + }break; + + // rjf: simple addr+off cases + case RDI_LocationKind_AddrRegPlusU16: + case RDI_LocationKind_AddrAddrRegPlusU16: + { + RDI_LocationRegPlusU16 loc = {0}; + loc.kind = src_location->kind; + loc.reg_code = src_location->reg_code; + loc.offset = src_location->offset; + rdim_str8_list_push(scratch.arena, &location_data_blobs, rdim_str8_copy(scratch.arena, rdim_str8_struct(&loc))); + }break; + + // rjf: register cases + case RDI_LocationKind_ValReg: + { + RDI_LocationReg loc = {0}; + loc.kind = src_location->kind; + loc.reg_code = src_location->reg_code; + rdim_str8_list_push(scratch.arena, &location_data_blobs, rdim_str8_copy(scratch.arena, rdim_str8_struct(&loc))); + }break; + } + } + } + RDI_U64 location_block_idx_opl = dst_location_block_idx; + + //- rjf: fill local + RDI_Local *dst_local = &locals[dst_local_idx]; + dst_local->kind = src_local->kind; + dst_local->name_string_idx = rdim_bake_idx_from_string(strings, src_local->name); + dst_local->type_idx = (RDI_U32)rdim_idx_from_type(src_local->type); // TODO(rjf): @u64_to_u32 + dst_local->location_first = (RDI_U32)location_block_idx_first; // TODO(rjf): @u64_to_u32 + dst_local->location_opl = (RDI_U32)location_block_idx_opl; // TODO(rjf): @u64_to_u32 + } + RDI_U64 local_idx_opl = dst_local_idx; + + //- rjf: fill scope + dst_scope->proc_idx = (RDI_U32)rdim_idx_from_symbol(src_scope->symbol); // TODO(rjf): @u64_to_u32 + dst_scope->parent_scope_idx = (RDI_U32)rdim_idx_from_scope(src_scope->parent_scope); // TODO(rjf): @u64_to_u32 + dst_scope->first_child_scope_idx = (RDI_U32)rdim_idx_from_scope(src_scope->first_child); // TODO(rjf): @u64_to_u32 + dst_scope->next_sibling_scope_idx = (RDI_U32)rdim_idx_from_scope(src_scope->next_sibling); // TODO(rjf): @u64_to_u32 + dst_scope->voff_range_first = (RDI_U32)voff_idx_first; // TODO(rjf): @u64_to_u32 + dst_scope->voff_range_opl = (RDI_U32)voff_idx_opl; // TODO(rjf): @u64_to_u32 + dst_scope->local_first = (RDI_U32)local_idx_first; // TODO(rjf): @u64_to_u32 + dst_scope->local_count = (RDI_U32)(local_idx_opl - local_idx_first); // TODO(rjf): @u64_to_u32 + dst_scope->inline_site_idx = (RDI_U32)rdim_idx_from_inline_site(src_scope->inline_site); // TODO(rjf): @u64_to_u32 + } + } + } + + //////////////////////////// + //- rjf: build flattened location data + // + RDIM_String8 location_data_blob = {0}; + RDIM_ProfScope("build flattened location data") + { + location_data_blob = rdim_str8_list_join(arena, &location_data_blobs, rdim_str8_lit("")); + } + + //////////////////////////// + //- rjf: fill result + // + RDIM_ScopeBakeResult result = {0}; + result.scopes = scopes; + result.scopes_count = src->total_count+1; + result.scope_voffs = scope_voffs; + result.scope_voffs_count = src->scope_voff_count+1; + result.locals = locals; + result.locals_count = src->local_count+1; + result.location_blocks = location_blocks; + result.location_blocks_count = src->location_count+1; + result.location_data = location_data_blob.str; + result.location_data_size = location_data_blob.size; + rdim_scratch_end(scratch); + return result; +} + +RDI_PROC RDIM_ScopeVMapBakeResult +rdim_bake_scope_vmap(RDIM_Arena *arena, RDIM_ScopeChunkList *src) +{ + RDIM_BakeVMap scope_vmap = {0}; + { + RDIM_Temp scratch = rdim_scratch_begin(&arena, 1); + + // rjf: allocate keys/markers + RDI_U64 marker_count = src->scope_voff_count; + RDIM_SortKey *keys = rdim_push_array_no_zero(scratch.arena, RDIM_SortKey, marker_count); + RDIM_VMapMarker *markers = rdim_push_array_no_zero(scratch.arena, RDIM_VMapMarker, marker_count); + + // rjf: fill + { + RDIM_SortKey *key_ptr = keys; + RDIM_VMapMarker *marker_ptr = markers; + for(RDIM_ScopeChunkNode *chunk_n = src->first; chunk_n != 0; chunk_n = chunk_n->next) + { + for(RDI_U64 chunk_idx = 0; chunk_idx < chunk_n->count; chunk_idx += 1) + { + RDIM_Scope *src_scope = &chunk_n->v[chunk_idx]; + RDI_U32 scope_idx = (RDI_U32)rdim_idx_from_scope(src_scope); // TODO(rjf): @u64_to_u32 + for(RDIM_Rng1U64Node *n = src_scope->voff_ranges.first; n != 0; n = n->next) + { + key_ptr->key = n->v.min; + key_ptr->val = marker_ptr; + marker_ptr->idx = scope_idx; + marker_ptr->begin_range = 1; + key_ptr += 1; + marker_ptr += 1; + + key_ptr->key = n->v.max; + key_ptr->val = marker_ptr; + marker_ptr->idx = scope_idx; + marker_ptr->begin_range = 0; + key_ptr += 1; + marker_ptr += 1; + } + } + } + } + + // rjf: produce vmap + scope_vmap = rdim_bake_vmap_from_markers(arena, markers, keys, marker_count); + rdim_scratch_end(scratch); + } + RDIM_ScopeVMapBakeResult result = {scope_vmap}; + return result; +} + +RDI_PROC RDIM_InlineSiteBakeResult +rdim_bake_inline_sites(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_InlineSiteChunkList *src) +{ + RDIM_InlineSiteBakeResult result = {0}; + { + result.inline_sites_count = src->total_count; + result.inline_sites = rdim_push_array(arena, RDI_InlineSite, result.inline_sites_count+1); + RDI_U64 dst_idx = 1; + for(RDIM_InlineSiteChunkNode *n = src->first; n != 0; n = n->next) + { + for(RDI_U64 chunk_idx = 0; chunk_idx < n->count; chunk_idx += 1, dst_idx += 1) + { + RDI_InlineSite *dst = &result.inline_sites[dst_idx]; + RDIM_InlineSite *src = &n->v[chunk_idx]; + dst->name_string_idx = rdim_bake_idx_from_string(strings, src->name); + dst->type_idx = (RDI_U32)rdim_idx_from_type(src->type); // TODO(rjf): @u64_to_u32 + dst->owner_type_idx = (RDI_U32)rdim_idx_from_type(src->owner); // TODO(rjf): @u64_to_u32 + dst->line_table_idx = (RDI_U32)rdim_idx_from_line_table(src->line_table); // TODO(rjf): @u64_to_u32 + } + } + } + return result; +} + +RDI_PROC RDIM_TopLevelNameMapBakeResult +rdim_bake_name_maps_top_level(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakeIdxRunMap *idx_runs, RDIM_BakeNameMap *name_maps[RDI_NameMapKind_COUNT]) +{ + RDI_NameMap *dst_maps = rdim_push_array(arena, RDI_NameMap, RDI_NameMapKind_COUNT); + { + RDI_U64 dst_map_bucket_idx = 0; + RDI_U64 dst_map_node_idx = 0; + for(RDI_NameMapKind k = (RDI_NameMapKind)(RDI_NameMapKind_NULL+1); + k < RDI_NameMapKind_COUNT; + k = (RDI_NameMapKind)(k+1)) + { + RDI_NameMap *dst_map = &dst_maps[k]; + RDIM_BakeNameMap *src_map = name_maps[k]; + dst_map->bucket_base_idx = (RDI_U32)dst_map_bucket_idx; // TODO(rjf): @u64_to_u32 + dst_map->node_base_idx = (RDI_U32)dst_map_node_idx; // TODO(rjf): @u64_to_u32 + dst_map->bucket_count = (RDI_U32)src_map->name_count; // TODO(rjf): @u64_to_u32 + dst_map->node_count = (RDI_U32)src_map->name_count; // TODO(rjf): @u64_to_u32 + dst_map_bucket_idx += dst_map->bucket_count; + dst_map_node_idx += dst_map->node_count; + } + } + RDIM_TopLevelNameMapBakeResult result = {0}; + result.name_maps = dst_maps; + result.name_maps_count = RDI_NameMapKind_COUNT; + return result; +} + +RDI_PROC RDIM_FilePathBakeResult +rdim_bake_file_paths(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakePathTree *path_tree) +{ + RDI_U32 dst_nodes_count = path_tree->count; + RDI_FilePathNode *dst_nodes = rdim_push_array(arena, RDI_FilePathNode, dst_nodes_count); + { + RDI_U32 dst_node_idx = 0; + for(RDIM_BakePathNode *src_node = path_tree->first; + src_node != 0; + src_node = src_node->next_order, dst_node_idx += 1) + { + RDI_FilePathNode *dst_node = &dst_nodes[dst_node_idx]; + dst_node->name_string_idx = rdim_bake_idx_from_string(strings, src_node->name); + dst_node->source_file_idx = rdim_idx_from_src_file(src_node->src_file); + if(src_node->parent != 0) + { + dst_node->parent_path_node = src_node->parent->idx; + } + if(src_node->first_child != 0) + { + dst_node->first_child = src_node->first_child->idx; + } + if(src_node->next_sibling != 0) + { + dst_node->next_sibling = src_node->next_sibling->idx; + } + } + } + RDIM_FilePathBakeResult result = {0}; + result.nodes = dst_nodes; + result.nodes_count = dst_nodes_count; + return result; +} + +RDI_PROC RDIM_StringBakeResult +rdim_bake_strings(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings) +{ + RDIM_BakeSectionList sections = {0}; + RDI_U32 *str_offs = rdim_push_array_no_zero(arena, RDI_U32, strings->total_count + 1); + RDI_U32 off_cursor = 0; + { + RDI_U32 *off_ptr = str_offs; + *off_ptr = 0; + off_ptr += 1; + for(RDI_U64 slot_idx = 0; slot_idx < strings->slots_count; slot_idx += 1) + { + for(RDIM_BakeStringChunkNode *n = strings->slots[slot_idx].first; n != 0; n = n->next) + { + for(RDI_U64 chunk_idx = 0; chunk_idx < n->count; chunk_idx += 1) + { + RDIM_BakeString *bake_string = &n->v[chunk_idx]; + *off_ptr = off_cursor; + off_cursor += bake_string->string.size; + off_ptr += 1; + } + } + } + } + RDI_U8 *buf = rdim_push_array(arena, RDI_U8, off_cursor); + { + RDI_U8 *ptr = buf; + for(RDI_U64 slot_idx = 0; slot_idx < strings->slots_count; slot_idx += 1) + { + for(RDIM_BakeStringChunkNode *n = strings->slots[slot_idx].first; n != 0; n = n->next) + { + for(RDI_U64 chunk_idx = 0; chunk_idx < n->count; chunk_idx += 1) + { + RDIM_BakeString *bake_string = &n->v[chunk_idx]; + rdim_memcpy(ptr, bake_string->string.str, bake_string->string.size); + ptr += bake_string->string.size; + } + } + } + } + RDIM_StringBakeResult result = {0}; + result.string_offs = str_offs; + result.string_offs_count = strings->total_count+1; + result.string_data = buf; + result.string_data_size = off_cursor; + return result; +} + +RDI_PROC RDIM_IndexRunBakeResult +rdim_bake_index_runs(RDIM_Arena *arena, RDIM_BakeIdxRunMap *idx_runs) +{ + RDI_U32 *idx_data = rdim_push_array_no_zero(arena, RDI_U32, idx_runs->idx_count); + { + RDI_U32 *out_ptr = idx_data; + RDI_U32 *opl = out_ptr + idx_runs->idx_count; + for(RDIM_BakeIdxRunNode *node = idx_runs->order_first; + node != 0 && out_ptr < opl; + node = node->order_next) + { + rdim_memcpy(out_ptr, node->idx_run, sizeof(*node->idx_run)*node->count); + out_ptr += node->count; + } + } + RDIM_IndexRunBakeResult result = {0}; + result.idx_runs = idx_data; + result.idx_count = idx_runs->idx_count; + return result; +} + +//////////////////////////////// +//~ rjf: [Serializing] Bake Results -> String Blobs + +RDI_PROC RDIM_SerializedSection +rdim_serialized_section_make_unpacked(void *data, RDI_U64 size) +{ + RDIM_SerializedSection s; + rdim_memzero_struct(&s); + s.data = data; + s.encoded_size = s.unpacked_size = size; + s.encoding = RDI_SectionEncoding_Unpacked; + return s; +} + +RDI_PROC RDIM_SerializedSectionBundle +rdim_serialized_section_bundle_from_bake_results(RDIM_BakeResults *results) +{ + RDIM_SerializedSectionBundle bundle; + rdim_memzero_struct(&bundle); + bundle.sections[RDI_SectionKind_TopLevelInfo] = rdim_serialized_section_make_unpacked_struct(results->top_level_info.top_level_info); + bundle.sections[RDI_SectionKind_StringData] = rdim_serialized_section_make_unpacked_array(results->strings.string_data, results->strings.string_data_size); + bundle.sections[RDI_SectionKind_StringTable] = rdim_serialized_section_make_unpacked_array(results->strings.string_offs, results->strings.string_offs_count); + bundle.sections[RDI_SectionKind_IndexRuns] = rdim_serialized_section_make_unpacked_array(results->idx_runs.idx_runs, results->idx_runs.idx_count); + bundle.sections[RDI_SectionKind_BinarySections] = rdim_serialized_section_make_unpacked_array(results->binary_sections.binary_sections, results->binary_sections.binary_sections_count); + bundle.sections[RDI_SectionKind_FilePathNodes] = rdim_serialized_section_make_unpacked_array(results->file_paths.nodes, results->file_paths.nodes_count); + bundle.sections[RDI_SectionKind_SourceFiles] = rdim_serialized_section_make_unpacked_array(results->src_files.source_files, results->src_files.source_files_count); + bundle.sections[RDI_SectionKind_LineTables] = rdim_serialized_section_make_unpacked_array(results->line_tables.line_tables, results->line_tables.line_tables_count); + bundle.sections[RDI_SectionKind_LineInfoVOffs] = rdim_serialized_section_make_unpacked_array(results->line_tables.line_table_voffs, results->line_tables.line_table_voffs_count); + bundle.sections[RDI_SectionKind_LineInfoLines] = rdim_serialized_section_make_unpacked_array(results->line_tables.line_table_lines, results->line_tables.line_table_lines_count); + bundle.sections[RDI_SectionKind_LineInfoColumns] = rdim_serialized_section_make_unpacked_array(results->line_tables.line_table_columns, results->line_tables.line_table_columns_count); + bundle.sections[RDI_SectionKind_SourceLineMaps] = rdim_serialized_section_make_unpacked_array(results->src_files.source_line_maps, results->src_files.source_line_maps_count); + bundle.sections[RDI_SectionKind_SourceLineMapNumbers] = rdim_serialized_section_make_unpacked_array(results->src_files.source_line_map_nums, results->src_files.source_line_map_nums_count); + bundle.sections[RDI_SectionKind_SourceLineMapRanges] = rdim_serialized_section_make_unpacked_array(results->src_files.source_line_map_rngs, results->src_files.source_line_map_rngs_count); + bundle.sections[RDI_SectionKind_SourceLineMapVOffs] = rdim_serialized_section_make_unpacked_array(results->src_files.source_line_map_voffs, results->src_files.source_line_map_voffs_count); + bundle.sections[RDI_SectionKind_Units] = rdim_serialized_section_make_unpacked_array(results->units.units, results->units.units_count); + bundle.sections[RDI_SectionKind_UnitVMap] = rdim_serialized_section_make_unpacked_array(results->unit_vmap.vmap.vmap, results->unit_vmap.vmap.count+1); + bundle.sections[RDI_SectionKind_TypeNodes] = rdim_serialized_section_make_unpacked_array(results->type_nodes.type_nodes, results->type_nodes.type_nodes_count); + bundle.sections[RDI_SectionKind_UDTs] = rdim_serialized_section_make_unpacked_array(results->udts.udts, results->udts.udts_count); + bundle.sections[RDI_SectionKind_Members] = rdim_serialized_section_make_unpacked_array(results->udts.members, results->udts.members_count); + bundle.sections[RDI_SectionKind_EnumMembers] = rdim_serialized_section_make_unpacked_array(results->udts.enum_members, results->udts.enum_members_count); + bundle.sections[RDI_SectionKind_GlobalVariables] = rdim_serialized_section_make_unpacked_array(results->global_variables.global_variables, results->global_variables.global_variables_count); + bundle.sections[RDI_SectionKind_GlobalVMap] = rdim_serialized_section_make_unpacked_array(results->global_vmap.vmap.vmap, results->global_vmap.vmap.count+1); + bundle.sections[RDI_SectionKind_ThreadVariables] = rdim_serialized_section_make_unpacked_array(results->thread_variables.thread_variables, results->thread_variables.thread_variables_count); + bundle.sections[RDI_SectionKind_Procedures] = rdim_serialized_section_make_unpacked_array(results->procedures.procedures, results->procedures.procedures_count); + bundle.sections[RDI_SectionKind_Scopes] = rdim_serialized_section_make_unpacked_array(results->scopes.scopes, results->scopes.scopes_count); + bundle.sections[RDI_SectionKind_ScopeVOffData] = rdim_serialized_section_make_unpacked_array(results->scopes.scope_voffs, results->scopes.scope_voffs_count); + bundle.sections[RDI_SectionKind_ScopeVMap] = rdim_serialized_section_make_unpacked_array(results->scope_vmap.vmap.vmap, results->scope_vmap.vmap.count+1); + bundle.sections[RDI_SectionKind_InlineSites] = rdim_serialized_section_make_unpacked_array(results->inline_sites.inline_sites, results->inline_sites.inline_sites_count); + bundle.sections[RDI_SectionKind_Locals] = rdim_serialized_section_make_unpacked_array(results->scopes.locals, results->scopes.locals_count); + bundle.sections[RDI_SectionKind_LocationBlocks] = rdim_serialized_section_make_unpacked_array(results->scopes.location_blocks, results->scopes.location_blocks_count); + bundle.sections[RDI_SectionKind_LocationData] = rdim_serialized_section_make_unpacked_array(results->scopes.location_data, results->scopes.location_data_size); + bundle.sections[RDI_SectionKind_NameMaps] = rdim_serialized_section_make_unpacked_array(results->top_level_name_maps.name_maps, results->top_level_name_maps.name_maps_count); + bundle.sections[RDI_SectionKind_NameMapBuckets] = rdim_serialized_section_make_unpacked_array(results->name_maps.buckets, results->name_maps.buckets_count); + bundle.sections[RDI_SectionKind_NameMapNodes] = rdim_serialized_section_make_unpacked_array(results->name_maps.nodes, results->name_maps.nodes_count); + return bundle; +} + +RDI_PROC RDIM_String8List +rdim_file_blobs_from_section_bundle(RDIM_Arena *arena, RDIM_SerializedSectionBundle *bundle) +{ + RDIM_String8List strings; + rdim_memzero_struct(&strings); + { + RDIM_Temp scratch = rdim_scratch_begin(&arena, 1); + + // rjf: push empty header & data section table + RDI_Header *rdi_header = rdim_push_array(arena, RDI_Header, 1); + RDI_Section *rdi_sections = rdim_push_array(arena, RDI_Section, RDI_SectionKind_COUNT); + rdim_str8_list_push(arena, &strings, rdim_str8_struct(rdi_header)); + rdim_str8_list_push_align(arena, &strings, 8); + U32 data_section_off = (U32)strings.total_size; + rdim_str8_list_push(arena, &strings, rdim_str8((RDI_U8 *)rdi_sections, sizeof(RDI_Section)*RDI_SectionKind_COUNT)); + + // rjf: fill baked header + { + rdi_header->magic = RDI_MAGIC_CONSTANT; + rdi_header->encoding_version = RDI_ENCODING_VERSION; + rdi_header->data_section_off = data_section_off; + rdi_header->data_section_count = RDI_SectionKind_COUNT; + } + + // rjf: fill baked data section table + for(RDI_SectionKind k = RDI_SectionKind_NULL; k < RDI_SectionKind_COUNT; k += 1) + { + RDI_Section *dst = rdi_sections+k; + U64 data_section_off = 0; + if(bundle->sections[k].encoded_size != 0) + { + rdim_str8_list_push_align(arena, &strings, 8); + data_section_off = strings.total_size; + rdim_str8_list_push(arena, &strings, rdim_str8((RDI_U8 *)bundle->sections[k].data, bundle->sections[k].encoded_size)); + } + dst->encoding = bundle->sections[k].encoding; + dst->off = data_section_off; + dst->encoded_size = bundle->sections[k].encoded_size; + dst->unpacked_size = bundle->sections[k].unpacked_size; + } + + rdim_scratch_end(scratch); + } + return strings; +} diff --git a/src/raddbg/raddbg.h b/src/raddbg/raddbg.h index 9d03bd2f..4186a1a9 100644 --- a/src/raddbg/raddbg.h +++ b/src/raddbg/raddbg.h @@ -1,472 +1,476 @@ -// Copyright (c) 2024 Epic Games Tools -// Licensed under the MIT license (https://opensource.org/license/mit/) - -//////////////////////////////// -//~ rjf: Frontend/UI Pass Tasks -// -// [ ] auto-scroll output window -// [ ] inline breakpoint hit_count -// [ ] to count hit counts, resolve all bps to addresses, check addresses -// against stopper thread's -// [ ] theme lister -> fonts & font sizes -// [ ] "Browse..." buttons should adopt a more relevant starting search path, -// if possible -// [ ] move breakpoints to being a global thing, not nested to particular files -// [ ] visualize all breakpoints everywhere - source view should show up in -// disasm, disasm should show up in source view, function should show up in -// both, etc. -// [ ] ** Function breakpoints should show up in the source listing. Without -// them being visible, it is confusing when you run and you stop there, -// because you're like "wait why did it stop" and then you later remember -// that's because there was a function breakpoint there. -// -// [ ] n-row table selection, in watch window & other UIs, multi-selection -// ctrl+C -// -// [ ] target/breakpoint/watch-pin reordering -// -// [ ] font lister -// [ ] per-panel font size overrides -// -// [ ] For the Scheduler window, it would be nice if you could dim or -// folderize threads that are not your threads - eg., if a thread doesn't -// have any resolved stack pointers in your executable code, then you can -// ignore it when you are focusing on your own code. I don't know what the -// best way to detect this is, other than by walking the call stack... one -// way might be to just have a way to separate threads you've named from -// threads you haven't? Or, there could even be a debugger-specific API -// that you use to tag them. Just some way that would make it easier to -// focus on your own threads. -// -// [ ] "concept key stack"; basically, any point in UI builder path has a stack -// of active "concept keys", which can be used to e.g. build context menus -// automatically (could just be a per-box attachment; right-click any -// point, search up the tree and see the concept keys) -// [ ] ui_next_event(...), built-in focus filtering, no need to manually check -// if(ui_is_focus_active()) - -//////////////////////////////// -//~ rjf: Hot, High Priority Tasks (Complete Unusability, Crashes, Fire-Worthy) -// -// [ ] PDB files distributed with the build are not found by DbgHelp!!! -// [ ] Jai compiler debugging crash - -//////////////////////////////// -//~ rjf: Hot, Medium Priority Tasks (Low-Hanging-Fruit Features, UI Jank, Cleanup) -// -// [ ] Setting the code_font/main_font values to a font name doesn't work. -// Should probably make note that you have to set it to a path to a TTF, -// since that's not normally how Windows fonts work. -// -// [ ] "root" concept in hash store, which buckets keys & allows usage code to -// jettison a collection of keys in retained mode fashion -// -// [ ] Jeff Notes -// [ ] sort locals by appearance in source code (or maybe just debug info) -// [ ] sum view rule -// [ ] plot view rule -// [ ] histogram view rule -// [ ] max view rule -// [ ] min view rule -// -// [ ] filesystem drag/drop support -// [ ] double-click vs. single-click for folder navigation, see if we can infer -// [ ] use backslashes on windows by default, forward slashes elsewhere -// -// [ ] investigate /DEBUG:FASTLINK - can we somehow alert that we do not -// support it? -// -// [ ] ** Converter performance & heuristics for asynchronously doing it early -// -// [ ] visualize conversion failures -// -// [ ] I was a little confused about what a profile file was. I understood -// what the user file was, but the profile file sounded like it should -// perhaps be per-project, yet it sounded like it was meant to be somewhat -// global? I don't have any feedback here because it probably will make -// sense once I use the debugger more, but I just thought I'd make a note -// to say that I was confused about it after reading the manual, so -// perhaps you could elaborate a little more on it in there. -// [ ] It wasn't clear to me how you save a user or project file. I can see -// how to load them, but not how you save them. Obviously I can just copy -// the files myself in the shell, but it seemed weird that there was no -// "save" option in the menus. -// -// [ ] Right-clicking on a thread in the Scheduler window pops up a context -// menu, but you can't actually see it because the tooltip for the thread -// draws on top of it, so you can't see the menu. -// -// [ ] In a "hover watch" (where you hover over a variable and it shows a pop- -// up watch window), if you expand an item near the bottom of the listing, -// it will be clipped to the bottom of the listing instead of showing the -// actual items (ie., it doesn't resize the listing based on what's -// actually visible) -// -// [ ] ** One very nice feature of RemedyBG that I use all the time is the -// ability to put "$err, hr" into the watch window, which will just show -// the value of GetLastError() as a string. This is super useful for -// debugging, so you don't have to litter your own code with it. -// -// [ ] Tooltip Coverage: -// [ ] lock icon -// [ ] "rotation arrow" icon next to executables -// -// [ ] For theme editing, when you hove the mouse over a theme color entry and -// it highlights that entry, it might help to temporarily change that -// color to white (or the inverse of the background color, or whatever) so -// that the user can see what things on the screen use that theme color. -// -// [ ] Theme window should include font scaling. I was able to find the -// command for increasing the font scale, but I imagine most people -// wouldn't think to look there. -// [ ] I had to go into the user file to change the font. That should probably -// be in the theme window? -// -// [ ] It'd be nice to have a "goto byte" option for source views, for jumping -// to error messages that are byte-based instead of line-based. -// -// [ ] @feature debug info overrides (both path-based AND module-based) -// -// [ ] C++ virtual inheritance member visualization in watch window - -//////////////////////////////// -//~ rjf: Hot, Low Priority Tasks (UI Opinions, Less-Serious Jank, Preferences, Cleanup) -// -// [ ] The hex format for color values in the config file was a real -// mindbender. It's prefixed with "0x", so I was assuming it was either -// Windows Big Endian (0xAARRGGBB) or Mac Little Endian (0xAABBGGRR). To -// my surprise, it was neither - it was actually web format (RRGGBBAA), -// which I was not expecting because that is normally written with a -// number sign (#AARRGGBB) not an 0x. -// -// [ ] Clicking on either side of a scroll bar is idiosyncratic. Normally, -// that is "page up" / "page down", but here it is "smooth scroll upward" -// / "smooth scroll downward" for some reason? -// -// [ ] can it ignore stepping into _RTC_CheckStackVars generated functions? -// [ ] mouse back button should make view to go back after I double clicked -// on function to open it -// [ ] Alt+8 to switch to disassembly would be nice (regardless on which -// panel was previous, don't want to use ctrl+, multiple times) -// Alt+8 for disasm and Alt+6 for memory view are shortcuts I often use -// in VS -// [ ] default font size is too small for me - not only source code, but -// menus/tab/watch names (which don't resize). Maybe you could query -// Windows for initial font size? -// [ ] icon fonts glyphs sometimes disappear for specific font size, but they -// reappear if you go +1 higher or -1 lower. Mostly red triangle in watch -// values for "unknown identifier". But also yellow arrow in call stack -// disappears if font size gets too large. -// [ ] undo close tab would be nice. If not for everything, then at least -// just for source files -// [ ] Jump table thunks, on code w/o /INCREMENTAL:NO - -//////////////////////////////// -//~ rjf: Hot, Feature Tasks (Not really "low priority" but less urgent than fixes) -// -// [ ] @eval_upgrade -// [ ] new eval system; support strings, many address spaces, many debug -// infos, wide/async transforms (e.g. diff(blob1, blob2)) -// [ ] collapse frontend visualization systems - source view, disasm view, -// callstack, modules, scheduler, should *all* be flavors of watch view -// -// [ ] Fancy View Rules -// [ ] table column boundaries should be checked against *AFTER* table -// contents, not before -// [ ] `array:(x, y)` - multidimensional array -// [ ] `text[:lang]` - interpret memory as text, in lang `lang` -// [ ] `disasm:arch` - interpret memory as machine code for isa `arch` -// [ ] `memory` - view memory in usual memory hex-editor view -// NOTE(rjf): When the visualization system is solid, layers like dasm, txti, -// and so on can be dispensed with, as things like the source view, disasm -// view, or memory view will simply be specializations of the general purpose -// viz system. -// [ ] view rule hook for standalone visualization ui, granted its own -// tab -// -// [ ] search-in-all-files -// -// [ ] Memory View -// [ ] memory view mutation controls -// [ ] memory view user-made annotations -// -// [ ] undo/redo -// [ ] proper "go back" + "go forward" history navigations -// -// [ ] globally disable/configure default view rule-like things (string -// viz for u8s in particular) -// [ ] globally disable/configure bp/ip lines in source view -// -// [ ] @feature processor/data breakpoints -// [ ] @feature automatically snap to search matches when searching source files -// [ ] automatically start search query with selected text -// [ ] @feature entity views: filtering & reordering - -//////////////////////////////// -//~ rjf: Cold, Clean-up Tasks That Probably Only Ryan Notices -// (E.G. Because They Are Code-Related Or Because Nobody Cares) -// -// [ ] @bug view-snapping in scroll-lists, accounting for mapping between -// visual positions & logical positions (variably sized rows in watch, -// table headers, etc.) -// [ ] @cleanup collapse DF_CfgNodes into just being MD trees, find another way -// to encode config source - don't need it at every node -// [ ] @cleanup straighten out index/number space & types & terminology for -// scroll lists -// [ ] @cleanup simplification pass over eval visualization pipeline & types, -// including view rule hooks -// [ ] @cleanup naming pass over eval visualization part of the frontend, -// "blocks" vs. "canvas" vs. "expansion" - etc. -// [ ] @cleanup central worker thread pool - eliminate per-layer thread pools -// [ ] @cleanup in the frontend, we are starting to have to pass down "DF_Window" -// everywhere, because of per-window parameters (e.g. font rendering settings). -// this is really better solved by implicit thread-local parameters, similar to -// interaction registers, so that one window can "pick" all of the implicit -// parameters, and then 99% of the UI code does not have to care. -// [ ] @cleanup eliminate explicit font parameters in the various ui paths (e.g. -// code slice params) - -//////////////////////////////// -//~ rjf: Cold, Unsorted Notes (Deferred Until Existing Lists Mostly Exhausted) -// -// [ ] @feature types -> auto view rules (don't statefully fill view rules -// given types, just query if no other view rule is present, & autofill -// when editing) -// [ ] @feature eval system -> somehow evaluate breakpoint hit counts? "meta" -// variables? -// -// [ ] @feature disasm view improvement features -// [ ] visualize jump destinations in disasm -// -// [ ] @feature eval ui improvement features -// [ ] serializing eval view maps -// [ ] view rule editors in hover-eval -// [ ] view rule hook coverage -// [ ] `each:(expr addition)` - apply some additional expression to all -// elements in an array/linked list would be useful to look at only a -// subset of an array of complex structs -// [ ] `slider:(min max)` view rule -// [ ] `v2f32` view rule -// [ ] `v3` view rule -// [ ] `quat` view rule -// [ ] `matrix` view rule -// [ ] `audio` waveform view rule -// [ ] smart scopes - expression operators for "grab me the first type X" -// [ ] "pinning" watch expressions, to attach it to a particular ctrl_ctx -// -// [ ] @feature header file for target -> debugger communication; printf, log, -// etc. -// [ ] @feature just-in-time debugging -// [ ] @feature step-out-of-loop -// -//-[ ] long-term future notes from martins -// [ ] core dump saving/loading -// [ ] parallel call stacks view -// [ ] parallel watch view -// [ ] mixed native/interpreted/jit debugging -// - it seems python has a top-level linked list of interpreter states, -// which should allow the debugger to map native callstacks to python -// code -// -// [ ] fancy string runs can include "weakness" information for text truncation -// ... can prioritize certain parts of strings to be truncated before -// others. would be good for e.g. the middle of a path -// [ ] font cache eviction (both for font tags, closing fp handles, and -// rasterizations) -// [ ] frontend speedup opportunities -// [ ] tables in UI -> currently building per-row, could probably cut down on -// # of boxes and # of draws by doing per-column in some cases? -// [ ] font cache layer -> can probably cache (string*font*size) -> (run) too -// (not just rasterization)... would save a *lot*, there is a ton of work -// just in looking up & stitching stuff repeatedly -// [ ] convert UI layout pass to not be naive recursive version -// [ ] (big change) parallelize window ui build codepaths per-panel - -//////////////////////////////// -//~ rjf: Recently Completed Task Log -// -// [x] UI_NavActions, OS_Event -> UI_Event (single event stream) -// [x] better discoverability for view rules - have better help hover tooltip, -// info on arguments, and better autocomplete lister -// [x] source view -> floating margin/line-nums -// [x] watch window reordering -// [x] standard way to filter -// [x] autocomplete lister should respect position in edited expression, -// tabbing through should autocomplete but not exit, etc. -// [x] pipe failure-to-launch errors back to frontend -// [x] bit more padding on the tabs -// [x] unified top-level cursor/typing/lister helper -// [x] collapse text cells & command lister & etc. into same codepath (?) -// [x] page-up & page-down correct handling in keyboard nav -// [x] interleaved src/dasm view -// [x] in watch window when I enter some new expression and then click mouse -// away from cell, then it should behave the same as if I pressed enter. -// Currently it does the same as if I have pressed esc and I have lost my -// expression -// [x] pressing random keyboard keys in source code advances text cursor like -// you were inputting text, very strange. -// [x] It's confusing that ENTER is the way you expand and collapse things in -// the watch window, but then also how you edit them if they are not -// expandable? It seems like this should be consistent (one way to edit, -// one way to expand/collapse, that are distinct) -// [x] Dragging a window tab (like Locals or Registers or whatnot) and -// canceling with ESC should revert the window tab to where it was. -// Currently, it leaves the window tab reordered if you dragged over its -// window and shuffled its position. -// [x] ** I couldn't figure out how to really view threads in the debugger. -// The only place I found a thread list was in "The Scheduler", but it -// only lists threads by ID, which is hard to use. I can hover over them -// to get the stack, which helps, but it would be much nicer if the top -// function was displayed in the window by default next to the thread. -// [x] ** It would be nice if thread listings displayed the name of the -// thread, instead of just the ID. -// [x] TLS eval -> in-process-memory EXE info -// [x] unwinding -> in-process-memory EXE info -// [x] new fuzzy searching layer -// [x] robustify dbgi layer to renames (cache should not be based only on -// path - must invalidate naturally when new filetime occurs) -// [x] rdi file regeneration too strict -// [x] raddbg jai.exe my_file.jai -- foobar -> raddbg consumes `--` incorrectly -// [x] mouse-driven way to complete file/folder selection, or more generally -// query completion -// [x] it would be nice to have "show in explorer" for right click on source -// file tab (opens explorer & selects the file) -// [x] asan stepping breakage -// [x] what's up with decimal number coloring where every group of 3 are in -// different color? can I turn it off? And why sometimes digits in number -// start with brighter color, but sometimes with darker - shouldn't it -// always have the same color ordering? -// [x] fix tabs-on-bottom positioning -// [x] colors: consistent tooltip styles (colors, font flags, etc.) -// [x] colors: scroll bars -// [x] colors: watch window navigation visuals -// [x] floating source view margin background/placement -// [x] "interaction root", or "group" ui_key, or something; used for menu bar interactions -// [x] theme colors -> more explicit about e.g. opaque backgrounds vs. floating -// & scrollbars etc. -// [x] Pressing the left mouse button on the menu bar and dragging does not -// move through the menus as expected - instead, it opens the one you -// clicked down on, then does nothing until you release, at which point it -// opens the menu you released on. -// [x] Similarly, pressing the left mouse button on a menu and dragging to an -// item, then releasing, does not trigger that item as expected. Instead, -// it is a nop, and it waits for you to click again on the item. -// [x] Using the word "symbol" in "Code (Symbol)" seems like a bad idea, since -// you're referring to non-identifier characters, but in a debugger -// "symbol" usually means something defined in the debug information. -// [x] I couldn't figure out how to affect the "dim" color in constants that -// have alternating bright/dim letters to show sections of a number. Is -// this in the theme colors somewhere? -// -// [x] ** Scrollbars are barely visible for me, for some reason. I could not -// find anything in the theme that would fill them with a solid, bright -// color. Instead they are just a thin outline and the same color as the -// scroll bar background. -// -// [x] Many of the UI elements, like the menus, would like better if they had -// a little bit of margin. Having the text right next to the edges, and -// with no line spacing, makes it harder to read things quickly. -// [x] colors: memory view -// [x] Hitting ESC during a color picker drag should abort the color picking -// and revert to the previous color. Currently, it just accepts the last -// drag result as the new color. -// [x] It was not clear to me why a small "tab picker" appeared when I got to -// a certain number of tabs. It seemed to appear even if the tabs were -// quite large, and there was no need to a drop-down menu to pick them. It -// feels like either it should always be there, or it should only show up -// if at least one tab gets small enough to have its name cut off? -// [x] I found the "context menu" convention to be confusing. For example, if -// I left-click on a tab, it selects the tab. If I right-click on a tab, -// it opens the context menu. However, if I left-click on a module, it -// opens the context window. It seems like maybe menus should be right, -// and left should do the default action, more consistently? -// -// [x] double click on procedure in procedures tab to jump to source -// [x] highlighted text & ctrl+f -> auto-fill search query -// [x] double-click any part of frame in callstack view -> snap to function -// [x] Menus take too long to show up. I would prefer it if they were instant. -// The animation doesn't really provide any useful cues, since I know -// where the menu came from. -// [x] user settings (ui & functionality - generally need a story for it) -// [x] hover animations -// [x] press animations -// [x] focus animations -// [x] tooltip animations -// [x] context menu animations -// [x] scrolling animations -// [x] background blur -// [x] tab width -// [x] ** In the call stack, I would like to be able to click quickly and move -// around the stack. Right now, you can do that with the first and third -// column, but the second column drops down a context menu. Since right -// click is already for context menus, can it not just be that double- -// clicking any column jumps to that stack frame? -// -// [x] ** I find it really hard to read the code with the heavyweight lines -// running through it for breakpoints and stepping and things. Is there a -// way to turn the lines off? AFAICT they are based on thread and -// breakpoint color, so you can't really control the line drawing? I might -// be fine with them, but they would have to be much more light (like -// alpha 0.1 or something) -// [x] zooming behaves very strangely - sometimes it zooms source code, -// sometimes both source code and menu/tab/watch font size, sometimes -// just menu/tab/watch font size not source size. -// [x] colors: fill out rest of theme presets for new theme setup -// [x] I LOVE ALT-W to add watch under cursor, but I would prefer to have it -// add what's under the MOUSE cursor instead of the keyboard cursor. Can -// we get a command for that so I can bind ALT-W to that instead? -// [x] editing multiple bindings for commands - -#ifndef RADDBG_H -#define RADDBG_H - -//////////////////////////////// -//~ rjf: Top-Level Execution Types - -typedef enum ExecMode -{ - ExecMode_Normal, - ExecMode_IPCSender, - ExecMode_Converter, - ExecMode_Help, -} -ExecMode; - -typedef struct IPCInfo IPCInfo; -struct IPCInfo -{ - U64 msg_size; -}; - -//////////////////////////////// -//~ rjf: Globals - -//- rjf: IPC resources -#define IPC_SHARED_MEMORY_BUFFER_SIZE MB(4) -StaticAssert(IPC_SHARED_MEMORY_BUFFER_SIZE > sizeof(IPCInfo), ipc_buffer_size_requirement); -global OS_Handle ipc_signal_semaphore = {0}; -global OS_Handle ipc_lock_semaphore = {0}; -global U8 *ipc_shared_memory_base = 0; -global U8 ipc_s2m_ring_buffer[MB(4)] = {0}; -global U64 ipc_s2m_ring_write_pos = 0; -global U64 ipc_s2m_ring_read_pos = 0; -global OS_Handle ipc_s2m_ring_mutex = {0}; -global OS_Handle ipc_s2m_ring_cv = {0}; - -//- rjf: last focused window -global DF_Handle last_focused_window = {0}; - -//- rjf: frame time history -global U64 frame_time_us_history[64] = {0}; -global U64 frame_time_us_history_idx = 0; - -//- rjf: main thread log -global Log *main_thread_log = 0; -global String8 main_thread_log_path = {0}; - -//////////////////////////////// -//~ rjf: Frontend Entry Points - -internal void update_and_render(OS_Handle repaint_window_handle, void *user_data); - -#endif // RADDBG_H +// Copyright (c) 2024 Epic Games Tools +// Licensed under the MIT license (https://opensource.org/license/mit/) + +//////////////////////////////// +//~ rjf: Frontend/UI Pass Tasks +// +// [ ] file overrides -> always pick most specific one! found with conflicting +// overrides, e.g. C:/devel/ -> D:/devel/, but also C:/devel/foo -> +// C:/devel/bar, etc. +// +// [ ] auto-scroll output window +// [ ] inline breakpoint hit_count +// [ ] to count hit counts, resolve all bps to addresses, check addresses +// against stopper thread's +// [ ] theme lister -> fonts & font sizes +// [ ] "Browse..." buttons should adopt a more relevant starting search path, +// if possible +// [ ] move breakpoints to being a global thing, not nested to particular files +// [ ] visualize all breakpoints everywhere - source view should show up in +// disasm, disasm should show up in source view, function should show up in +// both, etc. +// [ ] ** Function breakpoints should show up in the source listing. Without +// them being visible, it is confusing when you run and you stop there, +// because you're like "wait why did it stop" and then you later remember +// that's because there was a function breakpoint there. +// +// [ ] n-row table selection, in watch window & other UIs, multi-selection +// ctrl+C +// +// [ ] target/breakpoint/watch-pin reordering +// +// [ ] font lister +// [ ] per-panel font size overrides +// +// [ ] For the Scheduler window, it would be nice if you could dim or +// folderize threads that are not your threads - eg., if a thread doesn't +// have any resolved stack pointers in your executable code, then you can +// ignore it when you are focusing on your own code. I don't know what the +// best way to detect this is, other than by walking the call stack... one +// way might be to just have a way to separate threads you've named from +// threads you haven't? Or, there could even be a debugger-specific API +// that you use to tag them. Just some way that would make it easier to +// focus on your own threads. +// +// [ ] "concept key stack"; basically, any point in UI builder path has a stack +// of active "concept keys", which can be used to e.g. build context menus +// automatically (could just be a per-box attachment; right-click any +// point, search up the tree and see the concept keys) +// [ ] ui_next_event(...), built-in focus filtering, no need to manually check +// if(ui_is_focus_active()) + +//////////////////////////////// +//~ rjf: Hot, High Priority Tasks (Complete Unusability, Crashes, Fire-Worthy) +// +// [ ] PDB files distributed with the build are not found by DbgHelp!!! +// [ ] Jai compiler debugging crash + +//////////////////////////////// +//~ rjf: Hot, Medium Priority Tasks (Low-Hanging-Fruit Features, UI Jank, Cleanup) +// +// [ ] Setting the code_font/main_font values to a font name doesn't work. +// Should probably make note that you have to set it to a path to a TTF, +// since that's not normally how Windows fonts work. +// +// [ ] "root" concept in hash store, which buckets keys & allows usage code to +// jettison a collection of keys in retained mode fashion +// +// [ ] Jeff Notes +// [ ] sort locals by appearance in source code (or maybe just debug info) +// [ ] sum view rule +// [ ] plot view rule +// [ ] histogram view rule +// [ ] max view rule +// [ ] min view rule +// +// [ ] filesystem drag/drop support +// [ ] double-click vs. single-click for folder navigation, see if we can infer +// [ ] use backslashes on windows by default, forward slashes elsewhere +// +// [ ] investigate /DEBUG:FASTLINK - can we somehow alert that we do not +// support it? +// +// [ ] ** Converter performance & heuristics for asynchronously doing it early +// +// [ ] visualize conversion failures +// +// [ ] I was a little confused about what a profile file was. I understood +// what the user file was, but the profile file sounded like it should +// perhaps be per-project, yet it sounded like it was meant to be somewhat +// global? I don't have any feedback here because it probably will make +// sense once I use the debugger more, but I just thought I'd make a note +// to say that I was confused about it after reading the manual, so +// perhaps you could elaborate a little more on it in there. +// [ ] It wasn't clear to me how you save a user or project file. I can see +// how to load them, but not how you save them. Obviously I can just copy +// the files myself in the shell, but it seemed weird that there was no +// "save" option in the menus. +// +// [ ] Right-clicking on a thread in the Scheduler window pops up a context +// menu, but you can't actually see it because the tooltip for the thread +// draws on top of it, so you can't see the menu. +// +// [ ] In a "hover watch" (where you hover over a variable and it shows a pop- +// up watch window), if you expand an item near the bottom of the listing, +// it will be clipped to the bottom of the listing instead of showing the +// actual items (ie., it doesn't resize the listing based on what's +// actually visible) +// +// [ ] ** One very nice feature of RemedyBG that I use all the time is the +// ability to put "$err, hr" into the watch window, which will just show +// the value of GetLastError() as a string. This is super useful for +// debugging, so you don't have to litter your own code with it. +// +// [ ] Tooltip Coverage: +// [ ] lock icon +// [ ] "rotation arrow" icon next to executables +// +// [ ] For theme editing, when you hove the mouse over a theme color entry and +// it highlights that entry, it might help to temporarily change that +// color to white (or the inverse of the background color, or whatever) so +// that the user can see what things on the screen use that theme color. +// +// [ ] Theme window should include font scaling. I was able to find the +// command for increasing the font scale, but I imagine most people +// wouldn't think to look there. +// [ ] I had to go into the user file to change the font. That should probably +// be in the theme window? +// +// [ ] It'd be nice to have a "goto byte" option for source views, for jumping +// to error messages that are byte-based instead of line-based. +// +// [ ] @feature debug info overrides (both path-based AND module-based) +// +// [ ] C++ virtual inheritance member visualization in watch window + +//////////////////////////////// +//~ rjf: Hot, Low Priority Tasks (UI Opinions, Less-Serious Jank, Preferences, Cleanup) +// +// [ ] The hex format for color values in the config file was a real +// mindbender. It's prefixed with "0x", so I was assuming it was either +// Windows Big Endian (0xAARRGGBB) or Mac Little Endian (0xAABBGGRR). To +// my surprise, it was neither - it was actually web format (RRGGBBAA), +// which I was not expecting because that is normally written with a +// number sign (#AARRGGBB) not an 0x. +// +// [ ] Clicking on either side of a scroll bar is idiosyncratic. Normally, +// that is "page up" / "page down", but here it is "smooth scroll upward" +// / "smooth scroll downward" for some reason? +// +// [ ] can it ignore stepping into _RTC_CheckStackVars generated functions? +// [ ] mouse back button should make view to go back after I double clicked +// on function to open it +// [ ] Alt+8 to switch to disassembly would be nice (regardless on which +// panel was previous, don't want to use ctrl+, multiple times) +// Alt+8 for disasm and Alt+6 for memory view are shortcuts I often use +// in VS +// [ ] default font size is too small for me - not only source code, but +// menus/tab/watch names (which don't resize). Maybe you could query +// Windows for initial font size? +// [ ] icon fonts glyphs sometimes disappear for specific font size, but they +// reappear if you go +1 higher or -1 lower. Mostly red triangle in watch +// values for "unknown identifier". But also yellow arrow in call stack +// disappears if font size gets too large. +// [ ] undo close tab would be nice. If not for everything, then at least +// just for source files +// [ ] Jump table thunks, on code w/o /INCREMENTAL:NO + +//////////////////////////////// +//~ rjf: Hot, Feature Tasks (Not really "low priority" but less urgent than fixes) +// +// [ ] @eval_upgrade +// [ ] new eval system; support strings, many address spaces, many debug +// infos, wide/async transforms (e.g. diff(blob1, blob2)) +// [ ] collapse frontend visualization systems - source view, disasm view, +// callstack, modules, scheduler, should *all* be flavors of watch view +// +// [ ] Fancy View Rules +// [ ] table column boundaries should be checked against *AFTER* table +// contents, not before +// [ ] `array:(x, y)` - multidimensional array +// [ ] `text[:lang]` - interpret memory as text, in lang `lang` +// [ ] `disasm:arch` - interpret memory as machine code for isa `arch` +// [ ] `memory` - view memory in usual memory hex-editor view +// NOTE(rjf): When the visualization system is solid, layers like dasm, txti, +// and so on can be dispensed with, as things like the source view, disasm +// view, or memory view will simply be specializations of the general purpose +// viz system. +// [ ] view rule hook for standalone visualization ui, granted its own +// tab +// +// [ ] search-in-all-files +// +// [ ] Memory View +// [ ] memory view mutation controls +// [ ] memory view user-made annotations +// +// [ ] undo/redo +// [ ] proper "go back" + "go forward" history navigations +// +// [ ] globally disable/configure default view rule-like things (string +// viz for u8s in particular) +// [ ] globally disable/configure bp/ip lines in source view +// +// [ ] @feature processor/data breakpoints +// [ ] @feature automatically snap to search matches when searching source files +// [ ] automatically start search query with selected text +// [ ] @feature entity views: filtering & reordering + +//////////////////////////////// +//~ rjf: Cold, Clean-up Tasks That Probably Only Ryan Notices +// (E.G. Because They Are Code-Related Or Because Nobody Cares) +// +// [ ] @bug view-snapping in scroll-lists, accounting for mapping between +// visual positions & logical positions (variably sized rows in watch, +// table headers, etc.) +// [ ] @cleanup collapse DF_CfgNodes into just being MD trees, find another way +// to encode config source - don't need it at every node +// [ ] @cleanup straighten out index/number space & types & terminology for +// scroll lists +// [ ] @cleanup simplification pass over eval visualization pipeline & types, +// including view rule hooks +// [ ] @cleanup naming pass over eval visualization part of the frontend, +// "blocks" vs. "canvas" vs. "expansion" - etc. +// [ ] @cleanup central worker thread pool - eliminate per-layer thread pools +// [ ] @cleanup in the frontend, we are starting to have to pass down "DF_Window" +// everywhere, because of per-window parameters (e.g. font rendering settings). +// this is really better solved by implicit thread-local parameters, similar to +// interaction registers, so that one window can "pick" all of the implicit +// parameters, and then 99% of the UI code does not have to care. +// [ ] @cleanup eliminate explicit font parameters in the various ui paths (e.g. +// code slice params) + +//////////////////////////////// +//~ rjf: Cold, Unsorted Notes (Deferred Until Existing Lists Mostly Exhausted) +// +// [ ] @feature types -> auto view rules (don't statefully fill view rules +// given types, just query if no other view rule is present, & autofill +// when editing) +// [ ] @feature eval system -> somehow evaluate breakpoint hit counts? "meta" +// variables? +// +// [ ] @feature disasm view improvement features +// [ ] visualize jump destinations in disasm +// +// [ ] @feature eval ui improvement features +// [ ] serializing eval view maps +// [ ] view rule editors in hover-eval +// [ ] view rule hook coverage +// [ ] `each:(expr addition)` - apply some additional expression to all +// elements in an array/linked list would be useful to look at only a +// subset of an array of complex structs +// [ ] `slider:(min max)` view rule +// [ ] `v2f32` view rule +// [ ] `v3` view rule +// [ ] `quat` view rule +// [ ] `matrix` view rule +// [ ] `audio` waveform view rule +// [ ] smart scopes - expression operators for "grab me the first type X" +// [ ] "pinning" watch expressions, to attach it to a particular ctrl_ctx +// +// [ ] @feature header file for target -> debugger communication; printf, log, +// etc. +// [ ] @feature just-in-time debugging +// [ ] @feature step-out-of-loop +// +//-[ ] long-term future notes from martins +// [ ] core dump saving/loading +// [ ] parallel call stacks view +// [ ] parallel watch view +// [ ] mixed native/interpreted/jit debugging +// - it seems python has a top-level linked list of interpreter states, +// which should allow the debugger to map native callstacks to python +// code +// +// [ ] fancy string runs can include "weakness" information for text truncation +// ... can prioritize certain parts of strings to be truncated before +// others. would be good for e.g. the middle of a path +// [ ] font cache eviction (both for font tags, closing fp handles, and +// rasterizations) +// [ ] frontend speedup opportunities +// [ ] tables in UI -> currently building per-row, could probably cut down on +// # of boxes and # of draws by doing per-column in some cases? +// [ ] font cache layer -> can probably cache (string*font*size) -> (run) too +// (not just rasterization)... would save a *lot*, there is a ton of work +// just in looking up & stitching stuff repeatedly +// [ ] convert UI layout pass to not be naive recursive version +// [ ] (big change) parallelize window ui build codepaths per-panel + +//////////////////////////////// +//~ rjf: Recently Completed Task Log +// +// [x] UI_NavActions, OS_Event -> UI_Event (single event stream) +// [x] better discoverability for view rules - have better help hover tooltip, +// info on arguments, and better autocomplete lister +// [x] source view -> floating margin/line-nums +// [x] watch window reordering +// [x] standard way to filter +// [x] autocomplete lister should respect position in edited expression, +// tabbing through should autocomplete but not exit, etc. +// [x] pipe failure-to-launch errors back to frontend +// [x] bit more padding on the tabs +// [x] unified top-level cursor/typing/lister helper +// [x] collapse text cells & command lister & etc. into same codepath (?) +// [x] page-up & page-down correct handling in keyboard nav +// [x] interleaved src/dasm view +// [x] in watch window when I enter some new expression and then click mouse +// away from cell, then it should behave the same as if I pressed enter. +// Currently it does the same as if I have pressed esc and I have lost my +// expression +// [x] pressing random keyboard keys in source code advances text cursor like +// you were inputting text, very strange. +// [x] It's confusing that ENTER is the way you expand and collapse things in +// the watch window, but then also how you edit them if they are not +// expandable? It seems like this should be consistent (one way to edit, +// one way to expand/collapse, that are distinct) +// [x] Dragging a window tab (like Locals or Registers or whatnot) and +// canceling with ESC should revert the window tab to where it was. +// Currently, it leaves the window tab reordered if you dragged over its +// window and shuffled its position. +// [x] ** I couldn't figure out how to really view threads in the debugger. +// The only place I found a thread list was in "The Scheduler", but it +// only lists threads by ID, which is hard to use. I can hover over them +// to get the stack, which helps, but it would be much nicer if the top +// function was displayed in the window by default next to the thread. +// [x] ** It would be nice if thread listings displayed the name of the +// thread, instead of just the ID. +// [x] TLS eval -> in-process-memory EXE info +// [x] unwinding -> in-process-memory EXE info +// [x] new fuzzy searching layer +// [x] robustify dbgi layer to renames (cache should not be based only on +// path - must invalidate naturally when new filetime occurs) +// [x] rdi file regeneration too strict +// [x] raddbg jai.exe my_file.jai -- foobar -> raddbg consumes `--` incorrectly +// [x] mouse-driven way to complete file/folder selection, or more generally +// query completion +// [x] it would be nice to have "show in explorer" for right click on source +// file tab (opens explorer & selects the file) +// [x] asan stepping breakage +// [x] what's up with decimal number coloring where every group of 3 are in +// different color? can I turn it off? And why sometimes digits in number +// start with brighter color, but sometimes with darker - shouldn't it +// always have the same color ordering? +// [x] fix tabs-on-bottom positioning +// [x] colors: consistent tooltip styles (colors, font flags, etc.) +// [x] colors: scroll bars +// [x] colors: watch window navigation visuals +// [x] floating source view margin background/placement +// [x] "interaction root", or "group" ui_key, or something; used for menu bar interactions +// [x] theme colors -> more explicit about e.g. opaque backgrounds vs. floating +// & scrollbars etc. +// [x] Pressing the left mouse button on the menu bar and dragging does not +// move through the menus as expected - instead, it opens the one you +// clicked down on, then does nothing until you release, at which point it +// opens the menu you released on. +// [x] Similarly, pressing the left mouse button on a menu and dragging to an +// item, then releasing, does not trigger that item as expected. Instead, +// it is a nop, and it waits for you to click again on the item. +// [x] Using the word "symbol" in "Code (Symbol)" seems like a bad idea, since +// you're referring to non-identifier characters, but in a debugger +// "symbol" usually means something defined in the debug information. +// [x] I couldn't figure out how to affect the "dim" color in constants that +// have alternating bright/dim letters to show sections of a number. Is +// this in the theme colors somewhere? +// +// [x] ** Scrollbars are barely visible for me, for some reason. I could not +// find anything in the theme that would fill them with a solid, bright +// color. Instead they are just a thin outline and the same color as the +// scroll bar background. +// +// [x] Many of the UI elements, like the menus, would like better if they had +// a little bit of margin. Having the text right next to the edges, and +// with no line spacing, makes it harder to read things quickly. +// [x] colors: memory view +// [x] Hitting ESC during a color picker drag should abort the color picking +// and revert to the previous color. Currently, it just accepts the last +// drag result as the new color. +// [x] It was not clear to me why a small "tab picker" appeared when I got to +// a certain number of tabs. It seemed to appear even if the tabs were +// quite large, and there was no need to a drop-down menu to pick them. It +// feels like either it should always be there, or it should only show up +// if at least one tab gets small enough to have its name cut off? +// [x] I found the "context menu" convention to be confusing. For example, if +// I left-click on a tab, it selects the tab. If I right-click on a tab, +// it opens the context menu. However, if I left-click on a module, it +// opens the context window. It seems like maybe menus should be right, +// and left should do the default action, more consistently? +// +// [x] double click on procedure in procedures tab to jump to source +// [x] highlighted text & ctrl+f -> auto-fill search query +// [x] double-click any part of frame in callstack view -> snap to function +// [x] Menus take too long to show up. I would prefer it if they were instant. +// The animation doesn't really provide any useful cues, since I know +// where the menu came from. +// [x] user settings (ui & functionality - generally need a story for it) +// [x] hover animations +// [x] press animations +// [x] focus animations +// [x] tooltip animations +// [x] context menu animations +// [x] scrolling animations +// [x] background blur +// [x] tab width +// [x] ** In the call stack, I would like to be able to click quickly and move +// around the stack. Right now, you can do that with the first and third +// column, but the second column drops down a context menu. Since right +// click is already for context menus, can it not just be that double- +// clicking any column jumps to that stack frame? +// +// [x] ** I find it really hard to read the code with the heavyweight lines +// running through it for breakpoints and stepping and things. Is there a +// way to turn the lines off? AFAICT they are based on thread and +// breakpoint color, so you can't really control the line drawing? I might +// be fine with them, but they would have to be much more light (like +// alpha 0.1 or something) +// [x] zooming behaves very strangely - sometimes it zooms source code, +// sometimes both source code and menu/tab/watch font size, sometimes +// just menu/tab/watch font size not source size. +// [x] colors: fill out rest of theme presets for new theme setup +// [x] I LOVE ALT-W to add watch under cursor, but I would prefer to have it +// add what's under the MOUSE cursor instead of the keyboard cursor. Can +// we get a command for that so I can bind ALT-W to that instead? +// [x] editing multiple bindings for commands + +#ifndef RADDBG_H +#define RADDBG_H + +//////////////////////////////// +//~ rjf: Top-Level Execution Types + +typedef enum ExecMode +{ + ExecMode_Normal, + ExecMode_IPCSender, + ExecMode_Converter, + ExecMode_Help, +} +ExecMode; + +typedef struct IPCInfo IPCInfo; +struct IPCInfo +{ + U64 msg_size; +}; + +//////////////////////////////// +//~ rjf: Globals + +//- rjf: IPC resources +#define IPC_SHARED_MEMORY_BUFFER_SIZE MB(4) +StaticAssert(IPC_SHARED_MEMORY_BUFFER_SIZE > sizeof(IPCInfo), ipc_buffer_size_requirement); +global OS_Handle ipc_signal_semaphore = {0}; +global OS_Handle ipc_lock_semaphore = {0}; +global U8 *ipc_shared_memory_base = 0; +global U8 ipc_s2m_ring_buffer[MB(4)] = {0}; +global U64 ipc_s2m_ring_write_pos = 0; +global U64 ipc_s2m_ring_read_pos = 0; +global OS_Handle ipc_s2m_ring_mutex = {0}; +global OS_Handle ipc_s2m_ring_cv = {0}; + +//- rjf: last focused window +global DF_Handle last_focused_window = {0}; + +//- rjf: frame time history +global U64 frame_time_us_history[64] = {0}; +global U64 frame_time_us_history_idx = 0; + +//- rjf: main thread log +global Log *main_thread_log = 0; +global String8 main_thread_log_path = {0}; + +//////////////////////////////// +//~ rjf: Frontend Entry Points + +internal void update_and_render(OS_Handle repaint_window_handle, void *user_data); + +#endif // RADDBG_H