]>
Commit | Line | Data |
---|---|---|
ba9703b0 XL |
1 | use std::convert::TryFrom; |
2 | ||
3 | use rustc_hir::lang_items::PanicLocationLangItem; | |
4 | use rustc_middle::ty::subst::Subst; | |
dfeec247 | 5 | use rustc_span::{Span, Symbol}; |
60c5eb7d | 6 | use rustc_target::abi::LayoutOf; |
e74abb32 | 7 | |
dfeec247 XL |
8 | use crate::interpret::{ |
9 | intrinsics::{InterpCx, Machine}, | |
10 | MPlaceTy, MemoryKind, Scalar, | |
11 | }; | |
e74abb32 | 12 | |
ba9703b0 | 13 | impl<'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 | } |