Skip to content

Commit 0319e13

Browse files
committed
add unaligned_field_offset intrinsic
1 parent b4901a8 commit 0319e13

File tree

7 files changed

+37
-4
lines changed

7 files changed

+37
-4
lines changed

compiler/rustc_const_eval/src/interpret/intrinsics.rs

Lines changed: 19 additions & 2 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};
10+
use rustc_middle::mir::{self, BinOp, ConstValue, NonDivergingIntrinsic, NullOp};
1111
use rustc_middle::ty::layout::TyAndLayout;
1212
use rustc_middle::ty::{Ty, TyCtxt};
13-
use rustc_middle::{bug, ty};
13+
use rustc_middle::{bug, err_inval, ty};
1414
use rustc_span::{Symbol, sym};
1515
use tracing::trace;
1616

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

640+
sym::unaligned_field_offset => self.unaligned_field_offset(instance, dest)?,
641+
640642
// Unsupported intrinsic: skip the return_to_block below.
641643
_ => return interp_ok(false),
642644
}
@@ -646,6 +648,21 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
646648
interp_ok(true)
647649
}
648650

651+
fn unaligned_field_offset(
652+
&mut self,
653+
instance: ty::Instance<'tcx>,
654+
dest: &PlaceTy<'tcx, M::Provenance>,
655+
) -> InterpResult<'tcx, ()> {
656+
assert_eq!(instance.args.len(), 1);
657+
match instance.args.type_at(0).kind() {
658+
&ty::Field(container, field_path) => {
659+
let offset = self.nullary_op(NullOp::OffsetOf(field_path), container)?;
660+
self.write_immediate(*offset, dest)
661+
}
662+
_ => Err(err_inval!(TooGeneric)).into(),
663+
}
664+
}
665+
649666
pub(super) fn eval_nondiverging_intrinsic(
650667
&mut self,
651668
intrinsic: &NonDivergingIntrinsic<'tcx>,

compiler/rustc_hir_analysis/src/check/intrinsic.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,8 @@ fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -> hi
140140
| sym::prefetch_write_data
141141
| sym::prefetch_read_instruction
142142
| sym::prefetch_write_instruction
143-
| sym::const_eval_select => hir::Safety::Safe,
143+
| sym::const_eval_select
144+
| sym::unaligned_field_offset => hir::Safety::Safe,
144145
_ => hir::Safety::Unsafe,
145146
};
146147

@@ -673,6 +674,8 @@ pub(crate) fn check_intrinsic_type(
673674
| sym::atomic_xor => (2, 1, vec![Ty::new_mut_ptr(tcx, param(0)), param(1)], param(0)),
674675
sym::atomic_fence | sym::atomic_singlethreadfence => (0, 1, Vec::new(), tcx.types.unit),
675676

677+
sym::unaligned_field_offset => (1, 0, Vec::new(), tcx.types.usize),
678+
676679
other => {
677680
tcx.dcx().emit_err(UnrecognizedIntrinsicFunction { span, name: other });
678681
return;

compiler/rustc_middle/src/ty/context.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3431,6 +3431,9 @@ impl<'tcx> TyCtxt<'tcx> {
34313431
pub fn intrinsic(self, def_id: impl IntoQueryParam<DefId> + Copy) -> Option<ty::IntrinsicDef> {
34323432
match self.def_kind(def_id) {
34333433
DefKind::Fn | DefKind::AssocFn => {}
3434+
DefKind::AssocConst
3435+
if self.is_lang_item(def_id.into_query_param(), LangItem::UnalignedFieldOFFSET) => {
3436+
}
34343437
_ => return None,
34353438
}
34363439
self.intrinsic_raw(def_id)

compiler/rustc_span/src/symbol.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2282,6 +2282,7 @@ symbols! {
22822282
u128_legacy_fn_min_value,
22832283
u128_legacy_mod,
22842284
ub_checks,
2285+
unaligned_field_offset,
22852286
unaligned_volatile_load,
22862287
unaligned_volatile_store,
22872288
unboxed_closures,

library/core/src/field.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ pub unsafe trait UnalignedField: Sized {
1919

2020
/// The offset of the field in bytes.
2121
#[lang = "UnalignedFieldOFFSET"]
22-
const OFFSET: usize;
22+
const OFFSET: usize = crate::intrinsics::unaligned_field_offset::<Self>();
2323
}
2424

2525
/// Type representing an aligned field of a `struct`.

library/core/src/intrinsics/mod.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3314,3 +3314,11 @@ pub unsafe fn va_arg<T: VaArgSafe>(ap: &mut VaListImpl<'_>) -> T;
33143314
#[rustc_intrinsic]
33153315
#[rustc_nounwind]
33163316
pub unsafe fn va_end(ap: &mut VaListImpl<'_>);
3317+
3318+
/// `offset_of!` for `UnalignedField` trait.
3319+
#[rustc_intrinsic_const_stable_indirect]
3320+
#[rustc_intrinsic]
3321+
#[lang = "unaligned_field_offset"]
3322+
#[unstable(feature = "field_projections", issue = "145383")]
3323+
#[rustc_const_unstable(feature = "field_projections", issue = "145383")]
3324+
pub const fn unaligned_field_offset<F: crate::field::UnalignedField>() -> usize;

library/core/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@
154154
#![feature(extern_types)]
155155
#![feature(f16)]
156156
#![feature(f128)]
157+
#![feature(field_projections)]
157158
#![feature(freeze_impls)]
158159
#![feature(fundamental)]
159160
#![feature(funnel_shifts)]

0 commit comments

Comments
 (0)