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 /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                // 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.terms().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                        // FIXME: debug info for consts (using `createTemplateValueParameter`?)
302                        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        /// Returns a scope, plus `true` if that's a type scope for "class" methods,
331        /// otherwise `false` for plain namespace scopes.
332        fn get_containing_scope<'ll, 'tcx>(
333            cx: &CodegenCx<'ll, 'tcx>,
334            instance: Instance<'tcx>,
335        ) -> (&'ll DIScope, bool) {
336            // First, let's see if this is a method within an inherent impl. Because
337            // if yes, we want to make the result subroutine DIE a child of the
338            // subroutine's self-type.
339            // For trait method impls we still use the "parallel namespace"
340            // strategy
341            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                // Only "class" methods are generally understood by LLVM,
349                // so avoid methods on other types (e.g., `<*mut T>::null`).
350                if let ty::Adt(def, ..) = impl_self_ty.kind()
351                    && !def.is_box()
352                {
353                    // Again, only create type information if full debuginfo is enabled
354                    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    // FIXME(eddyb) find a common convention for all of the debuginfo-related
428    // names (choose between `dbg`, `debug`, `debuginfo`, `debug_info` etc.).
429    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, // (preserve descriptor during optimizations)
458                    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, // (preserve descriptor during optimizations)
471                    DIFlags::FlagZero,
472                    align.bits() as u32,
473                )
474            },
475        }
476    }
477
478    // FIXME(eddyb) find a common convention for all of the debuginfo-related
479    // names (choose between `dbg`, `debug`, `debuginfo`, `debug_info` etc.).
480    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        // Convert the direct and indirect offsets and fragment byte range to address ops.
492        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            // `DW_OP_LLVM_fragment` takes as arguments the fragment's
507            // offset and size, both of them in bits.
508            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        // Convert the direct and indirect offsets and fragment byte range to address ops.
539        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            // `DW_OP_LLVM_fragment` takes as arguments the fragment's
555            // offset and size, both of them in bits.
556            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        // Avoid wasting time if LLVM value names aren't even enabled.
595        if self.sess().fewer_names() {
596            return;
597        }
598
599        // Only function parameters and instructions are local to a function,
600        // don't change the name of anything else (e.g. globals).
601        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        // Avoid replacing the name if it already exists.
609        // While we could combine the names somehow, it'd
610        // get noisy quick, and the usefulness is dubious.
611        if llvm::get_value_name(value).is_empty() {
612            llvm::set_value_name(value, name.as_bytes());
613        }
614    }
615
616    /// Annotate move/copy operations with debug info for profiling.
617    ///
618    /// This creates a temporary debug scope that makes the move/copy appear as an inlined call to
619    /// `compiler_move<T, SIZE>()` or `compiler_copy<T, SIZE>()`. The provided closure is executed
620    /// with this temporary debug location active.
621    ///
622    /// The `instance` parameter should be the monomorphized instance of the `compiler_move` or
623    /// `compiler_copy` function with the actual type and size.
624    fn with_move_annotation<R>(
625        &mut self,
626        instance: ty::Instance<'tcx>,
627        f: impl FnOnce(&mut Self) -> R,
628    ) -> R {
629        // Save the current debug location
630        let saved_loc = self.get_dbg_loc();
631
632        // Create a DIScope for the compiler_move/compiler_copy function
633        // We use the function's FnAbi for debug info generation
634        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        // Create an inlined debug location:
645        // - scope: the compiler_move/compiler_copy function
646        // - inlined_at: the current location (where the move/copy actually occurs)
647        // - span: use the function's definition span
648        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        // Set the temporary debug location
652        self.set_dbg_loc(inlined_loc);
653
654        // Execute the closure (which will generate the memcpy)
655        let result = f(self);
656
657        // Restore the original debug location
658        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
668/// A source code location used to generate debug information.
669// FIXME(eddyb) rename this to better indicate it's a duplicate of
670// `rustc_span::Loc` rather than `DILocation`, perhaps by making
671// `lookup_char_pos` return the right information instead.
672struct DebugLoc {
673    /// Information about the original source file.
674    file: Arc<SourceFile>,
675    /// The (1-based) line number.
676    line: u32,
677    /// The (1-based) column number.
678    col: u32,
679}
680
681impl<'ll> CodegenCx<'ll, '_> {
682    /// Looks up debug source information about a `BytePos`.
683    // FIXME(eddyb) rename this to better indicate it's a duplicate of
684    // `lookup_char_pos` rather than `dbg_loc`, perhaps by making
685    // `lookup_char_pos` return the right information instead.
686    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                // Use 1-based indexing.
692                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        // For MSVC, omit the column number.
701        // Otherwise, emit it. This mimics clang behaviour.
702        // See discussion in https://github.com/rust-lang/rust/issues/42921
703        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    /// Creates any deferred debug metadata nodes
727    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                // Add a .debug_gdb_scripts section to this compile-unit. This will
733                // cause GDB to try and load the gdb_load_rust_pretty_printers.py file,
734                // which activates the Rust pretty printers for binary this section is
735                // contained in.
736                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}