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
2 changes: 1 addition & 1 deletion compiler/rustc_borrowck/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1563,7 +1563,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
self.consume_operand(location, (operand2, span), state);
}

Rvalue::NullaryOp(_op, _ty) => {
Rvalue::NullaryOp(_op) => {
// nullary ops take no dynamic input; no borrowck effect.
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,7 @@ impl<'a, 'tcx> LoanInvalidationsGenerator<'a, 'tcx> {
self.consume_operand(location, operand2);
}

Rvalue::NullaryOp(_op, _ty) => {}
Rvalue::NullaryOp(_op) => {}

Rvalue::Aggregate(_, operands) => {
for operand in operands {
Expand Down
6 changes: 2 additions & 4 deletions compiler/rustc_borrowck/src/type_check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1046,8 +1046,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
}
}

&Rvalue::NullaryOp(NullOp::ContractChecks, _) => {}
&Rvalue::NullaryOp(NullOp::UbChecks, _) => {}
&Rvalue::NullaryOp(NullOp::ContractChecks | NullOp::UbChecks) => {}

Rvalue::ShallowInitBox(_operand, ty) => {
let trait_ref =
Expand Down Expand Up @@ -1634,8 +1633,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
| Rvalue::BinaryOp(..)
| Rvalue::RawPtr(..)
| Rvalue::ThreadLocalRef(..)
| Rvalue::Discriminant(..)
| Rvalue::NullaryOp(NullOp::OffsetOf(..), _) => {}
| Rvalue::Discriminant(..) => {}
}
}

Expand Down
35 changes: 5 additions & 30 deletions compiler/rustc_codegen_cranelift/src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -829,40 +829,15 @@ fn codegen_stmt<'tcx>(fx: &mut FunctionCx<'_, '_, 'tcx>, cur_block: Block, stmt:
fx.bcx.ins().nop();
}
}
Rvalue::NullaryOp(ref null_op, ty) => {
Rvalue::NullaryOp(ref null_op) => {
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::OffsetOf(fields) => fx
.tcx
.offset_of_subfield(
ty::TypingEnv::fully_monomorphized(),
layout,
fields.iter(),
)
.bytes(),
NullOp::UbChecks => {
let val = fx.tcx.sess.ub_checks();
let val = CValue::by_val(
fx.bcx.ins().iconst(types::I8, i64::from(val)),
fx.layout_of(fx.tcx.types.bool),
);
lval.write_cvalue(fx, val);
return;
}
NullOp::ContractChecks => {
let val = fx.tcx.sess.contract_checks();
let val = CValue::by_val(
fx.bcx.ins().iconst(types::I8, i64::from(val)),
fx.layout_of(fx.tcx.types.bool),
);
lval.write_cvalue(fx, val);
return;
}
NullOp::UbChecks => fx.tcx.sess.ub_checks(),
NullOp::ContractChecks => fx.tcx.sess.contract_checks(),
};
let val = CValue::by_val(
fx.bcx.ins().iconst(fx.pointer_type, i64::try_from(val).unwrap()),
fx.layout_of(fx.tcx.types.usize),
fx.bcx.ins().iconst(types::I8, i64::from(val)),
fx.layout_of(fx.tcx.types.bool),
);
lval.write_cvalue(fx, val);
}
Expand Down
11 changes: 1 addition & 10 deletions compiler/rustc_codegen_ssa/src/mir/rvalue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -607,17 +607,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
}
}

