Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Implement core::intrinsics::caller_location.
Returns a `&core::panic::Location` corresponding to where it was
called, also making `Location` a lang item.
  • Loading branch information
anp committed Oct 27, 2019
commit 743964ad3fe566ca2ce5c2de14f8733887d283fd
4 changes: 4 additions & 0 deletions src/libcore/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -696,6 +696,10 @@ extern "rust-intrinsic" {
/// This will statically either panic, or do nothing.
pub fn panic_if_uninhabited<T>();

/// Gets a reference to a static `Location` indicating where it was called.
#[cfg(not(bootstrap))]
pub fn caller_location() -> &'static crate::panic::Location<'static>;

/// Creates a value initialized to zero.
///
/// `init` is unsafe because it returns a zeroed-out datum,
Expand Down
1 change: 1 addition & 0 deletions src/libcore/panic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ impl fmt::Display for PanicInfo<'_> {
///
/// panic!("Normal panic");
/// ```
#[cfg_attr(not(bootstrap), lang = "panic_location")]
#[derive(Debug)]
#[stable(feature = "panic_hooks", since = "1.10.0")]
pub struct Location<'a> {
Expand Down
1 change: 1 addition & 0 deletions src/librustc/middle/lang_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,7 @@ language_item_table! {
PanicFnLangItem, "panic", panic_fn, Target::Fn;
PanicBoundsCheckFnLangItem, "panic_bounds_check", panic_bounds_check_fn, Target::Fn;
PanicInfoLangItem, "panic_info", panic_info, Target::Struct;
PanicLocationLangItem, "panic_location", panic_location, Target::Struct;
PanicImplLangItem, "panic_impl", panic_impl, Target::Fn;
// Libstd panic entry point. Necessary for const eval to be able to catch it
BeginPanicFnLangItem, "begin_panic", begin_panic_fn, Target::Fn;
Expand Down
15 changes: 15 additions & 0 deletions src/librustc_codegen_llvm/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use crate::llvm::{AtomicRmwBinOp, AtomicOrdering, SynchronizationScope};
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;
Expand Down Expand Up @@ -1068,6 +1069,20 @@ impl StaticBuilderMethods for Builder<'a, 'll, 'tcx> {
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"))
}

fn static_panic_msg(
&mut self,
msg: Option<Symbol>,
Expand Down
7 changes: 7 additions & 0 deletions src/librustc_codegen_llvm/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,13 @@ impl ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> {
unsafe { llvm::LLVMConstReal(t, val) }
}

fn const_str(&self, s: Symbol) -> (&'ll Value, &'ll Value) {
let len = s.as_str().len();
let cs = consts::ptrcast(self.const_cstr(s, false),
self.type_ptr_to(self.layout_of(self.tcx.mk_str()).llvm_type(self)));
(cs, self.const_usize(len as u64))
}

fn const_struct(
&self,
elts: &[&'ll Value],
Expand Down
16 changes: 16 additions & 0 deletions src/librustc_codegen_ssa/mir/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -613,6 +613,22 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
ReturnDest::Nothing
};

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);

if let ReturnDest::IndirectOperand(tmp, _) = ret_dest {
Immediate(location).store(&mut bx, tmp);
}
self.store_return(&mut bx, ret_dest, &fn_ty.ret, location);

helper.maybe_sideeffect(self.mir, &mut bx, &[*target]);
helper.funclet_br(self, &mut bx, *target);
}
return;
}

