From 3b583cbac752435ec9385201f27438c96b6f8f7b Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 2 Nov 2022 00:05:51 +0000 Subject: [PATCH] Add debug symbols for global constants of integers, bools, enums, runes, & pointers. Variables are namespaced with `pkg::name` or `name` if built-in or the initial package for convenience. --- src/exact_value.cpp | 7 +++ src/llvm_backend.cpp | 27 +++++++++ src/llvm_backend_debug.cpp | 113 +++++++++++++++++++++++++++++++++++++ 3 files changed, 147 insertions(+) diff --git a/src/exact_value.cpp b/src/exact_value.cpp index 1572b564f..659db33b7 100644 --- a/src/exact_value.cpp +++ b/src/exact_value.cpp @@ -499,6 +499,13 @@ i64 exact_value_to_i64(ExactValue v) { } return 0; } +u64 exact_value_to_u64(ExactValue v) { + v = exact_value_to_integer(v); + if (v.kind == ExactValue_Integer) { + return big_int_to_u64(&v.value_integer); + } + return 0; +} f64 exact_value_to_f64(ExactValue v) { v = exact_value_to_float(v); if (v.kind == ExactValue_Float) { diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index b6e9cc423..1d2c00700 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -1736,6 +1736,13 @@ void lb_generate_code(lbGenerator *gen) { lbProcedure *startup_runtime = lb_create_startup_runtime(default_module, startup_type_info, objc_names, global_variables); gb_unused(startup_runtime); + if (build_context.ODIN_DEBUG) { + for_array(i, builtin_pkg->scope->elements.entries) { + Entity *e = builtin_pkg->scope->elements.entries[i].value; + add_debug_info_for_global_constant_from_entity(gen, e); + } + } + TIME_SECTION("LLVM Global Procedures and Types"); for_array(i, info->entities) { Entity *e = info->entities[i]; @@ -1759,6 +1766,11 @@ void lb_generate_code(lbGenerator *gen) { case Entity_TypeName: case Entity_Procedure: break; + case Entity_Constant: + if (build_context.ODIN_DEBUG) { + add_debug_info_for_global_constant_from_entity(gen, e); + } + break; } bool polymorphic_struct = false; @@ -1820,6 +1832,21 @@ void lb_generate_code(lbGenerator *gen) { lb_finalize_objc_names(objc_names); if (build_context.ODIN_DEBUG) { + TIME_SECTION("LLVM Debug Info for global constant value declarations"); + { + // lbModule *m = default_module; + + + } + // if (gen->modules.entries.count == 1) { + // } else { + // for_array(j, gen->modules.entries) { + // lbModule *m = gen->modules.entries[j].value; + // if (m->debug_builder != nullptr) { + // } + // } + // } + TIME_SECTION("LLVM Debug Info Complete Types and Finalize"); for_array(j, gen->modules.entries) { lbModule *m = gen->modules.entries[j].value; diff --git a/src/llvm_backend_debug.cpp b/src/llvm_backend_debug.cpp index 29b0ab488..8a98b7f39 100644 --- a/src/llvm_backend_debug.cpp +++ b/src/llvm_backend_debug.cpp @@ -1080,3 +1080,116 @@ void lb_add_debug_context_variable(lbProcedure *p, lbAddr const &ctx) { lb_add_debug_local_variable(p, ptr, t_context, token); } + + +String debug_info_mangle_constant_name(Entity *e, bool *did_allocate_) { + String name = e->token.string; + if (e->pkg && e->pkg->name.len > 0) { + // NOTE(bill): C++ NONSENSE FOR DEBUG SHITE! + name = concatenate3_strings(heap_allocator(), e->pkg->name, str_lit("::"), name); + if (did_allocate_) *did_allocate_ = true; + } + return name; +} + +void add_debug_info_global_variable_expr(lbModule *m, String const &name, LLVMMetadataRef dtype, LLVMMetadataRef expr) { + LLVMMetadataRef scope = nullptr; + LLVMMetadataRef file = nullptr; + unsigned line = 0; + + LLVMMetadataRef decl = nullptr; + + LLVMDIBuilderCreateGlobalVariableExpression( + m->debug_builder, scope, + cast(char const *)name.text, cast(size_t)name.len, + "", 0, // Linkage + file, line, dtype, + false, // local to unit + expr, decl, 8/*AlignInBits*/); +} + +void add_debug_info_for_global_constant_internal_i64(lbModule *m, Entity *e, LLVMMetadataRef dtype, i64 v) { + LLVMMetadataRef expr = LLVMDIBuilderCreateConstantValueExpression(m->debug_builder, v); + + bool did_allocate = false; + String name = debug_info_mangle_constant_name(e, &did_allocate); + defer (if (did_allocate) { + gb_free(heap_allocator(), name.text); + }); + + add_debug_info_global_variable_expr(m, name, dtype, expr); + if ((e->pkg && e->pkg->kind == Package_Init) || + (e->scope && (e->scope->flags & ScopeFlag_Global))) { + add_debug_info_global_variable_expr(m, e->token.string, dtype, expr); + } +} + +void add_debug_info_for_global_constant_from_entity(lbGenerator *gen, Entity *e) { + if (e == nullptr || e->kind != Entity_Constant) { + return; + } + if (is_blank_ident(e->token)) { + return; + } + lbModule *m = &gen->default_module; + if (USE_SEPARATE_MODULES) { + m = lb_pkg_module(gen, e->pkg); + } + + if (is_type_integer(e->type)) { + ExactValue const &value = e->Constant.value; + if (value.kind == ExactValue_Integer) { + LLVMMetadataRef dtype = nullptr; + i64 v = 0; + bool is_signed = false; + if (big_int_is_neg(&value.value_integer)) { + v = exact_value_to_i64(value); + is_signed = true; + } else { + v = cast(i64)exact_value_to_u64(value); + } + if (is_type_untyped(e->type)) { + dtype = lb_debug_type(m, is_signed ? t_i64 : t_u64); + } else { + dtype = lb_debug_type(m, e->type); + } + + add_debug_info_for_global_constant_internal_i64(m, e, dtype, v); + } + } else if (is_type_rune(e->type)) { + ExactValue const &value = e->Constant.value; + if (value.kind == ExactValue_Integer) { + LLVMMetadataRef dtype = lb_debug_type(m, t_rune); + i64 v = exact_value_to_i64(value); + add_debug_info_for_global_constant_internal_i64(m, e, dtype, v); + } + } else if (is_type_boolean(e->type)) { + ExactValue const &value = e->Constant.value; + if (value.kind == ExactValue_Bool) { + LLVMMetadataRef dtype = lb_debug_type(m, default_type(e->type)); + i64 v = cast(i64)value.value_bool; + + add_debug_info_for_global_constant_internal_i64(m, e, dtype, v); + } + } else if (is_type_enum(e->type)) { + ExactValue const &value = e->Constant.value; + if (value.kind == ExactValue_Integer) { + LLVMMetadataRef dtype = lb_debug_type(m, default_type(e->type)); + i64 v = 0; + if (big_int_is_neg(&value.value_integer)) { + v = exact_value_to_i64(value); + } else { + v = cast(i64)exact_value_to_u64(value); + } + + add_debug_info_for_global_constant_internal_i64(m, e, dtype, v); + } + } else if (is_type_pointer(e->type)) { + ExactValue const &value = e->Constant.value; + if (value.kind == ExactValue_Integer) { + LLVMMetadataRef dtype = lb_debug_type(m, default_type(e->type)); + i64 v = cast(i64)exact_value_to_u64(value); + add_debug_info_for_global_constant_internal_i64(m, e, dtype, v); + } + } +} \ No newline at end of file