Skip to content

Commit 86a47ee

Browse files
committed
add NullOp::FieldOffset & use it to lower unaligned_field_offset
1 parent a826fe7 commit 86a47ee

File tree

16 files changed

+80
-31
lines changed

16 files changed

+80
-31
lines changed

compiler/rustc_borrowck/src/type_check/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1633,7 +1633,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
16331633
| Rvalue::ThreadLocalRef(..)
16341634
| Rvalue::Len(..)
16351635
| Rvalue::Discriminant(..)
1636-
| Rvalue::NullaryOp(NullOp::OffsetOf(..), _) => {}
1636+
| Rvalue::NullaryOp(NullOp::OffsetOf(..) | NullOp::FieldOffset, _) => {}
16371637
}
16381638
}
16391639

compiler/rustc_codegen_ssa/src/mir/rvalue.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -626,6 +626,17 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
626626
.bytes();
627627
bx.cx().const_usize(val)
628628
}
629+
mir::NullOp::FieldOffset => {
630+
let &ty::Field(container, field_path) = ty.kind() else {
631+
bug!("expected `ty::Field`, but found {ty:?}")
632+
};
633+
let layout = bx.cx().layout_of(container);
634+
let val = bx
635+
.tcx()
636+
.offset_of_subfield(bx.typing_env(), layout, field_path.iter())
637+
.bytes();
638+
bx.cx().const_usize(val)
639+
}
629640
mir::NullOp::UbChecks => {
630641
let val = bx.tcx().sess.ub_checks();
631642
bx.cx().const_bool(val)

compiler/rustc_const_eval/src/check_consts/check.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -650,6 +650,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
650650
NullOp::SizeOf
651651
| NullOp::AlignOf
652652
| NullOp::OffsetOf(_)
653+
| NullOp::FieldOffset
653654
| NullOp::UbChecks
654655
| NullOp::ContractChecks,
655656
_,

compiler/rustc_const_eval/src/interpret/intrinsics.rs

Lines changed: 2 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@ use std::assert_matches::assert_matches;
77
use rustc_abi::{FieldIdx, HasDataLayout, Size};
88
use rustc_apfloat::ieee::{Double, Half, Quad, Single};
99
use rustc_middle::mir::interpret::{CTFE_ALLOC_SALT, read_target_uint, write_target_uint};
10-
use rustc_middle::mir::{self, BinOp, ConstValue, NonDivergingIntrinsic, NullOp};
10+
use rustc_middle::mir::{self, BinOp, ConstValue, NonDivergingIntrinsic};
1111
use rustc_middle::ty::layout::TyAndLayout;
1212
use rustc_middle::ty::{Ty, TyCtxt};
13-
use rustc_middle::{bug, err_inval, span_bug, ty};
13+
use rustc_middle::{bug, ty};
1414
use rustc_span::{Symbol, sym};
1515
use tracing::trace;
1616

@@ -638,8 +638,6 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
638638
rustc_apfloat::Round::NearestTiesToEven,
639639
)?,
640640

641-
sym::unaligned_field_offset => self.unaligned_field_offset(instance, dest)?,
642-
643641
// Unsupported intrinsic: skip the return_to_block below.
644642
_ => return interp_ok(false),
645643
}
@@ -649,25 +647,6 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
649647
interp_ok(true)
650648
}
651649

652-
fn unaligned_field_offset(
653-
&mut self,
654-
instance: ty::Instance<'tcx>,
655-
dest: &PlaceTy<'tcx, M::Provenance>,
656-
) -> InterpResult<'tcx, ()> {
657-
assert_eq!(instance.args.len(), 1);
658-
let ty = instance.args.type_at(0);
659-
match ty.kind() {
660-
&ty::Field(container, field_path) => {
661-
let offset = self.nullary_op(NullOp::OffsetOf(field_path), container)?;
662-
self.write_immediate(*offset, dest)
663-
}
664-
ty::Alias(..) | ty::Param(..) | ty::Placeholder(..) | ty::Infer(..) => {
665-
Err(err_inval!(TooGeneric)).into()
666-
}
667-
_ => span_bug!(self.cur_span(), "expected field representing type, found {ty}"),
668-
}
669-
}
670-
671650
pub(super) fn eval_nondiverging_intrinsic(
672651
&mut self,
673652
intrinsic: &NonDivergingIntrinsic<'tcx>,

compiler/rustc_const_eval/src/interpret/operator.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -536,6 +536,12 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
536536
self.tcx.offset_of_subfield(self.typing_env, layout, fields.iter()).bytes();
537537
ImmTy::from_uint(val, usize_layout())
538538
}
539+
FieldOffset => {
540+
let &ty::Field(container, field_path) = arg_ty.kind() else {
541+
span_bug!(self.cur_span(), "expected `ty::Field`, found {arg_ty:?}")
542+
};
543+
self.nullary_op(OffsetOf(field_path), container)?
544+
}
539545
UbChecks => ImmTy::from_bool(M::ub_checks(self)?, *self.tcx),
540546
ContractChecks => ImmTy::from_bool(M::contract_checks(self)?, *self.tcx),
541547
})

