1#\nfeatures for generating the debug information. The general principle is\nthis:\n\nGiven the right metadata in the LLVM IR, the LLVM code generator is able to\ncreate DWARF debug symbols for the given code. The\n[metadata](https://llvm.org/docs/LangRef.html#metadata-type) is structured\nmuch like DWARF *debugging information entries* (DIE), representing type\ninformation such as datatype layout, function signatures, block layout,\nvariable location and scope information, etc. It is the purpose of this\nmodule to generate correct metadata and insert it into the LLVM IR.\n\nAs the exact format of metadata trees may change between different LLVM\nversions, we now use LLVM\n[DIBuilder](https://llvm.org/docs/doxygen/html/classllvm_1_1DIBuilder.html)\nto create metadata where possible. This will hopefully ease the adaptation of\nthis module to future LLVM versions.\n\nThe public API of the module is a set of functions that will insert the\ncorrect metadata into the LLVM IR when called with the right parameters.\nThe module is thus driven from an outside client with functions like\n`debuginfo::create_local_var_metadata(bx: block, local: &ast::local)`.\n\nInternally the module will try to reuse already created metadata by\nutilizing a cache. The way to get a shared metadata node when needed is\nthus to just call the corresponding function in this module:\n```ignore (illustrative)\nlet file_metadata = file_metadata(cx, file);\n```\nThe function will take care of probing the cache for an existing node for\nthat exact file path.\n\nAll private state used by the module is stored within either the\nCodegenUnitDebugContext struct (owned by the CodegenCx) or the\nFunctionDebugContext (owned by the FunctionCx).\n\nThis file consists of three conceptual sections:\n1. The public interface of the module\n2. Module-internal metadata creation functions\n3. Minor utility functions\n\n\n## Recursive Types\n\nSome kinds of types, such as structs and enums can be recursive. That means\nthat the type definition of some type X refers to some other type which in\nturn (transitively) refers to X. This introduces cycles into the type\nreferral graph. A naive algorithm doing an on-demand, depth-first traversal\nof this graph when describing types, can get trapped in an endless loop\nwhen it reaches such a cycle.\n\nFor example, the following simple type for a singly-linked list...\n\n```\nstruct List {\n value: i32,\n tail: Option<Box<List>>,\n}\n```\n\nwill generate the following callstack with a naive DFS algorithm:\n\n```ignore (illustrative)\ndescribe(t = List)\n describe(t = i32)\n describe(t = Option<Box<List>>)\n describe(t = Box<List>)\n describe(t = List) // at the beginning again...\n ...\n```\n\nTo break cycles like these, we use \"stubs\". That is, when\nthe algorithm encounters a possibly recursive type (any struct or enum), it\nimmediately creates a type description node and inserts it into the cache\n*before* describing the members of the type. This type description is just\na stub (as type members are not described and added to it yet) but it\nallows the algorithm to already refer to the type. After the stub is\ninserted into the cache, the algorithm continues as before. If it now\nencounters a recursive reference, it will hit the cache and does not try to\ndescribe the type anew. This behavior is encapsulated in the\n`type_map::build_type_with_children()` function.\n\n\n## Source Locations and Line Information\n\nIn addition to data type descriptions the debugging information must also\nallow mapping machine code locations back to source code locations in order\nto be useful. This functionality is also handled in this module. The\nfollowing functions allow controlling source mappings:\n\n+ `set_source_location()`\n+ `clear_source_location()`\n+ `start_emitting_source_locations()`\n\n`set_source_location()` allows setting the current source location. All IR\ninstructions created after a call to this function will be linked to the\ngiven source location, until another location is specified with\n`set_source_location()` or the source location is cleared with\n`clear_source_location()`. In the latter case, subsequent IR instructions\nwill not be linked to any source location. As you can see, this is a\nstateful API (mimicking the one in LLVM), so be careful with source\nlocations set by previous calls. It\'s probably best to not rely on any\nspecific state being present at a given point in code.\n\nOne topic that deserves some extra attention is *function prologues*. At\nthe beginning of a function\'s machine code there are typically a few\ninstructions for loading argument values into allocas and checking if\nthere\'s enough stack space for the function to execute. This *prologue* is\nnot visible in the source code and LLVM puts a special PROLOGUE END marker\ninto the line table at the first non-prologue instruction of the function.\nIn order to find out where the prologue ends, LLVM looks for the first\ninstruction in the function body that is linked to a source location. So,\nwhen generating prologue instructions we have to make sure that we don\'t\nemit source location information until the \'real\' function body begins. For\nthis reason, source location emission is disabled by default for any new\nfunction being codegened and is only activated after a call to the third\nfunction from the list above, `start_emitting_source_locations()`. This\nfunction should be called right before regularly starting to codegen the\ntop-level block of the given function.\n\nThere is one exception to the above rule: `llvm.dbg.declare` instruction\nmust be linked to the source location of the variable being declared. For\nfunction parameters these `llvm.dbg.declare` instructions typically occur\nin the middle of the prologue, however, they are ignored by LLVM\'s prologue\ndetection. The `create_argument_metadata()` and related functions take care\nof linking the `llvm.dbg.declare` instructions to the correct source\nlocations even while source location emission is still disabled, so there\nis no need to do anything special with source location handling here.\n"include_str!("doc.md")]
2
3use std::cell::{OnceCell, RefCell};
4use std::ops::Range;
5use std::sync::Arc;
6use std::{iter, ptr};
7
8use libc::c_uint;
9use metadata::create_subroutine_type;
10use rustc_abi::Size;
11use rustc_codegen_ssa::debuginfo::type_names;
12use rustc_codegen_ssa::mir::debuginfo::VariableKind;
13use rustc_codegen_ssa::mir::debuginfo::VariableKind::*;
14use rustc_codegen_ssa::traits::*;
15use rustc_data_structures::unord::UnordMap;
16use rustc_hir::def_id::{DefId, DefIdMap};
17use rustc_middle::ty::layout::{HasTypingEnv, LayoutOf};
18use rustc_middle::ty::{self, GenericArgsRef, Instance, Ty, TypeVisitableExt, Unnormalized};
19use rustc_session::Session;
20use rustc_session::config::{self, DebugInfo};
21use rustc_span::{
22 BytePos, Pos, SourceFile, SourceFileAndLine, SourceFileHash, Span, StableSourceFileId, Symbol,
23};
24use rustc_target::callconv::FnAbi;
25use rustc_target::spec::DebuginfoKind;
26use smallvec::SmallVec;
27use tracing::debug;
28
29pub(crate) use self::di_builder::DIBuilderExt;
30pub(crate) use self::metadata::build_global_var_di_node;
31use self::metadata::{
32 UNKNOWN_COLUMN_NUMBER, UNKNOWN_LINE_NUMBER, file_metadata, spanned_type_di_node, type_di_node,
33};
34use self::namespace::mangled_name_of_instance;
35use self::utils::{DIB, create_DIArray, is_node_local_to_unit};
36use crate::builder::Builder;
37use crate::common::{AsCCharPtr, CodegenCx};
38use crate::debuginfo::di_builder::DIBuilderBox;
39use crate::llvm::debuginfo::{
40 DIArray, DIFile, DIFlags, DILexicalBlock, DILocation, DISPFlags, DIScope,
41 DITemplateTypeParameter, DIType, DIVariable,
42};
43use crate::llvm::{self, Value};
44
45mod di_builder;
46mod dwarf_const;
47mod gdb;
48pub(crate) mod metadata;
49mod namespace;
50mod utils;
51
52pub(crate) struct CodegenUnitDebugContext<'ll, 'tcx> {
54 builder: DIBuilderBox<'ll>,
55 created_files: RefCell<UnordMap<Option<(StableSourceFileId, SourceFileHash)>, &'ll DIFile>>,
56
57 type_map: metadata::TypeMap<'ll, 'tcx>,
58 adt_stack: RefCell<Vec<(DefId, GenericArgsRef<'tcx>)>>,
59 namespace_map: RefCell<DefIdMap<&'ll DIScope>>,
60 recursion_marker_type: OnceCell<&'ll DIType>,
61}
62
63impl<'ll, 'tcx> CodegenUnitDebugContext<'ll, 'tcx> {
64 pub(crate) fn new(llmod: &'ll llvm::Module, sess: &Session) -> Self {
65 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/923c95cdf5ba65cea505aa2ea829f578e1506ed8/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs:65",
"rustc_codegen_llvm::debuginfo", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/923c95cdf5ba65cea505aa2ea829f578e1506ed8/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs"),
::tracing_core::__macro_support::Option::Some(65u32),
::tracing_core::__macro_support::Option::Some("rustc_codegen_llvm::debuginfo"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("CodegenUnitDebugContext::new")
as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!("CodegenUnitDebugContext::new");
66
67 match sess.target.debuginfo_kind {
68 DebuginfoKind::Dwarf | DebuginfoKind::DwarfDsym => {
69 llvm::add_module_flag_u32(
76 llmod,
77 llvm::ModuleFlagMergeBehavior::Max,
82 "Dwarf Version",
83 sess.dwarf_version(),
84 );
85 }
86 DebuginfoKind::Pdb => {
87 llvm::add_module_flag_u32(
89 llmod,
90 llvm::ModuleFlagMergeBehavior::Warning,
91 "CodeView",
92 1,
93 );
94 }
95 }
96
97 llvm::add_module_flag_u32(
99 llmod,
100 llvm::ModuleFlagMergeBehavior::Warning,
101 "Debug Info Version",
102 unsafe { llvm::LLVMRustDebugMetadataVersion() },
103 );
104
105 let builder = DIBuilderBox::new(llmod);
106 CodegenUnitDebugContext {
108 builder,
109 created_files: Default::default(),
110 type_map: Default::default(),
111 adt_stack: Default::default(),
112 namespace_map: RefCell::new(Default::default()),
113 recursion_marker_type: OnceCell::new(),
114 }
115 }
116
117 pub(crate) fn finalize(&self) {
118 unsafe { llvm::LLVMDIBuilderFinalize(self.builder.as_ref()) };
119 }
120}
121
122impl<'ll> Builder<'_, 'll, '_> {
123 pub(crate) fn get_dbg_loc(&self) -> Option<&'ll DILocation> {
124 unsafe { llvm::LLVMGetCurrentDebugLocation2(self.llbuilder) }
125 }
126}
127
128impl<'ll, 'tcx> DebugInfoBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
129 fn dbg_scope_fn(
130 &mut self,
131 instance: Instance<'tcx>,
132 fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
133 maybe_definition_llfn: Option<&'ll Value>,
134 ) -> &'ll DIScope {
135 let tcx = self.tcx;
136
137 let def_id = instance.def_id();
138 let (containing_scope, is_method) = get_containing_scope(self, instance);
139 let span = tcx.def_span(def_id);
140 let loc = self.lookup_debug_loc(span.lo());
141 let file_metadata = file_metadata(self, &loc.file);
142
143 let function_type_metadata =
144 create_subroutine_type(self, &get_function_signature(self, fn_abi, span));
145
146 let mut name = String::with_capacity(64);
147 type_names::push_item_name(tcx, def_id, false, &mut name);
148
149 let enclosing_fn_def_id = tcx.typeck_root_def_id(def_id);
151
152 let generics = tcx.generics_of(enclosing_fn_def_id);
156 let args = instance.args.truncate_to(tcx, generics);
157
158 type_names::push_generic_args(
159 tcx,
160 tcx.normalize_erasing_regions(self.typing_env(), Unnormalized::new_wip(args)),
161 &mut name,
162 );
163
164 let template_parameters = get_template_parameters(self, generics, args);
165
166 let linkage_name = &mangled_name_of_instance(self, instance).name;
167 let linkage_name = if &name == linkage_name { "" } else { linkage_name };
169
170 let scope_line = loc.line;
172
173 let mut flags = DIFlags::FlagPrototyped;
174
175 if fn_abi.ret.layout.is_uninhabited() {
176 flags |= DIFlags::FlagNoReturn;
177 }
178
179 let mut spflags = DISPFlags::SPFlagDefinition;
180 if is_node_local_to_unit(self, def_id) {
181 spflags |= DISPFlags::SPFlagLocalToUnit;
182 }
183 if self.sess().opts.optimize != config::OptLevel::No {
184 spflags |= DISPFlags::SPFlagOptimized;
185 }
186 if let Some((id, _)) = tcx.entry_fn(()) {
187 if id == def_id {
188 spflags |= DISPFlags::SPFlagMainSubprogram;
189 }
190 }
191
192 let decl = is_method.then(|| unsafe {
197 llvm::LLVMRustDIBuilderCreateMethod(
198 DIB(self),
199 containing_scope,
200 name.as_c_char_ptr(),
201 name.len(),
202 linkage_name.as_c_char_ptr(),
203 linkage_name.len(),
204 file_metadata,
205 loc.line,
206 function_type_metadata,
207 flags,
208 spflags & !DISPFlags::SPFlagDefinition,
209 template_parameters,
210 )
211 });
212
213 return unsafe {
214 llvm::LLVMRustDIBuilderCreateFunction(
215 DIB(self),
216 containing_scope,
217 name.as_c_char_ptr(),
218 name.len(),
219 linkage_name.as_c_char_ptr(),
220 linkage_name.len(),
221 file_metadata,
222 loc.line,
223 function_type_metadata,
224 scope_line,
225 flags,
226 spflags,
227 maybe_definition_llfn,
228 template_parameters,
229 decl,
230 )
231 };
232
233 fn get_function_signature<'ll, 'tcx>(
234 cx: &CodegenCx<'ll, 'tcx>,
235 fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
236 span: Span,
237 ) -> Vec<Option<&'ll llvm::Metadata>> {
238 if cx.sess().opts.debuginfo != DebugInfo::Full {
239 return ::alloc::vec::Vec::new()vec![];
240 }
241
242 let mut signature = Vec::with_capacity(fn_abi.args.len() + 1);
243
244 signature.push(if fn_abi.ret.is_ignore() {
246 None
247 } else {
248 Some(spanned_type_di_node(cx, fn_abi.ret.layout.ty, span))
249 });
250
251 if cx.sess().target.is_like_msvc {
253 signature.extend(fn_abi.args.iter().map(|arg| {
264 let t = arg.layout.ty;
265 let t = match t.kind() {
266 ty::Array(ct, _)
267 if (*ct == cx.tcx.types.u8) || cx.layout_of(*ct).is_zst() =>
268 {
269 Ty::new_imm_ptr(cx.tcx, *ct)
270 }
271 _ => t,
272 };
273 Some(spanned_type_di_node(cx, t, span))
274 }));
275 } else {
276 signature.extend(
277 fn_abi
278 .args
279 .iter()
280 .map(|arg| Some(spanned_type_di_node(cx, arg.layout.ty, span))),
281 );
282 }
283
284 signature
285 }
286
287 fn get_template_parameters<'ll, 'tcx>(
288 cx: &CodegenCx<'ll, 'tcx>,
289 generics: &ty::Generics,
290 args: GenericArgsRef<'tcx>,
291 ) -> &'ll DIArray {
292 if args.terms().next().is_none() {
293 return create_DIArray(DIB(cx), &[]);
294 }
295
296 let template_params: Vec<_> = if cx.sess().opts.debuginfo == DebugInfo::Full {
298 let names = get_parameter_names(cx, generics);
299 iter::zip(args, names)
300 .filter_map(|(kind, name)| {
301 kind.as_type().map(|ty| {
303 let actual_type = cx.tcx.normalize_erasing_regions(
304 cx.typing_env(),
305 Unnormalized::new_wip(ty),
306 );
307 let actual_type_metadata = type_di_node(cx, actual_type);
308 Some(cx.create_template_type_parameter(
309 name.as_str(),
310 actual_type_metadata,
311 ))
312 })
313 })
314 .collect()
315 } else {
316 ::alloc::vec::Vec::new()vec![]
317 };
318
319 create_DIArray(DIB(cx), &template_params)
320 }
321
322 fn get_parameter_names(cx: &CodegenCx<'_, '_>, generics: &ty::Generics) -> Vec<Symbol> {
323 let mut names = generics.parent.map_or_else(Vec::new, |def_id| {
324 get_parameter_names(cx, cx.tcx.generics_of(def_id))
325 });
326 names.extend(generics.own_params.iter().map(|param| param.name));
327 names
328 }
329
330 fn get_containing_scope<'ll, 'tcx>(
333 cx: &CodegenCx<'ll, 'tcx>,
334 instance: Instance<'tcx>,
335 ) -> (&'ll DIScope, bool) {
336 if let Some(imp_def_id) = cx.tcx.inherent_impl_of_assoc(instance.def_id()) {
342 let impl_self_ty = cx.tcx.instantiate_and_normalize_erasing_regions(
343 instance.args,
344 cx.typing_env(),
345 cx.tcx.type_of(imp_def_id),
346 );
347
348 if let ty::Adt(def, ..) = impl_self_ty.kind()
351 && !def.is_box()
352 {
353 if cx.sess().opts.debuginfo == DebugInfo::Full && !impl_self_ty.has_param() {
355 return (type_di_node(cx, impl_self_ty), true);
356 } else {
357 return (namespace::item_namespace(cx, def.did()), false);
358 }
359 }
360 }
361
362 let scope = namespace::item_namespace(
363 cx,
364 DefId {
365 krate: instance.def_id().krate,
366 index: cx
367 .tcx
368 .def_key(instance.def_id())
369 .parent
370 .expect("get_containing_scope: missing parent?"),
371 },
372 );
373 (scope, false)
374 }
375 }
376
377 fn dbg_create_lexical_block(
378 &mut self,
379 pos: BytePos,
380 parent_scope: &'ll DIScope,
381 ) -> &'ll DIScope {
382 let loc = self.lookup_debug_loc(pos);
383 let file_metadata = file_metadata(self, &loc.file);
384 unsafe {
385 llvm::LLVMDIBuilderCreateLexicalBlock(
386 DIB(self),
387 parent_scope,
388 file_metadata,
389 loc.line,
390 loc.col,
391 )
392 }
393 }
394
395 fn dbg_location_clone_with_discriminator(
396 &mut self,
397 loc: &'ll DILocation,
398 discriminator: u32,
399 ) -> Option<&'ll DILocation> {
400 unsafe { llvm::LLVMRustDILocationCloneWithBaseDiscriminator(loc, discriminator) }
401 }
402
403 fn dbg_loc(
404 &mut self,
405 scope: &'ll DIScope,
406 inlined_at: Option<&'ll DILocation>,
407 span: Span,
408 ) -> &'ll DILocation {
409 let (line, col) = if span.is_dummy() {
410 (0, 0)
411 } else {
412 let DebugLoc { line, col, .. } = self.lookup_debug_loc(span.lo());
413 (line, col)
414 };
415
416 unsafe { llvm::LLVMDIBuilderCreateDebugLocation(self.llcx, line, col, scope, inlined_at) }
417 }
418
419 fn extend_scope_to_file(
420 &mut self,
421 scope_metadata: &'ll DIScope,
422 file: &rustc_span::SourceFile,
423 ) -> &'ll DILexicalBlock {
424 metadata::extend_scope_to_file(self, scope_metadata, file)
425 }
426
427 fn create_dbg_var(
430 &mut self,
431 variable_name: Symbol,
432 variable_type: Ty<'tcx>,
433 scope_metadata: &'ll DIScope,
434 variable_kind: VariableKind,
435 span: Span,
436 ) -> &'ll DIVariable {
437 let loc = self.lookup_debug_loc(span.lo());
438 let file_metadata = file_metadata(self, &loc.file);
439
440 let type_metadata = spanned_type_di_node(self, variable_type, span);
441
442 let align = self.align_of(variable_type);
443
444 let name = variable_name.as_str();
445
446 match variable_kind {
447 ArgumentVariable(arg_index) => unsafe {
448 llvm::LLVMDIBuilderCreateParameterVariable(
449 DIB(self),
450 scope_metadata,
451 name.as_ptr(),
452 name.len(),
453 arg_index as c_uint,
454 file_metadata,
455 loc.line,
456 type_metadata,
457 llvm::Bool::TRUE, DIFlags::FlagZero,
459 )
460 },
461 LocalVariable => unsafe {
462 llvm::LLVMDIBuilderCreateAutoVariable(
463 DIB(self),
464 scope_metadata,
465 name.as_ptr(),
466 name.len(),
467 file_metadata,
468 loc.line,
469 type_metadata,
470 llvm::Bool::TRUE, DIFlags::FlagZero,
472 align.bits() as u32,
473 )
474 },
475 }
476 }
477
478 fn dbg_var_addr(
481 &mut self,
482 dbg_var: &'ll DIVariable,
483 dbg_loc: &'ll DILocation,
484 variable_alloca: Self::Value,
485 direct_offset: Size,
486 indirect_offsets: &[Size],
487 fragment: &Option<Range<Size>>,
488 ) {
489 use dwarf_const::{DW_OP_LLVM_fragment, DW_OP_deref, DW_OP_plus_uconst};
490
491 let mut addr_ops = SmallVec::<[u64; 8]>::new();
493
494 if direct_offset.bytes() > 0 {
495 addr_ops.push(DW_OP_plus_uconst);
496 addr_ops.push(direct_offset.bytes());
497 }
498 for &offset in indirect_offsets {
499 addr_ops.push(DW_OP_deref);
500 if offset.bytes() > 0 {
501 addr_ops.push(DW_OP_plus_uconst);
502 addr_ops.push(offset.bytes());
503 }
504 }
505 if let Some(fragment) = fragment {
506 addr_ops.push(DW_OP_LLVM_fragment);
509 addr_ops.push(fragment.start.bits());
510 addr_ops.push((fragment.end - fragment.start).bits());
511 }
512
513 let di_builder = DIB(self.cx());
514 let addr_expr = di_builder.create_expression(&addr_ops);
515 unsafe {
516 llvm::LLVMDIBuilderInsertDeclareRecordAtEnd(
517 di_builder,
518 variable_alloca,
519 dbg_var,
520 addr_expr,
521 dbg_loc,
522 self.llbb(),
523 )
524 };
525 }
526
527 fn dbg_var_value(
528 &mut self,
529 dbg_var: &'ll DIVariable,
530 dbg_loc: &'ll DILocation,
531 value: Self::Value,
532 direct_offset: Size,
533 indirect_offsets: &[Size],
534 fragment: &Option<Range<Size>>,
535 ) {
536 use dwarf_const::{DW_OP_LLVM_fragment, DW_OP_deref, DW_OP_plus_uconst, DW_OP_stack_value};
537
538 let mut addr_ops = SmallVec::<[u64; 8]>::new();
540
541 if direct_offset.bytes() > 0 {
542 addr_ops.push(DW_OP_plus_uconst);
543 addr_ops.push(direct_offset.bytes() as u64);
544 addr_ops.push(DW_OP_stack_value);
545 }
546 for &offset in indirect_offsets {
547 addr_ops.push(DW_OP_deref);
548 if offset.bytes() > 0 {
549 addr_ops.push(DW_OP_plus_uconst);
550 addr_ops.push(offset.bytes() as u64);
551 }
552 }
553 if let Some(fragment) = fragment {
554 addr_ops.push(DW_OP_LLVM_fragment);
557 addr_ops.push(fragment.start.bits() as u64);
558 addr_ops.push((fragment.end - fragment.start).bits() as u64);
559 }
560
561 let di_builder = DIB(self.cx());
562 let addr_expr = unsafe {
563 llvm::LLVMDIBuilderCreateExpression(di_builder, addr_ops.as_ptr(), addr_ops.len())
564 };
565 unsafe {
566 llvm::LLVMDIBuilderInsertDbgValueRecordAtEnd(
567 di_builder,
568 value,
569 dbg_var,
570 addr_expr,
571 dbg_loc,
572 self.llbb(),
573 );
574 }
575 }
576
577 fn set_dbg_loc(&mut self, dbg_loc: &'ll DILocation) {
578 unsafe {
579 llvm::LLVMSetCurrentDebugLocation2(self.llbuilder, dbg_loc);
580 }
581 }
582
583 fn clear_dbg_loc(&mut self) {
584 unsafe {
585 llvm::LLVMSetCurrentDebugLocation2(self.llbuilder, ptr::null());
586 }
587 }
588
589 fn insert_reference_to_gdb_debug_scripts_section_global(&mut self) {
590 gdb::insert_reference_to_gdb_debug_scripts_section_global(self)
591 }
592
593 fn set_var_name(&mut self, value: &'ll Value, name: &str) {
594 if self.sess().fewer_names() {
596 return;
597 }
598
599 let param_or_inst = unsafe {
602 llvm::LLVMIsAArgument(value).is_some() || llvm::LLVMIsAInstruction(value).is_some()
603 };
604 if !param_or_inst {
605 return;
606 }
607
608 if llvm::get_value_name(value).is_empty() {
612 llvm::set_value_name(value, name.as_bytes());
613 }
614 }
615
616 fn with_move_annotation<R>(
625 &mut self,
626 instance: ty::Instance<'tcx>,
627 f: impl FnOnce(&mut Self) -> R,
628 ) -> R {
629 let saved_loc = self.get_dbg_loc();
631
632 let fn_abi = self
635 .cx()
636 .tcx
637 .fn_abi_of_instance(
638 self.cx().typing_env().as_query_input((instance, ty::List::empty())),
639 )
640 .unwrap();
641
642 let di_scope = self.dbg_scope_fn(instance, fn_abi, None);
643
644 let fn_span = self.cx().tcx.def_span(instance.def_id());
649 let inlined_loc = self.dbg_loc(di_scope, saved_loc, fn_span);
650
651 self.set_dbg_loc(inlined_loc);
653
654 let result = f(self);
656
657 if let Some(loc) = saved_loc {
659 self.set_dbg_loc(loc);
660 } else {
661 self.clear_dbg_loc();
662 }
663
664 result
665 }
666}
667
668struct DebugLoc {
673 file: Arc<SourceFile>,
675 line: u32,
677 col: u32,
679}
680
681impl<'ll> CodegenCx<'ll, '_> {
682 fn lookup_debug_loc(&self, pos: BytePos) -> DebugLoc {
687 let (file, line, col) = match self.sess().source_map().lookup_line(pos) {
688 Ok(SourceFileAndLine { sf: file, line }) => {
689 let line_pos = file.lines()[line];
690
691 let line = (line + 1) as u32;
693 let col = (file.relative_position(pos) - line_pos).to_u32() + 1;
694
695 (file, line, col)
696 }
697 Err(file) => (file, UNKNOWN_LINE_NUMBER, UNKNOWN_COLUMN_NUMBER),
698 };
699
700 if self.sess().target.is_like_msvc {
704 DebugLoc { file, line, col: UNKNOWN_COLUMN_NUMBER }
705 } else {
706 DebugLoc { file, line, col }
707 }
708 }
709
710 fn create_template_type_parameter(
711 &self,
712 name: &str,
713 actual_type_metadata: &'ll DIType,
714 ) -> &'ll DITemplateTypeParameter {
715 unsafe {
716 llvm::LLVMRustDIBuilderCreateTemplateTypeParameter(
717 DIB(self),
718 None,
719 name.as_c_char_ptr(),
720 name.len(),
721 actual_type_metadata,
722 )
723 }
724 }
725
726 pub(crate) fn debuginfo_finalize(&self) {
728 if let Some(dbg_cx) = &self.dbg_cx {
729 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/923c95cdf5ba65cea505aa2ea829f578e1506ed8/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs:729",
"rustc_codegen_llvm::debuginfo", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/923c95cdf5ba65cea505aa2ea829f578e1506ed8/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs"),
::tracing_core::__macro_support::Option::Some(729u32),
::tracing_core::__macro_support::Option::Some("rustc_codegen_llvm::debuginfo"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("finalize")
as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!("finalize");
730
731 if gdb::needs_gdb_debug_scripts_section(self) {
732 gdb::get_or_insert_gdb_debug_scripts_section_global(self);
737 }
738
739 dbg_cx.finalize();
740 }
741 }
742}
743
744impl<'ll, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
745 fn create_vtable_debuginfo(
746 &self,
747 ty: Ty<'tcx>,
748 trait_ref: Option<ty::ExistentialTraitRef<'tcx>>,
749 vtable: Self::Value,
750 ) {
751 metadata::create_vtable_di_node(self, ty, trait_ref, vtable)
752 }
753}