]> git.proxmox.com Git - rustc.git/blame - src/librustc_mir/interpret/intrinsics/caller_location.rs
New upstream version 1.44.1+dfsg1
[rustc.git] / src / librustc_mir / interpret / intrinsics / caller_location.rs
CommitLineData
ba9703b0
XL
1use std::convert::TryFrom;
2
3use rustc_hir::lang_items::PanicLocationLangItem;
4use rustc_middle::ty::subst::Subst;
dfeec247 5use rustc_span::{Span, Symbol};
60c5eb7d 6use rustc_target::abi::LayoutOf;
e74abb32 7
dfeec247
XL
8use crate::interpret::{
9 intrinsics::{InterpCx, Machine},
10 MPlaceTy, MemoryKind, Scalar,
11};
e74abb32 12
ba9703b0 13impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
dfeec247 14 /// Walks up the callstack from the intrinsic's callsite, searching for the first callsite in a
ba9703b0
XL
15 /// frame which is not `#[track_caller]`.
16 crate fn find_closest_untracked_caller_location(&self) -> Span {
17 self.stack()
18 .iter()
19 .rev()
20 // Find first non-`#[track_caller]` frame.
21 .find(|frame| !frame.instance.def.requires_caller_location(*self.tcx))
22 // Assert that there is always such a frame.
23 .unwrap()
24 .current_source_info()
25 // Assert that the frame we look at is actually executing code currently
26 // (`current_source_info` is None when we are unwinding and the frame does
27 // not require cleanup).
28 .unwrap()
29 .span
60c5eb7d
XL
30 }
31
32 /// Allocate a `const core::panic::Location` with the provided filename and line/column numbers.
33 crate fn alloc_caller_location(
e74abb32
XL
34 &mut self,
35 filename: Symbol,
36 line: u32,
37 col: u32,
60c5eb7d
XL
38 ) -> MPlaceTy<'tcx, M::PointerTag> {
39 let file = self.allocate_str(&filename.as_str(), MemoryKind::CallerLocation);
e74abb32
XL
40 let line = Scalar::from_u32(line);
41 let col = Scalar::from_u32(col);
42
60c5eb7d 43 // Allocate memory for `CallerLocation` struct.
dfeec247
XL
44 let loc_ty = self
45 .tcx
46 .type_of(self.tcx.require_lang_item(PanicLocationLangItem, None))
ba9703b0 47 .subst(*self.tcx, self.tcx.mk_substs([self.tcx.lifetimes.re_erased.into()].iter()));
60c5eb7d
XL
48 let loc_layout = self.layout_of(loc_ty).unwrap();
49 let location = self.allocate(loc_layout, MemoryKind::CallerLocation);
50
51 // Initialize fields.
52 self.write_immediate(file.to_ref(), self.mplace_field(location, 0).unwrap().into())
53 .expect("writing to memory we just allocated cannot fail");
54 self.write_scalar(line, self.mplace_field(location, 1).unwrap().into())
55 .expect("writing to memory we just allocated cannot fail");
56 self.write_scalar(col, self.mplace_field(location, 2).unwrap().into())
57 .expect("writing to memory we just allocated cannot fail");
58
59 location
60 }
e74abb32 61
74b04a01 62 crate fn location_triple_for_span(&self, span: Span) -> (Symbol, u32, u32) {
60c5eb7d
XL
63 let topmost = span.ctxt().outer_expn().expansion_cause().unwrap_or(span);
64 let caller = self.tcx.sess.source_map().lookup_char_pos(topmost.lo());
dfeec247 65 (
60c5eb7d 66 Symbol::intern(&caller.file.name.to_string()),
ba9703b0
XL
67 u32::try_from(caller.line).unwrap(),
68 u32::try_from(caller.col_display).unwrap().checked_add(1).unwrap(),
60c5eb7d 69 )
e74abb32 70 }
74b04a01
XL
71
72 pub fn alloc_caller_location_for_span(&mut self, span: Span) -> MPlaceTy<'tcx, M::PointerTag> {
73 let (file, line, column) = self.location_triple_for_span(span);
74 self.alloc_caller_location(file, line, column)
75 }
e74abb32 76}