diff --git a/compiler/rustc_abi/src/callconv/reg.rs b/compiler/rustc_abi/src/callconv/reg.rs index dda7a45f9c2b7..393ec3801f577 100644 --- a/compiler/rustc_abi/src/callconv/reg.rs +++ b/compiler/rustc_abi/src/callconv/reg.rs @@ -76,8 +76,7 @@ impl Reg { let dl = cx.data_layout(); match self.kind { RegKind::Integer => match self.size.bits() { - 1 => dl.i1_align, - 2..=8 => dl.i8_align, + 1..=8 => Align::ONE, 9..=16 => dl.i16_align, 17..=32 => dl.i32_align, 33..=64 => dl.i64_align, diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs index dd8652a05faab..720efd43dd248 100644 --- a/compiler/rustc_abi/src/layout.rs +++ b/compiler/rustc_abi/src/layout.rs @@ -365,7 +365,7 @@ impl LayoutCalculator { Some(present_first) => present_first, // Uninhabited because it has no variants, or only absent ones. None if is_enum => { - return Ok(LayoutData::never_type(&self.cx)); + return Ok(LayoutData::never_type()); } // If it's a struct, still compute a layout so that we can still compute the // field offsets. @@ -412,7 +412,7 @@ impl LayoutCalculator { F: Deref> + fmt::Debug + Copy, { let dl = self.cx.data_layout(); - let mut align = if repr.pack.is_some() { dl.i8_align } else { dl.aggregate_align }; + let mut align = if repr.pack.is_some() { Align::ONE } else { dl.aggregate_align }; let mut max_repr_align = repr.align; // If all the non-ZST fields have the same repr and union repr optimizations aren't @@ -601,7 +601,7 @@ impl LayoutCalculator { { let dl = self.cx.data_layout(); let pack = repr.pack; - let mut align = if pack.is_some() { dl.i8_align } else { dl.aggregate_align }; + let mut align = if pack.is_some() { Align::ONE } else { dl.aggregate_align }; let mut max_repr_align = repr.align; let mut in_memory_order: IndexVec = fields.indices().collect(); let optimize_field_order = !repr.inhibit_struct_field_reordering(); diff --git a/compiler/rustc_abi/src/layout/simple.rs b/compiler/rustc_abi/src/layout/simple.rs index f16daccc3c526..dff1f9ee44980 100644 --- a/compiler/rustc_abi/src/layout/simple.rs +++ b/compiler/rustc_abi/src/layout/simple.rs @@ -4,13 +4,13 @@ use rustc_hashes::Hash64; use rustc_index::{Idx, IndexVec}; use crate::{ - BackendRepr, FieldsShape, HasDataLayout, LayoutData, Niche, Primitive, Scalar, Size, Variants, + Align, BackendRepr, FieldsShape, HasDataLayout, LayoutData, Niche, Primitive, Scalar, Size, + Variants, }; /// "Simple" layout constructors that cannot fail. impl LayoutData { - pub fn unit(cx: &C, sized: bool) -> Self { - let dl = cx.data_layout(); + pub fn unit(sized: bool) -> Self { LayoutData { variants: Variants::Single { index: VariantIdx::new(0) }, fields: FieldsShape::Arbitrary { @@ -20,17 +20,16 @@ impl LayoutData { backend_repr: BackendRepr::Memory { sized }, largest_niche: None, uninhabited: false, - align: dl.i8_align, + align: Align::ONE, size: Size::ZERO, max_repr_align: None, - unadjusted_abi_align: dl.i8_align, + unadjusted_abi_align: Align::ONE, repr_c: false, randomization_seed: Hash64::new(0), } } - pub fn never_type(cx: &C) -> Self { - let dl = cx.data_layout(); + pub fn never_type() -> Self { // This is also used for uninhabited enums, so we use `Variants::Empty`. LayoutData { variants: Variants::Empty, @@ -38,10 +37,10 @@ impl LayoutData { backend_repr: BackendRepr::Memory { sized: true }, largest_niche: None, uninhabited: true, - align: dl.i8_align, + align: Align::ONE, size: Size::ZERO, max_repr_align: None, - unadjusted_abi_align: dl.i8_align, + unadjusted_abi_align: Align::ONE, repr_c: false, randomization_seed: Hash64::ZERO, } @@ -128,8 +127,7 @@ impl LayoutData { /// /// Uninhabited variants get pruned as part of the layout calculation, /// so this can be used after the fact to reconstitute a layout. - pub fn uninhabited_variant(cx: &C, index: VariantIdx, fields: usize) -> Self { - let dl = cx.data_layout(); + pub fn uninhabited_variant(index: VariantIdx, fields: usize) -> Self { LayoutData { variants: Variants::Single { index }, fields: match NonZero::new(fields) { @@ -142,10 +140,10 @@ impl LayoutData { backend_repr: BackendRepr::Memory { sized: true }, largest_niche: None, uninhabited: true, - align: dl.i8_align, + align: Align::ONE, size: Size::ZERO, max_repr_align: None, - unadjusted_abi_align: dl.i8_align, + unadjusted_abi_align: Align::ONE, repr_c: false, // Variant layouts never flow back into actual layout computations, // so dummy values are fine here. diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index 6d02f91ff7396..1f2fcfc389f2c 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -318,8 +318,6 @@ pub struct PointerSpec { #[derive(Debug, PartialEq, Eq)] pub struct TargetDataLayout { pub endian: Endian, - pub i1_align: Align, - pub i8_align: Align, pub i16_align: Align, pub i32_align: Align, pub i64_align: Align, @@ -359,8 +357,6 @@ impl Default for TargetDataLayout { let align = |bits| Align::from_bits(bits).unwrap(); TargetDataLayout { endian: Endian::Big, - i1_align: align(8), - i8_align: align(8), i16_align: align(16), i32_align: align(32), i64_align: align(32), @@ -394,6 +390,7 @@ pub enum TargetDataLayoutError<'a> { InvalidBits { kind: &'a str, bit: &'a str, cause: &'a str, err: ParseIntError }, MissingAlignment { cause: &'a str }, InvalidAlignment { cause: &'a str, err: AlignFromBytesError }, + AlignmentTooLargeForType { cause: &'a str, align: Align }, InconsistentTargetArchitecture { dl: &'a str, target: &'a str }, InconsistentTargetPointerWidth { pointer_size: u64, target: u16 }, InvalidBitsSize { err: String }, @@ -426,6 +423,9 @@ impl Diagnostic<'_> for TargetDataLayoutError<'_> { .with_arg("cause", cause) .with_arg("err", err.to_string()) } + TargetDataLayoutError::AlignmentTooLargeForType { cause, align } => { + Diag::new(dcx, level, msg!("alignment of `{$align}` bytes in \"data-layout\" is too large for `{$cause}`")).with_arg("align", align.bytes()).with_arg("cause", cause) + } TargetDataLayoutError::InconsistentTargetArchitecture { dl, target } => { Diag::new(dcx, level, msg!("inconsistent target specification: \"data-layout\" claims architecture is {$dl}-endian, while \"target-endian\" is `{$target}`")) .with_arg("dl", dl).with_arg("target", target) @@ -477,22 +477,28 @@ impl TargetDataLayout { |s: &'a str, cause: &'a str| parse_bits(s, "size", cause).map(Size::from_bits); // Parse an alignment string. - let parse_align_str = |s: &'a str, cause: &'a str| { + let parse_align_str = |s: &'a str, cause: &'a str, size_bits: u64| { let align_from_bits = |bits| { Align::from_bits(bits) .map_err(|err| TargetDataLayoutError::InvalidAlignment { cause, err }) }; - let abi = parse_bits(s, "alignment", cause)?; - Ok(align_from_bits(abi)?) + let align_bits = parse_bits(s, "alignment", cause)?; + let align = align_from_bits(align_bits)?; + let max_align_bytes = size_bits.div_ceil(8).next_power_of_two(); + if align.bytes() > max_align_bytes { + Err(TargetDataLayoutError::AlignmentTooLargeForType { cause, align }) + } else { + Ok(align) + } }; // Parse an alignment sequence, possibly in the form `[:]`, // ignoring the secondary alignment specifications. - let parse_align_seq = |s: &[&'a str], cause: &'a str| { + let parse_align_seq = |s: &[&'a str], cause: &'a str, size_bits: u64| { if s.is_empty() { return Err(TargetDataLayoutError::MissingAlignment { cause }); } - parse_align_str(s[0], cause) + parse_align_str(s[0], cause, size_bits) }; let mut dl = TargetDataLayout::default(); @@ -508,12 +514,12 @@ impl TargetDataLayout { [p] if p.starts_with('P') => { dl.instruction_address_space = parse_address_space(&p[1..], "P")? } - ["a", a @ ..] => dl.aggregate_align = parse_align_seq(a, "a")?, - ["f16", a @ ..] => dl.f16_align = parse_align_seq(a, "f16")?, - ["f32", a @ ..] => dl.f32_align = parse_align_seq(a, "f32")?, - ["f64", a @ ..] => dl.f64_align = parse_align_seq(a, "f64")?, - ["f80", a @ ..] => dl.x87_f80_align = parse_align_seq(a, "f80")?, - ["f128", a @ ..] => dl.f128_align = parse_align_seq(a, "f128")?, + ["a", a @ ..] => dl.aggregate_align = parse_align_seq(a, "a", u64::MAX)?, + ["f16", a @ ..] => dl.f16_align = parse_align_seq(a, "f16", 16)?, + ["f32", a @ ..] => dl.f32_align = parse_align_seq(a, "f32", 32)?, + ["f64", a @ ..] => dl.f64_align = parse_align_seq(a, "f64", 64)?, + ["f80", a @ ..] => dl.x87_f80_align = parse_align_seq(a, "f80", 80)?, + ["f128", a @ ..] => dl.f128_align = parse_align_seq(a, "f128", 128)?, [p, s, a @ ..] if p.starts_with("p") => { let mut p = p.strip_prefix('p').unwrap(); let mut _is_fat = false; @@ -541,7 +547,7 @@ impl TargetDataLayout { }; let pointer_size = parse_size(s, "p-")?; - let pointer_align = parse_align_seq(a, "p-")?; + let pointer_align = parse_align_seq(a, "p-", pointer_size.bits())?; let info = PointerSpec { pointer_offset: pointer_size, pointer_size, @@ -585,9 +591,10 @@ impl TargetDataLayout { AddressSpace::ZERO }; + let pointer_size = parse_size(s, "p-")?; let info = PointerSpec { - pointer_size: parse_size(s, "p-")?, - pointer_align: parse_align_str(a, "p-")?, + pointer_size, + pointer_align: parse_align_str(a, "p-", pointer_size.bits())?, pointer_offset: parse_size(i, "p-")?, _is_fat, }; @@ -609,10 +616,10 @@ impl TargetDataLayout { parse_size(&s[1..], "i")?; // For the user error. continue; }; - let a = parse_align_seq(a, s)?; + let a = parse_align_seq(a, s, bits)?; match bits { - 1 => dl.i1_align = a, - 8 => dl.i8_align = a, + // i1 and i8 always have an alignment of 1 byte - this has already been + // checked by `parse_align_seq` above. 16 => dl.i16_align = a, 32 => dl.i32_align = a, 64 => dl.i64_align = a, @@ -627,7 +634,7 @@ impl TargetDataLayout { } [s, a @ ..] if s.starts_with('v') => { let v_size = parse_size(&s[1..], "v")?; - let a = parse_align_seq(a, s)?; + let a = parse_align_seq(a, s, v_size.bits())?; if let Some(v) = dl.vector_align.iter_mut().find(|v| v.0 == v_size) { v.1 = a; continue; @@ -1280,7 +1287,7 @@ impl Integer { let dl = cx.data_layout(); match self { - I8 => dl.i8_align, + I8 => Align::ONE, I16 => dl.i16_align, I32 => dl.i32_align, I64 => dl.i64_align, diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs index 33d48642812e6..dd6465f7fcf75 100644 --- a/compiler/rustc_codegen_llvm/src/consts.rs +++ b/compiler/rustc_codegen_llvm/src/consts.rs @@ -700,7 +700,7 @@ impl<'ll> CodegenCx<'ll, '_> { let g = self.define_global(&sym, llty).unwrap_or_else(|| { bug!("symbol `{}` is already defined", sym); }); - set_global_alignment(self, g, self.tcx.data_layout.i8_align); + set_global_alignment(self, g, Align::ONE); llvm::set_initializer(g, llval); llvm::set_linkage(g, llvm::Linkage::PrivateLinkage); llvm::set_section(g, c"__TEXT,__cstring,cstring_literals"); @@ -816,7 +816,7 @@ impl<'ll> CodegenCx<'ll, '_> { let methname_g = self.define_global(&methname_sym, methname_llty).unwrap_or_else(|| { bug!("symbol `{}` is already defined", methname_sym); }); - set_global_alignment(self, methname_g, self.tcx.data_layout.i8_align); + set_global_alignment(self, methname_g, Align::ONE); llvm::set_initializer(methname_g, methname_llval); llvm::set_linkage(methname_g, llvm::Linkage::PrivateLinkage); llvm::set_section( diff --git a/compiler/rustc_codegen_llvm/src/va_arg.rs b/compiler/rustc_codegen_llvm/src/va_arg.rs index 7c2c20c2671e4..cd987c4c3351d 100644 --- a/compiler/rustc_codegen_llvm/src/va_arg.rs +++ b/compiler/rustc_codegen_llvm/src/va_arg.rs @@ -351,7 +351,7 @@ fn emit_powerpc_va_arg<'ll, 'tcx>( bx.inbounds_ptradd(va_list_addr, bx.const_usize(1)) // fpr }; - let mut num_regs = bx.load(bx.type_i8(), num_regs_addr, dl.i8_align); + let mut num_regs = bx.load(bx.type_i8(), num_regs_addr, Align::ONE); // "Align" the register count when the type is passed as `i64`. if layout.size.bytes() == 8 && !is_passed_in_fprs { @@ -390,7 +390,7 @@ fn emit_powerpc_va_arg<'ll, 'tcx>( // Increase the used-register count. let new_num_regs = bx.add(num_regs, bx.cx.const_u8(reg_incr)); - bx.store(new_num_regs, num_regs_addr, dl.i8_align); + bx.store(new_num_regs, num_regs_addr, Align::ONE); bx.br(end); @@ -400,7 +400,7 @@ fn emit_powerpc_va_arg<'ll, 'tcx>( let mem_addr = { bx.switch_to_block(in_mem); - bx.store(bx.const_u8(max_regs), num_regs_addr, dl.i8_align); + bx.store(bx.const_u8(max_regs), num_regs_addr, Align::ONE); // Everything in the overflow area is rounded up to a size of at least 4. let overflow_area_align = Align::FOUR; diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 80bfbb5b551e0..cddfc56579e01 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -836,7 +836,7 @@ where ty::Adt(def, _) => def.variant(variant_index).fields.len(), _ => bug!("`ty_and_layout_for_variant` on unexpected type {}", this.ty), }; - tcx.mk_layout(LayoutData::uninhabited_variant(cx, variant_index, fields)) + tcx.mk_layout(LayoutData::uninhabited_variant(variant_index, fields)) } Variants::Multiple { .. } => { diff --git a/compiler/rustc_session/src/config/cfg.rs b/compiler/rustc_session/src/config/cfg.rs index 7df6549a07a70..fc4abc9e4f391 100644 --- a/compiler/rustc_session/src/config/cfg.rs +++ b/compiler/rustc_session/src/config/cfg.rs @@ -270,7 +270,7 @@ pub(crate) fn default_configuration(sess: &Session) -> Cfg { }); let mut has_atomic = false; for (i, align) in [ - (8, layout.i8_align), + (8, Align::ONE), (16, layout.i16_align), (32, layout.i32_align), (64, layout.i64_align), diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 6404a062f2731..e09ae4497bf67 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -432,7 +432,7 @@ fn layout_of_uncached<'tcx>( } // The never type. - ty::Never => tcx.mk_layout(LayoutData::never_type(cx)), + ty::Never => tcx.mk_layout(LayoutData::never_type()), // Potentially-wide pointers. ty::Ref(_, pointee, _) | ty::RawPtr(pointee, _) => { @@ -543,7 +543,7 @@ fn layout_of_uncached<'tcx>( // Odd unit types. ty::FnDef(..) | ty::Dynamic(_, _) | ty::Foreign(..) => { let sized = matches!(ty.kind(), ty::FnDef(..)); - tcx.mk_layout(LayoutData::unit(cx, sized)) + tcx.mk_layout(LayoutData::unit(sized)) } ty::Coroutine(def_id, args) => {