From eaaf17aeb61982a6670ea28e5a6e128983d53581 Mon Sep 17 00:00:00 2001 From: Misomosi Date: Wed, 16 Oct 2024 00:34:20 -0400 Subject: [PATCH 1/8] Emit label debug info w/o location --- src/llvm_backend_debug.cpp | 66 ++++++++++++++++++++++++++++++++++++++ src/llvm_backend_stmt.cpp | 10 +++++- 2 files changed, 75 insertions(+), 1 deletion(-) diff --git a/src/llvm_backend_debug.cpp b/src/llvm_backend_debug.cpp index 5cc79dcc88b..0caf42349e5 100644 --- a/src/llvm_backend_debug.cpp +++ b/src/llvm_backend_debug.cpp @@ -1301,3 +1301,69 @@ gb_internal void add_debug_info_for_global_constant_from_entity(lbGenerator *gen } } } + +// TODO(tf2spi) ... *sigh* I hate LLVM so much. +// LLVM-C doesn't have an API to emit DILabel yet, so this is not exported in the dll. +// For Linux, we can temporarily use the C++ APIs, but we're out of luck for Windows +// until the DLL gets updated with a definition like LLVMDIBuilderCreateLabel. +// These might be the 50 most disgusting lines in this entire compiler. +#ifndef _WIN32 +// Don't you just love a good ol' mangled name? I know I do. +extern "C" LLVMMetadataRef _ZN4llvm9DIBuilder11createLabelEPNS_7DIScopeENS_9StringRefEPNS_6DIFileEjb( + LLVMDIBuilderRef Builder, + LLVMMetadataRef Scope, + String Name, // Not technically proper to do, but it's ABI compatible for now... + LLVMMetadataRef File, + unsigned int LineNo, + unsigned int AlwaysPreserve); +#endif +gb_internal void lb_add_debug_label(lbProcedure *p, Scope *parent, Ast *ast) { + if (p == nullptr || p->debug_info == nullptr || p->body == nullptr) { + return; + } + if (parent == nullptr) { + return; + } + if (ast == nullptr || ast->kind != Ast_Label) { + return; + } + Token label_token = ast->Label.token; + if (is_blank_ident(label_token.string)) { + return; + } + lbModule *m = p->module; + if (m == nullptr) { + return; + } + + #ifndef _WIN32 + AstFile *file = ast->file(); + LLVMMetadataRef llvm_file = lb_get_llvm_metadata(m, file); + if (llvm_file == nullptr) { + debugf("llvm file not found for label\n"); + return; + } + LLVMMetadataRef llvm_scope = lb_get_current_debug_scope(p); + if(llvm_scope == nullptr) { + debugf("llvm scope not found for label\n"); + return; + } + LLVMMetadataRef llvm_label = _ZN4llvm9DIBuilder11createLabelEPNS_7DIScopeENS_9StringRefEPNS_6DIFileEjb( + m->debug_builder, + llvm_scope, + label_token.string, + llvm_file, + label_token.pos.line, + 1 // False by default. Not sure why. + ); + String file_name = file->fullpath; + debugf("New label: %.*s %.*s:%d %p\n", + label_token.string.len, + label_token.string.text, + file_name.len, + file_name.text, + label_token.pos.line, + llvm_label + ); + #endif +} diff --git a/src/llvm_backend_stmt.cpp b/src/llvm_backend_stmt.cpp index df3d4bc030d..d79066a3e93 100644 --- a/src/llvm_backend_stmt.cpp +++ b/src/llvm_backend_stmt.cpp @@ -137,7 +137,6 @@ gb_internal lbBranchBlocks lb_lookup_branch_blocks(lbProcedure *p, Ast *ident) { return empty; } - gb_internal lbTargetList *lb_push_target_list(lbProcedure *p, Ast *label, lbBlock *break_, lbBlock *continue_, lbBlock *fallthrough_) { lbTargetList *tl = gb_alloc_item(permanent_allocator(), lbTargetList); tl->prev = p->target_list; @@ -711,6 +710,7 @@ gb_internal void lb_build_range_interval(lbProcedure *p, AstBinaryExpr *node, continue_block = check; } + lb_add_debug_label(p, rs->scope, rs->label); lb_push_target_list(p, rs->label, done, continue_block, nullptr); lb_build_stmt(p, rs->body); @@ -844,6 +844,7 @@ gb_internal void lb_build_range_tuple(lbProcedure *p, AstRangeStmt *rs, Scope *s } } + lb_add_debug_label(p, rs->scope, rs->label); lb_push_target_list(p, rs->label, done, loop, nullptr); lb_build_stmt(p, rs->body); @@ -966,6 +967,7 @@ gb_internal void lb_build_range_stmt_struct_soa(lbProcedure *p, AstRangeStmt *rs } + lb_add_debug_label(p, rs->scope, rs->label); lb_push_target_list(p, rs->label, done, loop, nullptr); lb_build_stmt(p, rs->body); @@ -1182,6 +1184,7 @@ gb_internal void lb_build_range_stmt(lbProcedure *p, AstRangeStmt *rs, Scope *sc if (val1_type) lb_store_range_stmt_val(p, val1, key); } + lb_add_debug_label(p, rs->scope, rs->label); lb_push_target_list(p, rs->label, done, loop, nullptr); lb_build_stmt(p, rs->body); @@ -1543,6 +1546,7 @@ gb_internal void lb_build_switch_stmt(lbProcedure *p, AstSwitchStmt *ss, Scope * } lb_start_block(p, body); + lb_add_debug_label(p, ss->scope, ss->label); lb_push_target_list(p, ss->label, done, nullptr, fall); lb_open_scope(p, body->scope); lb_build_stmt_list(p, cc->stmts); @@ -1561,6 +1565,7 @@ gb_internal void lb_build_switch_stmt(lbProcedure *p, AstSwitchStmt *ss, Scope * } lb_start_block(p, default_block); + lb_add_debug_label(p, ss->scope, ss->label); lb_push_target_list(p, ss->label, done, nullptr, default_fall); lb_open_scope(p, default_block->scope); lb_build_stmt_list(p, default_stmts); @@ -2183,6 +2188,7 @@ gb_internal void lb_build_if_stmt(lbProcedure *p, Ast *node) { else_ = lb_create_block(p, "if.else"); } if (is->label != nullptr) { + lb_add_debug_label(p, is->scope, is->label); lbTargetList *tl = lb_push_target_list(p, is->label, done, nullptr, nullptr); tl->is_block = true; } @@ -2273,6 +2279,7 @@ gb_internal void lb_build_for_stmt(lbProcedure *p, Ast *node) { post = lb_create_block(p, "for.post"); } + lb_add_debug_label(p, fs->scope, fs->label); lb_push_target_list(p, fs->label, done, post, nullptr); if (fs->init != nullptr) { @@ -2573,6 +2580,7 @@ gb_internal void lb_build_stmt(lbProcedure *p, Ast *node) { lbBlock *done = nullptr; if (bs->label != nullptr) { done = lb_create_block(p, "block.done"); + lb_add_debug_label(p, bs->scope, bs->label); lbTargetList *tl = lb_push_target_list(p, bs->label, done, nullptr, nullptr); tl->is_block = true; } From 36b04f9f47f8b10d6ef2ebfad72365d22e4d60a0 Mon Sep 17 00:00:00 2001 From: Misomosi Date: Wed, 16 Oct 2024 02:07:14 -0400 Subject: [PATCH 2/8] Insert debug label call --- src/llvm_backend_debug.cpp | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/src/llvm_backend_debug.cpp b/src/llvm_backend_debug.cpp index 0caf42349e5..260f4e232a3 100644 --- a/src/llvm_backend_debug.cpp +++ b/src/llvm_backend_debug.cpp @@ -1316,6 +1316,11 @@ extern "C" LLVMMetadataRef _ZN4llvm9DIBuilder11createLabelEPNS_7DIScopeENS_9Stri LLVMMetadataRef File, unsigned int LineNo, unsigned int AlwaysPreserve); +extern "C" LLVMMetadataRef _ZN4llvm9DIBuilder11insertLabelEPNS_7DILabelEPKNS_10DILocationEPNS_10BasicBlockE( + LLVMDIBuilderRef Builder, + LLVMMetadataRef Label, + LLVMMetadataRef Location, + LLVMBasicBlockRef Block); #endif gb_internal void lb_add_debug_label(lbProcedure *p, Scope *parent, Ast *ast) { if (p == nullptr || p->debug_info == nullptr || p->body == nullptr) { @@ -1343,11 +1348,13 @@ gb_internal void lb_add_debug_label(lbProcedure *p, Scope *parent, Ast *ast) { debugf("llvm file not found for label\n"); return; } - LLVMMetadataRef llvm_scope = lb_get_current_debug_scope(p); + LLVMMetadataRef llvm_scope = p->debug_info; if(llvm_scope == nullptr) { debugf("llvm scope not found for label\n"); return; } + LLVMMetadataRef llvm_debug_loc = lb_debug_location_from_token_pos(p, label_token.pos); + LLVMBasicBlockRef llvm_block = p->curr_block->block; LLVMMetadataRef llvm_label = _ZN4llvm9DIBuilder11createLabelEPNS_7DIScopeENS_9StringRefEPNS_6DIFileEjb( m->debug_builder, llvm_scope, @@ -1356,12 +1363,16 @@ gb_internal void lb_add_debug_label(lbProcedure *p, Scope *parent, Ast *ast) { label_token.pos.line, 1 // False by default. Not sure why. ); + _ZN4llvm9DIBuilder11insertLabelEPNS_7DILabelEPKNS_10DILocationEPNS_10BasicBlockE( + m->debug_builder, + llvm_label, + llvm_debug_loc, + llvm_block + ); String file_name = file->fullpath; debugf("New label: %.*s %.*s:%d %p\n", - label_token.string.len, - label_token.string.text, - file_name.len, - file_name.text, + LIT(label_token.string), + LIT(file_name), label_token.pos.line, llvm_label ); From 06b2b2c7313522cab8554fd4fdfa2a9ee889c017 Mon Sep 17 00:00:00 2001 From: Misomosi Date: Wed, 16 Oct 2024 10:32:17 -0400 Subject: [PATCH 3/8] Slight refactor for later fix --- src/llvm_backend_debug.cpp | 16 ++++++++-------- src/llvm_backend_stmt.cpp | 18 +++++++++--------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/llvm_backend_debug.cpp b/src/llvm_backend_debug.cpp index 260f4e232a3..5f8425bd81e 100644 --- a/src/llvm_backend_debug.cpp +++ b/src/llvm_backend_debug.cpp @@ -1322,17 +1322,14 @@ extern "C" LLVMMetadataRef _ZN4llvm9DIBuilder11insertLabelEPNS_7DILabelEPKNS_10D LLVMMetadataRef Location, LLVMBasicBlockRef Block); #endif -gb_internal void lb_add_debug_label(lbProcedure *p, Scope *parent, Ast *ast) { +gb_internal void lb_add_debug_label(lbProcedure *p, Ast *label, lbBlock *target) { if (p == nullptr || p->debug_info == nullptr || p->body == nullptr) { return; } - if (parent == nullptr) { + if (target == nullptr || label == nullptr || label->kind != Ast_Label) { return; } - if (ast == nullptr || ast->kind != Ast_Label) { - return; - } - Token label_token = ast->Label.token; + Token label_token = label->Label.token; if (is_blank_ident(label_token.string)) { return; } @@ -1342,7 +1339,7 @@ gb_internal void lb_add_debug_label(lbProcedure *p, Scope *parent, Ast *ast) { } #ifndef _WIN32 - AstFile *file = ast->file(); + AstFile *file = label->file(); LLVMMetadataRef llvm_file = lb_get_llvm_metadata(m, file); if (llvm_file == nullptr) { debugf("llvm file not found for label\n"); @@ -1354,7 +1351,10 @@ gb_internal void lb_add_debug_label(lbProcedure *p, Scope *parent, Ast *ast) { return; } LLVMMetadataRef llvm_debug_loc = lb_debug_location_from_token_pos(p, label_token.pos); - LLVMBasicBlockRef llvm_block = p->curr_block->block; + LLVMBasicBlockRef llvm_block = target->block; + if (llvm_block == nullptr || llvm_debug_loc == nullptr) { + return; + } LLVMMetadataRef llvm_label = _ZN4llvm9DIBuilder11createLabelEPNS_7DIScopeENS_9StringRefEPNS_6DIFileEjb( m->debug_builder, llvm_scope, diff --git a/src/llvm_backend_stmt.cpp b/src/llvm_backend_stmt.cpp index d79066a3e93..92f6f6ed752 100644 --- a/src/llvm_backend_stmt.cpp +++ b/src/llvm_backend_stmt.cpp @@ -710,7 +710,7 @@ gb_internal void lb_build_range_interval(lbProcedure *p, AstBinaryExpr *node, continue_block = check; } - lb_add_debug_label(p, rs->scope, rs->label); + lb_add_debug_label(p, rs->label, p->curr_block); lb_push_target_list(p, rs->label, done, continue_block, nullptr); lb_build_stmt(p, rs->body); @@ -844,7 +844,7 @@ gb_internal void lb_build_range_tuple(lbProcedure *p, AstRangeStmt *rs, Scope *s } } - lb_add_debug_label(p, rs->scope, rs->label); + lb_add_debug_label(p, rs->label, p->curr_block); lb_push_target_list(p, rs->label, done, loop, nullptr); lb_build_stmt(p, rs->body); @@ -967,7 +967,7 @@ gb_internal void lb_build_range_stmt_struct_soa(lbProcedure *p, AstRangeStmt *rs } - lb_add_debug_label(p, rs->scope, rs->label); + lb_add_debug_label(p, rs->label, p->curr_block); lb_push_target_list(p, rs->label, done, loop, nullptr); lb_build_stmt(p, rs->body); @@ -1184,7 +1184,7 @@ gb_internal void lb_build_range_stmt(lbProcedure *p, AstRangeStmt *rs, Scope *sc if (val1_type) lb_store_range_stmt_val(p, val1, key); } - lb_add_debug_label(p, rs->scope, rs->label); + lb_add_debug_label(p, rs->label, p->curr_block); lb_push_target_list(p, rs->label, done, loop, nullptr); lb_build_stmt(p, rs->body); @@ -1546,7 +1546,6 @@ gb_internal void lb_build_switch_stmt(lbProcedure *p, AstSwitchStmt *ss, Scope * } lb_start_block(p, body); - lb_add_debug_label(p, ss->scope, ss->label); lb_push_target_list(p, ss->label, done, nullptr, fall); lb_open_scope(p, body->scope); lb_build_stmt_list(p, cc->stmts); @@ -1565,7 +1564,7 @@ gb_internal void lb_build_switch_stmt(lbProcedure *p, AstSwitchStmt *ss, Scope * } lb_start_block(p, default_block); - lb_add_debug_label(p, ss->scope, ss->label); + lb_add_debug_label(p, ss->label, p->curr_block); lb_push_target_list(p, ss->label, done, nullptr, default_fall); lb_open_scope(p, default_block->scope); lb_build_stmt_list(p, default_stmts); @@ -1624,6 +1623,7 @@ gb_internal lbAddr lb_store_range_stmt_val(lbProcedure *p, Ast *stmt_val, lbValu gb_internal void lb_type_case_body(lbProcedure *p, Ast *label, Ast *clause, lbBlock *body, lbBlock *done) { ast_node(cc, CaseClause, clause); + // NOTE(tf2spi): Debug info for label not generated here on purpose lb_push_target_list(p, label, done, nullptr, nullptr); lb_build_stmt_list(p, cc->stmts); lb_close_scope(p, lbDeferExit_Default, body); @@ -2188,7 +2188,7 @@ gb_internal void lb_build_if_stmt(lbProcedure *p, Ast *node) { else_ = lb_create_block(p, "if.else"); } if (is->label != nullptr) { - lb_add_debug_label(p, is->scope, is->label); + lb_add_debug_label(p, is->label, p->curr_block); lbTargetList *tl = lb_push_target_list(p, is->label, done, nullptr, nullptr); tl->is_block = true; } @@ -2279,7 +2279,7 @@ gb_internal void lb_build_for_stmt(lbProcedure *p, Ast *node) { post = lb_create_block(p, "for.post"); } - lb_add_debug_label(p, fs->scope, fs->label); + lb_add_debug_label(p, fs->label, p->curr_block); lb_push_target_list(p, fs->label, done, post, nullptr); if (fs->init != nullptr) { @@ -2580,7 +2580,7 @@ gb_internal void lb_build_stmt(lbProcedure *p, Ast *node) { lbBlock *done = nullptr; if (bs->label != nullptr) { done = lb_create_block(p, "block.done"); - lb_add_debug_label(p, bs->scope, bs->label); + lb_add_debug_label(p, bs->label, p->curr_block); lbTargetList *tl = lb_push_target_list(p, bs->label, done, nullptr, nullptr); tl->is_block = true; } From bab68429c4f128cf9453ff2af6a474cb20976691 Mon Sep 17 00:00:00 2001 From: Misomosi Date: Wed, 16 Oct 2024 10:45:35 -0400 Subject: [PATCH 4/8] Improve debug labels for block statements --- src/llvm_backend_stmt.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/llvm_backend_stmt.cpp b/src/llvm_backend_stmt.cpp index 92f6f6ed752..9e548875a64 100644 --- a/src/llvm_backend_stmt.cpp +++ b/src/llvm_backend_stmt.cpp @@ -2577,10 +2577,14 @@ gb_internal void lb_build_stmt(lbProcedure *p, Ast *node) { case_ast_node(bs, BlockStmt, node); + lbBlock *body = nullptr; lbBlock *done = nullptr; if (bs->label != nullptr) { + body = lb_create_block(p, "block.body"); done = lb_create_block(p, "block.done"); - lb_add_debug_label(p, bs->label, p->curr_block); + lb_emit_jump(p, body); + lb_start_block(p, body); + lb_add_debug_label(p, bs->label, body); lbTargetList *tl = lb_push_target_list(p, bs->label, done, nullptr, nullptr); tl->is_block = true; } From c234fbc5cd8122305b7ce3807deb0b4eb6b674e5 Mon Sep 17 00:00:00 2001 From: Misomosi Date: Wed, 16 Oct 2024 11:11:47 -0400 Subject: [PATCH 5/8] Improve debug info with for loops --- src/llvm_backend_stmt.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/llvm_backend_stmt.cpp b/src/llvm_backend_stmt.cpp index 9e548875a64..f470812643e 100644 --- a/src/llvm_backend_stmt.cpp +++ b/src/llvm_backend_stmt.cpp @@ -2279,17 +2279,18 @@ gb_internal void lb_build_for_stmt(lbProcedure *p, Ast *node) { post = lb_create_block(p, "for.post"); } - lb_add_debug_label(p, fs->label, p->curr_block); lb_push_target_list(p, fs->label, done, post, nullptr); + lbBlock *init = lb_create_block(p, "for.init"); + lb_emit_jump(p, init); + lb_start_block(p, init); if (fs->init != nullptr) { - #if 1 - lbBlock *init = lb_create_block(p, "for.init"); - lb_emit_jump(p, init); - lb_start_block(p, init); - #endif lb_build_stmt(p, fs->init); } + if (fs->label != nullptr && p->debug_info != nullptr) { + LLVMSetCurrentDebugLocation2(p->builder, lb_debug_location_from_ast(p, fs->label)); + lb_add_debug_label(p, fs->label, init); + } lb_emit_jump(p, loop); lb_start_block(p, loop); @@ -2303,7 +2304,6 @@ gb_internal void lb_build_for_stmt(lbProcedure *p, Ast *node) { lb_start_block(p, body); } - lb_build_stmt(p, fs->body); lb_pop_target_list(p); From 9f7e283fdef4dbecceaa73d0be5f3a95088bc959 Mon Sep 17 00:00:00 2001 From: Misomosi Date: Wed, 16 Oct 2024 19:46:12 -0400 Subject: [PATCH 6/8] Generate label lbBlocks w/ debug --- src/llvm_backend_stmt.cpp | 80 +++++++++++++++++++++++++++++++-------- 1 file changed, 65 insertions(+), 15 deletions(-) diff --git a/src/llvm_backend_stmt.cpp b/src/llvm_backend_stmt.cpp index f470812643e..659a99ad861 100644 --- a/src/llvm_backend_stmt.cpp +++ b/src/llvm_backend_stmt.cpp @@ -682,6 +682,18 @@ gb_internal void lb_build_range_interval(lbProcedure *p, AstBinaryExpr *node, lbBlock *body = lb_create_block(p, "for.interval.body"); lbBlock *done = lb_create_block(p, "for.interval.done"); + // TODO(tf2spi): This is inlined in more than several places. + // Putting this in a function might be preferred. + // LLVMSetCurrentDebugLocation2 has side effects, + // so I didn't want to hide that before it got reviewed. + if (rs->label != nullptr && p->debug_info != nullptr) { + lbBlock *label = lb_create_block(p, "for.interval.label"); + lb_emit_jump(p, label); + lb_start_block(p, label); + + LLVMSetCurrentDebugLocation2(p->builder, lb_debug_location_from_ast(p, rs->label)); + lb_add_debug_label(p, rs->label, label); + } lb_emit_jump(p, loop); lb_start_block(p, loop); @@ -710,7 +722,6 @@ gb_internal void lb_build_range_interval(lbProcedure *p, AstBinaryExpr *node, continue_block = check; } - lb_add_debug_label(p, rs->label, p->curr_block); lb_push_target_list(p, rs->label, done, continue_block, nullptr); lb_build_stmt(p, rs->body); @@ -844,7 +855,6 @@ gb_internal void lb_build_range_tuple(lbProcedure *p, AstRangeStmt *rs, Scope *s } } - lb_add_debug_label(p, rs->label, p->curr_block); lb_push_target_list(p, rs->label, done, loop, nullptr); lb_build_stmt(p, rs->body); @@ -889,6 +899,14 @@ gb_internal void lb_build_range_stmt_struct_soa(lbProcedure *p, AstRangeStmt *rs lbAddr index = lb_add_local_generated(p, t_int, false); + if (rs->label != nullptr && p->debug_info != nullptr) { + lbBlock *label = lb_create_block(p, "for.soa.label"); + lb_emit_jump(p, label); + lb_start_block(p, label); + + LLVMSetCurrentDebugLocation2(p->builder, lb_debug_location_from_ast(p, rs->label)); + lb_add_debug_label(p, rs->label, label); + } if (!is_reverse) { /* for x, i in array { @@ -966,8 +984,6 @@ gb_internal void lb_build_range_stmt_struct_soa(lbProcedure *p, AstRangeStmt *rs lb_store_range_stmt_val(p, val1, lb_addr_load(p, index)); } - - lb_add_debug_label(p, rs->label, p->curr_block); lb_push_target_list(p, rs->label, done, loop, nullptr); lb_build_stmt(p, rs->body); @@ -1026,6 +1042,15 @@ gb_internal void lb_build_range_stmt(lbProcedure *p, AstRangeStmt *rs, Scope *sc lbBlock *done = nullptr; bool is_map = false; + if (rs->label != nullptr && p->debug_info != nullptr) { + lbBlock *label = lb_create_block(p, "for.range.label"); + lb_emit_jump(p, label); + lb_start_block(p, label); + + LLVMSetCurrentDebugLocation2(p->builder, lb_debug_location_from_ast(p, rs->label)); + lb_add_debug_label(p, rs->label, label); + } + if (tav.mode == Addressing_Type) { lb_build_range_enum(p, type_deref(tav.type), val0_type, &val, &key, &loop, &done); } else { @@ -1184,7 +1209,6 @@ gb_internal void lb_build_range_stmt(lbProcedure *p, AstRangeStmt *rs, Scope *sc if (val1_type) lb_store_range_stmt_val(p, val1, key); } - lb_add_debug_label(p, rs->label, p->curr_block); lb_push_target_list(p, rs->label, done, loop, nullptr); lb_build_stmt(p, rs->body); @@ -1418,6 +1442,14 @@ gb_internal bool lb_switch_stmt_can_be_trivial_jump_table(AstSwitchStmt *ss, boo gb_internal void lb_build_switch_stmt(lbProcedure *p, AstSwitchStmt *ss, Scope *scope) { lb_open_scope(p, scope); + if (ss->label != nullptr && p->debug_info != nullptr) { + lbBlock *label = lb_create_block(p, "switch.label"); + lb_emit_jump(p, label); + lb_start_block(p, label); + + LLVMSetCurrentDebugLocation2(p->builder, lb_debug_location_from_ast(p, ss->label)); + lb_add_debug_label(p, ss->label, label); + } if (ss->init != nullptr) { lb_build_stmt(p, ss->init); } @@ -1564,7 +1596,6 @@ gb_internal void lb_build_switch_stmt(lbProcedure *p, AstSwitchStmt *ss, Scope * } lb_start_block(p, default_block); - lb_add_debug_label(p, ss->label, p->curr_block); lb_push_target_list(p, ss->label, done, nullptr, default_fall); lb_open_scope(p, default_block->scope); lb_build_stmt_list(p, default_stmts); @@ -2188,7 +2219,14 @@ gb_internal void lb_build_if_stmt(lbProcedure *p, Ast *node) { else_ = lb_create_block(p, "if.else"); } if (is->label != nullptr) { - lb_add_debug_label(p, is->label, p->curr_block); + if (p->debug_info != nullptr) { + lbBlock *label = lb_create_block(p, "if.label"); + lb_emit_jump(p, label); + lb_start_block(p, label); + + LLVMSetCurrentDebugLocation2(p->builder, lb_debug_location_from_ast(p, is->label)); + lb_add_debug_label(p, is->label, label); + } lbTargetList *tl = lb_push_target_list(p, is->label, done, nullptr, nullptr); tl->is_block = true; } @@ -2281,15 +2319,20 @@ gb_internal void lb_build_for_stmt(lbProcedure *p, Ast *node) { lb_push_target_list(p, fs->label, done, post, nullptr); - lbBlock *init = lb_create_block(p, "for.init"); - lb_emit_jump(p, init); - lb_start_block(p, init); - if (fs->init != nullptr) { - lb_build_stmt(p, fs->init); - } if (fs->label != nullptr && p->debug_info != nullptr) { + lbBlock *label = lb_create_block(p, "for.label"); + lb_emit_jump(p, label); + lb_start_block(p, label); + LLVMSetCurrentDebugLocation2(p->builder, lb_debug_location_from_ast(p, fs->label)); - lb_add_debug_label(p, fs->label, init); + lb_add_debug_label(p, fs->label, label); + } + if (fs->init != nullptr) { + lbBlock *init = lb_create_block(p, "for.init"); + lb_emit_jump(p, init); + lb_start_block(p, init); + + lb_build_stmt(p, fs->init); } lb_emit_jump(p, loop); @@ -2580,11 +2623,18 @@ gb_internal void lb_build_stmt(lbProcedure *p, Ast *node) { lbBlock *body = nullptr; lbBlock *done = nullptr; if (bs->label != nullptr) { + if (p->debug_info != nullptr) { + lbBlock *label = lb_create_block(p, "block.label"); + lb_emit_jump(p, label); + lb_start_block(p, label); + + LLVMSetCurrentDebugLocation2(p->builder, lb_debug_location_from_ast(p, bs->label)); + lb_add_debug_label(p, bs->label, label); + } body = lb_create_block(p, "block.body"); done = lb_create_block(p, "block.done"); lb_emit_jump(p, body); lb_start_block(p, body); - lb_add_debug_label(p, bs->label, body); lbTargetList *tl = lb_push_target_list(p, bs->label, done, nullptr, nullptr); tl->is_block = true; } From 9d0bf239ea8a2d84ded4e635cd49c359d82fcc7f Mon Sep 17 00:00:00 2001 From: Misomosi Date: Wed, 16 Oct 2024 20:05:03 -0400 Subject: [PATCH 7/8] Lightly refactor lb_add_debug_label --- src/llvm_backend_debug.cpp | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/src/llvm_backend_debug.cpp b/src/llvm_backend_debug.cpp index 5f8425bd81e..47a04754c88 100644 --- a/src/llvm_backend_debug.cpp +++ b/src/llvm_backend_debug.cpp @@ -1304,18 +1304,20 @@ gb_internal void add_debug_info_for_global_constant_from_entity(lbGenerator *gen // TODO(tf2spi) ... *sigh* I hate LLVM so much. // LLVM-C doesn't have an API to emit DILabel yet, so this is not exported in the dll. -// For Linux, we can temporarily use the C++ APIs, but we're out of luck for Windows -// until the DLL gets updated with a definition like LLVMDIBuilderCreateLabel. -// These might be the 50 most disgusting lines in this entire compiler. +// For POSIX, we can temporarily use the C++ APIs, but we're out of luck for Windows +// until the DLL gets updated with definitions like LLVMDIBuilderCreateLabel. +// These might be the ~80 most disgusting lines in this entire compiler. #ifndef _WIN32 // Don't you just love a good ol' mangled name? I know I do. +// Mangled name of "llvm::DIBuilder::createLabel(DIScope, StringRef, DIFile, unsigned, bool)" extern "C" LLVMMetadataRef _ZN4llvm9DIBuilder11createLabelEPNS_7DIScopeENS_9StringRefEPNS_6DIFileEjb( LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, String Name, // Not technically proper to do, but it's ABI compatible for now... LLVMMetadataRef File, unsigned int LineNo, - unsigned int AlwaysPreserve); + bool AlwaysPreserve); +// Mangled name of "llvm::DIBuilder::insertLabel(DILabel, DILocation, BasicBlock)" extern "C" LLVMMetadataRef _ZN4llvm9DIBuilder11insertLabelEPNS_7DILabelEPKNS_10DILocationEPNS_10BasicBlockE( LLVMDIBuilderRef Builder, LLVMMetadataRef Label, @@ -1323,7 +1325,15 @@ extern "C" LLVMMetadataRef _ZN4llvm9DIBuilder11insertLabelEPNS_7DILabelEPKNS_10D LLVMBasicBlockRef Block); #endif gb_internal void lb_add_debug_label(lbProcedure *p, Ast *label, lbBlock *target) { - if (p == nullptr || p->debug_info == nullptr || p->body == nullptr) { + // TODO(tf2spi): Work with gingerBill to see if we can patch LLVM-C + // to export DILabel functions for the C API on Windows + // or to determine whether it is worthwhile to do this. + // Until then, unimplemented, so just return. + #ifdef _WIN32 + if ((volatile int)0 == 0) return; + #endif + + if (p == nullptr || p->debug_info == nullptr) { return; } if (target == nullptr || label == nullptr || label->kind != Ast_Label) { @@ -1338,7 +1348,6 @@ gb_internal void lb_add_debug_label(lbProcedure *p, Ast *label, lbBlock *target) return; } - #ifndef _WIN32 AstFile *file = label->file(); LLVMMetadataRef llvm_file = lb_get_llvm_metadata(m, file); if (llvm_file == nullptr) { @@ -1355,13 +1364,19 @@ gb_internal void lb_add_debug_label(lbProcedure *p, Ast *label, lbBlock *target) if (llvm_block == nullptr || llvm_debug_loc == nullptr) { return; } + + // TODO(tf2spi): Generate and insert DILabel for Windows when feasible + #ifndef _WIN32 LLVMMetadataRef llvm_label = _ZN4llvm9DIBuilder11createLabelEPNS_7DIScopeENS_9StringRefEPNS_6DIFileEjb( m->debug_builder, llvm_scope, label_token.string, llvm_file, label_token.pos.line, - 1 // False by default. Not sure why. + + // NOTE(tf2spi): Defaults to false in LLVM API, but I'd rather not take chances + // Always preserve the label no matter what when debugging + true ); _ZN4llvm9DIBuilder11insertLabelEPNS_7DILabelEPKNS_10DILocationEPNS_10BasicBlockE( m->debug_builder, @@ -1369,12 +1384,5 @@ gb_internal void lb_add_debug_label(lbProcedure *p, Ast *label, lbBlock *target) llvm_debug_loc, llvm_block ); - String file_name = file->fullpath; - debugf("New label: %.*s %.*s:%d %p\n", - LIT(label_token.string), - LIT(file_name), - label_token.pos.line, - llvm_label - ); #endif } From df880be9ae7265b7ffb8d6b5ed908624c90bb77e Mon Sep 17 00:00:00 2001 From: Misomosi Date: Thu, 17 Oct 2024 19:49:10 -0400 Subject: [PATCH 8/8] Revise comments, add null check assertion --- src/llvm_backend_debug.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/llvm_backend_debug.cpp b/src/llvm_backend_debug.cpp index 47a04754c88..74c146a5eb3 100644 --- a/src/llvm_backend_debug.cpp +++ b/src/llvm_backend_debug.cpp @@ -1302,7 +1302,7 @@ gb_internal void add_debug_info_for_global_constant_from_entity(lbGenerator *gen } } -// TODO(tf2spi) ... *sigh* I hate LLVM so much. +// TODO(tf2spi) ... *sigh* I'm sad // LLVM-C doesn't have an API to emit DILabel yet, so this is not exported in the dll. // For POSIX, we can temporarily use the C++ APIs, but we're out of luck for Windows // until the DLL gets updated with definitions like LLVMDIBuilderCreateLabel. @@ -1325,10 +1325,9 @@ extern "C" LLVMMetadataRef _ZN4llvm9DIBuilder11insertLabelEPNS_7DILabelEPKNS_10D LLVMBasicBlockRef Block); #endif gb_internal void lb_add_debug_label(lbProcedure *p, Ast *label, lbBlock *target) { - // TODO(tf2spi): Work with gingerBill to see if we can patch LLVM-C - // to export DILabel functions for the C API on Windows - // or to determine whether it is worthwhile to do this. - // Until then, unimplemented, so just return. + // TODO(tf2spi): Not implemented on Windows because LLVM-C does not have + // an official API for DILabel yet, so DLL does not export it. + // When there is one, implement this function for Windows. #ifdef _WIN32 if ((volatile int)0 == 0) return; #endif @@ -1378,6 +1377,7 @@ gb_internal void lb_add_debug_label(lbProcedure *p, Ast *label, lbBlock *target) // Always preserve the label no matter what when debugging true ); + GB_ASSERT(llvm_label != nullptr); _ZN4llvm9DIBuilder11insertLabelEPNS_7DILabelEPKNS_10DILocationEPNS_10BasicBlockE( m->debug_builder, llvm_label,