Skip to main content

rustc_codegen_llvm/debuginfo/
mod.rs

1#![doc = "# Debug Info Module\n\nThis module serves the purpose of generating debug symbols. We use LLVM\'s\n[source level debugging](https://llvm.org/docs/SourceLevelDebugging.html)\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
52/// A context object for maintaining all state needed by the debuginfo module.
53pub(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 compiler/rustc_codegen_llvm/src/debuginfo/mod.rs:65",
                        "rustc_codegen_llvm::debuginfo", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("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                // Debuginfo generation in LLVM by default uses a higher
70                // version of dwarf than macOS currently understands. We can
71                // instruct LLVM to emit an older version of dwarf, however,
72                // for macOS to understand. For more info see #11352
73                // This can be overridden using --llvm-opts -dwarf-version,N.
74                // Android has the same issue (#22398)
75                llvm::add_module_flag_u32(
76                    llmod,
77                    // In the case where multiple CGUs with different dwarf version
78                    // values are being merged together, such as with cross-crate
79                    // LTO, then we want to use the highest version of dwarf
80                    // we can. This matches Clang's behavior as well.
81                    llvm::ModuleFlagMergeBehavior::Max,
82                    "Dwarf Version",
83                    sess.dwarf_version(),
84                );
85            }
86            DebuginfoKind::Pdb => {
87                // Indicate that we want CodeView debug information
88                llvm::add_module_flag_u32(
89                    llmod,
90                    llvm::ModuleFlagMergeBehavior::Warning,
91                    "CodeView",
92                    1,
93                );
94            }
95        }
96
97        // Prevent bitcode readers from deleting the debug info.
98        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        // DIBuilder inherits context from the module, so we'd better use the same one
107        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        // Find the enclosing function, in case this is a closure.
150        let enclosing_fn_def_id = tcx.typeck_root_def_id(def_id);
151
152        // We look up the generics of the enclosing function and truncate the args
153        // to their length in order to cut off extra stuff that might be in there for
154        // closures or coroutines.
155        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        // Omit the linkage_name if it is the same as subprogram name.
168        let linkage_name = if &name == linkage_name { "" } else { linkage_name };
169
170        // FIXME(eddyb) does this need to be separate from `loc.line` for some reason?
171        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        // When we're adding a method to a type DIE, we only want a DW_AT_declaration there, because
193        // LLVM LTO can't unify type definitions when a child DIE is a full subprogram definition.
194        // When we use this `decl` below, the subprogram definition gets created at the CU level
195        // with a DW_AT_specification pointing back to the type's declaration.
196        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            // Return type -- llvm::DIBuilder wants this at index 0
245            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            // Arguments types
252            if cx.sess().target.is_like_msvc {
253                // FIXME(#42800):
254                // There is a bug in MSDIA that leads to a crash when it encounters
255                // a fixed-size array of `u8` or something zero-sized in a
256                // function-type (see #40477).
257                // As a workaround, we replace those fixed-size arrays with a
258                // pointer-type. So a function `fn foo(a: u8, b: [u8; 4])` would
259                // appear as `fn foo(a: u8, b: *const u8)` in debuginfo,
260                // and a function `fn bar(x: [(); 7])` as `fn bar(x: *const ())`.
261                // This transformed type is wrong, but these function types are
262                // already inaccurate due to ABI adjustments (see #42800).
263                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.types().next().is_none() {
293                return create_DIArray(DIB(cx), &[]);
294            }
295
296            // Again, only create type information if full debuginfo is enabled
297            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| {
302                            let actual_type = cx.tcx.normalize_erasing_regions(
303                                cx.typing_env(),
304                                Unnormalized::new_wip(ty),
305                            );
306                            let actual_type_metadata = type_di_node(cx, actual_type);
307                            Some(cx.create_template_type_parameter(
308                                name.as_str(),
309                                actual_type_metadata,
310                            ))
311                        })
312                    })
313                    .collect()
314            } else {
315                ::alloc::vec::Vec::new()vec![]
316            };
317
318            create_DIArray(DIB(cx), &template_params)
319        }
320
321        fn get_parameter_names(cx: &CodegenCx<'_, '_>, generics: &ty::Generics) -> Vec<Symbol> {
322            let mut names = generics.parent.map_or_else(Vec::new, |def_id| {
323                get_parameter_names(cx, cx.tcx.generics_of(def_id))
324            });
325            names.extend(generics.own_params.iter().map(|param| param.name));
326            names
327        }
328
329        /// Returns a scope, plus `true` if that's a type scope for "class" methods,
330        /// otherwise `false` for plain namespace scopes.
331        fn get_containing_scope<'ll, 'tcx>(
332            cx: &CodegenCx<'ll, 'tcx>,
333            instance: Instance<'tcx>,
334        ) -> (&'ll DIScope, bool) {
335            // First, let's see if this is a method within an inherent impl. Because
336            // if yes, we want to make the result subroutine DIE a child of the
337            // subroutine's self-type.
338            // For trait method impls we still use the "parallel namespace"
339            // strategy
340            if let Some(imp_def_id) = cx.tcx.inherent_impl_of_assoc(instance.def_id()) {
341                let impl_self_ty = cx.tcx.instantiate_and_normalize_erasing_regions(
342                    instance.args,
343                    cx.typing_env(),
344                    cx.tcx.type_of(imp_def_id),
345                );
346
347                // Only "class" methods are generally understood by LLVM,
348                // so avoid methods on other types (e.g., `<*mut T>::null`).
349                if let ty::Adt(def, ..) = impl_self_ty.kind()
350                    && !def.is_box()
351                {
352                    // Again, only create type information if full debuginfo is enabled
353                    if cx.sess().opts.debuginfo == DebugInfo::Full && !impl_self_ty.has_param() {
354                        return (type_di_node(cx, impl_self_ty), true);
355                    } else {
356                        return (namespace::item_namespace(cx, def.did()), false);
357                    }
358                }
359            }
360
361            let scope = namespace::item_namespace(
362                cx,
363                DefId {
364                    krate: instance.def_id().krate,
365                    index: cx
366                        .tcx
367                        .def_key(instance.def_id())
368                        .parent
369                        .expect("get_containing_scope: missing parent?"),
370                },
371            );
372            (scope, false)
373        }
374    }
375
376    fn dbg_create_lexical_block(
377        &mut self,
378        pos: BytePos,
379        parent_scope: &'ll DIScope,
380    ) -> &'ll DIScope {
381        let loc = self.lookup_debug_loc(pos);
382        let file_metadata = file_metadata(self, &loc.file);
383        unsafe {
384            llvm::LLVMDIBuilderCreateLexicalBlock(
385                DIB(self),
386                parent_scope,
387                file_metadata,
388                loc.line,
389                loc.col,
390            )
391        }
392    }
393
394    fn dbg_location_clone_with_discriminator(
395        &mut self,
396        loc: &'ll DILocation,
397        discriminator: u32,
398    ) -> Option<&'ll DILocation> {
399        unsafe { llvm::LLVMRustDILocationCloneWithBaseDiscriminator(loc, discriminator) }
400    }
401
402    fn dbg_loc(
403        &mut self,
404        scope: &'ll DIScope,
405        inlined_at: Option<&'ll DILocation>,
406        span: Span,
407    ) -> &'ll DILocation {
408        // When emitting debugging information, DWARF (i.e. everything but MSVC)
409        // treats line 0 as a magic value meaning that the code could not be
410        // attributed to any line in the source. That's also exactly what dummy
411        // spans are. Make that equivalence here, rather than passing dummy spans
412        // to lookup_debug_loc, which will return line 1 for them.
413        let (line, col) = if span.is_dummy() && !self.sess().target.is_like_msvc {
414            (0, 0)
415        } else {
416            let DebugLoc { line, col, .. } = self.lookup_debug_loc(span.lo());
417            (line, col)
418        };
419
420        unsafe { llvm::LLVMDIBuilderCreateDebugLocation(self.llcx, line, col, scope, inlined_at) }
421    }
422
423    fn extend_scope_to_file(
424        &mut self,
425        scope_metadata: &'ll DIScope,
426        file: &rustc_span::SourceFile,
427    ) -> &'ll DILexicalBlock {
428        metadata::extend_scope_to_file(self, scope_metadata, file)
429    }
430
431    // FIXME(eddyb) find a common convention for all of the debuginfo-related
432    // names (choose between `dbg`, `debug`, `debuginfo`, `debug_info` etc.).
433    fn create_dbg_var(
434        &mut self,
435        variable_name: Symbol,
436        variable_type: Ty<'tcx>,
437        scope_metadata: &'ll DIScope,
438        variable_kind: VariableKind,
439        span: Span,
440    ) -> &'ll DIVariable {
441        let loc = self.lookup_debug_loc(span.lo());
442        let file_metadata = file_metadata(self, &loc.file);
443
444        let type_metadata = spanned_type_di_node(self, variable_type, span);
445
446        let align = self.align_of(variable_type);
447
448        let name = variable_name.as_str();
449
450        match variable_kind {
451            ArgumentVariable(arg_index) => unsafe {
452                llvm::LLVMDIBuilderCreateParameterVariable(
453                    DIB(self),
454                    scope_metadata,
455                    name.as_ptr(),
456                    name.len(),
457                    arg_index as c_uint,
458                    file_metadata,
459                    loc.line,
460                    type_metadata,
461                    llvm::Bool::TRUE, // (preserve descriptor during optimizations)
462                    DIFlags::FlagZero,
463                )
464            },
465            LocalVariable => unsafe {
466                llvm::LLVMDIBuilderCreateAutoVariable(
467                    DIB(self),
468                    scope_metadata,
469                    name.as_ptr(),
470                    name.len(),
471                    file_metadata,
472                    loc.line,
473                    type_metadata,
474                    llvm::Bool::TRUE, // (preserve descriptor during optimizations)
475                    DIFlags::FlagZero,
476                    align.bits() as u32,
477                )
478            },
479        }
480    }
481
482    // FIXME(eddyb) find a common convention for all of the debuginfo-related
483    // names (choose between `dbg`, `debug`, `debuginfo`, `debug_info` etc.).
484    fn dbg_var_addr(
485        &mut self,
486        dbg_var: &'ll DIVariable,
487        dbg_loc: &'ll DILocation,
488        variable_alloca: Self::Value,
489        direct_offset: Size,
490        indirect_offsets: &[Size],
491        fragment: &Option<Range<Size>>,
492    ) {
493        use dwarf_const::{DW_OP_LLVM_fragment, DW_OP_deref, DW_OP_plus_uconst};
494
495        // Convert the direct and indirect offsets and fragment byte range to address ops.
496        let mut addr_ops = SmallVec::<[u64; 8]>::new();
497
498        if direct_offset.bytes() > 0 {
499            addr_ops.push(DW_OP_plus_uconst);
500            addr_ops.push(direct_offset.bytes());
501        }
502        for &offset in indirect_offsets {
503            addr_ops.push(DW_OP_deref);
504            if offset.bytes() > 0 {
505                addr_ops.push(DW_OP_plus_uconst);
506                addr_ops.push(offset.bytes());
507            }
508        }
509        if let Some(fragment) = fragment {
510            // `DW_OP_LLVM_fragment` takes as arguments the fragment's
511            // offset and size, both of them in bits.
512            addr_ops.push(DW_OP_LLVM_fragment);
513            addr_ops.push(fragment.start.bits());
514            addr_ops.push((fragment.end - fragment.start).bits());
515        }
516
517        let di_builder = DIB(self.cx());
518        let addr_expr = di_builder.create_expression(&addr_ops);
519        unsafe {
520            llvm::LLVMDIBuilderInsertDeclareRecordAtEnd(
521                di_builder,
522                variable_alloca,
523                dbg_var,
524                addr_expr,
525                dbg_loc,
526                self.llbb(),
527            )
528        };
529    }
530
531    fn dbg_var_value(
532        &mut self,
533        dbg_var: &'ll DIVariable,
534        dbg_loc: &'ll DILocation,
535        value: Self::Value,
536        direct_offset: Size,
537        indirect_offsets: &[Size],
538        fragment: &Option<Range<Size>>,
539    ) {
540        use dwarf_const::{DW_OP_LLVM_fragment, DW_OP_deref, DW_OP_plus_uconst, DW_OP_stack_value};
541
542        // Convert the direct and indirect offsets and fragment byte range to address ops.
543        let mut addr_ops = SmallVec::<[u64; 8]>::new();
544
545        if direct_offset.bytes() > 0 {
546            addr_ops.push(DW_OP_plus_uconst);
547            addr_ops.push(direct_offset.bytes() as u64);
548            addr_ops.push(DW_OP_stack_value);
549        }
550        for &offset in indirect_offsets {
551            addr_ops.push(DW_OP_deref);
552            if offset.bytes() > 0 {
553                addr_ops.push(DW_OP_plus_uconst);
554                addr_ops.push(offset.bytes() as u64);
555            }
556        }
557        if let Some(fragment) = fragment {
558            // `DW_OP_LLVM_fragment` takes as arguments the fragment's
559            // offset and size, both of them in bits.
560            addr_ops.push(DW_OP_LLVM_fragment);
561            addr_ops.push(fragment.start.bits() as u64);
562            addr_ops.push((fragment.end - fragment.start).bits() as u64);
563        }
564
565        let di_builder = DIB(self.cx());
566        let addr_expr = unsafe {
567            llvm::LLVMDIBuilderCreateExpression(di_builder, addr_ops.as_ptr(), addr_ops.len())
568        };
569        unsafe {
570            llvm::LLVMDIBuilderInsertDbgValueRecordAtEnd(
571                di_builder,
572                value,
573                dbg_var,
574                addr_expr,
575                dbg_loc,
576                self.llbb(),
577            );
578        }
579    }
580
581    fn set_dbg_loc(&mut self, dbg_loc: &'ll DILocation) {
582        unsafe {
583            llvm::LLVMSetCurrentDebugLocation2(self.llbuilder, dbg_loc);
584        }
585    }
586
587    fn clear_dbg_loc(&mut self) {
588        unsafe {
589            llvm::LLVMSetCurrentDebugLocation2(self.llbuilder, ptr::null());
590        }
591    }
592
593    fn insert_reference_to_gdb_debug_scripts_section_global(&mut self) {
594        gdb::insert_reference_to_gdb_debug_scripts_section_global(self)
595    }
596
597    fn set_var_name(&mut self, value: &'ll Value, name: &str) {
598        // Avoid wasting time if LLVM value names aren't even enabled.
599        if self.sess().fewer_names() {
600            return;
601        }
602
603        // Only function parameters and instructions are local to a function,
604        // don't change the name of anything else (e.g. globals).
605        let param_or_inst = unsafe {
606            llvm::LLVMIsAArgument(value).is_some() || llvm::LLVMIsAInstruction(value).is_some()
607        };
608        if !param_or_inst {
609            return;
610        }
611
612        // Avoid replacing the name if it already exists.
613        // While we could combine the names somehow, it'd
614        // get noisy quick, and the usefulness is dubious.
615        if llvm::get_value_name(value).is_empty() {
616            llvm::set_value_name(value, name.as_bytes());
617        }
618    }
619
620    /// Annotate move/copy operations with debug info for profiling.
621    ///
622    /// This creates a temporary debug scope that makes the move/copy appear as an inlined call to
623    /// `compiler_move<T, SIZE>()` or `compiler_copy<T, SIZE>()`. The provided closure is executed
624    /// with this temporary debug location active.
625    ///
626    /// The `instance` parameter should be the monomorphized instance of the `compiler_move` or
627    /// `compiler_copy` function with the actual type and size.
628    fn with_move_annotation<R>(
629        &mut self,
630        instance: ty::Instance<'tcx>,
631        f: impl FnOnce(&mut Self) -> R,
632    ) -> R {
633        // Save the current debug location
634        let saved_loc = self.get_dbg_loc();
635
636        // Create a DIScope for the compiler_move/compiler_copy function
637        // We use the function's FnAbi for debug info generation
638        let fn_abi = self
639            .cx()
640            .tcx
641            .fn_abi_of_instance(
642                self.cx().typing_env().as_query_input((instance, ty::List::empty())),
643            )
644            .unwrap();
645
646        let di_scope = self.dbg_scope_fn(instance, fn_abi, None);
647
648        // Create an inlined debug location:
649        // - scope: the compiler_move/compiler_copy function
650        // - inlined_at: the current location (where the move/copy actually occurs)
651        // - span: use the function's definition span
652        let fn_span = self.cx().tcx.def_span(instance.def_id());
653        let inlined_loc = self.dbg_loc(di_scope, saved_loc, fn_span);
654
655        // Set the temporary debug location
656        self.set_dbg_loc(inlined_loc);
657
658        // Execute the closure (which will generate the memcpy)
659        let result = f(self);
660
661        // Restore the original debug location
662        if let Some(loc) = saved_loc {
663            self.set_dbg_loc(loc);
664        } else {
665            self.clear_dbg_loc();
666        }
667
668        result
669    }
670}
671
672/// A source code location used to generate debug information.
673// FIXME(eddyb) rename this to better indicate it's a duplicate of
674// `rustc_span::Loc` rather than `DILocation`, perhaps by making
675// `lookup_char_pos` return the right information instead.
676struct DebugLoc {
677    /// Information about the original source file.
678    file: Arc<SourceFile>,
679    /// The (1-based) line number.
680    line: u32,
681    /// The (1-based) column number.
682    col: u32,
683}
684
685impl<'ll> CodegenCx<'ll, '_> {
686    /// Looks up debug source information about a `BytePos`.
687    // FIXME(eddyb) rename this to better indicate it's a duplicate of
688    // `lookup_char_pos` rather than `dbg_loc`, perhaps by making
689    // `lookup_char_pos` return the right information instead.
690    fn lookup_debug_loc(&self, pos: BytePos) -> DebugLoc {
691        let (file, line, col) = match self.sess().source_map().lookup_line(pos) {
692            Ok(SourceFileAndLine { sf: file, line }) => {
693                let line_pos = file.lines()[line];
694
695                // Use 1-based indexing.
696                let line = (line + 1) as u32;
697                let col = (file.relative_position(pos) - line_pos).to_u32() + 1;
698
699                (file, line, col)
700            }
701            Err(file) => (file, UNKNOWN_LINE_NUMBER, UNKNOWN_COLUMN_NUMBER),
702        };
703
704        // For MSVC, omit the column number.
705        // Otherwise, emit it. This mimics clang behaviour.
706        // See discussion in https://github.com/rust-lang/rust/issues/42921
707        if self.sess().target.is_like_msvc {
708            DebugLoc { file, line, col: UNKNOWN_COLUMN_NUMBER }
709        } else {
710            DebugLoc { file, line, col }
711        }
712    }
713
714    fn create_template_type_parameter(
715        &self,
716        name: &str,
717        actual_type_metadata: &'ll DIType,
718    ) -> &'ll DITemplateTypeParameter {
719        unsafe {
720            llvm::LLVMRustDIBuilderCreateTemplateTypeParameter(
721                DIB(self),
722                None,
723                name.as_c_char_ptr(),
724                name.len(),
725                actual_type_metadata,
726            )
727        }
728    }
729
730    /// Creates any deferred debug metadata nodes
731    pub(crate) fn debuginfo_finalize(&self) {
732        if let Some(dbg_cx) = &self.dbg_cx {
733            {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_codegen_llvm/src/debuginfo/mod.rs:733",
                        "rustc_codegen_llvm::debuginfo", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_codegen_llvm/src/debuginfo/mod.rs"),
                        ::tracing_core::__macro_support::Option::Some(733u32),
                        ::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");
734
735            if gdb::needs_gdb_debug_scripts_section(self) {
736                // Add a .debug_gdb_scripts section to this compile-unit. This will
737                // cause GDB to try and load the gdb_load_rust_pretty_printers.py file,
738                // which activates the Rust pretty printers for binary this section is
739                // contained in.
740                gdb::get_or_insert_gdb_debug_scripts_section_global(self);
741            }
742
743            dbg_cx.finalize();
744        }
745    }
746}
747
748impl<'ll, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
749    fn create_vtable_debuginfo(
750        &self,
751        ty: Ty<'tcx>,
752        trait_ref: Option<ty::ExistentialTraitRef<'tcx>>,
753        vtable: Self::Value,
754    ) {
755        metadata::create_vtable_di_node(self, ty, trait_ref, vtable)
756    }
757}