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:
@@ -221,6 +221,20 @@ impl ReprOptions {
|
||||
/// * Cranelift stores the base-2 log of the lane count in a 4 bit integer.
|
||||
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)
|
||||
/// for a target, which contains everything needed to compute layouts.
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
@@ -236,13 +250,22 @@ pub struct TargetDataLayout {
|
||||
pub f32_align: AbiAlign,
|
||||
pub f64_align: AbiAlign,
|
||||
pub f128_align: AbiAlign,
|
||||
pub pointer_size: Size,
|
||||
pub pointer_align: AbiAlign,
|
||||
pub aggregate_align: AbiAlign,
|
||||
|
||||
/// Alignments for vector types.
|
||||
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,
|
||||
|
||||
/// 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)),
|
||||
f64_align: AbiAlign::new(align(64)),
|
||||
f128_align: AbiAlign::new(align(128)),
|
||||
pointer_size: Size::from_bits(64),
|
||||
pointer_align: AbiAlign::new(align(64)),
|
||||
aggregate_align: AbiAlign { abi: align(8) },
|
||||
vector_align: vec![
|
||||
(Size::from_bits(64), AbiAlign::new(align(64))),
|
||||
(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,
|
||||
}
|
||||
}
|
||||
@@ -288,6 +317,7 @@ pub enum TargetDataLayoutErrors<'a> {
|
||||
InconsistentTargetArchitecture { dl: &'a str, target: &'a str },
|
||||
InconsistentTargetPointerWidth { pointer_size: u64, target: u32 },
|
||||
InvalidBitsSize { err: String },
|
||||
UnknownPointerSpecification { err: String },
|
||||
}
|
||||
|
||||
impl TargetDataLayout {
|
||||
@@ -298,6 +328,7 @@ impl TargetDataLayout {
|
||||
/// determined from llvm string.
|
||||
pub fn parse_from_llvm_datalayout_string<'a>(
|
||||
input: &'a str,
|
||||
default_address_space: AddressSpace,
|
||||
) -> Result<TargetDataLayout, TargetDataLayoutErrors<'a>> {
|
||||
// Parse an address space index from a string.
|
||||
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);
|
||||
|
||||
// Parse an alignment string.
|
||||
let parse_align = |s: &[&'a str], cause: &'a str| {
|
||||
if s.is_empty() {
|
||||
return Err(TargetDataLayoutErrors::MissingAlignment { cause });
|
||||
}
|
||||
let parse_align_str = |s: &'a str, cause: &'a str| {
|
||||
let align_from_bits = |bits| {
|
||||
Align::from_bits(bits)
|
||||
.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)?))
|
||||
};
|
||||
|
||||
// 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();
|
||||
dl.default_address_space = default_address_space;
|
||||
|
||||
let mut i128_align_src = 64;
|
||||
for spec in input.split('-') {
|
||||
let spec_parts = spec.split(':').collect::<Vec<_>>();
|
||||
@@ -344,24 +383,107 @@ 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(a, "a")?,
|
||||
["f16", a @ ..] => dl.f16_align = parse_align(a, "f16")?,
|
||||
["f32", a @ ..] => dl.f32_align = parse_align(a, "f32")?,
|
||||
["f64", a @ ..] => dl.f64_align = parse_align(a, "f64")?,
|
||||
["f128", a @ ..] => dl.f128_align = parse_align(a, "f128")?,
|
||||
// FIXME(erikdesjardins): we should be parsing nonzero address spaces
|
||||
// this will require replacing TargetDataLayout::{pointer_size,pointer_align}
|
||||
// with e.g. `fn pointer_size_in(AddressSpace)`
|
||||
[p @ "p", s, a @ ..] | [p @ "p0", s, a @ ..] => {
|
||||
dl.pointer_size = parse_size(s, p)?;
|
||||
dl.pointer_align = parse_align(a, 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")?,
|
||||
["f128", a @ ..] => dl.f128_align = parse_align_seq(a, "f128")?,
|
||||
[p, s, a @ ..] 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 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') => {
|
||||
let Ok(bits) = s[1..].parse::<u64>() else {
|
||||
parse_size(&s[1..], "i")?; // For the user error.
|
||||
continue;
|
||||
};
|
||||
let a = parse_align(a, s)?;
|
||||
let a = parse_align_seq(a, s)?;
|
||||
match bits {
|
||||
1 => dl.i1_align = a,
|
||||
8 => dl.i8_align = a,
|
||||
@@ -379,7 +501,7 @@ impl TargetDataLayout {
|
||||
}
|
||||
[s, a @ ..] if s.starts_with('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) {
|
||||
v.1 = a;
|
||||
continue;
|
||||
@@ -390,9 +512,45 @@ impl TargetDataLayout {
|
||||
_ => {} // 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)
|
||||
}
|
||||
|
||||
/// 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.
|
||||
///
|
||||
/// 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,
|
||||
/// 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() {
|
||||
pub fn obj_size_bound_in(&self, address_space: AddressSpace) -> u64 {
|
||||
match self.pointer_size_in(address_space).bits() {
|
||||
16 => 1 << 15,
|
||||
32 => 1 << 31,
|
||||
64 => 1 << 61,
|
||||
@@ -415,7 +573,18 @@ impl TargetDataLayout {
|
||||
#[inline]
|
||||
pub fn ptr_sized_integer(&self) -> 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,
|
||||
32 => I32,
|
||||
64 => I64,
|
||||
@@ -439,6 +608,66 @@ impl TargetDataLayout {
|
||||
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 {
|
||||
@@ -1100,10 +1329,7 @@ impl Primitive {
|
||||
match self {
|
||||
Int(i, _) => i.size(),
|
||||
Float(f) => f.size(),
|
||||
// FIXME(erikdesjardins): ignoring address space is technically wrong, pointers in
|
||||
// different address spaces can have different sizes
|
||||
// (but TargetDataLayout doesn't currently parse that part of the DL string)
|
||||
Pointer(_) => dl.pointer_size,
|
||||
Pointer(a) => dl.pointer_size_in(a),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1114,10 +1340,7 @@ impl Primitive {
|
||||
match self {
|
||||
Int(i, _) => i.align(dl),
|
||||
Float(f) => f.align(dl),
|
||||
// FIXME(erikdesjardins): ignoring address space is technically wrong, pointers in
|
||||
// different address spaces can have different alignments
|
||||
// (but TargetDataLayout doesn't currently parse that part of the DL string)
|
||||
Pointer(_) => dl.pointer_align,
|
||||
Pointer(a) => dl.pointer_align_in(a),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1421,8 +1644,8 @@ impl<FieldIdx: Idx> FieldsShape<FieldIdx> {
|
||||
pub struct AddressSpace(pub u32);
|
||||
|
||||
impl AddressSpace {
|
||||
/// The default address space, corresponding to data space.
|
||||
pub const DATA: Self = AddressSpace(0);
|
||||
/// LLVM's `0` address space.
|
||||
pub const ZERO: Self = AddressSpace(0);
|
||||
}
|
||||
|
||||
/// The way we represent values to the backend
|
||||
|
||||
@@ -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
|
||||
fn int_ty_max(&self, int_ty: IntTy) -> u128 {
|
||||
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::I16 => i16::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
|
||||
fn uint_ty_max(&self, uint_ty: UintTy) -> u128 {
|
||||
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::U16 => u16::MAX as u128,
|
||||
UintTy::U32 => u32::MAX as u128,
|
||||
|
||||
@@ -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 {
|
||||
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) {
|
||||
("x86_64", _) | ("aarch64", "apple") => match (ty, is_signed) {
|
||||
(types::I8 | types::I16, true) => param.sext(),
|
||||
|
||||
@@ -127,7 +127,7 @@ impl<'tcx> ArgAbiExt<'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
|
||||
PassMode::Indirect { attrs, meta_attrs: None, on_stack } => {
|
||||
if on_stack {
|
||||
// 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();
|
||||
smallvec![apply_attrs_to_abi_param(
|
||||
AbiParam::special(pointer_ty(tcx), ArgumentPurpose::StructArgument(size),),
|
||||
|
||||
@@ -15,7 +15,7 @@ use crate::debuginfo::FunctionDebugContext;
|
||||
use crate::prelude::*;
|
||||
|
||||
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,
|
||||
32 => types::I32,
|
||||
64 => types::I64,
|
||||
|
||||
@@ -443,7 +443,7 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant
|
||||
let addend = {
|
||||
let endianness = tcx.data_layout.endian;
|
||||
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(
|
||||
offset..offset + ptr_size.bytes() as usize,
|
||||
);
|
||||
|
||||
@@ -162,7 +162,7 @@ impl<'gcc, 'tcx> ConstCodegenMethods for CodegenCx<'gcc, 'tcx> {
|
||||
}
|
||||
|
||||
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 {
|
||||
// make sure it doesn't overflow
|
||||
assert!(i < (1 << bit_size));
|
||||
|
||||
@@ -294,7 +294,7 @@ pub(crate) fn const_alloc_to_gcc_uncached<'gcc>(
|
||||
let alloc = alloc.inner();
|
||||
let mut llvals = Vec::with_capacity(alloc.provenance().ptrs().len() + 1);
|
||||
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;
|
||||
for &(offset, prov) in alloc.provenance().ptrs().iter() {
|
||||
@@ -331,7 +331,7 @@ pub(crate) fn const_alloc_to_gcc_uncached<'gcc>(
|
||||
),
|
||||
abi::Scalar::Initialized {
|
||||
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),
|
||||
));
|
||||
|
||||
@@ -541,7 +541,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc
|
||||
// For rusty ABIs, small aggregates are actually passed
|
||||
// as `RegKind::Integer` (see `FnAbi::adjust_for_abi`),
|
||||
// so we re-use that same threshold here.
|
||||
layout.size() <= self.data_layout().pointer_size * 2
|
||||
layout.size() <= self.data_layout().pointer_size() * 2
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1184,7 +1184,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
||||
let lhs = args[0].immediate();
|
||||
let rhs = args[1].immediate();
|
||||
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() {
|
||||
ty::Int(i) => (true, i.bit_width().unwrap_or(ptr_bits) / 8, bx.cx.type_int_from_ty(i)),
|
||||
ty::Uint(i) => {
|
||||
|
||||
@@ -175,7 +175,7 @@ impl<'ll, 'tcx> ConstCodegenMethods for CodegenCx<'ll, 'tcx> {
|
||||
}
|
||||
|
||||
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 {
|
||||
// make sure it doesn't overflow
|
||||
assert!(i < (1 << bit_size));
|
||||
|
||||
@@ -43,7 +43,8 @@ pub(crate) fn const_alloc_to_llvm<'ll>(
|
||||
}
|
||||
let mut llvals = Vec::with_capacity(alloc.provenance().ptrs().len() + 1);
|
||||
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`
|
||||
// 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
|
||||
// affect interpreter execution (we inspect the result after interpreter execution),
|
||||
// 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")
|
||||
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),
|
||||
Scalar::Initialized {
|
||||
value: Primitive::Pointer(address_space),
|
||||
valid_range: WrappingRange::full(dl.pointer_size),
|
||||
valid_range: WrappingRange::full(pointer_size),
|
||||
},
|
||||
cx.type_ptr_ext(address_space),
|
||||
));
|
||||
next_offset = offset + pointer_size;
|
||||
next_offset = offset + pointer_size_bytes;
|
||||
}
|
||||
if alloc.len() >= next_offset {
|
||||
let range = next_offset..alloc.len();
|
||||
|
||||
@@ -605,7 +605,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
|
||||
GenericCx(
|
||||
FullCx {
|
||||
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,
|
||||
tls_model,
|
||||
codegen_unit,
|
||||
|
||||
@@ -159,13 +159,15 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>(
|
||||
return_if_di_node_created_in_meantime!(cx, unique_type_id);
|
||||
|
||||
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);
|
||||
|
||||
match wide_pointer_kind(cx, pointee_type) {
|
||||
None => {
|
||||
// This is a thin pointer. Create a regular pointer type and give it the correct name.
|
||||
assert_eq!(
|
||||
(data_layout.pointer_size, data_layout.pointer_align.abi),
|
||||
(pointer_size, pointer_align.abi),
|
||||
cx.size_and_align_of(ptr_type),
|
||||
"ptr_type={ptr_type}, pointee_type={pointee_type}",
|
||||
);
|
||||
@@ -174,8 +176,8 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>(
|
||||
llvm::LLVMRustDIBuilderCreatePointerType(
|
||||
DIB(cx),
|
||||
pointee_type_di_node,
|
||||
data_layout.pointer_size.bits(),
|
||||
data_layout.pointer_align.abi.bits() as u32,
|
||||
pointer_size.bits(),
|
||||
pointer_align.abi.bits() as u32,
|
||||
0, // Ignore DWARF address space.
|
||||
ptr_type_debuginfo_name.as_c_char_ptr(),
|
||||
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 (size, align) = match fn_ty.kind() {
|
||||
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!(),
|
||||
};
|
||||
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(
|
||||
cx,
|
||||
"<recur_type>",
|
||||
cx.tcx.data_layout.pointer_size,
|
||||
cx.tcx.data_layout.pointer_size(),
|
||||
dwarf_const::DW_ATE_unsigned,
|
||||
)
|
||||
})
|
||||
|
||||
@@ -458,7 +458,7 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
|
||||
// For rusty ABIs, small aggregates are actually passed
|
||||
// as `RegKind::Integer` (see `FnAbi::adjust_for_abi`),
|
||||
// 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.
|
||||
let ptr_size = bx.tcx().data_layout.pointer_size;
|
||||
let ptr_align = bx.tcx().data_layout.pointer_align.abi;
|
||||
let ptr_size = bx.tcx().data_layout.pointer_size();
|
||||
let ptr_align = bx.tcx().data_layout.pointer_align().abi;
|
||||
let slot = bx.alloca(ptr_size, ptr_align);
|
||||
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);
|
||||
@@ -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
|
||||
// create an alloca and pass a pointer to that.
|
||||
let ptr_size = bx.tcx().data_layout.pointer_size;
|
||||
let ptr_align = bx.tcx().data_layout.pointer_align.abi;
|
||||
let ptr_size = bx.tcx().data_layout.pointer_size();
|
||||
let ptr_align = bx.tcx().data_layout.pointer_align().abi;
|
||||
let i8_align = bx.tcx().data_layout.i8_align.abi;
|
||||
// Required in order for there to be no padding between the fields.
|
||||
assert!(i8_align <= ptr_align);
|
||||
@@ -1158,9 +1158,11 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
||||
macro_rules! require_int_or_uint_ty {
|
||||
($ty: expr, $diag: expr) => {
|
||||
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) => {
|
||||
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);
|
||||
@@ -2014,10 +2016,10 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
||||
} else {
|
||||
let bitwidth = match in_elem.kind() {
|
||||
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) => {
|
||||
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 {
|
||||
span,
|
||||
|
||||
@@ -113,7 +113,7 @@ impl ExtraBackendMethods for LlvmCodegenBackend {
|
||||
) -> ModuleLlvm {
|
||||
let module_llvm = ModuleLlvm::new_metadata(tcx, module_name);
|
||||
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 {
|
||||
allocator::codegen(tcx, cx, module_name, kind, alloc_error_handler_kind);
|
||||
}
|
||||
|
||||
@@ -208,7 +208,7 @@ impl<'ll, CX: Borrow<SCx<'ll>>> BaseTypeCodegenMethods for GenericCx<'ll, CX> {
|
||||
}
|
||||
|
||||
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 {
|
||||
@@ -258,7 +258,7 @@ impl Type {
|
||||
}
|
||||
|
||||
pub(crate) fn ptr_llcx(llcx: &llvm::Context) -> &Type {
|
||||
unsafe { llvm::LLVMPointerTypeInContext(llcx, AddressSpace::DATA.0) }
|
||||
unsafe { llvm::LLVMPointerTypeInContext(llcx, AddressSpace::ZERO.0) }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -45,7 +45,8 @@ fn emit_direct_ptr_va_arg<'ll, 'tcx>(
|
||||
let va_list_ty = bx.type_ptr();
|
||||
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 {
|
||||
(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 full_direct_size = bx.cx().const_i32(aligned_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()
|
||||
&& bx.tcx().sess.target.endian == Endian::Big
|
||||
@@ -108,8 +109,8 @@ fn emit_ptr_va_arg<'ll, 'tcx>(
|
||||
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.data_layout().pointer_size,
|
||||
bx.cx.data_layout().pointer_align,
|
||||
bx.cx.data_layout().pointer_size(),
|
||||
bx.cx.data_layout().pointer_align(),
|
||||
)
|
||||
} else {
|
||||
(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);
|
||||
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);
|
||||
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 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_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);
|
||||
|
||||
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.
|
||||
if !is_int && !is_soft_float_abi {
|
||||
@@ -342,11 +344,11 @@ fn emit_powerpc_va_arg<'ll, 'tcx>(
|
||||
let size = if !is_indirect {
|
||||
layout.layout.size.align_to(overflow_area_align)
|
||||
} 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 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
|
||||
if layout.layout.align.abi > overflow_area_align {
|
||||
@@ -362,7 +364,7 @@ fn emit_powerpc_va_arg<'ll, 'tcx>(
|
||||
|
||||
// Increase the overflow area.
|
||||
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);
|
||||
|
||||
@@ -373,11 +375,8 @@ fn emit_powerpc_va_arg<'ll, 'tcx>(
|
||||
bx.switch_to_block(end);
|
||||
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_addr = if is_indirect {
|
||||
bx.load(bx.cx.type_ptr(), val_addr, dl.pointer_align.abi)
|
||||
} else {
|
||||
val_addr
|
||||
};
|
||||
let val_addr =
|
||||
if is_indirect { bx.load(bx.cx.type_ptr(), val_addr, ptr_align_abi) } else { val_addr };
|
||||
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_mem = bx.append_sibling_block("va_arg.in_mem");
|
||||
let end = bx.append_sibling_block("va_arg.end");
|
||||
let ptr_align_abi = dl.pointer_align().abi;
|
||||
|
||||
// FIXME: vector ABI not yet supported.
|
||||
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);
|
||||
|
||||
// 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 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);
|
||||
@@ -449,15 +449,14 @@ fn emit_s390x_va_arg<'ll, 'tcx>(
|
||||
bx.switch_to_block(in_mem);
|
||||
|
||||
// Work out the address of the value in the argument overflow area.
|
||||
let arg_ptr_v =
|
||||
bx.load(bx.type_ptr(), overflow_arg_area, bx.tcx().data_layout.pointer_align.abi);
|
||||
let arg_ptr_v = bx.load(bx.type_ptr(), overflow_arg_area, ptr_align_abi);
|
||||
let arg_off = bx.const_u64(padding);
|
||||
let mem_addr = bx.ptradd(arg_ptr_v, arg_off);
|
||||
|
||||
// Update the argument overflow area pointer.
|
||||
let arg_size = bx.cx().const_u64(padded_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);
|
||||
|
||||
// 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_type = layout.llvm_type(bx);
|
||||
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)
|
||||
}
|
||||
|
||||
@@ -607,7 +606,7 @@ fn emit_x86_64_sysv64_va_arg<'ll, 'tcx>(
|
||||
// loads than necessary. Can we clean this up?
|
||||
let reg_save_area_ptr =
|
||||
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() {
|
||||
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>>,
|
||||
) -> &'ll Value {
|
||||
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_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
|
||||
// byte boundary if alignment needed by type exceeds 8 byte boundary.
|
||||
// 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 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);
|
||||
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
|
||||
}
|
||||
@@ -803,6 +803,7 @@ fn emit_xtensa_va_arg<'ll, 'tcx>(
|
||||
let from_stack = bx.append_sibling_block("va_arg.from_stack");
|
||||
let from_regsave = bx.append_sibling_block("va_arg.from_regsave");
|
||||
let end = bx.append_sibling_block("va_arg.end");
|
||||
let ptr_align_abi = bx.tcx().data_layout.pointer_align().abi;
|
||||
|
||||
// (*va).va_ndx
|
||||
let va_reg_offset = 4;
|
||||
@@ -825,12 +826,11 @@ fn emit_xtensa_va_arg<'ll, 'tcx>(
|
||||
|
||||
bx.switch_to_block(from_regsave);
|
||||
// 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
|
||||
let regsave_area_ptr = bx.inbounds_ptradd(va_list_addr, bx.cx.const_usize(va_reg_offset));
|
||||
let regsave_area =
|
||||
bx.load(bx.type_ptr(), regsave_area_ptr, bx.tcx().data_layout.pointer_align.abi);
|
||||
let regsave_area = bx.load(bx.type_ptr(), regsave_area_ptr, ptr_align_abi);
|
||||
let regsave_value_ptr = bx.inbounds_ptradd(regsave_area, offset);
|
||||
bx.br(end);
|
||||
|
||||
@@ -849,11 +849,11 @@ fn emit_xtensa_va_arg<'ll, 'tcx>(
|
||||
// va_ndx = offset_next_corrected;
|
||||
let offset_next_corrected = bx.add(offset_next, bx.const_i32(slot_size));
|
||||
// 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_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);
|
||||
bx.br(end);
|
||||
|
||||
|
||||
@@ -1208,7 +1208,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
|
||||
split_debuginfo: tcx.sess.split_debuginfo(),
|
||||
split_dwarf_kind: tcx.sess.opts.unstable_opts.split_dwarf_kind,
|
||||
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(),
|
||||
};
|
||||
|
||||
|
||||
@@ -200,7 +200,7 @@ fn unsized_info<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
||||
let vptr_entry_idx = cx.tcx().supertrait_vtable_slot((source, target));
|
||||
|
||||
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();
|
||||
load_vtable(bx, old_info, bx.type_ptr(), vtable_byte_offset, source, true)
|
||||
} else {
|
||||
@@ -577,8 +577,8 @@ fn get_argc_argv<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(bx: &mut Bx) -> (Bx::Va
|
||||
// Params for UEFI
|
||||
let param_handle = bx.get_param(0);
|
||||
let param_system_table = bx.get_param(1);
|
||||
let ptr_size = bx.tcx().data_layout.pointer_size;
|
||||
let ptr_align = bx.tcx().data_layout.pointer_align.abi;
|
||||
let ptr_size = bx.tcx().data_layout.pointer_size();
|
||||
let ptr_align = bx.tcx().data_layout.pointer_align().abi;
|
||||
let arg_argc = bx.const_int(bx.cx().type_isize(), 2);
|
||||
let arg_argv = bx.alloca(2 * ptr_size, ptr_align);
|
||||
bx.store(param_handle, arg_argv, ptr_align);
|
||||
|
||||
@@ -27,7 +27,7 @@ impl<'a, 'tcx> VirtualIndex {
|
||||
debug!("get_fn({llvtable:?}, {ty:?}, {self:?})");
|
||||
|
||||
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();
|
||||
|
||||
load_vtable(bx, llvtable, llty, vtable_byte_offset, ty, nonnull)
|
||||
@@ -63,7 +63,7 @@ impl<'a, 'tcx> VirtualIndex {
|
||||
debug!("get_int({:?}, {:?})", llvtable, self);
|
||||
|
||||
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();
|
||||
|
||||
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_allocation = tcx.global_alloc(vtable_alloc_id).unwrap_memory();
|
||||
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"));
|
||||
|
||||
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>,
|
||||
nonnull: bool,
|
||||
) -> 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
|
||||
&& bx.cx().sess().lto() == Lto::Fat
|
||||
|
||||
@@ -326,7 +326,7 @@ fn prefix_and_suffix<'tcx>(
|
||||
fn wasm_functype<'tcx>(tcx: TyCtxt<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> String {
|
||||
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",
|
||||
64 => "i64",
|
||||
other => bug!("wasm pointer size cannot be {other} bits"),
|
||||
|
||||
@@ -1135,7 +1135,7 @@ fn assume_scalar_range<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
||||
let range = scalar.valid_range(bx.cx());
|
||||
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) =>
|
||||
{
|
||||
bx.assume_nonnull(imm);
|
||||
|
||||
@@ -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.
|
||||
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.
|
||||
@@ -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.
|
||||
pub fn read_pointer(&self, offset: Size) -> InterpResult<'tcx, Scalar<Prov>> {
|
||||
self.read_scalar(
|
||||
alloc_range(offset, self.tcx.data_layout().pointer_size),
|
||||
alloc_range(offset, self.tcx.data_layout().pointer_size()),
|
||||
/*read_provenance*/ true,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -41,5 +41,8 @@ errors_target_invalid_bits =
|
||||
|
||||
errors_target_invalid_bits_size = {$err}
|
||||
|
||||
errors_target_invalid_datalayout_pointer_spec =
|
||||
unknown pointer specification `{$err}` in datalayout string
|
||||
|
||||
errors_target_missing_alignment =
|
||||
missing alignment for `{$cause}` in "data-layout"
|
||||
|
||||
@@ -374,6 +374,10 @@ impl<G: EmissionGuarantee> Diagnostic<'_, G> for TargetDataLayoutErrors<'_> {
|
||||
TargetDataLayoutErrors::InvalidBitsSize { 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,7 +142,7 @@ impl<'tcx> ConstValue<'tcx> {
|
||||
// The reference itself is stored behind an indirection.
|
||||
// Load the reference, and then load the actual slice contents.
|
||||
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 {
|
||||
// (partially) dangling reference
|
||||
return None;
|
||||
|
||||
@@ -519,7 +519,7 @@ impl Allocation {
|
||||
let mut bytes = alloc_bytes(&*self.bytes, self.align)?;
|
||||
// Adjust provenance of pointers stored in this allocation.
|
||||
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;
|
||||
for &(offset, alloc_id) in self.provenance.ptrs().iter() {
|
||||
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();
|
||||
|
||||
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
|
||||
// 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.
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
// the beginning of this range.
|
||||
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()
|
||||
}
|
||||
@@ -142,7 +142,7 @@ impl<Prov: Provenance> ProvenanceMap<Prov> {
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -160,6 +160,8 @@ impl<Prov: Provenance> ProvenanceMap<Prov> {
|
||||
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
|
||||
// provenance that overlaps with the given range.
|
||||
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
|
||||
// colder than the early return above, so it's worth it.
|
||||
let provenance = self.range_ptrs_get(range, cx);
|
||||
(
|
||||
provenance.first().unwrap().0,
|
||||
provenance.last().unwrap().0 + cx.data_layout().pointer_size,
|
||||
)
|
||||
(provenance.first().unwrap().0, provenance.last().unwrap().0 + pointer_size)
|
||||
};
|
||||
|
||||
// We need to handle clearing the provenance from parts of a pointer.
|
||||
@@ -192,7 +191,7 @@ impl<Prov: Provenance> ProvenanceMap<Prov> {
|
||||
}
|
||||
}
|
||||
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 {
|
||||
// We can't split up the provenance into less than a pointer.
|
||||
return Err(AllocError::OverwritePartialPointer(begin_of_last));
|
||||
@@ -255,7 +254,7 @@ impl<Prov: Provenance> ProvenanceMap<Prov> {
|
||||
// shift offsets from source allocation to destination allocation
|
||||
(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
|
||||
// Get the provenances that are entirely within this range.
|
||||
|
||||
@@ -297,7 +297,7 @@ impl<'tcx> GlobalAlloc<'tcx> {
|
||||
match self {
|
||||
GlobalAlloc::Function { .. } => cx.data_layout().instruction_address_space,
|
||||
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::VTable(..) => {
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ pub trait PointerArithmetic: HasDataLayout {
|
||||
|
||||
#[inline(always)]
|
||||
fn pointer_size(&self) -> Size {
|
||||
self.data_layout().pointer_size
|
||||
self.data_layout().pointer_size()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
|
||||
@@ -167,7 +167,7 @@ impl<Prov> Scalar<Prov> {
|
||||
|
||||
#[inline]
|
||||
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]
|
||||
@@ -205,7 +205,7 @@ impl<Prov> Scalar<Prov> {
|
||||
|
||||
#[inline]
|
||||
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]
|
||||
@@ -393,7 +393,7 @@ impl<'tcx, Prov: Provenance> Scalar<Prov> {
|
||||
/// Converts the scalar to produce a machine-pointer-sized unsigned integer.
|
||||
/// Fails if the scalar is a pointer.
|
||||
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())
|
||||
}
|
||||
|
||||
@@ -433,7 +433,7 @@ impl<'tcx, Prov: Provenance> Scalar<Prov> {
|
||||
/// Converts the scalar to produce a machine-pointer-sized signed integer.
|
||||
/// Fails if the scalar is a pointer.
|
||||
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())
|
||||
}
|
||||
|
||||
|
||||
@@ -1753,7 +1753,7 @@ pub fn write_allocation_bytes<'tcx, Prov: Provenance, Extra, Bytes: AllocBytes>(
|
||||
let mut i = 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();
|
||||
|
||||
|
||||
@@ -252,7 +252,7 @@ impl ScalarInt {
|
||||
|
||||
#[inline]
|
||||
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.
|
||||
@@ -328,7 +328,7 @@ impl ScalarInt {
|
||||
|
||||
#[inline]
|
||||
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]
|
||||
@@ -402,7 +402,7 @@ impl ScalarInt {
|
||||
|
||||
#[inline]
|
||||
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]
|
||||
|
||||
@@ -1067,7 +1067,7 @@ where
|
||||
if let Some(variant) = data_variant {
|
||||
// FIXME(erikdesjardins): handle non-default addrspace ptr sizes
|
||||
// (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() {
|
||||
let field_start = variant.fields.offset(i);
|
||||
if field_start <= offset {
|
||||
|
||||
@@ -1842,7 +1842,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
|
||||
}
|
||||
// Pointer types
|
||||
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(
|
||||
|this| {
|
||||
write!(this, "0x{data:x}")?;
|
||||
|
||||
@@ -106,8 +106,8 @@ pub(super) fn vtable_allocation_provider<'tcx>(
|
||||
let size = layout.size.bytes();
|
||||
let align = layout.align.abi.bytes();
|
||||
|
||||
let ptr_size = tcx.data_layout.pointer_size;
|
||||
let ptr_align = tcx.data_layout.pointer_align.abi;
|
||||
let ptr_size = tcx.data_layout.pointer_size();
|
||||
let ptr_align = tcx.data_layout.pointer_align().abi;
|
||||
|
||||
let vtable_size = ptr_size * u64::try_from(vtable_entries.len()).unwrap();
|
||||
let mut vtable = Allocation::new(vtable_size, ptr_align, AllocInit::Uninit, ());
|
||||
|
||||
@@ -20,7 +20,7 @@ pub(crate) fn lit_to_const<'tcx>(
|
||||
|
||||
let trunc = |n, width: ty::UintTy| {
|
||||
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()
|
||||
.unwrap();
|
||||
let width = Size::from_bits(width);
|
||||
|
||||
@@ -278,7 +278,7 @@ pub(crate) fn default_configuration(sess: &Session) -> Cfg {
|
||||
};
|
||||
insert_atomic(sym::integer(i), align);
|
||||
if sess.target.pointer_width as u64 == i {
|
||||
insert_atomic(sym::ptr, layout.pointer_align.abi);
|
||||
insert_atomic(sym::ptr, layout.pointer_align().abi);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,15 +47,12 @@ pub fn try_new_slice<'tcx, B: Bridge>(
|
||||
let scalar_ptr = Scalar::from_pointer(ptr, &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 ptr_size = cx.tcx.data_layout.pointer_size();
|
||||
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))?;
|
||||
allocation
|
||||
.write_scalar(
|
||||
&cx.tcx,
|
||||
alloc_range(cx.tcx.data_layout.pointer_size, scalar_meta.size()),
|
||||
scalar_meta,
|
||||
)
|
||||
.write_scalar(&cx.tcx, alloc_range(ptr_size, scalar_meta.size()), scalar_meta)
|
||||
.map_err(|e| B::Error::from_internal(e))?;
|
||||
|
||||
Ok(allocation)
|
||||
|
||||
@@ -112,7 +112,7 @@ impl<'tcx, B: Bridge> SmirCtxt<'tcx, B> {
|
||||
}
|
||||
|
||||
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> {
|
||||
|
||||
@@ -334,7 +334,7 @@ where
|
||||
Ty: TyAbiInterface<'a, C> + Copy,
|
||||
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[..] {
|
||||
"ilp32f" | "lp64f" => 32,
|
||||
"ilp32d" | "lp64d" => 64,
|
||||
@@ -369,7 +369,7 @@ where
|
||||
Ty: TyAbiInterface<'a, C> + Copy,
|
||||
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() {
|
||||
if arg.is_ignore() {
|
||||
|
||||
@@ -10,7 +10,7 @@ where
|
||||
ret.extend_integer_width_to(32);
|
||||
} else {
|
||||
ret.make_indirect();
|
||||
*offset += cx.data_layout().pointer_size;
|
||||
*offset += cx.data_layout().pointer_size();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -733,7 +733,7 @@ impl<'a, Ty> FnAbi<'a, Ty> {
|
||||
}
|
||||
|
||||
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 { .. })
|
||||
{
|
||||
// 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;
|
||||
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
|
||||
// an LLVM aggregate type for this leads to bad optimizations,
|
||||
|
||||
@@ -418,7 +418,7 @@ where
|
||||
"ilp32d" | "lp64d" => 64,
|
||||
_ => 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_fprs = 8;
|
||||
@@ -448,7 +448,7 @@ where
|
||||
Ty: TyAbiInterface<'a, C> + Copy,
|
||||
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() {
|
||||
if arg.is_ignore() {
|
||||
|
||||
@@ -10,7 +10,7 @@ where
|
||||
ret.extend_integer_width_to(32);
|
||||
} else {
|
||||
ret.make_indirect();
|
||||
*offset += cx.data_layout().pointer_size;
|
||||
*offset += cx.data_layout().pointer_size();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -219,7 +219,7 @@ where
|
||||
// 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.
|
||||
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.
|
||||
fn_abi.ret.cast_to(Reg { kind: RegKind::Integer, size: fn_abi.ret.layout.size });
|
||||
} else {
|
||||
|
||||
@@ -2198,7 +2198,10 @@ pub struct TargetMetadata {
|
||||
|
||||
impl Target {
|
||||
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.
|
||||
if dl.endian != self.endian {
|
||||
@@ -2209,9 +2212,10 @@ impl Target {
|
||||
}
|
||||
|
||||
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 {
|
||||
pointer_size: dl.pointer_size.bits(),
|
||||
pointer_size: dl_pointer_size,
|
||||
target: self.pointer_width,
|
||||
});
|
||||
}
|
||||
@@ -2650,6 +2654,11 @@ pub struct TargetOptions {
|
||||
/// Whether the target supports XRay instrumentation.
|
||||
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
|
||||
small_data_threshold_support: SmallDataThresholdSupport,
|
||||
}
|
||||
@@ -2878,6 +2887,7 @@ impl Default for TargetOptions {
|
||||
entry_name: "main".into(),
|
||||
entry_abi: CanonAbi::C,
|
||||
supports_xray: false,
|
||||
default_address_space: rustc_abi::AddressSpace::ZERO,
|
||||
small_data_threshold_support: SmallDataThresholdSupport::DefaultForArch,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -296,7 +296,7 @@ pub(crate) mod rustc {
|
||||
}
|
||||
|
||||
let target = cx.data_layout();
|
||||
let pointer_size = target.pointer_size;
|
||||
let pointer_size = target.pointer_size();
|
||||
|
||||
match ty.kind() {
|
||||
ty::Bool => Ok(Self::bool()),
|
||||
|
||||
@@ -379,7 +379,7 @@ fn layout_of_uncached<'tcx>(
|
||||
|
||||
// Potentially-wide pointers.
|
||||
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() {
|
||||
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::Dynamic(..) => {
|
||||
let mut vtable = scalar_unit(Pointer(AddressSpace::DATA));
|
||||
let mut vtable = scalar_unit(Pointer(AddressSpace::ZERO));
|
||||
vtable.valid_range_mut().start = 1;
|
||||
vtable
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>,
|
||||
ty::FnDef(..) | ty::FnPtr(..) => {
|
||||
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);
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
|
||||
@@ -17,7 +17,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>,
|
||||
let mut applicability = Applicability::MaybeIncorrect;
|
||||
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(
|
||||
cx,
|
||||
FN_TO_NUMERIC_CAST_WITH_TRUNCATION,
|
||||
|
||||
@@ -5,7 +5,7 @@ use rustc_middle::ty::{self, AdtDef, IntTy, Ty, TyCtxt, UintTy, VariantDiscr};
|
||||
/// integral type.
|
||||
pub(super) fn int_ty_to_nbits(tcx: TyCtxt<'_>, ty: Ty<'_>) -> Option<u64> {
|
||||
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::Uint(i) => i.bit_width(),
|
||||
_ => None,
|
||||
|
||||
@@ -35,7 +35,7 @@ declare_lint_pass!(UnportableVariant => [ENUM_CLIKE_UNPORTABLE_VARIANT]);
|
||||
impl<'tcx> LateLintPass<'tcx> for UnportableVariant {
|
||||
#[expect(clippy::cast_possible_wrap)]
|
||||
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;
|
||||
}
|
||||
if let ItemKind::Enum(_, _, def) = &item.kind {
|
||||
|
||||
@@ -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
|
||||
// [`ConstValue::try_get_slice_bytes_for_diagnostics`].
|
||||
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 {
|
||||
// (partially) dangling reference
|
||||
return None;
|
||||
|
||||
@@ -261,7 +261,7 @@ pub fn layout_of_ty_query(
|
||||
}
|
||||
// Potentially-wide pointers.
|
||||
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(..)) {
|
||||
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))
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
use base_db::Crate;
|
||||
use hir_def::layout::TargetDataLayout;
|
||||
use rustc_abi::{AlignFromBytesError, TargetDataLayoutErrors};
|
||||
use rustc_abi::{AlignFromBytesError, TargetDataLayoutErrors, AddressSpace};
|
||||
use triomphe::Arc;
|
||||
|
||||
use crate::db::HirDatabase;
|
||||
@@ -12,7 +12,7 @@ pub fn target_data_layout_query(
|
||||
krate: Crate,
|
||||
) -> Result<Arc<TargetDataLayout>, Arc<str>> {
|
||||
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)),
|
||||
Err(e) => {
|
||||
Err(match e {
|
||||
@@ -39,6 +39,7 @@ pub fn target_data_layout_query(
|
||||
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::UnknownPointerSpecification { err } => format!(r#"use of unknown pointer specifer in "data-layout": {err}"#),
|
||||
}.into())
|
||||
}
|
||||
},
|
||||
|
||||
@@ -630,7 +630,7 @@ impl Evaluator<'_> {
|
||||
Ok(target_data_layout) => target_data_layout,
|
||||
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 {
|
||||
target_data_layout,
|
||||
stack: vec![0],
|
||||
|
||||
Reference in New Issue
Block a user