Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

std::panic::Location is a lang_item, add core::intrinsics::caller_location (RFC 2091 3/N) #65664

Merged
merged 4 commits into from
Oct 28, 2019
Merged
Changes from all commits
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
4 changes: 4 additions & 0 deletions src/libcore/intrinsics.rs
Original file line number Diff line number Diff line change
@@ -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,
35 changes: 34 additions & 1 deletion src/libcore/macros.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
/// Panics the current thread.
///
/// For details, see `std::macros`.
#[cfg(bootstrap)]
#[macro_export]
#[allow_internal_unstable(core_panic)]
#[allow_internal_unstable(core_panic, panic_internals)]
#[stable(feature = "core", since = "1.6.0")]
macro_rules! panic {
() => (
@@ -20,6 +21,38 @@ macro_rules! panic {
});
}

/// Panics the current thread.
///
/// For details, see `std::macros`.
#[cfg(not(bootstrap))]
#[macro_export]
#[allow_internal_unstable(core_panic, panic_internals)]
#[stable(feature = "core", since = "1.6.0")]
macro_rules! panic {
() => (
$crate::panic!("explicit panic")
);
($msg:expr) => ({
const LOC: &$crate::panic::Location<'_> = &$crate::panic::Location::internal_constructor(
$crate::file!(),
$crate::line!(),
$crate::column!(),
);
$crate::panicking::panic($msg, LOC)
});
($msg:expr,) => (
$crate::panic!($msg)
);
($fmt:expr, $($arg:tt)+) => ({
const LOC: &$crate::panic::Location<'_> = &$crate::panic::Location::internal_constructor(
$crate::file!(),
$crate::line!(),
$crate::column!(),
);
$crate::panicking::panic_fmt($crate::format_args!($fmt, $($arg)+), LOC)
});
}

/// Asserts that two expressions are equal to each other (using [`PartialEq`]).
///
/// On panic, this macro will print the values of the expressions with their
18 changes: 12 additions & 6 deletions src/libcore/panic.rs
Original file line number Diff line number Diff line change
@@ -35,7 +35,7 @@ use crate::fmt;
pub struct PanicInfo<'a> {
payload: &'a (dyn Any + Send),
message: Option<&'a fmt::Arguments<'a>>,
location: Location<'a>,
location: &'a Location<'a>,
}

impl<'a> PanicInfo<'a> {
@@ -45,11 +45,16 @@ impl<'a> PanicInfo<'a> {
issue = "0")]
#[doc(hidden)]
#[inline]
pub fn internal_constructor(message: Option<&'a fmt::Arguments<'a>>,
location: Location<'a>)
-> Self {
pub fn internal_constructor(
message: Option<&'a fmt::Arguments<'a>>,
location: &'a Location<'a>,
) -> Self {
struct NoPayload;
PanicInfo { payload: &NoPayload, location, message }
PanicInfo {
location,
message,
payload: &NoPayload,
}
}

#[doc(hidden)]
@@ -162,6 +167,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> {
@@ -176,7 +182,7 @@ impl<'a> Location<'a> {
and related macros",
issue = "0")]
#[doc(hidden)]
pub fn internal_constructor(file: &'a str, line: u32, col: u32) -> Self {
pub const fn internal_constructor(file: &'a str, line: u32, col: u32) -> Self {
Location { file, line, col }
}

63 changes: 59 additions & 4 deletions src/libcore/panicking.rs
Original file line number Diff line number Diff line change
@@ -29,6 +29,7 @@
use crate::fmt;
use crate::panic::{Location, PanicInfo};

#[cfg(bootstrap)]
#[cold]
// never inline unless panic_immediate_abort to avoid code
// bloat at the call sites as much as possible
@@ -49,6 +50,27 @@ pub fn panic(expr_file_line_col: &(&'static str, &'static str, u32, u32)) -> ! {
panic_fmt(fmt::Arguments::new_v1(&[expr], &[]), &(file, line, col))
}

#[cfg(not(bootstrap))]
#[cold]
// never inline unless panic_immediate_abort to avoid code
// bloat at the call sites as much as possible
#[cfg_attr(not(feature="panic_immediate_abort"),inline(never))]
#[lang = "panic"]
pub fn panic(expr: &str, location: &Location<'_>) -> ! {
if cfg!(feature = "panic_immediate_abort") {
unsafe { super::intrinsics::abort() }
}

// Use Arguments::new_v1 instead of format_args!("{}", expr) to potentially
// reduce size overhead. The format_args! macro uses str's Display trait to
// write expr, which calls Formatter::pad, which must accommodate string
// truncation and padding (even though none is used here). Using
// Arguments::new_v1 may allow the compiler to omit Formatter::pad from the
// output binary, saving up to a few kilobytes.
panic_fmt(fmt::Arguments::new_v1(&[expr], &[]), location)
}

#[cfg(bootstrap)]
#[cold]
#[cfg_attr(not(feature="panic_immediate_abort"),inline(never))]
#[lang = "panic_bounds_check"]
@@ -62,6 +84,22 @@ fn panic_bounds_check(file_line_col: &(&'static str, u32, u32),
len, index), file_line_col)
}

#[cfg(not(bootstrap))]
#[cold]
#[cfg_attr(not(feature="panic_immediate_abort"),inline(never))]
#[lang = "panic_bounds_check"]
fn panic_bounds_check(location: &Location<'_>, index: usize, len: usize) -> ! {
if cfg!(feature = "panic_immediate_abort") {
unsafe { super::intrinsics::abort() }
}

panic_fmt(
format_args!("index out of bounds: the len is {} but the index is {}", len, index),
location
)
}

#[cfg(bootstrap)]
#[cold]
#[cfg_attr(not(feature="panic_immediate_abort"),inline(never))]
#[cfg_attr( feature="panic_immediate_abort" ,inline)]
@@ -77,9 +115,26 @@ pub fn panic_fmt(fmt: fmt::Arguments<'_>, file_line_col: &(&'static str, u32, u3
}

let (file, line, col) = *file_line_col;
let pi = PanicInfo::internal_constructor(
Some(&fmt),
Location::internal_constructor(file, line, col),
);
let location = Location::internal_constructor(file, line, col);
let pi = PanicInfo::internal_constructor(Some(&fmt), &location);
unsafe { panic_impl(&pi) }
}

#[cfg(not(bootstrap))]
#[cold]
#[cfg_attr(not(feature="panic_immediate_abort"),inline(never))]
#[cfg_attr( feature="panic_immediate_abort" ,inline)]
pub fn panic_fmt(fmt: fmt::Arguments<'_>, location: &Location<'_>) -> ! {
if cfg!(feature = "panic_immediate_abort") {
unsafe { super::intrinsics::abort() }
}

// NOTE This function never crosses the FFI boundary; it's a Rust-to-Rust call
extern "Rust" {
#[lang = "panic_impl"]
fn panic_impl(pi: &PanicInfo<'_>) -> !;
}

let pi = PanicInfo::internal_constructor(Some(&fmt), location);
unsafe { panic_impl(&pi) }
}
1 change: 1 addition & 0 deletions src/librustc/middle/lang_items.rs
Original file line number Diff line number Diff line change
@@ -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;
6 changes: 6 additions & 0 deletions src/librustc/query/mod.rs
Original file line number Diff line number Diff line change
@@ -466,6 +466,12 @@ rustc_queries! {
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" }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a span, but a position.

}
}

TypeChecking {
10 changes: 10 additions & 0 deletions src/librustc/ty/query/keys.rs
Original file line number Diff line number Diff line change
@@ -208,3 +208,13 @@ impl<'tcx, T> Key for Canonical<'tcx, T> {
DUMMY_SP
}
}

impl Key for (Symbol, u32, u32) {
fn query_crate(&self) -> CrateNum {
LOCAL_CRATE
}

fn default_span(&self, _tcx: TyCtxt<'_>) -> Span {
DUMMY_SP
}
}
31 changes: 0 additions & 31 deletions src/librustc_codegen_llvm/builder.rs
Original file line number Diff line number Diff line change
@@ -23,7 +23,6 @@ use std::ffi::CStr;
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]
@@ -1067,36 +1066,6 @@ impl StaticBuilderMethods for Builder<'a, 'll, 'tcx> {
// Forward to the `get_static` method of `CodegenCx`
self.cx().get_static(def_id)
}

