Implementation of const caller_location.
This commit is contained in:
parent
aec97e050e
commit
017877cbbe
7 changed files with 90 additions and 2 deletions
|
@ -375,11 +375,12 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
|
|||
|
||||
fn call_intrinsic(
|
||||
ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
||||
span: Span,
|
||||
instance: ty::Instance<'tcx>,
|
||||
args: &[OpTy<'tcx>],
|
||||
dest: PlaceTy<'tcx>,
|
||||
) -> InterpResult<'tcx> {
|
||||
if ecx.emulate_intrinsic(instance, args, dest)? {
|
||||
if ecx.emulate_intrinsic(span, instance, args, dest)? {
|
||||
return Ok(());
|
||||
}
|
||||
// An intrinsic that we do not support
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
//! and miri.
|
||||
|
||||
use syntax::symbol::Symbol;
|
||||
use syntax_pos::Span;
|
||||
use rustc::ty;
|
||||
use rustc::ty::layout::{LayoutOf, Primitive, Size};
|
||||
use rustc::ty::subst::SubstsRef;
|
||||
|
@ -15,6 +16,7 @@ use super::{
|
|||
Machine, PlaceTy, OpTy, InterpCx,
|
||||
};
|
||||
|
||||
mod caller_location;
|
||||
mod type_name;
|
||||
|
||||
fn numeric_intrinsic<'tcx, Tag>(
|
||||
|
@ -86,6 +88,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
/// Returns `true` if emulation happened.
|
||||
pub fn emulate_intrinsic(
|
||||
&mut self,
|
||||
span: Span,
|
||||
instance: ty::Instance<'tcx>,
|
||||
args: &[OpTy<'tcx, M::PointerTag>],
|
||||
dest: PlaceTy<'tcx, M::PointerTag>,
|
||||
|
@ -94,6 +97,10 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
|
||||
let intrinsic_name = &self.tcx.item_name(instance.def_id()).as_str()[..];
|
||||
match intrinsic_name {
|
||||
"caller_location" => {
|
||||
self.write_caller_location(span, dest)?;
|
||||
}
|
||||
|
||||
"min_align_of" |
|
||||
"pref_align_of" |
|
||||
"needs_drop" |
|
||||
|
|
54
src/librustc_mir/interpret/intrinsics/caller_location.rs
Normal file
54
src/librustc_mir/interpret/intrinsics/caller_location.rs
Normal file
|
@ -0,0 +1,54 @@
|
|||
use rustc::middle::lang_items::PanicLocationLangItem;
|
||||
use rustc::mir::interpret::{Pointer, PointerArithmetic, Scalar};
|
||||
use rustc::ty::subst::Subst;
|
||||
use rustc_target::abi::{LayoutOf, Size};
|
||||
use syntax_pos::Span;
|
||||
|
||||
use crate::interpret::{
|
||||
MemoryKind,
|
||||
intrinsics::{InterpCx, InterpResult, Machine, PlaceTy},
|
||||
};
|
||||
|
||||
impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
pub fn write_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);
|
||||
|
||||
let ptr_size = self.pointer_size();
|
||||
let u32_size = Size::from_bits(32);
|
||||
|
||||
let loc_ty = self.tcx.type_of(self.tcx.require_lang_item(PanicLocationLangItem, None))
|
||||
.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_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 location = self.allocate(loc_layout, MemoryKind::Stack);
|
||||
|
||||
let file_out = self.mplace_field(location, 0)?;
|
||||
let file_ptr_out = self.force_ptr(self.mplace_field(file_out, 0)?.ptr)?;
|
||||
let file_len_out = self.force_ptr(self.mplace_field(file_out, 1)?.ptr)?;
|
||||
let line_out = self.force_ptr(self.mplace_field(location, 1)?.ptr)?;
|
||||
let col_out = self.force_ptr(self.mplace_field(location, 2)?.ptr)?;
|
||||
|
||||
let layout = &self.tcx.data_layout;
|
||||
let alloc = self.memory.get_mut(file_ptr_out.alloc_id)?;
|
||||
|
||||
alloc.write_scalar(layout, file_ptr_out, file.into(), ptr_size)?;
|
||||
alloc.write_scalar(layout, file_len_out, file_len.into(), ptr_size)?;
|
||||
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(())
|
||||
}
|
||||
}
|
|
@ -8,6 +8,7 @@ use std::hash::Hash;
|
|||
use rustc::hir::def_id::DefId;
|
||||
use rustc::mir;
|
||||
use rustc::ty::{self, Ty, TyCtxt};
|
||||
use syntax_pos::Span;
|
||||
|
||||
use super::{
|
||||
Allocation, AllocId, InterpResult, Scalar, AllocationExtra,
|
||||
|
@ -152,6 +153,7 @@ pub trait Machine<'mir, 'tcx>: Sized {
|
|||
/// If this returns successfully, the engine will take care of jumping to the next block.
|
||||
fn call_intrinsic(
|
||||
ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
||||
span: Span,
|
||||
instance: ty::Instance<'tcx>,
|
||||
args: &[OpTy<'tcx, Self::PointerTag>],
|
||||
dest: PlaceTy<'tcx, Self::PointerTag>,
|
||||
|
|
|
@ -255,7 +255,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
Some(dest) => dest,
|
||||
None => throw_ub!(Unreachable)
|
||||
};
|
||||
M::call_intrinsic(self, instance, args, dest)?;
|
||||
M::call_intrinsic(self, span, instance, args, dest)?;
|
||||
// No stack frame gets pushed, the main loop will just act as if the
|
||||
// call completed.
|
||||
self.goto_block(ret)?;
|
||||
|
|
|
@ -158,6 +158,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine {
|
|||
|
||||
fn call_intrinsic(
|
||||
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
||||
_span: Span,
|
||||
_instance: ty::Instance<'tcx>,
|
||||
_args: &[OpTy<'tcx>],
|
||||
_dest: PlaceTy<'tcx>,
|
||||
|
|
23
src/test/ui/consts/const-eval/const_caller_location.rs
Normal file
23
src/test/ui/consts/const-eval/const_caller_location.rs
Normal file
|
@ -0,0 +1,23 @@
|
|||
// run-pass
|
||||
|
||||
#![feature(const_fn, core_intrinsics)]
|
||||
|
||||
use std::{intrinsics::caller_location, panic::Location};
|
||||
|
||||
const LOCATION: &Location = caller_location();
|
||||
const NESTED: &Location = {
|
||||
const fn nested_location() -> &'static Location<'static> {
|
||||
caller_location()
|
||||
};
|
||||
nested_location()
|
||||
};
|
||||
|
||||
fn main() {
|
||||
assert_eq!(LOCATION.file(), file!());
|
||||
assert_eq!(LOCATION.line(), 7);
|
||||
assert_eq!(LOCATION.column(), 29);
|
||||
|
||||
assert_eq!(NESTED.file(), file!());
|
||||
assert_eq!(NESTED.line(), 10);
|
||||
assert_eq!(NESTED.column(), 9);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue