Auto merge of #143182 - xdoardo:more-addrspace, r=workingjubilee

Allow custom default address spaces and parse `p-` specifications in the datalayout string

Some targets, such as CHERI, use as default an address space different from the "normal" default address space `0` (in the case of CHERI, [200 is used](https://www.cl.cam.ac.uk/techreports/UCAM-CL-TR-877.pdf)). Currently, `rustc` does not allow to specify custom address spaces and does not take into consideration [`p-` specifications in the datalayout string](https://llvm.org/docs/LangRef.html#langref-datalayout).

This patch tries to mitigate these problems by allowing targets to define a custom default address space (while keeping the default value to address space `0`) and adding the code to parse the `p-` specifications in `rustc_abi`. The main changes are that `TargetDataLayout` now uses functions to refer to pointer-related informations, instead of having specific fields for the size and alignment of pointers in the default address space; furthermore, the two `pointer_size` and `pointer_align` fields in `TargetDataLayout` are replaced with an `FxHashMap` that holds info for all the possible address spaces, as parsed by the `p-` specifications.

The potential performance drawbacks of not having ad-hoc fields for the default address space will be tested in this PR's CI run.

r? workingjubilee
This commit is contained in:
bors
2025-07-07 17:28:14 +00:00
58 changed files with 416 additions and 170 deletions

View File

@@ -221,6 +221,20 @@ impl ReprOptions {
/// * Cranelift stores the base-2 log of the lane count in a 4 bit integer. /// * Cranelift stores the base-2 log of the lane count in a 4 bit integer.
pub const MAX_SIMD_LANES: u64 = 1 << 0xF; pub const MAX_SIMD_LANES: u64 = 1 << 0xF;
/// How pointers are represented in a given address space
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct PointerSpec {
/// The size of the bitwise representation of the pointer.
pointer_size: Size,
/// The alignment of pointers for this address space
pointer_align: AbiAlign,
/// The size of the value a pointer can be offset by in this address space.
pointer_offset: Size,
/// Pointers into this address space contain extra metadata
/// FIXME(workingjubilee): Consider adequately reflecting this in the compiler?
_is_fat: bool,
}
/// Parsed [Data layout](https://llvm.org/docs/LangRef.html#data-layout) /// Parsed [Data layout](https://llvm.org/docs/LangRef.html#data-layout)
/// for a target, which contains everything needed to compute layouts. /// for a target, which contains everything needed to compute layouts.
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]
@@ -236,13 +250,22 @@ pub struct TargetDataLayout {
pub f32_align: AbiAlign, pub f32_align: AbiAlign,
pub f64_align: AbiAlign, pub f64_align: AbiAlign,
pub f128_align: AbiAlign, pub f128_align: AbiAlign,
pub pointer_size: Size,
pub pointer_align: AbiAlign,
pub aggregate_align: AbiAlign, pub aggregate_align: AbiAlign,
/// Alignments for vector types. /// Alignments for vector types.
pub vector_align: Vec<(Size, AbiAlign)>, pub vector_align: Vec<(Size, AbiAlign)>,
pub default_address_space: AddressSpace,
pub default_address_space_pointer_spec: PointerSpec,
/// Address space information of all known address spaces.
///
/// # Note
///
/// This vector does not contain the [`PointerSpec`] relative to the default address space,
/// which instead lives in [`Self::default_address_space_pointer_spec`].
address_space_info: Vec<(AddressSpace, PointerSpec)>,
pub instruction_address_space: AddressSpace, pub instruction_address_space: AddressSpace,
/// Minimum size of #[repr(C)] enums (default c_int::BITS, usually 32) /// Minimum size of #[repr(C)] enums (default c_int::BITS, usually 32)
@@ -267,14 +290,20 @@ impl Default for TargetDataLayout {
f32_align: AbiAlign::new(align(32)), f32_align: AbiAlign::new(align(32)),
f64_align: AbiAlign::new(align(64)), f64_align: AbiAlign::new(align(64)),
f128_align: AbiAlign::new(align(128)), f128_align: AbiAlign::new(align(128)),
pointer_size: Size::from_bits(64),
pointer_align: AbiAlign::new(align(64)),
aggregate_align: AbiAlign { abi: align(8) }, aggregate_align: AbiAlign { abi: align(8) },
vector_align: vec![ vector_align: vec![
(Size::from_bits(64), AbiAlign::new(align(64))), (Size::from_bits(64), AbiAlign::new(align(64))),
(Size::from_bits(128), AbiAlign::new(align(128))), (Size::from_bits(128), AbiAlign::new(align(128))),
], ],
instruction_address_space: AddressSpace::DATA, default_address_space: AddressSpace::ZERO,
default_address_space_pointer_spec: PointerSpec {
pointer_size: Size::from_bits(64),
pointer_align: AbiAlign::new(align(64)),
pointer_offset: Size::from_bits(64),
_is_fat: false,
},
address_space_info: vec![],
instruction_address_space: AddressSpace::ZERO,
c_enum_min_size: Integer::I32, c_enum_min_size: Integer::I32,
} }
} }
@@ -288,6 +317,7 @@ pub enum TargetDataLayoutErrors<'a> {
InconsistentTargetArchitecture { dl: &'a str, target: &'a str }, InconsistentTargetArchitecture { dl: &'a str, target: &'a str },
InconsistentTargetPointerWidth { pointer_size: u64, target: u32 }, InconsistentTargetPointerWidth { pointer_size: u64, target: u32 },
InvalidBitsSize { err: String }, InvalidBitsSize { err: String },
UnknownPointerSpecification { err: String },
} }
impl TargetDataLayout { impl TargetDataLayout {
@@ -298,6 +328,7 @@ impl TargetDataLayout {
/// determined from llvm string. /// determined from llvm string.
pub fn parse_from_llvm_datalayout_string<'a>( pub fn parse_from_llvm_datalayout_string<'a>(
input: &'a str, input: &'a str,
default_address_space: AddressSpace,
) -> Result<TargetDataLayout, TargetDataLayoutErrors<'a>> { ) -> Result<TargetDataLayout, TargetDataLayoutErrors<'a>> {
// Parse an address space index from a string. // Parse an address space index from a string.
let parse_address_space = |s: &'a str, cause: &'a str| { let parse_address_space = |s: &'a str, cause: &'a str| {
@@ -321,19 +352,27 @@ impl TargetDataLayout {
|s: &'a str, cause: &'a str| parse_bits(s, "size", cause).map(Size::from_bits); |s: &'a str, cause: &'a str| parse_bits(s, "size", cause).map(Size::from_bits);
// Parse an alignment string. // Parse an alignment string.
let parse_align = |s: &[&'a str], cause: &'a str| { let parse_align_str = |s: &'a str, cause: &'a str| {
if s.is_empty() {
return Err(TargetDataLayoutErrors::MissingAlignment { cause });
}
let align_from_bits = |bits| { let align_from_bits = |bits| {
Align::from_bits(bits) Align::from_bits(bits)
.map_err(|err| TargetDataLayoutErrors::InvalidAlignment { cause, err }) .map_err(|err| TargetDataLayoutErrors::InvalidAlignment { cause, err })
}; };
let abi = parse_bits(s[0], "alignment", cause)?; let abi = parse_bits(s, "alignment", cause)?;
Ok(AbiAlign::new(align_from_bits(abi)?)) Ok(AbiAlign::new(align_from_bits(abi)?))
}; };
// Parse an alignment sequence, possibly in the form `<align>[:<preferred_alignment>]`,
// ignoring the secondary alignment specifications.
let parse_align_seq = |s: &[&'a str], cause: &'a str| {
if s.is_empty() {
return Err(TargetDataLayoutErrors::MissingAlignment { cause });
}
parse_align_str(s[0], cause)
};
let mut dl = TargetDataLayout::default(); let mut dl = TargetDataLayout::default();
dl.default_address_space = default_address_space;
let mut i128_align_src = 64; let mut i128_align_src = 64;
for spec in input.split('-') { for spec in input.split('-') {
let spec_parts = spec.split(':').collect::<Vec<_>>(); let spec_parts = spec.split(':').collect::<Vec<_>>();
@@ -344,24 +383,107 @@ impl TargetDataLayout {
[p] if p.starts_with('P') => { [p] if p.starts_with('P') => {
dl.instruction_address_space = parse_address_space(&p[1..], "P")? dl.instruction_address_space = parse_address_space(&p[1..], "P")?
} }
["a", a @ ..] => dl.aggregate_align = parse_align(a, "a")?, ["a", a @ ..] => dl.aggregate_align = parse_align_seq(a, "a")?,
["f16", a @ ..] => dl.f16_align = parse_align(a, "f16")?, ["f16", a @ ..] => dl.f16_align = parse_align_seq(a, "f16")?,
["f32", a @ ..] => dl.f32_align = parse_align(a, "f32")?, ["f32", a @ ..] => dl.f32_align = parse_align_seq(a, "f32")?,
["f64", a @ ..] => dl.f64_align = parse_align(a, "f64")?, ["f64", a @ ..] => dl.f64_align = parse_align_seq(a, "f64")?,
["f128", a @ ..] => dl.f128_align = parse_align(a, "f128")?, ["f128", a @ ..] => dl.f128_align = parse_align_seq(a, "f128")?,
// FIXME(erikdesjardins): we should be parsing nonzero address spaces [p, s, a @ ..] if p.starts_with("p") => {
// this will require replacing TargetDataLayout::{pointer_size,pointer_align} let mut p = p.strip_prefix('p').unwrap();
// with e.g. `fn pointer_size_in(AddressSpace)` let mut _is_fat = false;
[p @ "p", s, a @ ..] | [p @ "p0", s, a @ ..] => {
dl.pointer_size = parse_size(s, p)?; // Some targets, such as CHERI, use the 'f' suffix in the p- spec to signal that
dl.pointer_align = parse_align(a, p)?; // they use 'fat' pointers. The resulting prefix may look like `pf<addr_space>`.
if p.starts_with('f') {
p = p.strip_prefix('f').unwrap();
_is_fat = true;
} }
// However, we currently don't take into account further specifications:
// an error is emitted instead.
if p.starts_with(char::is_alphabetic) {
return Err(TargetDataLayoutErrors::UnknownPointerSpecification {
err: p.to_string(),
});
}
let addr_space = if !p.is_empty() {
parse_address_space(p, "p-")?
} else {
AddressSpace::ZERO
};
let pointer_size = parse_size(s, "p-")?;
let pointer_align = parse_align_seq(a, "p-")?;
let info = PointerSpec {
pointer_offset: pointer_size,
pointer_size,
pointer_align,
_is_fat,
};
if addr_space == default_address_space {
dl.default_address_space_pointer_spec = info;
} else {
match dl.address_space_info.iter_mut().find(|(a, _)| *a == addr_space) {
Some(e) => e.1 = info,
None => {
dl.address_space_info.push((addr_space, info));
}
}
}
}
[p, s, a, _pr, i] if p.starts_with("p") => {
let mut p = p.strip_prefix('p').unwrap();
let mut _is_fat = false;
// Some targets, such as CHERI, use the 'f' suffix in the p- spec to signal that
// they use 'fat' pointers. The resulting prefix may look like `pf<addr_space>`.
if p.starts_with('f') {
p = p.strip_prefix('f').unwrap();
_is_fat = true;
}
// However, we currently don't take into account further specifications:
// an error is emitted instead.
if p.starts_with(char::is_alphabetic) {
return Err(TargetDataLayoutErrors::UnknownPointerSpecification {
err: p.to_string(),
});
}
let addr_space = if !p.is_empty() {
parse_address_space(p, "p")?
} else {
AddressSpace::ZERO
};
let info = PointerSpec {
pointer_size: parse_size(s, "p-")?,
pointer_align: parse_align_str(a, "p-")?,
pointer_offset: parse_size(i, "p-")?,
_is_fat,
};
if addr_space == default_address_space {
dl.default_address_space_pointer_spec = info;
} else {
match dl.address_space_info.iter_mut().find(|(a, _)| *a == addr_space) {
Some(e) => e.1 = info,
None => {
dl.address_space_info.push((addr_space, info));
}
}
}
}
[s, a @ ..] if s.starts_with('i') => { [s, a @ ..] if s.starts_with('i') => {
let Ok(bits) = s[1..].parse::<u64>() else { let Ok(bits) = s[1..].parse::<u64>() else {
parse_size(&s[1..], "i")?; // For the user error. parse_size(&s[1..], "i")?; // For the user error.
continue; continue;
}; };
let a = parse_align(a, s)?; let a = parse_align_seq(a, s)?;
match bits { match bits {
1 => dl.i1_align = a, 1 => dl.i1_align = a,
8 => dl.i8_align = a, 8 => dl.i8_align = a,
@@ -379,7 +501,7 @@ impl TargetDataLayout {
} }
[s, a @ ..] if s.starts_with('v') => { [s, a @ ..] if s.starts_with('v') => {
let v_size = parse_size(&s[1..], "v")?; let v_size = parse_size(&s[1..], "v")?;
let a = parse_align(a, s)?; let a = parse_align_seq(a, s)?;
if let Some(v) = dl.vector_align.iter_mut().find(|v| v.0 == v_size) { if let Some(v) = dl.vector_align.iter_mut().find(|v| v.0 == v_size) {
v.1 = a; v.1 = a;
continue; continue;
@@ -390,9 +512,45 @@ impl TargetDataLayout {
_ => {} // Ignore everything else. _ => {} // Ignore everything else.
} }
} }
// Inherit, if not given, address space information for specific LLVM elements from the
// default data address space.
if (dl.instruction_address_space != dl.default_address_space)
&& dl
.address_space_info
.iter()
.find(|(a, _)| *a == dl.instruction_address_space)
.is_none()
{
dl.address_space_info.push((
dl.instruction_address_space,
dl.default_address_space_pointer_spec.clone(),
));
}
Ok(dl) Ok(dl)
} }
/// Returns **exclusive** upper bound on object size in bytes, in the default data address
/// space.
///
/// The theoretical maximum object size is defined as the maximum positive `isize` value.
/// This ensures that the `offset` semantics remain well-defined by allowing it to correctly
/// index every address within an object along with one byte past the end, along with allowing
/// `isize` to store the difference between any two pointers into an object.
///
/// LLVM uses a 64-bit integer to represent object size in *bits*, but we care only for bytes,
/// so we adopt such a more-constrained size bound due to its technical limitations.
#[inline]
pub fn obj_size_bound(&self) -> u64 {
match self.pointer_size().bits() {
16 => 1 << 15,
32 => 1 << 31,
64 => 1 << 61,
bits => panic!("obj_size_bound: unknown pointer bit size {bits}"),
}
}
/// Returns **exclusive** upper bound on object size in bytes. /// Returns **exclusive** upper bound on object size in bytes.
/// ///
/// The theoretical maximum object size is defined as the maximum positive `isize` value. /// The theoretical maximum object size is defined as the maximum positive `isize` value.
@@ -403,8 +561,8 @@ impl TargetDataLayout {
/// LLVM uses a 64-bit integer to represent object size in *bits*, but we care only for bytes, /// LLVM uses a 64-bit integer to represent object size in *bits*, but we care only for bytes,
/// so we adopt such a more-constrained size bound due to its technical limitations. /// so we adopt such a more-constrained size bound due to its technical limitations.
#[inline] #[inline]
pub fn obj_size_bound(&self) -> u64 { pub fn obj_size_bound_in(&self, address_space: AddressSpace) -> u64 {
match self.pointer_size.bits() { match self.pointer_size_in(address_space).bits() {
16 => 1 << 15, 16 => 1 << 15,
32 => 1 << 31, 32 => 1 << 31,
64 => 1 << 61, 64 => 1 << 61,
@@ -415,7 +573,18 @@ impl TargetDataLayout {
#[inline] #[inline]
pub fn ptr_sized_integer(&self) -> Integer { pub fn ptr_sized_integer(&self) -> Integer {
use Integer::*; use Integer::*;
match self.pointer_size.bits() { match self.pointer_offset().bits() {
16 => I16,
32 => I32,
64 => I64,
bits => panic!("ptr_sized_integer: unknown pointer bit size {bits}"),
}
}
#[inline]
pub fn ptr_sized_integer_in(&self, address_space: AddressSpace) -> Integer {
use Integer::*;
match self.pointer_offset_in(address_space).bits() {
16 => I16, 16 => I16,
32 => I32, 32 => I32,
64 => I64, 64 => I64,
@@ -439,6 +608,66 @@ impl TargetDataLayout {
Align::from_bytes(vec_size.bytes().next_power_of_two()).unwrap(), Align::from_bytes(vec_size.bytes().next_power_of_two()).unwrap(),
)) ))
} }
/// Get the pointer size in the default data address space.
#[inline]
pub fn pointer_size(&self) -> Size {
self.default_address_space_pointer_spec.pointer_size
}
/// Get the pointer size in a specific address space.
#[inline]
pub fn pointer_size_in(&self, c: AddressSpace) -> Size {
if c == self.default_address_space {
return self.default_address_space_pointer_spec.pointer_size;
}
if let Some(e) = self.address_space_info.iter().find(|(a, _)| a == &c) {
e.1.pointer_size
} else {
panic!("Use of unknown address space {c:?}");
}
}
/// Get the pointer index in the default data address space.
#[inline]
pub fn pointer_offset(&self) -> Size {
self.default_address_space_pointer_spec.pointer_offset
}
/// Get the pointer index in a specific address space.
#[inline]
pub fn pointer_offset_in(&self, c: AddressSpace) -> Size {
if c == self.default_address_space {
return self.default_address_space_pointer_spec.pointer_offset;
}
if let Some(e) = self.address_space_info.iter().find(|(a, _)| a == &c) {
e.1.pointer_offset
} else {
panic!("Use of unknown address space {c:?}");
}
}
/// Get the pointer alignment in the default data address space.
#[inline]
pub fn pointer_align(&self) -> AbiAlign {
self.default_address_space_pointer_spec.pointer_align
}
/// Get the pointer alignment in a specific address space.
#[inline]
pub fn pointer_align_in(&self, c: AddressSpace) -> AbiAlign {
if c == self.default_address_space {
return self.default_address_space_pointer_spec.pointer_align;
}
if let Some(e) = self.address_space_info.iter().find(|(a, _)| a == &c) {
e.1.pointer_align
} else {
panic!("Use of unknown address space {c:?}");
}
}
} }
pub trait HasDataLayout { pub trait HasDataLayout {
@@ -1100,10 +1329,7 @@ impl Primitive {
match self { match self {
Int(i, _) => i.size(), Int(i, _) => i.size(),
Float(f) => f.size(), Float(f) => f.size(),
// FIXME(erikdesjardins): ignoring address space is technically wrong, pointers in Pointer(a) => dl.pointer_size_in(a),
// different address spaces can have different sizes
// (but TargetDataLayout doesn't currently parse that part of the DL string)
Pointer(_) => dl.pointer_size,
} }
} }
@@ -1114,10 +1340,7 @@ impl Primitive {
match self { match self {
Int(i, _) => i.align(dl), Int(i, _) => i.align(dl),
Float(f) => f.align(dl), Float(f) => f.align(dl),
// FIXME(erikdesjardins): ignoring address space is technically wrong, pointers in Pointer(a) => dl.pointer_align_in(a),
// different address spaces can have different alignments
// (but TargetDataLayout doesn't currently parse that part of the DL string)
Pointer(_) => dl.pointer_align,
} }
} }
} }
@@ -1421,8 +1644,8 @@ impl<FieldIdx: Idx> FieldsShape<FieldIdx> {
pub struct AddressSpace(pub u32); pub struct AddressSpace(pub u32);
impl AddressSpace { impl AddressSpace {
/// The default address space, corresponding to data space. /// LLVM's `0` address space.
pub const DATA: Self = AddressSpace(0); pub const ZERO: Self = AddressSpace(0);
} }
/// The way we represent values to the backend /// The way we represent values to the backend

View File

@@ -55,7 +55,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
/// Get the maximum value of int_ty. It is platform-dependent due to the byte size of isize /// Get the maximum value of int_ty. It is platform-dependent due to the byte size of isize
fn int_ty_max(&self, int_ty: IntTy) -> u128 { fn int_ty_max(&self, int_ty: IntTy) -> u128 {
match int_ty { match int_ty {
IntTy::Isize => self.tcx.data_layout.pointer_size.signed_int_max() as u128, IntTy::Isize => self.tcx.data_layout.pointer_size().signed_int_max() as u128,
IntTy::I8 => i8::MAX as u128, IntTy::I8 => i8::MAX as u128,
IntTy::I16 => i16::MAX as u128, IntTy::I16 => i16::MAX as u128,
IntTy::I32 => i32::MAX as u128, IntTy::I32 => i32::MAX as u128,
@@ -67,7 +67,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
/// Get the maximum value of uint_ty. It is platform-dependent due to the byte size of usize /// Get the maximum value of uint_ty. It is platform-dependent due to the byte size of usize
fn uint_ty_max(&self, uint_ty: UintTy) -> u128 { fn uint_ty_max(&self, uint_ty: UintTy) -> u128 {
match uint_ty { match uint_ty {
UintTy::Usize => self.tcx.data_layout.pointer_size.unsigned_int_max(), UintTy::Usize => self.tcx.data_layout.pointer_size().unsigned_int_max(),
UintTy::U8 => u8::MAX as u128, UintTy::U8 => u8::MAX as u128,
UintTy::U16 => u16::MAX as u128, UintTy::U16 => u16::MAX as u128,
UintTy::U32 => u32::MAX as u128, UintTy::U32 => u32::MAX as u128,

View File

@@ -786,7 +786,7 @@ pub(crate) fn codegen_drop<'tcx>(
pub(crate) fn lib_call_arg_param(tcx: TyCtxt<'_>, ty: Type, is_signed: bool) -> AbiParam { pub(crate) fn lib_call_arg_param(tcx: TyCtxt<'_>, ty: Type, is_signed: bool) -> AbiParam {
let param = AbiParam::new(ty); let param = AbiParam::new(ty);
if ty.is_int() && u64::from(ty.bits()) < tcx.data_layout.pointer_size.bits() { if ty.is_int() && u64::from(ty.bits()) < tcx.data_layout.pointer_size().bits() {
match (&*tcx.sess.target.arch, &*tcx.sess.target.vendor) { match (&*tcx.sess.target.arch, &*tcx.sess.target.vendor) {
("x86_64", _) | ("aarch64", "apple") => match (ty, is_signed) { ("x86_64", _) | ("aarch64", "apple") => match (ty, is_signed) {
(types::I8 | types::I16, true) => param.sext(), (types::I8 | types::I16, true) => param.sext(),

View File

@@ -127,7 +127,7 @@ impl<'tcx> ArgAbiExt<'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
PassMode::Indirect { attrs, meta_attrs: None, on_stack } => { PassMode::Indirect { attrs, meta_attrs: None, on_stack } => {
if on_stack { if on_stack {
// Abi requires aligning struct size to pointer size // Abi requires aligning struct size to pointer size
let size = self.layout.size.align_to(tcx.data_layout.pointer_align.abi); let size = self.layout.size.align_to(tcx.data_layout.pointer_align().abi);
let size = u32::try_from(size.bytes()).unwrap(); let size = u32::try_from(size.bytes()).unwrap();
smallvec![apply_attrs_to_abi_param( smallvec![apply_attrs_to_abi_param(
AbiParam::special(pointer_ty(tcx), ArgumentPurpose::StructArgument(size),), AbiParam::special(pointer_ty(tcx), ArgumentPurpose::StructArgument(size),),

View File

@@ -15,7 +15,7 @@ use crate::debuginfo::FunctionDebugContext;
use crate::prelude::*; use crate::prelude::*;
pub(crate) fn pointer_ty(tcx: TyCtxt<'_>) -> types::Type { pub(crate) fn pointer_ty(tcx: TyCtxt<'_>) -> types::Type {
match tcx.data_layout.pointer_size.bits() { match tcx.data_layout.pointer_size().bits() {
16 => types::I16, 16 => types::I16,
32 => types::I32, 32 => types::I32,
64 => types::I64, 64 => types::I64,

View File

@@ -443,7 +443,7 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant
let addend = { let addend = {
let endianness = tcx.data_layout.endian; let endianness = tcx.data_layout.endian;
let offset = offset.bytes() as usize; let offset = offset.bytes() as usize;
let ptr_size = tcx.data_layout.pointer_size; let ptr_size = tcx.data_layout.pointer_size();
let bytes = &alloc.inspect_with_uninit_and_ptr_outside_interpreter( let bytes = &alloc.inspect_with_uninit_and_ptr_outside_interpreter(
offset..offset + ptr_size.bytes() as usize, offset..offset + ptr_size.bytes() as usize,
); );

View File

@@ -162,7 +162,7 @@ impl<'gcc, 'tcx> ConstCodegenMethods for CodegenCx<'gcc, 'tcx> {
} }
fn const_usize(&self, i: u64) -> RValue<'gcc> { fn const_usize(&self, i: u64) -> RValue<'gcc> {
let bit_size = self.data_layout().pointer_size.bits(); let bit_size = self.data_layout().pointer_size().bits();
if bit_size < 64 { if bit_size < 64 {
// make sure it doesn't overflow // make sure it doesn't overflow
assert!(i < (1 << bit_size)); assert!(i < (1 << bit_size));

View File

@@ -294,7 +294,7 @@ pub(crate) fn const_alloc_to_gcc_uncached<'gcc>(
let alloc = alloc.inner(); let alloc = alloc.inner();
let mut llvals = Vec::with_capacity(alloc.provenance().ptrs().len() + 1); let mut llvals = Vec::with_capacity(alloc.provenance().ptrs().len() + 1);
let dl = cx.data_layout(); let dl = cx.data_layout();
let pointer_size = dl.pointer_size.bytes() as usize; let pointer_size = dl.pointer_size().bytes() as usize;
let mut next_offset = 0; let mut next_offset = 0;
for &(offset, prov) in alloc.provenance().ptrs().iter() { for &(offset, prov) in alloc.provenance().ptrs().iter() {
@@ -331,7 +331,7 @@ pub(crate) fn const_alloc_to_gcc_uncached<'gcc>(
), ),
abi::Scalar::Initialized { abi::Scalar::Initialized {
value: Primitive::Pointer(address_space), value: Primitive::Pointer(address_space),
valid_range: WrappingRange::full(dl.pointer_size), valid_range: WrappingRange::full(dl.pointer_size()),
}, },
cx.type_i8p_ext(address_space), cx.type_i8p_ext(address_space),
)); ));

View File

@@ -541,7 +541,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc
// For rusty ABIs, small aggregates are actually passed // For rusty ABIs, small aggregates are actually passed
// as `RegKind::Integer` (see `FnAbi::adjust_for_abi`), // as `RegKind::Integer` (see `FnAbi::adjust_for_abi`),
// so we re-use that same threshold here. // so we re-use that same threshold here.
layout.size() <= self.data_layout().pointer_size * 2 layout.size() <= self.data_layout().pointer_size() * 2
} }
}; };

View File

@@ -1184,7 +1184,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
let lhs = args[0].immediate(); let lhs = args[0].immediate();
let rhs = args[1].immediate(); let rhs = args[1].immediate();
let is_add = name == sym::simd_saturating_add; let is_add = name == sym::simd_saturating_add;
let ptr_bits = bx.tcx().data_layout.pointer_size.bits() as _; let ptr_bits = bx.tcx().data_layout.pointer_size().bits() as _;
let (signed, elem_width, elem_ty) = match *in_elem.kind() { let (signed, elem_width, elem_ty) = match *in_elem.kind() {
ty::Int(i) => (true, i.bit_width().unwrap_or(ptr_bits) / 8, bx.cx.type_int_from_ty(i)), ty::Int(i) => (true, i.bit_width().unwrap_or(ptr_bits) / 8, bx.cx.type_int_from_ty(i)),
ty::Uint(i) => { ty::Uint(i) => {

View File

@@ -175,7 +175,7 @@ impl<'ll, 'tcx> ConstCodegenMethods for CodegenCx<'ll, 'tcx> {
} }
fn const_usize(&self, i: u64) -> &'ll Value { fn const_usize(&self, i: u64) -> &'ll Value {
let bit_size = self.data_layout().pointer_size.bits(); let bit_size = self.data_layout().pointer_size().bits();
if bit_size < 64 { if bit_size < 64 {
// make sure it doesn't overflow // make sure it doesn't overflow
assert!(i < (1 << bit_size)); assert!(i < (1 << bit_size));

View File

@@ -43,7 +43,8 @@ pub(crate) fn const_alloc_to_llvm<'ll>(
} }
let mut llvals = Vec::with_capacity(alloc.provenance().ptrs().len() + 1); let mut llvals = Vec::with_capacity(alloc.provenance().ptrs().len() + 1);
let dl = cx.data_layout(); let dl = cx.data_layout();
let pointer_size = dl.pointer_size.bytes() as usize; let pointer_size = dl.pointer_size();
let pointer_size_bytes = pointer_size.bytes() as usize;
// Note: this function may call `inspect_with_uninit_and_ptr_outside_interpreter`, so `range` // Note: this function may call `inspect_with_uninit_and_ptr_outside_interpreter`, so `range`
// must be within the bounds of `alloc` and not contain or overlap a pointer provenance. // must be within the bounds of `alloc` and not contain or overlap a pointer provenance.
@@ -100,7 +101,9 @@ pub(crate) fn const_alloc_to_llvm<'ll>(
// This `inspect` is okay since it is within the bounds of the allocation, it doesn't // This `inspect` is okay since it is within the bounds of the allocation, it doesn't
// affect interpreter execution (we inspect the result after interpreter execution), // affect interpreter execution (we inspect the result after interpreter execution),
// and we properly interpret the provenance as a relocation pointer offset. // and we properly interpret the provenance as a relocation pointer offset.
alloc.inspect_with_uninit_and_ptr_outside_interpreter(offset..(offset + pointer_size)), alloc.inspect_with_uninit_and_ptr_outside_interpreter(
offset..(offset + pointer_size_bytes),
),
) )
.expect("const_alloc_to_llvm: could not read relocation pointer") .expect("const_alloc_to_llvm: could not read relocation pointer")
as u64; as u64;
@@ -111,11 +114,11 @@ pub(crate) fn const_alloc_to_llvm<'ll>(
InterpScalar::from_pointer(Pointer::new(prov, Size::from_bytes(ptr_offset)), &cx.tcx), InterpScalar::from_pointer(Pointer::new(prov, Size::from_bytes(ptr_offset)), &cx.tcx),
Scalar::Initialized { Scalar::Initialized {
value: Primitive::Pointer(address_space), value: Primitive::Pointer(address_space),
valid_range: WrappingRange::full(dl.pointer_size), valid_range: WrappingRange::full(pointer_size),
}, },
cx.type_ptr_ext(address_space), cx.type_ptr_ext(address_space),
)); ));
next_offset = offset + pointer_size; next_offset = offset + pointer_size_bytes;
} }
if alloc.len() >= next_offset { if alloc.len() >= next_offset {
let range = next_offset..alloc.len(); let range = next_offset..alloc.len();

View File

@@ -605,7 +605,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
GenericCx( GenericCx(
FullCx { FullCx {
tcx, tcx,
scx: SimpleCx::new(llmod, llcx, tcx.data_layout.pointer_size), scx: SimpleCx::new(llmod, llcx, tcx.data_layout.pointer_size()),
use_dll_storage_attrs, use_dll_storage_attrs,
tls_model, tls_model,
codegen_unit, codegen_unit,

View File

@@ -159,13 +159,15 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>(
return_if_di_node_created_in_meantime!(cx, unique_type_id); return_if_di_node_created_in_meantime!(cx, unique_type_id);
let data_layout = &cx.tcx.data_layout; let data_layout = &cx.tcx.data_layout;
let pointer_size = data_layout.pointer_size();
let pointer_align = data_layout.pointer_align();
let ptr_type_debuginfo_name = compute_debuginfo_type_name(cx.tcx, ptr_type, true); let ptr_type_debuginfo_name = compute_debuginfo_type_name(cx.tcx, ptr_type, true);
match wide_pointer_kind(cx, pointee_type) { match wide_pointer_kind(cx, pointee_type) {
None => { None => {
// This is a thin pointer. Create a regular pointer type and give it the correct name. // This is a thin pointer. Create a regular pointer type and give it the correct name.
assert_eq!( assert_eq!(
(data_layout.pointer_size, data_layout.pointer_align.abi), (pointer_size, pointer_align.abi),
cx.size_and_align_of(ptr_type), cx.size_and_align_of(ptr_type),
"ptr_type={ptr_type}, pointee_type={pointee_type}", "ptr_type={ptr_type}, pointee_type={pointee_type}",
); );
@@ -174,8 +176,8 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>(
llvm::LLVMRustDIBuilderCreatePointerType( llvm::LLVMRustDIBuilderCreatePointerType(
DIB(cx), DIB(cx),
pointee_type_di_node, pointee_type_di_node,
data_layout.pointer_size.bits(), pointer_size.bits(),
data_layout.pointer_align.abi.bits() as u32, pointer_align.abi.bits() as u32,
0, // Ignore DWARF address space. 0, // Ignore DWARF address space.
ptr_type_debuginfo_name.as_c_char_ptr(), ptr_type_debuginfo_name.as_c_char_ptr(),
ptr_type_debuginfo_name.len(), ptr_type_debuginfo_name.len(),
@@ -319,7 +321,9 @@ fn build_subroutine_type_di_node<'ll, 'tcx>(
let name = compute_debuginfo_type_name(cx.tcx, fn_ty, false); let name = compute_debuginfo_type_name(cx.tcx, fn_ty, false);
let (size, align) = match fn_ty.kind() { let (size, align) = match fn_ty.kind() {
ty::FnDef(..) => (Size::ZERO, Align::ONE), ty::FnDef(..) => (Size::ZERO, Align::ONE),
ty::FnPtr(..) => (cx.tcx.data_layout.pointer_size, cx.tcx.data_layout.pointer_align.abi), ty::FnPtr(..) => {
(cx.tcx.data_layout.pointer_size(), cx.tcx.data_layout.pointer_align().abi)
}
_ => unreachable!(), _ => unreachable!(),
}; };
let di_node = unsafe { let di_node = unsafe {
@@ -504,7 +508,7 @@ fn recursion_marker_type_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) -> &'ll D
create_basic_type( create_basic_type(
cx, cx,
"<recur_type>", "<recur_type>",
cx.tcx.data_layout.pointer_size, cx.tcx.data_layout.pointer_size(),
dwarf_const::DW_ATE_unsigned, dwarf_const::DW_ATE_unsigned,
) )
}) })

View File

@@ -458,7 +458,7 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
// For rusty ABIs, small aggregates are actually passed // For rusty ABIs, small aggregates are actually passed
// as `RegKind::Integer` (see `FnAbi::adjust_for_abi`), // as `RegKind::Integer` (see `FnAbi::adjust_for_abi`),
// so we re-use that same threshold here. // so we re-use that same threshold here.
layout.size() <= self.data_layout().pointer_size * 2 layout.size() <= self.data_layout().pointer_size() * 2
} }
}; };
@@ -758,8 +758,8 @@ fn codegen_msvc_try<'ll, 'tcx>(
// } // }
// //
// More information can be found in libstd's seh.rs implementation. // More information can be found in libstd's seh.rs implementation.
let ptr_size = bx.tcx().data_layout.pointer_size; let ptr_size = bx.tcx().data_layout.pointer_size();
let ptr_align = bx.tcx().data_layout.pointer_align.abi; let ptr_align = bx.tcx().data_layout.pointer_align().abi;
let slot = bx.alloca(ptr_size, ptr_align); let slot = bx.alloca(ptr_size, ptr_align);
let try_func_ty = bx.type_func(&[bx.type_ptr()], bx.type_void()); let try_func_ty = bx.type_func(&[bx.type_ptr()], bx.type_void());
bx.invoke(try_func_ty, None, None, try_func, &[data], normal, catchswitch, None, None); bx.invoke(try_func_ty, None, None, try_func, &[data], normal, catchswitch, None, None);
@@ -1031,8 +1031,8 @@ fn codegen_emcc_try<'ll, 'tcx>(
// We need to pass two values to catch_func (ptr and is_rust_panic), so // We need to pass two values to catch_func (ptr and is_rust_panic), so
// create an alloca and pass a pointer to that. // create an alloca and pass a pointer to that.
let ptr_size = bx.tcx().data_layout.pointer_size; let ptr_size = bx.tcx().data_layout.pointer_size();
let ptr_align = bx.tcx().data_layout.pointer_align.abi; let ptr_align = bx.tcx().data_layout.pointer_align().abi;
let i8_align = bx.tcx().data_layout.i8_align.abi; let i8_align = bx.tcx().data_layout.i8_align.abi;
// Required in order for there to be no padding between the fields. // Required in order for there to be no padding between the fields.
assert!(i8_align <= ptr_align); assert!(i8_align <= ptr_align);
@@ -1158,9 +1158,11 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
macro_rules! require_int_or_uint_ty { macro_rules! require_int_or_uint_ty {
($ty: expr, $diag: expr) => { ($ty: expr, $diag: expr) => {
match $ty { match $ty {
ty::Int(i) => i.bit_width().unwrap_or_else(|| bx.data_layout().pointer_size.bits()), ty::Int(i) => {
i.bit_width().unwrap_or_else(|| bx.data_layout().pointer_size().bits())
}
ty::Uint(i) => { ty::Uint(i) => {
i.bit_width().unwrap_or_else(|| bx.data_layout().pointer_size.bits()) i.bit_width().unwrap_or_else(|| bx.data_layout().pointer_size().bits())
} }
_ => { _ => {
return_error!($diag); return_error!($diag);
@@ -2014,10 +2016,10 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
} else { } else {
let bitwidth = match in_elem.kind() { let bitwidth = match in_elem.kind() {
ty::Int(i) => { ty::Int(i) => {
i.bit_width().unwrap_or_else(|| bx.data_layout().pointer_size.bits()) i.bit_width().unwrap_or_else(|| bx.data_layout().pointer_size().bits())
} }
ty::Uint(i) => { ty::Uint(i) => {
i.bit_width().unwrap_or_else(|| bx.data_layout().pointer_size.bits()) i.bit_width().unwrap_or_else(|| bx.data_layout().pointer_size().bits())
} }
_ => return_error!(InvalidMonomorphization::UnsupportedSymbol { _ => return_error!(InvalidMonomorphization::UnsupportedSymbol {
span, span,

View File

@@ -113,7 +113,7 @@ impl ExtraBackendMethods for LlvmCodegenBackend {
) -> ModuleLlvm { ) -> ModuleLlvm {
let module_llvm = ModuleLlvm::new_metadata(tcx, module_name); let module_llvm = ModuleLlvm::new_metadata(tcx, module_name);
let cx = let cx =
SimpleCx::new(module_llvm.llmod(), &module_llvm.llcx, tcx.data_layout.pointer_size); SimpleCx::new(module_llvm.llmod(), &module_llvm.llcx, tcx.data_layout.pointer_size());
unsafe { unsafe {
allocator::codegen(tcx, cx, module_name, kind, alloc_error_handler_kind); allocator::codegen(tcx, cx, module_name, kind, alloc_error_handler_kind);
} }

View File

@@ -208,7 +208,7 @@ impl<'ll, CX: Borrow<SCx<'ll>>> BaseTypeCodegenMethods for GenericCx<'ll, CX> {
} }
fn type_ptr(&self) -> &'ll Type { fn type_ptr(&self) -> &'ll Type {
self.type_ptr_ext(AddressSpace::DATA) self.type_ptr_ext(AddressSpace::ZERO)
} }
fn type_ptr_ext(&self, address_space: AddressSpace) -> &'ll Type { fn type_ptr_ext(&self, address_space: AddressSpace) -> &'ll Type {
@@ -258,7 +258,7 @@ impl Type {
} }
pub(crate) fn ptr_llcx(llcx: &llvm::Context) -> &Type { pub(crate) fn ptr_llcx(llcx: &llvm::Context) -> &Type {
unsafe { llvm::LLVMPointerTypeInContext(llcx, AddressSpace::DATA.0) } unsafe { llvm::LLVMPointerTypeInContext(llcx, AddressSpace::ZERO.0) }
} }
} }

View File

@@ -45,7 +45,8 @@ fn emit_direct_ptr_va_arg<'ll, 'tcx>(
let va_list_ty = bx.type_ptr(); let va_list_ty = bx.type_ptr();
let va_list_addr = list.immediate(); let va_list_addr = list.immediate();
let ptr = bx.load(va_list_ty, va_list_addr, bx.tcx().data_layout.pointer_align.abi); let ptr_align_abi = bx.tcx().data_layout.pointer_align().abi;
let ptr = bx.load(va_list_ty, va_list_addr, ptr_align_abi);
let (addr, addr_align) = if allow_higher_align && align > slot_size { let (addr, addr_align) = if allow_higher_align && align > slot_size {
(round_pointer_up_to_alignment(bx, ptr, align, bx.type_ptr()), align) (round_pointer_up_to_alignment(bx, ptr, align, bx.type_ptr()), align)
@@ -56,7 +57,7 @@ fn emit_direct_ptr_va_arg<'ll, 'tcx>(
let aligned_size = size.align_to(slot_size).bytes() as i32; let aligned_size = size.align_to(slot_size).bytes() as i32;
let full_direct_size = bx.cx().const_i32(aligned_size); let full_direct_size = bx.cx().const_i32(aligned_size);
let next = bx.inbounds_ptradd(addr, full_direct_size); let next = bx.inbounds_ptradd(addr, full_direct_size);
bx.store(next, va_list_addr, bx.tcx().data_layout.pointer_align.abi); bx.store(next, va_list_addr, ptr_align_abi);
if size.bytes() < slot_size.bytes() if size.bytes() < slot_size.bytes()
&& bx.tcx().sess.target.endian == Endian::Big && bx.tcx().sess.target.endian == Endian::Big
@@ -108,8 +109,8 @@ fn emit_ptr_va_arg<'ll, 'tcx>(
let (llty, size, align) = if indirect { let (llty, size, align) = if indirect {
( (
bx.cx.layout_of(Ty::new_imm_ptr(bx.cx.tcx, target_ty)).llvm_type(bx.cx), bx.cx.layout_of(Ty::new_imm_ptr(bx.cx.tcx, target_ty)).llvm_type(bx.cx),
bx.cx.data_layout().pointer_size, bx.cx.data_layout().pointer_size(),
bx.cx.data_layout().pointer_align, bx.cx.data_layout().pointer_align(),
) )
} else { } else {
(layout.llvm_type(bx.cx), layout.size, layout.align) (layout.llvm_type(bx.cx), layout.size, layout.align)
@@ -204,7 +205,7 @@ fn emit_aapcs_va_arg<'ll, 'tcx>(
bx.switch_to_block(in_reg); bx.switch_to_block(in_reg);
let top_type = bx.type_ptr(); let top_type = bx.type_ptr();
let top = bx.load(top_type, reg_top, dl.pointer_align.abi); let top = bx.load(top_type, reg_top, dl.pointer_align().abi);
// reg_value = *(@top + reg_off_v); // reg_value = *(@top + reg_off_v);
let mut reg_addr = bx.ptradd(top, reg_off_v); let mut reg_addr = bx.ptradd(top, reg_off_v);
@@ -297,6 +298,7 @@ fn emit_powerpc_va_arg<'ll, 'tcx>(
let max_regs = 8u8; let max_regs = 8u8;
let use_regs = bx.icmp(IntPredicate::IntULT, num_regs, bx.const_u8(max_regs)); let use_regs = bx.icmp(IntPredicate::IntULT, num_regs, bx.const_u8(max_regs));
let ptr_align_abi = bx.tcx().data_layout.pointer_align().abi;
let in_reg = bx.append_sibling_block("va_arg.in_reg"); let in_reg = bx.append_sibling_block("va_arg.in_reg");
let in_mem = bx.append_sibling_block("va_arg.in_mem"); let in_mem = bx.append_sibling_block("va_arg.in_mem");
@@ -308,7 +310,7 @@ fn emit_powerpc_va_arg<'ll, 'tcx>(
bx.switch_to_block(in_reg); bx.switch_to_block(in_reg);
let reg_safe_area_ptr = bx.inbounds_ptradd(va_list_addr, bx.cx.const_usize(1 + 1 + 2 + 4)); let reg_safe_area_ptr = bx.inbounds_ptradd(va_list_addr, bx.cx.const_usize(1 + 1 + 2 + 4));
let mut reg_addr = bx.load(bx.type_ptr(), reg_safe_area_ptr, dl.pointer_align.abi); let mut reg_addr = bx.load(bx.type_ptr(), reg_safe_area_ptr, ptr_align_abi);
// Floating-point registers start after the general-purpose registers. // Floating-point registers start after the general-purpose registers.
if !is_int && !is_soft_float_abi { if !is_int && !is_soft_float_abi {
@@ -342,11 +344,11 @@ fn emit_powerpc_va_arg<'ll, 'tcx>(
let size = if !is_indirect { let size = if !is_indirect {
layout.layout.size.align_to(overflow_area_align) layout.layout.size.align_to(overflow_area_align)
} else { } else {
dl.pointer_size dl.pointer_size()
}; };
let overflow_area_ptr = bx.inbounds_ptradd(va_list_addr, bx.cx.const_usize(1 + 1 + 2)); let overflow_area_ptr = bx.inbounds_ptradd(va_list_addr, bx.cx.const_usize(1 + 1 + 2));
let mut overflow_area = bx.load(bx.type_ptr(), overflow_area_ptr, dl.pointer_align.abi); let mut overflow_area = bx.load(bx.type_ptr(), overflow_area_ptr, ptr_align_abi);
// Round up address of argument to alignment // Round up address of argument to alignment
if layout.layout.align.abi > overflow_area_align { if layout.layout.align.abi > overflow_area_align {
@@ -362,7 +364,7 @@ fn emit_powerpc_va_arg<'ll, 'tcx>(
// Increase the overflow area. // Increase the overflow area.
overflow_area = bx.inbounds_ptradd(overflow_area, bx.const_usize(size.bytes())); overflow_area = bx.inbounds_ptradd(overflow_area, bx.const_usize(size.bytes()));
bx.store(overflow_area, overflow_area_ptr, dl.pointer_align.abi); bx.store(overflow_area, overflow_area_ptr, ptr_align_abi);
bx.br(end); bx.br(end);
@@ -373,11 +375,8 @@ fn emit_powerpc_va_arg<'ll, 'tcx>(
bx.switch_to_block(end); bx.switch_to_block(end);
let val_addr = bx.phi(bx.type_ptr(), &[reg_addr, mem_addr], &[in_reg, in_mem]); let val_addr = bx.phi(bx.type_ptr(), &[reg_addr, mem_addr], &[in_reg, in_mem]);
let val_type = layout.llvm_type(bx); let val_type = layout.llvm_type(bx);
let val_addr = if is_indirect { let val_addr =
bx.load(bx.cx.type_ptr(), val_addr, dl.pointer_align.abi) if is_indirect { bx.load(bx.cx.type_ptr(), val_addr, ptr_align_abi) } else { val_addr };
} else {
val_addr
};
bx.load(val_type, val_addr, layout.align.abi) bx.load(val_type, val_addr, layout.align.abi)
} }
@@ -414,6 +413,7 @@ fn emit_s390x_va_arg<'ll, 'tcx>(
let in_reg = bx.append_sibling_block("va_arg.in_reg"); let in_reg = bx.append_sibling_block("va_arg.in_reg");
let in_mem = bx.append_sibling_block("va_arg.in_mem"); let in_mem = bx.append_sibling_block("va_arg.in_mem");
let end = bx.append_sibling_block("va_arg.end"); let end = bx.append_sibling_block("va_arg.end");
let ptr_align_abi = dl.pointer_align().abi;
// FIXME: vector ABI not yet supported. // FIXME: vector ABI not yet supported.
let target_ty_size = bx.cx.size_of(target_ty).bytes(); let target_ty_size = bx.cx.size_of(target_ty).bytes();
@@ -435,7 +435,7 @@ fn emit_s390x_va_arg<'ll, 'tcx>(
bx.switch_to_block(in_reg); bx.switch_to_block(in_reg);
// Work out the address of the value in the register save area. // Work out the address of the value in the register save area.
let reg_ptr_v = bx.load(bx.type_ptr(), reg_save_area, dl.pointer_align.abi); let reg_ptr_v = bx.load(bx.type_ptr(), reg_save_area, ptr_align_abi);
let scaled_reg_count = bx.mul(reg_count_v, bx.const_u64(8)); let scaled_reg_count = bx.mul(reg_count_v, bx.const_u64(8));
let reg_off = bx.add(scaled_reg_count, bx.const_u64(reg_save_index * 8 + reg_padding)); let reg_off = bx.add(scaled_reg_count, bx.const_u64(reg_save_index * 8 + reg_padding));
let reg_addr = bx.ptradd(reg_ptr_v, reg_off); let reg_addr = bx.ptradd(reg_ptr_v, reg_off);
@@ -449,15 +449,14 @@ fn emit_s390x_va_arg<'ll, 'tcx>(
bx.switch_to_block(in_mem); bx.switch_to_block(in_mem);
// Work out the address of the value in the argument overflow area. // Work out the address of the value in the argument overflow area.
let arg_ptr_v = let arg_ptr_v = bx.load(bx.type_ptr(), overflow_arg_area, ptr_align_abi);
bx.load(bx.type_ptr(), overflow_arg_area, bx.tcx().data_layout.pointer_align.abi);
let arg_off = bx.const_u64(padding); let arg_off = bx.const_u64(padding);
let mem_addr = bx.ptradd(arg_ptr_v, arg_off); let mem_addr = bx.ptradd(arg_ptr_v, arg_off);
// Update the argument overflow area pointer. // Update the argument overflow area pointer.
let arg_size = bx.cx().const_u64(padded_size); let arg_size = bx.cx().const_u64(padded_size);
let new_arg_ptr_v = bx.inbounds_ptradd(arg_ptr_v, arg_size); let new_arg_ptr_v = bx.inbounds_ptradd(arg_ptr_v, arg_size);
bx.store(new_arg_ptr_v, overflow_arg_area, dl.pointer_align.abi); bx.store(new_arg_ptr_v, overflow_arg_area, ptr_align_abi);
bx.br(end); bx.br(end);
// Return the appropriate result. // Return the appropriate result.
@@ -465,7 +464,7 @@ fn emit_s390x_va_arg<'ll, 'tcx>(
let val_addr = bx.phi(bx.type_ptr(), &[reg_addr, mem_addr], &[in_reg, in_mem]); let val_addr = bx.phi(bx.type_ptr(), &[reg_addr, mem_addr], &[in_reg, in_mem]);
let val_type = layout.llvm_type(bx); let val_type = layout.llvm_type(bx);
let val_addr = let val_addr =
if indirect { bx.load(bx.cx.type_ptr(), val_addr, dl.pointer_align.abi) } else { val_addr }; if indirect { bx.load(bx.cx.type_ptr(), val_addr, ptr_align_abi) } else { val_addr };
bx.load(val_type, val_addr, layout.align.abi) bx.load(val_type, val_addr, layout.align.abi)
} }
@@ -607,7 +606,7 @@ fn emit_x86_64_sysv64_va_arg<'ll, 'tcx>(
// loads than necessary. Can we clean this up? // loads than necessary. Can we clean this up?
let reg_save_area_ptr = let reg_save_area_ptr =
bx.inbounds_ptradd(va_list_addr, bx.cx.const_usize(2 * unsigned_int_offset + ptr_offset)); bx.inbounds_ptradd(va_list_addr, bx.cx.const_usize(2 * unsigned_int_offset + ptr_offset));
let reg_save_area_v = bx.load(bx.type_ptr(), reg_save_area_ptr, dl.pointer_align.abi); let reg_save_area_v = bx.load(bx.type_ptr(), reg_save_area_ptr, dl.pointer_align().abi);
let reg_addr = match layout.layout.backend_repr() { let reg_addr = match layout.layout.backend_repr() {
BackendRepr::Scalar(scalar) => match scalar.primitive() { BackendRepr::Scalar(scalar) => match scalar.primitive() {
@@ -749,10 +748,11 @@ fn x86_64_sysv64_va_arg_from_memory<'ll, 'tcx>(
layout: TyAndLayout<'tcx, Ty<'tcx>>, layout: TyAndLayout<'tcx, Ty<'tcx>>,
) -> &'ll Value { ) -> &'ll Value {
let dl = bx.cx.data_layout(); let dl = bx.cx.data_layout();
let ptr_align_abi = dl.data_layout().pointer_align().abi;
let overflow_arg_area_ptr = bx.inbounds_ptradd(va_list_addr, bx.const_usize(8)); let overflow_arg_area_ptr = bx.inbounds_ptradd(va_list_addr, bx.const_usize(8));
let overflow_arg_area_v = bx.load(bx.type_ptr(), overflow_arg_area_ptr, dl.pointer_align.abi); let overflow_arg_area_v = bx.load(bx.type_ptr(), overflow_arg_area_ptr, ptr_align_abi);
// AMD64-ABI 3.5.7p5: Step 7. Align l->overflow_arg_area upwards to a 16 // AMD64-ABI 3.5.7p5: Step 7. Align l->overflow_arg_area upwards to a 16
// byte boundary if alignment needed by type exceeds 8 byte boundary. // byte boundary if alignment needed by type exceeds 8 byte boundary.
// It isn't stated explicitly in the standard, but in practice we use // It isn't stated explicitly in the standard, but in practice we use
@@ -771,7 +771,7 @@ fn x86_64_sysv64_va_arg_from_memory<'ll, 'tcx>(
let size_in_bytes = layout.layout.size().bytes(); let size_in_bytes = layout.layout.size().bytes();
let offset = bx.const_i32(size_in_bytes.next_multiple_of(8) as i32); let offset = bx.const_i32(size_in_bytes.next_multiple_of(8) as i32);
let overflow_arg_area = bx.inbounds_ptradd(overflow_arg_area_v, offset); let overflow_arg_area = bx.inbounds_ptradd(overflow_arg_area_v, offset);
bx.store(overflow_arg_area, overflow_arg_area_ptr, dl.pointer_align.abi); bx.store(overflow_arg_area, overflow_arg_area_ptr, ptr_align_abi);
mem_addr mem_addr
} }
@@ -803,6 +803,7 @@ fn emit_xtensa_va_arg<'ll, 'tcx>(
let from_stack = bx.append_sibling_block("va_arg.from_stack"); let from_stack = bx.append_sibling_block("va_arg.from_stack");
let from_regsave = bx.append_sibling_block("va_arg.from_regsave"); let from_regsave = bx.append_sibling_block("va_arg.from_regsave");
let end = bx.append_sibling_block("va_arg.end"); let end = bx.append_sibling_block("va_arg.end");
let ptr_align_abi = bx.tcx().data_layout.pointer_align().abi;
// (*va).va_ndx // (*va).va_ndx
let va_reg_offset = 4; let va_reg_offset = 4;
@@ -825,12 +826,11 @@ fn emit_xtensa_va_arg<'ll, 'tcx>(
bx.switch_to_block(from_regsave); bx.switch_to_block(from_regsave);
// update va_ndx // update va_ndx
bx.store(offset_next, offset_ptr, bx.tcx().data_layout.pointer_align.abi); bx.store(offset_next, offset_ptr, ptr_align_abi);
// (*va).va_reg // (*va).va_reg
let regsave_area_ptr = bx.inbounds_ptradd(va_list_addr, bx.cx.const_usize(va_reg_offset)); let regsave_area_ptr = bx.inbounds_ptradd(va_list_addr, bx.cx.const_usize(va_reg_offset));
let regsave_area = let regsave_area = bx.load(bx.type_ptr(), regsave_area_ptr, ptr_align_abi);
bx.load(bx.type_ptr(), regsave_area_ptr, bx.tcx().data_layout.pointer_align.abi);
let regsave_value_ptr = bx.inbounds_ptradd(regsave_area, offset); let regsave_value_ptr = bx.inbounds_ptradd(regsave_area, offset);
bx.br(end); bx.br(end);
@@ -849,11 +849,11 @@ fn emit_xtensa_va_arg<'ll, 'tcx>(
// va_ndx = offset_next_corrected; // va_ndx = offset_next_corrected;
let offset_next_corrected = bx.add(offset_next, bx.const_i32(slot_size)); let offset_next_corrected = bx.add(offset_next, bx.const_i32(slot_size));
// update va_ndx // update va_ndx
bx.store(offset_next_corrected, offset_ptr, bx.tcx().data_layout.pointer_align.abi); bx.store(offset_next_corrected, offset_ptr, ptr_align_abi);
// let stack_value_ptr = unsafe { (*va).va_stk.byte_add(offset_corrected) }; // let stack_value_ptr = unsafe { (*va).va_stk.byte_add(offset_corrected) };
let stack_area_ptr = bx.inbounds_ptradd(va_list_addr, bx.cx.const_usize(0)); let stack_area_ptr = bx.inbounds_ptradd(va_list_addr, bx.cx.const_usize(0));
let stack_area = bx.load(bx.type_ptr(), stack_area_ptr, bx.tcx().data_layout.pointer_align.abi); let stack_area = bx.load(bx.type_ptr(), stack_area_ptr, ptr_align_abi);
let stack_value_ptr = bx.inbounds_ptradd(stack_area, offset_corrected); let stack_value_ptr = bx.inbounds_ptradd(stack_area, offset_corrected);
bx.br(end); bx.br(end);

View File

@@ -1208,7 +1208,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
split_debuginfo: tcx.sess.split_debuginfo(), split_debuginfo: tcx.sess.split_debuginfo(),
split_dwarf_kind: tcx.sess.opts.unstable_opts.split_dwarf_kind, split_dwarf_kind: tcx.sess.opts.unstable_opts.split_dwarf_kind,
parallel: backend.supports_parallel() && !sess.opts.unstable_opts.no_parallel_backend, parallel: backend.supports_parallel() && !sess.opts.unstable_opts.no_parallel_backend,
pointer_size: tcx.data_layout.pointer_size, pointer_size: tcx.data_layout.pointer_size(),
invocation_temp: sess.invocation_temp.clone(), invocation_temp: sess.invocation_temp.clone(),
}; };

View File

@@ -200,7 +200,7 @@ fn unsized_info<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
let vptr_entry_idx = cx.tcx().supertrait_vtable_slot((source, target)); let vptr_entry_idx = cx.tcx().supertrait_vtable_slot((source, target));
if let Some(entry_idx) = vptr_entry_idx { if let Some(entry_idx) = vptr_entry_idx {
let ptr_size = bx.data_layout().pointer_size; let ptr_size = bx.data_layout().pointer_size();
let vtable_byte_offset = u64::try_from(entry_idx).unwrap() * ptr_size.bytes(); let vtable_byte_offset = u64::try_from(entry_idx).unwrap() * ptr_size.bytes();
load_vtable(bx, old_info, bx.type_ptr(), vtable_byte_offset, source, true) load_vtable(bx, old_info, bx.type_ptr(), vtable_byte_offset, source, true)
} else { } else {
@@ -577,8 +577,8 @@ fn get_argc_argv<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(bx: &mut Bx) -> (Bx::Va
// Params for UEFI // Params for UEFI
let param_handle = bx.get_param(0); let param_handle = bx.get_param(0);
let param_system_table = bx.get_param(1); let param_system_table = bx.get_param(1);
let ptr_size = bx.tcx().data_layout.pointer_size; let ptr_size = bx.tcx().data_layout.pointer_size();
let ptr_align = bx.tcx().data_layout.pointer_align.abi; let ptr_align = bx.tcx().data_layout.pointer_align().abi;
let arg_argc = bx.const_int(bx.cx().type_isize(), 2); let arg_argc = bx.const_int(bx.cx().type_isize(), 2);
let arg_argv = bx.alloca(2 * ptr_size, ptr_align); let arg_argv = bx.alloca(2 * ptr_size, ptr_align);
bx.store(param_handle, arg_argv, ptr_align); bx.store(param_handle, arg_argv, ptr_align);

View File

@@ -27,7 +27,7 @@ impl<'a, 'tcx> VirtualIndex {
debug!("get_fn({llvtable:?}, {ty:?}, {self:?})"); debug!("get_fn({llvtable:?}, {ty:?}, {self:?})");
let llty = bx.fn_ptr_backend_type(fn_abi); let llty = bx.fn_ptr_backend_type(fn_abi);
let ptr_size = bx.data_layout().pointer_size; let ptr_size = bx.data_layout().pointer_size();
let vtable_byte_offset = self.0 * ptr_size.bytes(); let vtable_byte_offset = self.0 * ptr_size.bytes();
load_vtable(bx, llvtable, llty, vtable_byte_offset, ty, nonnull) load_vtable(bx, llvtable, llty, vtable_byte_offset, ty, nonnull)
@@ -63,7 +63,7 @@ impl<'a, 'tcx> VirtualIndex {
debug!("get_int({:?}, {:?})", llvtable, self); debug!("get_int({:?}, {:?})", llvtable, self);
let llty = bx.type_isize(); let llty = bx.type_isize();
let ptr_size = bx.data_layout().pointer_size; let ptr_size = bx.data_layout().pointer_size();
let vtable_byte_offset = self.0 * ptr_size.bytes(); let vtable_byte_offset = self.0 * ptr_size.bytes();
load_vtable(bx, llvtable, llty, vtable_byte_offset, ty, false) load_vtable(bx, llvtable, llty, vtable_byte_offset, ty, false)
@@ -115,7 +115,7 @@ pub(crate) fn get_vtable<'tcx, Cx: CodegenMethods<'tcx>>(
let vtable_alloc_id = tcx.vtable_allocation((ty, trait_ref)); let vtable_alloc_id = tcx.vtable_allocation((ty, trait_ref));
let vtable_allocation = tcx.global_alloc(vtable_alloc_id).unwrap_memory(); let vtable_allocation = tcx.global_alloc(vtable_alloc_id).unwrap_memory();
let vtable_const = cx.const_data_from_alloc(vtable_allocation); let vtable_const = cx.const_data_from_alloc(vtable_allocation);
let align = cx.data_layout().pointer_align.abi; let align = cx.data_layout().pointer_align().abi;
let vtable = cx.static_addr_of(vtable_const, align, Some("vtable")); let vtable = cx.static_addr_of(vtable_const, align, Some("vtable"));
cx.apply_vcall_visibility_metadata(ty, trait_ref, vtable); cx.apply_vcall_visibility_metadata(ty, trait_ref, vtable);
@@ -133,7 +133,7 @@ pub(crate) fn load_vtable<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
ty: Ty<'tcx>, ty: Ty<'tcx>,
nonnull: bool, nonnull: bool,
) -> Bx::Value { ) -> Bx::Value {
let ptr_align = bx.data_layout().pointer_align.abi; let ptr_align = bx.data_layout().pointer_align().abi;
if bx.cx().sess().opts.unstable_opts.virtual_function_elimination if bx.cx().sess().opts.unstable_opts.virtual_function_elimination
&& bx.cx().sess().lto() == Lto::Fat && bx.cx().sess().lto() == Lto::Fat

View File

@@ -326,7 +326,7 @@ fn prefix_and_suffix<'tcx>(
fn wasm_functype<'tcx>(tcx: TyCtxt<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> String { fn wasm_functype<'tcx>(tcx: TyCtxt<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> String {
let mut signature = String::with_capacity(64); let mut signature = String::with_capacity(64);
let ptr_type = match tcx.data_layout.pointer_size.bits() { let ptr_type = match tcx.data_layout.pointer_size().bits() {
32 => "i32", 32 => "i32",
64 => "i64", 64 => "i64",
other => bug!("wasm pointer size cannot be {other} bits"), other => bug!("wasm pointer size cannot be {other} bits"),

View File

@@ -1135,7 +1135,7 @@ fn assume_scalar_range<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
let range = scalar.valid_range(bx.cx()); let range = scalar.valid_range(bx.cx());
bx.assume_integer_range(imm, backend_ty, range); bx.assume_integer_range(imm, backend_ty, range);
} }
abi::Primitive::Pointer(abi::AddressSpace::DATA) abi::Primitive::Pointer(abi::AddressSpace::ZERO)
if !scalar.valid_range(bx.cx()).contains(0) => if !scalar.valid_range(bx.cx()).contains(0) =>
{ {
bx.assume_nonnull(imm); bx.assume_nonnull(imm);

View File

@@ -1233,7 +1233,7 @@ impl<'a, 'tcx, Prov: Provenance, Extra, Bytes: AllocBytes>
/// `offset` is relative to this allocation reference, not the base of the allocation. /// `offset` is relative to this allocation reference, not the base of the allocation.
pub fn write_ptr_sized(&mut self, offset: Size, val: Scalar<Prov>) -> InterpResult<'tcx> { pub fn write_ptr_sized(&mut self, offset: Size, val: Scalar<Prov>) -> InterpResult<'tcx> {
self.write_scalar(alloc_range(offset, self.tcx.data_layout().pointer_size), val) self.write_scalar(alloc_range(offset, self.tcx.data_layout().pointer_size()), val)
} }
/// Mark the given sub-range (relative to this allocation reference) as uninitialized. /// Mark the given sub-range (relative to this allocation reference) as uninitialized.
@@ -1285,7 +1285,7 @@ impl<'a, 'tcx, Prov: Provenance, Extra, Bytes: AllocBytes> AllocRef<'a, 'tcx, Pr
/// `offset` is relative to this allocation reference, not the base of the allocation. /// `offset` is relative to this allocation reference, not the base of the allocation.
pub fn read_pointer(&self, offset: Size) -> InterpResult<'tcx, Scalar<Prov>> { pub fn read_pointer(&self, offset: Size) -> InterpResult<'tcx, Scalar<Prov>> {
self.read_scalar( self.read_scalar(
alloc_range(offset, self.tcx.data_layout().pointer_size), alloc_range(offset, self.tcx.data_layout().pointer_size()),
/*read_provenance*/ true, /*read_provenance*/ true,
) )
} }

View File

@@ -41,5 +41,8 @@ errors_target_invalid_bits =
errors_target_invalid_bits_size = {$err} errors_target_invalid_bits_size = {$err}
errors_target_invalid_datalayout_pointer_spec =
unknown pointer specification `{$err}` in datalayout string
errors_target_missing_alignment = errors_target_missing_alignment =
missing alignment for `{$cause}` in "data-layout" missing alignment for `{$cause}` in "data-layout"

View File

@@ -374,6 +374,10 @@ impl<G: EmissionGuarantee> Diagnostic<'_, G> for TargetDataLayoutErrors<'_> {
TargetDataLayoutErrors::InvalidBitsSize { err } => { TargetDataLayoutErrors::InvalidBitsSize { err } => {
Diag::new(dcx, level, fluent::errors_target_invalid_bits_size).with_arg("err", err) Diag::new(dcx, level, fluent::errors_target_invalid_bits_size).with_arg("err", err)
} }
TargetDataLayoutErrors::UnknownPointerSpecification { err } => {
Diag::new(dcx, level, fluent::errors_target_invalid_datalayout_pointer_spec)
.with_arg("err", err)
}
} }
} }
} }

View File

@@ -142,7 +142,7 @@ impl<'tcx> ConstValue<'tcx> {
// The reference itself is stored behind an indirection. // The reference itself is stored behind an indirection.
// Load the reference, and then load the actual slice contents. // Load the reference, and then load the actual slice contents.
let a = tcx.global_alloc(alloc_id).unwrap_memory().inner(); let a = tcx.global_alloc(alloc_id).unwrap_memory().inner();
let ptr_size = tcx.data_layout.pointer_size; let ptr_size = tcx.data_layout.pointer_size();
if a.size() < offset + 2 * ptr_size { if a.size() < offset + 2 * ptr_size {
// (partially) dangling reference // (partially) dangling reference
return None; return None;

View File

@@ -519,7 +519,7 @@ impl Allocation {
let mut bytes = alloc_bytes(&*self.bytes, self.align)?; let mut bytes = alloc_bytes(&*self.bytes, self.align)?;
// Adjust provenance of pointers stored in this allocation. // Adjust provenance of pointers stored in this allocation.
let mut new_provenance = Vec::with_capacity(self.provenance.ptrs().len()); let mut new_provenance = Vec::with_capacity(self.provenance.ptrs().len());
let ptr_size = cx.data_layout().pointer_size.bytes_usize(); let ptr_size = cx.data_layout().pointer_size().bytes_usize();
let endian = cx.data_layout().endian; let endian = cx.data_layout().endian;
for &(offset, alloc_id) in self.provenance.ptrs().iter() { for &(offset, alloc_id) in self.provenance.ptrs().iter() {
let idx = offset.bytes_usize(); let idx = offset.bytes_usize();
@@ -709,7 +709,7 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes>
let bits = read_target_uint(cx.data_layout().endian, bytes).unwrap(); let bits = read_target_uint(cx.data_layout().endian, bytes).unwrap();
if read_provenance { if read_provenance {
assert_eq!(range.size, cx.data_layout().pointer_size); assert_eq!(range.size, cx.data_layout().pointer_size());
// When reading data with provenance, the easy case is finding provenance exactly where we // When reading data with provenance, the easy case is finding provenance exactly where we
// are reading, then we can put data and provenance back together and return that. // are reading, then we can put data and provenance back together and return that.
@@ -782,7 +782,7 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes>
// See if we have to also store some provenance. // See if we have to also store some provenance.
if let Some(provenance) = provenance { if let Some(provenance) = provenance {
assert_eq!(range.size, cx.data_layout().pointer_size); assert_eq!(range.size, cx.data_layout().pointer_size());
self.provenance.insert_ptr(range.start, provenance, cx); self.provenance.insert_ptr(range.start, provenance, cx);
} }

View File

@@ -71,7 +71,7 @@ impl<Prov: Provenance> ProvenanceMap<Prov> {
// We have to go back `pointer_size - 1` bytes, as that one would still overlap with // We have to go back `pointer_size - 1` bytes, as that one would still overlap with
// the beginning of this range. // the beginning of this range.
let adjusted_start = Size::from_bytes( let adjusted_start = Size::from_bytes(
range.start.bytes().saturating_sub(cx.data_layout().pointer_size.bytes() - 1), range.start.bytes().saturating_sub(cx.data_layout().pointer_size().bytes() - 1),
); );
adjusted_start..range.end() adjusted_start..range.end()
} }
@@ -142,7 +142,7 @@ impl<Prov: Provenance> ProvenanceMap<Prov> {
} }
pub fn insert_ptr(&mut self, offset: Size, prov: Prov, cx: &impl HasDataLayout) { pub fn insert_ptr(&mut self, offset: Size, prov: Prov, cx: &impl HasDataLayout) {
debug_assert!(self.range_empty(alloc_range(offset, cx.data_layout().pointer_size), cx)); debug_assert!(self.range_empty(alloc_range(offset, cx.data_layout().pointer_size()), cx));
self.ptrs.insert(offset, prov); self.ptrs.insert(offset, prov);
} }
@@ -160,6 +160,8 @@ impl<Prov: Provenance> ProvenanceMap<Prov> {
debug_assert!(self.bytes.is_none()); debug_assert!(self.bytes.is_none());
} }
let pointer_size = cx.data_layout().pointer_size();
// For the ptr-sized part, find the first (inclusive) and last (exclusive) byte of // For the ptr-sized part, find the first (inclusive) and last (exclusive) byte of
// provenance that overlaps with the given range. // provenance that overlaps with the given range.
let (first, last) = { let (first, last) = {
@@ -172,10 +174,7 @@ impl<Prov: Provenance> ProvenanceMap<Prov> {
// This redoes some of the work of `range_get_ptrs_is_empty`, but this path is much // This redoes some of the work of `range_get_ptrs_is_empty`, but this path is much
// colder than the early return above, so it's worth it. // colder than the early return above, so it's worth it.
let provenance = self.range_ptrs_get(range, cx); let provenance = self.range_ptrs_get(range, cx);
( (provenance.first().unwrap().0, provenance.last().unwrap().0 + pointer_size)
provenance.first().unwrap().0,
provenance.last().unwrap().0 + cx.data_layout().pointer_size,
)
}; };
// We need to handle clearing the provenance from parts of a pointer. // We need to handle clearing the provenance from parts of a pointer.
@@ -192,7 +191,7 @@ impl<Prov: Provenance> ProvenanceMap<Prov> {
} }
} }
if last > end { if last > end {
let begin_of_last = last - cx.data_layout().pointer_size; let begin_of_last = last - pointer_size;
if !Prov::OFFSET_IS_ADDR { if !Prov::OFFSET_IS_ADDR {
// We can't split up the provenance into less than a pointer. // We can't split up the provenance into less than a pointer.
return Err(AllocError::OverwritePartialPointer(begin_of_last)); return Err(AllocError::OverwritePartialPointer(begin_of_last));
@@ -255,7 +254,7 @@ impl<Prov: Provenance> ProvenanceMap<Prov> {
// shift offsets from source allocation to destination allocation // shift offsets from source allocation to destination allocation
(offset - src.start) + dest_offset // `Size` operations (offset - src.start) + dest_offset // `Size` operations
}; };
let ptr_size = cx.data_layout().pointer_size; let ptr_size = cx.data_layout().pointer_size();
// # Pointer-sized provenances // # Pointer-sized provenances
// Get the provenances that are entirely within this range. // Get the provenances that are entirely within this range.

View File

@@ -297,7 +297,7 @@ impl<'tcx> GlobalAlloc<'tcx> {
match self { match self {
GlobalAlloc::Function { .. } => cx.data_layout().instruction_address_space, GlobalAlloc::Function { .. } => cx.data_layout().instruction_address_space,
GlobalAlloc::Static(..) | GlobalAlloc::Memory(..) | GlobalAlloc::VTable(..) => { GlobalAlloc::Static(..) | GlobalAlloc::Memory(..) | GlobalAlloc::VTable(..) => {
AddressSpace::DATA AddressSpace::ZERO
} }
} }
} }
@@ -380,7 +380,7 @@ impl<'tcx> GlobalAlloc<'tcx> {
GlobalAlloc::Function { .. } => (Size::ZERO, Align::ONE), GlobalAlloc::Function { .. } => (Size::ZERO, Align::ONE),
GlobalAlloc::VTable(..) => { GlobalAlloc::VTable(..) => {
// No data to be accessed here. But vtables are pointer-aligned. // No data to be accessed here. But vtables are pointer-aligned.
return (Size::ZERO, tcx.data_layout.pointer_align.abi); return (Size::ZERO, tcx.data_layout.pointer_align().abi);
} }
} }
} }

View File

@@ -16,7 +16,7 @@ pub trait PointerArithmetic: HasDataLayout {
#[inline(always)] #[inline(always)]
fn pointer_size(&self) -> Size { fn pointer_size(&self) -> Size {
self.data_layout().pointer_size self.data_layout().pointer_size()
} }
#[inline(always)] #[inline(always)]

View File

@@ -167,7 +167,7 @@ impl<Prov> Scalar<Prov> {
#[inline] #[inline]
pub fn from_target_usize(i: u64, cx: &impl HasDataLayout) -> Self { pub fn from_target_usize(i: u64, cx: &impl HasDataLayout) -> Self {
Self::from_uint(i, cx.data_layout().pointer_size) Self::from_uint(i, cx.data_layout().pointer_offset())
} }
#[inline] #[inline]
@@ -205,7 +205,7 @@ impl<Prov> Scalar<Prov> {
#[inline] #[inline]
pub fn from_target_isize(i: i64, cx: &impl HasDataLayout) -> Self { pub fn from_target_isize(i: i64, cx: &impl HasDataLayout) -> Self {
Self::from_int(i, cx.data_layout().pointer_size) Self::from_int(i, cx.data_layout().pointer_offset())
} }
#[inline] #[inline]
@@ -393,7 +393,7 @@ impl<'tcx, Prov: Provenance> Scalar<Prov> {
/// Converts the scalar to produce a machine-pointer-sized unsigned integer. /// Converts the scalar to produce a machine-pointer-sized unsigned integer.
/// Fails if the scalar is a pointer. /// Fails if the scalar is a pointer.
pub fn to_target_usize(self, cx: &impl HasDataLayout) -> InterpResult<'tcx, u64> { pub fn to_target_usize(self, cx: &impl HasDataLayout) -> InterpResult<'tcx, u64> {
let b = self.to_uint(cx.data_layout().pointer_size)?; let b = self.to_uint(cx.data_layout().pointer_size())?;
interp_ok(u64::try_from(b).unwrap()) interp_ok(u64::try_from(b).unwrap())
} }
@@ -433,7 +433,7 @@ impl<'tcx, Prov: Provenance> Scalar<Prov> {
/// Converts the scalar to produce a machine-pointer-sized signed integer. /// Converts the scalar to produce a machine-pointer-sized signed integer.
/// Fails if the scalar is a pointer. /// Fails if the scalar is a pointer.
pub fn to_target_isize(self, cx: &impl HasDataLayout) -> InterpResult<'tcx, i64> { pub fn to_target_isize(self, cx: &impl HasDataLayout) -> InterpResult<'tcx, i64> {
let b = self.to_int(cx.data_layout().pointer_size)?; let b = self.to_int(cx.data_layout().pointer_size())?;
interp_ok(i64::try_from(b).unwrap()) interp_ok(i64::try_from(b).unwrap())
} }

View File

@@ -1753,7 +1753,7 @@ pub fn write_allocation_bytes<'tcx, Prov: Provenance, Extra, Bytes: AllocBytes>(
let mut i = Size::ZERO; let mut i = Size::ZERO;
let mut line_start = Size::ZERO; let mut line_start = Size::ZERO;
let ptr_size = tcx.data_layout.pointer_size; let ptr_size = tcx.data_layout.pointer_size();
let mut ascii = String::new(); let mut ascii = String::new();

View File

@@ -252,7 +252,7 @@ impl ScalarInt {
#[inline] #[inline]
pub fn try_from_target_usize(i: impl Into<u128>, tcx: TyCtxt<'_>) -> Option<Self> { pub fn try_from_target_usize(i: impl Into<u128>, tcx: TyCtxt<'_>) -> Option<Self> {
Self::try_from_uint(i, tcx.data_layout.pointer_size) Self::try_from_uint(i, tcx.data_layout.pointer_size())
} }
/// Try to convert this ScalarInt to the raw underlying bits. /// Try to convert this ScalarInt to the raw underlying bits.
@@ -328,7 +328,7 @@ impl ScalarInt {
#[inline] #[inline]
pub fn to_target_usize(&self, tcx: TyCtxt<'_>) -> u64 { pub fn to_target_usize(&self, tcx: TyCtxt<'_>) -> u64 {
self.to_uint(tcx.data_layout.pointer_size).try_into().unwrap() self.to_uint(tcx.data_layout.pointer_size()).try_into().unwrap()
} }
#[inline] #[inline]
@@ -402,7 +402,7 @@ impl ScalarInt {
#[inline] #[inline]
pub fn to_target_isize(&self, tcx: TyCtxt<'_>) -> i64 { pub fn to_target_isize(&self, tcx: TyCtxt<'_>) -> i64 {
self.to_int(tcx.data_layout.pointer_size).try_into().unwrap() self.to_int(tcx.data_layout.pointer_size()).try_into().unwrap()
} }
#[inline] #[inline]

View File

@@ -1067,7 +1067,7 @@ where
if let Some(variant) = data_variant { if let Some(variant) = data_variant {
// FIXME(erikdesjardins): handle non-default addrspace ptr sizes // FIXME(erikdesjardins): handle non-default addrspace ptr sizes
// (requires passing in the expected address space from the caller) // (requires passing in the expected address space from the caller)
let ptr_end = offset + Primitive::Pointer(AddressSpace::DATA).size(cx); let ptr_end = offset + Primitive::Pointer(AddressSpace::ZERO).size(cx);
for i in 0..variant.fields.count() { for i in 0..variant.fields.count() {
let field_start = variant.fields.offset(i); let field_start = variant.fields.offset(i);
if field_start <= offset { if field_start <= offset {

View File

@@ -1842,7 +1842,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
} }
// Pointer types // Pointer types
ty::Ref(..) | ty::RawPtr(_, _) | ty::FnPtr(..) => { ty::Ref(..) | ty::RawPtr(_, _) | ty::FnPtr(..) => {
let data = int.to_bits(self.tcx().data_layout.pointer_size); let data = int.to_bits(self.tcx().data_layout.pointer_size());
self.typed_value( self.typed_value(
|this| { |this| {
write!(this, "0x{data:x}")?; write!(this, "0x{data:x}")?;

View File

@@ -106,8 +106,8 @@ pub(super) fn vtable_allocation_provider<'tcx>(
let size = layout.size.bytes(); let size = layout.size.bytes();
let align = layout.align.abi.bytes(); let align = layout.align.abi.bytes();
let ptr_size = tcx.data_layout.pointer_size; let ptr_size = tcx.data_layout.pointer_size();
let ptr_align = tcx.data_layout.pointer_align.abi; let ptr_align = tcx.data_layout.pointer_align().abi;
let vtable_size = ptr_size * u64::try_from(vtable_entries.len()).unwrap(); let vtable_size = ptr_size * u64::try_from(vtable_entries.len()).unwrap();
let mut vtable = Allocation::new(vtable_size, ptr_align, AllocInit::Uninit, ()); let mut vtable = Allocation::new(vtable_size, ptr_align, AllocInit::Uninit, ());

View File

@@ -20,7 +20,7 @@ pub(crate) fn lit_to_const<'tcx>(
let trunc = |n, width: ty::UintTy| { let trunc = |n, width: ty::UintTy| {
let width = width let width = width
.normalize(tcx.data_layout.pointer_size.bits().try_into().unwrap()) .normalize(tcx.data_layout.pointer_size().bits().try_into().unwrap())
.bit_width() .bit_width()
.unwrap(); .unwrap();
let width = Size::from_bits(width); let width = Size::from_bits(width);

View File

@@ -278,7 +278,7 @@ pub(crate) fn default_configuration(sess: &Session) -> Cfg {
}; };
insert_atomic(sym::integer(i), align); insert_atomic(sym::integer(i), align);
if sess.target.pointer_width as u64 == i { if sess.target.pointer_width as u64 == i {
insert_atomic(sym::ptr, layout.pointer_align.abi); insert_atomic(sym::ptr, layout.pointer_align().abi);
} }
} }
} }

View File

@@ -47,15 +47,12 @@ pub fn try_new_slice<'tcx, B: Bridge>(
let scalar_ptr = Scalar::from_pointer(ptr, &cx.tcx); let scalar_ptr = Scalar::from_pointer(ptr, &cx.tcx);
let scalar_meta: Scalar = Scalar::from_target_usize(meta, &cx.tcx); let scalar_meta: Scalar = Scalar::from_target_usize(meta, &cx.tcx);
let mut allocation = Allocation::new(layout.size, layout.align.abi, AllocInit::Uninit, ()); let mut allocation = Allocation::new(layout.size, layout.align.abi, AllocInit::Uninit, ());
let ptr_size = cx.tcx.data_layout.pointer_size();
allocation allocation
.write_scalar(&cx.tcx, alloc_range(Size::ZERO, cx.tcx.data_layout.pointer_size), scalar_ptr) .write_scalar(&cx.tcx, alloc_range(Size::ZERO, ptr_size), scalar_ptr)
.map_err(|e| B::Error::from_internal(e))?; .map_err(|e| B::Error::from_internal(e))?;
allocation allocation
.write_scalar( .write_scalar(&cx.tcx, alloc_range(ptr_size, scalar_meta.size()), scalar_meta)
&cx.tcx,
alloc_range(cx.tcx.data_layout.pointer_size, scalar_meta.size()),
scalar_meta,
)
.map_err(|e| B::Error::from_internal(e))?; .map_err(|e| B::Error::from_internal(e))?;
Ok(allocation) Ok(allocation)

View File

@@ -112,7 +112,7 @@ impl<'tcx, B: Bridge> SmirCtxt<'tcx, B> {
} }
pub fn target_pointer_size(&self) -> usize { pub fn target_pointer_size(&self) -> usize {
self.tcx.data_layout.pointer_size.bits().try_into().unwrap() self.tcx.data_layout.pointer_size().bits().try_into().unwrap()
} }
pub fn entry_fn(&self) -> Option<DefId> { pub fn entry_fn(&self) -> Option<DefId> {

View File

@@ -334,7 +334,7 @@ where
Ty: TyAbiInterface<'a, C> + Copy, Ty: TyAbiInterface<'a, C> + Copy,
C: HasDataLayout + HasTargetSpec, C: HasDataLayout + HasTargetSpec,
{ {
let xlen = cx.data_layout().pointer_size.bits(); let xlen = cx.data_layout().pointer_size().bits();
let flen = match &cx.target_spec().llvm_abiname[..] { let flen = match &cx.target_spec().llvm_abiname[..] {
"ilp32f" | "lp64f" => 32, "ilp32f" | "lp64f" => 32,
"ilp32d" | "lp64d" => 64, "ilp32d" | "lp64d" => 64,
@@ -369,7 +369,7 @@ where
Ty: TyAbiInterface<'a, C> + Copy, Ty: TyAbiInterface<'a, C> + Copy,
C: HasDataLayout + HasTargetSpec, C: HasDataLayout + HasTargetSpec,
{ {
let grlen = cx.data_layout().pointer_size.bits(); let grlen = cx.data_layout().pointer_size().bits();
for arg in fn_abi.args.iter_mut() { for arg in fn_abi.args.iter_mut() {
if arg.is_ignore() { if arg.is_ignore() {

View File

@@ -10,7 +10,7 @@ where
ret.extend_integer_width_to(32); ret.extend_integer_width_to(32);
} else { } else {
ret.make_indirect(); ret.make_indirect();
*offset += cx.data_layout().pointer_size; *offset += cx.data_layout().pointer_size();
} }
} }

View File

@@ -733,7 +733,7 @@ impl<'a, Ty> FnAbi<'a, Ty> {
} }
if arg_idx.is_none() if arg_idx.is_none()
&& arg.layout.size > Primitive::Pointer(AddressSpace::DATA).size(cx) * 2 && arg.layout.size > Primitive::Pointer(AddressSpace::ZERO).size(cx) * 2
&& !matches!(arg.layout.backend_repr, BackendRepr::SimdVector { .. }) && !matches!(arg.layout.backend_repr, BackendRepr::SimdVector { .. })
{ {
// Return values larger than 2 registers using a return area // Return values larger than 2 registers using a return area
@@ -792,7 +792,7 @@ impl<'a, Ty> FnAbi<'a, Ty> {
let size = arg.layout.size; let size = arg.layout.size;
if arg.layout.is_sized() if arg.layout.is_sized()
&& size <= Primitive::Pointer(AddressSpace::DATA).size(cx) && size <= Primitive::Pointer(AddressSpace::ZERO).size(cx)
{ {
// We want to pass small aggregates as immediates, but using // We want to pass small aggregates as immediates, but using
// an LLVM aggregate type for this leads to bad optimizations, // an LLVM aggregate type for this leads to bad optimizations,

View File

@@ -418,7 +418,7 @@ where
"ilp32d" | "lp64d" => 64, "ilp32d" | "lp64d" => 64,
_ => 0, _ => 0,
}; };
let xlen = cx.data_layout().pointer_size.bits(); let xlen = cx.data_layout().pointer_size().bits();
let mut avail_gprs = 8; let mut avail_gprs = 8;
let mut avail_fprs = 8; let mut avail_fprs = 8;
@@ -448,7 +448,7 @@ where
Ty: TyAbiInterface<'a, C> + Copy, Ty: TyAbiInterface<'a, C> + Copy,
C: HasDataLayout + HasTargetSpec, C: HasDataLayout + HasTargetSpec,
{ {
let xlen = cx.data_layout().pointer_size.bits(); let xlen = cx.data_layout().pointer_size().bits();
for arg in fn_abi.args.iter_mut() { for arg in fn_abi.args.iter_mut() {
if arg.is_ignore() { if arg.is_ignore() {

View File

@@ -10,7 +10,7 @@ where
ret.extend_integer_width_to(32); ret.extend_integer_width_to(32);
} else { } else {
ret.make_indirect(); ret.make_indirect();
*offset += cx.data_layout().pointer_size; *offset += cx.data_layout().pointer_size();
} }
} }

View File

@@ -219,7 +219,7 @@ where
// SSE ABI. We prefer this over integer registers as float scalars need to be in SSE // SSE ABI. We prefer this over integer registers as float scalars need to be in SSE
// registers for float operations, so that's the best place to pass them around. // registers for float operations, so that's the best place to pass them around.
fn_abi.ret.cast_to(Reg { kind: RegKind::Vector, size: fn_abi.ret.layout.size }); fn_abi.ret.cast_to(Reg { kind: RegKind::Vector, size: fn_abi.ret.layout.size });
} else if fn_abi.ret.layout.size <= Primitive::Pointer(AddressSpace::DATA).size(cx) { } else if fn_abi.ret.layout.size <= Primitive::Pointer(AddressSpace::ZERO).size(cx) {
// Same size or smaller than pointer, return in an integer register. // Same size or smaller than pointer, return in an integer register.
fn_abi.ret.cast_to(Reg { kind: RegKind::Integer, size: fn_abi.ret.layout.size }); fn_abi.ret.cast_to(Reg { kind: RegKind::Integer, size: fn_abi.ret.layout.size });
} else { } else {

View File

@@ -2198,7 +2198,10 @@ pub struct TargetMetadata {
impl Target { impl Target {
pub fn parse_data_layout(&self) -> Result<TargetDataLayout, TargetDataLayoutErrors<'_>> { pub fn parse_data_layout(&self) -> Result<TargetDataLayout, TargetDataLayoutErrors<'_>> {
let mut dl = TargetDataLayout::parse_from_llvm_datalayout_string(&self.data_layout)?; let mut dl = TargetDataLayout::parse_from_llvm_datalayout_string(
&self.data_layout,
self.options.default_address_space,
)?;
// Perform consistency checks against the Target information. // Perform consistency checks against the Target information.
if dl.endian != self.endian { if dl.endian != self.endian {
@@ -2209,9 +2212,10 @@ impl Target {
} }
let target_pointer_width: u64 = self.pointer_width.into(); let target_pointer_width: u64 = self.pointer_width.into();
if dl.pointer_size.bits() != target_pointer_width { let dl_pointer_size: u64 = dl.pointer_size().bits();
if dl_pointer_size != target_pointer_width {
return Err(TargetDataLayoutErrors::InconsistentTargetPointerWidth { return Err(TargetDataLayoutErrors::InconsistentTargetPointerWidth {
pointer_size: dl.pointer_size.bits(), pointer_size: dl_pointer_size,
target: self.pointer_width, target: self.pointer_width,
}); });
} }
@@ -2650,6 +2654,11 @@ pub struct TargetOptions {
/// Whether the target supports XRay instrumentation. /// Whether the target supports XRay instrumentation.
pub supports_xray: bool, pub supports_xray: bool,
/// The default address space for this target. When using LLVM as a backend, most targets simply
/// use LLVM's default address space (0). Some other targets, such as CHERI targets, use a
/// custom default address space (in this specific case, `200`).
pub default_address_space: rustc_abi::AddressSpace,
/// Whether the targets supports -Z small-data-threshold /// Whether the targets supports -Z small-data-threshold
small_data_threshold_support: SmallDataThresholdSupport, small_data_threshold_support: SmallDataThresholdSupport,
} }
@@ -2878,6 +2887,7 @@ impl Default for TargetOptions {
entry_name: "main".into(), entry_name: "main".into(),
entry_abi: CanonAbi::C, entry_abi: CanonAbi::C,
supports_xray: false, supports_xray: false,
default_address_space: rustc_abi::AddressSpace::ZERO,
small_data_threshold_support: SmallDataThresholdSupport::DefaultForArch, small_data_threshold_support: SmallDataThresholdSupport::DefaultForArch,
} }
} }

View File

@@ -296,7 +296,7 @@ pub(crate) mod rustc {
} }
let target = cx.data_layout(); let target = cx.data_layout();
let pointer_size = target.pointer_size; let pointer_size = target.pointer_size();
match ty.kind() { match ty.kind() {
ty::Bool => Ok(Self::bool()), ty::Bool => Ok(Self::bool()),

View File

@@ -379,7 +379,7 @@ fn layout_of_uncached<'tcx>(
// Potentially-wide pointers. // Potentially-wide pointers.
ty::Ref(_, pointee, _) | ty::RawPtr(pointee, _) => { ty::Ref(_, pointee, _) | ty::RawPtr(pointee, _) => {
let mut data_ptr = scalar_unit(Pointer(AddressSpace::DATA)); let mut data_ptr = scalar_unit(Pointer(AddressSpace::ZERO));
if !ty.is_raw_ptr() { if !ty.is_raw_ptr() {
data_ptr.valid_range_mut().start = 1; data_ptr.valid_range_mut().start = 1;
} }
@@ -435,7 +435,7 @@ fn layout_of_uncached<'tcx>(
} }
ty::Slice(_) | ty::Str => scalar_unit(Int(dl.ptr_sized_integer(), false)), ty::Slice(_) | ty::Str => scalar_unit(Int(dl.ptr_sized_integer(), false)),
ty::Dynamic(..) => { ty::Dynamic(..) => {
let mut vtable = scalar_unit(Pointer(AddressSpace::DATA)); let mut vtable = scalar_unit(Pointer(AddressSpace::ZERO));
vtable.valid_range_mut().start = 1; vtable.valid_range_mut().start = 1;
vtable vtable
} }

View File

@@ -17,7 +17,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>,
ty::FnDef(..) | ty::FnPtr(..) => { ty::FnDef(..) | ty::FnPtr(..) => {
let mut applicability = Applicability::MaybeIncorrect; let mut applicability = Applicability::MaybeIncorrect;
if to_nbits >= cx.tcx.data_layout.pointer_size.bits() && !cast_to.is_usize() { if to_nbits >= cx.tcx.data_layout.pointer_size().bits() && !cast_to.is_usize() {
let from_snippet = snippet_with_applicability(cx, cast_expr.span, "x", &mut applicability); let from_snippet = snippet_with_applicability(cx, cast_expr.span, "x", &mut applicability);
span_lint_and_sugg( span_lint_and_sugg(
cx, cx,

View File

@@ -17,7 +17,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>,
let mut applicability = Applicability::MaybeIncorrect; let mut applicability = Applicability::MaybeIncorrect;
let from_snippet = snippet_with_applicability(cx, cast_expr.span, "x", &mut applicability); let from_snippet = snippet_with_applicability(cx, cast_expr.span, "x", &mut applicability);
if to_nbits < cx.tcx.data_layout.pointer_size.bits() { if to_nbits < cx.tcx.data_layout.pointer_size().bits() {
span_lint_and_sugg( span_lint_and_sugg(
cx, cx,
FN_TO_NUMERIC_CAST_WITH_TRUNCATION, FN_TO_NUMERIC_CAST_WITH_TRUNCATION,

View File

@@ -5,7 +5,7 @@ use rustc_middle::ty::{self, AdtDef, IntTy, Ty, TyCtxt, UintTy, VariantDiscr};
/// integral type. /// integral type.
pub(super) fn int_ty_to_nbits(tcx: TyCtxt<'_>, ty: Ty<'_>) -> Option<u64> { pub(super) fn int_ty_to_nbits(tcx: TyCtxt<'_>, ty: Ty<'_>) -> Option<u64> {
match ty.kind() { match ty.kind() {
ty::Int(IntTy::Isize) | ty::Uint(UintTy::Usize) => Some(tcx.data_layout.pointer_size.bits()), ty::Int(IntTy::Isize) | ty::Uint(UintTy::Usize) => Some(tcx.data_layout.pointer_size().bits()),
ty::Int(i) => i.bit_width(), ty::Int(i) => i.bit_width(),
ty::Uint(i) => i.bit_width(), ty::Uint(i) => i.bit_width(),
_ => None, _ => None,

View File

@@ -35,7 +35,7 @@ declare_lint_pass!(UnportableVariant => [ENUM_CLIKE_UNPORTABLE_VARIANT]);
impl<'tcx> LateLintPass<'tcx> for UnportableVariant { impl<'tcx> LateLintPass<'tcx> for UnportableVariant {
#[expect(clippy::cast_possible_wrap)] #[expect(clippy::cast_possible_wrap)]
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
if cx.tcx.data_layout.pointer_size.bits() != 64 { if cx.tcx.data_layout.pointer_size().bits() != 64 {
return; return;
} }
if let ItemKind::Enum(_, _, def) = &item.kind { if let ItemKind::Enum(_, _, def) = &item.kind {

View File

@@ -918,7 +918,7 @@ fn mir_is_empty<'tcx>(tcx: TyCtxt<'tcx>, result: mir::Const<'tcx>) -> Option<boo
// Get the length from the slice, using the same formula as // Get the length from the slice, using the same formula as
// [`ConstValue::try_get_slice_bytes_for_diagnostics`]. // [`ConstValue::try_get_slice_bytes_for_diagnostics`].
let a = tcx.global_alloc(alloc_id).unwrap_memory().inner(); let a = tcx.global_alloc(alloc_id).unwrap_memory().inner();
let ptr_size = tcx.data_layout.pointer_size; let ptr_size = tcx.data_layout.pointer_size();
if a.size() < offset + 2 * ptr_size { if a.size() < offset + 2 * ptr_size {
// (partially) dangling reference // (partially) dangling reference
return None; return None;

View File

@@ -261,7 +261,7 @@ pub fn layout_of_ty_query(
} }
// Potentially-wide pointers. // Potentially-wide pointers.
TyKind::Ref(_, _, pointee) | TyKind::Raw(_, pointee) => { TyKind::Ref(_, _, pointee) | TyKind::Raw(_, pointee) => {
let mut data_ptr = scalar_unit(dl, Primitive::Pointer(AddressSpace::DATA)); let mut data_ptr = scalar_unit(dl, Primitive::Pointer(AddressSpace::ZERO));
if matches!(ty.kind(Interner), TyKind::Ref(..)) { if matches!(ty.kind(Interner), TyKind::Ref(..)) {
data_ptr.valid_range_mut().start = 1; data_ptr.valid_range_mut().start = 1;
} }
@@ -285,7 +285,7 @@ pub fn layout_of_ty_query(
scalar_unit(dl, Primitive::Int(dl.ptr_sized_integer(), false)) scalar_unit(dl, Primitive::Int(dl.ptr_sized_integer(), false))
} }
TyKind::Dyn(..) => { TyKind::Dyn(..) => {
let mut vtable = scalar_unit(dl, Primitive::Pointer(AddressSpace::DATA)); let mut vtable = scalar_unit(dl, Primitive::Pointer(AddressSpace::ZERO));
vtable.valid_range_mut().start = 1; vtable.valid_range_mut().start = 1;
vtable vtable
} }

View File

@@ -2,7 +2,7 @@
use base_db::Crate; use base_db::Crate;
use hir_def::layout::TargetDataLayout; use hir_def::layout::TargetDataLayout;
use rustc_abi::{AlignFromBytesError, TargetDataLayoutErrors}; use rustc_abi::{AlignFromBytesError, TargetDataLayoutErrors, AddressSpace};
use triomphe::Arc; use triomphe::Arc;
use crate::db::HirDatabase; use crate::db::HirDatabase;
@@ -12,7 +12,7 @@ pub fn target_data_layout_query(
krate: Crate, krate: Crate,
) -> Result<Arc<TargetDataLayout>, Arc<str>> { ) -> Result<Arc<TargetDataLayout>, Arc<str>> {
match &krate.workspace_data(db).data_layout { match &krate.workspace_data(db).data_layout {
Ok(it) => match TargetDataLayout::parse_from_llvm_datalayout_string(it) { Ok(it) => match TargetDataLayout::parse_from_llvm_datalayout_string(it, AddressSpace::ZERO) {
Ok(it) => Ok(Arc::new(it)), Ok(it) => Ok(Arc::new(it)),
Err(e) => { Err(e) => {
Err(match e { Err(match e {
@@ -39,6 +39,7 @@ pub fn target_data_layout_query(
target, target,
} => format!(r#"inconsistent target specification: "data-layout" claims pointers are {pointer_size}-bit, while "target-pointer-width" is `{target}`"#), } => format!(r#"inconsistent target specification: "data-layout" claims pointers are {pointer_size}-bit, while "target-pointer-width" is `{target}`"#),
TargetDataLayoutErrors::InvalidBitsSize { err } => err, TargetDataLayoutErrors::InvalidBitsSize { err } => err,
TargetDataLayoutErrors::UnknownPointerSpecification { err } => format!(r#"use of unknown pointer specifer in "data-layout": {err}"#),
}.into()) }.into())
} }
}, },

View File

@@ -630,7 +630,7 @@ impl Evaluator<'_> {
Ok(target_data_layout) => target_data_layout, Ok(target_data_layout) => target_data_layout,
Err(e) => return Err(MirEvalError::TargetDataLayoutNotAvailable(e)), Err(e) => return Err(MirEvalError::TargetDataLayoutNotAvailable(e)),
}; };
let cached_ptr_size = target_data_layout.pointer_size.bytes_usize(); let cached_ptr_size = target_data_layout.pointer_size().bytes_usize();
Ok(Evaluator { Ok(Evaluator {
target_data_layout, target_data_layout,
stack: vec![0], stack: vec![0],