73 lines
3.1 KiB
Rust
73 lines
3.1 KiB
Rust
use rustc_hir::LangItem;
|
|
use rustc_middle::bug;
|
|
use rustc_middle::mir;
|
|
use rustc_middle::query::TyCtxtAt;
|
|
use rustc_middle::ty::layout::LayoutOf;
|
|
use rustc_middle::ty::{self, Mutability};
|
|
use rustc_span::symbol::Symbol;
|
|
use tracing::trace;
|
|
|
|
use crate::const_eval::{mk_eval_cx_to_read_const_val, CanAccessMutGlobal, CompileTimeInterpCx};
|
|
use crate::interpret::*;
|
|
|
|
/// Allocate a `const core::panic::Location` with the provided filename and line/column numbers.
|
|
fn alloc_caller_location<'tcx>(
|
|
ecx: &mut CompileTimeInterpCx<'tcx>,
|
|
filename: Symbol,
|
|
line: u32,
|
|
col: u32,
|
|
) -> MPlaceTy<'tcx> {
|
|
let loc_details = ecx.tcx.sess.opts.unstable_opts.location_detail;
|
|
// This can fail if rustc runs out of memory right here. Trying to emit an error would be
|
|
// pointless, since that would require allocating more memory than these short strings.
|
|
let file = if loc_details.file {
|
|
ecx.allocate_str(filename.as_str(), MemoryKind::CallerLocation, Mutability::Not).unwrap()
|
|
} else {
|
|
// FIXME: This creates a new allocation each time. It might be preferable to
|
|
// perform this allocation only once, and re-use the `MPlaceTy`.
|
|
// See https://github.com/rust-lang/rust/pull/89920#discussion_r730012398
|
|
ecx.allocate_str("<redacted>", MemoryKind::CallerLocation, Mutability::Not).unwrap()
|
|
};
|
|
let file = file.map_provenance(CtfeProvenance::as_immutable);
|
|
let line = if loc_details.line { Scalar::from_u32(line) } else { Scalar::from_u32(0) };
|
|
let col = if loc_details.column { Scalar::from_u32(col) } else { Scalar::from_u32(0) };
|
|
|
|
// Allocate memory for `CallerLocation` struct.
|
|
let loc_ty = ecx
|
|
.tcx
|
|
.type_of(ecx.tcx.require_lang_item(LangItem::PanicLocation, None))
|
|
.instantiate(*ecx.tcx, ecx.tcx.mk_args(&[ecx.tcx.lifetimes.re_erased.into()]));
|
|
let loc_layout = ecx.layout_of(loc_ty).unwrap();
|
|
let location = ecx.allocate(loc_layout, MemoryKind::CallerLocation).unwrap();
|
|
|
|
// Initialize fields.
|
|
ecx.write_immediate(file.to_ref(ecx), &ecx.project_field(&location, 0).unwrap())
|
|
.expect("writing to memory we just allocated cannot fail");
|
|
ecx.write_scalar(line, &ecx.project_field(&location, 1).unwrap())
|
|
.expect("writing to memory we just allocated cannot fail");
|
|
ecx.write_scalar(col, &ecx.project_field(&location, 2).unwrap())
|
|
.expect("writing to memory we just allocated cannot fail");
|
|
|
|
location
|
|
}
|
|
|
|
pub(crate) fn const_caller_location_provider(
|
|
tcx: TyCtxtAt<'_>,
|
|
file: Symbol,
|
|
line: u32,
|
|
col: u32,
|
|
) -> mir::ConstValue<'_> {
|
|
trace!("const_caller_location: {}:{}:{}", file, line, col);
|
|
let mut ecx = mk_eval_cx_to_read_const_val(
|
|
tcx.tcx,
|
|
tcx.span,
|
|
ty::ParamEnv::reveal_all(),
|
|
CanAccessMutGlobal::No,
|
|
);
|
|
|
|
let loc_place = alloc_caller_location(&mut ecx, file, line, col);
|
|
if intern_const_alloc_recursive(&mut ecx, InternKind::Constant, &loc_place).is_err() {
|
|
bug!("intern_const_alloc_recursive should not error in this case")
|
|
}
|
|
mir::ConstValue::Scalar(Scalar::from_maybe_pointer(loc_place.ptr(), &tcx))
|
|
}
|