Skip to content

Commit 73100d8

Browse files
Rollup merge of #117317 - RalfJung:track-caller, r=oli-obk
share some track_caller logic between interpret and codegen Also move the code that implements the track_caller intrinsics out of the core interpreter engine -- it's just a helper creating a const-allocation, doesn't need to be part of the interpreter core.
2 parents 95de91b + 04fa124 commit 73100d8

File tree

13 files changed

+196
-238
lines changed

13 files changed

+196
-238
lines changed

compiler/rustc_codegen_cranelift/src/common.rs

+5-41
Original file line numberDiff line numberDiff line change
@@ -430,47 +430,11 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> {
430430
}
431431
}
432432

433-
// Note: must be kept in sync with get_caller_location from cg_ssa
434-
pub(crate) fn get_caller_location(&mut self, mut source_info: mir::SourceInfo) -> CValue<'tcx> {
435-
let span_to_caller_location = |fx: &mut FunctionCx<'_, '_, 'tcx>, span: Span| {
436-
use rustc_session::RemapFileNameExt;
437-
let topmost = span.ctxt().outer_expn().expansion_cause().unwrap_or(span);
438-
let caller = fx.tcx.sess.source_map().lookup_char_pos(topmost.lo());
439-
let const_loc = fx.tcx.const_caller_location((
440-
rustc_span::symbol::Symbol::intern(
441-
&caller.file.name.for_codegen(&fx.tcx.sess).to_string_lossy(),
442-
),
443-
caller.line as u32,
444-
caller.col_display as u32 + 1,
445-
));
446-
crate::constant::codegen_const_value(fx, const_loc, fx.tcx.caller_location_ty())
447-
};
448-
449-
// Walk up the `SourceScope`s, in case some of them are from MIR inlining.
450-
// If so, the starting `source_info.span` is in the innermost inlined
451-
// function, and will be replaced with outer callsite spans as long
452-
// as the inlined functions were `#[track_caller]`.
453-
loop {
454-
let scope_data = &self.mir.source_scopes[source_info.scope];
455-
456-
if let Some((callee, callsite_span)) = scope_data.inlined {
457-
// Stop inside the most nested non-`#[track_caller]` function,
458-
// before ever reaching its caller (which is irrelevant).
459-
if !callee.def.requires_caller_location(self.tcx) {
460-
return span_to_caller_location(self, source_info.span);
461-
}
462-
source_info.span = callsite_span;
463-
}
464-
465-
// Skip past all of the parents with `inlined: None`.
466-
match scope_data.inlined_parent_scope {
467-
Some(parent) => source_info.scope = parent,
468-
None => break,
469-
}
470-
}
471-
472-
// No inlined `SourceScope`s, or all of them were `#[track_caller]`.
473-
self.caller_location.unwrap_or_else(|| span_to_caller_location(self, source_info.span))
433+
pub(crate) fn get_caller_location(&mut self, source_info: mir::SourceInfo) -> CValue<'tcx> {
434+
self.mir.caller_location_span(source_info, self.caller_location, self.tcx, |span| {
435+
let const_loc = self.tcx.span_as_caller_location(span);
436+
crate::constant::codegen_const_value(self, const_loc, self.tcx.caller_location_ty())
437+
})
474438
}
475439

476440
pub(crate) fn anonymous_str(&mut self, msg: &str) -> Value {

compiler/rustc_codegen_ssa/src/mir/block.rs

+4-39
Original file line numberDiff line numberDiff line change
@@ -1449,47 +1449,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
14491449
fn get_caller_location(
14501450
&mut self,
14511451
bx: &mut Bx,
1452-
mut source_info: mir::SourceInfo,
1452+
source_info: mir::SourceInfo,
14531453
) -> OperandRef<'tcx, Bx::Value> {
1454-
let tcx = bx.tcx();
1455-
1456-
let mut span_to_caller_location = |span: Span| {
1457-
use rustc_session::RemapFileNameExt;
1458-
let topmost = span.ctxt().outer_expn().expansion_cause().unwrap_or(span);
1459-
let caller = tcx.sess.source_map().lookup_char_pos(topmost.lo());
1460-
let const_loc = tcx.const_caller_location((
1461-
Symbol::intern(&caller.file.name.for_codegen(self.cx.sess()).to_string_lossy()),
1462-
caller.line as u32,
1463-
caller.col_display as u32 + 1,
1464-
));
1454+
self.mir.caller_location_span(source_info, self.caller_location, bx.tcx(), |span: Span| {
1455+
let const_loc = bx.tcx().span_as_caller_location(span);
14651456
OperandRef::from_const(bx, const_loc, bx.tcx().caller_location_ty())
1466-
};
1467-
1468-
// Walk up the `SourceScope`s, in case some of them are from MIR inlining.
1469-
// If so, the starting `source_info.span` is in the innermost inlined
1470-
// function, and will be replaced with outer callsite spans as long
1471-
// as the inlined functions were `#[track_caller]`.
1472-
loop {
1473-
let scope_data = &self.mir.source_scopes[source_info.scope];
1474-
1475-
if let Some((callee, callsite_span)) = scope_data.inlined {
1476-
// Stop inside the most nested non-`#[track_caller]` function,
1477-
// before ever reaching its caller (which is irrelevant).
1478-
if !callee.def.requires_caller_location(tcx) {
1479-
return span_to_caller_location(source_info.span);
1480-
}
1481-
source_info.span = callsite_span;
1482-
}
1483-
1484-
// Skip past all of the parents with `inlined: None`.
1485-
match scope_data.inlined_parent_scope {
1486-
Some(parent) => source_info.scope = parent,
1487-
None => break,
1488-
}
1489-
}
1490-
1491-
// No inlined `SourceScope`s, or all of them were `#[track_caller]`.
1492-
self.caller_location.unwrap_or_else(|| span_to_caller_location(source_info.span))
1457+
})
14931458
}
14941459

