authorbors <bors@rust-lang.org> 2026-06-30 12:41:46 UTC
committerbors <bors@rust-lang.org> 2026-06-30 12:41:46 UTC
logf46ec5218fe7829ac18323b5ee0b409a63169f27
tree963eb7d1c0b8d9f06633c563aa30653e5df0afd6
parent51657149e91586571ff1c463bc58239daa1a88d2
parent8b54e845eec96a45278065e0fbfa3b8647a685f5

Auto merge of #158610 - JonathanBrouwer:rollup-YAPZ5ee, r=JonathanBrouwer

Rollup of 5 pull requests Successful merges: - rust-lang/rust#158600 (Fix `rustc --unpretty=expanded` emit of `[const] [unsafe] impl Trait for`) - rust-lang/rust#158560 (Move per-function debuginfo methods from codegen to builder methods) - rust-lang/rust#158563 (Test(lib/net): Fix `hostname_smoketest` for Win7) - rust-lang/rust#158571 (Update books) - rust-lang/rust#158592 (tests: only run `lexical-scope-in-match.rs` for LLDB >= 21)

14 files changed, 530 insertions(+), 524 deletions(-)

compiler/rustc_ast_pretty/src/pprust/state/item.rs+1-1
......@@ -344,9 +344,9 @@ impl<'a> State<'a> {
344344 let ast::TraitImplHeader { defaultness, safety, polarity, ref trait_ref } =
345345 *of_trait;
346346 self.print_defaultness(defaultness);
347 self.print_constness(*constness);
347348 self.print_safety(safety);
348349 impl_generics(self);
349 self.print_constness(*constness);
350350 if let ast::ImplPolarity::Negative(_) = polarity {
351351 self.word("!");
352352 }
compiler/rustc_codegen_gcc/src/base.rs-1
......@@ -7,7 +7,6 @@ use gccjit::{CType, Context, FunctionType, GlobalKind};
77use rustc_codegen_ssa::ModuleCodegen;
88use rustc_codegen_ssa::base::maybe_create_entry_wrapper;
99use rustc_codegen_ssa::mono_item::MonoItemExt;
10use rustc_codegen_ssa::traits::DebugInfoCodegenMethods;
1110use rustc_hir::attrs::{AttributeKind, Linkage};
1211use rustc_hir::find_attr;
1312use rustc_middle::dep_graph;
compiler/rustc_codegen_gcc/src/debuginfo.rs+64-64
......@@ -16,6 +16,66 @@ pub(super) const UNKNOWN_LINE_NUMBER: u32 = 0;
1616pub(super) const UNKNOWN_COLUMN_NUMBER: u32 = 0;
1717
1818impl<'a, 'gcc, 'tcx> DebugInfoBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
19 fn dbg_scope_fn(
20 &mut self,
21 _instance: Instance<'tcx>,
22 _fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
23 _maybe_definition_llfn: Option<Function<'gcc>>,
24 ) -> Self::DIScope {
25 // FIXME(antoyo): implement.
26 }
27
28 fn dbg_create_lexical_block(
29 &mut self,
30 _pos: BytePos,
31 _parent_scope: Self::DIScope,
32 ) -> Self::DIScope {
33 }
34
35 fn dbg_location_clone_with_discriminator(
36 &mut self,
37 loc: Self::DILocation,
38 _discriminator: u32,
39 ) -> Option<Self::DILocation> {
40 Some(loc)
41 }
42
43 fn extend_scope_to_file(
44 &mut self,
45 _scope_metadata: Self::DIScope,
46 _file: &SourceFile,
47 ) -> Self::DIScope {
48 // FIXME(antoyo): implement.
49 }
50
51 fn dbg_loc(
52 &mut self,
53 _scope: Self::DIScope,
54 _inlined_at: Option<Self::DILocation>,
55 span: Span,
56 ) -> Self::DILocation {
57 let pos = span.lo();
58 let DebugLoc { file, line, col } = self.lookup_debug_loc(pos);
59 match file.name {
60 rustc_span::FileName::Real(ref name) => self.context.new_location(
61 name.path(rustc_span::RemapPathScopeComponents::DEBUGINFO).to_string_lossy(),
62 line as i32,
63 col as i32,
64 ),
65 _ => Location::null(),
66 }
67 }
68
69 fn create_dbg_var(
70 &mut self,
71 _variable_name: Symbol,
72 _variable_type: Ty<'tcx>,
73 _scope_metadata: Self::DIScope,
74 _variable_kind: VariableKind,
75 _span: Span,
76 ) -> Self::DIVariable {
77 }
78
1979 // FIXME(eddyb) find a common convention for all of the debuginfo-related
2080 // names (choose between `dbg`, `debug`, `debuginfo`, `debug_info` etc.).
2181 fn dbg_var_addr(
......@@ -103,6 +163,10 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
103163 DebugLoc { file, line, col }
104164 }
105165 }
166
167 pub(crate) fn debuginfo_finalize(&self) {
168 self.context.set_debug_info(true)
169 }
106170}
107171
108172impl<'gcc, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
......@@ -114,68 +178,4 @@ impl<'gcc, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
114178 ) {
115179 // FIXME(antoyo)
116180 }
117
118 fn dbg_create_lexical_block(
119 &self,
120 _pos: BytePos,
121 _parent_scope: Self::DIScope,
122 ) -> Self::DIScope {
123 }
124
125 fn dbg_location_clone_with_discriminator(
126 &self,
127 loc: Self::DILocation,
128 _discriminator: u32,
129 ) -> Option<Self::DILocation> {
130 Some(loc)
131 }
132
133 fn extend_scope_to_file(
134 &self,
135 _scope_metadata: Self::DIScope,
136 _file: &SourceFile,
137 ) -> Self::DIScope {
138 // FIXME(antoyo): implement.
139 }
140
141 fn debuginfo_finalize(&self) {
142 self.context.set_debug_info(true)
143 }
144
145 fn create_dbg_var(
146 &self,
147 _variable_name: Symbol,
148 _variable_type: Ty<'tcx>,
149 _scope_metadata: Self::DIScope,
150 _variable_kind: VariableKind,
151 _span: Span,
152 ) -> Self::DIVariable {
153 }
154
155 fn dbg_scope_fn(
156 &self,
157 _instance: Instance<'tcx>,
158 _fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
159 _maybe_definition_llfn: Option<Function<'gcc>>,
160 ) -> Self::DIScope {
161 // FIXME(antoyo): implement.
162 }
163
164 fn dbg_loc(
165 &self,
166 _scope: Self::DIScope,
167 _inlined_at: Option<Self::DILocation>,
168 span: Span,
169 ) -> Self::DILocation {
170 let pos = span.lo();
171 let DebugLoc { file, line, col } = self.lookup_debug_loc(pos);
172 match file.name {
173 rustc_span::FileName::Real(ref name) => self.context.new_location(
174 name.path(rustc_span::RemapPathScopeComponents::DEBUGINFO).to_string_lossy(),
175 line as i32,
176 col as i32,
177 ),
178 _ => Location::null(),
179 }
180 }
181181}
compiler/rustc_codegen_llvm/src/allocator.rs+2-2
......@@ -99,9 +99,9 @@ pub(crate) unsafe fn codegen(
9999 );
100100
101101 if tcx.sess.opts.debuginfo != DebugInfo::None {
102 let dbg_cx = debuginfo::CodegenUnitDebugContext::new(cx.llmod);
102 let dbg_cx = debuginfo::CodegenUnitDebugContext::new(cx.llmod, tcx.sess);
103103 debuginfo::metadata::build_compile_unit_di_node(tcx, module_name, &dbg_cx);
104 dbg_cx.finalize(tcx.sess);
104 dbg_cx.finalize();
105105 }
106106}
107107
compiler/rustc_codegen_llvm/src/context.rs+1-1
......@@ -645,7 +645,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
645645 tcx.sess.instrument_coverage().then(coverageinfo::CguCoverageContext::new);
646646
647647 let dbg_cx = if tcx.sess.opts.debuginfo != DebugInfo::None {
648 let dctx = debuginfo::CodegenUnitDebugContext::new(llmod);
648 let dctx = debuginfo::CodegenUnitDebugContext::new(llmod, tcx.sess);
649649 debuginfo::metadata::build_compile_unit_di_node(
650650 tcx,
651651 codegen_unit.name().as_str(),
compiler/rustc_codegen_llvm/src/debuginfo/mod.rs+405-406
......@@ -51,7 +51,6 @@ mod utils;
5151
5252/// A context object for maintaining all state needed by the debuginfo module.
5353pub(crate) struct CodegenUnitDebugContext<'ll, 'tcx> {
54 llmod: &'ll llvm::Module,
5554 builder: DIBuilderBox<'ll>,
5655 created_files: RefCell<UnordMap<Option<(StableSourceFileId, SourceFileHash)>, &'ll DIFile>>,
5756
......@@ -62,23 +61,8 @@ pub(crate) struct CodegenUnitDebugContext<'ll, 'tcx> {
6261}
6362
6463impl<'ll, 'tcx> CodegenUnitDebugContext<'ll, 'tcx> {
65 pub(crate) fn new(llmod: &'ll llvm::Module) -> Self {
64 pub(crate) fn new(llmod: &'ll llvm::Module, sess: &Session) -> Self {
6665 debug!("CodegenUnitDebugContext::new");
67 let builder = DIBuilderBox::new(llmod);
68 // DIBuilder inherits context from the module, so we'd better use the same one
69 CodegenUnitDebugContext {
70 llmod,
71 builder,
72 created_files: Default::default(),
73 type_map: Default::default(),
74 adt_stack: Default::default(),
75 namespace_map: RefCell::new(Default::default()),
76 recursion_marker_type: OnceCell::new(),
77 }
78 }
79
80 pub(crate) fn finalize(&self, sess: &Session) {
81 unsafe { llvm::LLVMDIBuilderFinalize(self.builder.as_ref()) };
8266
8367 match sess.target.debuginfo_kind {
8468 DebuginfoKind::Dwarf | DebuginfoKind::DwarfDsym => {
......@@ -89,7 +73,7 @@ impl<'ll, 'tcx> CodegenUnitDebugContext<'ll, 'tcx> {
8973 // This can be overridden using --llvm-opts -dwarf-version,N.
9074 // Android has the same issue (#22398)
9175 llvm::add_module_flag_u32(
92 self.llmod,
76 llmod,
9377 // In the case where multiple CGUs with different dwarf version
9478 // values are being merged together, such as with cross-crate
9579 // LTO, then we want to use the highest version of dwarf
......@@ -102,7 +86,7 @@ impl<'ll, 'tcx> CodegenUnitDebugContext<'ll, 'tcx> {
10286 DebuginfoKind::Pdb => {
10387 // Indicate that we want CodeView debug information
10488 llvm::add_module_flag_u32(
105 self.llmod,
89 llmod,
10690 llvm::ModuleFlagMergeBehavior::Warning,
10791 "CodeView",
10892 1,
......@@ -112,28 +96,26 @@ impl<'ll, 'tcx> CodegenUnitDebugContext<'ll, 'tcx> {
11296
11397 // Prevent bitcode readers from deleting the debug info.
11498 llvm::add_module_flag_u32(
115 self.llmod,
99 llmod,
116100 llvm::ModuleFlagMergeBehavior::Warning,
117101 "Debug Info Version",
118102 unsafe { llvm::LLVMRustDebugMetadataVersion() },
119103 );
120 }
121}
122104
123/// Creates any deferred debug metadata nodes
124pub(crate) fn finalize(cx: &CodegenCx<'_, '_>) {
125 if let Some(dbg_cx) = &cx.dbg_cx {
126 debug!("finalize");
127
128 if gdb::needs_gdb_debug_scripts_section(cx) {
129 // Add a .debug_gdb_scripts section to this compile-unit. This will
130 // cause GDB to try and load the gdb_load_rust_pretty_printers.py file,
131 // which activates the Rust pretty printers for binary this section is
132 // contained in.
133 gdb::get_or_insert_gdb_debug_scripts_section_global(cx);
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(),
134114 }
115 }
135116
136 dbg_cx.finalize(cx.sess());
117 pub(crate) fn finalize(&self) {
118 unsafe { llvm::LLVMDIBuilderFinalize(self.builder.as_ref()) };
137119 }
138120}
139121
......@@ -144,381 +126,109 @@ impl<'ll> Builder<'_, 'll, '_> {
144126}
145127
146128impl<'ll, 'tcx> DebugInfoBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
147 // FIXME(eddyb) find a common convention for all of the debuginfo-related
148 // names (choose between `dbg`, `debug`, `debuginfo`, `debug_info` etc.).
149 fn dbg_var_addr(
129 fn dbg_scope_fn(
150130 &mut self,
151 dbg_var: &'ll DIVariable,
152 dbg_loc: &'ll DILocation,
153 variable_alloca: Self::Value,
154 direct_offset: Size,
155 indirect_offsets: &[Size],
156 fragment: &Option<Range<Size>>,
157 ) {
158 use dwarf_const::{DW_OP_LLVM_fragment, DW_OP_deref, DW_OP_plus_uconst};
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;
159136
160 // Convert the direct and indirect offsets and fragment byte range to address ops.
161 let mut addr_ops = SmallVec::<[u64; 8]>::new();
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);
162142
163 if direct_offset.bytes() > 0 {
164 addr_ops.push(DW_OP_plus_uconst);
165 addr_ops.push(direct_offset.bytes());
166 }
167 for &offset in indirect_offsets {
168 addr_ops.push(DW_OP_deref);
169 if offset.bytes() > 0 {
170 addr_ops.push(DW_OP_plus_uconst);
171 addr_ops.push(offset.bytes());
172 }
173 }
174 if let Some(fragment) = fragment {
175 // `DW_OP_LLVM_fragment` takes as arguments the fragment's
176 // offset and size, both of them in bits.
177 addr_ops.push(DW_OP_LLVM_fragment);
178 addr_ops.push(fragment.start.bits());
179 addr_ops.push((fragment.end - fragment.start).bits());
180 }
143 let function_type_metadata =
144 create_subroutine_type(self, &get_function_signature(self, fn_abi));
181145
182 let di_builder = DIB(self.cx());
183 let addr_expr = di_builder.create_expression(&addr_ops);
184 unsafe {
185 llvm::LLVMDIBuilderInsertDeclareRecordAtEnd(
186 di_builder,
187 variable_alloca,
188 dbg_var,
189 addr_expr,
190 dbg_loc,
191 self.llbb(),
192 )
193 };
194 }
146 let mut name = String::with_capacity(64);
147 type_names::push_item_name(tcx, def_id, false, &mut name);
195148
196 fn dbg_var_value(
197 &mut self,
198 dbg_var: &'ll DIVariable,
199 dbg_loc: &'ll DILocation,
200 value: Self::Value,
201 direct_offset: Size,
202 indirect_offsets: &[Size],
203 fragment: &Option<Range<Size>>,
204 ) {
205 use dwarf_const::{DW_OP_LLVM_fragment, DW_OP_deref, DW_OP_plus_uconst, DW_OP_stack_value};
149 // Find the enclosing function, in case this is a closure.
150 let enclosing_fn_def_id = tcx.typeck_root_def_id(def_id);
206151
207 // Convert the direct and indirect offsets and fragment byte range to address ops.
208 let mut addr_ops = SmallVec::<[u64; 8]>::new();
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);
209157
210 if direct_offset.bytes() > 0 {
211 addr_ops.push(DW_OP_plus_uconst);
212 addr_ops.push(direct_offset.bytes() as u64);
213 addr_ops.push(DW_OP_stack_value);
214 }
215 for &offset in indirect_offsets {
216 addr_ops.push(DW_OP_deref);
217 if offset.bytes() > 0 {
218 addr_ops.push(DW_OP_plus_uconst);
219 addr_ops.push(offset.bytes() as u64);
220 }
221 }
222 if let Some(fragment) = fragment {
223 // `DW_OP_LLVM_fragment` takes as arguments the fragment's
224 // offset and size, both of them in bits.
225 addr_ops.push(DW_OP_LLVM_fragment);
226 addr_ops.push(fragment.start.bits() as u64);
227 addr_ops.push((fragment.end - fragment.start).bits() as u64);
228 }
158 type_names::push_generic_args(
159 tcx,
160 tcx.normalize_erasing_regions(self.typing_env(), Unnormalized::new_wip(args)),
161 &mut name,
162 );
229163
230 let di_builder = DIB(self.cx());
231 let addr_expr = unsafe {
232 llvm::LLVMDIBuilderCreateExpression(di_builder, addr_ops.as_ptr(), addr_ops.len())
233 };
234 unsafe {
235 llvm::LLVMDIBuilderInsertDbgValueRecordAtEnd(
236 di_builder,
237 value,
238 dbg_var,
239 addr_expr,
240 dbg_loc,
241 self.llbb(),
242 );
243 }
244 }
164 let template_parameters = get_template_parameters(self, generics, args);
245165
246 fn set_dbg_loc(&mut self, dbg_loc: &'ll DILocation) {
247 unsafe {
248 llvm::LLVMSetCurrentDebugLocation2(self.llbuilder, dbg_loc);
249 }
250 }
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 };
251169
252 fn clear_dbg_loc(&mut self) {
253 unsafe {
254 llvm::LLVMSetCurrentDebugLocation2(self.llbuilder, ptr::null());
255 }
256 }
170 // FIXME(eddyb) does this need to be separate from `loc.line` for some reason?
171 let scope_line = loc.line;
257172
258 fn insert_reference_to_gdb_debug_scripts_section_global(&mut self) {
259 gdb::insert_reference_to_gdb_debug_scripts_section_global(self)
260 }
173 let mut flags = DIFlags::FlagPrototyped;
261174
262 fn set_var_name(&mut self, value: &'ll Value, name: &str) {
263 // Avoid wasting time if LLVM value names aren't even enabled.
264 if self.sess().fewer_names() {
265 return;
175 if fn_abi.ret.layout.is_uninhabited() {
176 flags |= DIFlags::FlagNoReturn;
266177 }
267178
268 // Only function parameters and instructions are local to a function,
269 // don't change the name of anything else (e.g. globals).
270 let param_or_inst = unsafe {
271 llvm::LLVMIsAArgument(value).is_some() || llvm::LLVMIsAInstruction(value).is_some()
272 };
273 if !param_or_inst {
274 return;
179 let mut spflags = DISPFlags::SPFlagDefinition;
180 if is_node_local_to_unit(self, def_id) {
181 spflags |= DISPFlags::SPFlagLocalToUnit;
275182 }
276
277 // Avoid replacing the name if it already exists.
278 // While we could combine the names somehow, it'd
279 // get noisy quick, and the usefulness is dubious.
280 if llvm::get_value_name(value).is_empty() {
281 llvm::set_value_name(value, name.as_bytes());
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 }
282190 }
283 }
284191
285 /// Annotate move/copy operations with debug info for profiling.
286 ///
287 /// This creates a temporary debug scope that makes the move/copy appear as an inlined call to
288 /// `compiler_move<T, SIZE>()` or `compiler_copy<T, SIZE>()`. The provided closure is executed
289 /// with this temporary debug location active.
290 ///
291 /// The `instance` parameter should be the monomorphized instance of the `compiler_move` or
292 /// `compiler_copy` function with the actual type and size.
293 fn with_move_annotation<R>(
294 &mut self,
295 instance: ty::Instance<'tcx>,
296 f: impl FnOnce(&mut Self) -> R,
297 ) -> R {
298 // Save the current debug location
299 let saved_loc = self.get_dbg_loc();
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 });
300212
301 // Create a DIScope for the compiler_move/compiler_copy function
302 // We use the function's FnAbi for debug info generation
303 let fn_abi = self
304 .cx()
305 .tcx
306 .fn_abi_of_instance(
307 self.cx().typing_env().as_query_input((instance, ty::List::empty())),
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,
308230 )
309 .unwrap();
310
311 let di_scope = self.cx().dbg_scope_fn(instance, fn_abi, None);
312
313 // Create an inlined debug location:
314 // - scope: the compiler_move/compiler_copy function
315 // - inlined_at: the current location (where the move/copy actually occurs)
316 // - span: use the function's definition span
317 let fn_span = self.cx().tcx.def_span(instance.def_id());
318 let inlined_loc = self.cx().dbg_loc(di_scope, saved_loc, fn_span);
319
320 // Set the temporary debug location
321 self.set_dbg_loc(inlined_loc);
322
323 // Execute the closure (which will generate the memcpy)
324 let result = f(self);
325
326 // Restore the original debug location
327 if let Some(loc) = saved_loc {
328 self.set_dbg_loc(loc);
329 } else {
330 self.clear_dbg_loc();
331 }
332
333 result
334 }
335}
336
337/// A source code location used to generate debug information.
338// FIXME(eddyb) rename this to better indicate it's a duplicate of
339// `rustc_span::Loc` rather than `DILocation`, perhaps by making
340// `lookup_char_pos` return the right information instead.
341struct DebugLoc {
342 /// Information about the original source file.
343 file: Arc<SourceFile>,
344 /// The (1-based) line number.
345 line: u32,
346 /// The (1-based) column number.
347 col: u32,
348}
349
350impl<'ll> CodegenCx<'ll, '_> {
351 /// Looks up debug source information about a `BytePos`.
352 // FIXME(eddyb) rename this to better indicate it's a duplicate of
353 // `lookup_char_pos` rather than `dbg_loc`, perhaps by making
354 // `lookup_char_pos` return the right information instead.
355 fn lookup_debug_loc(&self, pos: BytePos) -> DebugLoc {
356 let (file, line, col) = match self.sess().source_map().lookup_line(pos) {
357 Ok(SourceFileAndLine { sf: file, line }) => {
358 let line_pos = file.lines()[line];
359
360 // Use 1-based indexing.
361 let line = (line + 1) as u32;
362 let col = (file.relative_position(pos) - line_pos).to_u32() + 1;
363
364 (file, line, col)
365 }
366 Err(file) => (file, UNKNOWN_LINE_NUMBER, UNKNOWN_COLUMN_NUMBER),
367 };
368
369 // For MSVC, omit the column number.
370 // Otherwise, emit it. This mimics clang behaviour.
371 // See discussion in https://github.com/rust-lang/rust/issues/42921
372 if self.sess().target.is_like_msvc {
373 DebugLoc { file, line, col: UNKNOWN_COLUMN_NUMBER }
374 } else {
375 DebugLoc { file, line, col }
376 }
377 }
378
379 fn create_template_type_parameter(
380 &self,
381 name: &str,
382 actual_type_metadata: &'ll DIType,
383 ) -> &'ll DITemplateTypeParameter {
384 unsafe {
385 llvm::LLVMRustDIBuilderCreateTemplateTypeParameter(
386 DIB(self),
387 None,
388 name.as_c_char_ptr(),
389 name.len(),
390 actual_type_metadata,
391 )
392 }
393 }
394}
395
396impl<'ll, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
397 fn dbg_create_lexical_block(&self, pos: BytePos, parent_scope: &'ll DIScope) -> &'ll DIScope {
398 let loc = self.lookup_debug_loc(pos);
399 let file_metadata = file_metadata(self, &loc.file);
400 unsafe {
401 llvm::LLVMDIBuilderCreateLexicalBlock(
402 DIB(self),
403 parent_scope,
404 file_metadata,
405 loc.line,
406 loc.col,
407 )
408 }
409 }
410
411 fn dbg_location_clone_with_discriminator(
412 &self,
413 loc: &'ll DILocation,
414 discriminator: u32,
415 ) -> Option<&'ll DILocation> {
416 unsafe { llvm::LLVMRustDILocationCloneWithBaseDiscriminator(loc, discriminator) }
417 }
418
419 fn dbg_scope_fn(
420 &self,
421 instance: Instance<'tcx>,
422 fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
423 maybe_definition_llfn: Option<&'ll Value>,
424 ) -> &'ll DIScope {
425 let tcx = self.tcx;
426
427 let def_id = instance.def_id();
428 let (containing_scope, is_method) = get_containing_scope(self, instance);
429 let span = tcx.def_span(def_id);
430 let loc = self.lookup_debug_loc(span.lo());
431 let file_metadata = file_metadata(self, &loc.file);
432
433 let function_type_metadata =
434 create_subroutine_type(self, &get_function_signature(self, fn_abi));
435
436 let mut name = String::with_capacity(64);
437 type_names::push_item_name(tcx, def_id, false, &mut name);
438
439 // Find the enclosing function, in case this is a closure.
440 let enclosing_fn_def_id = tcx.typeck_root_def_id(def_id);
441
442 // We look up the generics of the enclosing function and truncate the args
443 // to their length in order to cut off extra stuff that might be in there for
444 // closures or coroutines.
445 let generics = tcx.generics_of(enclosing_fn_def_id);
446 let args = instance.args.truncate_to(tcx, generics);
447
448 type_names::push_generic_args(
449 tcx,
450 tcx.normalize_erasing_regions(self.typing_env(), Unnormalized::new_wip(args)),
451 &mut name,
452 );
453
454 let template_parameters = get_template_parameters(self, generics, args);
455
456 let linkage_name = &mangled_name_of_instance(self, instance).name;
457 // Omit the linkage_name if it is the same as subprogram name.
458 let linkage_name = if &name == linkage_name { "" } else { linkage_name };
459
460 // FIXME(eddyb) does this need to be separate from `loc.line` for some reason?
461 let scope_line = loc.line;
462
463 let mut flags = DIFlags::FlagPrototyped;
464
465 if fn_abi.ret.layout.is_uninhabited() {
466 flags |= DIFlags::FlagNoReturn;
467 }
468
469 let mut spflags = DISPFlags::SPFlagDefinition;
470 if is_node_local_to_unit(self, def_id) {
471 spflags |= DISPFlags::SPFlagLocalToUnit;
472 }
473 if self.sess().opts.optimize != config::OptLevel::No {
474 spflags |= DISPFlags::SPFlagOptimized;
475 }
476 if let Some((id, _)) = tcx.entry_fn(()) {
477 if id == def_id {
478 spflags |= DISPFlags::SPFlagMainSubprogram;
479 }
480 }
481
482 // When we're adding a method to a type DIE, we only want a DW_AT_declaration there, because
483 // LLVM LTO can't unify type definitions when a child DIE is a full subprogram definition.
484 // When we use this `decl` below, the subprogram definition gets created at the CU level
485 // with a DW_AT_specification pointing back to the type's declaration.
486 let decl = is_method.then(|| unsafe {
487 llvm::LLVMRustDIBuilderCreateMethod(
488 DIB(self),
489 containing_scope,
490 name.as_c_char_ptr(),
491 name.len(),
492 linkage_name.as_c_char_ptr(),
493 linkage_name.len(),
494 file_metadata,
495 loc.line,
496 function_type_metadata,
497 flags,
498 spflags & !DISPFlags::SPFlagDefinition,
499 template_parameters,
500 )
501 });
502
503 return unsafe {
504 llvm::LLVMRustDIBuilderCreateFunction(
505 DIB(self),
506 containing_scope,
507 name.as_c_char_ptr(),
508 name.len(),
509 linkage_name.as_c_char_ptr(),
510 linkage_name.len(),
511 file_metadata,
512 loc.line,
513 function_type_metadata,
514 scope_line,
515 flags,
516 spflags,
517 maybe_definition_llfn,
518 template_parameters,
519 decl,
520 )
521 };
231 };
522232
523233 fn get_function_signature<'ll, 'tcx>(
524234 cx: &CodegenCx<'ll, 'tcx>,
......@@ -658,8 +368,34 @@ impl<'ll, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
658368 }
659369 }
660370
371 fn dbg_create_lexical_block(
372 &mut self,
373 pos: BytePos,
374 parent_scope: &'ll DIScope,
375 ) -> &'ll DIScope {
376 let loc = self.lookup_debug_loc(pos);
377 let file_metadata = file_metadata(self, &loc.file);
378 unsafe {
379 llvm::LLVMDIBuilderCreateLexicalBlock(
380 DIB(self),
381 parent_scope,
382 file_metadata,
383 loc.line,
384 loc.col,
385 )
386 }
387 }
388
389 fn dbg_location_clone_with_discriminator(
390 &mut self,
391 loc: &'ll DILocation,
392 discriminator: u32,
393 ) -> Option<&'ll DILocation> {
394 unsafe { llvm::LLVMRustDILocationCloneWithBaseDiscriminator(loc, discriminator) }
395 }
396
661397 fn dbg_loc(
662 &self,
398 &mut self,
663399 scope: &'ll DIScope,
664400 inlined_at: Option<&'ll DILocation>,
665401 span: Span,
......@@ -679,31 +415,18 @@ impl<'ll, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
679415 unsafe { llvm::LLVMDIBuilderCreateDebugLocation(self.llcx, line, col, scope, inlined_at) }
680416 }
681417
682 fn create_vtable_debuginfo(
683 &self,
684 ty: Ty<'tcx>,
685 trait_ref: Option<ty::ExistentialTraitRef<'tcx>>,
686 vtable: Self::Value,
687 ) {
688 metadata::create_vtable_di_node(self, ty, trait_ref, vtable)
689 }
690
691418 fn extend_scope_to_file(
692 &self,
419 &mut self,
693420 scope_metadata: &'ll DIScope,
694421 file: &rustc_span::SourceFile,
695422 ) -> &'ll DILexicalBlock {
696423 metadata::extend_scope_to_file(self, scope_metadata, file)
697424 }
698425
699 fn debuginfo_finalize(&self) {
700 finalize(self)
701 }
702
703426 // FIXME(eddyb) find a common convention for all of the debuginfo-related
704427 // names (choose between `dbg`, `debug`, `debuginfo`, `debug_info` etc.).
705428 fn create_dbg_var(
706 &self,
429 &mut self,
707430 variable_name: Symbol,
708431 variable_type: Ty<'tcx>,
709432 scope_metadata: &'ll DIScope,
......@@ -750,4 +473,280 @@ impl<'ll, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
750473 },
751474 }
752475 }
476
477 // FIXME(eddyb) find a common convention for all of the debuginfo-related
478 // names (choose between `dbg`, `debug`, `debuginfo`, `debug_info` etc.).
479 fn dbg_var_addr(
480 &mut self,
481 dbg_var: &'ll DIVariable,
482 dbg_loc: &'ll DILocation,
483 variable_alloca: Self::Value,
484 direct_offset: Size,
485 indirect_offsets: &[Size],
486 fragment: &Option<Range<Size>>,
487 ) {
488 use dwarf_const::{DW_OP_LLVM_fragment, DW_OP_deref, DW_OP_plus_uconst};
489
490 // Convert the direct and indirect offsets and fragment byte range to address ops.
491 let mut addr_ops = SmallVec::<[u64; 8]>::new();
492
493 if direct_offset.bytes() > 0 {
494 addr_ops.push(DW_OP_plus_uconst);
495 addr_ops.push(direct_offset.bytes());
496 }
497 for &offset in indirect_offsets {
498 addr_ops.push(DW_OP_deref);
499 if offset.bytes() > 0 {
500 addr_ops.push(DW_OP_plus_uconst);
501 addr_ops.push(offset.bytes());
502 }
503 }
504 if let Some(fragment) = fragment {
505 // `DW_OP_LLVM_fragment` takes as arguments the fragment's
506 // offset and size, both of them in bits.
507 addr_ops.push(DW_OP_LLVM_fragment);
508 addr_ops.push(fragment.start.bits());
509 addr_ops.push((fragment.end - fragment.start).bits());
510 }
511
512 let di_builder = DIB(self.cx());
513 let addr_expr = di_builder.create_expression(&addr_ops);
514 unsafe {
515 llvm::LLVMDIBuilderInsertDeclareRecordAtEnd(
516 di_builder,
517 variable_alloca,
518 dbg_var,
519 addr_expr,
520 dbg_loc,
521 self.llbb(),
522 )
523 };
524 }
525
526 fn dbg_var_value(
527 &mut self,
528 dbg_var: &'ll DIVariable,
529 dbg_loc: &'ll DILocation,
530 value: Self::Value,
531 direct_offset: Size,
532 indirect_offsets: &[Size],
533 fragment: &Option<Range<Size>>,
534 ) {
535 use dwarf_const::{DW_OP_LLVM_fragment, DW_OP_deref, DW_OP_plus_uconst, DW_OP_stack_value};
536
537 // Convert the direct and indirect offsets and fragment byte range to address ops.
538 let mut addr_ops = SmallVec::<[u64; 8]>::new();
539
540 if direct_offset.bytes() > 0 {
541 addr_ops.push(DW_OP_plus_uconst);
542 addr_ops.push(direct_offset.bytes() as u64);
543 addr_ops.push(DW_OP_stack_value);
544 }
545 for &offset in indirect_offsets {
546 addr_ops.push(DW_OP_deref);
547 if offset.bytes() > 0 {
548 addr_ops.push(DW_OP_plus_uconst);
549 addr_ops.push(offset.bytes() as u64);
550 }
551 }
552 if let Some(fragment) = fragment {
553 // `DW_OP_LLVM_fragment` takes as arguments the fragment's
554 // offset and size, both of them in bits.
555 addr_ops.push(DW_OP_LLVM_fragment);
556 addr_ops.push(fragment.start.bits() as u64);
557 addr_ops.push((fragment.end - fragment.start).bits() as u64);
558 }
559
560 let di_builder = DIB(self.cx());
561 let addr_expr = unsafe {
562 llvm::LLVMDIBuilderCreateExpression(di_builder, addr_ops.as_ptr(), addr_ops.len())
563 };
564 unsafe {
565 llvm::LLVMDIBuilderInsertDbgValueRecordAtEnd(
566 di_builder,
567 value,
568 dbg_var,
569 addr_expr,
570 dbg_loc,
571 self.llbb(),
572 );
573 }
574 }
575
576 fn set_dbg_loc(&mut self, dbg_loc: &'ll DILocation) {
577 unsafe {
578 llvm::LLVMSetCurrentDebugLocation2(self.llbuilder, dbg_loc);
579 }
580 }
581
582 fn clear_dbg_loc(&mut self) {
583 unsafe {
584 llvm::LLVMSetCurrentDebugLocation2(self.llbuilder, ptr::null());
585 }
586 }
587
588 fn insert_reference_to_gdb_debug_scripts_section_global(&mut self) {
589 gdb::insert_reference_to_gdb_debug_scripts_section_global(self)
590 }
591
592 fn set_var_name(&mut self, value: &'ll Value, name: &str) {
593 // Avoid wasting time if LLVM value names aren't even enabled.
594 if self.sess().fewer_names() {
595 return;
596 }
597
598 // Only function parameters and instructions are local to a function,
599 // don't change the name of anything else (e.g. globals).
600 let param_or_inst = unsafe {
601 llvm::LLVMIsAArgument(value).is_some() || llvm::LLVMIsAInstruction(value).is_some()
602 };
603 if !param_or_inst {
604 return;
605 }
606
607 // Avoid replacing the name if it already exists.
608 // While we could combine the names somehow, it'd
609 // get noisy quick, and the usefulness is dubious.
610 if llvm::get_value_name(value).is_empty() {
611 llvm::set_value_name(value, name.as_bytes());
612 }
613 }
614
615 /// Annotate move/copy operations with debug info for profiling.
616 ///
617 /// This creates a temporary debug scope that makes the move/copy appear as an inlined call to
618 /// `compiler_move<T, SIZE>()` or `compiler_copy<T, SIZE>()`. The provided closure is executed
619 /// with this temporary debug location active.
620 ///
621 /// The `instance` parameter should be the monomorphized instance of the `compiler_move` or
622 /// `compiler_copy` function with the actual type and size.
623 fn with_move_annotation<R>(
624 &mut self,
625 instance: ty::Instance<'tcx>,
626 f: impl FnOnce(&mut Self) -> R,
627 ) -> R {
628 // Save the current debug location
629 let saved_loc = self.get_dbg_loc();
630
631 // Create a DIScope for the compiler_move/compiler_copy function
632 // We use the function's FnAbi for debug info generation
633 let fn_abi = self
634 .cx()
635 .tcx
636 .fn_abi_of_instance(
637 self.cx().typing_env().as_query_input((instance, ty::List::empty())),
638 )
639 .unwrap();
640
641 let di_scope = self.dbg_scope_fn(instance, fn_abi, None);
642
643 // Create an inlined debug location:
644 // - scope: the compiler_move/compiler_copy function
645 // - inlined_at: the current location (where the move/copy actually occurs)
646 // - span: use the function's definition span
647 let fn_span = self.cx().tcx.def_span(instance.def_id());
648 let inlined_loc = self.dbg_loc(di_scope, saved_loc, fn_span);
649
650 // Set the temporary debug location
651 self.set_dbg_loc(inlined_loc);
652
653 // Execute the closure (which will generate the memcpy)
654 let result = f(self);
655
656 // Restore the original debug location
657 if let Some(loc) = saved_loc {
658 self.set_dbg_loc(loc);
659 } else {
660 self.clear_dbg_loc();
661 }
662
663 result
664 }
665}
666
667/// A source code location used to generate debug information.
668// FIXME(eddyb) rename this to better indicate it's a duplicate of
669// `rustc_span::Loc` rather than `DILocation`, perhaps by making
670// `lookup_char_pos` return the right information instead.
671struct DebugLoc {
672 /// Information about the original source file.
673 file: Arc<SourceFile>,
674 /// The (1-based) line number.
675 line: u32,
676 /// The (1-based) column number.
677 col: u32,
678}
679
680impl<'ll> CodegenCx<'ll, '_> {
681 /// Looks up debug source information about a `BytePos`.
682 // FIXME(eddyb) rename this to better indicate it's a duplicate of
683 // `lookup_char_pos` rather than `dbg_loc`, perhaps by making
684 // `lookup_char_pos` return the right information instead.
685 fn lookup_debug_loc(&self, pos: BytePos) -> DebugLoc {
686 let (file, line, col) = match self.sess().source_map().lookup_line(pos) {
687 Ok(SourceFileAndLine { sf: file, line }) => {
688 let line_pos = file.lines()[line];
689
690 // Use 1-based indexing.
691 let line = (line + 1) as u32;
692 let col = (file.relative_position(pos) - line_pos).to_u32() + 1;
693
694 (file, line, col)
695 }
696 Err(file) => (file, UNKNOWN_LINE_NUMBER, UNKNOWN_COLUMN_NUMBER),
697 };
698
699 // For MSVC, omit the column number.
700 // Otherwise, emit it. This mimics clang behaviour.
701 // See discussion in https://github.com/rust-lang/rust/issues/42921
702 if self.sess().target.is_like_msvc {
703 DebugLoc { file, line, col: UNKNOWN_COLUMN_NUMBER }
704 } else {
705 DebugLoc { file, line, col }
706 }
707 }
708
709 fn create_template_type_parameter(
710 &self,
711 name: &str,
712 actual_type_metadata: &'ll DIType,
713 ) -> &'ll DITemplateTypeParameter {
714 unsafe {
715 llvm::LLVMRustDIBuilderCreateTemplateTypeParameter(
716 DIB(self),
717 None,
718 name.as_c_char_ptr(),
719 name.len(),
720 actual_type_metadata,
721 )
722 }
723 }
724
725 /// Creates any deferred debug metadata nodes
726 pub(crate) fn debuginfo_finalize(&self) {
727 if let Some(dbg_cx) = &self.dbg_cx {
728 debug!("finalize");
729
730 if gdb::needs_gdb_debug_scripts_section(self) {
731 // Add a .debug_gdb_scripts section to this compile-unit. This will
732 // cause GDB to try and load the gdb_load_rust_pretty_printers.py file,
733 // which activates the Rust pretty printers for binary this section is
734 // contained in.
735 gdb::get_or_insert_gdb_debug_scripts_section_global(self);
736 }
737
738 dbg_cx.finalize();
739 }
740 }
741}
742
743impl<'ll, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
744 fn create_vtable_debuginfo(
745 &self,
746 ty: Ty<'tcx>,
747 trait_ref: Option<ty::ExistentialTraitRef<'tcx>>,
748 vtable: Self::Value,
749 ) {
750 metadata::create_vtable_di_node(self, ty, trait_ref, vtable)
751 }
753752}
compiler/rustc_codegen_ssa/src/mir/debuginfo.rs+32-29
......@@ -78,15 +78,18 @@ impl<'tcx, S: Copy, L: Copy> DebugScope<S, L> {
7878 /// it may so happen that the current span belongs to a different file than the DIScope
7979 /// corresponding to span's containing source scope. If so, we need to create a DIScope
8080 /// "extension" into that file.
81 pub fn adjust_dbg_scope_for_span<Cx: CodegenMethods<'tcx, DIScope = S, DILocation = L>>(
81 pub fn adjust_dbg_scope_for_span<
82 'a,
83 Bx: BuilderMethods<'a, 'tcx, DIScope = S, DILocation = L>,
84 >(
8285 &self,
83 cx: &Cx,
86 bx: &mut Bx,
8487 span: Span,
8588 ) -> S {
8689 let pos = span.lo();
8790 if pos < self.file_start_pos || pos >= self.file_end_pos {
88 let sm = cx.sess().source_map();
89 cx.extend_scope_to_file(self.dbg_scope, &sm.lookup_char_pos(pos).file)
91 let sm = bx.sess().source_map();
92 bx.extend_scope_to_file(self.dbg_scope, &sm.lookup_char_pos(pos).file)
9093 } else {
9194 self.dbg_scope
9295 }
......@@ -217,23 +220,24 @@ fn calculate_debuginfo_offset<
217220impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
218221 pub fn set_debug_loc(&self, bx: &mut Bx, source_info: mir::SourceInfo) {
219222 bx.set_span(source_info.span);
220 if let Some(dbg_loc) = self.dbg_loc(source_info) {
223 if let Some(dbg_loc) = self.dbg_loc(bx, source_info) {
221224 bx.set_dbg_loc(dbg_loc);
222225 }
223226 }
224227
225 fn dbg_loc(&self, source_info: mir::SourceInfo) -> Option<Bx::DILocation> {
226 let (dbg_scope, inlined_at, span) = self.adjusted_span_and_dbg_scope(source_info)?;
227 Some(self.cx.dbg_loc(dbg_scope, inlined_at, span))
228 fn dbg_loc(&self, bx: &mut Bx, source_info: mir::SourceInfo) -> Option<Bx::DILocation> {
229 let (dbg_scope, inlined_at, span) = self.adjusted_span_and_dbg_scope(bx, source_info)?;
230 Some(bx.dbg_loc(dbg_scope, inlined_at, span))
228231 }
229232
230233 fn adjusted_span_and_dbg_scope(
231234 &self,
235 bx: &mut Bx,
232236 source_info: mir::SourceInfo,
233237 ) -> Option<(Bx::DIScope, Option<Bx::DILocation>, Span)> {
234238 let scope = &self.debug_context.as_ref()?.scopes[source_info.scope];
235239 let span = hygiene::walk_chain_collapsed(source_info.span, self.mir.span);
236 Some((scope.adjust_dbg_scope_for_span(self.cx, span), scope.inlined_at, span))
240 Some((scope.adjust_dbg_scope_for_span(bx, span), scope.inlined_at, span))
237241 }
238242
239243 fn spill_operand_to_stack(
......@@ -279,7 +283,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
279283 let Some(dbg_var) = var.dbg_var else {
280284 continue;
281285 };
282 let Some(dbg_loc) = self.dbg_loc(var.source_info) else {
286 let Some(dbg_loc) = self.dbg_loc(bx, var.source_info) else {
283287 continue;
284288 };
285289 bx.dbg_var_value(
......@@ -334,14 +338,14 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
334338 let name = sym::empty;
335339 let decl = &self.mir.local_decls[local];
336340 let dbg_var = if full_debug_info {
337 self.adjusted_span_and_dbg_scope(decl.source_info).map(
341 self.adjusted_span_and_dbg_scope(bx, decl.source_info).map(
338342 |(dbg_scope, _, span)| {
339343 // FIXME(eddyb) is this `+ 1` needed at all?
340344 let kind = VariableKind::ArgumentVariable(arg_index + 1);
341345
342346 let arg_ty = self.monomorphize(decl.ty);
343347
344 self.cx.create_dbg_var(name, arg_ty, dbg_scope, kind, span)
348 bx.create_dbg_var(name, arg_ty, dbg_scope, kind, span)
345349 },
346350 )
347351 } else {
......@@ -483,7 +487,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
483487 var: PerLocalVarDebugInfo<'tcx, Bx::DIVariable>,
484488 ) {
485489 let Some(dbg_var) = var.dbg_var else { return };
486 let Some(dbg_loc) = self.dbg_loc(var.source_info) else { return };
490 let Some(dbg_loc) = self.dbg_loc(bx, var.source_info) else { return };
487491
488492 let DebugInfoOffset { direct_offset, indirect_offsets, result: _ } =
489493 calculate_debuginfo_offset(bx, var.projection, base.layout);
......@@ -579,7 +583,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
579583 let mut params_seen: FxHashMap<_, Bx::DIVariable> = Default::default();
580584 for var in &self.mir.var_debug_info {
581585 let dbg_scope_and_span = if full_debug_info {
582 self.adjusted_span_and_dbg_scope(var.source_info)
586 self.adjusted_span_and_dbg_scope(bx, var.source_info)
583587 } else {
584588 None
585589 };
......@@ -625,13 +629,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
625629 match params_seen.entry((dbg_scope, arg_index)) {
626630 Entry::Occupied(o) => o.get().clone(),
627631 Entry::Vacant(v) => v
628 .insert(
629 self.cx.create_dbg_var(var.name, var_ty, dbg_scope, var_kind, span),
630 )
632 .insert(bx.create_dbg_var(var.name, var_ty, dbg_scope, var_kind, span))
631633 .clone(),
632634 }
633635 } else {
634 self.cx.create_dbg_var(var.name, var_ty, dbg_scope, var_kind, span)
636 bx.create_dbg_var(var.name, var_ty, dbg_scope, var_kind, span)
635637 }
636638 });
637639
......@@ -669,7 +671,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
669671 }
670672 mir::VarDebugInfoContents::Const(c) => {
671673 if let Some(dbg_var) = dbg_var {
672 let Some(dbg_loc) = self.dbg_loc(var.source_info) else { continue };
674 let Some(dbg_loc) = self.dbg_loc(bx, var.source_info) else { continue };
673675
674676 let operand = self.eval_mir_constant_to_operand(bx, &c);
675677 constants.push(ConstDebugInfo {
......@@ -692,7 +694,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
692694 ///
693695 /// Returns the FunctionDebugContext for the function which holds state needed
694696 /// for debug info creation, if it is enabled.
695 pub(super) fn fill_function_debug_context(&mut self) {
697 pub(super) fn fill_function_debug_context(&mut self, bx: &mut Bx) {
696698 if self.cx.sess().opts.debuginfo == DebugInfo::None {
697699 return;
698700 }
......@@ -722,7 +724,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
722724 // Instantiate all scopes.
723725 let mut discriminators = FxHashMap::default();
724726 for scope in self.mir.source_scopes.indices() {
725 let scope_data = self.make_mir_scope(&variables, &mut discriminators, scope);
727 let scope_data = self.make_mir_scope(bx, &variables, &mut discriminators, scope);
726728 let _s = self.debug_context.as_mut().unwrap().scopes.push(scope_data);
727729 debug_assert_eq!(_s, scope);
728730 }
......@@ -730,6 +732,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
730732
731733 fn make_mir_scope(
732734 &mut self,
735 bx: &mut Bx,
733736 variables: &Option<DenseBitSet<mir::SourceScope>>,
734737 discriminators: &mut FxHashMap<BytePos, u32>,
735738 scope: mir::SourceScope,
......@@ -741,7 +744,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
741744 } else {
742745 // The root is the function itself.
743746 let file = self.cx.sess().source_map().lookup_source_file(self.mir.span.lo());
744 let dbg_scope = self.cx.dbg_scope_fn(self.instance, self.fn_abi, Some(self.llfn));
747 let dbg_scope = bx.dbg_scope_fn(self.instance, self.fn_abi, Some(self.llfn));
745748 return DebugScope {
746749 dbg_scope,
747750 inlined_at: None,
......@@ -770,16 +773,16 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
770773 .entry(callee)
771774 .or_insert_with(|| {
772775 let callee_fn_abi = self.cx.fn_abi_of_instance(callee, ty::List::empty());
773 self.cx.dbg_scope_fn(callee, callee_fn_abi, None)
776 bx.dbg_scope_fn(callee, callee_fn_abi, None)
774777 })
775778 }
776 None => self.cx.dbg_create_lexical_block(scope_data.span.lo(), parent_scope.dbg_scope),
779 None => bx.dbg_create_lexical_block(scope_data.span.lo(), parent_scope.dbg_scope),
777780 };
778781
779782 let inlined_at = scope_data.inlined.map(|(_, callsite_span)| {
780783 let callsite_span = hygiene::walk_chain_collapsed(callsite_span, self.mir.span);
781 let callsite_scope = parent_scope.adjust_dbg_scope_for_span(self.cx, callsite_span);
782 let loc = self.cx.dbg_loc(callsite_scope, parent_scope.inlined_at, callsite_span);
784 let callsite_scope = parent_scope.adjust_dbg_scope_for_span(bx, callsite_span);
785 let loc = bx.dbg_loc(callsite_scope, parent_scope.inlined_at, callsite_span);
783786
784787 // NB: In order to produce proper debug info for variables (particularly
785788 // arguments) in multiply-inlined functions, LLVM expects to see a single
......@@ -805,9 +808,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
805808 // NB: We have to emit *something* here or we'll fail LLVM IR verification
806809 // in at least some circumstances (see issue #135322) so if the required
807810 // discriminant cannot be encoded fall back to the dummy location.
808 self.cx.dbg_location_clone_with_discriminator(loc, *o.get()).unwrap_or_else(
809 || self.cx.dbg_loc(callsite_scope, parent_scope.inlined_at, DUMMY_SP),
810 )
811 bx.dbg_location_clone_with_discriminator(loc, *o.get()).unwrap_or_else(|| {
812 bx.dbg_loc(callsite_scope, parent_scope.inlined_at, DUMMY_SP)
813 })
811814 }
812815 Entry::Vacant(v) => {
813816 v.insert(0);
compiler/rustc_codegen_ssa/src/mir/mod.rs+1-1
......@@ -269,7 +269,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
269269 // monomorphization, and if there is an error during collection then codegen never starts -- so
270270 // we don't have to do it again.
271271
272 fx.fill_function_debug_context();
272 fx.fill_function_debug_context(&mut start_bx);
273273
274274 let (per_local_var_debug_info, consts_debug_info) =
275275 fx.compute_per_local_var_debug_info(&mut start_bx).unzip();
compiler/rustc_codegen_ssa/src/traits/debuginfo.rs+18-15
......@@ -15,51 +15,54 @@ pub trait DebugInfoCodegenMethods<'tcx>: BackendTypes {
1515 trait_ref: Option<ExistentialTraitRef<'tcx>>,
1616 vtable: Self::Value,
1717 );
18}
1819
19 fn dbg_create_lexical_block(&self, pos: BytePos, parent_scope: Self::DIScope) -> Self::DIScope;
20
21 fn dbg_location_clone_with_discriminator(
22 &self,
23 loc: Self::DILocation,
24 discriminator: u32,
25 ) -> Option<Self::DILocation>;
26
20pub trait DebugInfoBuilderMethods<'tcx>: BackendTypes {
2721 // FIXME(eddyb) find a common convention for all of the debuginfo-related
2822 // names (choose between `dbg`, `debug`, `debuginfo`, `debug_info` etc.).
2923 fn dbg_scope_fn(
30 &self,
24 &mut self,
3125 instance: Instance<'tcx>,
3226 fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
3327 maybe_definition_llfn: Option<Self::Function>,
3428 ) -> Self::DIScope;
3529
30 fn dbg_create_lexical_block(
31 &mut self,
32 pos: BytePos,
33 parent_scope: Self::DIScope,
34 ) -> Self::DIScope;
35
36 fn dbg_location_clone_with_discriminator(
37 &mut self,
38 loc: Self::DILocation,
39 discriminator: u32,
40 ) -> Option<Self::DILocation>;
41
3642 fn dbg_loc(
37 &self,
43 &mut self,
3844 scope: Self::DIScope,
3945 inlined_at: Option<Self::DILocation>,
4046 span: Span,
4147 ) -> Self::DILocation;
4248
4349 fn extend_scope_to_file(
44 &self,
50 &mut self,
4551 scope_metadata: Self::DIScope,
4652 file: &SourceFile,
4753 ) -> Self::DIScope;
48 fn debuginfo_finalize(&self);
4954
5055 // FIXME(eddyb) find a common convention for all of the debuginfo-related
5156 // names (choose between `dbg`, `debug`, `debuginfo`, `debug_info` etc.).
5257 fn create_dbg_var(
53 &self,
58 &mut self,
5459 variable_name: Symbol,
5560 variable_type: Ty<'tcx>,
5661 scope_metadata: Self::DIScope,
5762 variable_kind: VariableKind,
5863 span: Span,
5964 ) -> Self::DIVariable;
60}
6165
62pub trait DebugInfoBuilderMethods<'tcx>: BackendTypes {
6366 // FIXME(eddyb) find a common convention for all of the debuginfo-related
6467 // names (choose between `dbg`, `debug`, `debuginfo`, `debug_info` etc.).
6568 fn dbg_var_addr(
library/std/src/net/tests.rs+2-1
......@@ -41,8 +41,9 @@ pub fn compare_ignore_zoneid(a: &SocketAddr, b: &SocketAddr) -> bool {
4141fn hostname_smoketest() {
4242 // Just a smoke test to ensure it can be called.
4343 let name = crate::net::hostname();
44 if cfg!(windows) || cfg!(unix) {
44 if cfg!(any(all(windows, not(target_vendor = "win7")), unix)) {
4545 // At least on Windows and Unix, this should succeed.
46 // The `win7` Windows targets do not support it yet though.
4647 name.unwrap();
4748 }
4849}
src/doc/nomicon+1-1
......@@ -1 +1 @@
1Subproject commit cc6a6bae8c3bfa389974e533c54694662c1a9de6
1Subproject commit 5012a37c682b26c4e19433888ed2ca9b129696ca
src/doc/reference+1-1
......@@ -1 +1 @@
1Subproject commit 2c27905c15a51983b54d84f050d3bda096194d27
1Subproject commit 86635e30bf861a038dc197d7e16fd09e7e514e7a
tests/debuginfo/lexical-scope-in-match.rs+1
......@@ -1,6 +1,7 @@
11//@ compile-flags:-g
22//@ disable-gdb-pretty-printers
33//@ ignore-backends: gcc
4//@ min-lldb-version: 2100
45
56// === GDB TESTS ===================================================================================
67
tests/ui/unpretty/exhaustive.expanded.stdout+1-1
......@@ -449,7 +449,7 @@ mod items {
449449 impl () {}
450450 impl<T> () {}
451451 impl Default for () {}
452 impl<T> const Default for () {}
452 const impl<T> Default for () {}
453453 }
454454 /// ItemKind::MacCall
455455 mod item_mac_call { }