From 6fa8af5e1a4bf35ecdbd90dfaa33e50a7fe3f831 Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Tue, 25 Jun 2024 16:31:31 -0700 Subject: [PATCH] checkpoint on unified code ctx menu & all of its operations --- src/df/core/df_core.c | 533 +++++++++++------- src/df/core/df_core.h | 56 +- src/df/core/df_core.mdesk | 4 + src/df/core/generated/df_core.meta.c | 4 +- src/df/core/generated/df_core.meta.h | 2 + src/df/gfx/df_gfx.c | 510 +++++++++-------- src/df/gfx/df_gfx.h | 23 +- src/df/gfx/df_view_rules.c | 20 +- src/df/gfx/df_views.c | 296 ++++++++-- src/df/gfx/df_views.h | 6 +- .../dwrite/font_provider_dwrite.c | 6 +- 11 files changed, 947 insertions(+), 513 deletions(-) diff --git a/src/df/core/df_core.c b/src/df/core/df_core.c index 76191291..2f896e03 100644 --- a/src/df/core/df_core.c +++ b/src/df/core/df_core.c @@ -837,6 +837,24 @@ df_single_inst_from_machine_code(Arena *arena, Architecture arch, U64 start_voff return result; } +//////////////////////////////// +//~ rjf: Debug Info Extraction Type Pure Functions + +internal DF_LineList +df_line_list_copy(Arena *arena, DF_LineList *list) +{ + DF_LineList dst = {0}; + for(DF_LineNode *src_n = list->first; src_n != 0; src_n = src_n->next) + { + DF_LineNode *dst_n = push_array(arena, DF_LineNode, 1); + MemoryCopyStruct(dst_n, src_n); + dst_n->v.dbgi_key = di_key_copy(arena, &src_n->v.dbgi_key); + SLLQueuePush(dst.first, dst.last, dst_n); + dst.count += 1; + } + return dst; +} + //////////////////////////////// //~ rjf: Control Flow Analysis Functions @@ -2862,14 +2880,17 @@ df_trap_net_from_thread__step_over_line(Arena *arena, DF_Entity *thread) Rng1U64 line_vaddr_rng = {0}; { U64 ip_voff = df_voff_from_vaddr(module, ip_vaddr); - DF_TextLineDasm2SrcInfo line_info = df_text_line_dasm2src_info_from_dbgi_key_voff(&dbgi_key, ip_voff, 0); - Rng1U64 line_voff_rng = line_info.voff_range; - if(line_voff_rng.max != 0) + DF_LineList lines = df_lines_from_dbgi_key_voff(scratch.arena, &dbgi_key, ip_voff); + Rng1U64 line_voff_rng = {0}; + if(lines.first != 0) { + line_voff_rng = lines.first->v.voff_range; line_vaddr_rng = df_vaddr_range_from_voff_range(module, line_voff_rng); + DF_Entity *file = df_entity_from_handle(lines.first->v.file); + log_infof("line: {%S:%I64i}\n", file->name, lines.first->v.pt.line); } - log_infof("line: {%S:%I64i}\n", line_info.file->name, line_info.pt.line); - log_infof("voff_range: {0x%I64x, 0x%I64x}\n", line_info.voff_range.min, line_info.voff_range.max); + log_infof("voff_range: {0x%I64x, 0x%I64x}\n", line_voff_rng.min, line_voff_rng.max); + log_infof("vaddr_range: {0x%I64x, 0x%I64x}\n", line_vaddr_rng.min, line_vaddr_rng.max); } // rjf: opl line_vaddr_rng -> 0xf00f00 or 0xfeefee? => include in line vaddr range @@ -2878,10 +2899,10 @@ df_trap_net_from_thread__step_over_line(Arena *arena, DF_Entity *thread) // is enabled. This is enabled by default normally. { U64 opl_line_voff_rng = df_voff_from_vaddr(module, line_vaddr_rng.max); - DF_TextLineDasm2SrcInfo line_info = df_text_line_dasm2src_info_from_dbgi_key_voff(&dbgi_key, opl_line_voff_rng, 0); - if(line_info.pt.line == 0xf00f00 || line_info.pt.line == 0xfeefee) + DF_LineList lines = df_lines_from_dbgi_key_voff(scratch.arena, &dbgi_key, opl_line_voff_rng); + if(lines.first != 0 && (lines.first->v.pt.line == 0xf00f00 || lines.first->v.pt.line == 0xfeefee)) { - line_vaddr_rng.max = df_vaddr_from_voff(module, line_info.voff_range.max); + line_vaddr_rng.max = df_vaddr_from_voff(module, lines.first->v.voff_range.max); } } @@ -3020,10 +3041,11 @@ df_trap_net_from_thread__step_into_line(Arena *arena, DF_Entity *thread) Rng1U64 line_vaddr_rng = {0}; { U64 ip_voff = df_voff_from_vaddr(module, ip_vaddr); - DF_TextLineDasm2SrcInfo line_info = df_text_line_dasm2src_info_from_dbgi_key_voff(&dbgi_key, ip_voff, 0); - Rng1U64 line_voff_rng = line_info.voff_range; - if(line_voff_rng.max != 0) + DF_LineList lines = df_lines_from_dbgi_key_voff(scratch.arena, &dbgi_key, ip_voff); + Rng1U64 line_voff_rng = {0}; + if(lines.first != 0) { + line_voff_rng = lines.first->v.voff_range; line_vaddr_rng = df_vaddr_range_from_voff_range(module, line_voff_rng); } } @@ -3034,10 +3056,10 @@ df_trap_net_from_thread__step_into_line(Arena *arena, DF_Entity *thread) // is enabled. This is enabled by default normally. { U64 opl_line_voff_rng = df_voff_from_vaddr(module, line_vaddr_rng.max); - DF_TextLineDasm2SrcInfo line_info = df_text_line_dasm2src_info_from_dbgi_key_voff(&dbgi_key, opl_line_voff_rng, 0); - if(line_info.pt.line == 0xf00f00 || line_info.pt.line == 0xfeefee) + DF_LineList lines = df_lines_from_dbgi_key_voff(scratch.arena, &dbgi_key, opl_line_voff_rng); + if(lines.first != 0 && (lines.first->v.pt.line == 0xf00f00 || lines.first->v.pt.line == 0xfeefee)) { - line_vaddr_rng.max = df_vaddr_from_voff(module, line_info.voff_range.max); + line_vaddr_rng.max = df_vaddr_from_voff(module, lines.first->v.voff_range.max); } } @@ -3247,186 +3269,6 @@ df_symbol_name_from_process_vaddr(Arena *arena, DF_Entity *process, U64 vaddr) return result; } -//- rjf: src -> voff lookups - -internal DF_TextLineSrc2DasmInfoListArray -df_text_line_src2dasm_info_list_array_from_src_line_range(Arena *arena, DF_Entity *file, Rng1S64 line_num_range) -{ - DF_TextLineSrc2DasmInfoListArray src2dasm_array = {0}; - { - src2dasm_array.count = dim_1s64(line_num_range)+1; - src2dasm_array.v = push_array(arena, DF_TextLineSrc2DasmInfoList, src2dasm_array.count); - } - Temp scratch = scratch_begin(&arena, 1); - DI_Scope *scope = di_scope_open(); - DI_KeyList dbgi_keys = df_push_active_dbgi_key_list(scratch.arena); - DF_EntityList overrides = df_possible_overrides_from_entity(scratch.arena, file); - for(DF_EntityNode *override_n = overrides.first; - override_n != 0; - override_n = override_n->next) - { - DF_Entity *override = override_n->entity; - String8 file_path = df_full_path_from_entity(scratch.arena, override); - String8 file_path_normalized = lower_from_str8(scratch.arena, file_path); - for(DI_KeyNode *dbgi_key_n = dbgi_keys.first; - dbgi_key_n != 0; - dbgi_key_n = dbgi_key_n->next) - { - // rjf: binary -> rdi - DI_Key key = dbgi_key_n->v; - RDI_Parsed *rdi = di_rdi_from_key(scope, &key, 0); - - // rjf: file_path_normalized * rdi -> src_id - B32 good_src_id = 0; - U32 src_id = 0; - if(rdi != &di_rdi_parsed_nil) - { - RDI_NameMap *mapptr = rdi_element_from_name_idx(rdi, NameMaps, RDI_NameMapKind_NormalSourcePaths); - RDI_ParsedNameMap map = {0}; - rdi_parsed_from_name_map(rdi, mapptr, &map); - RDI_NameMapNode *node = rdi_name_map_lookup(rdi, &map, file_path_normalized.str, file_path_normalized.size); - if(node != 0) - { - U32 id_count = 0; - U32 *ids = rdi_matches_from_map_node(rdi, node, &id_count); - if(id_count > 0) - { - good_src_id = 1; - src_id = ids[0]; - } - } - } - - // rjf: good src-id -> look up line info for visible range - if(good_src_id) - { - RDI_SourceFile *src = rdi_element_from_name_idx(rdi, SourceFiles, src_id); - RDI_SourceLineMap *src_line_map = rdi_element_from_name_idx(rdi, SourceLineMaps, src->source_line_map_idx); - RDI_ParsedSourceLineMap line_map = {0}; - rdi_parsed_from_source_line_map(rdi, src_line_map, &line_map); - U64 line_idx = 0; - for(S64 line_num = line_num_range.min; - line_num <= line_num_range.max; - line_num += 1, line_idx += 1) - { - DF_TextLineSrc2DasmInfoList *src2dasm_list = &src2dasm_array.v[line_idx]; - U32 voff_count = 0; - U64 *voffs = rdi_line_voffs_from_num(&line_map, u32_from_u64_saturate((U64)line_num), &voff_count); - for(U64 idx = 0; idx < voff_count; idx += 1) - { - U64 base_voff = voffs[idx]; - U64 unit_idx = rdi_vmap_idx_from_section_kind_voff(rdi, RDI_SectionKind_UnitVMap, base_voff); - RDI_Unit *unit = rdi_element_from_name_idx(rdi, Units, unit_idx); - RDI_LineTable *line_table = rdi_element_from_name_idx(rdi, LineTables, unit->line_table_idx); - RDI_ParsedLineTable unit_line_info = {0}; - rdi_parsed_from_line_table(rdi, line_table, &unit_line_info); - U64 line_info_idx = rdi_line_info_idx_from_voff(&unit_line_info, base_voff); - if(unit_line_info.voffs != 0) - { - Rng1U64 range = r1u64(base_voff, unit_line_info.voffs[line_info_idx+1]); - S64 actual_line = (S64)unit_line_info.lines[line_info_idx].line_num; - DF_TextLineSrc2DasmInfoNode *src2dasm_n = push_array(arena, DF_TextLineSrc2DasmInfoNode, 1); - src2dasm_n->v.voff_range = range; - src2dasm_n->v.remap_line = (S64)actual_line; - src2dasm_n->v.dbgi_key = key; - SLLQueuePush(src2dasm_list->first, src2dasm_list->last, src2dasm_n); - src2dasm_list->count += 1; - } - } - } - } - - // rjf: good src id -> push to relevant dbgi keys - if(good_src_id) - { - di_key_list_push(arena, &src2dasm_array.dbgi_keys, &key); - } - } - } - di_scope_close(scope); - scratch_end(scratch); - return src2dasm_array; -} - -//- rjf: voff -> src lookups - -internal DF_TextLineDasm2SrcInfo -df_text_line_dasm2src_info_from_dbgi_key_voff(DI_Key *dbgi_key, U64 voff, U64 inline_unwind_idx) -{ - Temp scratch = scratch_begin(0, 0); - DI_Scope *scope = di_scope_open(); - RDI_Parsed *rdi = di_rdi_from_key(scope, dbgi_key, 0); - DF_TextLineDasm2SrcInfo result = {0}; - result.file = &df_g_nil_entity; - { - RDI_Unit *unit = rdi_unit_from_voff(rdi, voff); - RDI_LineTable *unit_line_table = rdi_line_table_from_unit(rdi, unit); - typedef struct LineTableNode LineTableNode; - struct LineTableNode - { - LineTableNode *next; - RDI_ParsedLineTable parsed_line_table; - }; - LineTableNode start_line_table = {0}; - rdi_parsed_from_line_table(rdi, unit_line_table, &start_line_table.parsed_line_table); - LineTableNode *top_line_table = &start_line_table; - RDI_Scope *scope = rdi_scope_from_voff(rdi, voff); - { - U64 idx = 0; - for(RDI_Scope *s = scope; - s->inline_site_idx != 0 && idx <= inline_unwind_idx; - s = rdi_element_from_name_idx(rdi, Scopes, s->parent_scope_idx), idx += 1) - { - if(idx == inline_unwind_idx) - { - RDI_InlineSite *inline_site = rdi_element_from_name_idx(rdi, InlineSites, s->inline_site_idx); - if(inline_site->line_table_idx != 0) - { - LineTableNode *n = push_array(scratch.arena, LineTableNode, 1); - SLLStackPush(top_line_table, n); - RDI_LineTable *line_table = rdi_element_from_name_idx(rdi, LineTables, inline_site->line_table_idx); - rdi_parsed_from_line_table(rdi, line_table, &n->parsed_line_table); - } - break; - } - } - } - for(LineTableNode *n = top_line_table; n == top_line_table; n = n->next) - { - RDI_ParsedLineTable parsed_line_table = n->parsed_line_table; - U64 line_info_idx = rdi_line_info_idx_from_voff(&parsed_line_table, voff); - if(line_info_idx < parsed_line_table.count) - { - RDI_Line *line = &parsed_line_table.lines[line_info_idx]; - RDI_Column *column = (line_info_idx < parsed_line_table.col_count) ? &parsed_line_table.cols[line_info_idx] : 0; - RDI_SourceFile *file = rdi_element_from_name_idx(rdi, SourceFiles, line->file_idx); - 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); - MemoryCopyStruct(&result.dbgi_key, dbgi_key); - if(line->file_idx != 0 && file_normalized_full_path.size != 0) - { - result.file = df_entity_from_path(file_normalized_full_path, DF_EntityFromPathFlag_All); - } - result.pt = txt_pt(line->line_num, column ? column->col_first : 1); - result.voff_range = r1u64(parsed_line_table.voffs[line_info_idx], parsed_line_table.voffs[line_info_idx+1]); - } - } - for(LineTableNode *n = top_line_table->next; n != 0; n = n->next) - { - RDI_ParsedLineTable parsed_line_table = n->parsed_line_table; - U64 line_info_idx = rdi_line_info_idx_from_voff(&parsed_line_table, voff); - if(line_info_idx < parsed_line_table.count) - { - Rng1U64 voff_range = r1u64(parsed_line_table.voffs[line_info_idx], parsed_line_table.voffs[line_info_idx+1]); - result.voff_range = intersect_1u64(result.voff_range, voff_range); - } - } - } - di_scope_close(scope); - scratch_end(scratch); - return result; -} - //- rjf: symbol -> voff lookups internal U64 @@ -3549,6 +3391,298 @@ df_type_num_from_dbgi_key_name(DI_Key *dbgi_key, String8 name) return result; } +//- rjf: voff -> line info + +internal DF_LineList +df_lines_from_dbgi_key_voff(Arena *arena, DI_Key *dbgi_key, U64 voff) +{ + Temp scratch = scratch_begin(&arena, 1); + DI_Scope *scope = di_scope_open(); + RDI_Parsed *rdi = di_rdi_from_key(scope, dbgi_key, 0); + DF_LineList result = {0}; + { + //- rjf: gather line tables + typedef struct LineTableNode LineTableNode; + struct LineTableNode + { + LineTableNode *next; + RDI_ParsedLineTable parsed_line_table; + }; + LineTableNode start_line_table = {0}; + RDI_Unit *unit = rdi_unit_from_voff(rdi, voff); + RDI_LineTable *unit_line_table = rdi_line_table_from_unit(rdi, unit); + rdi_parsed_from_line_table(rdi, unit_line_table, &start_line_table.parsed_line_table); + LineTableNode *top_line_table = &start_line_table; + RDI_Scope *scope = rdi_scope_from_voff(rdi, voff); + { + for(RDI_Scope *s = scope; + s->inline_site_idx != 0; + s = rdi_element_from_name_idx(rdi, Scopes, s->parent_scope_idx)) + { + RDI_InlineSite *inline_site = rdi_element_from_name_idx(rdi, InlineSites, s->inline_site_idx); + if(inline_site->line_table_idx != 0) + { + LineTableNode *n = push_array(scratch.arena, LineTableNode, 1); + SLLStackPush(top_line_table, n); + RDI_LineTable *line_table = rdi_element_from_name_idx(rdi, LineTables, inline_site->line_table_idx); + rdi_parsed_from_line_table(rdi, line_table, &n->parsed_line_table); + } + } + } + + //- rjf: gather lines in each line table + Rng1U64 shallowest_voff_range = {0}; + for(LineTableNode *n = top_line_table; n != 0; n = n->next) + { + RDI_ParsedLineTable parsed_line_table = n->parsed_line_table; + U64 line_info_idx = rdi_line_info_idx_from_voff(&parsed_line_table, voff); + if(line_info_idx < parsed_line_table.count) + { + RDI_Line *line = &parsed_line_table.lines[line_info_idx]; + RDI_Column *column = (line_info_idx < parsed_line_table.col_count) ? &parsed_line_table.cols[line_info_idx] : 0; + RDI_SourceFile *file = rdi_element_from_name_idx(rdi, SourceFiles, line->file_idx); + 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); + result.count += 1; + if(line->file_idx != 0 && file_normalized_full_path.size != 0) + { + n->v.file = df_handle_from_entity(df_entity_from_path(file_normalized_full_path, DF_EntityFromPathFlag_All)); + } + n->v.pt = txt_pt(line->line_num, column ? column->col_first : 1); + n->v.voff_range = r1u64(parsed_line_table.voffs[line_info_idx], parsed_line_table.voffs[line_info_idx+1]); + n->v.dbgi_key = *dbgi_key; + shallowest_voff_range = n->v.voff_range; + } + } + + //- rjf: clamp all lines from all tables by shallowest (most unwound) range + for(DF_LineNode *n = result.first; n != 0; n = n->next) + { + n->v.voff_range = intersect_1u64(n->v.voff_range, shallowest_voff_range); + } + } + di_scope_close(scope); + scratch_end(scratch); + return result; +} + +//- rjf: file:line -> line info + +internal DF_LineListArray +df_lines_array_from_file_line_range(Arena *arena, DF_Entity *file, Rng1S64 line_num_range) +{ + DF_LineListArray array = {0}; + { + array.count = dim_1s64(line_num_range)+1; + array.v = push_array(arena, DF_LineList, array.count); + } + Temp scratch = scratch_begin(&arena, 1); + DI_Scope *scope = di_scope_open(); + DI_KeyList dbgi_keys = df_push_active_dbgi_key_list(scratch.arena); + DF_EntityList overrides = df_possible_overrides_from_entity(scratch.arena, file); + for(DF_EntityNode *override_n = overrides.first; + override_n != 0; + override_n = override_n->next) + { + DF_Entity *override = override_n->entity; + String8 file_path = df_full_path_from_entity(scratch.arena, override); + String8 file_path_normalized = lower_from_str8(scratch.arena, file_path); + for(DI_KeyNode *dbgi_key_n = dbgi_keys.first; + dbgi_key_n != 0; + dbgi_key_n = dbgi_key_n->next) + { + // rjf: binary -> rdi + DI_Key key = dbgi_key_n->v; + RDI_Parsed *rdi = di_rdi_from_key(scope, &key, 0); + + // rjf: file_path_normalized * rdi -> src_id + B32 good_src_id = 0; + U32 src_id = 0; + if(rdi != &di_rdi_parsed_nil) + { + RDI_NameMap *mapptr = rdi_element_from_name_idx(rdi, NameMaps, RDI_NameMapKind_NormalSourcePaths); + RDI_ParsedNameMap map = {0}; + rdi_parsed_from_name_map(rdi, mapptr, &map); + RDI_NameMapNode *node = rdi_name_map_lookup(rdi, &map, file_path_normalized.str, file_path_normalized.size); + if(node != 0) + { + U32 id_count = 0; + U32 *ids = rdi_matches_from_map_node(rdi, node, &id_count); + if(id_count > 0) + { + good_src_id = 1; + src_id = ids[0]; + } + } + } + + // rjf: good src-id -> look up line info for visible range + if(good_src_id) + { + RDI_SourceFile *src = rdi_element_from_name_idx(rdi, SourceFiles, src_id); + RDI_SourceLineMap *src_line_map = rdi_element_from_name_idx(rdi, SourceLineMaps, src->source_line_map_idx); + RDI_ParsedSourceLineMap line_map = {0}; + rdi_parsed_from_source_line_map(rdi, src_line_map, &line_map); + U64 line_idx = 0; + for(S64 line_num = line_num_range.min; + line_num <= line_num_range.max; + line_num += 1, line_idx += 1) + { + DF_LineList *list = &array.v[line_idx]; + U32 voff_count = 0; + U64 *voffs = rdi_line_voffs_from_num(&line_map, u32_from_u64_saturate((U64)line_num), &voff_count); + for(U64 idx = 0; idx < voff_count; idx += 1) + { + U64 base_voff = voffs[idx]; + U64 unit_idx = rdi_vmap_idx_from_section_kind_voff(rdi, RDI_SectionKind_UnitVMap, base_voff); + RDI_Unit *unit = rdi_element_from_name_idx(rdi, Units, unit_idx); + RDI_LineTable *line_table = rdi_element_from_name_idx(rdi, LineTables, unit->line_table_idx); + RDI_ParsedLineTable unit_line_info = {0}; + rdi_parsed_from_line_table(rdi, line_table, &unit_line_info); + U64 line_info_idx = rdi_line_info_idx_from_voff(&unit_line_info, base_voff); + if(unit_line_info.voffs != 0) + { + Rng1U64 range = r1u64(base_voff, unit_line_info.voffs[line_info_idx+1]); + S64 actual_line = (S64)unit_line_info.lines[line_info_idx].line_num; + DF_LineNode *n = push_array(arena, DF_LineNode, 1); + n->v.voff_range = range; + n->v.pt.line = (S64)actual_line; + n->v.pt.column = 1; + n->v.dbgi_key = key; + SLLQueuePush(list->first, list->last, n); + list->count += 1; + } + } + } + } + + // rjf: good src id -> push to relevant dbgi keys + if(good_src_id) + { + di_key_list_push(arena, &array.dbgi_keys, &key); + } + } + } + di_scope_close(scope); + scratch_end(scratch); + return array; +} + +internal DF_LineList +df_lines_from_file_line_num(Arena *arena, DF_Entity *file, S64 line_num) +{ + DF_LineListArray array = df_lines_array_from_file_line_range(arena, file, r1s64(line_num, line_num+1)); + DF_LineList list = {0}; + if(array.count != 0) + { + list = array.v[0]; + } + return list; +} + +//- rjf: src -> voff lookups + +internal DF_TextLineSrc2DasmInfoListArray +df_text_line_src2dasm_info_list_array_from_src_line_range(Arena *arena, DF_Entity *file, Rng1S64 line_num_range) +{ + DF_TextLineSrc2DasmInfoListArray src2dasm_array = {0}; + { + src2dasm_array.count = dim_1s64(line_num_range)+1; + src2dasm_array.v = push_array(arena, DF_TextLineSrc2DasmInfoList, src2dasm_array.count); + } + Temp scratch = scratch_begin(&arena, 1); + DI_Scope *scope = di_scope_open(); + DI_KeyList dbgi_keys = df_push_active_dbgi_key_list(scratch.arena); + DF_EntityList overrides = df_possible_overrides_from_entity(scratch.arena, file); + for(DF_EntityNode *override_n = overrides.first; + override_n != 0; + override_n = override_n->next) + { + DF_Entity *override = override_n->entity; + String8 file_path = df_full_path_from_entity(scratch.arena, override); + String8 file_path_normalized = lower_from_str8(scratch.arena, file_path); + for(DI_KeyNode *dbgi_key_n = dbgi_keys.first; + dbgi_key_n != 0; + dbgi_key_n = dbgi_key_n->next) + { + // rjf: binary -> rdi + DI_Key key = dbgi_key_n->v; + RDI_Parsed *rdi = di_rdi_from_key(scope, &key, 0); + + // rjf: file_path_normalized * rdi -> src_id + B32 good_src_id = 0; + U32 src_id = 0; + if(rdi != &di_rdi_parsed_nil) + { + RDI_NameMap *mapptr = rdi_element_from_name_idx(rdi, NameMaps, RDI_NameMapKind_NormalSourcePaths); + RDI_ParsedNameMap map = {0}; + rdi_parsed_from_name_map(rdi, mapptr, &map); + RDI_NameMapNode *node = rdi_name_map_lookup(rdi, &map, file_path_normalized.str, file_path_normalized.size); + if(node != 0) + { + U32 id_count = 0; + U32 *ids = rdi_matches_from_map_node(rdi, node, &id_count); + if(id_count > 0) + { + good_src_id = 1; + src_id = ids[0]; + } + } + } + + // rjf: good src-id -> look up line info for visible range + if(good_src_id) + { + RDI_SourceFile *src = rdi_element_from_name_idx(rdi, SourceFiles, src_id); + RDI_SourceLineMap *src_line_map = rdi_element_from_name_idx(rdi, SourceLineMaps, src->source_line_map_idx); + RDI_ParsedSourceLineMap line_map = {0}; + rdi_parsed_from_source_line_map(rdi, src_line_map, &line_map); + U64 line_idx = 0; + for(S64 line_num = line_num_range.min; + line_num <= line_num_range.max; + line_num += 1, line_idx += 1) + { + DF_TextLineSrc2DasmInfoList *src2dasm_list = &src2dasm_array.v[line_idx]; + U32 voff_count = 0; + U64 *voffs = rdi_line_voffs_from_num(&line_map, u32_from_u64_saturate((U64)line_num), &voff_count); + for(U64 idx = 0; idx < voff_count; idx += 1) + { + U64 base_voff = voffs[idx]; + U64 unit_idx = rdi_vmap_idx_from_section_kind_voff(rdi, RDI_SectionKind_UnitVMap, base_voff); + RDI_Unit *unit = rdi_element_from_name_idx(rdi, Units, unit_idx); + RDI_LineTable *line_table = rdi_element_from_name_idx(rdi, LineTables, unit->line_table_idx); + RDI_ParsedLineTable unit_line_info = {0}; + rdi_parsed_from_line_table(rdi, line_table, &unit_line_info); + U64 line_info_idx = rdi_line_info_idx_from_voff(&unit_line_info, base_voff); + if(unit_line_info.voffs != 0) + { + Rng1U64 range = r1u64(base_voff, unit_line_info.voffs[line_info_idx+1]); + S64 actual_line = (S64)unit_line_info.lines[line_info_idx].line_num; + DF_TextLineSrc2DasmInfoNode *src2dasm_n = push_array(arena, DF_TextLineSrc2DasmInfoNode, 1); + src2dasm_n->v.voff_range = range; + src2dasm_n->v.remap_line = (S64)actual_line; + src2dasm_n->v.dbgi_key = key; + SLLQueuePush(src2dasm_list->first, src2dasm_list->last, src2dasm_n); + src2dasm_list->count += 1; + } + } + } + } + + // rjf: good src id -> push to relevant dbgi keys + if(good_src_id) + { + di_key_list_push(arena, &src2dasm_array.dbgi_keys, &key); + } + } + } + di_scope_close(scope); + scratch_end(scratch); + return src2dasm_array; +} + //////////////////////////////// //~ rjf: Process/Thread/Module Info Lookups @@ -6886,7 +7020,6 @@ df_core_begin_frame(Arena *arena, DF_CmdList *cmds, F32 dt) DF_Entity *module = df_module_from_process_vaddr(process, stop_thread_vaddr); DI_Key dbgi_key = df_dbgi_key_from_module(module); U64 stop_thread_voff = df_voff_from_vaddr(module, stop_thread_vaddr); - DF_TextLineDasm2SrcInfo dasm2src_info = df_text_line_dasm2src_info_from_dbgi_key_voff(&dbgi_key, stop_thread_voff, 0); DF_EntityList user_bps = df_query_cached_entity_list_with_kind(DF_EntityKind_Breakpoint); for(DF_EntityNode *n = user_bps.first; n != 0; n = n->next) { @@ -6898,9 +7031,14 @@ df_core_begin_frame(Arena *arena, DF_CmdList *cmds, F32 dt) if(bp->flags & DF_EntityFlag_HasTextPoint) { DF_Entity *bp_file = df_entity_ancestor_from_kind(bp, DF_EntityKind_File); - if(bp_file == dasm2src_info.file && bp->text_point.line == dasm2src_info.pt.line) + DF_LineList lines = df_lines_from_file_line_num(scratch.arena, bp_file, bp_file->text_point.line); + for(DF_LineNode *n = lines.first; n != 0; n = n->next) { - bp->u64 += 1; + if(contains_1u64(n->v.voff_range, stop_thread_voff)) + { + bp->u64 += 1; + break; + } } } } @@ -7631,6 +7769,7 @@ df_core_begin_frame(Arena *arena, DF_CmdList *cmds, F32 dt) { DF_Entity *bp = df_entity_alloc(0, df_entity_root(), DF_EntityKind_Breakpoint); bp->flags |= DF_EntityFlag_DiesOnRunStop; + df_entity_equip_b32(bp, 1); df_entity_equip_vaddr(bp, params.vaddr); df_entity_equip_cfg_src(bp, DF_CfgSrc_Transient); DF_CmdParams p = df_cmd_params_zero(); diff --git a/src/df/core/df_core.h b/src/df/core/df_core.h index 9b09e319..41e1534c 100644 --- a/src/df/core/df_core.h +++ b/src/df/core/df_core.h @@ -556,6 +556,41 @@ struct DF_Unwind DF_UnwindFrameArray frames; }; +//////////////////////////////// +//~ rjf: Line Info Types + +typedef struct DF_Line DF_Line; +struct DF_Line +{ + DF_Handle file; + TxtPt pt; + Rng1U64 voff_range; + DI_Key dbgi_key; +}; + +typedef struct DF_LineNode DF_LineNode; +struct DF_LineNode +{ + DF_LineNode *next; + DF_Line v; +}; + +typedef struct DF_LineList DF_LineList; +struct DF_LineList +{ + DF_LineNode *first; + DF_LineNode *last; + U64 count; +}; + +typedef struct DF_LineListArray DF_LineListArray; +struct DF_LineListArray +{ + DF_LineList *v; + U64 count; + DI_KeyList dbgi_keys; +}; + //////////////////////////////// //~ rjf: Source <-> Disasm Types @@ -1391,6 +1426,11 @@ internal String8 df_string_from_cfg_node_key(DF_CfgNode *node, String8 key, Stri internal DF_Inst df_single_inst_from_machine_code__x64(Arena *arena, U64 start_voff, String8 string); internal DF_Inst df_single_inst_from_machine_code(Arena *arena, Architecture arch, U64 start_voff, String8 string); +//////////////////////////////// +//~ rjf: Debug Info Extraction Type Pure Functions + +internal DF_LineList df_line_list_copy(Arena *arena, DF_LineList *list); + //////////////////////////////// //~ rjf: Control Flow Analysis Pure Functions @@ -1582,16 +1622,20 @@ internal Rng1U64 df_vaddr_range_from_voff_range(DF_Entity *module, Rng1U64 voff_ internal String8 df_symbol_name_from_dbgi_key_voff(Arena *arena, DI_Key *dbgi_key, U64 voff); internal String8 df_symbol_name_from_process_vaddr(Arena *arena, DF_Entity *process, U64 vaddr); -//- rjf: src -> voff lookups -internal DF_TextLineSrc2DasmInfoListArray df_text_line_src2dasm_info_list_array_from_src_line_range(Arena *arena, DF_Entity *file, Rng1S64 line_num_range); - -//- rjf: voff -> src lookups -internal DF_TextLineDasm2SrcInfo df_text_line_dasm2src_info_from_dbgi_key_voff(DI_Key *dbgi_key, U64 voff, U64 inline_unwind_idx); - //- rjf: symbol -> voff lookups internal U64 df_voff_from_dbgi_key_symbol_name(DI_Key *dbgi_key, String8 symbol_name); internal U64 df_type_num_from_dbgi_key_name(DI_Key *dbgi_key, String8 name); +//- rjf: voff -> line info +internal DF_LineList df_lines_from_dbgi_key_voff(Arena *arena, DI_Key *dbgi_key, U64 voff); + +//- rjf: file:line -> line info +internal DF_LineListArray df_lines_array_from_file_line_range(Arena *arena, DF_Entity *file, Rng1S64 line_num_range); +internal DF_LineList df_lines_from_file_line_num(Arena *arena, DF_Entity *file, S64 line_num); + +//- rjf: src -> voff lookups +internal DF_TextLineSrc2DasmInfoListArray df_text_line_src2dasm_info_list_array_from_src_line_range(Arena *arena, DF_Entity *file, Rng1S64 line_num_range); + //////////////////////////////// //~ rjf: Process/Thread/Module Info Lookups diff --git a/src/df/core/df_core.mdesk b/src/df/core/df_core.mdesk index 331ac04c..28732b74 100644 --- a/src/df/core/df_core.mdesk +++ b/src/df/core/df_core.mdesk @@ -222,6 +222,10 @@ DF_CoreCmdTable:// | | | {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." "" } diff --git a/src/df/core/generated/df_core.meta.c b/src/df/core/generated/df_core.meta.c index b8e5b2cc..3fc0a521 100644 --- a/src/df/core/generated/df_core.meta.c +++ b/src/df/core/generated/df_core.meta.c @@ -209,7 +209,7 @@ DF_CoreCmdKind_Null, DF_CoreCmdKind_Null, }; -DF_CmdSpecInfo df_g_core_cmd_kind_spec_info_table[218] = +DF_CmdSpecInfo df_g_core_cmd_kind_spec_info_table[220] = { { str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp(""), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null}, { str8_lit_comp("exit"), str8_lit_comp("Exits the debugger."), str8_lit_comp("quit,close,abort"), str8_lit_comp("Exit"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_X}, @@ -294,6 +294,8 @@ DF_CmdSpecInfo df_g_core_cmd_kind_spec_info_table[218] = { str8_lit_comp("open"), str8_lit_comp("Opens a file."), str8_lit_comp("code,source,file"), str8_lit_comp("Open"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_FilePath, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*1)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*1)}, DF_IconKind_FileOutline}, { str8_lit_comp("switch"), str8_lit_comp("Switches to a loaded file."), str8_lit_comp("code,source,file"), str8_lit_comp("Switch"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Entity, DF_EntityKind_File, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*1)}, DF_IconKind_FileOutline}, { str8_lit_comp("switch_to_partner_file"), str8_lit_comp("Switches to the focused file's partner; or from header to implementation or vice versa."), str8_lit_comp("code,source,file"), str8_lit_comp("Switch To Partner File"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_FileOutline}, +{ str8_lit_comp("go_to_disassembly"), str8_lit_comp("Goes to the disassembly, if any, for a given source code line."), str8_lit_comp("code,source,disassembly,disasm"), str8_lit_comp("Go To Disassembly"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Glasses}, +{ str8_lit_comp("go_to_source"), str8_lit_comp("Goes to the source code, if any, for a given disassembly line."), str8_lit_comp("code,source,disassembly,disasm"), str8_lit_comp("Go To Source"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_FileOutline}, { str8_lit_comp("set_file_override_link_src"), str8_lit_comp("Sets the source path for an override file link."), str8_lit_comp(""), str8_lit_comp("Set File Override Link Source"), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null}, { str8_lit_comp("set_file_override_link_dst"), str8_lit_comp("Sets the destination path for an override file link."), str8_lit_comp(""), str8_lit_comp("Set File Override Link Destination"), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null}, { str8_lit_comp("set_file_replacement_path"), str8_lit_comp("Sets the path which should be used as the replacement for the passed file."), str8_lit_comp(""), str8_lit_comp("Set File Replacement Path"), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null}, diff --git a/src/df/core/generated/df_core.meta.h b/src/df/core/generated/df_core.meta.h index 722ecbb4..462a6852 100644 --- a/src/df/core/generated/df_core.meta.h +++ b/src/df/core/generated/df_core.meta.h @@ -130,6 +130,8 @@ DF_CoreCmdKind_SetCurrentPath, DF_CoreCmdKind_Open, DF_CoreCmdKind_Switch, DF_CoreCmdKind_SwitchToPartnerFile, +DF_CoreCmdKind_GoToDisassembly, +DF_CoreCmdKind_GoToSource, DF_CoreCmdKind_SetFileOverrideLinkSrc, DF_CoreCmdKind_SetFileOverrideLinkDst, DF_CoreCmdKind_SetFileReplacementPath, diff --git a/src/df/gfx/df_gfx.c b/src/df/gfx/df_gfx.c index ba9d31f3..3e7d24ab 100644 --- a/src/df/gfx/df_gfx.c +++ b/src/df/gfx/df_gfx.c @@ -1029,6 +1029,7 @@ df_window_open(Vec2F32 size, OS_Handle preferred_monitor, DF_CfgSrc cfg_src) window->code_ctx_menu_key = ui_key_from_string(ui_key_zero(), str8_lit("_code_ctx_menu_")); window->entity_ctx_menu_key = ui_key_from_string(ui_key_zero(), str8_lit("_entity_ctx_menu_")); window->tab_ctx_menu_key = ui_key_from_string(ui_key_zero(), str8_lit("_tab_ctx_menu_")); + window->code_ctx_menu_arena = arena_alloc(); window->hover_eval_arena = arena_alloc(); window->autocomp_lister_params_arena = arena_alloc(); window->free_panel = &df_g_nil_panel; @@ -2585,13 +2586,25 @@ df_window_update_and_render(Arena *arena, DF_Window *ws, DF_CmdList *cmds) DI_Key dbgi_key = df_dbgi_key_from_module(module); RDI_Parsed *rdi = di_rdi_from_key(scope, &dbgi_key, 0); U64 rip_voff = df_voff_from_vaddr(module, rip_vaddr); - DF_TextLineDasm2SrcInfo line_info = df_text_line_dasm2src_info_from_dbgi_key_voff(&dbgi_key, rip_voff, inline_unwind_index); + DF_LineList lines = df_lines_from_dbgi_key_voff(scratch.arena, &dbgi_key, rip_voff); + DF_Line line = {0}; + { + U64 idx = 0; + for(DF_LineNode *n = lines.first; n != 0; n = n->next, idx += 1) + { + line = n->v; + if(idx == inline_unwind_index) + { + break; + } + } + } // rjf: snap to resolved line B32 missing_rip = (rip_vaddr == 0); B32 dbgi_missing = (dbgi_key.min_timestamp == 0 || dbgi_key.path.size == 0); B32 dbgi_pending = !dbgi_missing && rdi == &di_rdi_parsed_nil; - B32 has_line_info = (line_info.voff_range.max != line_info.voff_range.min); + B32 has_line_info = (line.voff_range.max != line.voff_range.min); B32 has_module = !df_entity_is_nil(module); B32 has_dbg_info = has_module && !dbgi_missing; if(!dbgi_pending && (has_line_info || has_module)) @@ -2599,8 +2612,8 @@ df_window_update_and_render(Arena *arena, DF_Window *ws, DF_CmdList *cmds) DF_CmdParams params = df_cmd_params_from_window(ws); if(has_line_info) { - params.file_path = df_full_path_from_entity(scratch.arena, line_info.file); - params.text_point = line_info.pt; + params.file_path = df_full_path_from_entity(scratch.arena, df_entity_from_handle(line.file)); + params.text_point = line.pt; df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_FilePath); df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_TextPoint); } @@ -2783,28 +2796,31 @@ df_window_update_and_render(Arena *arena, DF_Window *ws, DF_CmdList *cmds) // rjf: name resolved to voff * dbg info if(name_resolved != 0 && voff != 0) { - DF_TextLineDasm2SrcInfo dasm2src_info = df_text_line_dasm2src_info_from_dbgi_key_voff(&voff_dbgi_key, voff, 0); - DF_CmdParams p = params; + DF_LineList lines = df_lines_from_dbgi_key_voff(scratch.arena, &voff_dbgi_key, voff); + if(lines.first != 0) { - p.file_path = df_full_path_from_entity(scratch.arena, dasm2src_info.file); - p.text_point = dasm2src_info.pt; - df_cmd_params_mark_slot(&p, DF_CmdParamSlot_FilePath); - df_cmd_params_mark_slot(&p, DF_CmdParamSlot_TextPoint); - if(voff_dbgi_key.path.size != 0) + DF_CmdParams p = params; { - DF_EntityList modules = df_modules_from_dbgi_key(scratch.arena, &voff_dbgi_key); - DF_Entity *module = df_first_entity_from_list(&modules); - DF_Entity *process = df_entity_ancestor_from_kind(module, DF_EntityKind_Process); - if(!df_entity_is_nil(process)) + p.file_path = df_full_path_from_entity(scratch.arena, df_entity_from_handle(lines.first->v.file)); + p.text_point = lines.first->v.pt; + df_cmd_params_mark_slot(&p, DF_CmdParamSlot_FilePath); + df_cmd_params_mark_slot(&p, DF_CmdParamSlot_TextPoint); + if(voff_dbgi_key.path.size != 0) { - p.entity = df_handle_from_entity(process); - p.vaddr = module->vaddr_rng.min + dasm2src_info.voff_range.min; - df_cmd_params_mark_slot(&p, DF_CmdParamSlot_Entity); - df_cmd_params_mark_slot(&p, DF_CmdParamSlot_VirtualAddr); + DF_EntityList modules = df_modules_from_dbgi_key(scratch.arena, &voff_dbgi_key); + DF_Entity *module = df_first_entity_from_list(&modules); + DF_Entity *process = df_entity_ancestor_from_kind(module, DF_EntityKind_Process); + if(!df_entity_is_nil(process)) + { + p.entity = df_handle_from_entity(process); + p.vaddr = module->vaddr_rng.min + lines.first->v.voff_range.min; + df_cmd_params_mark_slot(&p, DF_CmdParamSlot_Entity); + df_cmd_params_mark_slot(&p, DF_CmdParamSlot_VirtualAddr); + } } } + df_cmd_list_push(arena, cmds, &p, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_FindCodeLocation)); } - df_cmd_list_push(arena, cmds, &p, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_FindCodeLocation)); } // rjf: name resolved to a file @@ -3694,9 +3710,154 @@ df_window_update_and_render(Arena *arena, DF_Window *ws, DF_CmdList *cmds) UI_PrefWidth(ui_em(30.f, 1.f)) DF_Palette(DF_PaletteCode_ImplicitButton) { - ui_buttonf("Foo"); - ui_buttonf("Bar"); - ui_buttonf("Baz"); + TXT_Scope *txt_scope = txt_scope_open(); + HS_Scope *hs_scope = hs_scope_open(); + DF_CtrlCtx ctrl_ctx = df_ctrl_ctx_from_window(ws); + TxtRng range = ws->code_ctx_menu_range; + DF_LineList lines = ws->code_ctx_menu_lines; + if(!txt_pt_match(range.min, range.max) && ui_clicked(df_cmd_spec_button(df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_Copy)))) + { + U128 hash = {0}; + TXT_TextInfo info = txt_text_info_from_key_lang(txt_scope, ws->code_ctx_menu_text_key, ws->code_ctx_menu_lang_kind, &hash); + String8 data = hs_data_from_hash(hs_scope, hash); + String8 copy_data = txt_string_from_info_data_txt_rng(&info, data, ws->code_ctx_menu_range); + os_set_clipboard_text(copy_data); + ui_ctx_menu_close(); + } + if(range.min.line == range.max.line && ui_clicked(df_icon_buttonf(DF_IconKind_RightArrow, 0, "Move Thread Here"))) + { + DF_Entity *thread = df_entity_from_handle(ctrl_ctx.thread); + U64 new_rip_vaddr = ws->code_ctx_menu_vaddr; + if(!df_entity_is_nil(df_entity_from_handle(ws->code_ctx_menu_file))) + { + for(DF_LineNode *n = lines.first; n != 0; n = n->next) + { + DF_EntityList modules = df_modules_from_dbgi_key(scratch.arena, &n->v.dbgi_key); + DF_Entity *module = df_module_from_thread_candidates(thread, &modules); + if(!df_entity_is_nil(module)) + { + new_rip_vaddr = df_vaddr_from_voff(module, n->v.voff_range.min); + break; + } + } + } + DF_CmdParams p = df_cmd_params_from_window(ws); + p.entity = df_handle_from_entity(thread); + p.vaddr = new_rip_vaddr; + df_push_cmd__root(&p, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_SetThreadIP)); + ui_ctx_menu_close(); + } + if(range.min.line == range.max.line && ui_clicked(df_icon_buttonf(DF_IconKind_Play, 0, "Run To Line"))) + { + if(!df_entity_is_nil(df_entity_from_handle(ws->code_ctx_menu_file))) + { + DF_CmdParams p = df_cmd_params_from_window(ws); + p.entity = ws->code_ctx_menu_file; + p.text_point = range.min; + df_push_cmd__root(&p, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_RunToLine)); + } + else + { + DF_CmdParams p = df_cmd_params_from_window(ws); + p.vaddr = ws->code_ctx_menu_vaddr; + df_push_cmd__root(&p, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_RunToAddress)); + } + ui_ctx_menu_close(); + } + if(range.min.line == range.max.line && ui_clicked(df_icon_buttonf(DF_IconKind_Null, 0, "Go To Name"))) + { + U128 hash = {0}; + TXT_TextInfo info = txt_text_info_from_key_lang(txt_scope, ws->code_ctx_menu_text_key, ws->code_ctx_menu_lang_kind, &hash); + String8 data = hs_data_from_hash(hs_scope, hash); + Rng1U64 expr_off_range = {0}; + if(range.min.column != range.max.column) + { + expr_off_range = r1u64(txt_off_from_info_pt(&info, range.min), txt_off_from_info_pt(&info, range.max)); + } + else + { + expr_off_range = txt_expr_off_range_from_info_data_pt(&info, data, range.min); + } + String8 expr = str8_substr(data, expr_off_range); + DF_CmdParams p = df_cmd_params_from_window(ws); + p.string = expr; + df_push_cmd__root(&p, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_GoToName)); + ui_ctx_menu_close(); + } + if(range.min.line == range.max.line && ui_clicked(df_icon_buttonf(DF_IconKind_CircleFilled, 0, "Toggle Breakpoint"))) + { + if(ws->code_ctx_menu_vaddr != 0) + { + DF_CmdParams p = df_cmd_params_from_window(ws); + p.vaddr = ws->code_ctx_menu_vaddr; + df_push_cmd__root(&p, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_AddressBreakpoint)); + } + else + { + DF_CmdParams p = df_cmd_params_from_window(ws); + p.entity = ws->code_ctx_menu_file; + p.text_point = range.min; + df_push_cmd__root(&p, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_TextBreakpoint)); + } + ui_ctx_menu_close(); + } + if(range.min.line == range.max.line && ui_clicked(df_icon_buttonf(DF_IconKind_Binoculars, 0, "Toggle Watch Expression"))) + { + U128 hash = {0}; + TXT_TextInfo info = txt_text_info_from_key_lang(txt_scope, ws->code_ctx_menu_text_key, ws->code_ctx_menu_lang_kind, &hash); + String8 data = hs_data_from_hash(hs_scope, hash); + Rng1U64 expr_off_range = {0}; + if(range.min.column != range.max.column) + { + expr_off_range = r1u64(txt_off_from_info_pt(&info, range.min), txt_off_from_info_pt(&info, range.max)); + } + else + { + expr_off_range = txt_expr_off_range_from_info_data_pt(&info, data, range.min); + } + String8 expr = str8_substr(data, expr_off_range); + DF_CmdParams p = df_cmd_params_from_window(ws); + p.string = expr; + df_push_cmd__root(&p, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_ToggleWatchExpression)); + ui_ctx_menu_close(); + } + if(df_entity_is_nil(df_entity_from_handle(ws->code_ctx_menu_file)) && range.min.line == range.max.line && ui_clicked(df_icon_buttonf(DF_IconKind_FileOutline, 0, "Go To Source"))) + { + if(lines.first != 0) + { + DF_CmdParams params = df_cmd_params_from_window(ws); + params.file_path = df_full_path_from_entity(scratch.arena, df_entity_from_handle(lines.first->v.file)); + params.text_point = lines.first->v.pt; + df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_FilePath); + df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_TextPoint); + df_push_cmd__root(¶ms, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_FindCodeLocation)); + } + ui_ctx_menu_close(); + } + if(!df_entity_is_nil(df_entity_from_handle(ws->code_ctx_menu_file)) && range.min.line == range.max.line && ui_clicked(df_icon_buttonf(DF_IconKind_FileOutline, 0, "Go To Disassembly"))) + { + DF_Entity *thread = df_entity_from_handle(ctrl_ctx.thread); + U64 vaddr = 0; + for(DF_LineNode *n = lines.first; n != 0; n = n->next) + { + DF_EntityList modules = df_modules_from_dbgi_key(scratch.arena, &n->v.dbgi_key); + DF_Entity *module = df_module_from_thread_candidates(thread, &modules); + if(!df_entity_is_nil(module)) + { + vaddr = df_vaddr_from_voff(module, n->v.voff_range.min); + break; + } + } + DF_CmdParams params = df_cmd_params_from_window(ws); + df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_Entity); + df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_VirtualAddr); + params.entity = df_handle_from_entity(thread); + params.vaddr = vaddr; + df_push_cmd__root(¶ms, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_FindCodeLocation)); + ui_ctx_menu_close(); + } + hs_scope_close(hs_scope); + txt_scope_close(txt_scope); } //- rjf: entity menu @@ -10607,7 +10768,7 @@ internal UI_BOX_CUSTOM_DRAW(df_bp_box_draw_extensions) } internal DF_CodeSliceSignal -df_code_slice(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_CodeSliceParams *params, TxtPt *cursor, TxtPt *mark, S64 *preferred_column, String8 string) +df_code_slice(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_CodeCtx *code_ctx, DF_CodeSliceParams *params, TxtPt *cursor, TxtPt *mark, S64 *preferred_column, String8 string) { DF_CodeSliceSignal result = {0}; ProfBeginFunction(); @@ -10674,82 +10835,6 @@ df_code_slice(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_ } } - ////////////////////////////// - //- rjf: build per-line context menus - // - UI_Key *ctx_menu_keys = push_array(scratch.arena, UI_Key, dim_1s64(params->line_num_range)+1); - { - U64 line_idx = 0; - for(S64 line_num = params->line_num_range.min; - line_num < params->line_num_range.max; - line_num += 1, line_idx += 1) - { - ctx_menu_keys[line_idx] = ui_key_from_stringf(top_container_box->key, "line_ctx_%I64d", line_num); - DF_Palette(DF_PaletteCode_Floating) - UI_CtxMenu(ctx_menu_keys[line_idx]) - DF_Palette(DF_PaletteCode_ImplicitButton) - UI_PrefWidth(ui_em(37.f, 1.f)) - { - DF_TextLineSrc2DasmInfoList *line_src2dasm_list = ¶ms->line_src2dasm[line_idx]; - DF_TextLineDasm2SrcInfoList *line_dasm2src_list = ¶ms->line_dasm2src[line_idx]; - - //- rjf: copy selection - if(!txt_pt_match(*cursor, *mark) && ui_clicked(df_cmd_spec_button(df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_Copy)))) - { - result.copy_range = txt_rng(*cursor, *mark); - ui_ctx_menu_close(); - } - - //- rjf: watch selection - if(ui_clicked(df_cmd_spec_button(df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_ToggleWatchExpressionAtCursor)))) - { - result.toggle_cursor_watch = 1; - ui_ctx_menu_close(); - } - - //- rjf: set-next-statement - if(ui_clicked(df_cmd_spec_button(df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_SetNextStatement)))) - { - result.set_next_statement_line_num = line_num; - ui_ctx_menu_close(); - } - - //- rjf: run-to-line - if(ui_clicked(df_icon_buttonf(DF_IconKind_Play, 0, "Run To Line"))) - { - result.run_to_line_num = line_num; - ui_ctx_menu_close(); - } - - //- rjf: breakpoint placing - if((params->line_bps[line_idx].count == 0 && - ui_clicked(df_icon_buttonf(DF_IconKind_CircleFilled, 0, "Place Breakpoint"))) || - (params->line_bps[line_idx].count != 0 && - ui_clicked(df_icon_buttonf(DF_IconKind_CircleFilled, 0, "Remove Breakpoint")))) - { - result.clicked_margin_line_num = line_num; - ui_ctx_menu_close(); - } - - //- rjf: go from src -> disasm - if(line_src2dasm_list->first != 0 && - ui_clicked(df_icon_buttonf(DF_IconKind_Find, 0, "Go To Disassembly"))) - { - result.goto_disasm_line_num = line_num; - ui_ctx_menu_close(); - } - - //- rjf: go from disasm -> src - if(line_dasm2src_list->first != 0 && - ui_clicked(df_icon_buttonf(DF_IconKind_Find, 0, "Go To Source"))) - { - result.goto_src_line_num = line_num; - ui_ctx_menu_close(); - } - } - } - } - ////////////////////////////// //- rjf: build priority margin // @@ -10851,23 +10936,21 @@ df_code_slice(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_ // rjf: fill out progress t (progress into range of current line's // voff range) - if(params->line_src2dasm[line_idx].first != 0) + if(params->line_infos[line_idx].first != 0) { - DF_TextLineSrc2DasmInfoList *line_info_list = ¶ms->line_src2dasm[line_idx]; - DF_TextLineSrc2DasmInfo *line_info = 0; - for(DF_TextLineSrc2DasmInfoNode *n = line_info_list->first; - n != 0; - n = n->next) + DF_LineList *lines = ¶ms->line_infos[line_idx]; + DF_Line *line = 0; + for(DF_LineNode *n = lines->first; n != 0; n = n->next) { if(di_key_match(&n->v.dbgi_key, &dbgi_key)) { - line_info = &n->v; + line = &n->v; break; } } - if(line_info != 0) + if(line != 0) { - Rng1U64 line_voff_rng = line_info->voff_range; + Rng1U64 line_voff_rng = line->voff_range; Vec4F32 weak_thread_color = color; weak_thread_color.w *= 0.4f; F32 progress_t = (line_voff_rng.max != line_voff_rng.min) ? ((F32)(thread_rip_voff - line_voff_rng.min) / (F32)(line_voff_rng.max - line_voff_rng.min)) : 0; @@ -11008,23 +11091,21 @@ df_code_slice(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_ // rjf: fill out progress t (progress into range of current line's // voff range) - if(params->line_src2dasm[line_idx].first != 0) + if(code_ctx->file != &df_g_nil_entity && params->line_infos[line_idx].first != 0) { - DF_TextLineSrc2DasmInfoList *line_info_list = ¶ms->line_src2dasm[line_idx]; - DF_TextLineSrc2DasmInfo *line_info = 0; - for(DF_TextLineSrc2DasmInfoNode *n = line_info_list->first; - n != 0; - n = n->next) + DF_LineList *lines = ¶ms->line_infos[line_idx]; + DF_Line *line = 0; + for(DF_LineNode *n = lines->first; n != 0; n = n->next) { if(di_key_match(&n->v.dbgi_key, &dbgi_key)) { - line_info = &n->v; + line = &n->v; break; } } - if(line_info != 0) + if(line != 0) { - Rng1U64 line_voff_rng = line_info->voff_range; + Rng1U64 line_voff_rng = line->voff_range; Vec4F32 weak_thread_color = color; weak_thread_color.w *= 0.4f; F32 progress_t = (line_voff_rng.max != line_voff_rng.min) ? ((F32)(thread_rip_voff - line_voff_rng.min) / (F32)(line_voff_rng.max - line_voff_rng.min)) : 0; @@ -11086,17 +11167,20 @@ df_code_slice(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_ DF_BreakpointBoxDrawExtData *bp_draw = push_array(ui_build_arena(), DF_BreakpointBoxDrawExtData, 1); { bp_draw->color = bp_color; - DF_TextLineSrc2DasmInfoList *src2dasm_list = ¶ms->line_src2dasm[line_idx]; - for(DF_TextLineSrc2DasmInfoNode *n = src2dasm_list->first; n != 0; n = n->next) + bp_draw->alive_t = bp->alive_t; + if(code_ctx->file != &df_g_nil_entity) { - S64 remap_line = (S64)n->v.remap_line; - if(remap_line != line_num) + DF_LineList *lines = ¶ms->line_infos[line_idx]; + for(DF_LineNode *n = lines->first; n != 0; n = n->next) { - bp_draw->remap_px_delta = (remap_line - line_num) * params->line_height_px; - break; + S64 remap_line = n->v.pt.line; + if(remap_line != line_num) + { + bp_draw->remap_px_delta = (remap_line - line_num) * params->line_height_px; + break; + } } } - bp_draw->alive_t = bp->alive_t; } // rjf: build box for breakpoint @@ -11248,33 +11332,17 @@ df_code_slice(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_ // rjf: line info on this line -> adjust bg color to visualize B32 has_line_info = 0; { + U64 best_stamp = 0; S64 line_info_line_num = 0; - F32 line_info_t = 0; - DF_TextLineSrc2DasmInfoList *src2dasm_list = ¶ms->line_src2dasm[line_idx]; - DF_TextLineDasm2SrcInfoList *dasm2src_list = ¶ms->line_dasm2src[line_idx]; - if(src2dasm_list->first != 0) + F32 line_info_t = selected_thread_module->alive_t; + DF_LineList *lines = ¶ms->line_infos[line_idx]; + for(DF_LineNode *n = lines->first; n != 0; n = n->next) { - has_line_info = (src2dasm_list->first->v.remap_line == line_num); - line_info_line_num = line_num; - line_info_t = selected_thread_module->alive_t; - } - if(dasm2src_list->first != 0) - { - DF_TextLineDasm2SrcInfo *dasm2src_info = 0; - U64 best_stamp = 0; - for(DF_TextLineDasm2SrcInfoNode *n = dasm2src_list->first; n != 0; n = n->next) + if(n->v.dbgi_key.min_timestamp >= best_stamp) { - if(n->v.file->timestamp > best_stamp) - { - dasm2src_info = &n->v; - best_stamp = n->v.file->timestamp; - } - } - if(dasm2src_info != 0) - { - has_line_info = 1; - line_info_line_num = dasm2src_info->pt.line; - line_info_t = selected_thread_module->alive_t; + has_line_info = (n->v.pt.line == line_num || code_ctx->file == &df_g_nil_entity); + line_info_line_num = n->v.pt.line; + best_stamp = n->v.dbgi_key.min_timestamp; } } if(has_line_info) @@ -11575,42 +11643,26 @@ df_code_slice(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_ *preferred_column = cursor->column; } - //- rjf: right-click => active context menu for line + //- rjf: right-click => code context menu if(ui_right_clicked(text_container_sig)) { - S64 line_idx = mouse_pt.line-params->line_num_range.min; - if(0 <= line_idx && line_idx < dim_1s64(params->line_num_range)) + if(txt_pt_match(*cursor, *mark)) { - ui_ctx_menu_open(ctx_menu_keys[line_idx], ui_key_zero(), sub_2f32(ui_mouse(), v2f32(2, 2))); - if(txt_pt_match(*cursor, *mark)) - { - *cursor = *mark = mouse_pt; - } + *cursor = *mark = mouse_pt; } - } - - //- rjf: hovering text container & ctrl+scroll -> change font size - if(ui_hovering(text_container_sig)) - { - UI_EventList *events = ui_events(); - for(UI_EventNode *n = events->first, *next = 0; n != 0; n = next) + ui_ctx_menu_open(ws->code_ctx_menu_key, ui_key_zero(), sub_2f32(ui_mouse(), v2f32(2, 2))); + arena_clear(ws->code_ctx_menu_arena); + ws->code_ctx_menu_file = df_handle_from_entity(code_ctx->file); + ws->code_ctx_menu_text_key = code_ctx->text_key; + ws->code_ctx_menu_lang_kind = code_ctx->lang_kind; + ws->code_ctx_menu_range = txt_rng(*cursor, *mark); + if(params->line_num_range.min <= cursor->line && cursor->line < params->line_num_range.max) { - next = n->next; - UI_Event *event = &n->v; - if(event->kind == UI_EventKind_Scroll && event->modifiers & OS_EventFlag_Ctrl) - { - ui_eat_event(events, n); - if(event->delta_2f32.y < 0) - { - DF_CmdParams params = df_cmd_params_from_window(ws); - df_push_cmd__root(¶ms, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_IncCodeFontScale)); - } - else if(event->delta_2f32.y > 0) - { - DF_CmdParams params = df_cmd_params_from_window(ws); - df_push_cmd__root(¶ms, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_DecCodeFontScale)); - } - } + ws->code_ctx_menu_vaddr = params->line_vaddrs[cursor->line - params->line_num_range.min]; + } + if(params->line_num_range.min <= cursor->line && cursor->line < params->line_num_range.max) + { + ws->code_ctx_menu_lines = df_line_list_copy(ws->code_ctx_menu_arena, ¶ms->line_infos[cursor->line - params->line_num_range.min]); } } @@ -11629,6 +11681,8 @@ df_code_slice(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_ } //- rjf: drop target is dropped -> process + // TODO(rjf): @src_collapse +#if 0 { DF_DragDropPayload payload = {0}; if(!df_entity_is_nil(line_drag_entity) && df_drag_drop(&payload)) @@ -11637,6 +11691,7 @@ df_code_slice(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_ result.dropped_entity_line_num = mouse_pt.line; } } +#endif //- rjf: commit text container signal to main output result.base = text_container_sig; @@ -11645,6 +11700,8 @@ df_code_slice(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_ ////////////////////////////// //- rjf: mouse -> expression range info // + TxtRng mouse_expr_rng = {0}; + Vec2F32 mouse_expr_baseline_pos = {0}; if(ui_hovering(text_container_sig) && contains_1s64(params->line_num_range, mouse_pt.line)) ProfScope("mouse -> expression range") { TxtRng selected_rng = txt_rng(*cursor, *mark); @@ -11655,9 +11712,9 @@ df_code_slice(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_ U64 line_slice_idx = mouse_pt.line-params->line_num_range.min; String8 line_text = params->line_text[line_slice_idx]; F32 expr_hoff_px = params->line_num_width_px + f_dim_from_tag_size_string(params->font, params->font_size, 0, params->tab_size, str8_prefix(line_text, selected_rng.min.column-1)).x; - result.mouse_expr_rng = selected_rng; - result.mouse_expr_baseline_pos = v2f32(text_container_box->rect.x0+expr_hoff_px, - text_container_box->rect.y0+line_slice_idx*params->line_height_px + params->line_height_px*0.85f); + result.mouse_expr_rng = mouse_expr_rng = selected_rng; + result.mouse_expr_baseline_pos = mouse_expr_baseline_pos = v2f32(text_container_box->rect.x0+expr_hoff_px, + text_container_box->rect.y0+line_slice_idx*params->line_height_px + params->line_height_px*0.85f); } else { @@ -11670,9 +11727,9 @@ df_code_slice(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_ if(expr_off_rng.max != expr_off_rng.min) { F32 expr_hoff_px = params->line_num_width_px + f_dim_from_tag_size_string(params->font, params->font_size, 0, params->tab_size, str8_prefix(line_text, expr_off_rng.min-line_range.min)).x; - result.mouse_expr_rng = txt_rng(txt_pt(mouse_pt.line, 1+(expr_off_rng.min-line_range.min)), txt_pt(mouse_pt.line, 1+(expr_off_rng.max-line_range.min))); - result.mouse_expr_baseline_pos = v2f32(text_container_box->rect.x0+expr_hoff_px, - text_container_box->rect.y0+line_slice_idx*params->line_height_px + params->line_height_px*0.85f); + result.mouse_expr_rng = mouse_expr_rng = txt_rng(txt_pt(mouse_pt.line, 1+(expr_off_rng.min-line_range.min)), txt_pt(mouse_pt.line, 1+(expr_off_rng.max-line_range.min))); + result.mouse_expr_baseline_pos = mouse_expr_baseline_pos = v2f32(text_container_box->rect.x0+expr_hoff_px, + text_container_box->rect.y0+line_slice_idx*params->line_height_px + params->line_height_px*0.85f); } } } @@ -11683,29 +11740,38 @@ df_code_slice(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_ if(ui_hovering(text_container_sig) && contains_1s64(params->line_num_range, mouse_pt.line) && (ui_mouse().x - text_container_box->rect.x0 < params->line_num_width_px + line_num_padding_px)) { U64 line_slice_idx = mouse_pt.line-params->line_num_range.min; - if(params->line_src2dasm[line_slice_idx].first != 0 && - params->line_src2dasm[line_slice_idx].first->v.remap_line == mouse_pt.line) + DF_LineList *lines = ¶ms->line_infos[line_slice_idx]; + if(lines->first != 0 && (code_ctx->file == &df_g_nil_entity || lines->first->v.pt.line == mouse_pt.line)) { DF_RichHoverInfo info = {0}; info.process = df_handle_from_entity(selected_thread_process); - info.vaddr_range = df_vaddr_range_from_voff_range(selected_thread_module, params->line_src2dasm[line_slice_idx].first->v.voff_range); + info.vaddr_range = df_vaddr_range_from_voff_range(selected_thread_module, lines->first->v.voff_range); info.module = df_handle_from_entity(selected_thread_module); - info.dbgi_key = params->line_src2dasm[line_slice_idx].first->v.dbgi_key; - info.voff_range = params->line_src2dasm[line_slice_idx].first->v.voff_range; - df_set_rich_hover_info(&info); - } - if(params->line_dasm2src[line_slice_idx].first != 0) - { - DF_RichHoverInfo info = {0}; - info.process = df_handle_from_entity(selected_thread_process); - info.vaddr_range = df_vaddr_range_from_voff_range(selected_thread_module, params->line_dasm2src[line_slice_idx].first->v.voff_range); - info.module = df_handle_from_entity(selected_thread_module); - info.dbgi_key = params->line_dasm2src[line_slice_idx].first->v.dbgi_key; - info.voff_range = params->line_dasm2src[line_slice_idx].first->v.voff_range; + info.dbgi_key = lines->first->v.dbgi_key; + info.voff_range = lines->first->v.voff_range; df_set_rich_hover_info(&info); } } + ////////////////////////////// + //- rjf: hover eval + // +#if 0 + if(!ui_dragging(text_container_sig) && sig.mouse_expr_rng.min.line != 0 && sig.base.event_flags == 0) + { + TxtRng expr_rng = mouse_expr_rng; + String8 expr = txt_string_from_info_data_txt_rng(&text_info, data, expr_rng); + if(expr.size != 0) + { + DF_Eval eval = df_eval_from_string(scratch.arena, di_scope, &ctrl_ctx, &parse_ctx, &eval_string2expr_map_nil, expr); + if(eval.mode != EVAL_EvalMode_NULL) + { + df_set_hover_eval(ws, mouse_expr_baseline_pos, ctrl_ctx, entity, sig.mouse_pt, 0, expr); + } + } + } +#endif + ////////////////////////////// //- rjf: dragging entity which applies to lines over this slice -> visualize // @@ -12048,37 +12114,16 @@ df_code_slice(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_ { B32 matches = 0; S64 line_info_line_num = 0; - DF_TextLineSrc2DasmInfoList *src2dasm_list = ¶ms->line_src2dasm[line_idx]; - DF_TextLineDasm2SrcInfoList *dasm2src_list = ¶ms->line_dasm2src[line_idx]; - - // rjf: check src2dasm - if(src2dasm_list->first != 0) + DF_LineList *lines = ¶ms->line_infos[line_idx]; + for(DF_LineNode *n = lines->first; n != 0; n = n->next) { - for(DF_TextLineSrc2DasmInfoNode *n = src2dasm_list->first; n != 0; n = n->next) + if((n->v.pt.line == line_num || code_ctx->file == &df_g_nil_entity) && + di_key_match(&n->v.dbgi_key, &hovered_line_dbgi_key) && + n->v.voff_range.min <= hovered_line_voff && hovered_line_voff < n->v.voff_range.max) { - if(n->v.remap_line == line_num && - di_key_match(&n->v.dbgi_key, &hovered_line_dbgi_key) && - n->v.voff_range.min <= hovered_line_voff && hovered_line_voff < n->v.voff_range.max) - { - matches = 1; - line_info_line_num = line_num; - break; - } - } - } - - // rjf: check dasm2src - if(dasm2src_list->first != 0) - { - for(DF_TextLineDasm2SrcInfoNode *n = dasm2src_list->first; n != 0; n = n->next) - { - if(n->v.voff_range.min <= hovered_line_voff && - hovered_line_voff < n->v.voff_range.max) - { - line_info_line_num = n->v.pt.line; - matches = 1; - break; - } + matches = 1; + line_info_line_num = n->v.pt.line; + break; } } @@ -12108,13 +12153,13 @@ df_code_slice(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_ } internal DF_CodeSliceSignal -df_code_slicef(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_CodeSliceParams *params, TxtPt *cursor, TxtPt *mark, S64 *preferred_column, char *fmt, ...) +df_code_slicef(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_CodeCtx *code_ctx, DF_CodeSliceParams *params, TxtPt *cursor, TxtPt *mark, S64 *preferred_column, char *fmt, ...) { Temp scratch = scratch_begin(0, 0); va_list args; va_start(args, fmt); String8 string = push_str8fv(scratch.arena, fmt, args); - DF_CodeSliceSignal sig = df_code_slice(ws, ctrl_ctx, parse_ctx, params, cursor, mark, preferred_column, string); + DF_CodeSliceSignal sig = df_code_slice(ws, ctrl_ctx, parse_ctx, code_ctx, params, cursor, mark, preferred_column, string); va_end(args); scratch_end(scratch); return sig; @@ -13414,6 +13459,7 @@ df_gfx_begin_frame(Arena *arena, DF_CmdList *cmds) r_window_unequip(ws->os, ws->r); os_window_close(ws->os); arena_release(ws->query_cmd_arena); + arena_release(ws->code_ctx_menu_arena); arena_release(ws->hover_eval_arena); arena_release(ws->autocomp_lister_params_arena); arena_release(ws->arena); diff --git a/src/df/gfx/df_gfx.h b/src/df/gfx/df_gfx.h index 337fe601..afe3e7ab 100644 --- a/src/df/gfx/df_gfx.h +++ b/src/df/gfx/df_gfx.h @@ -432,6 +432,14 @@ enum DF_CodeSliceFlag_LineNums = (1<<3), }; +typedef struct DF_CodeCtx DF_CodeCtx; +struct DF_CodeCtx +{ + DF_Entity *file; // the source file, if any, from which the code was derived + U128 text_key; // the text info cache key for the backing textual data + TXT_LangKind lang_kind; // the language for which the text is parsed/analyzed +}; + typedef struct DF_CodeSliceParams DF_CodeSliceParams; struct DF_CodeSliceParams { @@ -444,8 +452,8 @@ struct DF_CodeSliceParams DF_EntityList *line_bps; DF_EntityList *line_ips; DF_EntityList *line_pins; - DF_TextLineDasm2SrcInfoList *line_dasm2src; - DF_TextLineSrc2DasmInfoList *line_src2dasm; + U64 *line_vaddrs; + DF_LineList *line_infos; DI_KeyList relevant_dbgi_keys; // rjf: visual parameters @@ -570,10 +578,14 @@ struct DF_Window B32 menu_bar_focus_press_started; // rjf: code context menu state + Arena *code_ctx_menu_arena; UI_Key code_ctx_menu_key; - DF_Handle code_ctx_menu_entity; + DF_Handle code_ctx_menu_file; U128 code_ctx_menu_text_key; + TXT_LangKind code_ctx_menu_lang_kind; TxtRng code_ctx_menu_range; + U64 code_ctx_menu_vaddr; + DF_LineList code_ctx_menu_lines; // rjf: entity context menu state UI_Key entity_ctx_menu_key; @@ -620,6 +632,7 @@ struct DF_Window Vec2F32 hover_eval_spawn_pos; String8 hover_eval_string; + // rjf: hover eval timer U64 hover_eval_first_frame_idx; U64 hover_eval_last_frame_idx; @@ -1071,8 +1084,8 @@ internal void df_entity_src_loc_button(DF_Window *ws, DF_Entity *entity, TxtPt p internal UI_BOX_CUSTOM_DRAW(df_thread_box_draw_extensions); internal UI_BOX_CUSTOM_DRAW(df_bp_box_draw_extensions); -internal DF_CodeSliceSignal df_code_slice(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_CodeSliceParams *params, TxtPt *cursor, TxtPt *mark, S64 *preferred_column, String8 string); -internal DF_CodeSliceSignal df_code_slicef(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_CodeSliceParams *params, TxtPt *cursor, TxtPt *mark, S64 *preferred_column, char *fmt, ...); +internal DF_CodeSliceSignal df_code_slice(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_CodeCtx *code_ctx, DF_CodeSliceParams *params, TxtPt *cursor, TxtPt *mark, S64 *preferred_column, String8 string); +internal DF_CodeSliceSignal df_code_slicef(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_CodeCtx *code_ctx, DF_CodeSliceParams *params, TxtPt *cursor, TxtPt *mark, S64 *preferred_column, char *fmt, ...); internal B32 df_do_txt_controls(TXT_TextInfo *info, String8 data, U64 line_count_per_page, TxtPt *cursor, TxtPt *mark, S64 *preferred_column); internal B32 df_do_txti_controls(TXTI_Handle handle, U64 line_count_per_page, TxtPt *cursor, TxtPt *mark, S64 *preferred_column); diff --git a/src/df/gfx/df_view_rules.c b/src/df/gfx/df_view_rules.c index 8939cb36..15a34f0c 100644 --- a/src/df/gfx/df_view_rules.c +++ b/src/df/gfx/df_view_rules.c @@ -537,9 +537,10 @@ DF_GFX_VIEW_RULE_BLOCK_UI_FUNCTION_DEF(text) String8 data = {0}; TXT_TextInfo info = {0}; TXT_LineTokensSlice line_tokens_slice = {0}; + U128 text_key = {0}; { U128 text_hash = {0}; - U128 text_key = ctrl_hash_store_key_from_process_vaddr_range(process->ctrl_machine_id, process->ctrl_handle, vaddr_range, 1); + text_key = ctrl_hash_store_key_from_process_vaddr_range(process->ctrl_machine_id, process->ctrl_handle, vaddr_range, 1); info = txt_text_info_from_key_lang(txt_scope, text_key, top.lang, &text_hash); data = hs_data_from_hash(hs_scope, text_hash); line_tokens_slice = txt_line_tokens_slice_from_info_data_line_range(scratch.arena, &info, data, r1s64(1, info.lines_count)); @@ -558,8 +559,8 @@ DF_GFX_VIEW_RULE_BLOCK_UI_FUNCTION_DEF(text) code_slice_params.line_bps = push_array(scratch.arena, DF_EntityList, info.lines_count); code_slice_params.line_ips = push_array(scratch.arena, DF_EntityList, info.lines_count); code_slice_params.line_pins = push_array(scratch.arena, DF_EntityList, info.lines_count); - code_slice_params.line_dasm2src = push_array(scratch.arena, DF_TextLineDasm2SrcInfoList, info.lines_count); - code_slice_params.line_src2dasm = push_array(scratch.arena, DF_TextLineSrc2DasmInfoList, info.lines_count); + code_slice_params.line_vaddrs = push_array(scratch.arena, U64, info.lines_count); + code_slice_params.line_infos = push_array(scratch.arena, DF_LineList, info.lines_count); for(U64 line_idx = 0; line_idx < info.lines_count; line_idx += 1) { code_slice_params.line_text[line_idx] = str8_substr(data, info.lines_ranges[line_idx]); @@ -591,7 +592,8 @@ DF_GFX_VIEW_RULE_BLOCK_UI_FUNCTION_DEF(text) //- rjf: build code slice UI_WidthFill UI_HeightFill UI_Parent(container) { - DF_CodeSliceSignal slice_sig = df_code_slice(ws, ctrl_ctx, parse_ctx, &code_slice_params, &state->cursor, &state->mark, &state->preferred_column, str8_lit("###slice")); + DF_CodeCtx code_ctx = {&df_g_nil_entity, text_key, top.lang}; + DF_CodeSliceSignal slice_sig = df_code_slice(ws, ctrl_ctx, parse_ctx, &code_ctx, &code_slice_params, &state->cursor, &state->mark, &state->preferred_column, str8_lit("###slice")); } } @@ -697,11 +699,12 @@ DF_GFX_VIEW_RULE_BLOCK_UI_FUNCTION_DEF(disasm) DASM_Info dasm_info = dasm_info_from_key_params(dasm_scope, dasm_key, &dasm_params, &data_hash); String8 dasm_text_data = {0}; TXT_TextInfo dasm_text_info = {0}; + TXT_LangKind lang_kind = TXT_LangKind_DisasmX64Intel; for(U64 rewind_idx = 0; rewind_idx < 2; rewind_idx += 1) { U128 dasm_text_hash = hs_hash_from_key(dasm_info.text_key, rewind_idx); dasm_text_data = hs_data_from_hash(hs_scope, dasm_text_hash); - dasm_text_info = txt_text_info_from_hash_lang(txt_scope, dasm_text_hash, TXT_LangKind_DisasmX64Intel); + dasm_text_info = txt_text_info_from_hash_lang(txt_scope, dasm_text_hash, lang_kind); if(dasm_text_info.lines_count != 0) { break; @@ -720,8 +723,8 @@ DF_GFX_VIEW_RULE_BLOCK_UI_FUNCTION_DEF(disasm) code_slice_params.line_bps = push_array(scratch.arena, DF_EntityList, dasm_text_info.lines_count); code_slice_params.line_ips = push_array(scratch.arena, DF_EntityList, dasm_text_info.lines_count); code_slice_params.line_pins = push_array(scratch.arena, DF_EntityList, dasm_text_info.lines_count); - code_slice_params.line_dasm2src = push_array(scratch.arena, DF_TextLineDasm2SrcInfoList, dasm_text_info.lines_count); - code_slice_params.line_src2dasm = push_array(scratch.arena, DF_TextLineSrc2DasmInfoList, dasm_text_info.lines_count); + code_slice_params.line_vaddrs = push_array(scratch.arena, U64, dasm_text_info.lines_count); + code_slice_params.line_infos = push_array(scratch.arena, DF_LineList, dasm_text_info.lines_count); for(U64 line_idx = 0; line_idx < dasm_text_info.lines_count; line_idx += 1) { code_slice_params.line_text[line_idx] = str8_substr(dasm_text_data, dasm_info.insts.v[line_idx].text_range); @@ -742,7 +745,8 @@ DF_GFX_VIEW_RULE_BLOCK_UI_FUNCTION_DEF(disasm) if(dasm_info.insts.count != 0 && dasm_text_info.lines_count != 0) UI_Padding(ui_pct(1, 0)) UI_PrefWidth(ui_px(dasm_text_info.lines_max_size*ui_top_font_size()*1.2f, 1.f)) UI_Column UI_Padding(ui_pct(1, 0)) { - DF_CodeSliceSignal sig = df_code_slice(ws, ctrl_ctx, parse_ctx, &code_slice_params, &state->cursor, &state->mark, &state->preferred_column, str8_lit("###code_slice")); + DF_CodeCtx code_ctx = {&df_g_nil_entity, dasm_info.text_key, lang_kind}; + DF_CodeSliceSignal sig = df_code_slice(ws, ctrl_ctx, parse_ctx, &code_ctx, &code_slice_params, &state->cursor, &state->mark, &state->preferred_column, str8_lit("###code_slice")); } } dasm_scope_close(dasm_scope); diff --git a/src/df/gfx/df_views.c b/src/df/gfx/df_views.c index 52b35955..2a7d9eaf 100644 --- a/src/df/gfx/df_views.c +++ b/src/df/gfx/df_views.c @@ -387,7 +387,7 @@ df_code_view_init(DF_CodeViewState *cv, DF_View *view) } internal void -df_code_view_cmds(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_CodeViewState *cv, DF_CmdList *cmds, String8 data, TXT_TextInfo *info) +df_code_view_cmds(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_CodeViewState *cv, DF_CmdList *cmds, String8 data, TXT_TextInfo *info, DF_CodeCtx *code_ctx) { for(DF_CmdNode *n = cmds->first; n != 0; n = n->next) { @@ -499,7 +499,7 @@ df_code_view_cmds(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_CodeViewStat } internal void -df_code_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_CodeViewState *cv, Rng2F32 rect, String8 data, TXT_TextInfo *info) +df_code_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_CodeViewState *cv, Rng2F32 rect, String8 data, TXT_TextInfo *info, DF_CodeCtx *code_ctx) { ProfBeginFunction(); Temp scratch = scratch_begin(0, 0); @@ -603,8 +603,8 @@ df_code_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_CodeViewSta code_slice_params.line_bps = push_array(scratch.arena, DF_EntityList, visible_line_count); code_slice_params.line_ips = push_array(scratch.arena, DF_EntityList, visible_line_count); code_slice_params.line_pins = push_array(scratch.arena, DF_EntityList, visible_line_count); - code_slice_params.line_dasm2src = push_array(scratch.arena, DF_TextLineDasm2SrcInfoList, visible_line_count); - code_slice_params.line_src2dasm = push_array(scratch.arena, DF_TextLineSrc2DasmInfoList, visible_line_count); + code_slice_params.line_vaddrs = push_array(scratch.arena, U64, visible_line_count); + code_slice_params.line_infos = push_array(scratch.arena, DF_LineList, visible_line_count); code_slice_params.font = code_font; code_slice_params.font_size = code_font_size; code_slice_params.tab_size = code_tab_size; @@ -627,6 +627,73 @@ df_code_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_CodeViewSta code_slice_params.line_tokens[visible_line_idx] = slice.line_tokens[visible_line_idx]; } } + + // rjf: find visible breakpoints + ProfScope("find visible breakpoints") + { + for(DF_Entity *bp = code_ctx->file->first; !df_entity_is_nil(bp); bp = bp->next) + { + if(bp->deleted || bp->kind != DF_EntityKind_Breakpoint) { continue; } + if(visible_line_num_range.min <= bp->text_point.line && bp->text_point.line <= visible_line_num_range.max) + { + U64 slice_line_idx = (bp->text_point.line-visible_line_num_range.min); + df_entity_list_push(scratch.arena, &code_slice_params.line_bps[slice_line_idx], bp); + } + } + } + + // rjf: find live threads mapping to this file + ProfScope("find live threads mapping to this file") + { + DF_Entity *selected_thread = df_entity_from_handle(ctrl_ctx.thread); + DF_EntityList threads = df_query_cached_entity_list_with_kind(DF_EntityKind_Thread); + for(DF_EntityNode *thread_n = threads.first; thread_n != 0; thread_n = thread_n->next) + { + 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 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); + U64 rip_voff = df_voff_from_vaddr(module, last_inst_on_unwound_rip_vaddr); + DI_Key dbgi_key = df_dbgi_key_from_module(module); + DF_LineList lines = df_lines_from_dbgi_key_voff(scratch.arena, &dbgi_key, rip_voff); + for(DF_LineNode *n = lines.first; n != 0; n = n->next) + { + if(df_entity_from_handle(n->v.file) == code_ctx->file && visible_line_num_range.min <= n->v.pt.line && n->v.pt.line <= visible_line_num_range.max) + { + U64 slice_line_idx = lines.first->v.pt.line-visible_line_num_range.min; + df_entity_list_push(scratch.arena, &code_slice_params.line_ips[slice_line_idx], thread); + } + } + } + } + + // rjf: find visible watch pins + ProfScope("find visible watch pins") + { + for(DF_Entity *wp = code_ctx->file->first; !df_entity_is_nil(wp); wp = wp->next) + { + if(wp->deleted || wp->kind != DF_EntityKind_WatchPin) { continue; } + if(visible_line_num_range.min <= wp->text_point.line && wp->text_point.line <= visible_line_num_range.max) + { + U64 slice_line_idx = (wp->text_point.line-visible_line_num_range.min); + df_entity_list_push(scratch.arena, &code_slice_params.line_pins[slice_line_idx], wp); + } + } + } + + // rjf: find all src -> dasm info + ProfScope("find all src -> dasm info") + { + DF_LineListArray lines_array = df_lines_array_from_file_line_range(scratch.arena, code_ctx->file, visible_line_num_range); + if(lines_array.count != 0) + { + MemoryCopy(code_slice_params.line_infos, lines_array.v, sizeof(DF_LineList)*lines_array.count); + } + code_slice_params.relevant_dbgi_keys = lines_array.dbgi_keys; + } } ////////////////////////////// @@ -819,7 +886,7 @@ df_code_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_CodeViewSta DF_CodeSliceSignal sig = {0}; UI_Focus(UI_FocusKind_On) { - sig = df_code_slicef(ws, &ctrl_ctx, &parse_ctx, &code_slice_params, &cv->cursor, &cv->mark, &cv->preferred_column, "txt_view_%p", view); + sig = df_code_slicef(ws, &ctrl_ctx, &parse_ctx, code_ctx, &code_slice_params, &cv->cursor, &cv->mark, &cv->preferred_column, "txt_view_%p", view); } //- rjf: press code slice? -> focus panel @@ -852,13 +919,6 @@ df_code_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_CodeViewSta df_push_cmd__root(¶ms, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_GoToName)); } - //- rjf: copy text - if(!txt_pt_match(sig.copy_range.min, sig.copy_range.max)) - { - String8 text = txt_string_from_info_data_txt_rng(info, data, sig.copy_range); - os_set_clipboard_text(text); - } - //- rjf: selected text on single line, no query? -> set search text if(!txt_pt_match(cv->cursor, cv->mark) && cv->cursor.line == cv->mark.line && search_query.size == 0) { @@ -866,22 +926,9 @@ df_code_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_CodeViewSta df_set_search_string(text); } - //- rjf: toggle cursor watch - if(sig.toggle_cursor_watch) - { - DF_CmdParams params = df_cmd_params_from_view(ws, panel, view); - df_push_cmd__root(¶ms, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_ToggleWatchExpressionAtCursor)); - } - - //- rjf: set next statement - if(sig.set_next_statement_line_num != 0 && contains_1s64(visible_line_num_range, sig.set_next_statement_line_num)) - { - DF_CmdParams params = df_cmd_params_from_view(ws, panel, view); - params.text_point = txt_pt(sig.set_next_statement_line_num, 1); - df_push_cmd__root(¶ms, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_SetNextStatement)); - } - //- rjf: go to disasm + // TODO(rjf): @src_collapse +#if 0 if(sig.goto_disasm_line_num != 0 && contains_1s64(visible_line_num_range, sig.goto_disasm_line_num)) { U64 line_idx = (sig.goto_disasm_line_num-visible_line_num_range.min); @@ -911,6 +958,7 @@ df_code_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_CodeViewSta } } } +#endif } ////////////////////////////// @@ -1038,6 +1086,29 @@ df_code_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_CodeViewSta } ui_scroll_pt_clamp_idx(&view->scroll_pos.x, scroll_idx_rng[Axis2_X]); ui_scroll_pt_clamp_idx(&view->scroll_pos.y, scroll_idx_rng[Axis2_Y]); + if(ui_mouse_over(sig)) + { + UI_EventList *events = ui_events(); + for(UI_EventNode *n = events->first, *next = 0; n != 0; n = next) + { + next = n->next; + UI_Event *event = &n->v; + if(event->kind == UI_EventKind_Scroll && event->modifiers & OS_EventFlag_Ctrl) + { + ui_eat_event(events, n); + if(event->delta_2f32.y < 0) + { + DF_CmdParams params = df_cmd_params_from_window(ws); + df_push_cmd__root(¶ms, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_IncCodeFontScale)); + } + else if(event->delta_2f32.y > 0) + { + DF_CmdParams params = df_cmd_params_from_window(ws); + df_push_cmd__root(¶ms, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_DecCodeFontScale)); + } + } + } + } } txt_scope_close(txt_scope); @@ -4076,15 +4147,15 @@ DF_VIEW_UI_FUNCTION_DEF(SymbolLister) } if(ui_hovering(sig)) UI_Tooltip { - U64 binary_voff = df_voff_from_dbgi_key_symbol_name(&dbgi_key, name); - DF_TextLineDasm2SrcInfo dasm2src_info = df_text_line_dasm2src_info_from_dbgi_key_voff(&dbgi_key, binary_voff, 0); - String8 file_path = df_full_path_from_entity(scratch.arena, dasm2src_info.file); - S64 line_num = dasm2src_info.pt.line; df_code_label(1.f, 0, df_rgba_from_theme_color(DF_ThemeColor_CodeSymbol), name); UI_Font(df_font_from_slot(DF_FontSlot_Main)) UI_FlagsAdd(UI_BoxFlag_DrawTextWeak) ui_labelf("Procedure #%I64u", item->idx); - if(!df_entity_is_nil(dasm2src_info.file)) + U64 binary_voff = df_voff_from_dbgi_key_symbol_name(&dbgi_key, name); + DF_LineList lines = df_lines_from_dbgi_key_voff(scratch.arena, &dbgi_key, binary_voff); + if(lines.first != 0) { + String8 file_path = df_full_path_from_entity(scratch.arena, df_entity_from_handle(lines.first->v.file)); + S64 line_num = lines.first->v.pt.line; UI_Font(df_font_from_slot(DF_FontSlot_Main)) UI_FlagsAdd(UI_BoxFlag_DrawTextWeak) ui_labelf("%S:%I64d", file_path, line_num); } @@ -5460,10 +5531,14 @@ DF_VIEW_UI_FUNCTION_DEF(Scheduler) 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); - DF_TextLineDasm2SrcInfo line_info = df_text_line_dasm2src_info_from_dbgi_key_voff(&dbgi_key, rip_voff, 0); - if(!df_entity_is_nil(line_info.file)) + DF_LineList lines = df_lines_from_dbgi_key_voff(scratch.arena, &dbgi_key, rip_voff); + if(lines.first != 0) { - UI_PrefWidth(ui_children_sum(0)) df_entity_src_loc_button(ws, line_info.file, line_info.pt); + DF_Entity *file = df_entity_from_handle(lines.first->v.file); + if(!df_entity_is_nil(file)) + { + UI_PrefWidth(ui_children_sum(0)) df_entity_src_loc_button(ws, file, lines.first->v.pt); + } } } }break; @@ -6191,7 +6266,7 @@ DF_VIEW_UI_FUNCTION_DEF(PendingEntity) //////////////////////////////// //~ rjf: Code @view_hook_impl -#if 0 +#if 1 DF_VIEW_SETUP_FUNCTION_DEF(Code) { // rjf: set up state @@ -6229,13 +6304,15 @@ DF_VIEW_CMD_FUNCTION_DEF(Code) Temp scratch = scratch_begin(0, 0); HS_Scope *hs_scope = hs_scope_open(); TXT_Scope *txt_scope = txt_scope_open(); - String8 path = df_full_path_from_entity(scratch.arena, df_entity_from_handle(view->entity)); + DF_Entity *entity = df_entity_from_handle(view->entity); + String8 path = df_full_path_from_entity(scratch.arena, entity); TXT_LangKind lang_kind = txt_lang_kind_from_extension(str8_skip_last_dot(path)); U128 key = fs_key_from_path(path); U128 hash = {0}; TXT_TextInfo info = txt_text_info_from_key_lang(txt_scope, key, lang_kind, &hash); String8 data = hs_data_from_hash(hs_scope, hash); - df_code_view_cmds(ws, panel, view, cv, cmds, data, &info); + DF_CodeCtx code_ctx = {entity, key, lang_kind}; + df_code_view_cmds(ws, panel, view, cv, cmds, data, &info, &code_ctx); txt_scope_close(txt_scope); hs_scope_close(hs_scope); scratch_end(scratch); @@ -6321,7 +6398,8 @@ DF_VIEW_UI_FUNCTION_DEF(Code) // if(!entity_is_missing && key_has_data) { - df_code_view_build(ws, panel, view, cv, code_area_rect, data, &info); + DF_CodeCtx code_ctx = {entity, key, lang_kind}; + df_code_view_build(ws, panel, view, cv, code_area_rect, data, &info, &code_ctx); } ////////////////////////////// @@ -6377,9 +6455,9 @@ DF_VIEW_UI_FUNCTION_DEF(Code) } #endif -//~ TODO(rjf): OLD vvvvvvvv +//~ TODO(rjf): OLD vvvvvvvv @src_collapse -#if 1 +#if 0 DF_VIEW_SETUP_FUNCTION_DEF(Code) { // rjf: set up state @@ -6744,6 +6822,7 @@ DF_VIEW_UI_FUNCTION_DEF(Code) code_slice_params.line_bps = push_array(scratch.arena, DF_EntityList, visible_line_count); code_slice_params.line_ips = push_array(scratch.arena, DF_EntityList, visible_line_count); code_slice_params.line_pins = push_array(scratch.arena, DF_EntityList, visible_line_count); + code_slice_params.line_vaddrs = push_array(scratch.arena, U64, visible_line_count); code_slice_params.line_dasm2src = push_array(scratch.arena, DF_TextLineDasm2SrcInfoList, visible_line_count); code_slice_params.line_src2dasm = push_array(scratch.arena, DF_TextLineSrc2DasmInfoList, visible_line_count); code_slice_params.font = code_font; @@ -7761,8 +7840,9 @@ DF_VIEW_UI_FUNCTION_DEF(Disassembly) dasm_params.dbgi_key = dasm_dbgi_key; } DASM_Info dasm_info = dasm_info_from_key_params(dasm_scope, dasm_key, &dasm_params, &dasm_data_hash); + TXT_LangKind lang_kind = txt_lang_kind_from_architecture(arch); U128 dasm_text_hash = {0}; - TXT_TextInfo dasm_text_info = txt_text_info_from_key_lang(txt_scope, dasm_info.text_key, txt_lang_kind_from_architecture(arch), &dasm_text_hash); + TXT_TextInfo dasm_text_info = txt_text_info_from_key_lang(txt_scope, dasm_info.text_key, lang_kind, &dasm_text_hash); String8 dasm_text_data = hs_data_from_hash(hs_scope, dasm_text_hash); B32 has_disasm = (dasm_info.insts.count != 0 && dasm_text_info.lines_count != 0); B32 is_loading = (!has_disasm && !df_entity_is_nil(process) && dim_1u64(dasm_vaddr_range) != 0); @@ -7846,8 +7926,8 @@ DF_VIEW_UI_FUNCTION_DEF(Disassembly) code_slice_params.line_bps = push_array(scratch.arena, DF_EntityList, visible_line_count); code_slice_params.line_ips = push_array(scratch.arena, DF_EntityList, visible_line_count); code_slice_params.line_pins = push_array(scratch.arena, DF_EntityList, visible_line_count); - code_slice_params.line_dasm2src = push_array(scratch.arena, DF_TextLineDasm2SrcInfoList, visible_line_count); - code_slice_params.line_src2dasm = push_array(scratch.arena, DF_TextLineSrc2DasmInfoList, visible_line_count); + code_slice_params.line_vaddrs = push_array(scratch.arena, U64, visible_line_count); + code_slice_params.line_infos = push_array(scratch.arena, DF_LineList, visible_line_count); code_slice_params.font = code_font; code_slice_params.font_size = code_font_size; code_slice_params.tab_size = code_tab_size; @@ -7858,7 +7938,6 @@ DF_VIEW_UI_FUNCTION_DEF(Disassembly) code_slice_params.line_num_width_px = line_num_width_px; code_slice_params.line_text_max_width_px = (F32)line_size_x; code_slice_params.margin_float_off_px = view->scroll_pos.x.idx + view->scroll_pos.x.off; - di_key_list_push(scratch.arena, &code_slice_params.relevant_dbgi_keys, &dbgi_key); // rjf: fill text info @@ -7947,10 +8026,8 @@ DF_VIEW_UI_FUNCTION_DEF(Disassembly) U64 vaddr = dasm_vaddr_range.min + dasm_inst_array_code_off_from_idx(&dasm_info.insts, line_num-1); U64 voff = df_voff_from_vaddr(module, vaddr); U64 slice_idx = line_num-visible_line_num_range.min; - DF_TextLineDasm2SrcInfoNode *dasm2src_n = push_array(scratch.arena, DF_TextLineDasm2SrcInfoNode, 1); - SLLQueuePush(code_slice_params.line_dasm2src[slice_idx].first, code_slice_params.line_dasm2src[slice_idx].last, dasm2src_n); - code_slice_params.line_dasm2src[slice_idx].count += 1; - dasm2src_n->v = df_text_line_dasm2src_info_from_dbgi_key_voff(&dbgi_key, voff, 0); + code_slice_params.line_vaddrs[slice_idx] = vaddr; + code_slice_params.line_infos[slice_idx] = df_lines_from_dbgi_key_voff(scratch.arena, &dbgi_key, voff); } } } @@ -8010,7 +8087,8 @@ DF_VIEW_UI_FUNCTION_DEF(Disassembly) DF_CodeSliceSignal sig = {0}; UI_Focus(UI_FocusKind_On) { - sig = df_code_slicef(ws, &ctrl_ctx, &parse_ctx, &code_slice_params, &dv->cursor, &dv->mark, &dv->preferred_column, "dasm_slice_%p", view); + DF_CodeCtx code_ctx = {&df_g_nil_entity, dasm_info.text_key, lang_kind}; + sig = df_code_slicef(ws, &ctrl_ctx, &parse_ctx, &code_ctx, &code_slice_params, &dv->cursor, &dv->mark, &dv->preferred_column, "dasm_slice_%p", view); } //- rjf: hover eval @@ -8129,14 +8207,17 @@ DF_VIEW_UI_FUNCTION_DEF(Disassembly) DF_Entity *module = df_module_from_process_vaddr(process, vaddr); DI_Key dbgi_key = df_dbgi_key_from_module(module); U64 voff = df_voff_from_vaddr(module, vaddr); - DF_TextLineDasm2SrcInfo dasm2src = df_text_line_dasm2src_info_from_dbgi_key_voff(&dbgi_key, voff, 0); - String8 file_path = df_full_path_from_entity(scratch.arena, dasm2src.file); - DF_CmdParams params = df_cmd_params_from_view(ws, panel, view); - params.text_point = dasm2src.pt; - params.file_path = file_path; - df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_TextPoint); - df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_FilePath); - df_push_cmd__root(¶ms, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_FindCodeLocation)); + DF_LineList lines = df_lines_from_dbgi_key_voff(scratch.arena, &dbgi_key, voff); + if(lines.first != 0) + { + String8 file_path = df_full_path_from_entity(scratch.arena, df_entity_from_handle(lines.first->v.file)); + DF_CmdParams params = df_cmd_params_from_view(ws, panel, view); + params.text_point = lines.first->v.pt; + params.file_path = file_path; + df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_TextPoint); + df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_FilePath); + df_push_cmd__root(¶ms, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_FindCodeLocation)); + } } } @@ -8485,6 +8566,103 @@ DF_VIEW_UI_FUNCTION_DEF(Procedures) //////////////////////////////// //~ rjf: Output @view_hook_impl +#if 1 +DF_VIEW_SETUP_FUNCTION_DEF(Output) +{ + DF_CodeViewState *cv = df_view_user_state(view, DF_CodeViewState); + df_code_view_init(cv, view); +} + +DF_VIEW_STRING_FROM_STATE_FUNCTION_DEF(Output) +{ + return str8_zero(); +} + +DF_VIEW_CMD_FUNCTION_DEF(Output) +{ + DF_CodeViewState *cv = df_view_user_state(view, DF_CodeViewState); + Temp scratch = scratch_begin(0, 0); + HS_Scope *hs_scope = hs_scope_open(); + TXT_Scope *txt_scope = txt_scope_open(); + U128 key = df_state->output_log_key; + TXT_LangKind lang_kind = TXT_LangKind_Null; + U128 hash = {0}; + TXT_TextInfo info = txt_text_info_from_key_lang(txt_scope, key, lang_kind, &hash); + String8 data = hs_data_from_hash(hs_scope, hash); + DF_CodeCtx code_ctx = {&df_g_nil_entity, key, lang_kind}; + df_code_view_cmds(ws, panel, view, cv, cmds, data, &info, &code_ctx); + txt_scope_close(txt_scope); + hs_scope_close(hs_scope); + scratch_end(scratch); +} + +DF_VIEW_UI_FUNCTION_DEF(Output) +{ + DF_CodeViewState *cv = df_view_user_state(view, DF_CodeViewState); + Temp scratch = scratch_begin(0, 0); + HS_Scope *hs_scope = hs_scope_open(); + TXT_Scope *txt_scope = txt_scope_open(); + + ////////////////////////////// + //- rjf: set up invariants + // + F32 bottom_bar_height = ui_top_font_size()*2.f; + Rng2F32 code_area_rect = r2f32p(rect.x0, rect.y0, rect.x1, rect.y1 - bottom_bar_height); + Rng2F32 bottom_bar_rect = r2f32p(rect.x0, rect.y1 - bottom_bar_height, rect.x1, rect.y1); + + ////////////////////////////// + //- rjf: unpack text info + // + U128 key = df_state->output_log_key; + TXT_LangKind lang_kind = TXT_LangKind_Null; + U128 hash = {0}; + TXT_TextInfo info = txt_text_info_from_key_lang(txt_scope, key, lang_kind, &hash); + String8 data = hs_data_from_hash(hs_scope, hash); + Rng1U64 empty_range = {0}; + if(info.lines_count == 0) + { + info.lines_count = 1; + info.lines_ranges = &empty_range; + } + + ////////////////////////////// + //- rjf: build code contents + // + { + DF_CodeCtx code_ctx = {&df_g_nil_entity, key, lang_kind}; + df_code_view_build(ws, panel, view, cv, code_area_rect, data, &info, &code_ctx); + } + + ////////////////////////////// + //- rjf: build bottom bar + // + { + ui_set_next_rect(shift_2f32(bottom_bar_rect, scale_2f32(rect.p0, -1.f))); + ui_set_next_flags(UI_BoxFlag_DrawBackground); + UI_Row + UI_TextAlignment(UI_TextAlign_Center) + UI_PrefWidth(ui_text_dim(10, 1)) + UI_FlagsAdd(UI_BoxFlag_DrawTextWeak) + { + UI_Font(df_font_from_slot(DF_FontSlot_Code)) + { + ui_labelf("(Debug String Output)"); + ui_spacer(ui_em(1.5f, 1)); + ui_labelf("Line: %I64d, Column: %I64d", cv->cursor.line, cv->cursor.column); + ui_spacer(ui_pct(1, 0)); + ui_labelf("(read only)"); + } + } + } + + txt_scope_close(txt_scope); + hs_scope_close(hs_scope); + scratch_end(scratch); +} +#endif + +//~ TODO(rjf): OLD vvvvvvvvvvvvvvvvvvvv @src_collapse +#if 0 DF_VIEW_SETUP_FUNCTION_DEF(Output) { // rjf: set up state @@ -8692,6 +8870,7 @@ DF_VIEW_UI_FUNCTION_DEF(Output) code_slice_params.line_bps = push_array(scratch.arena, DF_EntityList, slice.line_count); code_slice_params.line_ips = push_array(scratch.arena, DF_EntityList, slice.line_count); code_slice_params.line_pins = push_array(scratch.arena, DF_EntityList, slice.line_count); + code_slice_params.line_vaddrs = push_array(scratch.arena, U64, visible_line_count); code_slice_params.line_dasm2src = push_array(scratch.arena, DF_TextLineDasm2SrcInfoList, slice.line_count); code_slice_params.line_src2dasm = push_array(scratch.arena, DF_TextLineSrc2DasmInfoList, slice.line_count); code_slice_params.font = code_font; @@ -9097,6 +9276,7 @@ DF_VIEW_UI_FUNCTION_DEF(Output) scratch_end(scratch); ProfEnd(); } +#endif //////////////////////////////// //~ rjf: Memory @view_hook_impl diff --git a/src/df/gfx/df_views.h b/src/df/gfx/df_views.h index efa2d6b9..90f030a6 100644 --- a/src/df/gfx/df_views.h +++ b/src/df/gfx/df_views.h @@ -359,7 +359,7 @@ struct DF_WatchViewState }; //////////////////////////////// -//~ rjf: Code @view_types +//~ rjf: Code, Output @view_types typedef struct DF_CodeViewState DF_CodeViewState; struct DF_CodeViewState @@ -471,8 +471,8 @@ internal void df_entity_lister_item_array_sort_by_strength__in_place(DF_EntityLi //~ rjf: Code Views internal void df_code_view_init(DF_CodeViewState *cv, DF_View *view); -internal void df_code_view_cmds(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_CodeViewState *cv, DF_CmdList *cmds, String8 data, TXT_TextInfo *info); -internal void df_code_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_CodeViewState *cv, Rng2F32 rect, String8 data, TXT_TextInfo *info); +internal void df_code_view_cmds(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_CodeViewState *cv, DF_CmdList *cmds, String8 data, TXT_TextInfo *info, DF_CodeCtx *code_ctx); +internal void df_code_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_CodeViewState *cv, Rng2F32 rect, String8 data, TXT_TextInfo *info, DF_CodeCtx *code_ctx); //////////////////////////////// //~ rjf: Watch Views diff --git a/src/font_provider/dwrite/font_provider_dwrite.c b/src/font_provider/dwrite/font_provider_dwrite.c index 79ead99b..7050323a 100644 --- a/src/font_provider/dwrite/font_provider_dwrite.c +++ b/src/font_provider/dwrite/font_provider_dwrite.c @@ -198,7 +198,7 @@ fp_init(void) gamma, enhanced_contrast, enhanced_contrast, - 1.f, + 0.f, DWRITE_PIXEL_GEOMETRY_FLAT, DWRITE_RENDERING_MODE_GDI_NATURAL, DWRITE_GRID_FIT_MODE_ENABLED, @@ -209,7 +209,7 @@ fp_init(void) error = IDWriteFactory_CreateCustomRenderingParams(fp_dwrite_state->factory, gamma, enhanced_contrast, - 1.f, + 0.f, DWRITE_PIXEL_GEOMETRY_FLAT, DWRITE_RENDERING_MODE_GDI_NATURAL, &fp_dwrite_state->rendering_params[FP_RasterMode_Sharp]); @@ -226,7 +226,7 @@ fp_init(void) gamma, enhanced_contrast, enhanced_contrast, - 1.f, + 0.f, DWRITE_PIXEL_GEOMETRY_FLAT, DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC, DWRITE_GRID_FIT_MODE_DISABLED,