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 } ;
3
3
use 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 } ;
5
7
use 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 } ;
7
10
use rustc_target:: abi:: call:: FnAbi ;
8
11
use rustc_target:: abi:: Size ;
12
+ use rustc_data_structures:: sync:: Lrc ;
13
+ use crate :: rustc_index:: Idx ;
9
14
use std:: ops:: Range ;
10
15
11
16
use crate :: builder:: Builder ;
12
17
use crate :: context:: CodegenCx ;
13
18
19
+ pub ( super ) const UNKNOWN_LINE_NUMBER : u32 = 0 ;
20
+ pub ( super ) const UNKNOWN_COLUMN_NUMBER : u32 = 0 ;
21
+
14
22
impl < ' a , ' gcc , ' tcx > DebugInfoBuilderMethods for Builder < ' a , ' gcc , ' tcx > {
15
23
// FIXME(eddyb) find a common convention for all of the debuginfo-related
16
24
// names (choose between `dbg`, `debug`, `debuginfo`, `debug_info` etc.).
17
25
fn dbg_var_addr (
18
26
& mut self ,
19
27
_dbg_var : Self :: DIVariable ,
20
- _scope_metadata : Self :: DIScope ,
21
- _variable_alloca : Self :: Value ,
28
+ dbg_loc : Self :: DILocation ,
29
+ variable_alloca : Self :: Value ,
22
30
_direct_offset : Size ,
23
31
_indirect_offsets : & [ Size ] ,
24
32
_fragment : Option < Range < Size > > ,
25
33
) {
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
+ }
27
39
}
28
40
29
41
fn insert_reference_to_gdb_debug_scripts_section_global ( & mut self ) {
30
42
// TODO(antoyo): insert reference to gdb debug scripts section global.
31
43
}
32
44
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
+ }
35
126
}
36
127
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
+ }
39
170
}
40
171
}
41
172
@@ -51,25 +182,45 @@ impl<'gcc, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
51
182
52
183
fn create_function_debug_context (
53
184
& 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 > ,
58
189
) -> Option < FunctionDebugContext < ' tcx , Self :: DIScope , Self :: DILocation > > {
59
190
// 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)
61
211
}
62
212
63
213
fn extend_scope_to_file (
64
214
& self ,
65
215
_scope_metadata : Self :: DIScope ,
66
216
_file : & SourceFile ,
67
217
) -> Self :: DIScope {
68
- unimplemented ! ( ) ;
218
+ // unimplemented!();
69
219
}
70
220
71
221
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 )
73
224
}
74
225
75
226
fn create_dbg_var (
@@ -80,7 +231,7 @@ impl<'gcc, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
80
231
_variable_kind : VariableKind ,
81
232
_span : Span ,
82
233
) -> Self :: DIVariable {
83
- unimplemented ! ( ) ;
234
+ ( )
84
235
}
85
236
86
237
fn dbg_scope_fn (
@@ -89,15 +240,47 @@ impl<'gcc, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
89
240
_fn_abi : & FnAbi < ' tcx , Ty < ' tcx > > ,
90
241
_maybe_definition_llfn : Option < RValue < ' gcc > > ,
91
242
) -> Self :: DIScope {
92
- unimplemented ! ( ) ;
243
+ // unimplemented!();
93
244
}
94
245
95
246
fn dbg_loc (
96
247
& self ,
97
248
_scope : Self :: DIScope ,
98
249
_inlined_at : Option < Self :: DILocation > ,
99
- _span : Span ,
250
+ span : Span ,
100
251
) -> 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
102
285
}
103
286
}
0 commit comments