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
+ // FIXME(tempdragon): Not sure if this is correct, probably wrong but still keep it here.
35
+ #[ cfg( feature = "master" ) ]
36
+ variable_alloca. set_location ( dbg_loc) ;
27
37
}
28
38
29
39
fn insert_reference_to_gdb_debug_scripts_section_global ( & mut self ) {
30
40
// TODO(antoyo): insert reference to gdb debug scripts section global.
31
41
}
32
42
43
+ /// FIXME(tempdragon): Currently, this function is not yet implemented. It seems that the
44
+ /// debug name and the mangled name should both be included in the LValues.
45
+ /// Besides, a function to get the rvalue type(m_is_lvalue) should also be included.
33
46
fn set_var_name ( & mut self , _value : RValue < ' gcc > , _name : & str ) {
34
- unimplemented ! ( ) ;
35
47
}
36
48
37
- fn set_dbg_loc ( & mut self , _dbg_loc : Self :: DILocation ) {
38
- unimplemented ! ( ) ;
49
+ fn set_dbg_loc ( & mut self , dbg_loc : Self :: DILocation ) {
50
+ self . loc = Some ( dbg_loc) ;
51
+ }
52
+ }
53
+
54
+ /// Generate the `debug_context` in an MIR Body.
55
+ /// # Souce of Origin
56
+ /// Copied from `create_scope_map.rs` of rustc_codegen_llvm
57
+ 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
+ /// Update the `debug_context`, adding new scope to it,
88
+ /// if it's not added as is denoted in `instantiated`.
89
+ ///
90
+ /// # Souce of Origin
91
+ /// Copied from `create_scope_map.rs` of rustc_codegen_llvm
92
+ /// FIXME(tempdragon/?): Add Scope Support Here.
93
+ fn make_mir_scope < ' gcc , ' tcx > (
94
+ cx : & CodegenCx < ' gcc , ' tcx > ,
95
+ instance : Instance < ' tcx > ,
96
+ mir : & Body < ' tcx > ,
97
+ variables : & Option < BitSet < SourceScope > > ,
98
+ debug_context : & mut FunctionDebugContext < ' tcx , ( ) , Location < ' gcc > > ,
99
+ instantiated : & mut BitSet < SourceScope > ,
100
+ scope : SourceScope ,
101
+ ) {
102
+ if instantiated. contains ( scope) {
103
+ return ;
104
+ }
105
+
106
+ let scope_data = & mir. source_scopes [ scope] ;
107
+ let parent_scope = if let Some ( parent) = scope_data. parent_scope {
108
+ make_mir_scope ( cx, instance, mir, variables, debug_context, instantiated, parent) ;
109
+ debug_context. scopes [ parent]
110
+ } else {
111
+ // The root is the function itself.
112
+ let file = cx. sess ( ) . source_map ( ) . lookup_source_file ( mir. span . lo ( ) ) ;
113
+ debug_context. scopes [ scope] = DebugScope {
114
+ file_start_pos : file. start_pos ,
115
+ file_end_pos : file. end_position ( ) ,
116
+ ..debug_context. scopes [ scope]
117
+ } ;
118
+ instantiated. insert ( scope) ;
119
+ return ;
120
+ } ;
121
+
122
+ if let Some ( vars) = variables
123
+ {
124
+ if !vars. contains ( scope)
125
+ && scope_data. inlined . is_none ( ) {
126
+ // Do not create a DIScope if there are no variables defined in this
127
+ // MIR `SourceScope`, and it's not `inlined`, to avoid debuginfo bloat.
128
+ debug_context. scopes [ scope] = parent_scope;
129
+ instantiated. insert ( scope) ;
130
+ return ;
131
+ }
132
+ }
133
+
134
+ let loc = cx. lookup_debug_loc ( scope_data. span . lo ( ) ) ;
135
+
136
+ // FIXME(tempdragon): Add the scope related code here if the scope is supported.
137
+ let dbg_scope = ( ) ;
138
+
139
+ let inlined_at = scope_data. inlined . map ( |( _, callsite_span) | {
140
+ // FIXME(eddyb) this doesn't account for the macro-related
141
+ // `Span` fixups that `rustc_codegen_ssa::mir::debuginfo` does.
142
+ let callsite_scope = parent_scope. adjust_dbg_scope_for_span ( cx, callsite_span) ;
143
+ cx. dbg_loc ( callsite_scope, parent_scope. inlined_at , callsite_span)
144
+ } ) ;
145
+ let p_inlined_at = parent_scope. inlined_at ;
146
+ // TODO(tempdragon): dbg_scope: Add support for scope extension here.
147
+ inlined_at. or ( p_inlined_at) ;
148
+
149
+ debug_context. scopes [ scope] = DebugScope {
150
+ dbg_scope,
151
+ inlined_at,
152
+ file_start_pos : loc. file . start_pos ,
153
+ file_end_pos : loc. file . end_position ( ) ,
154
+ } ;
155
+ instantiated. insert ( scope) ;
156
+ }
157
+
158
+ /// A source code location used to generate debug information.
159
+ // FIXME(eddyb) rename this to better indicate it's a duplicate of
160
+ // `rustc_span::Loc` rather than `DILocation`, perhaps by making
161
+ // `lookup_char_pos` return the right information instead.
162
+ pub struct DebugLoc {
163
+ /// Information about the original source file.
164
+ pub file : Lrc < SourceFile > ,
165
+ /// The (1-based) line number.
166
+ pub line : u32 ,
167
+ /// The (1-based) column number.
168
+ pub col : u32 ,
169
+ }
170
+
171
+ impl < ' gcc , ' tcx > CodegenCx < ' gcc , ' tcx > {
172
+ /// Looks up debug source information about a `BytePos`.
173
+ // FIXME(eddyb) rename this to better indicate it's a duplicate of
174
+ // `lookup_char_pos` rather than `dbg_loc`, perhaps by making
175
+ // `lookup_char_pos` return the right information instead.
176
+ // Source of Origin: cg_llvm
177
+ pub fn lookup_debug_loc ( & self , pos : BytePos ) -> DebugLoc {
178
+ let ( file, line, col) = match self . sess ( ) . source_map ( ) . lookup_line ( pos) {
179
+ Ok ( SourceFileAndLine { sf : file, line } ) => {
180
+ let line_pos = file. lines ( ) [ line] ;
181
+
182
+ // Use 1-based indexing.
183
+ let line = ( line + 1 ) as u32 ;
184
+ let col = ( file. relative_position ( pos) - line_pos) . to_u32 ( ) + 1 ;
185
+
186
+ ( file, line, col)
187
+ }
188
+ Err ( file) => ( file, UNKNOWN_LINE_NUMBER , UNKNOWN_COLUMN_NUMBER ) ,
189
+ } ;
190
+
191
+ // For MSVC, omit the column number.
192
+ // Otherwise, emit it. This mimics clang behaviour.
193
+ // See discussion in https://github.com/rust-lang/rust/issues/42921
194
+ if self . sess ( ) . target . is_like_msvc {
195
+ DebugLoc { file, line, col : UNKNOWN_COLUMN_NUMBER }
196
+ } else {
197
+ DebugLoc { file, line, col }
198
+ }
39
199
}
40
200
}
41
201
@@ -51,25 +211,44 @@ impl<'gcc, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
51
211
52
212
fn create_function_debug_context (
53
213
& self ,
54
- _instance : Instance < ' tcx > ,
55
- _fn_abi : & FnAbi < ' tcx , Ty < ' tcx > > ,
56
- _llfn : RValue < ' gcc > ,
57
- _mir : & mir:: Body < ' tcx > ,
214
+ instance : Instance < ' tcx > ,
215
+ fn_abi : & FnAbi < ' tcx , Ty < ' tcx > > ,
216
+ llfn : RValue < ' gcc > ,
217
+ mir : & mir:: Body < ' tcx > ,
58
218
) -> Option < FunctionDebugContext < ' tcx , Self :: DIScope , Self :: DILocation > > {
59
219
// TODO(antoyo)
60
- None
220
+ if self . sess ( ) . opts . debuginfo == DebugInfo :: None {
221
+ return None ;
222
+ }
223
+
224
+ // Initialize fn debug context (including scopes).
225
+ let empty_scope = DebugScope {
226
+ dbg_scope : self . dbg_scope_fn ( instance, fn_abi, Some ( llfn) ) ,
227
+ inlined_at : None ,
228
+ file_start_pos : BytePos ( 0 ) ,
229
+ file_end_pos : BytePos ( 0 ) ,
230
+ } ;
231
+ let mut fn_debug_context = FunctionDebugContext {
232
+ scopes : IndexVec :: from_elem ( empty_scope, & mir. source_scopes . as_slice ( ) ) ,
233
+ inlined_function_scopes : Default :: default ( ) ,
234
+ } ;
235
+
236
+ // Fill in all the scopes, with the information from the MIR body.
237
+ compute_mir_scopes ( self , instance, mir, & mut fn_debug_context) ;
238
+
239
+ Some ( fn_debug_context)
61
240
}
62
241
63
242
fn extend_scope_to_file (
64
243
& self ,
65
244
_scope_metadata : Self :: DIScope ,
66
245
_file : & SourceFile ,
67
246
) -> Self :: DIScope {
68
- unimplemented ! ( ) ;
247
+ // TODO(antoyo): implement.
69
248
}
70
249
71
250
fn debuginfo_finalize ( & self ) {
72
- // TODO(antoyo )
251
+ self . context . set_debug_info ( true )
73
252
}
74
253
75
254
fn create_dbg_var (
@@ -80,7 +259,7 @@ impl<'gcc, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
80
259
_variable_kind : VariableKind ,
81
260
_span : Span ,
82
261
) -> Self :: DIVariable {
83
- unimplemented ! ( ) ;
262
+ ( )
84
263
}
85
264
86
265
fn dbg_scope_fn (
@@ -89,15 +268,46 @@ impl<'gcc, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
89
268
_fn_abi : & FnAbi < ' tcx , Ty < ' tcx > > ,
90
269
_maybe_definition_llfn : Option < RValue < ' gcc > > ,
91
270
) -> Self :: DIScope {
92
- unimplemented ! ( ) ;
271
+ // TODO(antoyo): implement.
93
272
}
94
273
95
274
fn dbg_loc (
96
275
& self ,
97
276
_scope : Self :: DIScope ,
98
277
_inlined_at : Option < Self :: DILocation > ,
99
- _span : Span ,
278
+ span : Span ,
100
279
) -> Self :: DILocation {
101
- unimplemented ! ( ) ;
280
+ let pos = span. lo ( ) ;
281
+ let DebugLoc { file, line, col} = self . lookup_debug_loc ( pos) ;
282
+ let loc = match & file. name {
283
+ rustc_span:: FileName :: Real ( name) => match name {
284
+ rustc_span:: RealFileName :: LocalPath ( name) => {
285
+ if let Some ( name) = name. to_str ( ) {
286
+ self . context
287
+ . new_location ( name, line as i32 , col as i32 )
288
+ } else {
289
+ Location :: null ( )
290
+ }
291
+ }
292
+ rustc_span:: RealFileName :: Remapped {
293
+ local_path,
294
+ virtual_name : _,
295
+ } => if let Some ( name) = local_path. as_ref ( ) {
296
+ if let Some ( name) = name. to_str ( ) {
297
+ self . context . new_location (
298
+ name,
299
+ line as i32 ,
300
+ col as i32 ,
301
+ )
302
+ } else {
303
+ Location :: null ( )
304
+ }
305
+ } else {
306
+ Location :: null ( )
307
+ } ,
308
+ } ,
309
+ _ => Location :: null ( ) ,
310
+ } ;
311
+ loc
102
312
}
103
313
}
0 commit comments