diff --git a/src/dasm_cache/dasm_cache.c b/src/dasm_cache/dasm_cache.c index 1f8b8967..ef3418f1 100644 --- a/src/dasm_cache/dasm_cache.c +++ b/src/dasm_cache/dasm_cache.c @@ -69,7 +69,8 @@ dasm_inst_array_idx_from_code_off__linear_scan(DASM_InstArray *array, U64 off) U64 result = 0; for(U64 idx = 0; idx < array->count; idx += 1) { - if(array->v[idx].code_off == off) + U64 next_off = (idx+1 < array->count ? array->v[idx+1].code_off : max_U64); + if(array->v[idx].code_off <= off && off < next_off) { result = idx; break; diff --git a/src/demon/win32/demon_core_win32.c b/src/demon/win32/demon_core_win32.c index 2d39e0fe..8bfac593 100644 --- a/src/demon/win32/demon_core_win32.c +++ b/src/demon/win32/demon_core_win32.c @@ -1900,7 +1900,7 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls) // case EXCEPTION_DEBUG_EVENT: { - // NOTE(rjf): Notes on multithreaded breakpoint events + //- NOTE(rjf): Notes on multithreaded breakpoint events // (2021/11/1): // // When many threads are simultaneously running, multiple threads @@ -1928,7 +1928,17 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls) // #B. If the actual unmodified instruction is an int 3, then this // becomes a trap event and we do not reset RIP. - // NOTE(rjf): The exception record struct has a 32-bit version and a + //- NOTE(rjf): Further notes on MULTITHREADED STEPPING ACCESS VIOLATION + // EVENTS! @rjf @rjf @rjf + // (2024/05/29): + // + // Just adding another comment here to document that the above long + // comment went completely unnoticed by me during a pass over demon, + // and I had removed the proper rollback stuff here without reading + // the above comment. So this comment just serves to make that + // original comment even heftier. + + //- NOTE(rjf): The exception record struct has a 32-bit version and a // 64-bit version. We only currently handle the 64-bit version. //- rjf: unpack @@ -1981,7 +1991,7 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls) } //- rjf: determine whether to roll back instruction pointer - B32 should_do_rollback = (hit_user_trap); + B32 should_do_rollback = (hit_user_trap || (is_trap && !hit_explicit_trap)); //- rjf: roll back thread's instruction pointer U64 post_trap_rip = 0; diff --git a/src/df/core/df_core.c b/src/df/core/df_core.c index e2b2de46..c627903c 100644 --- a/src/df/core/df_core.c +++ b/src/df/core/df_core.c @@ -4473,6 +4473,7 @@ df_string_from_ascii_value(Arena *arena, U8 val) case '\'':{result = str8_lit("\\'");}break; case '\\':{result = str8_lit("\\\\");}break; default: + if(32 <= val && val < 255) { result = push_str8f(arena, "%c", val); }break; @@ -4511,14 +4512,21 @@ df_string_from_simple_typed_eval(Arena *arena, TG_Graph *graph, RDI_Parsed *rdi, case TG_Kind_UChar32: { String8 char_str = df_string_from_ascii_value(arena, eval.imm_s64); - if(flags & DF_EvalVizStringFlag_ReadOnlyDisplayRules) + if(char_str.size != 0) { - String8 imm_string = str8_from_s64(arena, eval.imm_s64, radix, 0, digit_group_separator); - result = push_str8f(arena, "'%S' (%S)", char_str, imm_string); + if(flags & DF_EvalVizStringFlag_ReadOnlyDisplayRules) + { + String8 imm_string = str8_from_s64(arena, eval.imm_s64, radix, 0, digit_group_separator); + result = push_str8f(arena, "'%S' (%S)", char_str, imm_string); + } + else + { + result = push_str8f(arena, "'%S'", char_str); + } } else { - result = push_str8f(arena, "'%S'", char_str); + result = str8_from_s64(arena, eval.imm_s64, radix, 0, digit_group_separator); } }break; @@ -6206,8 +6214,8 @@ df_query_cached_unwind_from_thread(DF_Entity *thread) { node = push_array_no_zero(df_state->arena, DF_UnwindCacheNode, 1); } - DLLPushBack(slot->first, slot->last, node); MemoryZeroStruct(node); + DLLPushBack(slot->first, slot->last, node); node->arena = arena_alloc(); node->thread = handle; } diff --git a/src/df/gfx/df_gfx.c b/src/df/gfx/df_gfx.c index c81e56e7..d0b8ae1a 100644 --- a/src/df/gfx/df_gfx.c +++ b/src/df/gfx/df_gfx.c @@ -2903,6 +2903,13 @@ df_window_update_and_render(Arena *arena, DF_Window *ws, DF_CmdList *cmds) df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_Entity); df_push_cmd__root(¶ms, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_SelectThread)); }break; + case DF_EntityKind_Target: + { + DF_CmdParams params = df_cmd_params_from_window(ws); + params.entity = df_handle_from_entity(entity); + df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_Entity); + df_push_cmd__root(¶ms, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_SelectTarget)); + }break; } }break; case DF_CoreCmdKind_SpawnEntityView: @@ -5992,7 +5999,7 @@ df_window_update_and_render(Arena *arena, DF_Window *ws, DF_CmdList *cmds) //- rjf: calculate width of exp row if(row == viz_rows.first) { - expr_column_width_px = f_dim_from_tag_size_string(ui_top_font(), ui_top_font_size(), 0, ui_top_tab_size(), row->display_expr).x + ui_top_font_size()*0.5f; + expr_column_width_px = f_dim_from_tag_size_string(ui_top_font(), ui_top_font_size(), 0, ui_top_tab_size(), row->display_expr).x + ui_top_font_size()*2.5f; expr_column_width_px = Max(expr_column_width_px, ui_top_font_size()*10.f); } @@ -10424,9 +10431,9 @@ internal UI_BOX_CUSTOM_DRAW(df_thread_box_draw_extensions) // rjf: draw line before next-to-execute line { - R_Rect2DInst *inst = d_rect(r2f32p(box->rect.x0, + R_Rect2DInst *inst = d_rect(r2f32p(box->parent->parent->parent->rect.x0, box->parent->rect.y0 - box->font_size*0.125f, - box->rect.x0 + box->font_size*260*u->alive_t, + box->parent->parent->parent->rect.x0 + box->font_size*260*u->alive_t, box->parent->rect.y0 + box->font_size*0.125f), v4f32(u->thread_color.x, u->thread_color.y, u->thread_color.z, 0), 0, 0, 1); @@ -10451,9 +10458,9 @@ internal UI_BOX_CUSTOM_DRAW(df_thread_box_draw_extensions) { Vec4F32 weak_thread_color = u->thread_color; weak_thread_color.w *= 0.3f; - R_Rect2DInst *inst = d_rect(r2f32p(box->rect.x0, + R_Rect2DInst *inst = d_rect(r2f32p(box->parent->parent->parent->rect.x0, box->parent->rect.y0, - box->rect.x0 + ui_top_font_size()*22.f*u->alive_t, + box->parent->parent->parent->rect.x0 + ui_top_font_size()*22.f*u->alive_t, box->parent->rect.y1), v4f32(0, 0, 0, 0), 0, 0, 1); @@ -10491,9 +10498,9 @@ internal UI_BOX_CUSTOM_DRAW(df_bp_box_draw_extensions) // rjf: draw line before next-to-execute line { - R_Rect2DInst *inst = d_rect(r2f32p(box->rect.x0, + R_Rect2DInst *inst = d_rect(r2f32p(box->parent->parent->parent->rect.x0, box->parent->rect.y0 - box->font_size*0.125f, - box->rect.x0 + ui_top_font_size()*250.f*u->alive_t, + box->parent->parent->parent->rect.x0 + ui_top_font_size()*250.f*u->alive_t, box->parent->rect.y0 + box->font_size*0.125f), v4f32(u->color.x, u->color.y, u->color.z, 0), 0, 0, 1.f); @@ -10504,9 +10511,9 @@ internal UI_BOX_CUSTOM_DRAW(df_bp_box_draw_extensions) { Vec4F32 weak_thread_color = u->color; weak_thread_color.w *= 0.3f; - R_Rect2DInst *inst = d_rect(r2f32p(box->rect.x0, + R_Rect2DInst *inst = d_rect(r2f32p(box->parent->parent->parent->rect.x0, box->parent->rect.y0, - box->rect.x0 + ui_top_font_size()*22.f*u->alive_t, + box->parent->parent->parent->rect.x0 + ui_top_font_size()*22.f*u->alive_t, box->parent->rect.y1), v4f32(0, 0, 0, 0), 0, 0, 1); @@ -10677,24 +10684,24 @@ df_code_slice(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_ } ////////////////////////////// - //- rjf: build margins + //- rjf: build priority margin // - UI_Box *margin_container_box = &ui_g_nil_box; - if(params->flags & DF_CodeSliceFlag_Margin) UI_Focus(UI_FocusKind_Off) UI_Parent(top_container_box) ProfScope("build margins") + UI_Box *priority_margin_container_box = &ui_g_nil_box; + if(params->flags & DF_CodeSliceFlag_PriorityMargin) UI_Focus(UI_FocusKind_Off) UI_Parent(top_container_box) ProfScope("build priority margins") { if(params->margin_float_off_px != 0) { - ui_set_next_pref_width(ui_px(params->margin_width_px, 1)); + ui_set_next_pref_width(ui_px(params->priority_margin_width_px, 1)); ui_set_next_pref_height(ui_px(params->line_height_px*(dim_1s64(params->line_num_range)+1), 1.f)); ui_build_box_from_key(0, ui_key_zero()); ui_set_next_fixed_x(params->margin_float_off_px); ui_set_next_flags(UI_BoxFlag_DrawBackground); } - ui_set_next_pref_width(ui_px(params->margin_width_px, 1)); + ui_set_next_pref_width(ui_px(params->priority_margin_width_px, 1)); ui_set_next_pref_height(ui_px(params->line_height_px*(dim_1s64(params->line_num_range)+1), 1.f)); ui_set_next_child_layout_axis(Axis2_Y); - margin_container_box = ui_build_box_from_string(UI_BoxFlag_Clickable*!!(params->flags & DF_CodeSliceFlag_Clickable), str8_lit("margin_container")); - UI_Parent(margin_container_box) UI_PrefHeight(ui_px(params->line_height_px, 1.f)) + priority_margin_container_box = ui_build_box_from_string(UI_BoxFlag_Clickable*!!(params->flags & DF_CodeSliceFlag_Clickable), str8_lit("priority_margin_container")); + UI_Parent(priority_margin_container_box) UI_PrefHeight(ui_px(params->line_height_px, 1.f)) { U64 line_idx = 0; for(S64 line_num = params->line_num_range.min; @@ -10702,8 +10709,6 @@ df_code_slice(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_ line_num += 1, line_idx += 1) { DF_EntityList line_ips = params->line_ips[line_idx]; - DF_EntityList line_bps = params->line_bps[line_idx]; - DF_EntityList line_pins = params->line_pins[line_idx]; ui_set_next_hover_cursor(OS_Cursor_HandPoint); ui_set_next_background_color(v4f32(0, 0, 0, 0)); UI_Box *line_margin_box = ui_build_box_from_stringf(UI_BoxFlag_Clickable*!!(params->flags & DF_CodeSliceFlag_Clickable)|UI_BoxFlag_DrawBackground|UI_BoxFlag_DrawActiveEffects, "line_margin_%I64x", line_num); @@ -10714,6 +10719,175 @@ df_code_slice(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_ { // rjf: unpack thread DF_Entity *thread = n->entity; + if(thread != selected_thread) + { + continue; + } + U64 unwind_count = (thread == selected_thread) ? ctrl_ctx->unwind_count : 0; + U64 thread_rip_vaddr = df_query_cached_rip_from_thread_unwind(thread, unwind_count); + DF_Entity *process = df_entity_ancestor_from_kind(thread, DF_EntityKind_Process); + DF_Entity *module = df_module_from_process_vaddr(process, thread_rip_vaddr); + DI_Key dbgi_key = df_dbgi_key_from_module(module); + U64 thread_rip_voff = df_voff_from_vaddr(module, thread_rip_vaddr); + + // rjf: thread info => color + Vec4F32 color = v4f32(1, 1, 1, 1); + { + if(unwind_count != 0) + { + color = df_rgba_from_theme_color(DF_ThemeColor_ThreadUnwound); + } + else if(thread == stopper_thread && + (stop_event.cause == CTRL_EventCause_InterruptedByHalt || + stop_event.cause == CTRL_EventCause_InterruptedByTrap || + stop_event.cause == CTRL_EventCause_InterruptedByException)) + { + color = df_rgba_from_theme_color(DF_ThemeColor_FailureBackground); + } + else if(thread->flags & DF_EntityFlag_HasColor) + { + color = df_rgba_from_entity(thread); + } + if(df_ctrl_targets_running() && df_ctrl_last_run_frame_idx() < df_frame_index()) + { + color.w *= 0.5f; + } + if(thread != selected_thread) + { + color.w *= 0.8f; + } + } + + // rjf: build thread box + ui_set_next_hover_cursor(OS_Cursor_UpDownLeftRight); + ui_set_next_font(ui_icon_font()); + ui_set_next_font_size(params->font_size); + ui_set_next_pref_width(ui_pct(1, 0)); + ui_set_next_pref_height(ui_pct(1, 0)); + ui_set_next_text_color(color); + ui_set_next_text_alignment(UI_TextAlign_Center); + UI_Key thread_box_key = ui_key_from_stringf(top_container_box->key, "###ip_%p", thread); + UI_Box *thread_box = ui_build_box_from_key(UI_BoxFlag_DisableTextTrunc| + UI_BoxFlag_Clickable*!!(params->flags & DF_CodeSliceFlag_Clickable)| + UI_BoxFlag_DrawText, + thread_box_key); + ui_box_equip_display_string(thread_box, df_g_icon_kind_text_table[DF_IconKind_RightArrow]); + UI_Signal thread_sig = ui_signal_from_box(thread_box); + + // rjf: custom draw + { + DF_ThreadBoxDrawExtData *u = push_array(ui_build_arena(), DF_ThreadBoxDrawExtData, 1); + u->thread_color = color; + u->alive_t = thread->alive_t; + u->is_selected = (thread == selected_thread); + u->is_frozen = df_entity_is_frozen(thread); + ui_box_equip_custom_draw(thread_box, df_thread_box_draw_extensions, u); + + // rjf: fill out progress t (progress into range of current line's + // voff range) + if(params->line_src2dasm[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) + { + if(di_key_match(&n->v.dbgi_key, &dbgi_key)) + { + line_info = &n->v; + break; + } + } + if(line_info != 0) + { + Rng1U64 line_voff_rng = line_info->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; + progress_t = Clamp(0, progress_t, 1); + u->progress_t = progress_t; + } + } + } + + // rjf: hover tooltips + if(ui_hovering(thread_sig)) + { + df_entity_tooltips(thread); + } + + // rjf: ip right-click menu + if(ui_right_clicked(thread_sig)) + { + DF_Handle handle = df_handle_from_entity(thread); + if(ui_ctx_menu_is_open(ws->entity_ctx_menu_key) && df_handle_match(ws->entity_ctx_menu_entity, handle)) + { + ui_ctx_menu_close(); + } + else + { + ui_ctx_menu_open(ws->entity_ctx_menu_key, thread_box->key, v2f32(0, thread_box->rect.y1-thread_box->rect.y0)); + ws->entity_ctx_menu_entity = handle; + } + } + + // rjf: drag start + if(ui_dragging(thread_sig) && !contains_2f32(thread_box->rect, ui_mouse())) + { + DF_DragDropPayload payload = {0}; + payload.key = thread_box->key; + payload.entity = df_handle_from_entity(thread); + df_drag_begin(&payload); + } + } + } + } + } + } + + ////////////////////////////// + //- rjf: build catchall margin + // + UI_Box *catchall_margin_container_box = &ui_g_nil_box; + if(params->flags & DF_CodeSliceFlag_CatchallMargin) UI_Focus(UI_FocusKind_Off) UI_Parent(top_container_box) ProfScope("build catchall margins") + { + if(params->margin_float_off_px != 0) + { + ui_set_next_pref_width(ui_px(params->catchall_margin_width_px, 1)); + ui_set_next_pref_height(ui_px(params->line_height_px*(dim_1s64(params->line_num_range)+1), 1.f)); + ui_build_box_from_key(0, ui_key_zero()); + ui_set_next_fixed_x(params->margin_float_off_px + params->priority_margin_width_px); + ui_set_next_flags(UI_BoxFlag_DrawBackground); + } + ui_set_next_pref_width(ui_px(params->catchall_margin_width_px, 1)); + ui_set_next_pref_height(ui_px(params->line_height_px*(dim_1s64(params->line_num_range)+1), 1.f)); + ui_set_next_child_layout_axis(Axis2_Y); + catchall_margin_container_box = ui_build_box_from_string(UI_BoxFlag_DrawSideLeft|UI_BoxFlag_Clickable*!!(params->flags & DF_CodeSliceFlag_Clickable), str8_lit("catchall_margin_container")); + UI_Parent(catchall_margin_container_box) UI_PrefHeight(ui_px(params->line_height_px, 1.f)) + { + 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) + { + DF_EntityList line_ips = params->line_ips[line_idx]; + DF_EntityList line_bps = params->line_bps[line_idx]; + DF_EntityList line_pins = params->line_pins[line_idx]; + ui_set_next_hover_cursor(OS_Cursor_HandPoint); + ui_set_next_background_color(v4f32(0, 0, 0, 0)); + UI_Box *line_margin_box = ui_build_box_from_stringf(UI_BoxFlag_Clickable*!!(params->flags & DF_CodeSliceFlag_Clickable)|UI_BoxFlag_DrawBackground|UI_BoxFlag_DrawActiveEffects, "line_margin_%I64x", line_num); + UI_Parent(line_margin_box) + { + //- rjf: build margin thread ip ui + for(DF_EntityNode *n = line_ips.first; n != 0; n = n->next) + { + // rjf: unpack thread + DF_Entity *thread = n->entity; + if(thread == selected_thread) + { + continue; + } U64 unwind_count = (thread == selected_thread) ? ctrl_ctx->unwind_count : 0; U64 thread_rip_vaddr = df_query_cached_rip_from_thread_unwind(thread, unwind_count); DF_Entity *process = df_entity_ancestor_from_kind(thread, DF_EntityKind_Process); @@ -10760,7 +10934,6 @@ df_code_slice(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_ UI_Key thread_box_key = ui_key_from_stringf(top_container_box->key, "###ip_%p", thread); UI_Box *thread_box = ui_build_box_from_key(UI_BoxFlag_DisableTextTrunc| UI_BoxFlag_Clickable*!!(params->flags & DF_CodeSliceFlag_Clickable)| - UI_BoxFlag_AnimatePosX| UI_BoxFlag_DrawText, thread_box_key); ui_box_equip_display_string(thread_box, df_g_icon_kind_text_table[DF_IconKind_RightArrow]); @@ -10831,6 +11004,7 @@ df_code_slice(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_ params.entity = df_handle_from_entity(thread); df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_Entity); df_push_cmd__root(¶ms, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_SelectThread)); + ui_kill_action(); } // rjf: drag start @@ -10884,7 +11058,6 @@ df_code_slice(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_ UI_BoxFlag_DrawActiveEffects| UI_BoxFlag_DrawHotEffects| UI_BoxFlag_DrawBorder| - UI_BoxFlag_AnimatePosX| UI_BoxFlag_Clickable*!!(params->flags & DF_CodeSliceFlag_Clickable)| UI_BoxFlag_DisableTextTrunc, "%S##bp_%p", @@ -10953,7 +11126,6 @@ df_code_slice(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_ UI_BoxFlag_DrawHotEffects| UI_BoxFlag_DrawBorder| UI_BoxFlag_Clickable*!!(params->flags & DF_CodeSliceFlag_Clickable)| - UI_BoxFlag_AnimatePosX| UI_BoxFlag_DisableTextTrunc, "%S##watch_%p", df_g_icon_kind_text_table[DF_IconKind_Pin], @@ -11236,7 +11408,8 @@ df_code_slice(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_ ////////////////////////////// //- rjf: interact with margin box & text box // - UI_Signal margin_container_sig = ui_signal_from_box(margin_container_box); + UI_Signal priority_margin_container_sig = ui_signal_from_box(priority_margin_container_box); + UI_Signal catchall_margin_container_sig = ui_signal_from_box(catchall_margin_container_box); UI_Signal text_container_sig = ui_signal_from_box(text_container_box); DF_Entity *line_drag_entity = &df_g_nil_entity; { diff --git a/src/df/gfx/df_gfx.h b/src/df/gfx/df_gfx.h index 3c317042..3a724f90 100644 --- a/src/df/gfx/df_gfx.h +++ b/src/df/gfx/df_gfx.h @@ -388,9 +388,10 @@ enum typedef U32 DF_CodeSliceFlags; enum { - DF_CodeSliceFlag_Clickable = (1<<0), - DF_CodeSliceFlag_Margin = (1<<1), - DF_CodeSliceFlag_LineNums = (1<<2), + DF_CodeSliceFlag_Clickable = (1<<0), + DF_CodeSliceFlag_PriorityMargin = (1<<1), + DF_CodeSliceFlag_CatchallMargin = (1<<2), + DF_CodeSliceFlag_LineNums = (1<<3), }; typedef struct DF_CodeSliceParams DF_CodeSliceParams; @@ -415,7 +416,8 @@ struct DF_CodeSliceParams F32 tab_size; String8 search_query; F32 line_height_px; - F32 margin_width_px; + F32 priority_margin_width_px; + F32 catchall_margin_width_px; F32 line_num_width_px; F32 line_text_max_width_px; DF_EntityList flash_ranges; diff --git a/src/df/gfx/df_view_rules.c b/src/df/gfx/df_view_rules.c index d96de95d..13472ff5 100644 --- a/src/df/gfx/df_view_rules.c +++ b/src/df/gfx/df_view_rules.c @@ -570,7 +570,8 @@ DF_GFX_VIEW_RULE_BLOCK_UI_FUNCTION_DEF(text) code_slice_params.font_size = ui_top_font_size(); code_slice_params.tab_size = f_column_size_from_tag_size(code_slice_params.font, code_slice_params.font_size)*4.f; code_slice_params.line_height_px = ui_top_font_size()*1.5f; - code_slice_params.margin_width_px = 0; + code_slice_params.priority_margin_width_px = 0; + code_slice_params.catchall_margin_width_px = 0; code_slice_params.line_num_width_px = ui_top_font_size()*5.f; code_slice_params.line_text_max_width_px = ui_top_font_size()*2.f*info.lines_max_size; } @@ -731,7 +732,8 @@ DF_GFX_VIEW_RULE_BLOCK_UI_FUNCTION_DEF(disasm) code_slice_params.font_size = ui_top_font_size(); code_slice_params.tab_size = f_column_size_from_tag_size(code_slice_params.font, code_slice_params.font_size)*4.f; code_slice_params.line_height_px = ui_top_font_size()*1.5f; - code_slice_params.margin_width_px = 0; + code_slice_params.priority_margin_width_px = 0; + code_slice_params.catchall_margin_width_px = 0; code_slice_params.line_num_width_px = ui_top_font_size()*5.f; code_slice_params.line_text_max_width_px = ui_top_font_size()*2.f*dasm_text_info.lines_max_size; } diff --git a/src/df/gfx/df_views.c b/src/df/gfx/df_views.c index 99b1679b..93a85a2e 100644 --- a/src/df/gfx/df_views.c +++ b/src/df/gfx/df_views.c @@ -3867,13 +3867,7 @@ DF_VIEW_UI_FUNCTION_DEF(Targets) UI_FocusHot((row_selected && cursor.x == 0) ? UI_FocusKind_On : UI_FocusKind_Off) { UI_Signal sig = df_icon_buttonf(target->b32 ? DF_IconKind_CheckFilled : DF_IconKind_CheckHollow, 0, "###ebl_%p", target); - if(ui_clicked(sig) && sig.event_flags == 0) - { - DF_CmdParams p = df_cmd_params_from_view(ws, panel, view); - p.entity = df_handle_from_entity(target); - df_push_cmd__root(&p, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_SelectTarget)); - } - else if(ui_clicked(sig) && sig.event_flags == OS_EventFlag_Ctrl) + if(ui_clicked(sig)) { DF_CmdParams p = df_cmd_params_from_view(ws, panel, view); p.entity = df_handle_from_entity(target); @@ -4835,6 +4829,7 @@ DF_VIEW_UI_FUNCTION_DEF(CallStack) { ProfBeginFunction(); Temp scratch = scratch_begin(0, 0); + DI_Scope *scope = di_scope_open(); DF_CtrlCtx ctrl_ctx = df_ctrl_ctx_from_view(ws, view); DF_Entity *thread = df_entity_from_handle(ctrl_ctx.thread); U64 selected_unwind_count = ctrl_ctx.unwind_count; @@ -4915,20 +4910,33 @@ DF_VIEW_UI_FUNCTION_DEF(CallStack) { continue; } - U64 frame_idx = row_num-1; - CTRL_UnwindFrame *frame = &unwind.frames.v[frame_idx]; - - // rjf: determine selection B32 row_selected = (cs->cursor.y == row_num); - // rjf: regs => rip + // rjf: unpack frame + U64 frame_idx = row_num-1; + CTRL_UnwindFrame *frame = &unwind.frames.v[frame_idx]; U64 rip_vaddr = regs_rip_from_arch_block(thread->arch, frame->regs); - - // rjf: rip_vaddr => module DF_Entity *module = df_module_from_process_vaddr(process, rip_vaddr); - - // rjf: rip => validity? B32 frame_valid = (rip_vaddr != 0); + U64 rip_voff = df_voff_from_vaddr(module, rip_vaddr); + DI_Key dbgi_key = df_dbgi_key_from_module(module); + RDI_Parsed *rdi = di_rdi_from_key(scope, &dbgi_key, 0); + String8 symbol_name = {0}; + String8 symbol_type_string = {0}; + if(rdi->scope_vmap != 0) + { + U64 scope_idx = rdi_vmap_idx_from_voff(rdi->scope_vmap, rdi->scope_vmap_count, rip_voff); + RDI_Scope *scope = rdi_element_from_idx(rdi, scopes, scope_idx); + U64 proc_idx = scope->proc_idx; + RDI_Procedure *procedure = &rdi->procedures[proc_idx]; + RDI_TypeNode *type_node = rdi_element_from_idx(rdi, type_nodes, procedure->type_idx); + TG_Key type_key = tg_key_ext(tg_kind_from_rdi_type_kind(type_node->kind), procedure->type_idx); + U64 name_size = 0; + U8 *name_ptr = rdi_string_from_idx(rdi, procedure->name_string_idx, &name_size); + TG_Graph *graph = tg_graph_begin(rdi_addr_size_from_arch(rdi->top_level_info->architecture), 256); + symbol_name = str8(name_ptr, name_size); + symbol_type_string = tg_string_from_key(scratch.arena, graph, rdi, type_key); + } // rjf: build row if(frame_valid) UI_NamedTableVectorF("###callstack_%p_%I64x", view, frame_idx) @@ -4981,21 +4989,32 @@ DF_VIEW_UI_FUNCTION_DEF(CallStack) } } - // rjf: build cell for function name + // rjf: build cell for function header UI_TableCell UI_Font(df_font_from_slot(DF_FontSlot_Code)) UI_FocusHot((row_selected && cs->cursor.x == 2) ? UI_FocusKind_On : UI_FocusKind_Off) { - String8 symbol = df_symbol_name_from_process_vaddr(scratch.arena, process, rip_vaddr); - if(symbol.size == 0) + ui_set_next_child_layout_axis(Axis2_X); + UI_Box *box = ui_build_box_from_stringf(UI_BoxFlag_Clickable|UI_BoxFlag_Clip, "frame_%I64x", frame_idx); + UI_Parent(box) { - symbol = str8_lit("[external code]"); - ui_set_next_text_color(df_rgba_from_theme_color(DF_ThemeColor_WeakText)); + if(symbol_name.size == 0) + { + ui_set_next_text_color(df_rgba_from_theme_color(DF_ThemeColor_WeakText)); + ui_label(str8_lit("[unknown symbol]")); + } + else UI_WidthFill + { + D_FancyStringList symbol_name_fstrs = df_fancy_string_list_from_code_string(scratch.arena, 1.f, 0, df_rgba_from_theme_color(DF_ThemeColor_CodeFunction), symbol_name); + D_FancyStringList symbol_type_fstrs = df_fancy_string_list_from_code_string(scratch.arena, 0.5f, 0, df_rgba_from_theme_color(DF_ThemeColor_CodeDefault), symbol_type_string); + D_FancyStringList fstrs = {0}; + d_fancy_string_list_concat_in_place(&fstrs, &symbol_name_fstrs); + D_FancyString sep = {ui_top_font(), str8_lit(": "), df_rgba_from_theme_color(DF_ThemeColor_WeakText), ui_top_font_size()}; + d_fancy_string_list_push(scratch.arena, &fstrs, &sep); + d_fancy_string_list_concat_in_place(&fstrs, &symbol_type_fstrs); + UI_Box *label = ui_build_box_from_key(UI_BoxFlag_DrawText, ui_key_zero()); + ui_box_equip_display_fancy_strings(label, 0, &fstrs); + } } - else - { - ui_set_next_text_color(df_rgba_from_theme_color(DF_ThemeColor_CodeFunction)); - } - UI_Box *box = ui_build_box_from_string(UI_BoxFlag_DrawText|UI_BoxFlag_Clickable, symbol); UI_Signal sig = ui_signal_from_box(box); if(ui_pressed(sig)) { @@ -5046,6 +5065,7 @@ DF_VIEW_UI_FUNCTION_DEF(CallStack) } } + di_scope_close(scope); scratch_end(scratch); ProfEnd(); } @@ -5819,7 +5839,8 @@ DF_VIEW_UI_FUNCTION_DEF(Code) ////////////////////////////// //- rjf: calculate line-range-dependent info // - F32 margin_width_px = big_glyph_advance*3.5f; + F32 priority_margin_width_px = big_glyph_advance*3.5f; + F32 catchall_margin_width_px = big_glyph_advance*3.5f; F32 line_num_width_px = big_glyph_advance * (log10(visible_line_num_range.max) + 3); TXT_LineTokensSlice slice = txt_line_tokens_slice_from_info_data_line_range(scratch.arena, &text_info, data, visible_line_num_range); @@ -5847,7 +5868,7 @@ DF_VIEW_UI_FUNCTION_DEF(Code) if(text_info_is_ready) { // rjf: fill basics - code_slice_params.flags = DF_CodeSliceFlag_Margin|DF_CodeSliceFlag_LineNums|DF_CodeSliceFlag_Clickable; + code_slice_params.flags = DF_CodeSliceFlag_PriorityMargin|DF_CodeSliceFlag_CatchallMargin|DF_CodeSliceFlag_LineNums|DF_CodeSliceFlag_Clickable; code_slice_params.line_num_range = visible_line_num_range; code_slice_params.line_text = push_array(scratch.arena, String8, visible_line_count); code_slice_params.line_ranges = push_array(scratch.arena, Rng1U64, visible_line_count); @@ -5862,7 +5883,8 @@ DF_VIEW_UI_FUNCTION_DEF(Code) code_slice_params.tab_size = code_tab_size; code_slice_params.line_height_px = code_line_height; code_slice_params.search_query = search_query; - code_slice_params.margin_width_px = margin_width_px; + code_slice_params.priority_margin_width_px = priority_margin_width_px; + code_slice_params.catchall_margin_width_px = catchall_margin_width_px; 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.flash_ranges = df_push_entity_child_list_with_kind(scratch.arena, entity, DF_EntityKind_FlashMarker); @@ -6382,7 +6404,7 @@ DF_VIEW_UI_FUNCTION_DEF(Code) if(snap[Axis2_X]) { String8 cursor_line = str8_substr(data, text_info.lines_ranges[tv->cursor.line-1]); - S64 cursor_off = (S64)(f_dim_from_tag_size_string(code_font, code_font_size, 0, code_tab_size, str8_prefix(cursor_line, tv->cursor.column-1)).x + margin_width_px + line_num_width_px); + S64 cursor_off = (S64)(f_dim_from_tag_size_string(code_font, code_font_size, 0, code_tab_size, str8_prefix(cursor_line, tv->cursor.column-1)).x + priority_margin_width_px + catchall_margin_width_px + line_num_width_px); Rng1S64 visible_pixel_range = { view->scroll_pos.x.idx, @@ -6390,7 +6412,7 @@ DF_VIEW_UI_FUNCTION_DEF(Code) }; Rng1S64 cursor_pixel_range = { - cursor_off - (S64)(big_glyph_advance*4) - (S64)(margin_width_px + line_num_width_px), + cursor_off - (S64)(big_glyph_advance*4) - (S64)(priority_margin_width_px + catchall_margin_width_px + line_num_width_px), cursor_off + (S64)(big_glyph_advance*4), }; S64 min_delta = Min(0, cursor_pixel_range.min - visible_pixel_range.min); @@ -6895,7 +6917,8 @@ DF_VIEW_UI_FUNCTION_DEF(Disassembly) ////////////////////////////// //- rjf: calculate line-range-dependent info // - F32 margin_width_px = big_glyph_advance*3.5f; + F32 priority_margin_width_px = big_glyph_advance*3.5f; + F32 catchall_margin_width_px = big_glyph_advance*3.5f; F32 line_num_width_px = big_glyph_advance * (log10(visible_line_num_range.max) + 3); TXT_LineTokensSlice slice = txt_line_tokens_slice_from_info_data_line_range(scratch.arena, &dasm_text_info, dasm_text_data, visible_line_num_range); @@ -6936,7 +6959,7 @@ DF_VIEW_UI_FUNCTION_DEF(Disassembly) if(has_disasm) { // rjf: fill basics - code_slice_params.flags = DF_CodeSliceFlag_Margin|DF_CodeSliceFlag_LineNums|DF_CodeSliceFlag_Clickable; + code_slice_params.flags = DF_CodeSliceFlag_PriorityMargin|DF_CodeSliceFlag_CatchallMargin|DF_CodeSliceFlag_LineNums|DF_CodeSliceFlag_Clickable; code_slice_params.line_num_range = visible_line_num_range; code_slice_params.line_text = push_array(scratch.arena, String8, visible_line_count); code_slice_params.line_ranges = push_array(scratch.arena, Rng1U64, visible_line_count); @@ -6951,7 +6974,8 @@ DF_VIEW_UI_FUNCTION_DEF(Disassembly) code_slice_params.tab_size = code_tab_size; code_slice_params.line_height_px = code_line_height; code_slice_params.search_query = search_query; - code_slice_params.margin_width_px = margin_width_px; + code_slice_params.priority_margin_width_px = priority_margin_width_px; + code_slice_params.catchall_margin_width_px = catchall_margin_width_px; 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.flash_ranges = df_push_entity_child_list_with_kind(scratch.arena, process, DF_EntityKind_FlashMarker); @@ -7750,7 +7774,8 @@ DF_VIEW_UI_FUNCTION_DEF(Output) ////////////////////////////// //- rjf: calculate line-range-dependent info // - F32 margin_width_px = big_glyph_advance*3.5f; + F32 priority_margin_width_px = big_glyph_advance*3.5f; + F32 catchall_margin_width_px = big_glyph_advance*3.5f; F32 line_num_width_px = big_glyph_advance * (log10(visible_line_num_range.max) + 3); TXTI_Slice slice = txti_slice_from_handle_line_range(scratch.arena, txti_handle, visible_line_num_range); @@ -7793,7 +7818,8 @@ DF_VIEW_UI_FUNCTION_DEF(Output) code_slice_params.tab_size = code_tab_size; code_slice_params.line_height_px = code_line_height; code_slice_params.search_query = search_query; - code_slice_params.margin_width_px = margin_width_px; + code_slice_params.priority_margin_width_px = priority_margin_width_px; + code_slice_params.catchall_margin_width_px = catchall_margin_width_px; 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.flash_ranges = df_push_entity_child_list_with_kind(scratch.arena, entity, DF_EntityKind_FlashMarker); @@ -8079,7 +8105,7 @@ DF_VIEW_UI_FUNCTION_DEF(Output) if(snap[Axis2_X]) { String8 cursor_line = txti_string_from_handle_line_num(scratch.arena, txti_handle, tv->cursor.line); - S64 cursor_off = (S64)(f_dim_from_tag_size_string(code_font, code_font_size, 0, code_tab_size, str8_prefix(cursor_line, tv->cursor.column-1)).x + margin_width_px + line_num_width_px); + S64 cursor_off = (S64)(f_dim_from_tag_size_string(code_font, code_font_size, 0, code_tab_size, str8_prefix(cursor_line, tv->cursor.column-1)).x + priority_margin_width_px + catchall_margin_width_px + line_num_width_px); Rng1S64 visible_pixel_range = { view->scroll_pos.x.idx, @@ -8087,7 +8113,7 @@ DF_VIEW_UI_FUNCTION_DEF(Output) }; Rng1S64 cursor_pixel_range = { - cursor_off - (S64)(big_glyph_advance*4) - (S64)(margin_width_px + line_num_width_px), + cursor_off - (S64)(big_glyph_advance*4) - (S64)(priority_margin_width_px + catchall_margin_width_px + line_num_width_px), cursor_off + (S64)(big_glyph_advance*4), }; S64 min_delta = Min(0, cursor_pixel_range.min - visible_pixel_range.min); diff --git a/src/draw/draw.c b/src/draw/draw.c index b8a2c94b..16f47342 100644 --- a/src/draw/draw.c +++ b/src/draw/draw.c @@ -54,6 +54,23 @@ d_fancy_string_list_push(Arena *arena, D_FancyStringList *list, D_FancyString *s list->total_size += str->string.size; } +internal void +d_fancy_string_list_concat_in_place(D_FancyStringList *dst, D_FancyStringList *to_push) +{ + if(dst->last != 0 && to_push->first != 0) + { + dst->last->next = to_push->first; + dst->last = to_push->last; + dst->node_count += to_push->node_count; + dst->total_size += to_push->total_size; + } + else if(to_push->first != 0) + { + MemoryCopyStruct(dst, to_push); + } + MemoryZeroStruct(to_push); +} + internal String8 d_string_from_fancy_string_list(Arena *arena, D_FancyStringList *list) { diff --git a/src/draw/draw.h b/src/draw/draw.h index 2764605d..b3de754a 100644 --- a/src/draw/draw.h +++ b/src/draw/draw.h @@ -109,6 +109,7 @@ internal U64 d_hash_from_string(String8 string); //~ rjf: Fancy String Type Functions internal void d_fancy_string_list_push(Arena *arena, D_FancyStringList *list, D_FancyString *str); +internal void d_fancy_string_list_concat_in_place(D_FancyStringList *dst, D_FancyStringList *to_push); internal String8 d_string_from_fancy_string_list(Arena *arena, D_FancyStringList *list); internal D_FancyRunList d_fancy_run_list_from_fancy_string_list(Arena *arena, F32 tab_size_px, D_FancyStringList *strs); internal D_FancyRunList d_fancy_run_list_copy(Arena *arena, D_FancyRunList *src); diff --git a/src/type_graph/type_graph.h b/src/type_graph/type_graph.h index a413dc24..7299a1c9 100644 --- a/src/type_graph/type_graph.h +++ b/src/type_graph/type_graph.h @@ -180,7 +180,7 @@ global read_only TG_Type tg_type_nil = { /* kind */ TG_Kind_Null, /* flags */ 0, - /* name */ {(U8*)"",5}, + /* name */ {(U8*)"???",3}, }; global read_only TG_Type tg_type_variadic = diff --git a/src/ui/ui_core.c b/src/ui/ui_core.c index a0e32ef0..adc59066 100644 --- a/src/ui/ui_core.c +++ b/src/ui/ui_core.c @@ -1155,7 +1155,13 @@ ui_end_build(void) //- rjf: ensure special floating roots are within screen bounds UI_Box *floating_roots[] = {ui_state->tooltip_root, ui_state->ctx_menu_root}; - B32 force_contain[] = {0, 1}; + B32 force_contain[] = + { + (ui_key_match(ui_active_key(UI_MouseButtonKind_Left), ui_key_zero()) && + ui_key_match(ui_active_key(UI_MouseButtonKind_Right), ui_key_zero()) && + ui_key_match(ui_active_key(UI_MouseButtonKind_Middle), ui_key_zero())), + 1, + }; for(U64 idx = 0; idx < ArrayCount(floating_roots); idx += 1) { UI_Box *root = floating_roots[idx]; @@ -1164,11 +1170,10 @@ ui_end_build(void) Rng2F32 window_rect = os_client_rect_from_window(ui_window()); Vec2F32 window_dim = dim_2f32(window_rect); Rng2F32 root_rect = root->rect; - Vec2F32 root_rect_dim = dim_2f32(root_rect); Vec2F32 shift = { - -ClampBot(0, root_rect.x1 - window_rect.x1) * (root_rect_dim.x < root->font_size*15.f || force_contain[idx]), - -ClampBot(0, root_rect.y1 - window_rect.y1) * (root_rect_dim.y < root->font_size*15.f || force_contain[idx]), + -ClampBot(0, root_rect.x1 - window_rect.x1) * (force_contain[idx]), + -ClampBot(0, root_rect.y1 - window_rect.y1) * (force_contain[idx]), }; Rng2F32 new_root_rect = shift_2f32(root_rect, shift); root->fixed_position = new_root_rect.p0; @@ -1420,14 +1425,22 @@ ui_end_build(void) { if(b->flags & UI_BoxFlag_DrawText && !(b->flags & UI_BoxFlag_DisableTextTrunc)) { + Rng2F32 rect = b->rect; + for(UI_Box *p = b->parent; !ui_box_is_nil(p); p = p->parent) + { + if(p->flags & UI_BoxFlag_Clip) + { + rect = intersect_2f32(rect, p->rect); + } + } String8 box_display_string = ui_box_display_string(b); Vec2F32 text_pos = ui_box_text_position(b); Vec2F32 drawn_text_dim = b->display_string_runs.dim; - B32 text_is_truncated = (drawn_text_dim.x + text_pos.x > b->rect.x1); + B32 text_is_truncated = (drawn_text_dim.x + text_pos.x > rect.x1); B32 mouse_is_hovering = contains_2f32(r2f32p(text_pos.x, - b->rect.y0, - Min(text_pos.x+drawn_text_dim.x, b->rect.x1), - b->rect.y1), + rect.y0, + Min(text_pos.x+drawn_text_dim.x, rect.x1), + rect.y1), ui_state->mouse); if(text_is_truncated && mouse_is_hovering) { @@ -1443,6 +1456,10 @@ ui_end_build(void) goto break_all_hover_string; } } + if(b != box && ui_key_match(b->key, ui_hot_key())) + { + goto break_all_hover_string; + } if(b != box && contains_2f32(b->rect, ui_state->mouse) && b->flags & UI_BoxFlag_DrawText) { goto break_all_hover_string;