提交 86e55b18 编写于 作者: A Adam Perry

Always use consteval to codegen caller_location.

上级 017877cb
......@@ -466,6 +466,12 @@
no_force
desc { "extract field of const" }
}
query const_caller_location(key: (syntax_pos::Symbol, u32, u32)) -> &'tcx ty::Const<'tcx> {
eval_always
no_force
desc { "get a &core::panic::Location referring to a span" }
}
}
TypeChecking {
......
......@@ -208,3 +208,13 @@ fn default_span(&self, _tcx: TyCtxt<'_>) -> Span {
DUMMY_SP
}
}
impl Key for (Symbol, u32, u32) {
fn query_crate(&self) -> CrateNum {
LOCAL_CRATE
}
fn default_span(&self, _tcx: TyCtxt<'_>) -> Span {
DUMMY_SP
}
}
......@@ -2,7 +2,6 @@
use crate::llvm::{self, False, BasicBlock};
use crate::common::Funclet;
use crate::context::CodegenCx;
use crate::syntax_pos::Pos;
use crate::type_::Type;
use crate::type_of::LayoutLlvmExt;
use crate::value::Value;
......@@ -24,7 +23,6 @@
use std::ops::{Deref, Range};
use std::ptr;
use std::iter::TrustedLen;
use syntax::symbol::Symbol;
// All Builders must have an llfn associated with them
#[must_use]
......@@ -1068,20 +1066,6 @@ fn get_static(&mut self, def_id: DefId) -> &'ll Value {
// Forward to the `get_static` method of `CodegenCx`
self.cx().get_static(def_id)
}
fn static_panic_location(&mut self, loc: &syntax::source_map::Loc) -> Self::Value {
let filename = Symbol::intern(&loc.file.name.to_string());
let filename = self.const_str(filename);
let line = self.const_u32(loc.line as u32);
let col = self.const_u32(loc.col.to_usize() as u32 + 1);
let struct_ = self.const_struct(&[filename.0, filename.1, line, col], false);
let align = self.tcx.data_layout.aggregate_align.abi
.max(self.tcx.data_layout.i32_align.abi)
.max(self.tcx.data_layout.pointer_align.abi);
// FIXME(eddyb) move this into miri, it can be correct if e.g. field order changes
self.static_addr_of(struct_, align, Some("panic_loc"))
}
}
impl Builder<'a, 'll, 'tcx> {
......
......@@ -15,7 +15,7 @@
use std::borrow::Cow;
use syntax::symbol::Symbol;
use syntax::{source_map::Span, symbol::Symbol};
use super::{FunctionCx, LocalRef};
use super::place::PlaceRef;
......@@ -420,8 +420,7 @@ fn codegen_assert_terminator<'b>(
self.set_debug_loc(&mut bx, terminator.source_info);
// Get the location information.
let loc = bx.sess().source_map().lookup_char_pos(span.lo());
let location = bx.static_panic_location(&loc);
let location = self.get_caller_location(&mut bx, span).immediate();
// Put together the arguments to the panic entry point.
let (lang_item, args) = match msg {
......@@ -534,11 +533,9 @@ fn codegen_call_terminator<'b>(
let ty = instance.unwrap().substs.type_at(0);
let layout = bx.layout_of(ty);
if layout.abi.is_uninhabited() {
let loc = bx.sess().source_map().lookup_char_pos(span.lo());
let msg_str = format!("Attempted to instantiate uninhabited type {}", ty);
let msg = bx.const_str(Symbol::intern(&msg_str));
let location = bx.static_panic_location(&loc);
let location = self.get_caller_location(&mut bx, span).immediate();
// Obtain the panic entry point.
let def_id =
......@@ -584,13 +581,12 @@ fn codegen_call_terminator<'b>(
if intrinsic == Some("caller_location") {
if let Some((_, target)) = destination.as_ref() {
let loc = bx.sess().source_map().lookup_char_pos(span.lo());
let location = bx.static_panic_location(&loc);
let location = self.get_caller_location(&mut bx, span);
if let ReturnDest::IndirectOperand(tmp, _) = ret_dest {
Immediate(location).store(&mut bx, tmp);
location.val.store(&mut bx, tmp);
}
self.store_return(&mut bx, ret_dest, &fn_ty.ret, location);
self.store_return(&mut bx, ret_dest, &fn_ty.ret, location.immediate());
helper.maybe_sideeffect(self.mir, &mut bx, &[*target]);
helper.funclet_br(self, &mut bx, *target);
......@@ -994,6 +990,20 @@ fn codegen_arguments_untupled(
}
}
fn get_caller_location(
&mut self,
bx: &mut Bx,
span: Span,
) -> OperandRef<'tcx, Bx::Value> {
let caller = bx.tcx().sess.source_map().lookup_char_pos(span.lo());
let const_loc = bx.tcx().const_caller_location((
Symbol::intern(&caller.file.name.to_string()),
caller.line as u32,
caller.col_display as u32 + 1,
));
OperandRef::from_const(bx, const_loc)
}
fn get_personality_slot(
&mut self,
bx: &mut Bx
......
use super::BackendTypes;
use syntax::source_map::Loc;
use rustc::hir::def_id::DefId;
use rustc::ty::layout::Align;
......@@ -10,5 +9,4 @@ pub trait StaticMethods: BackendTypes {
pub trait StaticBuilderMethods: BackendTypes {
fn get_static(&mut self, def_id: DefId) -> Self::Value;
fn static_panic_location(&mut self, loc: &Loc) -> Self::Value;
}
......@@ -18,7 +18,7 @@
use rustc_data_structures::fx::FxHashMap;
use crate::interpret::eval_nullary_intrinsic;
use syntax::source_map::{Span, DUMMY_SP};
use syntax::{source_map::{Span, DUMMY_SP}, symbol::Symbol};
use crate::interpret::{self,
PlaceTy, MPlaceTy, OpTy, ImmTy, Immediate, Scalar, Pointer,
......@@ -159,11 +159,7 @@ fn eval_body_using_ecx<'mir, 'tcx>(
ecx.run()?;
// Intern the result
intern_const_alloc_recursive(
ecx,
cid.instance.def_id(),
ret,
)?;
intern_const_alloc_recursive(ecx, tcx.static_mutability(cid.instance.def_id()), ret)?;
debug!("eval_body_using_ecx done: {:?}", *ret);
Ok(ret)
......
......@@ -6,7 +6,6 @@
use rustc::ty::{Ty, self};
use rustc::mir::interpret::{InterpResult, ErrorHandled};
use rustc::hir;
use rustc::hir::def_id::DefId;
use super::validity::RefTracking;
use rustc_data_structures::fx::FxHashSet;
......@@ -270,12 +269,12 @@ fn visit_primitive(&mut self, mplace: MPlaceTy<'tcx>) -> InterpResult<'tcx> {
pub fn intern_const_alloc_recursive(
ecx: &mut CompileTimeEvalContext<'mir, 'tcx>,
def_id: DefId,
// The `mutability` of the place, ignoring the type.
place_mut: Option<hir::Mutability>,
ret: MPlaceTy<'tcx>,
) -> InterpResult<'tcx> {
let tcx = ecx.tcx;
// this `mutability` is the mutability of the place, ignoring the type
let (base_mutability, base_intern_mode) = match tcx.static_mutability(def_id) {
let (base_mutability, base_intern_mode) = match place_mut {
Some(hir::Mutability::MutImmutable) => (Mutability::Immutable, InternMode::Static),
// `static mut` doesn't care about interior mutability, it's mutable anyway
Some(hir::Mutability::MutMutable) => (Mutability::Mutable, InternMode::Static),
......
......@@ -98,7 +98,13 @@ pub fn emulate_intrinsic(
let intrinsic_name = &self.tcx.item_name(instance.def_id()).as_str()[..];
match intrinsic_name {
"caller_location" => {
self.write_caller_location(span, dest)?;
let caller = self.tcx.sess.source_map().lookup_char_pos(span.lo());
let location = self.alloc_caller_location(
Symbol::intern(&caller.file.name.to_string()),
caller.line as u32,
caller.col_display as u32 + 1,
)?;
self.write_scalar(location.ptr, dest)?;
}
"min_align_of" |
......
......@@ -2,23 +2,19 @@
use rustc::mir::interpret::{Pointer, PointerArithmetic, Scalar};
use rustc::ty::subst::Subst;
use rustc_target::abi::{LayoutOf, Size};
use syntax_pos::Span;
use syntax_pos::Symbol;
use crate::interpret::{
MemoryKind,
intrinsics::{InterpCx, InterpResult, Machine, PlaceTy},
};
use crate::interpret::{MemoryKind, MPlaceTy, intrinsics::{InterpCx, InterpResult, Machine}};
impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
pub fn write_caller_location(
pub fn alloc_caller_location(
&mut self,
span: Span,
dest: PlaceTy<'tcx, M::PointerTag>,
) -> InterpResult<'tcx> {
let caller = self.tcx.sess.source_map().lookup_char_pos(span.lo());
let filename = caller.file.name.to_string();
let line = Scalar::from_u32(caller.line as u32);
let col = Scalar::from_u32(caller.col_display as u32 + 1);
filename: Symbol,
line: u32,
col: u32,
) -> InterpResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
let line = Scalar::from_u32(line);
let col = Scalar::from_u32(col);
let ptr_size = self.pointer_size();
let u32_size = Size::from_bits(32);
......@@ -27,10 +23,10 @@ pub fn write_caller_location(
.subst(*self.tcx, self.tcx.mk_substs([self.tcx.lifetimes.re_static.into()].iter()));
let loc_layout = self.layout_of(loc_ty)?;
let file_alloc = self.tcx.allocate_bytes(filename.as_bytes());
let file_alloc = self.tcx.allocate_bytes(filename.as_str().as_bytes());
let file_ptr = Pointer::new(file_alloc, Size::ZERO);
let file = Scalar::Ptr(self.tag_static_base_pointer(file_ptr));
let file_len = Scalar::from_uint(filename.len() as u128, ptr_size);
let file_len = Scalar::from_uint(filename.as_str().len() as u128, ptr_size);
let location = self.allocate(loc_layout, MemoryKind::Stack);
......@@ -48,7 +44,6 @@ pub fn write_caller_location(
alloc.write_scalar(layout, line_out, line.into(), u32_size)?;
alloc.write_scalar(layout, col_out, col.into(), u32_size)?;
self.write_scalar(location.ptr, dest)?;
Ok(())
Ok(location)
}
}
......@@ -58,6 +58,7 @@ pub fn provide(providers: &mut Providers<'_>) {
providers.const_eval = const_eval::const_eval_provider;
providers.const_eval_raw = const_eval::const_eval_raw_provider;
providers.check_match = hair::pattern::check_match;
providers.const_caller_location = const_eval::const_caller_location;
providers.const_field = |tcx, param_env_and_value| {
let (param_env, (value, field)) = param_env_and_value.into_parts();
const_eval::const_field(tcx, param_env, None, field, value)
......
//! Type-checking for the rust-intrinsic and platform-intrinsic
//! intrinsics that the compiler exposes.
use rustc::hir::{self, Mutability};
use rustc::middle::lang_items::PanicLocationLangItem;
use rustc::traits::{ObligationCause, ObligationCauseCode};
use rustc::ty::{self, TyCtxt, Ty};
......@@ -11,6 +10,8 @@
use rustc_target::spec::abi::Abi;
use syntax::symbol::Symbol;
use rustc::hir;
use std::iter;
fn equate_intrinsic_type<'tcx>(
......@@ -146,13 +147,10 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem) {
"caller_location" => (
0,
vec![],
tcx.mk_ref(
tcx.mk_imm_ref(
tcx.lifetimes.re_static,
ty::TypeAndMut {
mutbl: Mutability::MutImmutable,
ty: tcx.type_of(tcx.require_lang_item(PanicLocationLangItem, None))
.subst(tcx, tcx.mk_substs([tcx.lifetimes.re_static.into()].iter())),
},
tcx.type_of(tcx.require_lang_item(PanicLocationLangItem, None))
.subst(tcx, tcx.mk_substs([tcx.lifetimes.re_static.into()].iter())),
),
),
"panic_if_uninhabited" => (1, Vec::new(), tcx.mk_unit()),
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册