14951460
fn get_personality_slot(&mut self, bx: &mut Bx) -> PlaceRef<'tcx, Bx::Value> {

compiler/rustc_const_eval/src/const_eval/eval_queries.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ fn eval_body_using_ecx<'mir, 'tcx>(
9090
/// that inform us about the generic bounds of the constant. E.g., using an associated constant
9191
/// of a function's generic parameter will require knowledge about the bounds on the generic
9292
/// parameter. These bounds are passed to `mk_eval_cx` via the `ParamEnv` argument.
93-
pub(super) fn mk_eval_cx<'mir, 'tcx>(
93+
pub(crate) fn mk_eval_cx<'mir, 'tcx>(
9494
tcx: TyCtxt<'tcx>,
9595
root_span: Span,
9696
param_env: ty::ParamEnv<'tcx>,

compiler/rustc_const_eval/src/const_eval/machine.rs

+19
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use rustc_middle::mir;
44
use rustc_middle::mir::interpret::PointerArithmetic;
55
use rustc_middle::ty::layout::{FnAbiOf, TyAndLayout};
66
use rustc_middle::ty::{self, TyCtxt};
7+
use rustc_span::Span;
78
use std::borrow::Borrow;
89
use std::hash::Hash;
910
use std::ops::ControlFlow;
@@ -181,6 +182,24 @@ impl interpret::MayLeak for ! {
181182
}
182183

183184
impl<'mir, 'tcx: 'mir> CompileTimeEvalContext<'mir, 'tcx> {
185+
fn location_triple_for_span(&self, span: Span) -> (Symbol, u32, u32) {
186+
let topmost = span.ctxt().outer_expn().expansion_cause().unwrap_or(span);
187+
let caller = self.tcx.sess.source_map().lookup_char_pos(topmost.lo());
188+
189+
use rustc_session::{config::RemapPathScopeComponents, RemapFileNameExt};
190+
(
191+
Symbol::intern(
192+
&caller
193+
.file
194+
.name
195+
.for_scope(&self.tcx.sess, RemapPathScopeComponents::DIAGNOSTICS)
196+
.to_string_lossy(),
197+
),
198+
u32::try_from(caller.line).unwrap(),
199+
u32::try_from(caller.col_display).unwrap().checked_add(1).unwrap(),
200+
)
201+
}
202+
184203
/// "Intercept" a function call, because we have something special to do for it.
185204
/// All `#[rustc_do_not_const_check]` functions should be hooked here.
186205
/// If this returns `Some` function, which may be `instance` or a different function with

compiler/rustc_const_eval/src/const_eval/mod.rs

+2-16
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
// Not in interpret to make sure we do not use private implementation details
22

33
use crate::errors::MaxNumNodesInConstErr;
4-
use crate::interpret::{intern_const_alloc_recursive, InternKind, InterpCx, Scalar};
4+
use crate::interpret::InterpCx;
55
use rustc_middle::mir;
66
use rustc_middle::mir::interpret::{EvalToValTreeResult, GlobalId};
77
use rustc_middle::query::TyCtxtAt;
88
use rustc_middle::ty::{self, Ty, TyCtxt};
9-
use rustc_span::{source_map::DUMMY_SP, symbol::Symbol};
9+
use rustc_span::source_map::DUMMY_SP;
1010

1111
mod error;
1212
mod eval_queries;
@@ -20,20 +20,6 @@ pub use fn_queries::*;
2020
pub use machine::*;
2121
pub(crate) use valtrees::{const_to_valtree_inner, valtree_to_const_value};
2222

23-
pub(crate) fn const_caller_location(
24-
tcx: TyCtxt<'_>,
25-
(file, line, col): (Symbol, u32, u32),
26-
) -> mir::ConstValue<'_> {
27-
trace!("const_caller_location: {}:{}:{}", file, line, col);
28-
let mut ecx = mk_eval_cx(tcx, DUMMY_SP, ty::ParamEnv::reveal_all(), CanAccessStatics::No);
29-
30-
let loc_place = ecx.alloc_caller_location(file, line, col);
31-
if intern_const_alloc_recursive(&mut ecx, InternKind::Constant, &loc_place).is_err() {
32-
bug!("intern_const_alloc_recursive should not error in this case")
33-
}
34-
mir::ConstValue::Scalar(Scalar::from_maybe_pointer(loc_place.ptr(), &tcx))
35-
}
36-
3723
// We forbid type-level constants that contain more than `VALTREE_MAX_NODES` nodes.
3824
const VALTREE_MAX_NODES: usize = 100000;
3925

compiler/rustc_const_eval/src/interpret/eval_context.rs

+44
Original file line numberDiff line numberDiff line change
@@ -595,6 +595,50 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
595595
}
596596
}
597597

