Skip to content
Draft
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: 0 additions & 10 deletions compiler/rustc_borrowck/src/type_check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1046,16 +1046,6 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
}
}

&Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, ty) => {
let trait_ref =
ty::TraitRef::new(tcx, tcx.require_lang_item(LangItem::Sized, span), [ty]);

self.prove_trait_ref(
trait_ref,
location.to_locations(),
ConstraintCategory::SizedBound,
);
}
&Rvalue::NullaryOp(NullOp::ContractChecks, _) => {}
&Rvalue::NullaryOp(NullOp::UbChecks, _) => {}

Expand Down
4 changes: 0 additions & 4 deletions compiler/rustc_codegen_cranelift/example/example.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,6 @@ pub fn debug_tuple() -> DebugTuple {
DebugTuple(())
}

pub fn size_of<T>() -> usize {
intrinsics::size_of::<T>()
}

pub fn use_size_of() -> usize {
size_of::<u64>()
}
Expand Down
24 changes: 21 additions & 3 deletions compiler/rustc_codegen_cranelift/example/mini_core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
extern_types,
decl_macro,
rustc_attrs,
rustc_private,
transparent_unions,
auto_traits,
freeze_impls,
Expand Down Expand Up @@ -594,7 +595,7 @@ impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Box<U>> for Box<T> {}
impl<T> Box<T> {
pub fn new(val: T) -> Box<T> {
unsafe {
let size = intrinsics::size_of::<T>();
let size = size_of::<T>();
let ptr = libc::malloc(size);
intrinsics::copy(&val as *const T as *const u8, ptr, size);
Box(Unique { pointer: NonNull(ptr as *const T), _marker: PhantomData }, Global)
Expand Down Expand Up @@ -646,11 +647,11 @@ pub mod intrinsics {
#[rustc_intrinsic]
pub fn abort() -> !;
#[rustc_intrinsic]
pub fn size_of<T>() -> usize;
pub const fn size_of<T>() -> usize;
#[rustc_intrinsic]
pub unsafe fn size_of_val<T: ?::Sized>(val: *const T) -> usize;
#[rustc_intrinsic]
pub fn align_of<T>() -> usize;
pub const fn align_of<T>() -> usize;
#[rustc_intrinsic]
pub unsafe fn align_of_val<T: ?::Sized>(val: *const T) -> usize;
#[rustc_intrinsic]
Expand Down Expand Up @@ -715,6 +716,23 @@ impl<T> Index<usize> for [T] {
}
}

pub const fn size_of<T>() -> usize {
const { intrinsics::size_of::<T>() }
}

pub const fn align_of<T>() -> usize {
const { intrinsics::align_of::<T>() }
}

trait SizedTypeProperties: Sized {
#[lang = "mem_size_const"]
const SIZE: usize = intrinsics::size_of::<Self>();

#[lang = "mem_align_const"]
const ALIGN: usize = intrinsics::align_of::<Self>();
}
impl<T> SizedTypeProperties for T {}

extern "C" {
type VaListImpl;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,10 +109,10 @@ fn start<T: Termination + 'static>(
puts(*argv as *const i8);
}
unsafe {
puts(*((argv as usize + intrinsics::size_of::<*const u8>()) as *const *const i8));
puts(*((argv as usize + size_of::<*const u8>()) as *const *const i8));
}
unsafe {
puts(*((argv as usize + 2 * intrinsics::size_of::<*const u8>()) as *const *const i8));
puts(*((argv as usize + 2 * size_of::<*const u8>()) as *const *const i8));
}
}

Expand Down Expand Up @@ -213,8 +213,8 @@ fn main() {
assert_eq!(intrinsics::size_of_val(a) as u8, 16);
assert_eq!(intrinsics::size_of_val(&0u32) as u8, 4);

assert_eq!(intrinsics::align_of::<u16>() as u8, 2);
assert_eq!(intrinsics::align_of_val(&a) as u8, intrinsics::align_of::<&str>() as u8);
assert_eq!(align_of::<u16>() as u8, 2);
assert_eq!(intrinsics::align_of_val(&a) as u8, align_of::<&str>() as u8);

let u8_needs_drop = const { intrinsics::needs_drop::<u8>() };
assert!(!u8_needs_drop);
Expand Down
2 changes: 0 additions & 2 deletions compiler/rustc_codegen_cranelift/src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -840,8 +840,6 @@ fn codegen_stmt<'tcx>(fx: &mut FunctionCx<'_, '_, 'tcx>, cur_block: Block, stmt:
assert!(lval.layout().ty.is_sized(fx.tcx, fx.typing_env()));
let layout = fx.layout_of(fx.monomorphize(ty));
let val = match null_op {
NullOp::SizeOf => layout.size.bytes(),
NullOp::AlignOf => layout.align.bytes(),
NullOp::OffsetOf(fields) => fx
.tcx
.offset_of_subfield(
Expand Down
10 changes: 0 additions & 10 deletions compiler/rustc_codegen_ssa/src/mir/rvalue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -611,16 +611,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
let ty = self.monomorphize(ty);
let layout = bx.cx().layout_of(ty);
let val = match null_op {
mir::NullOp::SizeOf => {
assert!(bx.cx().type_is_sized(ty));
let val = layout.size.bytes();
bx.cx().const_usize(val)
}
mir::NullOp::AlignOf => {
assert!(bx.cx().type_is_sized(ty));
let val = layout.align.bytes();
bx.cx().const_usize(val)
}
mir::NullOp::OffsetOf(fields) => {
let val = bx
.tcx()
Expand Down
6 changes: 1 addition & 5 deletions compiler/rustc_const_eval/src/check_consts/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -646,11 +646,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
Rvalue::Cast(_, _, _) => {}

Rvalue::NullaryOp(
NullOp::SizeOf
| NullOp::AlignOf
| NullOp::OffsetOf(_)
| NullOp::UbChecks
| NullOp::ContractChecks,
NullOp::OffsetOf(_) | NullOp::UbChecks | NullOp::ContractChecks,
_,
) => {}
Rvalue::ShallowInitBox(_, _) => {}
Expand Down
18 changes: 18 additions & 0 deletions compiler/rustc_const_eval/src/interpret/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,24 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
let b_ty = self.read_type_id(&args[1])?;
self.write_scalar(Scalar::from_bool(a_ty == b_ty), dest)?;
}
sym::size_of => {
let tp_ty = instance.args.type_at(0);
let layout = self.layout_of(tp_ty)?;
if !layout.is_sized() {
span_bug!(self.cur_span(), "unsized type for `size_of`");
}
let val = layout.size.bytes();
self.write_scalar(Scalar::from_target_usize(val, self), dest)?;
}
sym::align_of => {
let tp_ty = instance.args.type_at(0);
let layout = self.layout_of(tp_ty)?;
if !layout.is_sized() {
span_bug!(self.cur_span(), "unsized type for `align_of`");
}
let val = layout.align.bytes();
self.write_scalar(Scalar::from_target_usize(val, self), dest)?;
}
sym::variant_count => {
let tp_ty = instance.args.type_at(0);
let ty = match tp_ty.kind() {
Expand Down
14 changes: 0 additions & 14 deletions compiler/rustc_const_eval/src/interpret/operator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -517,20 +517,6 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
let usize_layout = || self.layout_of(self.tcx.types.usize).unwrap();

interp_ok(match null_op {
SizeOf => {
if !layout.is_sized() {
span_bug!(self.cur_span(), "unsized type for `NullaryOp::SizeOf`");
}
let val = layout.size.bytes();
ImmTy::from_uint(val, usize_layout())
}
AlignOf => {
if !layout.is_sized() {
span_bug!(self.cur_span(), "unsized type for `NullaryOp::AlignOf`");
}
let val = layout.align.bytes();
ImmTy::from_uint(val, usize_layout())
}
OffsetOf(fields) => {
let val =
self.tcx.offset_of_subfield(self.typing_env, layout, fields.iter()).bytes();
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_hir/src/lang_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,8 @@ language_item_table! {
MetaSized, sym::meta_sized, meta_sized_trait, Target::Trait, GenericRequirement::Exact(0);
PointeeSized, sym::pointee_sized, pointee_sized_trait, Target::Trait, GenericRequirement::Exact(0);
Unsize, sym::unsize, unsize_trait, Target::Trait, GenericRequirement::Minimum(1);
AlignOf, sym::mem_align_const, align_const, Target::AssocConst, GenericRequirement::Exact(0);
SizeOf, sym::mem_size_const, size_const, Target::AssocConst, GenericRequirement::Exact(0);
/// Trait injected by `#[derive(PartialEq)]`, (i.e. "Partial EQ").
StructuralPeq, sym::structural_peq, structural_peq_trait, Target::Trait, GenericRequirement::None;
Copy, sym::copy, copy_trait, Target::Trait, GenericRequirement::Exact(0);
Expand Down
2 changes: 0 additions & 2 deletions compiler/rustc_middle/src/mir/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1092,8 +1092,6 @@ impl<'tcx> Debug for Rvalue<'tcx> {
NullaryOp(ref op, ref t) => {
let t = with_no_trimmed_paths!(format!("{}", t));
match op {
NullOp::SizeOf => write!(fmt, "SizeOf({t})"),
NullOp::AlignOf => write!(fmt, "AlignOf({t})"),
NullOp::OffsetOf(fields) => write!(fmt, "OffsetOf({t}, {fields:?})"),
NullOp::UbChecks => write!(fmt, "UbChecks()"),
NullOp::ContractChecks => write!(fmt, "ContractChecks()"),
Expand Down
6 changes: 2 additions & 4 deletions compiler/rustc_middle/src/mir/statement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -782,9 +782,7 @@ impl<'tcx> Rvalue<'tcx> {
op.ty(tcx, arg_ty)
}
Rvalue::Discriminant(ref place) => place.ty(local_decls, tcx).ty.discriminant_ty(tcx),
Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(..), _) => {
tcx.types.usize
}
Rvalue::NullaryOp(NullOp::OffsetOf(..), _) => tcx.types.usize,
Rvalue::NullaryOp(NullOp::ContractChecks, _)
| Rvalue::NullaryOp(NullOp::UbChecks, _) => tcx.types.bool,
Rvalue::Aggregate(ref ak, ref ops) => match **ak {
Expand Down Expand Up @@ -853,7 +851,7 @@ impl BorrowKind {
impl<'tcx> NullOp<'tcx> {
pub fn ty(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
match self {
NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(_) => tcx.types.usize,
NullOp::OffsetOf(_) => tcx.types.usize,
NullOp::UbChecks | NullOp::ContractChecks => tcx.types.bool,
}
}
Expand Down
4 changes: 0 additions & 4 deletions compiler/rustc_middle/src/mir/syntax.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1559,10 +1559,6 @@ pub enum AggregateKind<'tcx> {

#[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)]
pub enum NullOp<'tcx> {
/// Returns the size of a value of that type
SizeOf,
/// Returns the minimum alignment of a type
AlignOf,
/// Returns the offset of a field
OffsetOf(&'tcx List<(VariantIdx, FieldIdx)>),
/// Returns whether we should perform some UB-checking at runtime.
Expand Down
33 changes: 17 additions & 16 deletions compiler/rustc_mir_build/src/builder/expr/as_rvalue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,21 +126,22 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
let tcx = this.tcx;
let source_info = this.source_info(expr_span);

let size = this.temp(tcx.types.usize, expr_span);
this.cfg.push_assign(
block,
source_info,
size,
Rvalue::NullaryOp(NullOp::SizeOf, value_ty),
);
let size = tcx.require_lang_item(LangItem::SizeOf, expr_span);
let size = Const::from_unevaluated(tcx, size).instantiate(tcx, &[value_ty.into()]);
let size = Operand::Constant(Box::new(ConstOperand {
span: expr_span,
user_ty: None,
const_: size,
}));

let align = this.temp(tcx.types.usize, expr_span);
this.cfg.push_assign(
block,
source_info,
align,
Rvalue::NullaryOp(NullOp::AlignOf, value_ty),
);
let align = tcx.require_lang_item(LangItem::AlignOf, expr_span);
let align =
Const::from_unevaluated(tcx, align).instantiate(tcx, &[value_ty.into()]);
let align = Operand::Constant(Box::new(ConstOperand {
span: expr_span,
user_ty: None,
const_: align,
}));

// malloc some memory of suitable size and align:
let exchange_malloc = Operand::function_handle(
Expand All @@ -157,8 +158,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
TerminatorKind::Call {
func: exchange_malloc,
args: [
Spanned { node: Operand::Move(size), span: DUMMY_SP },
Spanned { node: Operand::Move(align), span: DUMMY_SP },
Spanned { node: size, span: DUMMY_SP },
Spanned { node: align, span: DUMMY_SP },
]
.into(),
destination: storage,
Expand Down
6 changes: 1 addition & 5 deletions compiler/rustc_mir_dataflow/src/move_paths/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -411,11 +411,7 @@ impl<'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> MoveDataBuilder<'a, 'tcx, F> {
| Rvalue::RawPtr(..)
| Rvalue::Discriminant(..)
| Rvalue::NullaryOp(
NullOp::SizeOf
| NullOp::AlignOf
| NullOp::OffsetOf(..)
| NullOp::UbChecks
| NullOp::ContractChecks,
NullOp::OffsetOf(..) | NullOp::UbChecks | NullOp::ContractChecks,
_,
) => {}
}
Expand Down
17 changes: 11 additions & 6 deletions compiler/rustc_mir_transform/src/check_alignment.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use rustc_abi::Align;
use rustc_hir::LangItem;
use rustc_index::IndexVec;
use rustc_middle::mir::interpret::Scalar;
use rustc_middle::mir::visit::PlaceContext;
Expand Down Expand Up @@ -59,10 +60,14 @@ fn insert_alignment_check<'tcx>(
stmts.push(Statement::new(source_info, StatementKind::Assign(Box::new((addr, rvalue)))));

// Get the alignment of the pointee
let alignment =
local_decls.push(LocalDecl::with_source_info(tcx.types.usize, source_info)).into();
let rvalue = Rvalue::NullaryOp(NullOp::AlignOf, pointee_ty);
stmts.push(Statement::new(source_info, StatementKind::Assign(Box::new((alignment, rvalue)))));
let align_def_id = tcx.require_lang_item(LangItem::AlignOf, source_info.span);
let align_const =
Const::from_unevaluated(tcx, align_def_id).instantiate(tcx, &[pointee_ty.into()]);
let alignment = Operand::Constant(Box::new(ConstOperand {
span: source_info.span,
user_ty: None,
const_: align_const,
}));

// Subtract 1 from the alignment to get the alignment mask
let alignment_mask =
Expand All @@ -76,7 +81,7 @@ fn insert_alignment_check<'tcx>(
source_info,
StatementKind::Assign(Box::new((
alignment_mask,
Rvalue::BinaryOp(BinOp::Sub, Box::new((Operand::Copy(alignment), one))),
Rvalue::BinaryOp(BinOp::Sub, Box::new((alignment.clone(), one))),
))),
));

Expand Down Expand Up @@ -141,7 +146,7 @@ fn insert_alignment_check<'tcx>(
PointerCheck {
cond: Operand::Copy(is_ok),
assert_kind: Box::new(AssertKind::MisalignedPointerDereference {
required: Operand::Copy(alignment),
required: alignment,
found: Operand::Copy(addr),
}),
}
Expand Down
33 changes: 13 additions & 20 deletions compiler/rustc_mir_transform/src/check_null.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use rustc_hir::LangItem;
use rustc_index::IndexVec;
use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext};
use rustc_middle::mir::*;
Expand Down Expand Up @@ -62,35 +63,27 @@ fn insert_null_check<'tcx>(
Operand::Constant(Box::new(ConstOperand {
span: source_info.span,
user_ty: None,
const_: Const::Val(ConstValue::from_bool(true), tcx.types.bool),
const_: Const::from_bool(tcx, true),
}))
}
// Other usages of null pointers only are UB if the pointee is not a ZST.
_ => {
let rvalue = Rvalue::NullaryOp(NullOp::SizeOf, pointee_ty);
let sizeof_pointee =
local_decls.push(LocalDecl::with_source_info(tcx.types.usize, source_info)).into();
stmts.push(Statement::new(
source_info,
StatementKind::Assign(Box::new((sizeof_pointee, rvalue))),
));
let size_of = tcx.require_lang_item(LangItem::SizeOf, source_info.span);
let size_of = Operand::Constant(Box::new(ConstOperand {
span: source_info.span,
user_ty: None,
const_: Const::from_unevaluated(tcx, size_of)
.instantiate(tcx, &[pointee_ty.into()]),
}));

// Check that the pointee is not a ZST.
let is_pointee_not_zst =
let pointee_should_be_checked =
local_decls.push(LocalDecl::with_source_info(tcx.types.bool, source_info)).into();
let rvalue = Rvalue::BinaryOp(BinOp::Ne, Box::new((size_of, zero.clone())));
stmts.push(Statement::new(
source_info,
StatementKind::Assign(Box::new((
is_pointee_not_zst,
Rvalue::BinaryOp(
BinOp::Ne,
Box::new((Operand::Copy(sizeof_pointee), zero.clone())),
),
))),
StatementKind::Assign(Box::new((pointee_should_be_checked, rvalue))),
));

// Pointer needs to be checked only if pointee is not a ZST.
Operand::Copy(is_pointee_not_zst)
Operand::Copy(pointee_should_be_checked.into())
}
};

Expand Down
Loading
Loading