Merge commit 'b385428e3ddf330805241e7758e773f933357c4b' into subtree-update_cg_gcc_2024-03-05
This commit is contained in:
@@ -1,9 +1,14 @@
|
||||
use gccjit::RValue;
|
||||
use rustc_codegen_ssa::mir::debuginfo::{FunctionDebugContext, VariableKind};
|
||||
use crate::rustc_index::Idx;
|
||||
use gccjit::{Location, RValue};
|
||||
use rustc_codegen_ssa::mir::debuginfo::{DebugScope, FunctionDebugContext, VariableKind};
|
||||
use rustc_codegen_ssa::traits::{DebugInfoBuilderMethods, DebugInfoMethods};
|
||||
use rustc_middle::mir;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_index::bit_set::BitSet;
|
||||
use rustc_index::IndexVec;
|
||||
use rustc_middle::mir::{self, Body, SourceScope};
|
||||
use rustc_middle::ty::{Instance, PolyExistentialTraitRef, Ty};
|
||||
use rustc_span::{SourceFile, Span, Symbol};
|
||||
use rustc_session::config::DebugInfo;
|
||||
use rustc_span::{BytePos, Pos, SourceFile, SourceFileAndLine, Span, Symbol};
|
||||
use rustc_target::abi::call::FnAbi;
|
||||
use rustc_target::abi::Size;
|
||||
use std::ops::Range;
|
||||
@@ -11,31 +16,183 @@ use std::ops::Range;
|
||||
use crate::builder::Builder;
|
||||
use crate::context::CodegenCx;
|
||||
|
||||
pub(super) const UNKNOWN_LINE_NUMBER: u32 = 0;
|
||||
pub(super) const UNKNOWN_COLUMN_NUMBER: u32 = 0;
|
||||
|
||||
impl<'a, 'gcc, 'tcx> DebugInfoBuilderMethods for Builder<'a, 'gcc, 'tcx> {
|
||||
// FIXME(eddyb) find a common convention for all of the debuginfo-related
|
||||
// names (choose between `dbg`, `debug`, `debuginfo`, `debug_info` etc.).
|
||||
fn dbg_var_addr(
|
||||
&mut self,
|
||||
_dbg_var: Self::DIVariable,
|
||||
_scope_metadata: Self::DIScope,
|
||||
_dbg_loc: Self::DILocation,
|
||||
_variable_alloca: Self::Value,
|
||||
_direct_offset: Size,
|
||||
_indirect_offsets: &[Size],
|
||||
_fragment: Option<Range<Size>>,
|
||||
) {
|
||||
unimplemented!();
|
||||
// FIXME(tempdragon): Not sure if this is correct, probably wrong but still keep it here.
|
||||
#[cfg(feature = "master")]
|
||||
_variable_alloca.set_location(_dbg_loc);
|
||||
}
|
||||
|
||||
fn insert_reference_to_gdb_debug_scripts_section_global(&mut self) {
|
||||
// TODO(antoyo): insert reference to gdb debug scripts section global.
|
||||
}
|
||||
|
||||
fn set_var_name(&mut self, _value: RValue<'gcc>, _name: &str) {
|
||||
unimplemented!();
|
||||
/// FIXME(tempdragon): Currently, this function is not yet implemented. It seems that the
|
||||
/// debug name and the mangled name should both be included in the LValues.
|
||||
/// Besides, a function to get the rvalue type(m_is_lvalue) should also be included.
|
||||
fn set_var_name(&mut self, _value: RValue<'gcc>, _name: &str) {}
|
||||
|
||||
fn set_dbg_loc(&mut self, dbg_loc: Self::DILocation) {
|
||||
self.location = Some(dbg_loc);
|
||||
}
|
||||
}
|
||||
|
||||
/// Generate the `debug_context` in an MIR Body.
|
||||
/// # Souce of Origin
|
||||
/// Copied from `create_scope_map.rs` of rustc_codegen_llvm
|
||||
fn compute_mir_scopes<'gcc, 'tcx>(
|
||||
cx: &CodegenCx<'gcc, 'tcx>,
|
||||
instance: Instance<'tcx>,
|
||||
mir: &Body<'tcx>,
|
||||
debug_context: &mut FunctionDebugContext<'tcx, (), Location<'gcc>>,
|
||||
) {
|
||||
// Find all scopes with variables defined in them.
|
||||
let variables = if cx.sess().opts.debuginfo == DebugInfo::Full {
|
||||
let mut vars = BitSet::new_empty(mir.source_scopes.len());
|
||||
// FIXME(eddyb) take into account that arguments always have debuginfo,
|
||||
// irrespective of their name (assuming full debuginfo is enabled).
|
||||
// NOTE(eddyb) actually, on second thought, those are always in the
|
||||
// function scope, which always exists.
|
||||
for var_debug_info in &mir.var_debug_info {
|
||||
vars.insert(var_debug_info.source_info.scope);
|
||||
}
|
||||
Some(vars)
|
||||
} else {
|
||||
// Nothing to emit, of course.
|
||||
None
|
||||
};
|
||||
let mut instantiated = BitSet::new_empty(mir.source_scopes.len());
|
||||
// Instantiate all scopes.
|
||||
for idx in 0..mir.source_scopes.len() {
|
||||
let scope = SourceScope::new(idx);
|
||||
make_mir_scope(cx, instance, mir, &variables, debug_context, &mut instantiated, scope);
|
||||
}
|
||||
assert!(instantiated.count() == mir.source_scopes.len());
|
||||
}
|
||||
|
||||
/// Update the `debug_context`, adding new scope to it,
|
||||
/// if it's not added as is denoted in `instantiated`.
|
||||
///
|
||||
/// # Souce of Origin
|
||||
/// Copied from `create_scope_map.rs` of rustc_codegen_llvm
|
||||
/// FIXME(tempdragon/?): Add Scope Support Here.
|
||||
fn make_mir_scope<'gcc, 'tcx>(
|
||||
cx: &CodegenCx<'gcc, 'tcx>,
|
||||
instance: Instance<'tcx>,
|
||||
mir: &Body<'tcx>,
|
||||
variables: &Option<BitSet<SourceScope>>,
|
||||
debug_context: &mut FunctionDebugContext<'tcx, (), Location<'gcc>>,
|
||||
instantiated: &mut BitSet<SourceScope>,
|
||||
scope: SourceScope,
|
||||
) {
|
||||
if instantiated.contains(scope) {
|
||||
return;
|
||||
}
|
||||
|
||||
fn set_dbg_loc(&mut self, _dbg_loc: Self::DILocation) {
|
||||
unimplemented!();
|
||||
let scope_data = &mir.source_scopes[scope];
|
||||
let parent_scope = if let Some(parent) = scope_data.parent_scope {
|
||||
make_mir_scope(cx, instance, mir, variables, debug_context, instantiated, parent);
|
||||
debug_context.scopes[parent]
|
||||
} else {
|
||||
// The root is the function itself.
|
||||
let file = cx.sess().source_map().lookup_source_file(mir.span.lo());
|
||||
debug_context.scopes[scope] = DebugScope {
|
||||
file_start_pos: file.start_pos,
|
||||
file_end_pos: file.end_position(),
|
||||
..debug_context.scopes[scope]
|
||||
};
|
||||
instantiated.insert(scope);
|
||||
return;
|
||||
};
|
||||
|
||||
if let Some(vars) = variables {
|
||||
if !vars.contains(scope) && scope_data.inlined.is_none() {
|
||||
// Do not create a DIScope if there are no variables defined in this
|
||||
// MIR `SourceScope`, and it's not `inlined`, to avoid debuginfo bloat.
|
||||
debug_context.scopes[scope] = parent_scope;
|
||||
instantiated.insert(scope);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
let loc = cx.lookup_debug_loc(scope_data.span.lo());
|
||||
|
||||
// FIXME(tempdragon): Add the scope related code here if the scope is supported.
|
||||
let dbg_scope = ();
|
||||
|
||||
let inlined_at = scope_data.inlined.map(|(_, callsite_span)| {
|
||||
// FIXME(eddyb) this doesn't account for the macro-related
|
||||
// `Span` fixups that `rustc_codegen_ssa::mir::debuginfo` does.
|
||||
let callsite_scope = parent_scope.adjust_dbg_scope_for_span(cx, callsite_span);
|
||||
cx.dbg_loc(callsite_scope, parent_scope.inlined_at, callsite_span)
|
||||
});
|
||||
let p_inlined_at = parent_scope.inlined_at;
|
||||
// TODO(tempdragon): dbg_scope: Add support for scope extension here.
|
||||
inlined_at.or(p_inlined_at);
|
||||
|
||||
debug_context.scopes[scope] = DebugScope {
|
||||
dbg_scope,
|
||||
inlined_at,
|
||||
file_start_pos: loc.file.start_pos,
|
||||
file_end_pos: loc.file.end_position(),
|
||||
};
|
||||
instantiated.insert(scope);
|
||||
}
|
||||
|
||||
/// A source code location used to generate debug information.
|
||||
// FIXME(eddyb) rename this to better indicate it's a duplicate of
|
||||
// `rustc_span::Loc` rather than `DILocation`, perhaps by making
|
||||
// `lookup_char_pos` return the right information instead.
|
||||
pub struct DebugLoc {
|
||||
/// Information about the original source file.
|
||||
pub file: Lrc<SourceFile>,
|
||||
/// The (1-based) line number.
|
||||
pub line: u32,
|
||||
/// The (1-based) column number.
|
||||
pub col: u32,
|
||||
}
|
||||
|
||||
impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
|
||||
/// Looks up debug source information about a `BytePos`.
|
||||
// FIXME(eddyb) rename this to better indicate it's a duplicate of
|
||||
// `lookup_char_pos` rather than `dbg_loc`, perhaps by making
|
||||
// `lookup_char_pos` return the right information instead.
|
||||
// Source of Origin: cg_llvm
|
||||
pub fn lookup_debug_loc(&self, pos: BytePos) -> DebugLoc {
|
||||
let (file, line, col) = match self.sess().source_map().lookup_line(pos) {
|
||||
Ok(SourceFileAndLine { sf: file, line }) => {
|
||||
let line_pos = file.lines()[line];
|
||||
|
||||
// Use 1-based indexing.
|
||||
let line = (line + 1) as u32;
|
||||
let col = (file.relative_position(pos) - line_pos).to_u32() + 1;
|
||||
|
||||
(file, line, col)
|
||||
}
|
||||
Err(file) => (file, UNKNOWN_LINE_NUMBER, UNKNOWN_COLUMN_NUMBER),
|
||||
};
|
||||
|
||||
// For MSVC, omit the column number.
|
||||
// Otherwise, emit it. This mimics clang behaviour.
|
||||
// See discussion in https://github.com/rust-lang/rust/issues/42921
|
||||
if self.sess().target.is_like_msvc {
|
||||
DebugLoc { file, line, col: UNKNOWN_COLUMN_NUMBER }
|
||||
} else {
|
||||
DebugLoc { file, line, col }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,13 +208,31 @@ impl<'gcc, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
|
||||
|
||||
fn create_function_debug_context(
|
||||
&self,
|
||||
_instance: Instance<'tcx>,
|
||||
_fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
|
||||
_llfn: RValue<'gcc>,
|
||||
_mir: &mir::Body<'tcx>,
|
||||
instance: Instance<'tcx>,
|
||||
fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
|
||||
llfn: RValue<'gcc>,
|
||||
mir: &mir::Body<'tcx>,
|
||||
) -> Option<FunctionDebugContext<'tcx, Self::DIScope, Self::DILocation>> {
|
||||
// TODO(antoyo)
|
||||
None
|
||||
if self.sess().opts.debuginfo == DebugInfo::None {
|
||||
return None;
|
||||
}
|
||||
|
||||
// Initialize fn debug context (including scopes).
|
||||
let empty_scope = DebugScope {
|
||||
dbg_scope: self.dbg_scope_fn(instance, fn_abi, Some(llfn)),
|
||||
inlined_at: None,
|
||||
file_start_pos: BytePos(0),
|
||||
file_end_pos: BytePos(0),
|
||||
};
|
||||
let mut fn_debug_context = FunctionDebugContext {
|
||||
scopes: IndexVec::from_elem(empty_scope, &mir.source_scopes.as_slice()),
|
||||
inlined_function_scopes: Default::default(),
|
||||
};
|
||||
|
||||
// Fill in all the scopes, with the information from the MIR body.
|
||||
compute_mir_scopes(self, instance, mir, &mut fn_debug_context);
|
||||
|
||||
Some(fn_debug_context)
|
||||
}
|
||||
|
||||
fn extend_scope_to_file(
|
||||
@@ -65,11 +240,11 @@ impl<'gcc, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
|
||||
_scope_metadata: Self::DIScope,
|
||||
_file: &SourceFile,
|
||||
) -> Self::DIScope {
|
||||
unimplemented!();
|
||||
// TODO(antoyo): implement.
|
||||
}
|
||||
|
||||
fn debuginfo_finalize(&self) {
|
||||
// TODO(antoyo)
|
||||
self.context.set_debug_info(true)
|
||||
}
|
||||
|
||||
fn create_dbg_var(
|
||||
@@ -80,7 +255,6 @@ impl<'gcc, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
|
||||
_variable_kind: VariableKind,
|
||||
_span: Span,
|
||||
) -> Self::DIVariable {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
fn dbg_scope_fn(
|
||||
@@ -89,15 +263,40 @@ impl<'gcc, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
|
||||
_fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
|
||||
_maybe_definition_llfn: Option<RValue<'gcc>>,
|
||||
) -> Self::DIScope {
|
||||
unimplemented!();
|
||||
// TODO(antoyo): implement.
|
||||
}
|
||||
|
||||
fn dbg_loc(
|
||||
&self,
|
||||
_scope: Self::DIScope,
|
||||
_inlined_at: Option<Self::DILocation>,
|
||||
_span: Span,
|
||||
span: Span,
|
||||
) -> Self::DILocation {
|
||||
unimplemented!();
|
||||
let pos = span.lo();
|
||||
let DebugLoc { file, line, col } = self.lookup_debug_loc(pos);
|
||||
let loc = match &file.name {
|
||||
rustc_span::FileName::Real(name) => match name {
|
||||
rustc_span::RealFileName::LocalPath(name) => {
|
||||
if let Some(name) = name.to_str() {
|
||||
self.context.new_location(name, line as i32, col as i32)
|
||||
} else {
|
||||
Location::null()
|
||||
}
|
||||
}
|
||||
rustc_span::RealFileName::Remapped { local_path, virtual_name: _ } => {
|
||||
if let Some(name) = local_path.as_ref() {
|
||||
if let Some(name) = name.to_str() {
|
||||
self.context.new_location(name, line as i32, col as i32)
|
||||
} else {
|
||||
Location::null()
|
||||
}
|
||||
} else {
|
||||
Location::null()
|
||||
}
|
||||
}
|
||||
},
|
||||
_ => Location::null(),
|
||||
};
|
||||
loc
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user