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.
|
/// * 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
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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(),
|
||||||
|
|||||||
@@ -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),),
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -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));
|
||||||
|
|||||||
@@ -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),
|
||||||
));
|
));
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -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) => {
|
||||||
|
|||||||
@@ -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));
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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"),
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)]
|
||||||
|
|||||||
@@ -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())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|
||||||
|
|||||||
@@ -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]
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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}")?;
|
||||||
|
|||||||
@@ -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, ());
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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> {
|
||||||
|
|||||||
@@ -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() {
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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() {
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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()),
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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())
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -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],
|
||||||
|
|||||||
Reference in New Issue
Block a user