Skip to content

Commit 351d532

Browse files
committed
interpret: call caller_location logic the same way codegen does, and share some code
1 parent 615d0f2 commit 351d532

File tree

12 files changed

+173
-176
lines changed

12 files changed

+173
-176
lines changed

Diff for: compiler/rustc_codegen_cranelift/src/common.rs

+1-10
Original file line numberDiff line numberDiff line change
@@ -433,16 +433,7 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> {
433433
// Note: must be kept in sync with get_caller_location from cg_ssa
434434
pub(crate) fn get_caller_location(&mut self, mut source_info: mir::SourceInfo) -> CValue<'tcx> {
435435
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-
));
436+
let const_loc = fx.tcx.span_as_caller_location(span);
446437
crate::constant::codegen_const_value(fx, const_loc, fx.tcx.caller_location_ty())
447438
};
448439

Diff for: compiler/rustc_codegen_ssa/src/mir/block.rs

+1-8
Original file line numberDiff line numberDiff line change
@@ -1454,14 +1454,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
14541454
let tcx = bx.tcx();
14551455

14561456
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-
));
1457+
let const_loc = tcx.span_as_caller_location(span);
14651458
OperandRef::from_const(bx, const_loc, bx.tcx().caller_location_ty())
14661459
};
14671460

Diff for: 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>,

Diff for: 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

Diff for: 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

Diff for: compiler/rustc_const_eval/src/interpret/eval_context.rs

+62
Original file line numberDiff line numberDiff line change
@@ -595,6 +595,68 @@ 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+
// Note: this must be kept in sync with get_caller_location from cg_ssa.
626+
627+
// Walk up the `SourceScope`s, in case some of them are from MIR inlining.
628+
// If so, the starting `source_info.span` is in the innermost inlined
629+
// function, and will be replaced with outer callsite spans as long
630+
// as the inlined functions were `#[track_caller]`.
631+
loop {
632+
let scope_data = &frame.body.source_scopes[source_info.scope];
633+
634+
if let Some((callee, callsite_span)) = scope_data.inlined {
635+
// Stop inside the most nested non-`#[track_caller]` function,
636+
// before ever reaching its caller (which is irrelevant).
637+
if !callee.def.requires_caller_location(*self.tcx) {
638+
return source_info.span;
639+
}
640+
source_info.span = callsite_span;
641+
}
642+
643+
// Skip past all of the parents with `inlined: None`.
644+
match scope_data.inlined_parent_scope {
645+
Some(parent) => source_info.scope = parent,
646+
None => break,
647+
}
648+
}
649+
650+
// Stop inside the most nested non-`#[track_caller]` function,
651+
// before ever reaching its caller (which is irrelevant).
652+
if !frame.instance.def.requires_caller_location(*self.tcx) {
653+
return source_info.span;
654+
}
655+
}
656+
657+
span_bug!(self.cur_span(), "no non-`#[track_caller]` frame found")
658+
}
659+
598660
#[inline(always)]
599661
pub fn layout_of_local(
600662
&self,

Diff for: 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 => {

Diff for: compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs

-136
This file was deleted.

Diff for: compiler/rustc_const_eval/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ pub fn provide(providers: &mut Providers) {
4949
const_eval::provide(providers);
5050
providers.eval_to_const_value_raw = const_eval::eval_to_const_value_raw_provider;
5151
providers.eval_to_allocation_raw = const_eval::eval_to_allocation_raw_provider;
52-
providers.const_caller_location = const_eval::const_caller_location;
52+
providers.const_caller_location = util::caller_location::const_caller_location_provider;
5353
providers.eval_to_valtree = |tcx, param_env_and_value| {
5454
let (param_env, raw) = param_env_and_value.into_parts();
5555
const_eval::eval_to_valtree(tcx, param_env, raw)

0 commit comments

Comments
 (0)