mir::Rvalue::NullaryOp(ref null_op, ty) => {
let ty = self.monomorphize(ty);
let layout = bx.cx().layout_of(ty);
mir::Rvalue::NullaryOp(ref null_op) => {
let val = match null_op {
mir::NullOp::OffsetOf(fields) => {
let val = bx
.tcx()
.offset_of_subfield(bx.typing_env(), layout, fields.iter())
.bytes();
bx.cx().const_usize(val)
}
mir::NullOp::UbChecks => {
let val = bx.tcx().sess.ub_checks();
bx.cx().const_bool(val)
Expand Down
9 changes: 4 additions & 5 deletions compiler/rustc_const_eval/src/check_consts/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -645,10 +645,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {

Rvalue::Cast(_, _, _) => {}

Rvalue::NullaryOp(
NullOp::OffsetOf(_) | NullOp::UbChecks | NullOp::ContractChecks,
_,
) => {}
Rvalue::NullaryOp(NullOp::UbChecks | NullOp::ContractChecks) => {}
Rvalue::ShallowInitBox(_, _) => {}

Rvalue::UnaryOp(op, operand) => {
Expand Down Expand Up @@ -856,7 +853,9 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
}

// Intrinsics are language primitives, not regular calls, so treat them separately.
if let Some(intrinsic) = tcx.intrinsic(callee) {
if let Some(intrinsic) = tcx.intrinsic(callee)
&& intrinsic.name != sym::offset_of
{
if !tcx.is_const_fn(callee) {
// Non-const intrinsic.
self.check_op(ops::IntrinsicNonConst { name: intrinsic.name });
Expand Down
17 changes: 16 additions & 1 deletion compiler/rustc_const_eval/src/interpret/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ mod simd;

use std::assert_matches::assert_matches;

use rustc_abi::{FieldIdx, HasDataLayout, Size};
use rustc_abi::{FieldIdx, HasDataLayout, Size, VariantIdx};
use rustc_apfloat::ieee::{Double, Half, Quad, Single};
use rustc_middle::mir::interpret::{CTFE_ALLOC_SALT, read_target_uint, write_target_uint};
use rustc_middle::mir::{self, BinOp, ConstValue, NonDivergingIntrinsic};
Expand Down Expand Up @@ -174,6 +174,21 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
let val = layout.align.bytes();
self.write_scalar(Scalar::from_target_usize(val, self), dest)?;
}
sym::offset_of => {
let tp_ty = instance.args.type_at(0);

let u32_layout = self.layout_of(self.tcx.types.u32)?;
let variant = self.read_scalar(&args[0])?.to_bits(u32_layout.size)? as u32;
let field = self.read_scalar(&args[1])?.to_bits(u32_layout.size)? as usize;

let layout = self.layout_of(tp_ty)?;
let cx = ty::layout::LayoutCx::new(*self.tcx, self.typing_env);

let layout = layout.for_variant(&cx, VariantIdx::from_u32(variant));
let offset = layout.fields.offset(field).bytes();

self.write_scalar(Scalar::from_target_usize(offset, self), dest)?;
}
sym::variant_count => {
let tp_ty = instance.args.type_at(0);
let ty = match tp_ty.kind() {
Expand Down
17 changes: 2 additions & 15 deletions compiler/rustc_const_eval/src/interpret/operator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use rustc_apfloat::{Float, FloatConvert};
use rustc_middle::mir::NullOp;
use rustc_middle::mir::interpret::{InterpResult, PointerArithmetic, Scalar};
use rustc_middle::ty::layout::TyAndLayout;
use rustc_middle::ty::{self, FloatTy, ScalarInt, Ty};
use rustc_middle::ty::{self, FloatTy, ScalarInt};
use rustc_middle::{bug, mir, span_bug};
use rustc_span::sym;
use tracing::trace;
Expand Down Expand Up @@ -506,22 +506,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
}
}

pub fn nullary_op(
&self,
null_op: NullOp<'tcx>,
arg_ty: Ty<'tcx>,
) -> InterpResult<'tcx, ImmTy<'tcx, M::Provenance>> {
pub fn nullary_op(&self, null_op: NullOp) -> InterpResult<'tcx, ImmTy<'tcx, M::Provenance>> {
use rustc_middle::mir::NullOp::*;

let layout = self.layout_of(arg_ty)?;
let usize_layout = || self.layout_of(self.tcx.types.usize).unwrap();

interp_ok(match null_op {
OffsetOf(fields) => {
let val =
self.tcx.offset_of_subfield(self.typing_env, layout, fields.iter()).bytes();
ImmTy::from_uint(val, usize_layout())
}
UbChecks => ImmTy::from_bool(M::ub_checks(self)?, *self.tcx),
ContractChecks => ImmTy::from_bool(M::contract_checks(self)?, *self.tcx),
})
Expand Down
5 changes: 2 additions & 3 deletions compiler/rustc_const_eval/src/interpret/step.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,9 +203,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
self.write_immediate(*result, &dest)?;
}

NullaryOp(null_op, ty) => {
let ty = self.instantiate_from_current_frame_and_normalize_erasing_regions(ty)?;
let val = self.nullary_op(null_op, ty)?;
NullaryOp(null_op) => {
let val = self.nullary_op(null_op)?;
self.write_immediate(*val, &dest)?;
}

Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_hir/src/lang_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ language_item_table! {
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);
OffsetOf, sym::offset_of, offset_of, Target::Fn, GenericRequirement::Exact(1);
/// 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: 2 additions & 0 deletions compiler/rustc_hir_analysis/src/check/intrinsic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -> hi
| sym::minnumf128
| sym::mul_with_overflow
| sym::needs_drop
| sym::offset_of
| sym::powf16
| sym::powf32
| sym::powf64
Expand Down Expand Up @@ -287,6 +288,7 @@ pub(crate) fn check_intrinsic_type(
sym::size_of_val | sym::align_of_val => {
(1, 0, vec![Ty::new_imm_ptr(tcx, param(0))], tcx.types.usize)
}
sym::offset_of => (1, 0, vec![tcx.types.u32, tcx.types.u32], tcx.types.usize),
sym::rustc_peek => (1, 0, vec![param(0)], param(0)),
sym::caller_location => (0, 0, vec![], tcx.caller_location_ty()),
sym::assert_inhabited | sym::assert_zero_valid | sym::assert_mem_uninitialized_valid => {
Expand Down
15 changes: 5 additions & 10 deletions compiler/rustc_hir_typeck/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3837,10 +3837,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
fields: &[Ident],
expr: &'tcx hir::Expr<'tcx>,
) -> Ty<'tcx> {
let container = self.lower_ty(container).normalized;

let mut current_container = self.lower_ty(container).normalized;
let mut field_indices = Vec::with_capacity(fields.len());
let mut current_container = container;
let mut fields = fields.into_iter();

while let Some(&field) = fields.next() {
Expand Down Expand Up @@ -3928,7 +3926,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

// Save the index of all fields regardless of their visibility in case
// of error recovery.
field_indices.push((index, subindex));
field_indices.push((current_container, index, subindex));
current_container = field_ty;

continue;
Expand Down Expand Up @@ -3963,7 +3961,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

// Save the index of all fields regardless of their visibility in case
// of error recovery.
field_indices.push((FIRST_VARIANT, index));
field_indices.push((current_container, FIRST_VARIANT, index));
current_container = field_ty;

continue;
Expand All @@ -3984,7 +3982,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
);
}

field_indices.push((FIRST_VARIANT, index.into()));
field_indices.push((current_container, FIRST_VARIANT, index.into()));
current_container = field_ty;

continue;
Expand All @@ -3999,10 +3997,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
break;
}

self.typeck_results
.borrow_mut()
.offset_of_data_mut()
.insert(expr.hir_id, (container, field_indices));
self.typeck_results.borrow_mut().offset_of_data_mut().insert(expr.hir_id, field_indices);

self.tcx.types.usize
}
Expand Down
11 changes: 6 additions & 5 deletions compiler/rustc_hir_typeck/src/writeback.rs
Original file line number Diff line number Diff line change
Expand Up @@ -775,12 +775,13 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
assert_eq!(fcx_typeck_results.hir_owner, self.typeck_results.hir_owner);
let common_hir_owner = fcx_typeck_results.hir_owner;

for (local_id, &(container, ref indices)) in
fcx_typeck_results.offset_of_data().items_in_stable_order()
{
for (local_id, indices) in fcx_typeck_results.offset_of_data().items_in_stable_order() {
let hir_id = HirId { owner: common_hir_owner, local_id };
let container = self.resolve(container, &hir_id);
self.typeck_results.offset_of_data_mut().insert(hir_id, (container, indices.clone()));
let indices = indices
.iter()
.map(|&(ty, variant, field)| (self.resolve(ty, &hir_id), variant, field))
.collect();
self.typeck_results.offset_of_data_mut().insert(hir_id, indices);
}
}

Expand Down
12 changes: 12 additions & 0 deletions compiler/rustc_lint/src/unused.rs
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,18 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
hir::ExprKind::AddrOf(..) => Some("borrow"),
hir::ExprKind::OffsetOf(..) => Some("`offset_of` call"),
hir::ExprKind::Unary(..) => Some("unary operation"),
// The `offset_of` macro wraps its contents inside a `const` block.
hir::ExprKind::ConstBlock(block) => {
let body = cx.tcx.hir_body(block.body);
if let hir::ExprKind::Block(block, _) = body.value.kind
&& let Some(expr) = block.expr
&& let hir::ExprKind::OffsetOf(..) = expr.kind
{
Some("`offset_of` call")
} else {
None
}
}
_ => None,
};

Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/mir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -649,7 +649,7 @@ impl<'tcx> Body<'tcx> {
}

match rvalue {
Rvalue::NullaryOp(NullOp::UbChecks, _) => Some((tcx.sess.ub_checks() as u128, targets)),
Rvalue::NullaryOp(NullOp::UbChecks) => Some((tcx.sess.ub_checks() as u128, targets)),
Rvalue::Use(Operand::Constant(constant)) => {
let bits = eval_mono_const(constant)?;
Some((bits, targets))
Expand Down
12 changes: 4 additions & 8 deletions compiler/rustc_middle/src/mir/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1089,14 +1089,10 @@ impl<'tcx> Debug for Rvalue<'tcx> {
BinaryOp(ref op, box (ref a, ref b)) => write!(fmt, "{op:?}({a:?}, {b:?})"),
UnaryOp(ref op, ref a) => write!(fmt, "{op:?}({a:?})"),
Discriminant(ref place) => write!(fmt, "discriminant({place:?})"),
NullaryOp(ref op, ref t) => {
let t = with_no_trimmed_paths!(format!("{}", t));
match op {
NullOp::OffsetOf(fields) => write!(fmt, "OffsetOf({t}, {fields:?})"),
NullOp::UbChecks => write!(fmt, "UbChecks()"),
NullOp::ContractChecks => write!(fmt, "ContractChecks()"),
}
}
NullaryOp(ref op) => match op {
NullOp::UbChecks => write!(fmt, "UbChecks()"),
NullOp::ContractChecks => write!(fmt, "ContractChecks()"),
},
ThreadLocalRef(did) => ty::tls::with(|tcx| {
let muta = tcx.static_mutability(did).unwrap().prefix_str();
write!(fmt, "&/*tls*/ {}{}", muta, tcx.def_path_str(did))
Expand Down
13 changes: 6 additions & 7 deletions compiler/rustc_middle/src/mir/statement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -756,7 +756,7 @@ impl<'tcx> Rvalue<'tcx> {
_,
)
| Rvalue::BinaryOp(_, _)
| Rvalue::NullaryOp(_, _)
| Rvalue::NullaryOp(_)
| Rvalue::UnaryOp(_, _)
| Rvalue::Discriminant(_)
| Rvalue::Aggregate(_, _)
Expand Down Expand Up @@ -794,9 +794,9 @@ 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::OffsetOf(..), _) => tcx.types.usize,
Rvalue::NullaryOp(NullOp::ContractChecks, _)
| Rvalue::NullaryOp(NullOp::UbChecks, _) => tcx.types.bool,
Rvalue::NullaryOp(NullOp::ContractChecks) | Rvalue::NullaryOp(NullOp::UbChecks) => {
tcx.types.bool
}
Rvalue::Aggregate(ref ak, ref ops) => match **ak {
AggregateKind::Array(ty) => Ty::new_array(tcx, ty, ops.len() as u64),
AggregateKind::Tuple => {
Expand Down Expand Up @@ -860,10 +860,9 @@ impl BorrowKind {
}
}

impl<'tcx> NullOp<'tcx> {
pub fn ty(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
impl NullOp {
pub fn ty<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
match self {
NullOp::OffsetOf(_) => tcx.types.usize,
NullOp::UbChecks | NullOp::ContractChecks => tcx.types.bool,
}
}
Expand Down
6 changes: 2 additions & 4 deletions compiler/rustc_middle/src/mir/syntax.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1419,7 +1419,7 @@ pub enum Rvalue<'tcx> {
BinaryOp(BinOp, Box<(Operand<'tcx>, Operand<'tcx>)>),

/// Computes a value as described by the operation.
NullaryOp(NullOp<'tcx>, Ty<'tcx>),
NullaryOp(NullOp),

/// Exactly like `BinaryOp`, but less operands.
///
Expand Down Expand Up @@ -1562,9 +1562,7 @@ pub enum AggregateKind<'tcx> {
}

#[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)]
pub enum NullOp<'tcx> {
/// Returns the offset of a field
OffsetOf(&'tcx List<(VariantIdx, FieldIdx)>),
pub enum NullOp {
/// Returns whether we should perform some UB-checking at runtime.
/// See the `ub_checks` intrinsic docs for details.
UbChecks,
Expand Down
Loading
Loading