1
Fork 0

Auto merge of #68965 - eddyb:mir-inline-scope, r=nagisa,oli-obk

rustc_mir: track inlined callees in SourceScopeData.

We now record which MIR scopes are the roots of *other* (inlined) functions's scope trees, which allows us to generate the correct debuginfo in codegen, similar to what LLVM inlining generates.
This PR makes the `ui` test `backtrace-debuginfo` pass, if the MIR inliner is turned on by default.

Also, `#[track_caller]` is now correct in the face of MIR inlining (cc `@anp).`

Fixes #76997.

r? `@rust-lang/wg-mir-opt`
This commit is contained in:
bors 2020-10-26 18:50:22 +00:00
commit 0da6d42f29
68 changed files with 879 additions and 619 deletions

View file

@ -56,6 +56,7 @@ impl BackendTypes for Builder<'_, 'll, 'tcx> {
type Funclet = <CodegenCx<'ll, 'tcx> as BackendTypes>::Funclet; type Funclet = <CodegenCx<'ll, 'tcx> as BackendTypes>::Funclet;
type DIScope = <CodegenCx<'ll, 'tcx> as BackendTypes>::DIScope; type DIScope = <CodegenCx<'ll, 'tcx> as BackendTypes>::DIScope;
type DILocation = <CodegenCx<'ll, 'tcx> as BackendTypes>::DILocation;
type DIVariable = <CodegenCx<'ll, 'tcx> as BackendTypes>::DIVariable; type DIVariable = <CodegenCx<'ll, 'tcx> as BackendTypes>::DIVariable;
} }

View file

@ -80,6 +80,7 @@ impl Funclet<'ll> {
impl BackendTypes for CodegenCx<'ll, 'tcx> { impl BackendTypes for CodegenCx<'ll, 'tcx> {
type Value = &'ll Value; type Value = &'ll Value;
// FIXME(eddyb) replace this with a `Function` "subclass" of `Value`.
type Function = &'ll Value; type Function = &'ll Value;
type BasicBlock = &'ll BasicBlock; type BasicBlock = &'ll BasicBlock;
@ -87,6 +88,7 @@ impl BackendTypes for CodegenCx<'ll, 'tcx> {
type Funclet = Funclet<'ll>; type Funclet = Funclet<'ll>;
type DIScope = &'ll llvm::debuginfo::DIScope; type DIScope = &'ll llvm::debuginfo::DIScope;
type DILocation = &'ll llvm::debuginfo::DILocation;
type DIVariable = &'ll llvm::debuginfo::DIVariable; type DIVariable = &'ll llvm::debuginfo::DIVariable;
} }

View file

@ -3,21 +3,26 @@ use super::utils::DIB;
use rustc_codegen_ssa::mir::debuginfo::{DebugScope, FunctionDebugContext}; use rustc_codegen_ssa::mir::debuginfo::{DebugScope, FunctionDebugContext};
use rustc_codegen_ssa::traits::*; use rustc_codegen_ssa::traits::*;
use crate::abi::FnAbi;
use crate::common::CodegenCx; use crate::common::CodegenCx;
use crate::llvm; use crate::llvm;
use crate::llvm::debuginfo::{DIScope, DISubprogram}; use crate::llvm::debuginfo::{DILocation, DIScope};
use rustc_middle::mir::{Body, SourceScope}; use rustc_middle::mir::{Body, SourceScope};
use rustc_middle::ty::layout::FnAbiExt;
use rustc_middle::ty::{self, Instance};
use rustc_session::config::DebugInfo; use rustc_session::config::DebugInfo;
use rustc_index::bit_set::BitSet; use rustc_index::bit_set::BitSet;
use rustc_index::vec::Idx; use rustc_index::vec::Idx;
/// Produces DIScope DIEs for each MIR Scope which has variables defined in it. /// Produces DIScope DIEs for each MIR Scope which has variables defined in it.
// FIXME(eddyb) almost all of this should be in `rustc_codegen_ssa::mir::debuginfo`.
pub fn compute_mir_scopes( pub fn compute_mir_scopes(
cx: &CodegenCx<'ll, '_>, cx: &CodegenCx<'ll, 'tcx>,
mir: &Body<'_>, instance: Instance<'tcx>,
fn_metadata: &'ll DISubprogram, mir: &Body<'tcx>,
debug_context: &mut FunctionDebugContext<&'ll DIScope>, fn_dbg_scope: &'ll DIScope,
debug_context: &mut FunctionDebugContext<&'ll DIScope, &'ll DILocation>,
) { ) {
// Find all the scopes with variables defined in them. // Find all the scopes with variables defined in them.
let mut has_variables = BitSet::new_empty(mir.source_scopes.len()); let mut has_variables = BitSet::new_empty(mir.source_scopes.len());
@ -37,58 +42,82 @@ pub fn compute_mir_scopes(
// Instantiate all scopes. // Instantiate all scopes.
for idx in 0..mir.source_scopes.len() { for idx in 0..mir.source_scopes.len() {
let scope = SourceScope::new(idx); let scope = SourceScope::new(idx);
make_mir_scope(cx, &mir, fn_metadata, &has_variables, debug_context, scope); make_mir_scope(cx, instance, &mir, fn_dbg_scope, &has_variables, debug_context, scope);
} }
} }
fn make_mir_scope( fn make_mir_scope(
cx: &CodegenCx<'ll, '_>, cx: &CodegenCx<'ll, 'tcx>,
mir: &Body<'_>, instance: Instance<'tcx>,
fn_metadata: &'ll DISubprogram, mir: &Body<'tcx>,
fn_dbg_scope: &'ll DIScope,
has_variables: &BitSet<SourceScope>, has_variables: &BitSet<SourceScope>,
debug_context: &mut FunctionDebugContext<&'ll DISubprogram>, debug_context: &mut FunctionDebugContext<&'ll DIScope, &'ll DILocation>,
scope: SourceScope, scope: SourceScope,
) { ) {
if debug_context.scopes[scope].is_valid() { if debug_context.scopes[scope].dbg_scope.is_some() {
return; return;
} }
let scope_data = &mir.source_scopes[scope]; let scope_data = &mir.source_scopes[scope];
let parent_scope = if let Some(parent) = scope_data.parent_scope { let parent_scope = if let Some(parent) = scope_data.parent_scope {
make_mir_scope(cx, mir, fn_metadata, has_variables, debug_context, parent); make_mir_scope(cx, instance, mir, fn_dbg_scope, has_variables, debug_context, parent);
debug_context.scopes[parent] debug_context.scopes[parent]
} else { } else {
// The root is the function itself. // The root is the function itself.
let loc = cx.lookup_debug_loc(mir.span.lo()); let loc = cx.lookup_debug_loc(mir.span.lo());
debug_context.scopes[scope] = DebugScope { debug_context.scopes[scope] = DebugScope {
scope_metadata: Some(fn_metadata), dbg_scope: Some(fn_dbg_scope),
inlined_at: None,
file_start_pos: loc.file.start_pos, file_start_pos: loc.file.start_pos,
file_end_pos: loc.file.end_pos, file_end_pos: loc.file.end_pos,
}; };
return; return;
}; };
if !has_variables.contains(scope) { if !has_variables.contains(scope) && scope_data.inlined.is_none() {
// Do not create a DIScope if there are no variables // Do not create a DIScope if there are no variables defined in this
// defined in this MIR Scope, to avoid debuginfo bloat. // MIR `SourceScope`, and it's not `inlined`, to avoid debuginfo bloat.
debug_context.scopes[scope] = parent_scope; debug_context.scopes[scope] = parent_scope;
return; return;
} }
let loc = cx.lookup_debug_loc(scope_data.span.lo()); let loc = cx.lookup_debug_loc(scope_data.span.lo());
let file_metadata = file_metadata(cx, &loc.file, debug_context.defining_crate); let file_metadata = file_metadata(cx, &loc.file);
let scope_metadata = unsafe { let dbg_scope = match scope_data.inlined {
Some(llvm::LLVMRustDIBuilderCreateLexicalBlock( Some((callee, _)) => {
DIB(cx), // FIXME(eddyb) this would be `self.monomorphize(&callee)`
parent_scope.scope_metadata.unwrap(), // if this is moved to `rustc_codegen_ssa::mir::debuginfo`.
file_metadata, let callee = cx.tcx.subst_and_normalize_erasing_regions(
loc.line.unwrap_or(UNKNOWN_LINE_NUMBER), instance.substs,
loc.col.unwrap_or(UNKNOWN_COLUMN_NUMBER), ty::ParamEnv::reveal_all(),
)) &callee,
);
let callee_fn_abi = FnAbi::of_instance(cx, callee, &[]);
cx.dbg_scope_fn(callee, &callee_fn_abi, None)
}
None => unsafe {
llvm::LLVMRustDIBuilderCreateLexicalBlock(
DIB(cx),
parent_scope.dbg_scope.unwrap(),
file_metadata,
loc.line.unwrap_or(UNKNOWN_LINE_NUMBER),
loc.col.unwrap_or(UNKNOWN_COLUMN_NUMBER),
)
},
}; };
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)
});
debug_context.scopes[scope] = DebugScope { debug_context.scopes[scope] = DebugScope {
scope_metadata, dbg_scope: Some(dbg_scope),
inlined_at: inlined_at.or(parent_scope.inlined_at),
file_start_pos: loc.file.start_pos, file_start_pos: loc.file.start_pos,
file_end_pos: loc.file.end_pos, file_end_pos: loc.file.end_pos,
}; };

View file

@ -28,7 +28,7 @@
//! utilizing a cache. The way to get a shared metadata node when needed is //! utilizing a cache. The way to get a shared metadata node when needed is
//! thus to just call the corresponding function in this module: //! thus to just call the corresponding function in this module:
//! //!
//! let file_metadata = file_metadata(crate_context, path); //! let file_metadata = file_metadata(cx, file);
//! //!
//! The function will take care of probing the cache for an existing node for //! The function will take care of probing the cache for an existing node for
//! that exact file path. //! that exact file path.

View file

@ -26,7 +26,7 @@ use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_fs_util::path_to_c_string; use rustc_fs_util::path_to_c_string;
use rustc_hir::def::CtorKind; use rustc_hir::def::CtorKind;
use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; use rustc_hir::def_id::{DefId, LOCAL_CRATE};
use rustc_index::vec::{Idx, IndexVec}; use rustc_index::vec::{Idx, IndexVec};
use rustc_middle::ich::NodeIdHashingMode; use rustc_middle::ich::NodeIdHashingMode;
use rustc_middle::mir::interpret::truncate; use rustc_middle::mir::interpret::truncate;
@ -760,16 +760,12 @@ fn hex_encode(data: &[u8]) -> String {
hex_string hex_string
} }
pub fn file_metadata( pub fn file_metadata(cx: &CodegenCx<'ll, '_>, source_file: &SourceFile) -> &'ll DIFile {
cx: &CodegenCx<'ll, '_>, debug!("file_metadata: file_name: {}", source_file.name);
source_file: &SourceFile,
defining_crate: CrateNum,
) -> &'ll DIFile {
debug!("file_metadata: file_name: {}, defining_crate: {}", source_file.name, defining_crate);
let hash = Some(&source_file.src_hash); let hash = Some(&source_file.src_hash);
let file_name = Some(source_file.name.to_string()); let file_name = Some(source_file.name.to_string());
let directory = if defining_crate == LOCAL_CRATE { let directory = if source_file.is_real_file() && !source_file.is_imported() {
Some(cx.sess().working_dir.0.to_string_lossy().to_string()) Some(cx.sess().working_dir.0.to_string_lossy().to_string())
} else { } else {
// If the path comes from an upstream crate we assume it has been made // If the path comes from an upstream crate we assume it has been made
@ -1835,7 +1831,7 @@ impl<'tcx> VariantInfo<'_, 'tcx> {
if !span.is_dummy() { if !span.is_dummy() {
let loc = cx.lookup_debug_loc(span.lo()); let loc = cx.lookup_debug_loc(span.lo());
return Some(SourceInfo { return Some(SourceInfo {
file: file_metadata(cx, &loc.file, def_id.krate), file: file_metadata(cx, &loc.file),
line: loc.line.unwrap_or(UNKNOWN_LINE_NUMBER), line: loc.line.unwrap_or(UNKNOWN_LINE_NUMBER),
}); });
} }
@ -2474,7 +2470,7 @@ pub fn create_global_var_metadata(cx: &CodegenCx<'ll, '_>, def_id: DefId, global
let (file_metadata, line_number) = if !span.is_dummy() { let (file_metadata, line_number) = if !span.is_dummy() {
let loc = cx.lookup_debug_loc(span.lo()); let loc = cx.lookup_debug_loc(span.lo());
(file_metadata(cx, &loc.file, LOCAL_CRATE), loc.line) (file_metadata(cx, &loc.file), loc.line)
} else { } else {
(unknown_file_metadata(cx), None) (unknown_file_metadata(cx), None)
}; };
@ -2576,9 +2572,8 @@ pub fn create_vtable_metadata(cx: &CodegenCx<'ll, 'tcx>, ty: Ty<'tcx>, vtable: &
pub fn extend_scope_to_file( pub fn extend_scope_to_file(
cx: &CodegenCx<'ll, '_>, cx: &CodegenCx<'ll, '_>,
scope_metadata: &'ll DIScope, scope_metadata: &'ll DIScope,
file: &rustc_span::SourceFile, file: &SourceFile,
defining_crate: CrateNum,
) -> &'ll DILexicalBlock { ) -> &'ll DILexicalBlock {
let file_metadata = file_metadata(cx, &file, defining_crate); let file_metadata = file_metadata(cx, file);
unsafe { llvm::LLVMRustDIBuilderCreateLexicalBlockFile(DIB(cx), scope_metadata, file_metadata) } unsafe { llvm::LLVMRustDIBuilderCreateLexicalBlockFile(DIB(cx), scope_metadata, file_metadata) }
} }

View file

@ -3,7 +3,8 @@ mod doc;
use rustc_codegen_ssa::mir::debuginfo::VariableKind::*; use rustc_codegen_ssa::mir::debuginfo::VariableKind::*;
use self::metadata::{file_metadata, type_metadata, TypeMap, UNKNOWN_LINE_NUMBER}; use self::metadata::{file_metadata, type_metadata, TypeMap};
use self::metadata::{UNKNOWN_COLUMN_NUMBER, UNKNOWN_LINE_NUMBER};
use self::namespace::mangled_name_of_instance; use self::namespace::mangled_name_of_instance;
use self::type_names::compute_debuginfo_type_name; use self::type_names::compute_debuginfo_type_name;
use self::utils::{create_DIArray, is_node_local_to_unit, DIB}; use self::utils::{create_DIArray, is_node_local_to_unit, DIB};
@ -13,7 +14,8 @@ use crate::builder::Builder;
use crate::common::CodegenCx; use crate::common::CodegenCx;
use crate::llvm; use crate::llvm;
use crate::llvm::debuginfo::{ use crate::llvm::debuginfo::{
DIArray, DIBuilder, DIFile, DIFlags, DILexicalBlock, DISPFlags, DIScope, DIType, DIVariable, DIArray, DIBuilder, DIFile, DIFlags, DILexicalBlock, DILocation, DISPFlags, DIScope, DIType,
DIVariable,
}; };
use crate::value::Value; use crate::value::Value;
@ -21,7 +23,8 @@ use rustc_codegen_ssa::debuginfo::type_names;
use rustc_codegen_ssa::mir::debuginfo::{DebugScope, FunctionDebugContext, VariableKind}; use rustc_codegen_ssa::mir::debuginfo::{DebugScope, FunctionDebugContext, VariableKind};
use rustc_codegen_ssa::traits::*; use rustc_codegen_ssa::traits::*;
use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LOCAL_CRATE}; use rustc_data_structures::sync::Lrc;
use rustc_hir::def_id::{DefId, DefIdMap, LOCAL_CRATE};
use rustc_index::vec::IndexVec; use rustc_index::vec::IndexVec;
use rustc_middle::mir; use rustc_middle::mir;
use rustc_middle::ty::layout::HasTyCtxt; use rustc_middle::ty::layout::HasTyCtxt;
@ -29,7 +32,7 @@ use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
use rustc_middle::ty::{self, Instance, ParamEnv, Ty, TypeFoldable}; use rustc_middle::ty::{self, Instance, ParamEnv, Ty, TypeFoldable};
use rustc_session::config::{self, DebugInfo}; use rustc_session::config::{self, DebugInfo};
use rustc_span::symbol::Symbol; use rustc_span::symbol::Symbol;
use rustc_span::{self, BytePos, Span}; use rustc_span::{self, BytePos, Pos, SourceFile, SourceFileAndLine, Span};
use rustc_target::abi::{LayoutOf, Primitive, Size}; use rustc_target::abi::{LayoutOf, Primitive, Size};
use libc::c_uint; use libc::c_uint;
@ -41,7 +44,6 @@ mod create_scope_map;
pub mod gdb; pub mod gdb;
pub mod metadata; pub mod metadata;
mod namespace; mod namespace;
mod source_loc;
mod utils; mod utils;
pub use self::create_scope_map::compute_mir_scopes; pub use self::create_scope_map::compute_mir_scopes;
@ -141,14 +143,11 @@ impl DebugInfoBuilderMethods for Builder<'a, 'll, 'tcx> {
fn dbg_var_addr( fn dbg_var_addr(
&mut self, &mut self,
dbg_var: &'ll DIVariable, dbg_var: &'ll DIVariable,
scope_metadata: &'ll DIScope, dbg_loc: &'ll DILocation,
variable_alloca: Self::Value, variable_alloca: Self::Value,
direct_offset: Size, direct_offset: Size,
indirect_offsets: &[Size], indirect_offsets: &[Size],
span: Span,
) { ) {
let cx = self.cx();
// Convert the direct and indirect offsets to address ops. // Convert the direct and indirect offsets to address ops.
// FIXME(eddyb) use `const`s instead of getting the values via FFI, // FIXME(eddyb) use `const`s instead of getting the values via FFI,
// the values should match the ones in the DWARF standard anyway. // the values should match the ones in the DWARF standard anyway.
@ -168,14 +167,10 @@ impl DebugInfoBuilderMethods for Builder<'a, 'll, 'tcx> {
} }
} }
// FIXME(eddyb) maybe this information could be extracted from `dbg_var`,
// to avoid having to pass it down in both places?
// NB: `var` doesn't seem to know about the column, so that's a limitation.
let dbg_loc = cx.create_debug_loc(scope_metadata, span);
unsafe { unsafe {
// FIXME(eddyb) replace `llvm.dbg.declare` with `llvm.dbg.addr`. // FIXME(eddyb) replace `llvm.dbg.declare` with `llvm.dbg.addr`.
llvm::LLVMRustDIBuilderInsertDeclareAtEnd( llvm::LLVMRustDIBuilderInsertDeclareAtEnd(
DIB(cx), DIB(self.cx()),
variable_alloca, variable_alloca,
dbg_var, dbg_var,
addr_ops.as_ptr(), addr_ops.as_ptr(),
@ -186,15 +181,13 @@ impl DebugInfoBuilderMethods for Builder<'a, 'll, 'tcx> {
} }
} }
fn set_source_location(&mut self, scope: &'ll DIScope, span: Span) { fn set_dbg_loc(&mut self, dbg_loc: &'ll DILocation) {
debug!("set_source_location: {}", self.sess().source_map().span_to_string(span));
let dbg_loc = self.cx().create_debug_loc(scope, span);
unsafe { unsafe {
llvm::LLVMSetCurrentDebugLocation(self.llbuilder, dbg_loc); let dbg_loc_as_llval = llvm::LLVMRustMetadataAsValue(self.cx().llcx, dbg_loc);
llvm::LLVMSetCurrentDebugLocation(self.llbuilder, dbg_loc_as_llval);
} }
} }
fn insert_reference_to_gdb_debug_scripts_section_global(&mut self) { fn insert_reference_to_gdb_debug_scripts_section_global(&mut self) {
gdb::insert_reference_to_gdb_debug_scripts_section_global(self) gdb::insert_reference_to_gdb_debug_scripts_section_global(self)
} }
@ -223,30 +216,95 @@ impl DebugInfoBuilderMethods for Builder<'a, 'll, 'tcx> {
} }
} }
/// 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: Option<u32>,
/// The (1-based) column number.
pub col: Option<u32>,
}
impl CodegenCx<'ll, '_> {
/// 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.
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.line_begin_pos(pos);
// Use 1-based indexing.
let line = (line + 1) as u32;
let col = (pos - line_pos).to_u32() + 1;
(file, Some(line), Some(col))
}
Err(file) => (file, None, None),
};
// 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.options.is_like_msvc {
DebugLoc { file, line, col: None }
} else {
DebugLoc { file, line, col }
}
}
}
impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
fn create_function_debug_context( fn create_function_debug_context(
&self, &self,
instance: Instance<'tcx>, instance: Instance<'tcx>,
fn_abi: &FnAbi<'tcx, Ty<'tcx>>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
llfn: &'ll Value, llfn: &'ll Value,
mir: &mir::Body<'_>, mir: &mir::Body<'tcx>,
) -> Option<FunctionDebugContext<&'ll DIScope>> { ) -> Option<FunctionDebugContext<&'ll DIScope, &'ll DILocation>> {
if self.sess().opts.debuginfo == DebugInfo::None { if self.sess().opts.debuginfo == DebugInfo::None {
return None; return None;
} }
let span = mir.span; // Initialize fn debug context (including scopes).
// FIXME(eddyb) figure out a way to not need `Option` for `dbg_scope`.
let empty_scope = DebugScope {
dbg_scope: None,
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) };
// This can be the case for functions inlined from another crate // Fill in all the scopes, with the information from the MIR body.
if span.is_dummy() { compute_mir_scopes(
// FIXME(simulacrum): Probably can't happen; remove. self,
return None; instance,
} mir,
self.dbg_scope_fn(instance, fn_abi, Some(llfn)),
&mut fn_debug_context,
);
Some(fn_debug_context)
}
fn dbg_scope_fn(
&self,
instance: Instance<'tcx>,
fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
maybe_definition_llfn: Option<&'ll Value>,
) -> &'ll DIScope {
let def_id = instance.def_id(); let def_id = instance.def_id();
let containing_scope = get_containing_scope(self, instance); let containing_scope = get_containing_scope(self, instance);
let span = self.tcx.def_span(def_id);
let loc = self.lookup_debug_loc(span.lo()); let loc = self.lookup_debug_loc(span.lo());
let file_metadata = file_metadata(self, &loc.file, def_id.krate); let file_metadata = file_metadata(self, &loc.file);
let function_type_metadata = unsafe { let function_type_metadata = unsafe {
let fn_signature = get_function_signature(self, fn_abi); let fn_signature = get_function_signature(self, fn_abi);
@ -291,8 +349,8 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
} }
} }
let fn_metadata = unsafe { unsafe {
llvm::LLVMRustDIBuilderCreateFunction( return llvm::LLVMRustDIBuilderCreateFunction(
DIB(self), DIB(self),
containing_scope, containing_scope,
name.as_ptr().cast(), name.as_ptr().cast(),
@ -305,28 +363,11 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
scope_line.unwrap_or(UNKNOWN_LINE_NUMBER), scope_line.unwrap_or(UNKNOWN_LINE_NUMBER),
flags, flags,
spflags, spflags,
llfn, maybe_definition_llfn,
template_parameters, template_parameters,
None, None,
) );
}; }
// Initialize fn debug context (including scopes).
// FIXME(eddyb) figure out a way to not need `Option` for `scope_metadata`.
let null_scope = DebugScope {
scope_metadata: None,
file_start_pos: BytePos(0),
file_end_pos: BytePos(0),
};
let mut fn_debug_context = FunctionDebugContext {
scopes: IndexVec::from_elem(null_scope, &mir.source_scopes),
defining_crate: def_id.krate,
};
// Fill in all the scopes, with the information from the MIR body.
compute_mir_scopes(self, mir, fn_metadata, &mut fn_debug_context);
return Some(fn_debug_context);
fn get_function_signature<'ll, 'tcx>( fn get_function_signature<'ll, 'tcx>(
cx: &CodegenCx<'ll, 'tcx>, cx: &CodegenCx<'ll, 'tcx>,
@ -501,6 +542,25 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
} }
} }
fn dbg_loc(
&self,
scope: &'ll DIScope,
inlined_at: Option<&'ll DILocation>,
span: Span,
) -> &'ll DILocation {
let DebugLoc { line, col, .. } = self.lookup_debug_loc(span.lo());
unsafe {
llvm::LLVMRustDIBuilderCreateDebugLocation(
utils::debug_context(self).llcontext,
line.unwrap_or(UNKNOWN_LINE_NUMBER),
col.unwrap_or(UNKNOWN_COLUMN_NUMBER),
scope,
inlined_at,
)
}
}
fn create_vtable_metadata(&self, ty: Ty<'tcx>, vtable: Self::Value) { fn create_vtable_metadata(&self, ty: Ty<'tcx>, vtable: Self::Value) {
metadata::create_vtable_metadata(self, ty, vtable) metadata::create_vtable_metadata(self, ty, vtable)
} }
@ -509,9 +569,8 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
&self, &self,
scope_metadata: &'ll DIScope, scope_metadata: &'ll DIScope,
file: &rustc_span::SourceFile, file: &rustc_span::SourceFile,
defining_crate: CrateNum,
) -> &'ll DILexicalBlock { ) -> &'ll DILexicalBlock {
metadata::extend_scope_to_file(&self, scope_metadata, file, defining_crate) metadata::extend_scope_to_file(&self, scope_metadata, file)
} }
fn debuginfo_finalize(&self) { fn debuginfo_finalize(&self) {
@ -522,7 +581,6 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
// names (choose between `dbg`, `debug`, `debuginfo`, `debug_info` etc.). // names (choose between `dbg`, `debug`, `debuginfo`, `debug_info` etc.).
fn create_dbg_var( fn create_dbg_var(
&self, &self,
dbg_context: &FunctionDebugContext<&'ll DIScope>,
variable_name: Symbol, variable_name: Symbol,
variable_type: Ty<'tcx>, variable_type: Ty<'tcx>,
scope_metadata: &'ll DIScope, scope_metadata: &'ll DIScope,
@ -530,7 +588,7 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
span: Span, span: Span,
) -> &'ll DIVariable { ) -> &'ll DIVariable {
let loc = self.lookup_debug_loc(span.lo()); let loc = self.lookup_debug_loc(span.lo());
let file_metadata = file_metadata(self, &loc.file, dbg_context.defining_crate); let file_metadata = file_metadata(self, &loc.file);
let type_metadata = type_metadata(self, variable_type, span); let type_metadata = type_metadata(self, variable_type, span);

View file

@ -1,61 +0,0 @@
use super::metadata::{UNKNOWN_COLUMN_NUMBER, UNKNOWN_LINE_NUMBER};
use super::utils::debug_context;
use crate::common::CodegenCx;
use crate::llvm::debuginfo::DIScope;
use crate::llvm::{self, Value};
use rustc_codegen_ssa::traits::*;
use rustc_data_structures::sync::Lrc;
use rustc_span::{BytePos, Pos, SourceFile, SourceFileAndLine, Span};
/// A source code location used to generate debug information.
pub struct DebugLoc {
/// Information about the original source file.
pub file: Lrc<SourceFile>,
/// The (1-based) line number.
pub line: Option<u32>,
/// The (1-based) column number.
pub col: Option<u32>,
}
impl CodegenCx<'ll, '_> {
/// Looks up debug source information about a `BytePos`.
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.line_begin_pos(pos);
// Use 1-based indexing.
let line = (line + 1) as u32;
let col = (pos - line_pos).to_u32() + 1;
(file, Some(line), Some(col))
}
Err(file) => (file, None, None),
};
// 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.options.is_like_msvc {
DebugLoc { file, line, col: None }
} else {
DebugLoc { file, line, col }
}
}
pub fn create_debug_loc(&self, scope: &'ll DIScope, span: Span) -> &'ll Value {
let DebugLoc { line, col, .. } = self.lookup_debug_loc(span.lo());
unsafe {
llvm::LLVMRustDIBuilderCreateDebugLocation(
debug_context(self).llcontext,
line.unwrap_or(UNKNOWN_LINE_NUMBER),
col.unwrap_or(UNKNOWN_COLUMN_NUMBER),
scope,
None,
)
}
}
}

View file

@ -5,8 +5,9 @@ use rustc_codegen_ssa::coverageinfo::map as coverage_map;
use super::debuginfo::{ use super::debuginfo::{
DIArray, DIBasicType, DIBuilder, DICompositeType, DIDerivedType, DIDescriptor, DIEnumerator, DIArray, DIBasicType, DIBuilder, DICompositeType, DIDerivedType, DIDescriptor, DIEnumerator,
DIFile, DIFlags, DIGlobalVariableExpression, DILexicalBlock, DINameSpace, DISPFlags, DIScope, DIFile, DIFlags, DIGlobalVariableExpression, DILexicalBlock, DILocation, DINameSpace,
DISubprogram, DISubrange, DITemplateTypeParameter, DIType, DIVariable, DebugEmissionKind, DISPFlags, DIScope, DISubprogram, DISubrange, DITemplateTypeParameter, DIType, DIVariable,
DebugEmissionKind,
}; };
use libc::{c_char, c_int, c_uint, size_t}; use libc::{c_char, c_int, c_uint, size_t};
@ -794,6 +795,7 @@ pub mod debuginfo {
pub struct DIBuilder<'a>(InvariantOpaque<'a>); pub struct DIBuilder<'a>(InvariantOpaque<'a>);
pub type DIDescriptor = Metadata; pub type DIDescriptor = Metadata;
pub type DILocation = Metadata;
pub type DIScope = DIDescriptor; pub type DIScope = DIDescriptor;
pub type DIFile = DIScope; pub type DIFile = DIScope;
pub type DILexicalBlock = DIScope; pub type DILexicalBlock = DIScope;
@ -1854,7 +1856,7 @@ extern "C" {
ScopeLine: c_uint, ScopeLine: c_uint,
Flags: DIFlags, Flags: DIFlags,
SPFlags: DISPFlags, SPFlags: DISPFlags,
Fn: &'a Value, MaybeFn: Option<&'a Value>,
TParam: &'a DIArray, TParam: &'a DIArray,
Decl: Option<&'a DIDescriptor>, Decl: Option<&'a DIDescriptor>,
) -> &'a DISubprogram; ) -> &'a DISubprogram;
@ -2005,7 +2007,7 @@ extern "C" {
VarInfo: &'a DIVariable, VarInfo: &'a DIVariable,
AddrOps: *const i64, AddrOps: *const i64,
AddrOpsCount: c_uint, AddrOpsCount: c_uint,
DL: &'a Value, DL: &'a DILocation,
InsertAtEnd: &'a BasicBlock, InsertAtEnd: &'a BasicBlock,
) -> &'a Value; ) -> &'a Value;
@ -2093,8 +2095,8 @@ extern "C" {
Line: c_uint, Line: c_uint,
Column: c_uint, Column: c_uint,
Scope: &'a DIScope, Scope: &'a DIScope,
InlinedAt: Option<&'a Metadata>, InlinedAt: Option<&'a DILocation>,
) -> &'a Value; ) -> &'a DILocation;
pub fn LLVMRustDIBuilderCreateOpDeref() -> i64; pub fn LLVMRustDIBuilderCreateOpDeref() -> i64;
pub fn LLVMRustDIBuilderCreateOpPlusUconst() -> i64; pub fn LLVMRustDIBuilderCreateOpPlusUconst() -> i64;

