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:
commit
0da6d42f29
68 changed files with 879 additions and 619 deletions
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
};
|
};
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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) }
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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> {
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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,
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
>;
|
>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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>,
|
||||||
|
|
|
@ -10,7 +10,6 @@ CloneTypeFoldableAndLiftImpls! {
|
||||||
FakeReadCause,
|
FakeReadCause,
|
||||||
RetagKind,
|
RetagKind,
|
||||||
SourceScope,
|
SourceScope,
|
||||||
SourceScopeData,
|
|
||||||
SourceScopeLocalData,
|
SourceScopeLocalData,
|
||||||
UserTypeAnnotationIndex,
|
UserTypeAnnotationIndex,
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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())?;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
17
src/test/codegen/inline-debuginfo.rs
Normal file
17
src/test/codegen/inline-debuginfo.rs
Normal 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)
|
||||||
|
}
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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: {
|
||||||
|
|
|
@ -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: {
|
||||||
|
|
|
@ -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: {
|
||||||
|
|
|
@ -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: {
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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: {
|
||||||
|
|
|
@ -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: {
|
||||||
|
|
|
@ -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(())
|
||||||
|
}
|
|
@ -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: {
|
||||||
|
|
|
@ -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: {
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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() {}
|
||||||
|
|
||||||
|
|
|
@ -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)]
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue