Skip to content

Commit c638def

Browse files
committed
feat(debuginfo): Init Commit for debuginfo Support
TODO: 1. Add int.rs locations 2. Add demangling support 3. Add debug scope support 4. Add vtable support 5. Clean up builder.rs locations
1 parent 2262073 commit c638def

File tree

6 files changed

+398
-212
lines changed

6 files changed

+398
-212
lines changed

src/base.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -184,8 +184,8 @@ pub fn compile_codegen_unit(tcx: TyCtxt<'_>, cgu_name: Symbol, target_info: Lock
184184
// wrapper here
185185
maybe_create_entry_wrapper::<Builder<'_, '_, '_>>(&cx);
186186

187-
// Finalize debuginfo
188-
if cx.sess().opts.debuginfo != DebugInfo::None {
187+
// FINALIZE debuginfo
188+
if cx.sess().opts.debuginfo != DebugInfo::None {
189189
cx.debuginfo_finalize();
190190
}
191191
}

src/builder.rs

Lines changed: 182 additions & 180 deletions
Large diffs are not rendered by default.

src/context.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::cell::{Cell, RefCell};
22

3-
use gccjit::{Block, CType, Context, Function, FunctionPtrType, FunctionType, LValue, RValue, Type};
3+
use gccjit::{Block, CType, Context, Function, FunctionPtrType, FunctionType, LValue, Location, RValue, Type};
44
use rustc_codegen_ssa::base::wants_msvc_seh;
55
use rustc_codegen_ssa::traits::{
66
BackendTypes,
@@ -345,7 +345,7 @@ impl<'gcc, 'tcx> BackendTypes for CodegenCx<'gcc, 'tcx> {
345345
type Funclet = (); // TODO(antoyo)
346346

347347
type DIScope = (); // TODO(antoyo)
348-
type DILocation = (); // TODO(antoyo)
348+
type DILocation = Location<'gcc>; // TODO(antoyo)
349349
type DIVariable = (); // TODO(antoyo)
350350
}
351351

src/debuginfo.rs

Lines changed: 205 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,172 @@
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};
33
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};
57
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};
710
use rustc_target::abi::call::FnAbi;
811
use rustc_target::abi::Size;
12+
use rustc_data_structures::sync::Lrc;
13+
use crate::rustc_index::Idx;
914
use std::ops::Range;
1015

1116
use crate::builder::Builder;
1217
use crate::context::CodegenCx;
1318

19+
pub(super) const UNKNOWN_LINE_NUMBER: u32 = 0;
20+
pub(super) const UNKNOWN_COLUMN_NUMBER: u32 = 0;
21+
1422
impl<'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
}

src/int.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
195195
let a_type = a.get_type();
196196
let b_type = b.get_type();
197197
if (self.is_native_int_type_or_bool(a_type) && self.is_native_int_type_or_bool(b_type)) || (a_type.is_vector() && b_type.is_vector()) {
198-
self.context.new_binary_op(None, operation, a_type, a, b)
198+
self.context.new_binary_op(self.loc, operation, a_type, a, b)
199199
}
200200
else {
201201
debug_assert!(a_type.dyncast_array().is_some());
@@ -208,10 +208,10 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
208208
"u"
209209
};
210210
let func_name = format!("__{}{}ti3", sign, operation_name);
211-
let param_a = self.context.new_parameter(None, a_type, "a");
212-
let param_b = self.context.new_parameter(None, b_type, "b");
213-
let func = self.context.new_function(None, FunctionType::Extern, a_type, &[param_a, param_b], func_name, false);
214-
self.context.new_call(None, func, &[a, b])
211+
let param_a = self.context.new_parameter(self.loc, a_type, "a");
212+
let param_b = self.context.new_parameter(self.loc, b_type, "b");
213+
let func = self.context.new_function(self.loc, FunctionType::Extern, a_type, &[param_a, param_b], func_name, false);
214+
self.context.new_call(self.loc, func, &[a, b])
215215
}
216216
}
217217

src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ extern crate rustc_errors;
3939
extern crate rustc_fluent_macro;
4040
extern crate rustc_fs_util;
4141
extern crate rustc_hir;
42+
extern crate rustc_index;
4243
#[cfg(feature="master")]
4344
extern crate rustc_interface;
4445
extern crate rustc_macros;
@@ -174,7 +175,7 @@ impl CodegenBackend for GccCodegenBackend {
174175
crate::DEFAULT_LOCALE_RESOURCE
175176
}
176177

177-
fn init(&self, sess: &Session) {
178+
fn init(&self, sess: &Session) {
178179
#[cfg(feature="master")]
179180
{
180181
let target_cpu = target_cpu(sess);

0 commit comments

Comments
 (0)