598+
/// Walks up the callstack from the intrinsic's callsite, searching for the first callsite in a
599+
/// frame which is not `#[track_caller]`. This is the fancy version of `cur_span`.
600+
pub(crate) fn find_closest_untracked_caller_location(&self) -> Span {
601+
for frame in self.stack().iter().rev() {
602+
debug!("find_closest_untracked_caller_location: checking frame {:?}", frame.instance);
603+
604+
// Assert that the frame we look at is actually executing code currently
605+
// (`loc` is `Right` when we are unwinding and the frame does not require cleanup).
606+
let loc = frame.loc.left().unwrap();
607+
608+
// This could be a non-`Call` terminator (such as `Drop`), or not a terminator at all
609+
// (such as `box`). Use the normal span by default.
610+
let mut source_info = *frame.body.source_info(loc);
611+
612+
// If this is a `Call` terminator, use the `fn_span` instead.
613+
let block = &frame.body.basic_blocks[loc.block];
614+
if loc.statement_index == block.statements.len() {
615+
debug!(
616+
"find_closest_untracked_caller_location: got terminator {:?} ({:?})",
617+
block.terminator(),
618+
block.terminator().kind,
619+
);
620+
if let mir::TerminatorKind::Call { fn_span, .. } = block.terminator().kind {
621+
source_info.span = fn_span;
622+
}
623+
}
624+
625+
let caller_location = if frame.instance.def.requires_caller_location(*self.tcx) {
626+
// We use `Err(())` as indication that we should continue up the call stack since
627+
// this is a `#[track_caller]` function.
628+
Some(Err(()))
629+
} else {
630+
None
631+
};
632+
if let Ok(span) =
633+
frame.body.caller_location_span(source_info, caller_location, *self.tcx, Ok)
634+
{
635+
return span;
636+
}
637+
}
638+
639+
span_bug!(self.cur_span(), "no non-`#[track_caller]` frame found")
640+
}
641+
598642
#[inline(always)]
599643
pub fn layout_of_local(
600644
&self,

compiler/rustc_const_eval/src/interpret/intrinsics.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,6 @@ use super::{
2222

2323
use crate::fluent_generated as fluent;
2424

25-
mod caller_location;
26-
2725
fn numeric_intrinsic<Prov>(name: Symbol, bits: u128, kind: Primitive) -> Scalar<Prov> {
2826
let size = match kind {
2927
Primitive::Int(integer, _) => integer.size(),
@@ -130,8 +128,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
130128
match intrinsic_name {
131129
sym::caller_location => {
132130
let span = self.find_closest_untracked_caller_location();
133-
let location = self.alloc_caller_location_for_span(span);
134-
self.write_immediate(location.to_ref(self), dest)?;
131+
let val = self.tcx.span_as_caller_location(span);
132+
let val =
133+
self.const_val_to_op(val, self.tcx.caller_location_ty(), Some(dest.layout))?;
134+
self.copy_op(&val, dest, /* allow_transmute */ false)?;
135135
}
136136

137137
sym::min_align_of_val | sym::size_of_val => {

compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs

-136
This file was deleted.

0 commit comments

Comments
 (0)