1+ use std:: collections:: hash_map:: Entry ;
2+
13use rustc_codegen_ssa:: mir:: debuginfo:: { DebugScope , FunctionDebugContext } ;
24use rustc_codegen_ssa:: traits:: * ;
5+ use rustc_data_structures:: fx:: FxHashMap ;
36use rustc_index:: Idx ;
47use rustc_index:: bit_set:: BitSet ;
58use rustc_middle:: mir:: { Body , SourceScope } ;
69use rustc_middle:: ty:: layout:: FnAbiOf ;
710use rustc_middle:: ty:: { self , Instance } ;
811use rustc_session:: config:: DebugInfo ;
12+ use rustc_span:: BytePos ;
913
1014use super :: metadata:: file_metadata;
1115use super :: utils:: DIB ;
@@ -37,10 +41,20 @@ pub(crate) fn compute_mir_scopes<'ll, 'tcx>(
3741 None
3842 } ;
3943 let mut instantiated = BitSet :: new_empty ( mir. source_scopes . len ( ) ) ;
44+ let mut discriminators = FxHashMap :: default ( ) ;
4045 // Instantiate all scopes.
4146 for idx in 0 ..mir. source_scopes . len ( ) {
4247 let scope = SourceScope :: new ( idx) ;
43- make_mir_scope ( cx, instance, mir, & variables, debug_context, & mut instantiated, scope) ;
48+ make_mir_scope (
49+ cx,
50+ instance,
51+ mir,
52+ & variables,
53+ debug_context,
54+ & mut instantiated,
55+ & mut discriminators,
56+ scope,
57+ ) ;
4458 }
4559 assert ! ( instantiated. count( ) == mir. source_scopes. len( ) ) ;
4660}
@@ -52,6 +66,7 @@ fn make_mir_scope<'ll, 'tcx>(
5266 variables : & Option < BitSet < SourceScope > > ,
5367 debug_context : & mut FunctionDebugContext < ' tcx , & ' ll DIScope , & ' ll DILocation > ,
5468 instantiated : & mut BitSet < SourceScope > ,
69+ discriminators : & mut FxHashMap < BytePos , u32 > ,
5570 scope : SourceScope ,
5671) {
5772 if instantiated. contains ( scope) {
@@ -60,7 +75,16 @@ fn make_mir_scope<'ll, 'tcx>(
6075
6176 let scope_data = & mir. source_scopes [ scope] ;
6277 let parent_scope = if let Some ( parent) = scope_data. parent_scope {
63- make_mir_scope ( cx, instance, mir, variables, debug_context, instantiated, parent) ;
78+ make_mir_scope (
79+ cx,
80+ instance,
81+ mir,
82+ variables,
83+ debug_context,
84+ instantiated,
85+ discriminators,
86+ parent,
87+ ) ;
6488 debug_context. scopes [ parent]
6589 } else {
6690 // The root is the function itself.
@@ -117,7 +141,37 @@ fn make_mir_scope<'ll, 'tcx>(
117141 // FIXME(eddyb) this doesn't account for the macro-related
118142 // `Span` fixups that `rustc_codegen_ssa::mir::debuginfo` does.
119143 let callsite_scope = parent_scope. adjust_dbg_scope_for_span ( cx, callsite_span) ;
120- cx. dbg_loc ( callsite_scope, parent_scope. inlined_at , callsite_span)
144+ let loc = cx. dbg_loc ( callsite_scope, parent_scope. inlined_at , callsite_span) ;
145+
146+ // NB: In order to produce proper debug info for variables (particularly
147+ // arguments) in multiply-inline functions, LLVM expects to see a single
148+ // DILocalVariable with multiple different DILocations in the IR. While
149+ // the source information for each DILocation would be identical, their
150+ // inlinedAt attributes will be unique to the particular callsite.
151+ //
152+ // We generate DILocations here based on the callsite's location in the
153+ // source code. A single location in the source code usually can't
154+ // produce multiple distinct calls so this mostly works, until
155+ // proc-macros get involved. A proc-macro can generate multiple calls
156+ // at the same span, which breaks the assumption that we're going to
157+ // produce a unique DILocation for every scope we process here. We
158+ // have to explicitly add discriminators if we see inlines into the
159+ // same source code location.
160+ //
161+ // Note further that we can't key this hashtable on the span itself,
162+ // because these spans could have distinct SyntaxContexts. We have
163+ // to key on exactly what we're giving to LLVM.
164+ match discriminators. entry ( callsite_span. lo ( ) ) {
165+ Entry :: Occupied ( mut o) => {
166+ * o. get_mut ( ) += 1 ;
167+ unsafe { llvm:: LLVMRustDILocationCloneWithBaseDiscriminator ( loc, * o. get ( ) ) }
168+ . expect ( "Failed to encode discriminator in DILocation" )
169+ }
170+ Entry :: Vacant ( v) => {
171+ v. insert ( 0 ) ;
172+ loc
173+ }
174+ }
121175 } ) ;
122176
123177 debug_context. scopes [ scope] = DebugScope {
0 commit comments