compiler/rustc_middle/src/mir/pretty.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1073,6 +1073,7 @@ impl<'tcx> Debug for Rvalue<'tcx> {
10731073
NullOp::SizeOf => write!(fmt, "SizeOf({t})"),
10741074
NullOp::AlignOf => write!(fmt, "AlignOf({t})"),
10751075
NullOp::OffsetOf(fields) => write!(fmt, "OffsetOf({t}, {fields:?})"),
1076+
NullOp::FieldOffset => write!(fmt, "FieldOffset({t})"),
10761077
NullOp::UbChecks => write!(fmt, "UbChecks()"),
10771078
NullOp::ContractChecks => write!(fmt, "ContractChecks()"),
10781079
}

compiler/rustc_middle/src/mir/statement.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -751,9 +751,10 @@ impl<'tcx> Rvalue<'tcx> {
751751
op.ty(tcx, arg_ty)
752752
}
753753
Rvalue::Discriminant(ref place) => place.ty(local_decls, tcx).ty.discriminant_ty(tcx),
754-
Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(..), _) => {
755-
tcx.types.usize
756-
}
754+
Rvalue::NullaryOp(
755+
NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(..) | NullOp::FieldOffset,
756+
_,
757+
) => tcx.types.usize,
757758
Rvalue::NullaryOp(NullOp::ContractChecks, _)
758759
| Rvalue::NullaryOp(NullOp::UbChecks, _) => tcx.types.bool,
759760
Rvalue::Aggregate(ref ak, ref ops) => match **ak {
@@ -822,7 +823,9 @@ impl BorrowKind {
822823
impl<'tcx> NullOp<'tcx> {
823824
pub fn ty(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
824825
match self {
825-
NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(_) => tcx.types.usize,
826+
NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(_) | NullOp::FieldOffset => {
827+
tcx.types.usize
828+
}
826829
NullOp::UbChecks | NullOp::ContractChecks => tcx.types.bool,
827830
}
828831
}

compiler/rustc_middle/src/mir/syntax.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1575,6 +1575,8 @@ pub enum NullOp<'tcx> {
15751575
AlignOf,
15761576
/// Returns the offset of a field
15771577
OffsetOf(FieldPath<'tcx>),
1578+
/// Returns the offset of the field represented by the type
1579+
FieldOffset,
15781580
/// Returns whether we should perform some UB-checking at runtime.
15791581
/// See the `ub_checks` intrinsic docs for details.
15801582
UbChecks,

compiler/rustc_mir_dataflow/src/move_paths/builder.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -420,6 +420,7 @@ impl<'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> MoveDataBuilder<'a, 'tcx, F> {
420420
NullOp::SizeOf
421421
| NullOp::AlignOf
422422
| NullOp::OffsetOf(..)
423+
| NullOp::FieldOffset
423424
| NullOp::UbChecks
424425
| NullOp::ContractChecks,
425426
_,

compiler/rustc_mir_transform/src/gvn.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -497,6 +497,16 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
497497
.tcx
498498
.offset_of_subfield(self.typing_env(), arg_layout, fields.iter())
499499
.bytes(),
500+
NullOp::FieldOffset => {
501+
let &ty::Field(container, field_path) = arg_ty.kind() else {
502+
bug!("expected `ty::Field`, found {arg_ty:?}")
503+
};
504+
let layout = self.ecx.layout_of(container).ok()?;
505+
self.ecx
506+
.tcx
507+
.offset_of_subfield(self.typing_env(), layout, field_path.iter())
508+
.bytes()
509+
}
500510
NullOp::UbChecks => return None,
501511
NullOp::ContractChecks => return None,
502512
};

0 commit comments

Comments
 (0)