1- use gccjit:: RValue ;
2- use rustc_codegen_ssa:: mir:: debuginfo:: { FunctionDebugContext , VariableKind } ;
1+ use gccjit:: { Location , RValue } ;
2+ use rustc_codegen_ssa:: mir:: debuginfo:: { DebugScope , FunctionDebugContext , VariableKind } ;
33use rustc_codegen_ssa:: traits:: { DebugInfoBuilderMethods , DebugInfoMethods } ;
4- use rustc_middle:: mir;
4+ use rustc_index:: bit_set:: BitSet ;
5+ use rustc_index:: IndexVec ;
6+ use rustc_middle:: mir:: { Body , self , SourceScope } ;
57use rustc_middle:: ty:: { Instance , PolyExistentialTraitRef , Ty } ;
6- use rustc_span:: { SourceFile , Span , Symbol } ;
8+ use rustc_session:: config:: DebugInfo ;
9+ use rustc_span:: { BytePos , Pos , SourceFile , SourceFileAndLine , Span , Symbol } ;
710use rustc_target:: abi:: call:: FnAbi ;
811use rustc_target:: abi:: Size ;
12+ use rustc_data_structures:: sync:: Lrc ;
13+ use crate :: rustc_index:: Idx ;
914use std:: ops:: Range ;
1015
1116use crate :: builder:: Builder ;
1217use crate :: context:: CodegenCx ;
1318
19+ pub ( super ) const UNKNOWN_LINE_NUMBER : u32 = 0 ;
20+ pub ( super ) const UNKNOWN_COLUMN_NUMBER : u32 = 0 ;
21+
1422impl < ' a , ' gcc , ' tcx > DebugInfoBuilderMethods for Builder < ' a , ' gcc , ' tcx > {
1523 // FIXME(eddyb) find a common convention for all of the debuginfo-related
1624 // names (choose between `dbg`, `debug`, `debuginfo`, `debug_info` etc.).
1725 fn dbg_var_addr (
1826 & mut self ,
1927 _dbg_var : Self :: DIVariable ,
20- _scope_metadata : Self :: DIScope ,
21- _variable_alloca : Self :: Value ,
28+ dbg_loc : Self :: DILocation ,
29+ variable_alloca : Self :: Value ,
2230 _direct_offset : Size ,
2331 _indirect_offsets : & [ Size ] ,
2432 _fragment : Option < Range < Size > > ,
2533 ) {
26- unimplemented ! ( ) ;
34+ // Not sure if this is correct, probably wrong but still keep it here.
35+ unsafe {
36+ #[ cfg( feature = "master" ) ]
37+ variable_alloca. set_location ( dbg_loc) ;
38+ }
2739 }
2840
2941 fn insert_reference_to_gdb_debug_scripts_section_global ( & mut self ) {
3042 // TODO(antoyo): insert reference to gdb debug scripts section global.
3143 }
3244
33- fn set_var_name ( & mut self , _value : RValue < ' gcc > , _name : & str ) {
34- unimplemented ! ( ) ;
45+ /// Currently, this function is not yet implemented. It seems that the
46+ /// debug name and the mangled name should both be included in the LValues.
47+ /// Besides, a function to get the rvalue type(m_is_lvalue) should also be included.
48+ fn set_var_name ( & mut self , value : RValue < ' gcc > , name : & str ) {
49+ //unimplemented!();
50+ }
51+
52+ fn set_dbg_loc ( & mut self , dbg_loc : Self :: DILocation ) {
53+ self . loc = Some ( dbg_loc) ;
54+ }
55+ }
56+
57+ pub fn compute_mir_scopes < ' gcc , ' tcx > (
58+ cx : & CodegenCx < ' gcc , ' tcx > ,
59+ instance : Instance < ' tcx > ,
60+ mir : & Body < ' tcx > ,
61+ debug_context : & mut FunctionDebugContext < ' tcx , ( ) , Location < ' gcc > > ,
62+ ) {
63+ // Find all scopes with variables defined in them.
64+ let variables = if cx. sess ( ) . opts . debuginfo == DebugInfo :: Full {
65+ let mut vars = BitSet :: new_empty ( mir. source_scopes . len ( ) ) ;
66+ // FIXME(eddyb) take into account that arguments always have debuginfo,
67+ // irrespective of their name (assuming full debuginfo is enabled).
68+ // NOTE(eddyb) actually, on second thought, those are always in the
69+ // function scope, which always exists.
70+ for var_debug_info in & mir. var_debug_info {
71+ vars. insert ( var_debug_info. source_info . scope ) ;
72+ }
73+ Some ( vars)
74+ } else {
75+ // Nothing to emit, of course.
76+ None
77+ } ;
78+ let mut instantiated = BitSet :: new_empty ( mir. source_scopes . len ( ) ) ;
79+ // Instantiate all scopes.
80+ for idx in 0 ..mir. source_scopes . len ( ) {
81+ let scope = SourceScope :: new ( idx) ;
82+ make_mir_scope ( cx, instance, mir, & variables, debug_context, & mut instantiated, scope) ;
83+ }
84+ assert ! ( instantiated. count( ) == mir. source_scopes. len( ) ) ;
85+ }
86+
87+ fn make_mir_scope < ' gcc , ' tcx > (
88+ cx : & CodegenCx < ' gcc , ' tcx > ,
89+ instance : Instance < ' tcx > ,
90+ mir : & Body < ' tcx > ,
91+ variables : & Option < BitSet < SourceScope > > ,
92+ debug_context : & mut FunctionDebugContext < ' tcx , ( ) , Location < ' gcc > > ,
93+ instantiated : & mut BitSet < SourceScope > ,
94+ scope : SourceScope ,
95+ ) {
96+ if instantiated. contains ( scope) {
97+ return ;
98+ }
99+
100+ let scope_data = & mir. source_scopes [ scope] ;
101+ let parent_scope = if let Some ( parent) = scope_data. parent_scope {
102+ make_mir_scope ( cx, instance, mir, variables, debug_context, instantiated, parent) ;
103+ debug_context. scopes [ parent]
104+ } else {
105+ // The root is the function itself.
106+ let file = cx. sess ( ) . source_map ( ) . lookup_source_file ( mir. span . lo ( ) ) ;
107+ debug_context. scopes [ scope] = DebugScope {
108+ file_start_pos : file. start_pos ,
109+ file_end_pos : file. end_position ( ) ,
110+ ..debug_context. scopes [ scope]
111+ } ;
112+ instantiated. insert ( scope) ;
113+ return ;
114+ } ;
115+
116+ if let Some ( vars) = variables
117+ {
118+ if !vars. contains ( scope)
119+ && scope_data. inlined . is_none ( ) {
120+ // Do not create a DIScope if there are no variables defined in this
121+ // MIR `SourceScope`, and it's not `inlined`, to avoid debuginfo bloat.
122+ debug_context. scopes [ scope] = parent_scope;
123+ instantiated. insert ( scope) ;
124+ return ;
125+ }
35126 }
36127
37- fn set_dbg_loc ( & mut self , _dbg_loc : Self :: DILocation ) {
38- unimplemented ! ( ) ;
128+ let loc = cx. lookup_debug_loc ( scope_data. span . lo ( ) ) ;
129+ let dbg_scope = ( ) ;
130+
131+ let inlined_at = scope_data. inlined . map ( |( _, callsite_span) | {
132+ // FIXME(eddyb) this doesn't account for the macro-related
133+ // `Span` fixups that `rustc_codegen_ssa::mir::debuginfo` does.
134+ let callsite_scope = parent_scope. adjust_dbg_scope_for_span ( cx, callsite_span) ;
135+ cx. dbg_loc ( callsite_scope, parent_scope. inlined_at , callsite_span)
136+ } ) ;
137+ let p_inlined_at = parent_scope. inlined_at ;
138+ // TODO(tempdragon): dbg_scope: Add support for scope extension here.
139+ inlined_at. or ( p_inlined_at) ;
140+
141+ debug_context. scopes [ scope] = DebugScope {
142+ dbg_scope,
143+ inlined_at,
144+ file_start_pos : loc. 0 . start_pos ,
145+ file_end_pos : loc. 0 . end_position ( ) ,
146+ } ;
147+ instantiated. insert ( scope) ;
148+ }
149+
150+ /// Copied from LLVM backend
151+ impl < ' gcc , ' tcx > CodegenCx < ' gcc , ' tcx > {
152+ pub fn lookup_debug_loc ( & self , pos : BytePos ) -> ( Lrc < SourceFile > , u32 , u32 ) {
153+ match self . sess ( ) . source_map ( ) . lookup_line ( pos) {
154+ Ok ( SourceFileAndLine { sf : file, line } ) => {
155+ let line_pos = file. lines ( ) [ line] ;
156+
157+ // Use 1-based indexing.
158+ let line = ( line + 1 ) as u32 ;
159+ let col = ( file. relative_position ( pos) - line_pos) . to_u32 ( ) + 1 ;
160+ ( file,
161+ line,
162+ if ! self . sess ( ) . target . is_like_msvc {
163+ col } else {
164+ UNKNOWN_COLUMN_NUMBER
165+ }
166+ )
167+ }
168+ Err ( file) => ( file, UNKNOWN_LINE_NUMBER , UNKNOWN_COLUMN_NUMBER ) ,
169+ }
39170 }
40171}
41172
@@ -51,25 +182,45 @@ impl<'gcc, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
51182
52183 fn create_function_debug_context (
53184 & self ,
54- _instance : Instance < ' tcx > ,
55- _fn_abi : & FnAbi < ' tcx , Ty < ' tcx > > ,
56- _llfn : RValue < ' gcc > ,
57- _mir : & mir:: Body < ' tcx > ,
185+ instance : Instance < ' tcx > ,
186+ fn_abi : & FnAbi < ' tcx , Ty < ' tcx > > ,
187+ llfn : RValue < ' gcc > ,
188+ mir : & mir:: Body < ' tcx > ,
58189 ) -> Option < FunctionDebugContext < ' tcx , Self :: DIScope , Self :: DILocation > > {
59190 // TODO(antoyo)
60- None
191+ if self . sess ( ) . opts . debuginfo == DebugInfo :: None {
192+ return None ;
193+ }
194+
195+ // Initialize fn debug context (including scopes).
196+ let empty_scope = DebugScope {
197+ dbg_scope : self . dbg_scope_fn ( instance, fn_abi, Some ( llfn) ) ,
198+ inlined_at : None ,
199+ file_start_pos : BytePos ( 0 ) ,
200+ file_end_pos : BytePos ( 0 ) ,
201+ } ;
202+ let mut fn_debug_context = FunctionDebugContext {
203+ scopes : IndexVec :: from_elem ( empty_scope, & mir. source_scopes . as_slice ( ) ) ,
204+ inlined_function_scopes : Default :: default ( ) ,
205+ } ;
206+
207+ // Fill in all the scopes, with the information from the MIR body.
208+ compute_mir_scopes ( self , instance, mir, & mut fn_debug_context) ;
209+
210+ Some ( fn_debug_context)
61211 }
62212
63213 fn extend_scope_to_file (
64214 & self ,
65215 _scope_metadata : Self :: DIScope ,
66216 _file : & SourceFile ,
67217 ) -> Self :: DIScope {
68- unimplemented ! ( ) ;
218+ // unimplemented!();
69219 }
70220
71221 fn debuginfo_finalize ( & self ) {
72- // TODO(antoyo)
222+ // TODO(antoyo): Get the debug flag/predicate to allow optional generation of debuginfo.
223+ self . context . set_debug_info ( true )
73224 }
74225
75226 fn create_dbg_var (
@@ -80,7 +231,7 @@ impl<'gcc, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
80231 _variable_kind : VariableKind ,
81232 _span : Span ,
82233 ) -> Self :: DIVariable {
83- unimplemented ! ( ) ;
234+ ( )
84235 }
85236
86237 fn dbg_scope_fn (
@@ -89,15 +240,47 @@ impl<'gcc, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
89240 _fn_abi : & FnAbi < ' tcx , Ty < ' tcx > > ,
90241 _maybe_definition_llfn : Option < RValue < ' gcc > > ,
91242 ) -> Self :: DIScope {
92- unimplemented ! ( ) ;
243+ // unimplemented!();
93244 }
94245
95246 fn dbg_loc (
96247 & self ,
97248 _scope : Self :: DIScope ,
98249 _inlined_at : Option < Self :: DILocation > ,
99- _span : Span ,
250+ span : Span ,
100251 ) -> Self :: DILocation {
101- unimplemented ! ( ) ;
252+ //unimplemented!();
253+ let pos = span. lo ( ) ;
254+ let ( file, line, col) = self . lookup_debug_loc ( pos) ;
255+ let loc = match & file. name {
256+ rustc_span:: FileName :: Real ( name) => match name {
257+ rustc_span:: RealFileName :: LocalPath ( name) => {
258+ if let Some ( name) = name. to_str ( ) {
259+ self . context
260+ . new_location ( name, line as i32 , col as i32 )
261+ } else {
262+ Location :: null ( )
263+ }
264+ }
265+ rustc_span:: RealFileName :: Remapped {
266+ local_path,
267+ virtual_name,
268+ } => if let Some ( name) = local_path. as_ref ( ) {
269+ if let Some ( name) = name. to_str ( ) {
270+ self . context . new_location (
271+ name,
272+ line as i32 ,
273+ col as i32 ,
274+ )
275+ } else {
276+ Location :: null ( )
277+ }
278+ } else {
279+ Location :: null ( )
280+ } ,
281+ } ,
282+ _ => Location :: null ( ) ,
283+ } ;
284+ loc
102285 }
103286}
0 commit comments