diff options
| author | Camille GILLOT <gillot.camille@gmail.com> | 2021-01-05 20:08:11 +0100 |
|---|---|---|
| committer | Camille GILLOT <gillot.camille@gmail.com> | 2021-09-07 20:46:26 +0200 |
| commit | c5fc2609f0f81698616734e22adee9b9ed67f729 (patch) | |
| tree | f01d9c73942c336e3c7bbbd5e7a7621a7c230e1f /compiler/rustc_const_eval/src/util/alignment.rs | |
| parent | fd9c04fe32d3b7700d600ae1be72d5758ffd66ff (diff) | |
| download | rust-c5fc2609f0f81698616734e22adee9b9ed67f729.tar.gz rust-c5fc2609f0f81698616734e22adee9b9ed67f729.zip | |
Rename rustc_mir to rustc_const_eval.
Diffstat (limited to 'compiler/rustc_const_eval/src/util/alignment.rs')
| -rw-r--r-- | compiler/rustc_const_eval/src/util/alignment.rs | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/compiler/rustc_const_eval/src/util/alignment.rs b/compiler/rustc_const_eval/src/util/alignment.rs new file mode 100644 index 00000000000..73adc60577b --- /dev/null +++ b/compiler/rustc_const_eval/src/util/alignment.rs @@ -0,0 +1,70 @@ +use rustc_middle::mir::*; +use rustc_middle::ty::{self, TyCtxt}; +use rustc_target::abi::Align; + +/// Returns `true` if this place is allowed to be less aligned +/// than its containing struct (because it is within a packed +/// struct). +pub fn is_disaligned<'tcx, L>( + tcx: TyCtxt<'tcx>, + local_decls: &L, + param_env: ty::ParamEnv<'tcx>, + place: Place<'tcx>, +) -> bool +where + L: HasLocalDecls<'tcx>, +{ + debug!("is_disaligned({:?})", place); + let pack = match is_within_packed(tcx, local_decls, place) { + None => { + debug!("is_disaligned({:?}) - not within packed", place); + return false; + } + Some(pack) => pack, + }; + + let ty = place.ty(local_decls, tcx).ty; + match tcx.layout_of(param_env.and(ty)) { + Ok(layout) if layout.align.abi <= pack => { + // If the packed alignment is greater or equal to the field alignment, the type won't be + // further disaligned. + debug!( + "is_disaligned({:?}) - align = {}, packed = {}; not disaligned", + place, + layout.align.abi.bytes(), + pack.bytes() + ); + false + } + _ => { + debug!("is_disaligned({:?}) - true", place); + true + } + } +} + +fn is_within_packed<'tcx, L>( + tcx: TyCtxt<'tcx>, + local_decls: &L, + place: Place<'tcx>, +) -> Option<Align> +where + L: HasLocalDecls<'tcx>, +{ + for (place_base, elem) in place.iter_projections().rev() { + match elem { + // encountered a Deref, which is ABI-aligned + ProjectionElem::Deref => break, + ProjectionElem::Field(..) => { + let ty = place_base.ty(local_decls, tcx).ty; + match ty.kind() { + ty::Adt(def, _) => return def.repr.pack, + _ => {} + } + } + _ => {} + } + } + + None +} |