if intrinsic.is_some() && intrinsic != Some("drop_in_place") {
let dest = match ret_dest {
_ if fn_ty.ret.is_indirect() => llargs[0],
Expand Down
2 changes: 2 additions & 0 deletions src/librustc_codegen_ssa/traits/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use crate::mir::place::PlaceRef;
use rustc::mir::interpret::Allocation;
use rustc::mir::interpret::Scalar;
use rustc::ty::layout;
use syntax_pos::Symbol;

pub trait ConstMethods<'tcx>: BackendTypes {
// Constant constructors
Expand All @@ -19,6 +20,7 @@ pub trait ConstMethods<'tcx>: BackendTypes {
fn const_u8(&self, i: u8) -> Self::Value;
fn const_real(&self, t: Self::Type, val: f64) -> Self::Value;

fn const_str(&self, s: Symbol) -> (Self::Value, Self::Value);
fn const_struct(&self, elts: &[Self::Value], packed: bool) -> Self::Value;

fn const_to_opt_uint(&self, v: Self::Value) -> Option<u64>;
Expand Down
2 changes: 2 additions & 0 deletions src/librustc_codegen_ssa/traits/statics.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use super::BackendTypes;
use syntax::source_map::Loc;
use syntax_pos::symbol::Symbol;
use rustc::hir::def_id::DefId;
use rustc::ty::layout::Align;
Expand All @@ -10,6 +11,7 @@ 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;
fn static_panic_msg(
&mut self,
msg: Option<Symbol>,
Expand Down
23 changes: 23 additions & 0 deletions src/librustc_mir/const_eval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use std::convert::TryInto;

use rustc::hir::def::DefKind;
use rustc::hir::def_id::DefId;
use rustc::middle::lang_items::PanicLocationLangItem;
use rustc::mir::interpret::{ConstEvalErr, ErrorHandled, ScalarMaybeUndef};
use rustc::mir;
use rustc::ty::{self, Ty, TyCtxt, subst::Subst};
Expand Down Expand Up @@ -505,6 +506,28 @@ pub fn const_field<'tcx>(
op_to_const(&ecx, field)
}

pub fn const_caller_location<'tcx>(
tcx: TyCtxt<'tcx>,
(file, line, col): (Symbol, u32, u32),
) -> &'tcx ty::Const<'tcx> {
trace!("const_caller_location: {}:{}:{}", file, line, col);
let mut ecx = mk_eval_cx(tcx, DUMMY_SP, ty::ParamEnv::reveal_all());

let loc_ty = tcx.mk_imm_ref(
tcx.lifetimes.re_static,
tcx.type_of(tcx.require_lang_item(PanicLocationLangItem, None))
.subst(tcx, tcx.mk_substs([tcx.lifetimes.re_static.into()].iter())),
);
let loc_place = ecx.alloc_caller_location(file, line, col).unwrap();
intern_const_alloc_recursive(&mut ecx, None, loc_place).unwrap();
let loc_const = ty::Const {
ty: loc_ty,
val: ConstValue::Scalar(loc_place.ptr.into()),
};

tcx.mk_const(loc_const)
}

// this function uses `unwrap` copiously, because an already validated constant must have valid
// fields and can thus never fail outside of compiler bugs
pub fn const_variant_index<'tcx>(
Expand Down
18 changes: 15 additions & 3 deletions src/librustc_typeck/check/intrinsic.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
//! 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};
use rustc::ty::subst::Subst;
Expand All @@ -9,8 +11,6 @@ use crate::require_same_types;
use rustc_target::spec::abi::Abi;
use syntax::symbol::Symbol;

use rustc::hir;

use std::iter;

fn equate_intrinsic_type<'tcx>(
Expand Down Expand Up @@ -65,7 +65,7 @@ fn equate_intrinsic_type<'tcx>(
/// Returns `true` if the given intrinsic is unsafe to call or not.
pub fn intrinsic_operation_unsafety(intrinsic: &str) -> hir::Unsafety {
match intrinsic {
"size_of" | "min_align_of" | "needs_drop" |
"size_of" | "min_align_of" | "needs_drop" | "caller_location" |
"add_with_overflow" | "sub_with_overflow" | "mul_with_overflow" |
"wrapping_add" | "wrapping_sub" | "wrapping_mul" |
"saturating_add" | "saturating_sub" |
Expand Down Expand Up @@ -143,6 +143,18 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem) {
], tcx.types.usize)
}
"rustc_peek" => (1, vec![param(0)], param(0)),
"caller_location" => (
0,
vec![],
tcx.mk_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())),
},
),
),
"panic_if_uninhabited" => (1, Vec::new(), tcx.mk_unit()),
"init" => (1, Vec::new(), param(0)),
"uninit" => (1, Vec::new(), param(0)),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// run-pass

#![feature(core_intrinsics)]
fn main() {
let loc = core::intrinsics::caller_location();
assert_eq!(loc.file(), file!());
assert_eq!(loc.line(), 5);
assert_eq!(loc.column(), 15);
}