]> git.lizzy.rs Git - rust.git/blob - src/librustc_mir/interpret/intrinsics/caller_location.rs
Rollup merge of #68504 - tmiasko:check-pass, r=alexcrichton
[rust.git] / src / librustc_mir / interpret / intrinsics / caller_location.rs
1 use rustc::middle::lang_items::PanicLocationLangItem;
2 use rustc::ty::subst::Subst;
3 use rustc_span::{Span, Symbol};
4 use rustc_target::abi::LayoutOf;
5
6 use crate::interpret::{
7     intrinsics::{InterpCx, Machine},
8     MPlaceTy, MemoryKind, Scalar,
9 };
10
11 impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
12     /// Walks up the callstack from the intrinsic's callsite, searching for the first callsite in a
13     /// frame which is not `#[track_caller]`. If the first frame found lacks `#[track_caller]`, then
14     /// `None` is returned and the callsite of the function invocation itself should be used.
15     crate fn find_closest_untracked_caller_location(&self) -> Option<Span> {
16         let mut caller_span = None;
17         for next_caller in self.stack.iter().rev() {
18             if !next_caller.instance.def.requires_caller_location(*self.tcx) {
19                 return caller_span;
20             }
21             caller_span = Some(next_caller.span);
22         }
23
24         caller_span
25     }
26
27     /// Allocate a `const core::panic::Location` with the provided filename and line/column numbers.
28     crate fn alloc_caller_location(
29         &mut self,
30         filename: Symbol,
31         line: u32,
32         col: u32,
33     ) -> MPlaceTy<'tcx, M::PointerTag> {
34         let file = self.allocate_str(&filename.as_str(), MemoryKind::CallerLocation);
35         let line = Scalar::from_u32(line);
36         let col = Scalar::from_u32(col);
37
38         // Allocate memory for `CallerLocation` struct.
39         let loc_ty = self
40             .tcx
41             .type_of(self.tcx.require_lang_item(PanicLocationLangItem, None))
42             .subst(*self.tcx, self.tcx.mk_substs([self.tcx.lifetimes.re_static.into()].iter()));
43         let loc_layout = self.layout_of(loc_ty).unwrap();
44         let location = self.allocate(loc_layout, MemoryKind::CallerLocation);
45
46         // Initialize fields.
47         self.write_immediate(file.to_ref(), self.mplace_field(location, 0).unwrap().into())
48             .expect("writing to memory we just allocated cannot fail");
49         self.write_scalar(line, self.mplace_field(location, 1).unwrap().into())
50             .expect("writing to memory we just allocated cannot fail");
51         self.write_scalar(col, self.mplace_field(location, 2).unwrap().into())
52             .expect("writing to memory we just allocated cannot fail");
53
54         location
55     }
56
57     pub fn alloc_caller_location_for_span(&mut self, span: Span) -> MPlaceTy<'tcx, M::PointerTag> {
58         let (file, line, column) = self.location_triple_for_span(span);
59         self.alloc_caller_location(file, line, column)
60     }
61
62     pub(super) fn location_triple_for_span(&self, span: Span) -> (Symbol, u32, u32) {
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());
65         (
66             Symbol::intern(&caller.file.name.to_string()),
67             caller.line as u32,
68             caller.col_display as u32 + 1,
69         )
70     }
71 }