From f1d942b371278aaca8897050645ac5351735bbb7 Mon Sep 17 00:00:00 2001 From: Adam Perry Date: Sun, 27 Oct 2019 17:31:12 -0700 Subject: Add field to FunctionCx for passing caller location. --- src/librustc_codegen_ssa/mir/block.rs | 20 ++++++++++++-------- src/librustc_codegen_ssa/mir/mod.rs | 4 ++++ 2 files changed, 16 insertions(+), 8 deletions(-) (limited to 'src/librustc_codegen_ssa') diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs index 6dccf329c9f..4f47d84047d 100644 --- a/src/librustc_codegen_ssa/mir/block.rs +++ b/src/librustc_codegen_ssa/mir/block.rs @@ -1004,14 +1004,18 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bx: &mut Bx, span: Span, ) -> OperandRef<'tcx, Bx::Value> { - let topmost = span.ctxt().outer_expn().expansion_cause().unwrap_or(span); - let caller = bx.tcx().sess.source_map().lookup_char_pos(topmost.lo()); - let const_loc = bx.tcx().const_caller_location(( - Symbol::intern(&caller.file.name.to_string()), - caller.line as u32, - caller.col_display as u32 + 1, - )); - OperandRef::from_const(bx, const_loc) + if let Some(l) = self.caller_location { + bx.load_operand(l) + } else { + let topmost = span.ctxt().outer_expn().expansion_cause().unwrap_or(span); + let caller = bx.tcx().sess.source_map().lookup_char_pos(topmost.lo()); + let const_loc = bx.tcx().const_caller_location(( + Symbol::intern(&caller.file.name.to_string()), + caller.line as u32, + caller.col_display as u32 + 1, + )); + OperandRef::from_const(bx, const_loc) + } } fn get_personality_slot( diff --git a/src/librustc_codegen_ssa/mir/mod.rs b/src/librustc_codegen_ssa/mir/mod.rs index 3a157ca24a4..a6333ef23f5 100644 --- a/src/librustc_codegen_ssa/mir/mod.rs +++ b/src/librustc_codegen_ssa/mir/mod.rs @@ -77,6 +77,9 @@ pub struct FunctionCx<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> { /// All `VarDebuginfo` from the MIR body, partitioned by `Local`. /// This is `None` if no variable debuginfo/names are needed. per_local_var_debug_info: Option>>>, + + /// Caller location propagated if this function has `#[track_caller]`. + caller_location: Option>, } impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { @@ -172,6 +175,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( locals: IndexVec::new(), debug_context, per_local_var_debug_info: debuginfo::per_local_var_debug_info(cx.tcx(), mir_body), + caller_location: None, }; let memory_locals = analyze::non_ssa_locals(&fx); -- cgit 1.4.1-3-g733a5 From 207f5208273667c5c72397fdf99390e594a3cdf1 Mon Sep 17 00:00:00 2001 From: Adam Perry Date: Thu, 7 Nov 2019 06:04:14 -0800 Subject: Pass a location to #[track_caller] functions in codegen_call_terminator. --- src/librustc_codegen_ssa/mir/block.rs | 12 ++++++++++++ src/librustc_codegen_ssa/mir/mod.rs | 21 +++++++++++++++++---- 2 files changed, 29 insertions(+), 4 deletions(-) (limited to 'src/librustc_codegen_ssa') diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs index 4f47d84047d..b33cca2ee8d 100644 --- a/src/librustc_codegen_ssa/mir/block.rs +++ b/src/librustc_codegen_ssa/mir/block.rs @@ -770,6 +770,18 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { &fn_abi.args[first_args.len()..]) } + let needs_location = + instance.map(|i| i.def.requires_caller_location(self.cx.tcx())).unwrap_or_default(); + if needs_location { + assert_eq!( + fn_abi.args.len(), args.len() + 1, + "#[track_caller] fn's must have 1 more argument in their ABI than in their MIR", + ); + let location = self.get_caller_location(&mut bx, span); + let last_arg = &fn_abi.args.last().unwrap(); + self.codegen_argument(&mut bx, location, &mut llargs, last_arg); + } + let fn_ptr = match (llfn, instance) { (Some(llfn), _) => llfn, (None, Some(instance)) => bx.get_fn_addr(instance), diff --git a/src/librustc_codegen_ssa/mir/mod.rs b/src/librustc_codegen_ssa/mir/mod.rs index a6333ef23f5..6be6e13cc1d 100644 --- a/src/librustc_codegen_ssa/mir/mod.rs +++ b/src/librustc_codegen_ssa/mir/mod.rs @@ -182,7 +182,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( // Allocate variable and temp allocas fx.locals = { - let args = arg_local_refs(&mut bx, &fx, &memory_locals); + let args = arg_local_refs(&mut bx, &mut fx, &memory_locals); let mut allocate_local = |local| { let decl = &mir_body.local_decls[local]; @@ -324,14 +324,14 @@ fn create_funclets<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( /// indirect. fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( bx: &mut Bx, - fx: &FunctionCx<'a, 'tcx, Bx>, + fx: &mut FunctionCx<'a, 'tcx, Bx>, memory_locals: &BitSet, ) -> Vec> { let mir = fx.mir; let mut idx = 0; let mut llarg_idx = fx.fn_abi.ret.is_indirect() as usize; - mir.args_iter().enumerate().map(|(arg_index, local)| { + let args = mir.args_iter().enumerate().map(|(arg_index, local)| { let arg_decl = &mir.local_decls[local]; if Some(local) == mir.spread_arg { @@ -427,7 +427,20 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( bx.store_fn_arg(arg, &mut llarg_idx, tmp); LocalRef::Place(tmp) } - }).collect() + }).collect::>(); + + if fx.instance.def.requires_caller_location(bx.tcx()) { + assert_eq!( + fx.fn_abi.args.len(), args.len() + 1, + "#[track_caller] fn's must have 1 more argument in their ABI than in their MIR", + ); + let arg = &fx.fn_abi.args.last().unwrap(); + let place = PlaceRef::alloca(bx, arg.layout); + bx.store_fn_arg(arg, &mut llarg_idx, place); + fx.caller_location = Some(place); + } + + args } mod analyze; -- cgit 1.4.1-3-g733a5 From 99165ce1f76573729530c241036a0514ca1cf232 Mon Sep 17 00:00:00 2001 From: Adam Perry Date: Fri, 6 Dec 2019 16:09:40 -0800 Subject: Caller location is propagated via immediates rather than memory. --- src/librustc_codegen_ssa/mir/block.rs | 6 ++---- src/librustc_codegen_ssa/mir/mod.rs | 15 +++++++++++---- 2 files changed, 13 insertions(+), 8 deletions(-) (limited to 'src/librustc_codegen_ssa') diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs index b33cca2ee8d..5d25f7022c5 100644 --- a/src/librustc_codegen_ssa/mir/block.rs +++ b/src/librustc_codegen_ssa/mir/block.rs @@ -1016,9 +1016,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bx: &mut Bx, span: Span, ) -> OperandRef<'tcx, Bx::Value> { - if let Some(l) = self.caller_location { - bx.load_operand(l) - } else { + self.caller_location.unwrap_or_else(|| { let topmost = span.ctxt().outer_expn().expansion_cause().unwrap_or(span); let caller = bx.tcx().sess.source_map().lookup_char_pos(topmost.lo()); let const_loc = bx.tcx().const_caller_location(( @@ -1027,7 +1025,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { caller.col_display as u32 + 1, )); OperandRef::from_const(bx, const_loc) - } + }) } fn get_personality_slot( diff --git a/src/librustc_codegen_ssa/mir/mod.rs b/src/librustc_codegen_ssa/mir/mod.rs index 6be6e13cc1d..5e4da8f2125 100644 --- a/src/librustc_codegen_ssa/mir/mod.rs +++ b/src/librustc_codegen_ssa/mir/mod.rs @@ -79,7 +79,7 @@ pub struct FunctionCx<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> { per_local_var_debug_info: Option>>>, /// Caller location propagated if this function has `#[track_caller]`. - caller_location: Option>, + caller_location: Option>, } impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { @@ -434,10 +434,17 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( fx.fn_abi.args.len(), args.len() + 1, "#[track_caller] fn's must have 1 more argument in their ABI than in their MIR", ); + let arg = &fx.fn_abi.args.last().unwrap(); - let place = PlaceRef::alloca(bx, arg.layout); - bx.store_fn_arg(arg, &mut llarg_idx, place); - fx.caller_location = Some(place); + match arg.mode { + PassMode::Direct(_) => (), + _ => panic!("caller location must be PassMode::Direct, found {:?}", arg.mode), + } + + fx.caller_location = Some(OperandRef { + val: OperandValue::Immediate(bx.get_param(llarg_idx)), + layout: arg.layout, + }); } args -- cgit 1.4.1-3-g733a5 From 1c2483eb6fd679fd7f63cc0c0fb9692a2aa698aa Mon Sep 17 00:00:00 2001 From: Adam Perry Date: Fri, 6 Dec 2019 17:05:51 -0800 Subject: Address review feedback. --- src/librustc_codegen_ssa/mir/block.rs | 4 ++-- src/librustc_codegen_ssa/mir/mod.rs | 4 ++-- src/librustc_mir/interpret/intrinsics.rs | 2 +- .../interpret/intrinsics/caller_location.rs | 17 +++++------------ 4 files changed, 10 insertions(+), 17 deletions(-) (limited to 'src/librustc_codegen_ssa') diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs index 5d25f7022c5..099ba5b39bb 100644 --- a/src/librustc_codegen_ssa/mir/block.rs +++ b/src/librustc_codegen_ssa/mir/block.rs @@ -771,14 +771,14 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } let needs_location = - instance.map(|i| i.def.requires_caller_location(self.cx.tcx())).unwrap_or_default(); + instance.map_or(false, |i| i.def.requires_caller_location(self.cx.tcx())); if needs_location { assert_eq!( fn_abi.args.len(), args.len() + 1, "#[track_caller] fn's must have 1 more argument in their ABI than in their MIR", ); let location = self.get_caller_location(&mut bx, span); - let last_arg = &fn_abi.args.last().unwrap(); + let last_arg = fn_abi.args.last().unwrap(); self.codegen_argument(&mut bx, location, &mut llargs, last_arg); } diff --git a/src/librustc_codegen_ssa/mir/mod.rs b/src/librustc_codegen_ssa/mir/mod.rs index 5e4da8f2125..33e343de86b 100644 --- a/src/librustc_codegen_ssa/mir/mod.rs +++ b/src/librustc_codegen_ssa/mir/mod.rs @@ -435,10 +435,10 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( "#[track_caller] fn's must have 1 more argument in their ABI than in their MIR", ); - let arg = &fx.fn_abi.args.last().unwrap(); + let arg = fx.fn_abi.args.last().unwrap(); match arg.mode { PassMode::Direct(_) => (), - _ => panic!("caller location must be PassMode::Direct, found {:?}", arg.mode), + _ => bug!("caller location must be PassMode::Direct, found {:?}", arg.mode), } fx.caller_location = Some(OperandRef { diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs index 20f1a1d7c48..67f0aed243d 100644 --- a/src/librustc_mir/interpret/intrinsics.rs +++ b/src/librustc_mir/interpret/intrinsics.rs @@ -112,7 +112,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // `src/librustc/ty/constness.rs` match intrinsic_name { sym::caller_location => { - let span = self.find_closest_untracked_caller_location(span); + let span = self.find_closest_untracked_caller_location().unwrap_or(span); let location = self.alloc_caller_location_for_span(span); self.write_scalar(location.ptr, dest)?; } diff --git a/src/librustc_mir/interpret/intrinsics/caller_location.rs b/src/librustc_mir/interpret/intrinsics/caller_location.rs index 391c0c30bde..ec843ef7a4d 100644 --- a/src/librustc_mir/interpret/intrinsics/caller_location.rs +++ b/src/librustc_mir/interpret/intrinsics/caller_location.rs @@ -7,24 +7,17 @@ use crate::interpret::{Scalar, MemoryKind, MPlaceTy, intrinsics::{InterpCx, Mach impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { /// Walks up the callstack from the intrinsic's callsite, searching for the first frame which is - /// not `#[track_caller]`. Returns the (passed) span of the intrinsic's callsite if the first - /// frame in the stack is untracked so that we can display the callsite of the intrinsic within - /// that function. - crate fn find_closest_untracked_caller_location( - &self, - intrinsic_loc: Span, - ) -> Span { - debug!("finding closest untracked caller relative to {:?}", intrinsic_loc); - - let mut caller_span = intrinsic_loc; + /// not `#[track_caller]`. + crate fn find_closest_untracked_caller_location(&self) -> Option { + let mut caller_span = None; for next_caller in self.stack.iter().rev() { if !next_caller.instance.def.requires_caller_location(*self.tcx) { return caller_span; } - caller_span = next_caller.span; + caller_span = Some(next_caller.span); } - intrinsic_loc + caller_span } /// Allocate a `const core::panic::Location` with the provided filename and line/column numbers. -- cgit 1.4.1-3-g733a5