View file

@ -405,7 +405,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
self.set_debug_loc(&mut bx, terminator.source_info); self.set_debug_loc(&mut bx, terminator.source_info);
// Get the location information. // Get the location information.
let location = self.get_caller_location(&mut bx, span).immediate(); let location = self.get_caller_location(&mut bx, terminator.source_info).immediate();
// Put together the arguments to the panic entry point. // Put together the arguments to the panic entry point.
let (lang_item, args) = match msg { let (lang_item, args) = match msg {
@ -442,7 +442,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
bx: &mut Bx, bx: &mut Bx,
intrinsic: Option<Symbol>, intrinsic: Option<Symbol>,
instance: Option<Instance<'tcx>>, instance: Option<Instance<'tcx>>,
span: Span, source_info: mir::SourceInfo,
destination: &Option<(mir::Place<'tcx>, mir::BasicBlock)>, destination: &Option<(mir::Place<'tcx>, mir::BasicBlock)>,
cleanup: Option<mir::BasicBlock>, cleanup: Option<mir::BasicBlock>,
) -> bool { ) -> bool {
@ -484,11 +484,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
} }
}); });
let msg = bx.const_str(Symbol::intern(&msg_str)); let msg = bx.const_str(Symbol::intern(&msg_str));
let location = self.get_caller_location(bx, span).immediate(); let location = self.get_caller_location(bx, source_info).immediate();
// Obtain the panic entry point. // Obtain the panic entry point.
// FIXME: dedup this with `codegen_assert_terminator` above. // FIXME: dedup this with `codegen_assert_terminator` above.
let def_id = common::langcall(bx.tcx(), Some(span), "", LangItem::Panic); let def_id =
common::langcall(bx.tcx(), Some(source_info.span), "", LangItem::Panic);
let instance = ty::Instance::mono(bx.tcx(), def_id); let instance = ty::Instance::mono(bx.tcx(), def_id);
let fn_abi = FnAbi::of_instance(bx, instance, &[]); let fn_abi = FnAbi::of_instance(bx, instance, &[]);
let llfn = bx.get_fn_addr(instance); let llfn = bx.get_fn_addr(instance);
@ -529,7 +530,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
cleanup: Option<mir::BasicBlock>, cleanup: Option<mir::BasicBlock>,
fn_span: Span, fn_span: Span,
) { ) {
let span = terminator.source_info.span; let source_info = terminator.source_info;
let span = source_info.span;
// Create the callee. This is a fn ptr or zero-sized and hence a kind of scalar. // Create the callee. This is a fn ptr or zero-sized and hence a kind of scalar.
let callee = self.codegen_operand(&mut bx, func); let callee = self.codegen_operand(&mut bx, func);
@ -606,7 +609,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
&mut bx, &mut bx,
intrinsic, intrinsic,
instance, instance,
span, source_info,
destination, destination,
cleanup, cleanup,
) { ) {
@ -627,7 +630,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
if intrinsic == Some(sym::caller_location) { if intrinsic == Some(sym::caller_location) {
if let Some((_, target)) = destination.as_ref() { if let Some((_, target)) = destination.as_ref() {
let location = self.get_caller_location(&mut bx, fn_span); let location = self
.get_caller_location(&mut bx, mir::SourceInfo { span: fn_span, ..source_info });
if let ReturnDest::IndirectOperand(tmp, _) = ret_dest { if let ReturnDest::IndirectOperand(tmp, _) = ret_dest {
location.val.store(&mut bx, tmp); location.val.store(&mut bx, tmp);
@ -686,7 +690,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
&fn_abi, &fn_abi,
&args, &args,
dest, dest,
terminator.source_info.span, span,
); );
if let ReturnDest::IndirectOperand(dst, _) = ret_dest { if let ReturnDest::IndirectOperand(dst, _) = ret_dest {
@ -793,7 +797,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
args.len() + 1, args.len() + 1,
"#[track_caller] fn's must have 1 more argument in their ABI than in their MIR", "#[track_caller] fn's must have 1 more argument in their ABI than in their MIR",
); );
let location = self.get_caller_location(&mut bx, fn_span); let location =
self.get_caller_location(&mut bx, mir::SourceInfo { span: fn_span, ..source_info });
debug!( debug!(
"codegen_call_terminator({:?}): location={:?} (fn_span {:?})", "codegen_call_terminator({:?}): location={:?} (fn_span {:?})",
terminator, location, fn_span terminator, location, fn_span
@ -1179,17 +1184,49 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
} }
} }
fn get_caller_location(&mut self, bx: &mut Bx, span: Span) -> OperandRef<'tcx, Bx::Value> { fn get_caller_location(
self.caller_location.unwrap_or_else(|| { &mut self,
bx: &mut Bx,
mut source_info: mir::SourceInfo,
) -> OperandRef<'tcx, Bx::Value> {
let tcx = bx.tcx();
let mut span_to_caller_location = |span: Span| {
let topmost = span.ctxt().outer_expn().expansion_cause().unwrap_or(span); let topmost = span.ctxt().outer_expn().expansion_cause().unwrap_or(span);
let caller = bx.tcx().sess.source_map().lookup_char_pos(topmost.lo()); let caller = tcx.sess.source_map().lookup_char_pos(topmost.lo());
let const_loc = bx.tcx().const_caller_location(( let const_loc = tcx.const_caller_location((
Symbol::intern(&caller.file.name.to_string()), Symbol::intern(&caller.file.name.to_string()),
caller.line as u32, caller.line as u32,
caller.col_display as u32 + 1, caller.col_display as u32 + 1,
)); ));
OperandRef::from_const(bx, const_loc, bx.tcx().caller_location_ty()) OperandRef::from_const(bx, const_loc, bx.tcx().caller_location_ty())
}) };
// Walk up the `SourceScope`s, in case some of them are from MIR inlining.
// If so, the starting `source_info.span` is in the innermost inlined
// function, and will be replaced with outer callsite spans as long
// as the inlined functions were `#[track_caller]`.
loop {
let scope_data = &self.mir.source_scopes[source_info.scope];
if let Some((callee, callsite_span)) = scope_data.inlined {
// Stop inside the most nested non-`#[track_caller]` function,
// before ever reaching its caller (which is irrelevant).
if !callee.def.requires_caller_location(tcx) {
return span_to_caller_location(source_info.span);
}
source_info.span = callsite_span;
}
// Skip past all of the parents with `inlined: None`.
match scope_data.inlined_parent_scope {
Some(parent) => source_info.scope = parent,
None => break,
}
}
// No inlined `SourceScope`s, or all of them were `#[track_caller]`.
self.caller_location.unwrap_or_else(|| span_to_caller_location(source_info.span))
} }
fn get_personality_slot(&mut self, bx: &mut Bx) -> PlaceRef<'tcx, Bx::Value> { fn get_personality_slot(&mut self, bx: &mut Bx) -> PlaceRef<'tcx, Bx::Value> {

View file

@ -1,5 +1,4 @@
use crate::traits::*; use crate::traits::*;
use rustc_hir::def_id::CrateNum;
use rustc_index::vec::IndexVec; use rustc_index::vec::IndexVec;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use rustc_middle::mir; use rustc_middle::mir;
@ -13,9 +12,8 @@ use super::operand::OperandValue;
use super::place::PlaceRef; use super::place::PlaceRef;
use super::{FunctionCx, LocalRef}; use super::{FunctionCx, LocalRef};
pub struct FunctionDebugContext<D> { pub struct FunctionDebugContext<S, L> {
pub scopes: IndexVec<mir::SourceScope, DebugScope<D>>, pub scopes: IndexVec<mir::SourceScope, DebugScope<S, L>>,
pub defining_crate: CrateNum,
} }
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
@ -38,77 +36,84 @@ pub struct PerLocalVarDebugInfo<'tcx, D> {
} }
#[derive(Clone, Copy, Debug)] #[derive(Clone, Copy, Debug)]
pub struct DebugScope<D> { pub struct DebugScope<S, L> {
pub scope_metadata: Option<D>, // FIXME(eddyb) this should never be `None`, after initialization.
pub dbg_scope: Option<S>,
/// Call site location, if this scope was inlined from another function.
pub inlined_at: Option<L>,
// Start and end offsets of the file to which this DIScope belongs. // Start and end offsets of the file to which this DIScope belongs.
// These are used to quickly determine whether some span refers to the same file. // These are used to quickly determine whether some span refers to the same file.
pub file_start_pos: BytePos, pub file_start_pos: BytePos,
pub file_end_pos: BytePos, pub file_end_pos: BytePos,
} }
impl<D> DebugScope<D> { impl<'tcx, S: Copy, L: Copy> DebugScope<S, L> {
pub fn is_valid(&self) -> bool { /// DILocations inherit source file name from the parent DIScope. Due to macro expansions
self.scope_metadata.is_some() /// it may so happen that the current span belongs to a different file than the DIScope
/// corresponding to span's containing source scope. If so, we need to create a DIScope
/// "extension" into that file.
pub fn adjust_dbg_scope_for_span<Cx: CodegenMethods<'tcx, DIScope = S, DILocation = L>>(
&self,
cx: &Cx,
span: Span,
) -> S {
// FIXME(eddyb) this should never be `None`.
let dbg_scope = self
.dbg_scope
.unwrap_or_else(|| bug!("`dbg_scope` is only `None` during initialization"));
let pos = span.lo();
if pos < self.file_start_pos || pos >= self.file_end_pos {
let sm = cx.sess().source_map();
cx.extend_scope_to_file(dbg_scope, &sm.lookup_char_pos(pos).file)
} else {
dbg_scope
}
} }
} }
impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
pub fn set_debug_loc(&self, bx: &mut Bx, source_info: mir::SourceInfo) { pub fn set_debug_loc(&self, bx: &mut Bx, source_info: mir::SourceInfo) {
let (scope, span) = self.debug_loc(source_info); bx.set_span(source_info.span);
bx.set_span(span); if let Some(dbg_loc) = self.dbg_loc(source_info) {
if let Some(scope) = scope { bx.set_dbg_loc(dbg_loc);
bx.set_source_location(scope, span);
} }
} }
pub fn debug_loc(&self, source_info: mir::SourceInfo) -> (Option<Bx::DIScope>, Span) { fn dbg_loc(&self, source_info: mir::SourceInfo) -> Option<Bx::DILocation> {
let (dbg_scope, inlined_at, span) = self.adjusted_span_and_dbg_scope(source_info)?;
Some(self.cx.dbg_loc(dbg_scope, inlined_at, span))
}
fn adjusted_span_and_dbg_scope(
&self,
source_info: mir::SourceInfo,
) -> Option<(Bx::DIScope, Option<Bx::DILocation>, Span)> {
let span = self.adjust_span_for_debugging(source_info.span);
let scope = &self.debug_context.as_ref()?.scopes[source_info.scope];
Some((scope.adjust_dbg_scope_for_span(self.cx, span), scope.inlined_at, span))
}
/// In order to have a good line stepping behavior in debugger, we overwrite debug
/// locations of macro expansions with that of the outermost expansion site
/// (unless the crate is being compiled with `-Z debug-macros`).
fn adjust_span_for_debugging(&self, mut span: Span) -> Span {
// Bail out if debug info emission is not enabled. // Bail out if debug info emission is not enabled.
match self.debug_context { if self.debug_context.is_none() {
None => return (None, source_info.span), return span;
Some(_) => {}
} }
// In order to have a good line stepping behavior in debugger, we overwrite debug if span.from_expansion() && !self.cx.sess().opts.debugging_opts.debug_macros {
// locations of macro expansions with that of the outermost expansion site
// (unless the crate is being compiled with `-Z debug-macros`).
if !source_info.span.from_expansion() || self.cx.sess().opts.debugging_opts.debug_macros {
let scope = self.scope_metadata_for_loc(source_info.scope, source_info.span.lo());
(scope, source_info.span)
} else {
// Walk up the macro expansion chain until we reach a non-expanded span. // Walk up the macro expansion chain until we reach a non-expanded span.
// We also stop at the function body level because no line stepping can occur // We also stop at the function body level because no line stepping can occur
// at the level above that. // at the level above that.
let span = rustc_span::hygiene::walk_chain(source_info.span, self.mir.span.ctxt());
let scope = self.scope_metadata_for_loc(source_info.scope, span.lo());
// Use span of the outermost expansion site, while keeping the original lexical scope. // Use span of the outermost expansion site, while keeping the original lexical scope.
(scope, span) span = rustc_span::hygiene::walk_chain(span, self.mir.span.ctxt());
} }
}
// DILocations inherit source file name from the parent DIScope. Due to macro expansions span
// it may so happen that the current span belongs to a different file than the DIScope
// corresponding to span's containing source scope. If so, we need to create a DIScope
// "extension" into that file.
fn scope_metadata_for_loc(
&self,
scope_id: mir::SourceScope,
pos: BytePos,
) -> Option<Bx::DIScope> {
let debug_context = self.debug_context.as_ref()?;
let scope_metadata = debug_context.scopes[scope_id].scope_metadata;
if pos < debug_context.scopes[scope_id].file_start_pos
|| pos >= debug_context.scopes[scope_id].file_end_pos
{
let sm = self.cx.sess().source_map();
let defining_crate = debug_context.defining_crate;
Some(self.cx.extend_scope_to_file(
scope_metadata.unwrap(),
&sm.lookup_char_pos(pos).file,
defining_crate,
))
} else {
scope_metadata
}
} }
/// Apply debuginfo and/or name, after creating the `alloca` for a local, /// Apply debuginfo and/or name, after creating the `alloca` for a local,
@ -149,24 +154,20 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
} else { } else {
let name = kw::Invalid; let name = kw::Invalid;
let decl = &self.mir.local_decls[local]; let decl = &self.mir.local_decls[local];
let (scope, span) = if full_debug_info { let dbg_var = if full_debug_info {
self.debug_loc(decl.source_info) self.adjusted_span_and_dbg_scope(decl.source_info).map(
} else { |(dbg_scope, _, span)| {
(None, decl.source_info.span) // FIXME(eddyb) is this `+ 1` needed at all?
}; let kind = VariableKind::ArgumentVariable(arg_index + 1);
let dbg_var = scope.map(|scope| {
// FIXME(eddyb) is this `+ 1` needed at all?
let kind = VariableKind::ArgumentVariable(arg_index + 1);
self.cx.create_dbg_var( let arg_ty = self.monomorphize(&decl.ty);
self.debug_context.as_ref().unwrap(),
name, self.cx.create_dbg_var(name, arg_ty, dbg_scope, kind, span)
self.monomorphize(&decl.ty), },
scope,
kind,
span,
) )
}); } else {
None
};
Some(PerLocalVarDebugInfo { Some(PerLocalVarDebugInfo {
name, name,
@ -247,6 +248,15 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
let vars = vars.iter().copied().chain(fallback_var); let vars = vars.iter().copied().chain(fallback_var);
for var in vars { for var in vars {
let dbg_var = match var.dbg_var {
Some(dbg_var) => dbg_var,
None => continue,
};
let dbg_loc = match self.dbg_loc(var.source_info) {
Some(dbg_loc) => dbg_loc,
None => continue,
};
let mut layout = base.layout; let mut layout = base.layout;
let mut direct_offset = Size::ZERO; let mut direct_offset = Size::ZERO;
// FIXME(eddyb) use smallvec here. // FIXME(eddyb) use smallvec here.
@ -283,19 +293,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
} }
} }
let (scope, span) = self.debug_loc(var.source_info); bx.dbg_var_addr(dbg_var, dbg_loc, base.llval, direct_offset, &indirect_offsets);
if let Some(scope) = scope {
if let Some(dbg_var) = var.dbg_var {
bx.dbg_var_addr(
dbg_var,
scope,
base.llval,
direct_offset,
&indirect_offsets,
span,
);
}
}
} }
} }
@ -319,12 +317,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
let mut per_local = IndexVec::from_elem(vec![], &self.mir.local_decls); let mut per_local = IndexVec::from_elem(vec![], &self.mir.local_decls);
for var in &self.mir.var_debug_info { for var in &self.mir.var_debug_info {
let (scope, span) = if full_debug_info { let dbg_scope_and_span = if full_debug_info {
self.debug_loc(var.source_info) self.adjusted_span_and_dbg_scope(var.source_info)
} else { } else {
(None, var.source_info.span) None
}; };
let dbg_var = scope.map(|scope| { let dbg_var = dbg_scope_and_span.map(|(dbg_scope, _, span)| {
let place = var.place; let place = var.place;
let var_ty = self.monomorphized_place_ty(place.as_ref()); let var_ty = self.monomorphized_place_ty(place.as_ref());
let var_kind = if self.mir.local_kind(place.local) == mir::LocalKind::Arg let var_kind = if self.mir.local_kind(place.local) == mir::LocalKind::Arg
@ -340,14 +338,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
} else { } else {
VariableKind::LocalVariable VariableKind::LocalVariable
}; };
self.cx.create_dbg_var( self.cx.create_dbg_var(var.name, var_ty, dbg_scope, var_kind, span)
self.debug_context.as_ref().unwrap(),
var.name,
var_ty,
scope,
var_kind,
span,
)
}); });
per_local[var.place.local].push(PerLocalVarDebugInfo { per_local[var.place.local].push(PerLocalVarDebugInfo {

View file

@ -26,7 +26,7 @@ pub struct FunctionCx<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> {
mir: &'tcx mir::Body<'tcx>, mir: &'tcx mir::Body<'tcx>,
debug_context: Option<FunctionDebugContext<Bx::DIScope>>, debug_context: Option<FunctionDebugContext<Bx::DIScope, Bx::DILocation>>,
llfn: Bx::Function, llfn: Bx::Function,

View file

@ -34,6 +34,7 @@ pub trait BackendTypes {
// FIXME(eddyb) find a common convention for all of the debuginfo-related // FIXME(eddyb) find a common convention for all of the debuginfo-related
// names (choose between `Dbg`, `Debug`, `DebugInfo`, `DI` etc.). // names (choose between `Dbg`, `Debug`, `DebugInfo`, `DI` etc.).
type DIScope: Copy; type DIScope: Copy;
type DILocation: Copy;
type DIVariable: Copy; type DIVariable: Copy;
} }

View file

@ -1,6 +1,5 @@
use super::BackendTypes; use super::BackendTypes;
use crate::mir::debuginfo::{FunctionDebugContext, VariableKind}; use crate::mir::debuginfo::{FunctionDebugContext, VariableKind};
use rustc_hir::def_id::CrateNum;
use rustc_middle::mir; use rustc_middle::mir;
use rustc_middle::ty::{Instance, Ty}; use rustc_middle::ty::{Instance, Ty};
use rustc_span::{SourceFile, Span, Symbol}; use rustc_span::{SourceFile, Span, Symbol};
@ -19,14 +18,29 @@ pub trait DebugInfoMethods<'tcx>: BackendTypes {
instance: Instance<'tcx>, instance: Instance<'tcx>,
fn_abi: &FnAbi<'tcx, Ty<'tcx>>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
llfn: Self::Function, llfn: Self::Function,
mir: &mir::Body<'_>, mir: &mir::Body<'tcx>,
) -> Option<FunctionDebugContext<Self::DIScope>>; ) -> Option<FunctionDebugContext<Self::DIScope, Self::DILocation>>;
// FIXME(eddyb) find a common convention for all of the debuginfo-related
// names (choose between `dbg`, `debug`, `debuginfo`, `debug_info` etc.).
fn dbg_scope_fn(
&self,
instance: Instance<'tcx>,
fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
maybe_definition_llfn: Option<Self::Function>,
) -> Self::DIScope;
fn dbg_loc(
&self,
scope: Self::DIScope,
inlined_at: Option<Self::DILocation>,
span: Span,
) -> Self::DILocation;
fn extend_scope_to_file( fn extend_scope_to_file(
&self, &self,
scope_metadata: Self::DIScope, scope_metadata: Self::DIScope,
file: &SourceFile, file: &SourceFile,
defining_crate: CrateNum,
) -> Self::DIScope; ) -> Self::DIScope;
fn debuginfo_finalize(&self); fn debuginfo_finalize(&self);
@ -34,7 +48,6 @@ pub trait DebugInfoMethods<'tcx>: BackendTypes {
// names (choose between `dbg`, `debug`, `debuginfo`, `debug_info` etc.). // names (choose between `dbg`, `debug`, `debuginfo`, `debug_info` etc.).
fn create_dbg_var( fn create_dbg_var(
&self, &self,
dbg_context: &FunctionDebugContext<Self::DIScope>,
variable_name: Symbol, variable_name: Symbol,
variable_type: Ty<'tcx>, variable_type: Ty<'tcx>,
scope_metadata: Self::DIScope, scope_metadata: Self::DIScope,
@ -49,14 +62,13 @@ pub trait DebugInfoBuilderMethods: BackendTypes {
fn dbg_var_addr( fn dbg_var_addr(
&mut self, &mut self,
dbg_var: Self::DIVariable, dbg_var: Self::DIVariable,
scope_metadata: Self::DIScope, dbg_loc: Self::DILocation,
variable_alloca: Self::Value, variable_alloca: Self::Value,
direct_offset: Size, direct_offset: Size,
// NB: each offset implies a deref (i.e. they're steps in a pointer chain). // NB: each offset implies a deref (i.e. they're steps in a pointer chain).
indirect_offsets: &[Size], indirect_offsets: &[Size],
span: Span,
); );
fn set_source_location(&mut self, scope: Self::DIScope, span: Span); fn set_dbg_loc(&mut self, dbg_loc: Self::DILocation);
fn insert_reference_to_gdb_debug_scripts_section_global(&mut self); fn insert_reference_to_gdb_debug_scripts_section_global(&mut self);
fn set_var_name(&mut self, value: Self::Value, name: &str); fn set_var_name(&mut self, value: Self::Value, name: &str);
} }

View file

@ -95,6 +95,7 @@ pub trait HasCodegen<'tcx>:
Type = Self::Type, Type = Self::Type,
Funclet = Self::Funclet, Funclet = Self::Funclet,
DIScope = Self::DIScope, DIScope = Self::DIScope,
DILocation = Self::DILocation,
DIVariable = Self::DIVariable, DIVariable = Self::DIVariable,
>; >;
} }

View file

@ -733,7 +733,7 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFunction(
const char *LinkageName, size_t LinkageNameLen, const char *LinkageName, size_t LinkageNameLen,
LLVMMetadataRef File, unsigned LineNo, LLVMMetadataRef File, unsigned LineNo,
LLVMMetadataRef Ty, unsigned ScopeLine, LLVMRustDIFlags Flags, LLVMMetadataRef Ty, unsigned ScopeLine, LLVMRustDIFlags Flags,
LLVMRustDISPFlags SPFlags, LLVMValueRef Fn, LLVMMetadataRef TParam, LLVMRustDISPFlags SPFlags, LLVMValueRef MaybeFn, LLVMMetadataRef TParam,
LLVMMetadataRef Decl) { LLVMMetadataRef Decl) {
DITemplateParameterArray TParams = DITemplateParameterArray TParams =
DITemplateParameterArray(unwrap<MDTuple>(TParam)); DITemplateParameterArray(unwrap<MDTuple>(TParam));
@ -750,7 +750,8 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFunction(
unwrapDI<DIFile>(File), LineNo, unwrapDI<DIFile>(File), LineNo,
unwrapDI<DISubroutineType>(Ty), ScopeLine, llvmFlags, unwrapDI<DISubroutineType>(Ty), ScopeLine, llvmFlags,
llvmSPFlags, TParams, unwrapDIPtr<DISubprogram>(Decl)); llvmSPFlags, TParams, unwrapDIPtr<DISubprogram>(Decl));
unwrap<Function>(Fn)->setSubprogram(Sub); if (MaybeFn)
unwrap<Function>(MaybeFn)->setSubprogram(Sub);
return wrap(Sub); return wrap(Sub);
} }
@ -930,12 +931,12 @@ LLVMRustDIBuilderGetOrCreateArray(LLVMRustDIBuilderRef Builder,
extern "C" LLVMValueRef LLVMRustDIBuilderInsertDeclareAtEnd( extern "C" LLVMValueRef LLVMRustDIBuilderInsertDeclareAtEnd(
LLVMRustDIBuilderRef Builder, LLVMValueRef V, LLVMMetadataRef VarInfo, LLVMRustDIBuilderRef Builder, LLVMValueRef V, LLVMMetadataRef VarInfo,
int64_t *AddrOps, unsigned AddrOpsCount, LLVMValueRef DL, int64_t *AddrOps, unsigned AddrOpsCount, LLVMMetadataRef DL,
LLVMBasicBlockRef InsertAtEnd) { LLVMBasicBlockRef InsertAtEnd) {
return wrap(Builder->insertDeclare( return wrap(Builder->insertDeclare(
unwrap(V), unwrap<DILocalVariable>(VarInfo), unwrap(V), unwrap<DILocalVariable>(VarInfo),
Builder->createExpression(llvm::ArrayRef<int64_t>(AddrOps, AddrOpsCount)), Builder->createExpression(llvm::ArrayRef<int64_t>(AddrOps, AddrOpsCount)),
DebugLoc(cast<MDNode>(unwrap<MetadataAsValue>(DL)->getMetadata())), DebugLoc(cast<MDNode>(DL)),
unwrap(InsertAtEnd))); unwrap(InsertAtEnd)));
} }
@ -1002,7 +1003,7 @@ LLVMRustDICompositeTypeReplaceArrays(LLVMRustDIBuilderRef Builder,
DINodeArray(unwrap<MDTuple>(Params))); DINodeArray(unwrap<MDTuple>(Params)));
} }
extern "C" LLVMValueRef extern "C" LLVMMetadataRef
LLVMRustDIBuilderCreateDebugLocation(LLVMContextRef ContextRef, unsigned Line, LLVMRustDIBuilderCreateDebugLocation(LLVMContextRef ContextRef, unsigned Line,
unsigned Column, LLVMMetadataRef Scope, unsigned Column, LLVMMetadataRef Scope,
LLVMMetadataRef InlinedAt) { LLVMMetadataRef InlinedAt) {
@ -1011,7 +1012,7 @@ LLVMRustDIBuilderCreateDebugLocation(LLVMContextRef ContextRef, unsigned Line,
DebugLoc debug_loc = DebugLoc::get(Line, Column, unwrapDIPtr<MDNode>(Scope), DebugLoc debug_loc = DebugLoc::get(Line, Column, unwrapDIPtr<MDNode>(Scope),
unwrapDIPtr<MDNode>(InlinedAt)); unwrapDIPtr<MDNode>(InlinedAt));
return wrap(MetadataAsValue::get(Context, debug_loc.getAsMDNode())); return wrap(debug_loc.getAsMDNode());
} }
extern "C" int64_t LLVMRustDIBuilderCreateOpDeref() { extern "C" int64_t LLVMRustDIBuilderCreateOpDeref() {

View file

@ -161,7 +161,7 @@ pub struct Body<'tcx> {
/// A list of source scopes; these are referenced by statements /// A list of source scopes; these are referenced by statements
/// and used for debuginfo. Indexed by a `SourceScope`. /// and used for debuginfo. Indexed by a `SourceScope`.
pub source_scopes: IndexVec<SourceScope, SourceScopeData>, pub source_scopes: IndexVec<SourceScope, SourceScopeData<'tcx>>,
/// The yield type of the function, if it is a generator. /// The yield type of the function, if it is a generator.
pub yield_ty: Option<Ty<'tcx>>, pub yield_ty: Option<Ty<'tcx>>,
@ -244,7 +244,7 @@ impl<'tcx> Body<'tcx> {
pub fn new( pub fn new(
source: MirSource<'tcx>, source: MirSource<'tcx>,
basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>, basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
source_scopes: IndexVec<SourceScope, SourceScopeData>, source_scopes: IndexVec<SourceScope, SourceScopeData<'tcx>>,
local_decls: LocalDecls<'tcx>, local_decls: LocalDecls<'tcx>,
user_type_annotations: ty::CanonicalUserTypeAnnotations<'tcx>, user_type_annotations: ty::CanonicalUserTypeAnnotations<'tcx>,
arg_count: usize, arg_count: usize,
@ -1865,11 +1865,21 @@ rustc_index::newtype_index! {
} }
} }
#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)] #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable)]
pub struct SourceScopeData { pub struct SourceScopeData<'tcx> {
pub span: Span, pub span: Span,
pub parent_scope: Option<SourceScope>, pub parent_scope: Option<SourceScope>,
/// Whether this scope is the root of a scope tree of another body,
/// inlined into this body by the MIR inliner.
/// `ty::Instance` is the callee, and the `Span` is the call site.
pub inlined: Option<(ty::Instance<'tcx>, Span)>,
/// Nearest (transitive) parent scope (if any) which is inlined.
/// This is an optimization over walking up `parent_scope`
/// until a scope with `inlined: Some(...)` is found.
pub inlined_parent_scope: Option<SourceScope>,
/// Crate-local information for this source scope, that can't (and /// Crate-local information for this source scope, that can't (and
/// needn't) be tracked across crates. /// needn't) be tracked across crates.
pub local_data: ClearCrossCrate<SourceScopeLocalData>, pub local_data: ClearCrossCrate<SourceScopeLocalData>,

View file

@ -10,7 +10,6 @@ CloneTypeFoldableAndLiftImpls! {
FakeReadCause, FakeReadCause,
RetagKind, RetagKind,
SourceScope, SourceScope,
SourceScopeData,
SourceScopeLocalData, SourceScopeLocalData,
UserTypeAnnotationIndex, UserTypeAnnotationIndex,
} }

View file

@ -85,7 +85,7 @@ macro_rules! make_mir_visitor {
} }
fn visit_source_scope_data(&mut self, fn visit_source_scope_data(&mut self,
scope_data: & $($mutability)? SourceScopeData) { scope_data: & $($mutability)? SourceScopeData<'tcx>) {
self.super_source_scope_data(scope_data); self.super_source_scope_data(scope_data);
} }
@ -317,10 +317,15 @@ macro_rules! make_mir_visitor {
} }
} }
fn super_source_scope_data(&mut self, scope_data: & $($mutability)? SourceScopeData) { fn super_source_scope_data(
&mut self,
scope_data: & $($mutability)? SourceScopeData<'tcx>,
) {
let SourceScopeData { let SourceScopeData {
span, span,
parent_scope, parent_scope,
inlined,
inlined_parent_scope,
local_data: _, local_data: _,
} = scope_data; } = scope_data;
@ -328,6 +333,34 @@ macro_rules! make_mir_visitor {
if let Some(parent_scope) = parent_scope { if let Some(parent_scope) = parent_scope {
self.visit_source_scope(parent_scope); self.visit_source_scope(parent_scope);
} }
if let Some((callee, callsite_span)) = inlined {
let location = START_BLOCK.start_location();
self.visit_span(callsite_span);
let ty::Instance { def: callee_def, substs: callee_substs } = callee;
match callee_def {
ty::InstanceDef::Item(_def_id) => {}
ty::InstanceDef::Intrinsic(_def_id) |
ty::InstanceDef::VtableShim(_def_id) |
ty::InstanceDef::ReifyShim(_def_id) |
ty::InstanceDef::Virtual(_def_id, _) |
ty::InstanceDef::ClosureOnceShim { call_once: _def_id } |
ty::InstanceDef::DropGlue(_def_id, None) => {}
ty::InstanceDef::FnPtrShim(_def_id, ty) |
ty::InstanceDef::DropGlue(_def_id, Some(ty)) |
ty::InstanceDef::CloneShim(_def_id, ty) => {
// FIXME(eddyb) use a better `TyContext` here.
self.visit_ty(ty, TyContext::Location(location));
}
}
self.visit_substs(callee_substs, location);
}
if let Some(inlined_parent_scope) = inlined_parent_scope {
self.visit_source_scope(inlined_parent_scope);
}
} }
fn super_statement(&mut self, fn super_statement(&mut self,

View file

@ -15,38 +15,61 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
/// Walks up the callstack from the intrinsic's callsite, searching for the first callsite in a /// Walks up the callstack from the intrinsic's callsite, searching for the first callsite in a
/// frame which is not `#[track_caller]`. /// frame which is not `#[track_caller]`.
crate fn find_closest_untracked_caller_location(&self) -> Span { crate fn find_closest_untracked_caller_location(&self) -> Span {
let frame = self for frame in self.stack().iter().rev() {
.stack() debug!("find_closest_untracked_caller_location: checking frame {:?}", frame.instance);
.iter()
.rev() // Assert that the frame we look at is actually executing code currently
// Find first non-`#[track_caller]` frame. // (`loc` is `Err` when we are unwinding and the frame does not require cleanup).
.find(|frame| { let loc = frame.loc.unwrap();
// This could be a non-`Call` terminator (such as `Drop`), or not a terminator at all
// (such as `box`). Use the normal span by default.
let mut source_info = *frame.body.source_info(loc);
// If this is a `Call` terminator, use the `fn_span` instead.
let block = &frame.body.basic_blocks()[loc.block];
if loc.statement_index == block.statements.len() {
debug!( debug!(
"find_closest_untracked_caller_location: checking frame {:?}", "find_closest_untracked_caller_location: got terminator {:?} ({:?})",
frame.instance block.terminator(),
block.terminator().kind
); );
!frame.instance.def.requires_caller_location(*self.tcx) if let TerminatorKind::Call { fn_span, .. } = block.terminator().kind {
}) source_info.span = fn_span;
// Assert that there is always such a frame. }
.unwrap(); }
// Assert that the frame we look at is actually executing code currently
// (`loc` is `Err` when we are unwinding and the frame does not require cleanup). // Walk up the `SourceScope`s, in case some of them are from MIR inlining.
let loc = frame.loc.unwrap(); // If so, the starting `source_info.span` is in the innermost inlined
// If this is a `Call` terminator, use the `fn_span` instead. // function, and will be replaced with outer callsite spans as long
let block = &frame.body.basic_blocks()[loc.block]; // as the inlined functions were `#[track_caller]`.
if loc.statement_index == block.statements.len() { loop {
debug!( let scope_data = &frame.body.source_scopes[source_info.scope];
"find_closest_untracked_caller_location:: got terminator {:?} ({:?})",
block.terminator(), if let Some((callee, callsite_span)) = scope_data.inlined {
block.terminator().kind // Stop inside the most nested non-`#[track_caller]` function,
); // before ever reaching its caller (which is irrelevant).
if let TerminatorKind::Call { fn_span, .. } = block.terminator().kind { if !callee.def.requires_caller_location(*self.tcx) {
return fn_span; return source_info.span;
}
source_info.span = callsite_span;
}
// Skip past all of the parents with `inlined: None`.
match scope_data.inlined_parent_scope {
Some(parent) => source_info.scope = parent,
None => break,
}
}
// Stop inside the most nested non-`#[track_caller]` function,
// before ever reaching its caller (which is irrelevant).
if !frame.instance.def.requires_caller_location(*self.tcx) {
return source_info.span;
} }
} }
// This is a different terminator (such as `Drop`) or not a terminator at all
// (such as `box`). Use the normal span. bug!("no non-`#[track_caller]` frame found")
frame.body.source_info(loc).span
} }
/// Allocate a `const core::panic::Location` with the provided filename and line/column numbers. /// Allocate a `const core::panic::Location` with the provided filename and line/column numbers.

View file

@ -212,7 +212,13 @@ fn new_body<'tcx>(
source, source,
basic_blocks, basic_blocks,
IndexVec::from_elem_n( IndexVec::from_elem_n(
SourceScopeData { span, parent_scope: None, local_data: ClearCrossCrate::Clear }, SourceScopeData {
span,
parent_scope: None,
inlined: None,
inlined_parent_scope: None,
local_data: ClearCrossCrate::Clear,
},
1, 1,
), ),
local_decls, local_decls,

View file

@ -313,7 +313,7 @@ struct ConstPropagator<'mir, 'tcx> {
param_env: ParamEnv<'tcx>, param_env: ParamEnv<'tcx>,
// FIXME(eddyb) avoid cloning these two fields more than once, // FIXME(eddyb) avoid cloning these two fields more than once,
// by accessing them through `ecx` instead. // by accessing them through `ecx` instead.
source_scopes: IndexVec<SourceScope, SourceScopeData>, source_scopes: IndexVec<SourceScope, SourceScopeData<'tcx>>,
local_decls: IndexVec<Local, LocalDecl<'tcx>>, local_decls: IndexVec<Local, LocalDecl<'tcx>>,
// Because we have `MutVisitor` we can't obtain the `SourceInfo` from a `Location`. So we store // Because we have `MutVisitor` we can't obtain the `SourceInfo` from a `Location`. So we store
// the last known `SourceInfo` here and just keep revisiting it. // the last known `SourceInfo` here and just keep revisiting it.

View file

@ -1,13 +1,12 @@
//! Inlining pass for MIR functions //! Inlining pass for MIR functions
use rustc_attr as attr; use rustc_attr as attr;
use rustc_hir::def_id::DefId;
use rustc_index::bit_set::BitSet; use rustc_index::bit_set::BitSet;
use rustc_index::vec::{Idx, IndexVec}; use rustc_index::vec::Idx;
use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
use rustc_middle::mir::visit::*; use rustc_middle::mir::visit::*;
use rustc_middle::mir::*; use rustc_middle::mir::*;
use rustc_middle::ty::subst::{Subst, SubstsRef}; use rustc_middle::ty::subst::Subst;
use rustc_middle::ty::{self, ConstKind, Instance, InstanceDef, ParamEnv, Ty, TyCtxt}; use rustc_middle::ty::{self, ConstKind, Instance, InstanceDef, ParamEnv, Ty, TyCtxt};
use rustc_target::spec::abi::Abi; use rustc_target::spec::abi::Abi;
@ -15,6 +14,7 @@ use super::simplify::{remove_dead_blocks, CfgSimplifier};
use crate::transform::MirPass; use crate::transform::MirPass;
use std::collections::VecDeque; use std::collections::VecDeque;
use std::iter; use std::iter;
use std::ops::RangeFrom;
const DEFAULT_THRESHOLD: usize = 50; const DEFAULT_THRESHOLD: usize = 50;
const HINT_THRESHOLD: usize = 100; const HINT_THRESHOLD: usize = 100;
@ -30,10 +30,9 @@ pub struct Inline;
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
struct CallSite<'tcx> { struct CallSite<'tcx> {
callee: DefId, callee: Instance<'tcx>,
substs: SubstsRef<'tcx>,
bb: BasicBlock, bb: BasicBlock,
location: SourceInfo, source_info: SourceInfo,
} }
impl<'tcx> MirPass<'tcx> for Inline { impl<'tcx> MirPass<'tcx> for Inline {
@ -101,14 +100,20 @@ impl Inliner<'tcx> {
local_change = false; local_change = false;
while let Some(callsite) = callsites.pop_front() { while let Some(callsite) = callsites.pop_front() {
debug!("checking whether to inline callsite {:?}", callsite); debug!("checking whether to inline callsite {:?}", callsite);
if !self.tcx.is_mir_available(callsite.callee) {
debug!("checking whether to inline callsite {:?} - MIR unavailable", callsite); if let InstanceDef::Item(_) = callsite.callee.def {
continue; if !self.tcx.is_mir_available(callsite.callee.def_id()) {
debug!(
"checking whether to inline callsite {:?} - MIR unavailable",
callsite,
);
continue;
}
} }
let callee_body = if let Some(callee_def_id) = callsite.callee.as_local() { let callee_body = if let Some(callee_def_id) = callsite.callee.def_id().as_local() {
let callee_hir_id = self.tcx.hir().local_def_id_to_hir_id(callee_def_id); let callee_hir_id = self.tcx.hir().local_def_id_to_hir_id(callee_def_id);
// Avoid a cycle here by only using `optimized_mir` only if we have // Avoid a cycle here by only using `instance_mir` only if we have
// a lower `HirId` than the callee. This ensures that the callee will // a lower `HirId` than the callee. This ensures that the callee will
// not inline us. This trick only works without incremental compilation. // not inline us. This trick only works without incremental compilation.
// So don't do it if that is enabled. Also avoid inlining into generators, // So don't do it if that is enabled. Also avoid inlining into generators,
@ -119,19 +124,21 @@ impl Inliner<'tcx> {
&& self_hir_id < callee_hir_id && self_hir_id < callee_hir_id
&& caller_body.generator_kind.is_none() && caller_body.generator_kind.is_none()
{ {
self.tcx.optimized_mir(callsite.callee) self.tcx.instance_mir(callsite.callee.def)
} else { } else {
continue; continue;
} }
} else { } else {
// This cannot result in a cycle since the callee MIR is from another crate // This cannot result in a cycle since the callee MIR is from another crate
// and is already optimized. // and is already optimized.
self.tcx.optimized_mir(callsite.callee) self.tcx.instance_mir(callsite.callee.def)
}; };
let callee_body: &Body<'tcx> = &*callee_body;
let callee_body = if self.consider_optimizing(callsite, callee_body) { let callee_body = if self.consider_optimizing(callsite, callee_body) {
self.tcx.subst_and_normalize_erasing_regions( self.tcx.subst_and_normalize_erasing_regions(
&callsite.substs, &callsite.callee.substs,
self.param_env, self.param_env,
callee_body, callee_body,
) )
@ -204,21 +211,16 @@ impl Inliner<'tcx> {
// To resolve an instance its substs have to be fully normalized, so // To resolve an instance its substs have to be fully normalized, so
// we do this here. // we do this here.
let normalized_substs = self.tcx.normalize_erasing_regions(self.param_env, substs); let normalized_substs = self.tcx.normalize_erasing_regions(self.param_env, substs);
let instance = let callee =
Instance::resolve(self.tcx, self.param_env, callee_def_id, normalized_substs) Instance::resolve(self.tcx, self.param_env, callee_def_id, normalized_substs)
.ok() .ok()
.flatten()?; .flatten()?;
if let InstanceDef::Virtual(..) = instance.def { if let InstanceDef::Virtual(..) | InstanceDef::Intrinsic(_) = callee.def {
return None; return None;
} }
return Some(CallSite { return Some(CallSite { callee, bb, source_info: terminator.source_info });
callee: instance.def_id(),
substs: instance.substs,
bb,
location: terminator.source_info,
});
} }
} }
@ -243,12 +245,7 @@ impl Inliner<'tcx> {
return false; return false;
} }
let codegen_fn_attrs = tcx.codegen_fn_attrs(callsite.callee); let codegen_fn_attrs = tcx.codegen_fn_attrs(callsite.callee.def_id());
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::TRACK_CALLER) {
debug!("`#[track_caller]` present - not inlining");
return false;
}
let self_features = &self.codegen_fn_attrs.target_features; let self_features = &self.codegen_fn_attrs.target_features;
let callee_features = &codegen_fn_attrs.target_features; let callee_features = &codegen_fn_attrs.target_features;
@ -282,8 +279,8 @@ impl Inliner<'tcx> {
// Only inline local functions if they would be eligible for cross-crate // Only inline local functions if they would be eligible for cross-crate
// inlining. This is to ensure that the final crate doesn't have MIR that // inlining. This is to ensure that the final crate doesn't have MIR that
// reference unexported symbols // reference unexported symbols
if callsite.callee.is_local() { if callsite.callee.def_id().is_local() {
if callsite.substs.non_erasable_generics().count() == 0 && !hinted { if callsite.callee.substs.non_erasable_generics().count() == 0 && !hinted {
debug!(" callee is an exported function - not inlining"); debug!(" callee is an exported function - not inlining");
return false; return false;
} }
@ -336,7 +333,7 @@ impl Inliner<'tcx> {
work_list.push(target); work_list.push(target);
// If the place doesn't actually need dropping, treat it like // If the place doesn't actually need dropping, treat it like
// a regular goto. // a regular goto.
let ty = place.ty(callee_body, tcx).subst(tcx, callsite.substs).ty; let ty = place.ty(callee_body, tcx).subst(tcx, callsite.callee.substs).ty;
if ty.needs_drop(tcx, self.param_env) { if ty.needs_drop(tcx, self.param_env) {
cost += CALL_PENALTY; cost += CALL_PENALTY;
if let Some(unwind) = unwind { if let Some(unwind) = unwind {
@ -399,7 +396,7 @@ impl Inliner<'tcx> {
for v in callee_body.vars_and_temps_iter() { for v in callee_body.vars_and_temps_iter() {
let v = &callee_body.local_decls[v]; let v = &callee_body.local_decls[v];
let ty = v.ty.subst(tcx, callsite.substs); let ty = v.ty.subst(tcx, callsite.callee.substs);
// Cost of the var is the size in machine-words, if we know // Cost of the var is the size in machine-words, if we know
// it. // it.
if let Some(size) = type_size_of(tcx, self.param_env, ty) { if let Some(size) = type_size_of(tcx, self.param_env, ty) {
@ -435,36 +432,6 @@ impl Inliner<'tcx> {
TerminatorKind::Call { args, destination: Some(destination), cleanup, .. } => { TerminatorKind::Call { args, destination: Some(destination), cleanup, .. } => {
debug!("inlined {:?} into {:?}", callsite.callee, caller_body.source); debug!("inlined {:?} into {:?}", callsite.callee, caller_body.source);
let mut local_map = IndexVec::with_capacity(callee_body.local_decls.len());
let mut scope_map = IndexVec::with_capacity(callee_body.source_scopes.len());
for mut scope in callee_body.source_scopes.iter().cloned() {
if scope.parent_scope.is_none() {
scope.parent_scope = Some(callsite.location.scope);
// FIXME(eddyb) is this really needed?
// (also note that it's always overwritten below)
scope.span = callee_body.span;
}
// FIXME(eddyb) this doesn't seem right at all.
// The inlined source scopes should probably be annotated as
// such, but also contain all of the original information.
scope.span = callsite.location.span;
let idx = caller_body.source_scopes.push(scope);
scope_map.push(idx);
}
for loc in callee_body.vars_and_temps_iter() {
let mut local = callee_body.local_decls[loc].clone();
local.source_info.scope = scope_map[local.source_info.scope];
local.source_info.span = callsite.location.span;
let idx = caller_body.local_decls.push(local);
local_map.push(idx);
}
// If the call is something like `a[*i] = f(i)`, where // If the call is something like `a[*i] = f(i)`, where
// `i : &mut usize`, then just duplicating the `a[*i]` // `i : &mut usize`, then just duplicating the `a[*i]`
// Place could result in two different locations if `f` // Place could result in two different locations if `f`
@ -491,13 +458,13 @@ impl Inliner<'tcx> {
let ty = dest.ty(caller_body, self.tcx); let ty = dest.ty(caller_body, self.tcx);
let temp = LocalDecl::new(ty, callsite.location.span); let temp = LocalDecl::new(ty, callsite.source_info.span);
let tmp = caller_body.local_decls.push(temp); let tmp = caller_body.local_decls.push(temp);
let tmp = Place::from(tmp); let tmp = Place::from(tmp);
let stmt = Statement { let stmt = Statement {
source_info: callsite.location, source_info: callsite.source_info,
kind: StatementKind::Assign(box (tmp, dest)), kind: StatementKind::Assign(box (tmp, dest)),
}; };
caller_body[callsite.bb].statements.push(stmt); caller_body[callsite.bb].statements.push(stmt);
@ -511,12 +478,11 @@ impl Inliner<'tcx> {
// Copy the arguments if needed. // Copy the arguments if needed.
let args: Vec<_> = self.make_call_args(args, &callsite, caller_body, return_block); let args: Vec<_> = self.make_call_args(args, &callsite, caller_body, return_block);
let bb_len = caller_body.basic_blocks().len();
let mut integrator = Integrator { let mut integrator = Integrator {
block_idx: bb_len,
args: &args, args: &args,
local_map, new_locals: Local::new(caller_body.local_decls.len())..,
scope_map, new_scopes: SourceScope::new(caller_body.source_scopes.len())..,
new_blocks: BasicBlock::new(caller_body.basic_blocks().len())..,
destination: dest, destination: dest,
return_block, return_block,
cleanup_block: cleanup, cleanup_block: cleanup,
@ -524,22 +490,51 @@ impl Inliner<'tcx> {
tcx: self.tcx, tcx: self.tcx,
}; };
for mut var_debug_info in callee_body.var_debug_info.drain(..) { // Map all `Local`s, `SourceScope`s and `BasicBlock`s to new ones
integrator.visit_var_debug_info(&mut var_debug_info); // (or existing ones, in a few special cases) in the caller.
caller_body.var_debug_info.push(var_debug_info); integrator.visit_body(&mut callee_body);
for scope in &mut callee_body.source_scopes {
// FIXME(eddyb) move this into a `fn visit_scope_data` in `Integrator`.
if scope.parent_scope.is_none() {
let callsite_scope = &caller_body.source_scopes[callsite.source_info.scope];
// Attach the outermost callee scope as a child of the callsite
// scope, via the `parent_scope` and `inlined_parent_scope` chains.
scope.parent_scope = Some(callsite.source_info.scope);
assert_eq!(scope.inlined_parent_scope, None);
scope.inlined_parent_scope = if callsite_scope.inlined.is_some() {
Some(callsite.source_info.scope)
} else {
callsite_scope.inlined_parent_scope
};
// Mark the outermost callee scope as an inlined one.
assert_eq!(scope.inlined, None);
scope.inlined = Some((callsite.callee, callsite.source_info.span));
} else if scope.inlined_parent_scope.is_none() {
// Make it easy to find the scope with `inlined` set above.
scope.inlined_parent_scope =
Some(integrator.map_scope(OUTERMOST_SOURCE_SCOPE));
}
} }
for (bb, mut block) in callee_body.basic_blocks_mut().drain_enumerated(..) { // Insert all of the (mapped) parts of the callee body into the caller.
integrator.visit_basic_block_data(bb, &mut block); caller_body.local_decls.extend(
caller_body.basic_blocks_mut().push(block); // FIXME(eddyb) make `Range<Local>` iterable so that we can use
} // `callee_body.local_decls.drain(callee_body.vars_and_temps())`
callee_body
.vars_and_temps_iter()
.map(|local| callee_body.local_decls[local].clone()),
);
caller_body.source_scopes.extend(callee_body.source_scopes.drain(..));
caller_body.var_debug_info.extend(callee_body.var_debug_info.drain(..));
caller_body.basic_blocks_mut().extend(callee_body.basic_blocks_mut().drain(..));
let terminator = Terminator { caller_body[callsite.bb].terminator = Some(Terminator {
source_info: callsite.location, source_info: callsite.source_info,
kind: TerminatorKind::Goto { target: BasicBlock::new(bb_len) }, kind: TerminatorKind::Goto { target: integrator.map_block(START_BLOCK) },
}; });
caller_body[callsite.bb].terminator = Some(terminator);
true true
} }
@ -583,7 +578,9 @@ impl Inliner<'tcx> {
// tmp2 = tuple_tmp.2 // tmp2 = tuple_tmp.2
// //
// and the vector is `[closure_ref, tmp0, tmp1, tmp2]`. // and the vector is `[closure_ref, tmp0, tmp1, tmp2]`.
if tcx.is_closure(callsite.callee) { // FIXME(eddyb) make this check for `"rust-call"` ABI combined with
// `callee_body.spread_arg == None`, instead of special-casing closures.
if tcx.is_closure(callsite.callee.def_id()) {
let mut args = args.into_iter(); let mut args = args.into_iter();
let self_ = self.create_temp_if_necessary( let self_ = self.create_temp_if_necessary(
args.next().unwrap(), args.next().unwrap(),
@ -654,20 +651,23 @@ impl Inliner<'tcx> {
let ty = arg.ty(caller_body, self.tcx); let ty = arg.ty(caller_body, self.tcx);
let arg_tmp = LocalDecl::new(ty, callsite.location.span); let arg_tmp = LocalDecl::new(ty, callsite.source_info.span);
let arg_tmp = caller_body.local_decls.push(arg_tmp); let arg_tmp = caller_body.local_decls.push(arg_tmp);
caller_body[callsite.bb].statements.push(Statement { caller_body[callsite.bb].statements.push(Statement {
source_info: callsite.location, source_info: callsite.source_info,
kind: StatementKind::StorageLive(arg_tmp), kind: StatementKind::StorageLive(arg_tmp),
}); });
caller_body[callsite.bb].statements.push(Statement { caller_body[callsite.bb].statements.push(Statement {
source_info: callsite.location, source_info: callsite.source_info,
kind: StatementKind::Assign(box (Place::from(arg_tmp), arg)), kind: StatementKind::Assign(box (Place::from(arg_tmp), arg)),
}); });
caller_body[return_block].statements.insert( caller_body[return_block].statements.insert(
0, 0,
Statement { source_info: callsite.location, kind: StatementKind::StorageDead(arg_tmp) }, Statement {
source_info: callsite.source_info,
kind: StatementKind::StorageDead(arg_tmp),
},
); );
arg_tmp arg_tmp
@ -690,10 +690,10 @@ fn type_size_of<'tcx>(
* stuff. * stuff.
*/ */
struct Integrator<'a, 'tcx> { struct Integrator<'a, 'tcx> {
block_idx: usize,
args: &'a [Local], args: &'a [Local],
local_map: IndexVec<Local, Local>, new_locals: RangeFrom<Local>,
scope_map: IndexVec<SourceScope, SourceScope>, new_scopes: RangeFrom<SourceScope>,
new_blocks: RangeFrom<BasicBlock>,
destination: Place<'tcx>, destination: Place<'tcx>,
return_block: BasicBlock, return_block: BasicBlock,
cleanup_block: Option<BasicBlock>, cleanup_block: Option<BasicBlock>,
@ -702,23 +702,31 @@ struct Integrator<'a, 'tcx> {
} }
impl<'a, 'tcx> Integrator<'a, 'tcx> { impl<'a, 'tcx> Integrator<'a, 'tcx> {
fn update_target(&self, tgt: BasicBlock) -> BasicBlock { fn map_local(&self, local: Local) -> Local {
let new = BasicBlock::new(tgt.index() + self.block_idx); let new = if local == RETURN_PLACE {
debug!("updating target `{:?}`, new: `{:?}`", tgt, new); self.destination.local
} else {
let idx = local.index() - 1;
if idx < self.args.len() {
self.args[idx]
} else {
Local::new(self.new_locals.start.index() + (idx - self.args.len()))
}
};
debug!("mapping local `{:?}` to `{:?}`", local, new);
new new
} }
fn make_integrate_local(&self, local: Local) -> Local { fn map_scope(&self, scope: SourceScope) -> SourceScope {
if local == RETURN_PLACE { let new = SourceScope::new(self.new_scopes.start.index() + scope.index());
return self.destination.local; debug!("mapping scope `{:?}` to `{:?}`", scope, new);
} new
}
let idx = local.index() - 1; fn map_block(&self, block: BasicBlock) -> BasicBlock {
if idx < self.args.len() { let new = BasicBlock::new(self.new_blocks.start.index() + block.index());
return self.args[idx]; debug!("mapping block `{:?}` to `{:?}`", block, new);
} new
self.local_map[Local::new(idx - self.args.len())]
} }
} }
@ -728,7 +736,11 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> {
} }
fn visit_local(&mut self, local: &mut Local, _ctxt: PlaceContext, _location: Location) { fn visit_local(&mut self, local: &mut Local, _ctxt: PlaceContext, _location: Location) {
*local = self.make_integrate_local(*local); *local = self.map_local(*local);
}
fn visit_source_scope(&mut self, scope: &mut SourceScope) {
*scope = self.map_scope(*scope);
} }
fn visit_place(&mut self, place: &mut Place<'tcx>, context: PlaceContext, location: Location) { fn visit_place(&mut self, place: &mut Place<'tcx>, context: PlaceContext, location: Location) {
@ -772,18 +784,18 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> {
match terminator.kind { match terminator.kind {
TerminatorKind::GeneratorDrop | TerminatorKind::Yield { .. } => bug!(), TerminatorKind::GeneratorDrop | TerminatorKind::Yield { .. } => bug!(),
TerminatorKind::Goto { ref mut target } => { TerminatorKind::Goto { ref mut target } => {
*target = self.update_target(*target); *target = self.map_block(*target);
} }
TerminatorKind::SwitchInt { ref mut targets, .. } => { TerminatorKind::SwitchInt { ref mut targets, .. } => {
for tgt in targets.all_targets_mut() { for tgt in targets.all_targets_mut() {
*tgt = self.update_target(*tgt); *tgt = self.map_block(*tgt);
} }
} }
TerminatorKind::Drop { ref mut target, ref mut unwind, .. } TerminatorKind::Drop { ref mut target, ref mut unwind, .. }
| TerminatorKind::DropAndReplace { ref mut target, ref mut unwind, .. } => { | TerminatorKind::DropAndReplace { ref mut target, ref mut unwind, .. } => {
*target = self.update_target(*target); *target = self.map_block(*target);
if let Some(tgt) = *unwind { if let Some(tgt) = *unwind {
*unwind = Some(self.update_target(tgt)); *unwind = Some(self.map_block(tgt));
} else if !self.in_cleanup_block { } else if !self.in_cleanup_block {
// Unless this drop is in a cleanup block, add an unwind edge to // Unless this drop is in a cleanup block, add an unwind edge to
// the original call's cleanup block // the original call's cleanup block
@ -792,10 +804,10 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> {
} }
TerminatorKind::Call { ref mut destination, ref mut cleanup, .. } => { TerminatorKind::Call { ref mut destination, ref mut cleanup, .. } => {
if let Some((_, ref mut tgt)) = *destination { if let Some((_, ref mut tgt)) = *destination {
*tgt = self.update_target(*tgt); *tgt = self.map_block(*tgt);
} }
if let Some(tgt) = *cleanup { if let Some(tgt) = *cleanup {
*cleanup = Some(self.update_target(tgt)); *cleanup = Some(self.map_block(tgt));
} else if !self.in_cleanup_block { } else if !self.in_cleanup_block {
// Unless this call is in a cleanup block, add an unwind edge to // Unless this call is in a cleanup block, add an unwind edge to
// the original call's cleanup block // the original call's cleanup block
@ -803,9 +815,9 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> {
} }
} }
TerminatorKind::Assert { ref mut target, ref mut cleanup, .. } => { TerminatorKind::Assert { ref mut target, ref mut cleanup, .. } => {
*target = self.update_target(*target); *target = self.map_block(*target);
if let Some(tgt) = *cleanup { if let Some(tgt) = *cleanup {
*cleanup = Some(self.update_target(tgt)); *cleanup = Some(self.map_block(tgt));
} else if !self.in_cleanup_block { } else if !self.in_cleanup_block {
// Unless this assert is in a cleanup block, add an unwind edge to // Unless this assert is in a cleanup block, add an unwind edge to
// the original call's cleanup block // the original call's cleanup block
@ -823,8 +835,8 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> {
TerminatorKind::Abort => {} TerminatorKind::Abort => {}
TerminatorKind::Unreachable => {} TerminatorKind::Unreachable => {}
TerminatorKind::FalseEdge { ref mut real_target, ref mut imaginary_target } => { TerminatorKind::FalseEdge { ref mut real_target, ref mut imaginary_target } => {
*real_target = self.update_target(*real_target); *real_target = self.map_block(*real_target);
*imaginary_target = self.update_target(*imaginary_target); *imaginary_target = self.map_block(*imaginary_target);
} }
TerminatorKind::FalseUnwind { real_target: _, unwind: _ } => TerminatorKind::FalseUnwind { real_target: _, unwind: _ } =>
// see the ordering of passes in the optimized_mir query. // see the ordering of passes in the optimized_mir query.
@ -833,13 +845,9 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> {
} }
TerminatorKind::InlineAsm { ref mut destination, .. } => { TerminatorKind::InlineAsm { ref mut destination, .. } => {
if let Some(ref mut tgt) = *destination { if let Some(ref mut tgt) = *destination {
*tgt = self.update_target(*tgt); *tgt = self.map_block(*tgt);
} }
} }
} }
} }
fn visit_source_scope(&mut self, scope: &mut SourceScope) {
*scope = self.scope_map[*scope];
}
} }

View file

@ -548,8 +548,36 @@ fn write_scope_tree(
}; };
for &child in children { for &child in children {
assert_eq!(body.source_scopes[child].parent_scope, Some(parent)); let child_data = &body.source_scopes[child];
writeln!(w, "{0:1$}scope {2} {{", "", indent, child.index())?; assert_eq!(child_data.parent_scope, Some(parent));
let (special, span) = if let Some((callee, callsite_span)) = child_data.inlined {
(
format!(
" (inlined {}{})",
if callee.def.requires_caller_location(tcx) { "#[track_caller] " } else { "" },
callee
),
Some(callsite_span),
)
} else {
(String::new(), None)
};
let indented_header = format!("{0:1$}scope {2}{3} {{", "", indent, child.index(), special);
if let Some(span) = span {
writeln!(
w,
"{0:1$} // at {2}",
indented_header,
ALIGN,
tcx.sess.source_map().span_to_string(span),
)?;
} else {
writeln!(w, "{}", indented_header)?;
}
write_scope_tree(tcx, body, scope_tree, w, child, depth + 1)?; write_scope_tree(tcx, body, scope_tree, w, child, depth + 1)?;
writeln!(w, "{0:1$}}}", "", depth * INDENT.len())?; writeln!(w, "{0:1$}}}", "", depth * INDENT.len())?;
} }

View file

@ -334,7 +334,7 @@ struct Builder<'a, 'tcx> {
/// The vector of all scopes that we have created thus far; /// The vector of all scopes that we have created thus far;
/// we track this for debuginfo later. /// we track this for debuginfo later.
source_scopes: IndexVec<SourceScope, SourceScopeData>, source_scopes: IndexVec<SourceScope, SourceScopeData<'tcx>>,
source_scope: SourceScope, source_scope: SourceScope,
/// The guard-context: each time we build the guard expression for /// The guard-context: each time we build the guard expression for

View file

@ -705,6 +705,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
self.source_scopes.push(SourceScopeData { self.source_scopes.push(SourceScopeData {
span, span,
parent_scope: Some(parent), parent_scope: Some(parent),
inlined: None,
inlined_parent_scope: None,
local_data: ClearCrossCrate::Set(scope_local_data), local_data: ClearCrossCrate::Set(scope_local_data),
}) })
} }

View file

@ -0,0 +1,17 @@
#![crate_type="rlib"]
// compile-flags: -Copt-level=3 -g
// ignore-tidy-linelength
#[no_mangle]
#[inline(always)]
pub extern "C" fn callee(x: u32) -> u32 {
x + 4
}
// CHECK-LABEL: caller
// CHECK: call void @llvm.dbg.value(metadata i32 %y, metadata !{{.*}}, metadata !DIExpression(DW_OP_constu, 3, DW_OP_minus, DW_OP_stack_value)), !dbg [[A:!.*]]
// CHECK: [[A]] = !DILocation(line: {{.*}}, scope: {{.*}}, inlinedAt: {{.*}})
#[no_mangle]
pub extern "C" fn caller(y: u32) -> u32 {
callee(y - 3)
}

View file

@ -18,7 +18,7 @@
scope 3 { scope 3 {
- debug z => _3; // in scope 3 at $DIR/cycle.rs:11:9: 11:10 - debug z => _3; // in scope 3 at $DIR/cycle.rs:11:9: 11:10
+ debug z => _4; // in scope 3 at $DIR/cycle.rs:11:9: 11:10 + debug z => _4; // in scope 3 at $DIR/cycle.rs:11:9: 11:10
scope 4 { scope 4 (inlined std::mem::drop::<i32>) { // at $DIR/cycle.rs:14:5: 14:12
debug _x => _6; // in scope 4 at $SRC_DIR/core/src/mem/mod.rs:LL:COL debug _x => _6; // in scope 4 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
} }
} }

View file

@ -11,7 +11,7 @@
debug un => _1; // in scope 1 at $DIR/union.rs:13:9: 13:11 debug un => _1; // in scope 1 at $DIR/union.rs:13:9: 13:11
scope 2 { scope 2 {
} }
scope 3 { scope 3 (inlined std::mem::drop::<u32>) { // at $DIR/union.rs:15:5: 15:27
debug _x => _4; // in scope 3 at $SRC_DIR/core/src/mem/mod.rs:LL:COL debug _x => _4; // in scope 3 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
} }
} }

View file

@ -26,9 +26,9 @@ fn main::{closure#0}(_1: *mut [generator@$DIR/generator-drop-cleanup.rs:10:15: 1
scope 1 { scope 1 {
debug _s => (((*_1) as variant#3).0: std::string::String); // in scope 1 at $DIR/generator-drop-cleanup.rs:11:13: 11:15 debug _s => (((*_1) as variant#3).0: std::string::String); // in scope 1 at $DIR/generator-drop-cleanup.rs:11:13: 11:15
} }
scope 2 { scope 2 (inlined String::new) { // at $DIR/generator-drop-cleanup.rs:11:18: 11:31
let mut _6: std::vec::Vec<u8>; // in scope 2 at $DIR/generator-drop-cleanup.rs:11:18: 11:31 let mut _6: std::vec::Vec<u8>; // in scope 2 at $SRC_DIR/alloc/src/string.rs:LL:COL
scope 3 { scope 3 (inlined Vec::<u8>::new) { // at $SRC_DIR/alloc/src/string.rs:LL:COL
} }
} }

View file

@ -4,15 +4,15 @@ fn bar() -> bool {
let mut _0: bool; // return place in scope 0 at $DIR/inline-any-operand.rs:10:13: 10:17 let mut _0: bool; // return place in scope 0 at $DIR/inline-any-operand.rs:10:13: 10:17
let _1: fn(i32, i32) -> bool {foo}; // in scope 0 at $DIR/inline-any-operand.rs:11:9: 11:10 let _1: fn(i32, i32) -> bool {foo}; // in scope 0 at $DIR/inline-any-operand.rs:11:9: 11:10
let mut _2: fn(i32, i32) -> bool {foo}; // in scope 0 at $DIR/inline-any-operand.rs:12:5: 12:6 let mut _2: fn(i32, i32) -> bool {foo}; // in scope 0 at $DIR/inline-any-operand.rs:12:5: 12:6
let mut _5: i32; // in scope 0 at $DIR/inline-any-operand.rs:12:5: 12:13 let mut _3: i32; // in scope 0 at $DIR/inline-any-operand.rs:12:5: 12:13
let mut _6: i32; // in scope 0 at $DIR/inline-any-operand.rs:12:5: 12:13 let mut _4: i32; // in scope 0 at $DIR/inline-any-operand.rs:12:5: 12:13
scope 1 { scope 1 {
debug f => _1; // in scope 1 at $DIR/inline-any-operand.rs:11:9: 11:10 debug f => _1; // in scope 1 at $DIR/inline-any-operand.rs:11:9: 11:10
scope 2 { scope 2 (inlined foo) { // at $DIR/inline-any-operand.rs:12:5: 12:13
debug x => _5; // in scope 2 at $DIR/inline-any-operand.rs:16:8: 16:9 debug x => _3; // in scope 2 at $DIR/inline-any-operand.rs:16:8: 16:9
debug y => _6; // in scope 2 at $DIR/inline-any-operand.rs:16:16: 16:17 debug y => _4; // in scope 2 at $DIR/inline-any-operand.rs:16:16: 16:17
let mut _3: i32; // in scope 2 at $DIR/inline-any-operand.rs:12:5: 12:13 let mut _5: i32; // in scope 2 at $DIR/inline-any-operand.rs:17:5: 17:6
let mut _4: i32; // in scope 2 at $DIR/inline-any-operand.rs:12:5: 12:13 let mut _6: i32; // in scope 2 at $DIR/inline-any-operand.rs:17:10: 17:11
} }
} }
@ -24,19 +24,19 @@ fn bar() -> bool {
// + literal: Const { ty: fn(i32, i32) -> bool {foo}, val: Value(Scalar(<ZST>)) } // + literal: Const { ty: fn(i32, i32) -> bool {foo}, val: Value(Scalar(<ZST>)) }
StorageLive(_2); // scope 1 at $DIR/inline-any-operand.rs:12:5: 12:6 StorageLive(_2); // scope 1 at $DIR/inline-any-operand.rs:12:5: 12:6
_2 = _1; // scope 1 at $DIR/inline-any-operand.rs:12:5: 12:6 _2 = _1; // scope 1 at $DIR/inline-any-operand.rs:12:5: 12:6
StorageLive(_5); // scope 1 at $DIR/inline-any-operand.rs:12:5: 12:13 StorageLive(_3); // scope 1 at $DIR/inline-any-operand.rs:12:5: 12:13
_5 = const 1_i32; // scope 1 at $DIR/inline-any-operand.rs:12:5: 12:13 _3 = const 1_i32; // scope 1 at $DIR/inline-any-operand.rs:12:5: 12:13
StorageLive(_6); // scope 1 at $DIR/inline-any-operand.rs:12:5: 12:13 StorageLive(_4); // scope 1 at $DIR/inline-any-operand.rs:12:5: 12:13
_6 = const -1_i32; // scope 1 at $DIR/inline-any-operand.rs:12:5: 12:13 _4 = const -1_i32; // scope 1 at $DIR/inline-any-operand.rs:12:5: 12:13
StorageLive(_3); // scope 2 at $DIR/inline-any-operand.rs:17:5: 17:6 StorageLive(_5); // scope 2 at $DIR/inline-any-operand.rs:17:5: 17:6
_3 = _5; // scope 2 at $DIR/inline-any-operand.rs:17:5: 17:6 _5 = _3; // scope 2 at $DIR/inline-any-operand.rs:17:5: 17:6
StorageLive(_4); // scope 2 at $DIR/inline-any-operand.rs:17:10: 17:11 StorageLive(_6); // scope 2 at $DIR/inline-any-operand.rs:17:10: 17:11
_4 = _6; // scope 2 at $DIR/inline-any-operand.rs:17:10: 17:11 _6 = _4; // scope 2 at $DIR/inline-any-operand.rs:17:10: 17:11
_0 = Eq(move _3, move _4); // scope 2 at $DIR/inline-any-operand.rs:17:5: 17:11 _0 = Eq(move _5, move _6); // scope 2 at $DIR/inline-any-operand.rs:17:5: 17:11
StorageDead(_4); // scope 2 at $DIR/inline-any-operand.rs:17:10: 17:11 StorageDead(_6); // scope 2 at $DIR/inline-any-operand.rs:17:10: 17:11
StorageDead(_3); // scope 2 at $DIR/inline-any-operand.rs:17:10: 17:11 StorageDead(_5); // scope 2 at $DIR/inline-any-operand.rs:17:10: 17:11
StorageDead(_6); // scope 1 at $DIR/inline-any-operand.rs:12:5: 12:13 StorageDead(_4); // scope 1 at $DIR/inline-any-operand.rs:12:5: 12:13
StorageDead(_5); // scope 1 at $DIR/inline-any-operand.rs:12:5: 12:13 StorageDead(_3); // scope 1 at $DIR/inline-any-operand.rs:12:5: 12:13
StorageDead(_2); // scope 1 at $DIR/inline-any-operand.rs:12:12: 12:13 StorageDead(_2); // scope 1 at $DIR/inline-any-operand.rs:12:12: 12:13
StorageDead(_1); // scope 0 at $DIR/inline-any-operand.rs:13:1: 13:2 StorageDead(_1); // scope 0 at $DIR/inline-any-operand.rs:13:1: 13:2
return; // scope 0 at $DIR/inline-any-operand.rs:13:2: 13:2 return; // scope 0 at $DIR/inline-any-operand.rs:13:2: 13:2

View file

@ -13,7 +13,7 @@ fn foo(_1: T, _2: i32) -> i32 {
let mut _9: i32; // in scope 0 at $DIR/inline-closure.rs:12:5: 12:12 let mut _9: i32; // in scope 0 at $DIR/inline-closure.rs:12:5: 12:12
scope 1 { scope 1 {
debug x => _3; // in scope 1 at $DIR/inline-closure.rs:11:9: 11:10 debug x => _3; // in scope 1 at $DIR/inline-closure.rs:11:9: 11:10
scope 2 { scope 2 (inlined foo::<T>::{closure#0}) { // at $DIR/inline-closure.rs:12:5: 12:12
debug _t => _8; // in scope 2 at $DIR/inline-closure.rs:11:14: 11:16 debug _t => _8; // in scope 2 at $DIR/inline-closure.rs:11:14: 11:16
debug _q => _9; // in scope 2 at $DIR/inline-closure.rs:11:18: 11:20 debug _q => _9; // in scope 2 at $DIR/inline-closure.rs:11:18: 11:20
} }

View file

@ -9,19 +9,19 @@ fn foo(_1: T, _2: &i32) -> i32 {
let mut _5: (&i32, &i32); // in scope 0 at $DIR/inline-closure-borrows-arg.rs:16:5: 16:12 let mut _5: (&i32, &i32); // in scope 0 at $DIR/inline-closure-borrows-arg.rs:16:5: 16:12
let mut _6: &i32; // in scope 0 at $DIR/inline-closure-borrows-arg.rs:16:7: 16:8 let mut _6: &i32; // in scope 0 at $DIR/inline-closure-borrows-arg.rs:16:7: 16:8
let mut _7: &i32; // in scope 0 at $DIR/inline-closure-borrows-arg.rs:16:10: 16:11 let mut _7: &i32; // in scope 0 at $DIR/inline-closure-borrows-arg.rs:16:10: 16:11
let mut _8: &i32; // in scope 0 at $DIR/inline-closure-borrows-arg.rs:16:5: 16:12
let mut _9: &i32; // in scope 0 at $DIR/inline-closure-borrows-arg.rs:16:5: 16:12 let mut _9: &i32; // in scope 0 at $DIR/inline-closure-borrows-arg.rs:16:5: 16:12
let mut _10: &i32; // in scope 0 at $DIR/inline-closure-borrows-arg.rs:16:5: 16:12
scope 1 { scope 1 {
debug x => _3; // in scope 1 at $DIR/inline-closure-borrows-arg.rs:12:9: 12:10 debug x => _3; // in scope 1 at $DIR/inline-closure-borrows-arg.rs:12:9: 12:10
scope 2 { scope 2 (inlined foo::<T>::{closure#0}) { // at $DIR/inline-closure-borrows-arg.rs:16:5: 16:12
debug r => _9; // in scope 2 at $DIR/inline-closure-borrows-arg.rs:12:14: 12:15 debug r => _8; // in scope 2 at $DIR/inline-closure-borrows-arg.rs:12:14: 12:15
debug _s => _10; // in scope 2 at $DIR/inline-closure-borrows-arg.rs:12:23: 12:25 debug _s => _9; // in scope 2 at $DIR/inline-closure-borrows-arg.rs:12:23: 12:25
let _8: &i32; // in scope 2 at $DIR/inline-closure-borrows-arg.rs:16:5: 16:12 let _10: &i32; // in scope 2 at $DIR/inline-closure-borrows-arg.rs:13:13: 13:21
scope 3 {
debug variable => _10; // in scope 3 at $DIR/inline-closure-borrows-arg.rs:13:13: 13:21
}
} }
} }
scope 3 {
debug variable => _8; // in scope 3 at $DIR/inline-closure-borrows-arg.rs:13:13: 13:21
}
bb0: { bb0: {
StorageLive(_3); // scope 0 at $DIR/inline-closure-borrows-arg.rs:12:9: 12:10 StorageLive(_3); // scope 0 at $DIR/inline-closure-borrows-arg.rs:12:9: 12:10
@ -34,16 +34,16 @@ fn foo(_1: T, _2: &i32) -> i32 {
_7 = &(*_2); // scope 1 at $DIR/inline-closure-borrows-arg.rs:16:10: 16:11 _7 = &(*_2); // scope 1 at $DIR/inline-closure-borrows-arg.rs:16:10: 16:11
(_5.0: &i32) = move _6; // scope 1 at $DIR/inline-closure-borrows-arg.rs:16:5: 16:12 (_5.0: &i32) = move _6; // scope 1 at $DIR/inline-closure-borrows-arg.rs:16:5: 16:12
(_5.1: &i32) = move _7; // scope 1 at $DIR/inline-closure-borrows-arg.rs:16:5: 16:12 (_5.1: &i32) = move _7; // scope 1 at $DIR/inline-closure-borrows-arg.rs:16:5: 16:12
StorageLive(_8); // scope 1 at $DIR/inline-closure-borrows-arg.rs:16:5: 16:12
_8 = move (_5.0: &i32); // scope 1 at $DIR/inline-closure-borrows-arg.rs:16:5: 16:12
StorageLive(_9); // scope 1 at $DIR/inline-closure-borrows-arg.rs:16:5: 16:12 StorageLive(_9); // scope 1 at $DIR/inline-closure-borrows-arg.rs:16:5: 16:12
_9 = move (_5.0: &i32); // scope 1 at $DIR/inline-closure-borrows-arg.rs:16:5: 16:12 _9 = move (_5.1: &i32); // scope 1 at $DIR/inline-closure-borrows-arg.rs:16:5: 16:12
StorageLive(_10); // scope 1 at $DIR/inline-closure-borrows-arg.rs:16:5: 16:12 StorageLive(_10); // scope 2 at $DIR/inline-closure-borrows-arg.rs:13:13: 13:21
_10 = move (_5.1: &i32); // scope 1 at $DIR/inline-closure-borrows-arg.rs:16:5: 16:12 _10 = _8; // scope 2 at $DIR/inline-closure-borrows-arg.rs:13:24: 13:27
StorageLive(_8); // scope 2 at $DIR/inline-closure-borrows-arg.rs:13:13: 13:21 _0 = (*_8); // scope 3 at $DIR/inline-closure-borrows-arg.rs:14:9: 14:18
_8 = _9; // scope 2 at $DIR/inline-closure-borrows-arg.rs:13:24: 13:27 StorageDead(_10); // scope 2 at $DIR/inline-closure-borrows-arg.rs:15:5: 15:6
_0 = (*_9); // scope 3 at $DIR/inline-closure-borrows-arg.rs:14:9: 14:18
StorageDead(_8); // scope 2 at $DIR/inline-closure-borrows-arg.rs:15:5: 15:6
StorageDead(_10); // scope 1 at $DIR/inline-closure-borrows-arg.rs:16:5: 16:12
StorageDead(_9); // scope 1 at $DIR/inline-closure-borrows-arg.rs:16:5: 16:12 StorageDead(_9); // scope 1 at $DIR/inline-closure-borrows-arg.rs:16:5: 16:12
StorageDead(_8); // scope 1 at $DIR/inline-closure-borrows-arg.rs:16:5: 16:12
StorageDead(_7); // scope 1 at $DIR/inline-closure-borrows-arg.rs:16:11: 16:12 StorageDead(_7); // scope 1 at $DIR/inline-closure-borrows-arg.rs:16:11: 16:12
StorageDead(_6); // scope 1 at $DIR/inline-closure-borrows-arg.rs:16:11: 16:12 StorageDead(_6); // scope 1 at $DIR/inline-closure-borrows-arg.rs:16:11: 16:12
StorageDead(_5); // scope 1 at $DIR/inline-closure-borrows-arg.rs:16:11: 16:12 StorageDead(_5); // scope 1 at $DIR/inline-closure-borrows-arg.rs:16:11: 16:12

View file

@ -10,14 +10,14 @@ fn foo(_1: T, _2: i32) -> (i32, T) {
let mut _6: &[closure@foo<T>::{closure#0}]; // in scope 0 at $DIR/inline-closure-captures.rs:12:5: 12:6 let mut _6: &[closure@foo<T>::{closure#0}]; // in scope 0 at $DIR/inline-closure-captures.rs:12:5: 12:6
let mut _7: (i32,); // in scope 0 at $DIR/inline-closure-captures.rs:12:5: 12:9 let mut _7: (i32,); // in scope 0 at $DIR/inline-closure-captures.rs:12:5: 12:9
let mut _8: i32; // in scope 0 at $DIR/inline-closure-captures.rs:12:7: 12:8 let mut _8: i32; // in scope 0 at $DIR/inline-closure-captures.rs:12:7: 12:8
let mut _10: i32; // in scope 0 at $DIR/inline-closure-captures.rs:12:5: 12:9 let mut _9: i32; // in scope 0 at $DIR/inline-closure-captures.rs:12:5: 12:9
scope 1 { scope 1 {
debug x => _3; // in scope 1 at $DIR/inline-closure-captures.rs:11:9: 11:10 debug x => _3; // in scope 1 at $DIR/inline-closure-captures.rs:11:9: 11:10
scope 2 { scope 2 (inlined foo::<T>::{closure#0}) { // at $DIR/inline-closure-captures.rs:12:5: 12:9
debug _q => _10; // in scope 2 at $DIR/inline-closure-captures.rs:11:14: 11:16 debug _q => _9; // in scope 2 at $DIR/inline-closure-captures.rs:11:14: 11:16
debug q => (*((*_6).0: &i32)); // in scope 2 at $DIR/inline-closure-captures.rs:10:23: 10:24 debug q => (*((*_6).0: &i32)); // in scope 2 at $DIR/inline-closure-captures.rs:10:23: 10:24
debug t => (*((*_6).1: &T)); // in scope 2 at $DIR/inline-closure-captures.rs:10:17: 10:18 debug t => (*((*_6).1: &T)); // in scope 2 at $DIR/inline-closure-captures.rs:10:17: 10:18
let mut _9: T; // in scope 2 at $DIR/inline-closure-captures.rs:12:5: 12:9 let mut _10: T; // in scope 2 at $DIR/inline-closure-captures.rs:11:22: 11:23
} }
} }
@ -37,14 +37,14 @@ fn foo(_1: T, _2: i32) -> (i32, T) {
StorageLive(_8); // scope 1 at $DIR/inline-closure-captures.rs:12:7: 12:8 StorageLive(_8); // scope 1 at $DIR/inline-closure-captures.rs:12:7: 12:8
_8 = _2; // scope 1 at $DIR/inline-closure-captures.rs:12:7: 12:8 _8 = _2; // scope 1 at $DIR/inline-closure-captures.rs:12:7: 12:8
(_7.0: i32) = move _8; // scope 1 at $DIR/inline-closure-captures.rs:12:5: 12:9 (_7.0: i32) = move _8; // scope 1 at $DIR/inline-closure-captures.rs:12:5: 12:9
StorageLive(_10); // scope 1 at $DIR/inline-closure-captures.rs:12:5: 12:9 StorageLive(_9); // scope 1 at $DIR/inline-closure-captures.rs:12:5: 12:9
_10 = move (_7.0: i32); // scope 1 at $DIR/inline-closure-captures.rs:12:5: 12:9 _9 = move (_7.0: i32); // scope 1 at $DIR/inline-closure-captures.rs:12:5: 12:9
(_0.0: i32) = (*((*_6).0: &i32)); // scope 2 at $DIR/inline-closure-captures.rs:11:19: 11:20 (_0.0: i32) = (*((*_6).0: &i32)); // scope 2 at $DIR/inline-closure-captures.rs:11:19: 11:20
StorageLive(_9); // scope 2 at $DIR/inline-closure-captures.rs:11:22: 11:23 StorageLive(_10); // scope 2 at $DIR/inline-closure-captures.rs:11:22: 11:23
_9 = (*((*_6).1: &T)); // scope 2 at $DIR/inline-closure-captures.rs:11:22: 11:23 _10 = (*((*_6).1: &T)); // scope 2 at $DIR/inline-closure-captures.rs:11:22: 11:23
(_0.1: T) = move _9; // scope 2 at $DIR/inline-closure-captures.rs:11:18: 11:24 (_0.1: T) = move _10; // scope 2 at $DIR/inline-closure-captures.rs:11:18: 11:24
StorageDead(_9); // scope 2 at $DIR/inline-closure-captures.rs:11:23: 11:24 StorageDead(_10); // scope 2 at $DIR/inline-closure-captures.rs:11:23: 11:24
StorageDead(_10); // scope 1 at $DIR/inline-closure-captures.rs:12:5: 12:9 StorageDead(_9); // scope 1 at $DIR/inline-closure-captures.rs:12:5: 12:9
StorageDead(_8); // scope 1 at $DIR/inline-closure-captures.rs:12:8: 12:9 StorageDead(_8); // scope 1 at $DIR/inline-closure-captures.rs:12:8: 12:9
StorageDead(_7); // scope 1 at $DIR/inline-closure-captures.rs:12:8: 12:9 StorageDead(_7); // scope 1 at $DIR/inline-closure-captures.rs:12:8: 12:9
StorageDead(_6); // scope 1 at $DIR/inline-closure-captures.rs:12:8: 12:9 StorageDead(_6); // scope 1 at $DIR/inline-closure-captures.rs:12:8: 12:9

View file

@ -4,7 +4,7 @@
fn inlined_no_sanitize() -> () { fn inlined_no_sanitize() -> () {
let mut _0: (); // return place in scope 0 at $DIR/inline-compatibility.rs:24:37: 24:37 let mut _0: (); // return place in scope 0 at $DIR/inline-compatibility.rs:24:37: 24:37
let _1: (); // in scope 0 at $DIR/inline-compatibility.rs:25:5: 25:18 let _1: (); // in scope 0 at $DIR/inline-compatibility.rs:25:5: 25:18
+ scope 1 { + scope 1 (inlined no_sanitize) { // at $DIR/inline-compatibility.rs:25:5: 25:18
+ } + }
bb0: { bb0: {

View file

@ -4,7 +4,7 @@
fn inlined_target_feature() -> () { fn inlined_target_feature() -> () {
let mut _0: (); // return place in scope 0 at $DIR/inline-compatibility.rs:13:40: 13:40 let mut _0: (); // return place in scope 0 at $DIR/inline-compatibility.rs:13:40: 13:40
let _1: (); // in scope 0 at $DIR/inline-compatibility.rs:14:5: 14:21 let _1: (); // in scope 0 at $DIR/inline-compatibility.rs:14:5: 14:21
+ scope 1 { + scope 1 (inlined target_feature) { // at $DIR/inline-compatibility.rs:14:5: 14:21
+ } + }
bb0: { bb0: {

View file

@ -10,7 +10,7 @@
scope 1 { scope 1 {
debug _x => _1; // in scope 1 at $DIR/inline-into-box-place.rs:8:9: 8:11 debug _x => _1; // in scope 1 at $DIR/inline-into-box-place.rs:8:9: 8:11
} }
+ scope 2 { + scope 2 (inlined Vec::<u32>::new) { // at $DIR/inline-into-box-place.rs:8:33: 8:43
+ } + }
bb0: { bb0: {

View file

@ -10,7 +10,7 @@
scope 1 { scope 1 {
debug _x => _1; // in scope 1 at $DIR/inline-into-box-place.rs:8:9: 8:11 debug _x => _1; // in scope 1 at $DIR/inline-into-box-place.rs:8:9: 8:11
} }
+ scope 2 { + scope 2 (inlined Vec::<u32>::new) { // at $DIR/inline-into-box-place.rs:8:33: 8:43
+ } + }
bb0: { bb0: {

View file

@ -14,11 +14,11 @@ fn bar() -> bool {
debug f => _1; // in scope 1 at $DIR/inline-retag.rs:11:9: 11:10 debug f => _1; // in scope 1 at $DIR/inline-retag.rs:11:9: 11:10
let mut _9: &i32; // in scope 1 at $DIR/inline-retag.rs:12:11: 12:14 let mut _9: &i32; // in scope 1 at $DIR/inline-retag.rs:12:11: 12:14
let mut _10: &i32; // in scope 1 at $DIR/inline-retag.rs:12:7: 12:9 let mut _10: &i32; // in scope 1 at $DIR/inline-retag.rs:12:7: 12:9
scope 2 { scope 2 (inlined foo) { // at $DIR/inline-retag.rs:12:5: 12:15
debug x => _3; // in scope 2 at $DIR/inline-retag.rs:16:8: 16:9 debug x => _3; // in scope 2 at $DIR/inline-retag.rs:16:8: 16:9
debug y => _6; // in scope 2 at $DIR/inline-retag.rs:16:17: 16:18 debug y => _6; // in scope 2 at $DIR/inline-retag.rs:16:17: 16:18
let mut _11: i32; // in scope 2 at $DIR/inline-retag.rs:12:5: 12:15 let mut _11: i32; // in scope 2 at $DIR/inline-retag.rs:17:5: 17:7
let mut _12: i32; // in scope 2 at $DIR/inline-retag.rs:12:5: 12:15 let mut _12: i32; // in scope 2 at $DIR/inline-retag.rs:17:11: 17:13
} }
} }

View file

@ -7,7 +7,7 @@
scope 1 { scope 1 {
debug x => _1; // in scope 1 at $DIR/inline-specialization.rs:5:9: 5:10 debug x => _1; // in scope 1 at $DIR/inline-specialization.rs:5:9: 5:10
} }
+ scope 2 { + scope 2 (inlined <Vec<()> as Foo>::bar) { // at $DIR/inline-specialization.rs:5:13: 5:38
+ } + }
bb0: { bb0: {

View file

@ -5,9 +5,9 @@ fn test2(_1: &dyn X) -> bool {
let mut _0: bool; // return place in scope 0 at $DIR/inline-trait-method_2.rs:4:24: 4:28 let mut _0: bool; // return place in scope 0 at $DIR/inline-trait-method_2.rs:4:24: 4:28
let mut _2: &dyn X; // in scope 0 at $DIR/inline-trait-method_2.rs:5:10: 5:11 let mut _2: &dyn X; // in scope 0 at $DIR/inline-trait-method_2.rs:5:10: 5:11
let mut _3: &dyn X; // in scope 0 at $DIR/inline-trait-method_2.rs:5:10: 5:11 let mut _3: &dyn X; // in scope 0 at $DIR/inline-trait-method_2.rs:5:10: 5:11
scope 1 { scope 1 (inlined test) { // at $DIR/inline-trait-method_2.rs:5:5: 5:12
debug x => _2; // in scope 1 at $DIR/inline-trait-method_2.rs:9:9: 9:10 debug x => _2; // in scope 1 at $DIR/inline-trait-method_2.rs:9:9: 9:10
let mut _4: &dyn X; // in scope 1 at $DIR/inline-trait-method_2.rs:5:5: 5:12 let mut _4: &dyn X; // in scope 1 at $DIR/inline-trait-method_2.rs:10:5: 10:6
} }
bb0: { bb0: {

View file

@ -0,0 +1,7 @@
// Tests that MIR inliner can handle `SourceScopeData` parenting correctly. (#76997)
// EMIT_MIR issue_76997_inline_scopes_parenting.main.Inline.after.mir
fn main() {
let f = |x| { let y = x; y };
f(())
}

View file

@ -6,9 +6,9 @@ fn a(_1: &mut [T]) -> &mut [T] {
let mut _2: &mut [T]; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:5: 3:15 let mut _2: &mut [T]; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:5: 3:15
let mut _3: &mut [T]; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:5: 3:15 let mut _3: &mut [T]; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:5: 3:15
let mut _4: &mut [T]; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:5: 3:6 let mut _4: &mut [T]; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:5: 3:6
scope 1 { scope 1 (inlined <[T] as AsMut<[T]>>::as_mut) { // at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:5: 3:15
debug self => _4; // in scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL debug self => _4; // in scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
let mut _5: &mut [T]; // in scope 1 at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:5: 3:15 let mut _5: &mut [T]; // in scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
} }
bb0: { bb0: {

View file

@ -6,10 +6,10 @@ fn b(_1: &mut Box<T>) -> &mut T {
let mut _2: &mut T; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:5: 8:15 let mut _2: &mut T; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:5: 8:15
let mut _3: &mut T; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:5: 8:15 let mut _3: &mut T; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:5: 8:15
let mut _4: &mut std::boxed::Box<T>; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:5: 8:6 let mut _4: &mut std::boxed::Box<T>; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:5: 8:6
scope 1 { scope 1 (inlined <Box<T> as AsMut<T>>::as_mut) { // at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:5: 8:15
debug self => _4; // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL debug self => _4; // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
let mut _5: &mut T; // in scope 1 at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:5: 8:15 let mut _5: &mut T; // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
let mut _6: &mut T; // in scope 1 at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:5: 8:15 let mut _6: &mut T; // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
} }
bb0: { bb0: {

View file

@ -5,7 +5,7 @@ fn c(_1: &[T]) -> &[T] {
let mut _0: &[T]; // return place in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:12:25: 12:29 let mut _0: &[T]; // return place in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:12:25: 12:29
let _2: &[T]; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:13:5: 13:15 let _2: &[T]; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:13:5: 13:15
let mut _3: &[T]; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:13:5: 13:6 let mut _3: &[T]; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:13:5: 13:6
scope 1 { scope 1 (inlined <[T] as AsRef<[T]>>::as_ref) { // at $DIR/issue-58867-inline-as-ref-as-mut.rs:13:5: 13:15
debug self => _3; // in scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL debug self => _3; // in scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
} }

View file

@ -5,7 +5,7 @@ fn d(_1: &Box<T>) -> &T {
let mut _0: &T; // return place in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:17:28: 17:30 let mut _0: &T; // return place in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:17:28: 17:30
let _2: &T; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:18:5: 18:15 let _2: &T; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:18:5: 18:15
let mut _3: &std::boxed::Box<T>; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:18:5: 18:6 let mut _3: &std::boxed::Box<T>; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:18:5: 18:6
scope 1 { scope 1 (inlined <Box<T> as AsRef<T>>::as_ref) { // at $DIR/issue-58867-inline-as-ref-as-mut.rs:18:5: 18:15
debug self => _3; // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL debug self => _3; // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
} }

View file

@ -0,0 +1,41 @@
// MIR for `main` after Inline
fn main() -> () {
let mut _0: (); // return place in scope 0 at $DIR/issue-76997-inline-scopes-parenting.rs:4:11: 4:11
let _1: [closure@$DIR/issue-76997-inline-scopes-parenting.rs:5:13: 5:33]; // in scope 0 at $DIR/issue-76997-inline-scopes-parenting.rs:5:9: 5:10
let mut _2: &[closure@$DIR/issue-76997-inline-scopes-parenting.rs:5:13: 5:33]; // in scope 0 at $DIR/issue-76997-inline-scopes-parenting.rs:6:5: 6:6
let mut _3: ((),); // in scope 0 at $DIR/issue-76997-inline-scopes-parenting.rs:6:5: 6:10
let mut _4: (); // in scope 0 at $DIR/issue-76997-inline-scopes-parenting.rs:6:7: 6:9
let mut _5: (); // in scope 0 at $DIR/issue-76997-inline-scopes-parenting.rs:6:5: 6:10
scope 1 {
debug f => _1; // in scope 1 at $DIR/issue-76997-inline-scopes-parenting.rs:5:9: 5:10
scope 2 (inlined main::{closure#0}) { // at $DIR/issue-76997-inline-scopes-parenting.rs:6:5: 6:10
debug x => _5; // in scope 2 at $DIR/issue-76997-inline-scopes-parenting.rs:5:14: 5:15
let _6: (); // in scope 2 at $DIR/issue-76997-inline-scopes-parenting.rs:5:23: 5:24
scope 3 {
debug y => _6; // in scope 3 at $DIR/issue-76997-inline-scopes-parenting.rs:5:23: 5:24
}
}
}
bb0: {
StorageLive(_1); // scope 0 at $DIR/issue-76997-inline-scopes-parenting.rs:5:9: 5:10
StorageLive(_2); // scope 1 at $DIR/issue-76997-inline-scopes-parenting.rs:6:5: 6:6
_2 = &_1; // scope 1 at $DIR/issue-76997-inline-scopes-parenting.rs:6:5: 6:6
StorageLive(_3); // scope 1 at $DIR/issue-76997-inline-scopes-parenting.rs:6:5: 6:10
StorageLive(_4); // scope 1 at $DIR/issue-76997-inline-scopes-parenting.rs:6:7: 6:9
(_3.0: ()) = move _4; // scope 1 at $DIR/issue-76997-inline-scopes-parenting.rs:6:5: 6:10
StorageLive(_5); // scope 1 at $DIR/issue-76997-inline-scopes-parenting.rs:6:5: 6:10
_5 = move (_3.0: ()); // scope 1 at $DIR/issue-76997-inline-scopes-parenting.rs:6:5: 6:10
StorageLive(_6); // scope 2 at $DIR/issue-76997-inline-scopes-parenting.rs:5:23: 5:24
_6 = const (); // scope 2 at $DIR/issue-76997-inline-scopes-parenting.rs:5:27: 5:28
_0 = const (); // scope 3 at $DIR/issue-76997-inline-scopes-parenting.rs:5:30: 5:31
StorageDead(_6); // scope 2 at $DIR/issue-76997-inline-scopes-parenting.rs:5:32: 5:33
StorageDead(_5); // scope 1 at $DIR/issue-76997-inline-scopes-parenting.rs:6:5: 6:10
StorageDead(_4); // scope 1 at $DIR/issue-76997-inline-scopes-parenting.rs:6:9: 6:10
StorageDead(_3); // scope 1 at $DIR/issue-76997-inline-scopes-parenting.rs:6:9: 6:10
StorageDead(_2); // scope 1 at $DIR/issue-76997-inline-scopes-parenting.rs:6:9: 6:10
StorageDead(_1); // scope 0 at $DIR/issue-76997-inline-scopes-parenting.rs:7:1: 7:2
return; // scope 0 at $DIR/issue-76997-inline-scopes-parenting.rs:7:2: 7:2
}
}

View file

@ -35,27 +35,31 @@
scope 5 { scope 5 {
debug arg0 => _25; // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL debug arg0 => _25; // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
debug arg1 => _28; // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL debug arg1 => _28; // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
scope 6 { scope 6 (inlined ArgumentV1::new::<&i32>) { // at $SRC_DIR/std/src/macros.rs:LL:COL
debug x => _25; // in scope 6 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL debug x => _25; // in scope 6 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
debug f => _24; // in scope 6 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL debug f => _24; // in scope 6 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
let mut _23: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 6 at $SRC_DIR/std/src/macros.rs:LL:COL let mut _23: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 6 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
let mut _24: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 6 at $SRC_DIR/std/src/macros.rs:LL:COL let mut _24: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 6 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
let mut _25: &&i32; // in scope 6 at $SRC_DIR/std/src/macros.rs:LL:COL let mut _25: &&i32; // in scope 6 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
scope 7 {
}
} }
scope 8 { scope 8 (inlined ArgumentV1::new::<&i32>) { // at $SRC_DIR/std/src/macros.rs:LL:COL
debug x => _28; // in scope 8 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL debug x => _28; // in scope 8 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
debug f => _27; // in scope 8 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL debug f => _27; // in scope 8 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
let mut _26: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 8 at $SRC_DIR/std/src/macros.rs:LL:COL let mut _26: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 8 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
let mut _27: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 8 at $SRC_DIR/std/src/macros.rs:LL:COL let mut _27: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 8 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
let mut _28: &&i32; // in scope 8 at $SRC_DIR/std/src/macros.rs:LL:COL let mut _28: &&i32; // in scope 8 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
scope 9 {
}
} }
} }
scope 10 { scope 10 (inlined Arguments::new_v1) { // at $SRC_DIR/std/src/macros.rs:LL:COL
debug pieces => _29; // in scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL debug pieces => _29; // in scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
debug args => _31; // in scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL debug args => _31; // in scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
let mut _29: &[&str]; // in scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL let mut _29: &[&str]; // in scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
let mut _30: std::option::Option<&[std::fmt::rt::v1::Argument]>; // in scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL let mut _30: std::option::Option<&[std::fmt::rt::v1::Argument]>; // in scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
let mut _31: &[std::fmt::ArgumentV1]; // in scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL let mut _31: &[std::fmt::ArgumentV1]; // in scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
} }
} }
} }
@ -63,10 +67,6 @@
scope 2 { scope 2 {
debug v => _3; // in scope 2 at $DIR/issue-73223.rs:3:14: 3:15 debug v => _3; // in scope 2 at $DIR/issue-73223.rs:3:14: 3:15
} }
scope 7 {
}
scope 9 {
}
bb0: { bb0: {
StorageLive(_1); // scope 0 at $DIR/issue-73223.rs:2:9: 2:14 StorageLive(_1); // scope 0 at $DIR/issue-73223.rs:2:9: 2:14

View file

@ -35,27 +35,31 @@
scope 5 { scope 5 {
debug arg0 => _25; // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL debug arg0 => _25; // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
debug arg1 => _28; // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL debug arg1 => _28; // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
scope 6 { scope 6 (inlined ArgumentV1::new::<&i32>) { // at $SRC_DIR/std/src/macros.rs:LL:COL
debug x => _25; // in scope 6 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL debug x => _25; // in scope 6 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
debug f => _24; // in scope 6 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL debug f => _24; // in scope 6 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
let mut _23: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 6 at $SRC_DIR/std/src/macros.rs:LL:COL let mut _23: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 6 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
let mut _24: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 6 at $SRC_DIR/std/src/macros.rs:LL:COL let mut _24: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 6 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
let mut _25: &&i32; // in scope 6 at $SRC_DIR/std/src/macros.rs:LL:COL let mut _25: &&i32; // in scope 6 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
scope 7 {
}
} }
scope 8 { scope 8 (inlined ArgumentV1::new::<&i32>) { // at $SRC_DIR/std/src/macros.rs:LL:COL
debug x => _28; // in scope 8 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL debug x => _28; // in scope 8 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
debug f => _27; // in scope 8 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL debug f => _27; // in scope 8 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
let mut _26: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 8 at $SRC_DIR/std/src/macros.rs:LL:COL let mut _26: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 8 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
let mut _27: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 8 at $SRC_DIR/std/src/macros.rs:LL:COL let mut _27: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 8 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
let mut _28: &&i32; // in scope 8 at $SRC_DIR/std/src/macros.rs:LL:COL let mut _28: &&i32; // in scope 8 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
scope 9 {
}
} }
} }
scope 10 { scope 10 (inlined Arguments::new_v1) { // at $SRC_DIR/std/src/macros.rs:LL:COL
debug pieces => _29; // in scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL debug pieces => _29; // in scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
debug args => _31; // in scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL debug args => _31; // in scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
let mut _29: &[&str]; // in scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL let mut _29: &[&str]; // in scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
let mut _30: std::option::Option<&[std::fmt::rt::v1::Argument]>; // in scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL let mut _30: std::option::Option<&[std::fmt::rt::v1::Argument]>; // in scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
let mut _31: &[std::fmt::ArgumentV1]; // in scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL let mut _31: &[std::fmt::ArgumentV1]; // in scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
} }
} }
} }
@ -63,10 +67,6 @@
scope 2 { scope 2 {
debug v => _3; // in scope 2 at $DIR/issue-73223.rs:3:14: 3:15 debug v => _3; // in scope 2 at $DIR/issue-73223.rs:3:14: 3:15
} }
scope 7 {
}
scope 9 {
}
bb0: { bb0: {
StorageLive(_1); // scope 0 at $DIR/issue-73223.rs:2:9: 2:14 StorageLive(_1); // scope 0 at $DIR/issue-73223.rs:2:9: 2:14

View file

@ -58,29 +58,33 @@
scope 5 { scope 5 {
debug arg0 => _36; // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL debug arg0 => _36; // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
debug arg1 => _37; // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL debug arg1 => _37; // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
scope 6 { scope 6 (inlined ArgumentV1::new::<&i32>) { // at $SRC_DIR/std/src/macros.rs:LL:COL
debug x => _39; // in scope 6 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL debug x => _39; // in scope 6 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
debug f => _40; // in scope 6 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL debug f => _40; // in scope 6 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
let mut _46: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 6 at $SRC_DIR/std/src/macros.rs:LL:COL let mut _46: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 6 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
let mut _47: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 6 at $SRC_DIR/std/src/macros.rs:LL:COL let mut _47: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 6 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
let mut _48: &core::fmt::Opaque; // in scope 6 at $SRC_DIR/std/src/macros.rs:LL:COL let mut _48: &core::fmt::Opaque; // in scope 6 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
let mut _49: &&i32; // in scope 6 at $SRC_DIR/std/src/macros.rs:LL:COL let mut _49: &&i32; // in scope 6 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
scope 7 {
}
} }
scope 8 { scope 8 (inlined ArgumentV1::new::<&i32>) { // at $SRC_DIR/std/src/macros.rs:LL:COL
debug x => _42; // in scope 8 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL debug x => _42; // in scope 8 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
debug f => _43; // in scope 8 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL debug f => _43; // in scope 8 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
let mut _50: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 8 at $SRC_DIR/std/src/macros.rs:LL:COL let mut _50: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 8 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
let mut _51: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 8 at $SRC_DIR/std/src/macros.rs:LL:COL let mut _51: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 8 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
let mut _52: &core::fmt::Opaque; // in scope 8 at $SRC_DIR/std/src/macros.rs:LL:COL let mut _52: &core::fmt::Opaque; // in scope 8 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
let mut _53: &&i32; // in scope 8 at $SRC_DIR/std/src/macros.rs:LL:COL let mut _53: &&i32; // in scope 8 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
scope 9 {
}
} }
} }
scope 10 { scope 10 (inlined Arguments::new_v1) { // at $SRC_DIR/std/src/macros.rs:LL:COL
debug pieces => _23; // in scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL debug pieces => _23; // in scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
debug args => _27; // in scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL debug args => _27; // in scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
let mut _54: &[&str]; // in scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL let mut _54: &[&str]; // in scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
let mut _55: std::option::Option<&[std::fmt::rt::v1::Argument]>; // in scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL let mut _55: std::option::Option<&[std::fmt::rt::v1::Argument]>; // in scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
let mut _56: &[std::fmt::ArgumentV1]; // in scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL let mut _56: &[std::fmt::ArgumentV1]; // in scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
} }
} }
} }
@ -88,10 +92,6 @@
scope 2 { scope 2 {
debug v => _4; // in scope 2 at $DIR/issue-73223.rs:3:14: 3:15 debug v => _4; // in scope 2 at $DIR/issue-73223.rs:3:14: 3:15
} }
scope 7 {
}
scope 9 {
}
bb0: { bb0: {
StorageLive(_1); // scope 0 at $DIR/issue-73223.rs:2:9: 2:14 StorageLive(_1); // scope 0 at $DIR/issue-73223.rs:2:9: 2:14

View file

@ -58,29 +58,33 @@
scope 5 { scope 5 {
debug arg0 => _36; // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL debug arg0 => _36; // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
debug arg1 => _37; // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL debug arg1 => _37; // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
scope 6 { scope 6 (inlined ArgumentV1::new::<&i32>) { // at $SRC_DIR/std/src/macros.rs:LL:COL
debug x => _39; // in scope 6 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL debug x => _39; // in scope 6 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
debug f => _40; // in scope 6 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL debug f => _40; // in scope 6 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
let mut _46: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 6 at $SRC_DIR/std/src/macros.rs:LL:COL let mut _46: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 6 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
let mut _47: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 6 at $SRC_DIR/std/src/macros.rs:LL:COL let mut _47: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 6 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
let mut _48: &core::fmt::Opaque; // in scope 6 at $SRC_DIR/std/src/macros.rs:LL:COL let mut _48: &core::fmt::Opaque; // in scope 6 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
let mut _49: &&i32; // in scope 6 at $SRC_DIR/std/src/macros.rs:LL:COL let mut _49: &&i32; // in scope 6 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
scope 7 {
}
} }
scope 8 { scope 8 (inlined ArgumentV1::new::<&i32>) { // at $SRC_DIR/std/src/macros.rs:LL:COL
debug x => _42; // in scope 8 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL debug x => _42; // in scope 8 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
debug f => _43; // in scope 8 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL debug f => _43; // in scope 8 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
let mut _50: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 8 at $SRC_DIR/std/src/macros.rs:LL:COL let mut _50: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 8 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
let mut _51: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 8 at $SRC_DIR/std/src/macros.rs:LL:COL let mut _51: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 8 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
let mut _52: &core::fmt::Opaque; // in scope 8 at $SRC_DIR/std/src/macros.rs:LL:COL let mut _52: &core::fmt::Opaque; // in scope 8 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
let mut _53: &&i32; // in scope 8 at $SRC_DIR/std/src/macros.rs:LL:COL let mut _53: &&i32; // in scope 8 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
scope 9 {
}
} }
} }
scope 10 { scope 10 (inlined Arguments::new_v1) { // at $SRC_DIR/std/src/macros.rs:LL:COL
debug pieces => _23; // in scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL debug pieces => _23; // in scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
debug args => _27; // in scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL debug args => _27; // in scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
let mut _54: &[&str]; // in scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL let mut _54: &[&str]; // in scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
let mut _55: std::option::Option<&[std::fmt::rt::v1::Argument]>; // in scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL let mut _55: std::option::Option<&[std::fmt::rt::v1::Argument]>; // in scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
let mut _56: &[std::fmt::ArgumentV1]; // in scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL let mut _56: &[std::fmt::ArgumentV1]; // in scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
} }
} }
} }
@ -88,10 +92,6 @@
scope 2 { scope 2 {
debug v => _4; // in scope 2 at $DIR/issue-73223.rs:3:14: 3:15 debug v => _4; // in scope 2 at $DIR/issue-73223.rs:3:14: 3:15
} }
scope 7 {
}
scope 9 {
}
bb0: { bb0: {
StorageLive(_1); // scope 0 at $DIR/issue-73223.rs:2:9: 2:14 StorageLive(_1); // scope 0 at $DIR/issue-73223.rs:2:9: 2:14

View file

@ -6,7 +6,7 @@
let mut _0: (); // return place in scope 0 at $DIR/remove_unneeded_drops.rs:20:32: 20:32 let mut _0: (); // return place in scope 0 at $DIR/remove_unneeded_drops.rs:20:32: 20:32
let _2: (); // in scope 0 at $DIR/remove_unneeded_drops.rs:21:5: 21:12 let _2: (); // in scope 0 at $DIR/remove_unneeded_drops.rs:21:5: 21:12
let mut _3: T; // in scope 0 at $DIR/remove_unneeded_drops.rs:21:10: 21:11 let mut _3: T; // in scope 0 at $DIR/remove_unneeded_drops.rs:21:10: 21:11
scope 1 { scope 1 (inlined std::mem::drop::<T>) { // at $DIR/remove_unneeded_drops.rs:21:5: 21:12
debug _x => _3; // in scope 1 at $SRC_DIR/core/src/mem/mod.rs:LL:COL debug _x => _3; // in scope 1 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
} }

View file

@ -6,7 +6,7 @@
let mut _0: (); // return place in scope 0 at $DIR/remove_unneeded_drops.rs:8:27: 8:27 let mut _0: (); // return place in scope 0 at $DIR/remove_unneeded_drops.rs:8:27: 8:27
let _2: (); // in scope 0 at $DIR/remove_unneeded_drops.rs:9:5: 9:12 let _2: (); // in scope 0 at $DIR/remove_unneeded_drops.rs:9:5: 9:12
let mut _3: std::vec::Vec<bool>; // in scope 0 at $DIR/remove_unneeded_drops.rs:9:10: 9:11 let mut _3: std::vec::Vec<bool>; // in scope 0 at $DIR/remove_unneeded_drops.rs:9:10: 9:11
scope 1 { scope 1 (inlined std::mem::drop::<Vec<bool>>) { // at $DIR/remove_unneeded_drops.rs:9:5: 9:12
debug _x => _3; // in scope 1 at $SRC_DIR/core/src/mem/mod.rs:LL:COL debug _x => _3; // in scope 1 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
} }

View file

@ -6,7 +6,7 @@
let mut _0: (); // return place in scope 0 at $DIR/remove_unneeded_drops.rs:3:17: 3:17 let mut _0: (); // return place in scope 0 at $DIR/remove_unneeded_drops.rs:3:17: 3:17
let _2: (); // in scope 0 at $DIR/remove_unneeded_drops.rs:4:5: 4:12 let _2: (); // in scope 0 at $DIR/remove_unneeded_drops.rs:4:5: 4:12
let mut _3: bool; // in scope 0 at $DIR/remove_unneeded_drops.rs:4:10: 4:11 let mut _3: bool; // in scope 0 at $DIR/remove_unneeded_drops.rs:4:10: 4:11
scope 1 { scope 1 (inlined std::mem::drop::<bool>) { // at $DIR/remove_unneeded_drops.rs:4:5: 4:12
debug _x => _3; // in scope 1 at $SRC_DIR/core/src/mem/mod.rs:LL:COL debug _x => _3; // in scope 1 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
} }

View file

@ -6,7 +6,7 @@
let mut _0: (); // return place in scope 0 at $DIR/remove_unneeded_drops.rs:13:36: 13:36 let mut _0: (); // return place in scope 0 at $DIR/remove_unneeded_drops.rs:13:36: 13:36
let _2: (); // in scope 0 at $DIR/remove_unneeded_drops.rs:14:5: 14:12 let _2: (); // in scope 0 at $DIR/remove_unneeded_drops.rs:14:5: 14:12
let mut _3: T; // in scope 0 at $DIR/remove_unneeded_drops.rs:14:10: 14:11 let mut _3: T; // in scope 0 at $DIR/remove_unneeded_drops.rs:14:10: 14:11
scope 1 { scope 1 (inlined std::mem::drop::<T>) { // at $DIR/remove_unneeded_drops.rs:14:5: 14:12
debug _x => _3; // in scope 1 at $SRC_DIR/core/src/mem/mod.rs:LL:COL debug _x => _3; // in scope 1 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
} }

View file

@ -22,14 +22,14 @@
- debug err => _6; // in scope 2 at $DIR/simplify-arm.rs:24:14: 24:15 - debug err => _6; // in scope 2 at $DIR/simplify-arm.rs:24:14: 24:15
+ debug err => ((_0 as Err).0: i32); // in scope 2 at $DIR/simplify-arm.rs:24:14: 24:15 + debug err => ((_0 as Err).0: i32); // in scope 2 at $DIR/simplify-arm.rs:24:14: 24:15
scope 3 { scope 3 {
scope 7 { scope 7 (inlined <i32 as From<i32>>::from) { // at $DIR/simplify-arm.rs:24:14: 24:15
- debug t => _9; // in scope 7 at $SRC_DIR/core/src/convert/mod.rs:LL:COL - debug t => _9; // in scope 7 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
+ debug t => ((_0 as Err).0: i32); // in scope 7 at $SRC_DIR/core/src/convert/mod.rs:LL:COL + debug t => ((_0 as Err).0: i32); // in scope 7 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
} }
scope 8 { scope 8 (inlined <std::result::Result<u8, i32> as Try>::from_error) { // at $DIR/simplify-arm.rs:24:13: 24:15
- debug v => _8; // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL - debug v => _8; // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
+ debug v => ((_0 as Err).0: i32); // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL + debug v => ((_0 as Err).0: i32); // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
let mut _12: i32; // in scope 8 at $DIR/simplify-arm.rs:24:13: 24:15 let mut _12: i32; // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
} }
} }
} }
@ -39,7 +39,7 @@
scope 5 { scope 5 {
} }
} }
scope 6 { scope 6 (inlined <std::result::Result<u8, i32> as Try>::into_result) { // at $DIR/simplify-arm.rs:24:13: 24:15
debug self => _4; // in scope 6 at $SRC_DIR/core/src/result.rs:LL:COL debug self => _4; // in scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
} }

View file

@ -20,12 +20,12 @@
scope 2 { scope 2 {
debug err => ((_0 as Err).0: i32); // in scope 2 at $DIR/simplify-arm.rs:24:14: 24:15 debug err => ((_0 as Err).0: i32); // in scope 2 at $DIR/simplify-arm.rs:24:14: 24:15
scope 3 { scope 3 {
scope 7 { scope 7 (inlined <i32 as From<i32>>::from) { // at $DIR/simplify-arm.rs:24:14: 24:15
debug t => ((_0 as Err).0: i32); // in scope 7 at $SRC_DIR/core/src/convert/mod.rs:LL:COL debug t => ((_0 as Err).0: i32); // in scope 7 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
} }
scope 8 { scope 8 (inlined <std::result::Result<u8, i32> as Try>::from_error) { // at $DIR/simplify-arm.rs:24:13: 24:15
debug v => ((_0 as Err).0: i32); // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL debug v => ((_0 as Err).0: i32); // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
let mut _12: i32; // in scope 8 at $DIR/simplify-arm.rs:24:13: 24:15 let mut _12: i32; // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
} }
} }
} }
@ -34,7 +34,7 @@
scope 5 { scope 5 {
} }
} }
scope 6 { scope 6 (inlined <std::result::Result<u8, i32> as Try>::into_result) { // at $DIR/simplify-arm.rs:24:13: 24:15
debug self => _4; // in scope 6 at $SRC_DIR/core/src/result.rs:LL:COL debug self => _4; // in scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
} }

View file

@ -20,12 +20,12 @@
scope 2 { scope 2 {
debug err => ((_0 as Err).0: i32); // in scope 2 at $DIR/simplify_try.rs:8:14: 8:15 debug err => ((_0 as Err).0: i32); // in scope 2 at $DIR/simplify_try.rs:8:14: 8:15
scope 3 { scope 3 {
scope 7 { scope 7 (inlined <i32 as From<i32>>::from) { // at $DIR/simplify_try.rs:8:14: 8:15
debug t => ((_0 as Err).0: i32); // in scope 7 at $SRC_DIR/core/src/convert/mod.rs:LL:COL debug t => ((_0 as Err).0: i32); // in scope 7 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
} }
scope 8 { scope 8 (inlined <std::result::Result<u32, i32> as Try>::from_error) { // at $DIR/simplify_try.rs:8:13: 8:15
debug v => ((_0 as Err).0: i32); // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL debug v => ((_0 as Err).0: i32); // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
let mut _12: i32; // in scope 8 at $DIR/simplify_try.rs:8:13: 8:15 let mut _12: i32; // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
} }
} }
} }
@ -34,7 +34,7 @@
scope 5 { scope 5 {
} }
} }
scope 6 { scope 6 (inlined <std::result::Result<u32, i32> as Try>::into_result) { // at $DIR/simplify_try.rs:8:13: 8:15
- debug self => _4; // in scope 6 at $SRC_DIR/core/src/result.rs:LL:COL - debug self => _4; // in scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
+ debug self => _0; // in scope 6 at $SRC_DIR/core/src/result.rs:LL:COL + debug self => _0; // in scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
} }

View file

@ -22,14 +22,14 @@
- debug err => _6; // in scope 2 at $DIR/simplify_try.rs:8:14: 8:15 - debug err => _6; // in scope 2 at $DIR/simplify_try.rs:8:14: 8:15
+ debug err => ((_0 as Err).0: i32); // in scope 2 at $DIR/simplify_try.rs:8:14: 8:15 + debug err => ((_0 as Err).0: i32); // in scope 2 at $DIR/simplify_try.rs:8:14: 8:15
scope 3 { scope 3 {
scope 7 { scope 7 (inlined <i32 as From<i32>>::from) { // at $DIR/simplify_try.rs:8:14: 8:15
- debug t => _9; // in scope 7 at $SRC_DIR/core/src/convert/mod.rs:LL:COL - debug t => _9; // in scope 7 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
+ debug t => ((_0 as Err).0: i32); // in scope 7 at $SRC_DIR/core/src/convert/mod.rs:LL:COL + debug t => ((_0 as Err).0: i32); // in scope 7 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
} }
scope 8 { scope 8 (inlined <std::result::Result<u32, i32> as Try>::from_error) { // at $DIR/simplify_try.rs:8:13: 8:15
- debug v => _8; // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL - debug v => _8; // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
+ debug v => ((_0 as Err).0: i32); // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL + debug v => ((_0 as Err).0: i32); // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
let mut _12: i32; // in scope 8 at $DIR/simplify_try.rs:8:13: 8:15 let mut _12: i32; // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
} }
} }
} }
@ -39,7 +39,7 @@
scope 5 { scope 5 {
} }
} }
scope 6 { scope 6 (inlined <std::result::Result<u32, i32> as Try>::into_result) { // at $DIR/simplify_try.rs:8:13: 8:15
debug self => _4; // in scope 6 at $SRC_DIR/core/src/result.rs:LL:COL debug self => _4; // in scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
} }

View file

@ -19,12 +19,12 @@ fn try_identity(_1: std::result::Result<u32, i32>) -> std::result::Result<u32, i
scope 2 { scope 2 {
debug err => ((_0 as Err).0: i32); // in scope 2 at $DIR/simplify_try.rs:8:14: 8:15 debug err => ((_0 as Err).0: i32); // in scope 2 at $DIR/simplify_try.rs:8:14: 8:15
scope 3 { scope 3 {
scope 7 { scope 7 (inlined <i32 as From<i32>>::from) { // at $DIR/simplify_try.rs:8:14: 8:15
debug t => ((_0 as Err).0: i32); // in scope 7 at $SRC_DIR/core/src/convert/mod.rs:LL:COL debug t => ((_0 as Err).0: i32); // in scope 7 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
} }
scope 8 { scope 8 (inlined <std::result::Result<u32, i32> as Try>::from_error) { // at $DIR/simplify_try.rs:8:13: 8:15
debug v => ((_0 as Err).0: i32); // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL debug v => ((_0 as Err).0: i32); // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
let mut _12: i32; // in scope 8 at $DIR/simplify_try.rs:8:13: 8:15 let mut _12: i32; // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
} }
} }
} }
@ -33,7 +33,7 @@ fn try_identity(_1: std::result::Result<u32, i32>) -> std::result::Result<u32, i
scope 5 { scope 5 {
} }
} }
scope 6 { scope 6 (inlined <std::result::Result<u32, i32> as Try>::into_result) { // at $DIR/simplify_try.rs:8:13: 8:15
debug self => _4; // in scope 6 at $SRC_DIR/core/src/result.rs:LL:COL debug self => _4; // in scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
} }

View file

@ -9,10 +9,10 @@ fn try_identity(_1: std::result::Result<u32, i32>) -> std::result::Result<u32, i
scope 2 { scope 2 {
debug err => ((_0 as Err).0: i32); // in scope 2 at $DIR/simplify_try.rs:8:14: 8:15 debug err => ((_0 as Err).0: i32); // in scope 2 at $DIR/simplify_try.rs:8:14: 8:15
scope 3 { scope 3 {
scope 7 { scope 7 (inlined <i32 as From<i32>>::from) { // at $DIR/simplify_try.rs:8:14: 8:15
debug t => ((_0 as Err).0: i32); // in scope 7 at $SRC_DIR/core/src/convert/mod.rs:LL:COL debug t => ((_0 as Err).0: i32); // in scope 7 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
} }
scope 8 { scope 8 (inlined <std::result::Result<u32, i32> as Try>::from_error) { // at $DIR/simplify_try.rs:8:13: 8:15
debug v => ((_0 as Err).0: i32); // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL debug v => ((_0 as Err).0: i32); // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
} }
} }
@ -22,7 +22,7 @@ fn try_identity(_1: std::result::Result<u32, i32>) -> std::result::Result<u32, i
scope 5 { scope 5 {
} }
} }
scope 6 { scope 6 (inlined <std::result::Result<u32, i32> as Try>::into_result) { // at $DIR/simplify_try.rs:8:13: 8:15
debug self => _0; // in scope 6 at $SRC_DIR/core/src/result.rs:LL:COL debug self => _0; // in scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
} }

View file

@ -1,4 +1,6 @@
// run-pass // run-pass
// revisions: default mir-opt
//[mir-opt] compile-flags: -Zmir-opt-level=3
#[inline(never)] #[inline(never)]
#[track_caller] #[track_caller]
@ -13,13 +15,13 @@ macro_rules! caller_location_from_macro {
fn main() { fn main() {
let loc = codegen_caller_loc(); let loc = codegen_caller_loc();
assert_eq!(loc.file(), file!()); assert_eq!(loc.file(), file!());
assert_eq!(loc.line(), 14); assert_eq!(loc.line(), 16);
assert_eq!(loc.column(), 15); assert_eq!(loc.column(), 15);
// `Location::caller()` in a macro should behave similarly to `file!` and `line!`, // `Location::caller()` in a macro should behave similarly to `file!` and `line!`,
// i.e. point to where the macro was invoked, instead of the macro itself. // i.e. point to where the macro was invoked, instead of the macro itself.
let loc2 = caller_location_from_macro!(); let loc2 = caller_location_from_macro!();
assert_eq!(loc2.file(), file!()); assert_eq!(loc2.file(), file!());
assert_eq!(loc2.line(), 21); assert_eq!(loc2.line(), 23);
assert_eq!(loc2.column(), 16); assert_eq!(loc2.column(), 16);
} }

View file

@ -1,4 +1,6 @@
// run-pass // run-pass
// revisions: default mir-opt
//[mir-opt] compile-flags: -Zmir-opt-level=3
#![feature(const_caller_location, const_fn)] #![feature(const_caller_location, const_fn)]
@ -24,18 +26,18 @@ const fn contained() -> &'static Location<'static> {
fn main() { fn main() {
assert_eq!(LOCATION.file(), file!()); assert_eq!(LOCATION.file(), file!());
assert_eq!(LOCATION.line(), 7); assert_eq!(LOCATION.line(), 9);
assert_eq!(LOCATION.column(), 29); assert_eq!(LOCATION.column(), 29);
assert_eq!(TRACKED.file(), file!()); assert_eq!(TRACKED.file(), file!());
assert_eq!(TRACKED.line(), 9); assert_eq!(TRACKED.line(), 11);
assert_eq!(TRACKED.column(), 28); assert_eq!(TRACKED.column(), 28);
assert_eq!(NESTED.file(), file!()); assert_eq!(NESTED.file(), file!());
assert_eq!(NESTED.line(), 17); assert_eq!(NESTED.line(), 19);
assert_eq!(NESTED.column(), 5); assert_eq!(NESTED.column(), 5);
assert_eq!(CONTAINED.file(), file!()); assert_eq!(CONTAINED.file(), file!());
assert_eq!(CONTAINED.line(), 22); assert_eq!(CONTAINED.line(), 24);
assert_eq!(CONTAINED.column(), 5); assert_eq!(CONTAINED.column(), 5);
} }

View file

@ -1,4 +1,6 @@
// run-pass // run-pass
// revisions: default mir-opt
//[mir-opt] compile-flags: -Zmir-opt-level=3
macro_rules! caller_location_from_macro { macro_rules! caller_location_from_macro {
() => (core::panic::Location::caller()); () => (core::panic::Location::caller());
@ -7,13 +9,13 @@ macro_rules! caller_location_from_macro {
fn main() { fn main() {
let loc = core::panic::Location::caller(); let loc = core::panic::Location::caller();
assert_eq!(loc.file(), file!()); assert_eq!(loc.file(), file!());
assert_eq!(loc.line(), 8); assert_eq!(loc.line(), 10);
assert_eq!(loc.column(), 15); assert_eq!(loc.column(), 15);
// `Location::caller()` in a macro should behave similarly to `file!` and `line!`, // `Location::caller()` in a macro should behave similarly to `file!` and `line!`,
// i.e. point to where the macro was invoked, instead of the macro itself. // i.e. point to where the macro was invoked, instead of the macro itself.
let loc2 = caller_location_from_macro!(); let loc2 = caller_location_from_macro!();
assert_eq!(loc2.file(), file!()); assert_eq!(loc2.file(), file!());
assert_eq!(loc2.line(), 15); assert_eq!(loc2.line(), 17);
assert_eq!(loc2.column(), 16); assert_eq!(loc2.column(), 16);
} }

View file

@ -1,4 +1,7 @@
// run-pass // run-pass
// revisions: default mir-opt
//[mir-opt] compile-flags: -Zmir-opt-level=3
#[track_caller] #[track_caller]
fn f() {} fn f() {}

View file

@ -1,5 +1,7 @@
// run-pass // run-pass
// ignore-wasm32-bare compiled with panic=abort by default // ignore-wasm32-bare compiled with panic=abort by default
// revisions: default mir-opt
//[mir-opt] compile-flags: -Zmir-opt-level=3
#![feature(option_expect_none, option_unwrap_none)] #![feature(option_expect_none, option_unwrap_none)]
#![allow(unconditional_panic)] #![allow(unconditional_panic)]

View file

@ -1,4 +1,6 @@
// run-pass // run-pass
// revisions: default mir-opt
//[mir-opt] compile-flags: -Zmir-opt-level=3
use std::panic::Location; use std::panic::Location;
@ -18,21 +20,21 @@ fn nested_tracked() -> &'static Location<'static> {
fn main() { fn main() {
let location = Location::caller(); let location = Location::caller();
assert_eq!(location.file(), file!()); assert_eq!(location.file(), file!());
assert_eq!(location.line(), 19); assert_eq!(location.line(), 21);
assert_eq!(location.column(), 20); assert_eq!(location.column(), 20);
let tracked = tracked(); let tracked = tracked();
assert_eq!(tracked.file(), file!()); assert_eq!(tracked.file(), file!());
assert_eq!(tracked.line(), 24); assert_eq!(tracked.line(), 26);
assert_eq!(tracked.column(), 19); assert_eq!(tracked.column(), 19);
let nested = nested_intrinsic(); let nested = nested_intrinsic();
assert_eq!(nested.file(), file!()); assert_eq!(nested.file(), file!());
assert_eq!(nested.line(), 11); assert_eq!(nested.line(), 13);
assert_eq!(nested.column(), 5); assert_eq!(nested.column(), 5);
let contained = nested_tracked(); let contained = nested_tracked();
assert_eq!(contained.file(), file!()); assert_eq!(contained.file(), file!());
assert_eq!(contained.line(), 15); assert_eq!(contained.line(), 17);
assert_eq!(contained.column(), 5); assert_eq!(contained.column(), 5);
} }

View file

@ -1,4 +1,6 @@
// run-pass // run-pass
// revisions: default mir-opt
//[mir-opt] compile-flags: -Zmir-opt-level=3
fn pass_to_ptr_call<T>(f: fn(T), x: T) { fn pass_to_ptr_call<T>(f: fn(T), x: T) {
f(x); f(x);

View file

@ -1,4 +1,6 @@
// run-pass // run-pass
// revisions: default mir-opt
//[mir-opt] compile-flags: -Zmir-opt-level=3
fn ptr_call(f: fn()) { fn ptr_call(f: fn()) {
f(); f();