Skip to content
Merged
Show file tree
Hide file tree
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
10 changes: 10 additions & 0 deletions compiler/rustc_codegen_llvm/src/intrinsic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -517,6 +517,16 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
return Ok(());
}

sym::cheri_address_get => {
let (size, _) = tcx.types.usize.int_size_and_signed(self.tcx);
let width = size.bits();

let arg = args[0].immediate();

let llty = self.type_ix(width);
self.call_intrinsic(format!("llvm.cheri.cap.address.get.i{width}"), &[llty], &[arg])
}

_ if name.as_str().starts_with("simd_") => {
// Unpack non-power-of-2 #[repr(packed, simd)] arguments.
// This gives them the expected layout of a regular #[repr(simd)] vector.
Expand Down
5 changes: 5 additions & 0 deletions compiler/rustc_const_eval/src/const_eval/machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,11 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> {
// not the optimization stage.)
sym::is_val_statically_known => ecx.write_scalar(Scalar::from_bool(false), dest)?,

sym::cheri_without_provenance => {
let addr = ecx.read_scalar(&args[0])?.to_target_usize(ecx)?;
ecx.write_pointer(Pointer::without_provenance(addr), dest)?
}

// We handle these here since Miri does not want to have them.
sym::assert_inhabited
| sym::assert_zero_valid
Expand Down
11 changes: 10 additions & 1 deletion compiler/rustc_hir_analysis/src/check/intrinsic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,9 @@ fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -> hi
| sym::round_ties_even_f32
| sym::round_ties_even_f64
| sym::round_ties_even_f128
| sym::const_eval_select => hir::Safety::Safe,
| sym::const_eval_select
| sym::cheri_address_get
| sym::cheri_without_provenance => hir::Safety::Safe,
_ => hir::Safety::Unsafe,
};

Expand Down Expand Up @@ -664,6 +666,13 @@ pub(crate) fn check_intrinsic_type(
| sym::atomic_umin => (1, 1, vec![Ty::new_mut_ptr(tcx, param(0)), param(0)], param(0)),
sym::atomic_fence | sym::atomic_singlethreadfence => (0, 1, Vec::new(), tcx.types.unit),

// CHERI-specific intrinsics
sym::cheri_without_provenance => {
(1, 0, vec![tcx.types.usize], Ty::new_mut_ptr(tcx, param(0)))
}
sym::cheri_address_get => {
(0, 0, vec![Ty::new_imm_ptr(tcx, tcx.types.unit)], tcx.types.usize)
}
other => {
tcx.dcx().emit_err(UnrecognizedIntrinsicFunction { span, name: other });
return;
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -641,6 +641,9 @@ symbols! {
char,
char_is_ascii,
char_to_digit,
cheri,
cheri_address_get,
cheri_without_provenance,
child_id,
child_kill,
client,
Expand Down
14 changes: 14 additions & 0 deletions library/core/src/intrinsics/cheri.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//! Some intrinsics specific to CHERI systems.

/// Create an pointer without provenance metadata from the given value.
#[inline]
#[rustc_intrinsic]
#[rustc_nounwind]
#[rustc_intrinsic_const_stable_indirect]
pub const fn cheri_without_provenance<T>(value: usize) -> *mut T;

/// Retrieve the address of the pointer.
#[inline]
#[rustc_intrinsic]
#[rustc_nounwind]
pub fn cheri_address_get(ptr: *const ()) -> usize;
3 changes: 3 additions & 0 deletions library/core/src/intrinsics/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ pub mod fallback;
pub mod mir;
pub mod simd;

#[cfg(target_family = "cheri")]
pub mod cheri;

// These imports are used for simplifying intra-doc links
#[allow(unused_imports)]
#[cfg(all(target_has_atomic = "8", target_has_atomic = "32", target_has_atomic = "ptr"))]
Expand Down
23 changes: 16 additions & 7 deletions library/core/src/ptr/const_ptr.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use super::*;
use crate::cmp::Ordering::{Equal, Greater, Less};
use crate::intrinsics::const_eval_select;
use crate::mem::{self, SizedTypeProperties};
use crate::mem::SizedTypeProperties;
use crate::slice::{self, SliceIndex};

impl<T: PointeeSized> *const T {
Expand Down Expand Up @@ -172,12 +172,21 @@ impl<T: PointeeSized> *const T {
#[inline(always)]
#[stable(feature = "strict_provenance", since = "1.84.0")]
pub fn addr(self) -> usize {
// A pointer-to-integer transmute currently has exactly the right semantics: it returns the
// address without exposing the provenance. Note that this is *not* a stable guarantee about
// transmute semantics, it relies on sysroot crates having special status.
// SAFETY: Pointer-to-integer transmutes are valid (if you are okay with losing the
// provenance).
unsafe { mem::transmute(self.cast::<()>()) }

#[cfg(target_family = "cheri")]
{
crate::intrinsics::cheri::cheri_address_get(self.cast::<()>())
}

#[cfg(not(target_family = "cheri"))]
{
// A pointer-to-integer transmute currently has exactly the right semantics: it returns the
// address without exposing the provenance. Note that this is *not* a stable guarantee about
// transmute semantics, it relies on sysroot crates having special status.
// SAFETY: Pointer-to-integer transmutes are valid (if you are okay with losing the
// provenance).
unsafe { crate::mem::transmute(self.cast::<()>()) }
}
}

/// Exposes the ["provenance"][crate::ptr#provenance] part of the pointer for future use in
Expand Down
20 changes: 14 additions & 6 deletions library/core/src/ptr/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -915,12 +915,20 @@ pub const fn dangling<T>() -> *const T {
#[stable(feature = "strict_provenance", since = "1.84.0")]
#[rustc_const_stable(feature = "strict_provenance", since = "1.84.0")]
pub const fn without_provenance_mut<T>(addr: usize) -> *mut T {
// An int-to-pointer transmute currently has exactly the intended semantics: it creates a
// pointer without provenance. Note that this is *not* a stable guarantee about transmute
// semantics, it relies on sysroot crates having special status.
// SAFETY: every valid integer is also a valid pointer (as long as you don't dereference that
// pointer).
unsafe { mem::transmute(addr) }
#[cfg(target_family = "cheri")]
{
crate::intrinsics::cheri::cheri_without_provenance(addr)
}

#[cfg(not(target_family = "cheri"))]
{
// An int-to-pointer transmute currently has exactly the intended semantics: it creates a
// pointer without provenance. Note that this is *not* a stable guarantee about transmute
// semantics, it relies on sysroot crates having special status.
// SAFETY: every valid integer is also a valid pointer (as long as you don't dereference that
// pointer).
unsafe { mem::transmute(addr) }
}
}

/// Creates a new pointer that is dangling, but non-null and well-aligned.
Expand Down
22 changes: 15 additions & 7 deletions library/core/src/ptr/mut_ptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use super::*;
use crate::cmp::Ordering::{Equal, Greater, Less};
use crate::intrinsics::const_eval_select;
use crate::marker::PointeeSized;
use crate::mem::{self, SizedTypeProperties};
use crate::mem::SizedTypeProperties;
use crate::slice::{self, SliceIndex};

impl<T: PointeeSized> *mut T {
Expand Down Expand Up @@ -160,12 +160,20 @@ impl<T: PointeeSized> *mut T {
#[inline(always)]
#[stable(feature = "strict_provenance", since = "1.84.0")]
pub fn addr(self) -> usize {
// A pointer-to-integer transmute currently has exactly the right semantics: it returns the
// address without exposing the provenance. Note that this is *not* a stable guarantee about
// transmute semantics, it relies on sysroot crates having special status.
// SAFETY: Pointer-to-integer transmutes are valid (if you are okay with losing the
// provenance).
unsafe { mem::transmute(self.cast::<()>()) }
#[cfg(target_family = "cheri")]
{
crate::intrinsics::cheri::cheri_address_get(self.cast::<()>())
}

#[cfg(not(target_family = "cheri"))]
{
// A pointer-to-integer transmute currently has exactly the right semantics: it returns the
// address without exposing the provenance. Note that this is *not* a stable guarantee about
// transmute semantics, it relies on sysroot crates having special status.
// SAFETY: Pointer-to-integer transmutes are valid (if you are okay with losing the
// provenance).
unsafe { crate::mem::transmute(self.cast::<()>()) }
}
}

/// Exposes the ["provenance"][crate::ptr#provenance] part of the pointer for future use in
Expand Down
4 changes: 4 additions & 0 deletions src/tools/tidy/src/pal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ const EXCEPTION_PATHS: &[&str] = &[
"library/unwind",
"library/rtstartup", // Not sure what to do about this. magic stuff for mingw
"library/test", // Probably should defer to unstable `std::sys` APIs.
// With the addition of CHERI-like platforms, some CHERI-specific intrinsics must be added.
"library/core/src/intrinsics/mod.rs",
// With the addition of CHERI-specific intrinsics for CHERI-like platforms, `ptr` too must have platform specific code (to use those intrinsics).
"library/core/src/ptr",
// The `VaList` implementation must have platform specific code.
// The Windows implementation of a `va_list` is always a character
// pointer regardless of the target architecture. As a result,
Expand Down