mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-28 19:17:43 +00:00

tree-wide: parallel: Fully removed all `Lrc`, replaced with `Arc` tree-wide: parallel: Fully removed all `Lrc`, replaced with `Arc` This is continuation of https://github.com/rust-lang/rust/pull/132282 . I'm pretty sure I did everything right. In particular, I searched all occurrences of `Lrc` in submodules and made sure that they don't need replacement. There are other possibilities, through. We can define `enum Lrc<T> { Rc(Rc<T>), Arc(Arc<T>) }`. Or we can make `Lrc` a union and on every clone we can read from special thread-local variable. Or we can add a generic parameter to `Lrc` and, yes, this parameter will be everywhere across all codebase. So, if you think we should take some alternative approach, then don't merge this PR. But if it is decided to stick with `Arc`, then, please, merge. cc "Parallel Rustc Front-end" ( https://github.com/rust-lang/rust/issues/113349 ) r? SparrowLii `@rustbot` label WG-compiler-parallel
320 lines
11 KiB
Rust
320 lines
11 KiB
Rust
use std::ops::Range;
|
|
use std::sync::Arc;
|
|
|
|
use gccjit::{Location, RValue};
|
|
use rustc_abi::Size;
|
|
use rustc_codegen_ssa::mir::debuginfo::{DebugScope, FunctionDebugContext, VariableKind};
|
|
use rustc_codegen_ssa::traits::{DebugInfoBuilderMethods, DebugInfoCodegenMethods};
|
|
use rustc_index::bit_set::DenseBitSet;
|
|
use rustc_index::{Idx, IndexVec};
|
|
use rustc_middle::mir::{self, Body, SourceScope};
|
|
use rustc_middle::ty::{ExistentialTraitRef, Instance, Ty};
|
|
use rustc_session::config::DebugInfo;
|
|
use rustc_span::{BytePos, Pos, SourceFile, SourceFileAndLine, Span, Symbol};
|
|
use rustc_target::callconv::FnAbi;
|
|
|
|
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,
|
|
_dbg_loc: Self::DILocation,
|
|
_variable_alloca: Self::Value,
|
|
_direct_offset: Size,
|
|
_indirect_offsets: &[Size],
|
|
_fragment: Option<Range<Size>>,
|
|
) {
|
|
// 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.
|
|
}
|
|
|
|
/// 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);
|
|
}
|
|
|
|
fn clear_dbg_loc(&mut self) {
|
|
self.location = None;
|
|
}
|
|
|
|
fn get_dbg_loc(&self) -> Option<Self::DILocation> {
|
|
self.location
|
|
}
|
|
}
|
|
|
|
/// Generate the `debug_context` in an MIR Body.
|
|
/// # Source 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 = DenseBitSet::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 = DenseBitSet::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`.
|
|
///
|
|
/// # Source 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<DenseBitSet<SourceScope>>,
|
|
debug_context: &mut FunctionDebugContext<'tcx, (), Location<'gcc>>,
|
|
instantiated: &mut DenseBitSet<SourceScope>,
|
|
scope: SourceScope,
|
|
) {
|
|
if instantiated.contains(scope) {
|
|
return;
|
|
}
|
|
|
|
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(ref 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.
|
|
|
|
// TODO(tempdragon): Add scope support and then revert to cg_llvm version of this closure
|
|
// NOTE: These variables passed () here.
|
|
// Changed to comply to clippy.
|
|
|
|
/* 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: Arc<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 }
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<'gcc, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
|
|
fn create_vtable_debuginfo(
|
|
&self,
|
|
_ty: Ty<'tcx>,
|
|
_trait_ref: Option<ExistentialTraitRef<'tcx>>,
|
|
_vtable: Self::Value,
|
|
) {
|
|
// TODO(antoyo)
|
|
}
|
|
|
|
fn create_function_debug_context(
|
|
&self,
|
|
instance: Instance<'tcx>,
|
|
fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
|
|
llfn: RValue<'gcc>,
|
|
mir: &mir::Body<'tcx>,
|
|
) -> Option<FunctionDebugContext<'tcx, Self::DIScope, Self::DILocation>> {
|
|
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(
|
|
&self,
|
|
_scope_metadata: Self::DIScope,
|
|
_file: &SourceFile,
|
|
) -> Self::DIScope {
|
|
// TODO(antoyo): implement.
|
|
}
|
|
|
|
fn debuginfo_finalize(&self) {
|
|
self.context.set_debug_info(true)
|
|
}
|
|
|
|
fn create_dbg_var(
|
|
&self,
|
|
_variable_name: Symbol,
|
|
_variable_type: Ty<'tcx>,
|
|
_scope_metadata: Self::DIScope,
|
|
_variable_kind: VariableKind,
|
|
_span: Span,
|
|
) -> Self::DIVariable {
|
|
}
|
|
|
|
fn dbg_scope_fn(
|
|
&self,
|
|
_instance: Instance<'tcx>,
|
|
_fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
|
|
_maybe_definition_llfn: Option<RValue<'gcc>>,
|
|
) -> Self::DIScope {
|
|
// TODO(antoyo): implement.
|
|
}
|
|
|
|
fn dbg_loc(
|
|
&self,
|
|
_scope: Self::DIScope,
|
|
_inlined_at: Option<Self::DILocation>,
|
|
span: Span,
|
|
) -> Self::DILocation {
|
|
let pos = span.lo();
|
|
let DebugLoc { file, line, col } = self.lookup_debug_loc(pos);
|
|
let loc = match file.name {
|
|
rustc_span::FileName::Real(ref name) => match *name {
|
|
rustc_span::RealFileName::LocalPath(ref 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 {
|
|
ref local_path,
|
|
virtual_name: ref _unused,
|
|
} => {
|
|
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
|
|
}
|
|
}
|