fn static_panic_msg(
&mut self,
msg: Option<Symbol>,
filename: Symbol,
line: Self::Value,
col: Self::Value,
kind: &str,
) -> Self::Value {
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);

let filename = self.const_str_slice(filename);

let with_msg_components;
let without_msg_components;

let components = if let Some(msg) = msg {
let msg = self.const_str_slice(msg);
with_msg_components = [msg, filename, line, col];
&with_msg_components as &[_]
} else {
without_msg_components = [filename, line, col];
&without_msg_components as &[_]
};

let struct_ = self.const_struct(&components, false);
self.static_addr_of(struct_, align, Some(kind))
}
}

impl Builder<'a, 'll, 'tcx> {
25 changes: 7 additions & 18 deletions src/librustc_codegen_llvm/common.rs
Original file line number Diff line number Diff line change
@@ -3,7 +3,6 @@
//! Code that is useful in various codegen modules.

use crate::llvm::{self, True, False, Bool, BasicBlock, OperandBundleDef, ConstantInt};
use crate::abi;
use crate::consts;
use crate::type_::Type;
use crate::type_of::LayoutLlvmExt;
@@ -96,16 +95,6 @@ impl BackendTypes for CodegenCx<'ll, 'tcx> {
}

impl CodegenCx<'ll, 'tcx> {
pub fn const_fat_ptr(
&self,
ptr: &'ll Value,
meta: &'ll Value
) -> &'ll Value {
assert_eq!(abi::FAT_PTR_ADDR, 0);
assert_eq!(abi::FAT_PTR_EXTRA, 1);
self.const_struct(&[ptr, meta], false)
}

pub fn const_array(&self, ty: &'ll Type, elts: &[&'ll Value]) -> &'ll Value {
unsafe {
return llvm::LLVMConstArray(ty, elts.as_ptr(), elts.len() as c_uint);
@@ -150,13 +139,6 @@ impl CodegenCx<'ll, 'tcx> {
}
}

pub fn const_str_slice(&self, s: Symbol) -> &'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)));
self.const_fat_ptr(cs, self.const_usize(len as u64))
}

pub fn const_get_elt(&self, v: &'ll Value, idx: u64) -> &'ll Value {
unsafe {
assert_eq!(idx as c_uint as u64, idx);
@@ -237,6 +219,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],
Loading