CTFE: move target_{i, u}size_{min, max)
to rustc_abi::TargetDataLayout
This commit is contained in:
parent
bf2f8ff2ec
commit
39cfe70e4f
@ -354,17 +354,19 @@ pub fn ptr_sized_integer(&self) -> Integer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the theoretical maximum address.
|
|
||||||
///
|
|
||||||
/// Note that this doesn't take into account target-specific limitations.
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn max_address(&self) -> u64 {
|
pub fn target_usize_max(&self) -> u64 {
|
||||||
match self.pointer_size.bits() {
|
self.pointer_size.unsigned_int_max().try_into().unwrap()
|
||||||
16 => u16::MAX.into(),
|
}
|
||||||
32 => u32::MAX.into(),
|
|
||||||
64 => u64::MAX,
|
#[inline]
|
||||||
bits => panic!("max_address: unknown pointer bit size {}", bits),
|
pub fn target_isize_min(&self) -> i64 {
|
||||||
}
|
self.pointer_size.signed_int_min().try_into().unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn target_isize_max(&self) -> i64 {
|
||||||
|
self.pointer_size.signed_int_max().try_into().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the (inclusive) range of possible addresses for an allocation with
|
/// Returns the (inclusive) range of possible addresses for an allocation with
|
||||||
@ -373,7 +375,7 @@ pub fn max_address(&self) -> u64 {
|
|||||||
/// Note that this doesn't take into account target-specific limitations.
|
/// Note that this doesn't take into account target-specific limitations.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn address_range_for(&self, size: Size, align: Align) -> (u64, u64) {
|
pub fn address_range_for(&self, size: Size, align: Align) -> (u64, u64) {
|
||||||
let end = Size::from_bytes(self.max_address());
|
let end = Size::from_bytes(self.target_usize_max());
|
||||||
let min = align.bytes();
|
let min = align.bytes();
|
||||||
let max = (end - size).align_down_to(align).bytes();
|
let max = (end - size).align_down_to(align).bytes();
|
||||||
(min, max)
|
(min, max)
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
use rustc_hir::def::DefKind;
|
use rustc_hir::def::DefKind;
|
||||||
use rustc_hir::{LangItem, CRATE_HIR_ID};
|
use rustc_hir::{LangItem, CRATE_HIR_ID};
|
||||||
use rustc_middle::mir;
|
use rustc_middle::mir;
|
||||||
use rustc_middle::mir::interpret::PointerArithmetic;
|
|
||||||
use rustc_middle::ty::layout::{FnAbiOf, TyAndLayout};
|
use rustc_middle::ty::layout::{FnAbiOf, TyAndLayout};
|
||||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||||
use rustc_session::lint::builtin::INVALID_ALIGNMENT;
|
use rustc_session::lint::builtin::INVALID_ALIGNMENT;
|
||||||
@ -17,7 +16,7 @@
|
|||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_middle::mir::AssertMessage;
|
use rustc_middle::mir::AssertMessage;
|
||||||
use rustc_span::symbol::{sym, Symbol};
|
use rustc_span::symbol::{sym, Symbol};
|
||||||
use rustc_target::abi::{Align, Size};
|
use rustc_target::abi::{Align, HasDataLayout as _, Size};
|
||||||
use rustc_target::spec::abi::Abi as CallAbi;
|
use rustc_target::spec::abi::Abi as CallAbi;
|
||||||
|
|
||||||
use crate::errors::{LongRunning, LongRunningWarn};
|
use crate::errors::{LongRunning, LongRunningWarn};
|
||||||
@ -304,8 +303,8 @@ fn align_offset(
|
|||||||
Ok(ControlFlow::Break(()))
|
Ok(ControlFlow::Break(()))
|
||||||
} else {
|
} else {
|
||||||
// Not alignable in const, return `usize::MAX`.
|
// Not alignable in const, return `usize::MAX`.
|
||||||
let usize_max = Scalar::from_target_usize(self.target_usize_max(), self);
|
let usize_max = self.data_layout().target_usize_max();
|
||||||
self.write_scalar(usize_max, dest)?;
|
self.write_scalar(Scalar::from_target_usize(usize_max, self), dest)?;
|
||||||
self.return_to_block(ret)?;
|
self.return_to_block(ret)?;
|
||||||
Ok(ControlFlow::Break(()))
|
Ok(ControlFlow::Break(()))
|
||||||
}
|
}
|
||||||
|
@ -5,9 +5,7 @@
|
|||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_middle::mir::{
|
use rustc_middle::mir::{
|
||||||
self,
|
self,
|
||||||
interpret::{
|
interpret::{Allocation, ConstAllocation, ConstValue, GlobalId, InterpResult, Scalar},
|
||||||
Allocation, ConstAllocation, ConstValue, GlobalId, InterpResult, PointerArithmetic, Scalar,
|
|
||||||
},
|
|
||||||
BinOp, NonDivergingIntrinsic,
|
BinOp, NonDivergingIntrinsic,
|
||||||
};
|
};
|
||||||
use rustc_middle::ty;
|
use rustc_middle::ty;
|
||||||
@ -15,7 +13,7 @@
|
|||||||
use rustc_middle::ty::GenericArgsRef;
|
use rustc_middle::ty::GenericArgsRef;
|
||||||
use rustc_middle::ty::{Ty, TyCtxt};
|
use rustc_middle::ty::{Ty, TyCtxt};
|
||||||
use rustc_span::symbol::{sym, Symbol};
|
use rustc_span::symbol::{sym, Symbol};
|
||||||
use rustc_target::abi::{Abi, Align, Primitive, Size};
|
use rustc_target::abi::{Abi, Align, HasDataLayout as _, Primitive, Size};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
util::ensure_monomorphic_enough, CheckInAllocMsg, ImmTy, InterpCx, Machine, OpTy, PlaceTy,
|
util::ensure_monomorphic_enough, CheckInAllocMsg, ImmTy, InterpCx, Machine, OpTy, PlaceTy,
|
||||||
@ -361,11 +359,12 @@ pub fn emulate_intrinsic(
|
|||||||
)?;
|
)?;
|
||||||
|
|
||||||
// Perform division by size to compute return value.
|
// Perform division by size to compute return value.
|
||||||
|
let dl = self.data_layout();
|
||||||
let ret_layout = if intrinsic_name == sym::ptr_offset_from_unsigned {
|
let ret_layout = if intrinsic_name == sym::ptr_offset_from_unsigned {
|
||||||
assert!(0 <= dist && dist <= self.target_isize_max());
|
assert!(0 <= dist && dist <= dl.target_isize_max());
|
||||||
usize_layout
|
usize_layout
|
||||||
} else {
|
} else {
|
||||||
assert!(self.target_isize_min() <= dist && dist <= self.target_isize_max());
|
assert!(dl.target_isize_min() <= dist && dist <= dl.target_isize_max());
|
||||||
isize_layout
|
isize_layout
|
||||||
};
|
};
|
||||||
let pointee_layout = self.layout_of(instance_args.type_at(0))?;
|
let pointee_layout = self.layout_of(instance_args.type_at(0))?;
|
||||||
|
@ -1244,7 +1244,7 @@ pub fn ptr_scalar_range(
|
|||||||
if offset > size.bytes() {
|
if offset > size.bytes() {
|
||||||
// If the pointer is out-of-bounds, we do not have a
|
// If the pointer is out-of-bounds, we do not have a
|
||||||
// meaningful range to return.
|
// meaningful range to return.
|
||||||
0..=dl.max_address()
|
0..=dl.target_usize_max()
|
||||||
} else {
|
} else {
|
||||||
let (min, max) = dl.address_range_for(size, align);
|
let (min, max) = dl.address_range_for(size, align);
|
||||||
(min + offset)..=(max + offset)
|
(min + offset)..=(max + offset)
|
||||||
|
@ -19,33 +19,19 @@ fn pointer_size(&self) -> Size {
|
|||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn max_size_of_val(&self) -> Size {
|
fn max_size_of_val(&self) -> Size {
|
||||||
Size::from_bytes(self.target_isize_max())
|
Size::from_bytes(self.data_layout().target_isize_max())
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn target_usize_max(&self) -> u64 {
|
|
||||||
self.pointer_size().unsigned_int_max().try_into().unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn target_isize_min(&self) -> i64 {
|
|
||||||
self.pointer_size().signed_int_min().try_into().unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn target_isize_max(&self) -> i64 {
|
|
||||||
self.pointer_size().signed_int_max().try_into().unwrap()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn target_usize_to_isize(&self, val: u64) -> i64 {
|
fn target_usize_to_isize(&self, val: u64) -> i64 {
|
||||||
|
let dl = self.data_layout();
|
||||||
let val = val as i64;
|
let val = val as i64;
|
||||||
// Now wrap-around into the machine_isize range.
|
// Now wrap-around into the machine_isize range.
|
||||||
if val > self.target_isize_max() {
|
if val > dl.target_isize_max() {
|
||||||
// This can only happen if the ptr size is < 64, so we know max_usize_plus_1 fits into
|
// This can only happen if the ptr size is < 64, so we know max_usize_plus_1 fits into
|
||||||
// i64.
|
// i64.
|
||||||
debug_assert!(self.pointer_size().bits() < 64);
|
debug_assert!(dl.pointer_size.bits() < 64);
|
||||||
let max_usize_plus_1 = 1u128 << self.pointer_size().bits();
|
let max_usize_plus_1 = 1u128 << dl.pointer_size.bits();
|
||||||
val - i64::try_from(max_usize_plus_1).unwrap()
|
val - i64::try_from(max_usize_plus_1).unwrap()
|
||||||
} else {
|
} else {
|
||||||
val
|
val
|
||||||
@ -58,7 +44,7 @@ fn target_usize_to_isize(&self, val: u64) -> i64 {
|
|||||||
#[inline]
|
#[inline]
|
||||||
fn truncate_to_ptr(&self, (val, over): (u64, bool)) -> (u64, bool) {
|
fn truncate_to_ptr(&self, (val, over): (u64, bool)) -> (u64, bool) {
|
||||||
let val = u128::from(val);
|
let val = u128::from(val);
|
||||||
let max_ptr_plus_1 = 1u128 << self.pointer_size().bits();
|
let max_ptr_plus_1 = 1u128 << self.data_layout().pointer_size.bits();
|
||||||
(u64::try_from(val % max_ptr_plus_1).unwrap(), over || val >= max_ptr_plus_1)
|
(u64::try_from(val % max_ptr_plus_1).unwrap(), over || val >= max_ptr_plus_1)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,11 +62,11 @@ fn overflowing_signed_offset(&self, val: u64, i: i64) -> (u64, bool) {
|
|||||||
let n = i.unsigned_abs();
|
let n = i.unsigned_abs();
|
||||||
if i >= 0 {
|
if i >= 0 {
|
||||||
let (val, over) = self.overflowing_offset(val, n);
|
let (val, over) = self.overflowing_offset(val, n);
|
||||||
(val, over || i > self.target_isize_max())
|
(val, over || i > self.data_layout().target_isize_max())
|
||||||
} else {
|
} else {
|
||||||
let res = val.overflowing_sub(n);
|
let res = val.overflowing_sub(n);
|
||||||
let (val, over) = self.truncate_to_ptr(res);
|
let (val, over) = self.truncate_to_ptr(res);
|
||||||
(val, over || i < self.target_isize_min())
|
(val, over || i < self.data_layout().target_isize_min())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -207,7 +207,7 @@ fn alloc_base_addr(
|
|||||||
.checked_add(max(size.bytes(), 1))
|
.checked_add(max(size.bytes(), 1))
|
||||||
.ok_or_else(|| err_exhaust!(AddressSpaceFull))?;
|
.ok_or_else(|| err_exhaust!(AddressSpaceFull))?;
|
||||||
// Even if `Size` didn't overflow, we might still have filled up the address space.
|
// Even if `Size` didn't overflow, we might still have filled up the address space.
|
||||||
if global_state.next_base_addr > ecx.target_usize_max() {
|
if global_state.next_base_addr > ecx.data_layout().target_usize_max() {
|
||||||
throw_exhaust!(AddressSpaceFull);
|
throw_exhaust!(AddressSpaceFull);
|
||||||
}
|
}
|
||||||
// Given that `next_base_addr` increases in each allocation, pushing the
|
// Given that `next_base_addr` increases in each allocation, pushing the
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
use rustc_middle::{mir, ty};
|
use rustc_middle::{mir, ty};
|
||||||
use rustc_target::spec::abi::Abi;
|
use rustc_target::spec::abi::Abi;
|
||||||
|
use rustc_target::abi::HasDataLayout as _;
|
||||||
|
|
||||||
use crate::*;
|
use crate::*;
|
||||||
use helpers::check_arg_count;
|
use helpers::check_arg_count;
|
||||||
@ -108,7 +109,8 @@ fn align_offset(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Return error result (usize::MAX), and jump to caller.
|
// Return error result (usize::MAX), and jump to caller.
|
||||||
this.write_scalar(Scalar::from_target_usize(this.target_usize_max(), this), dest)?;
|
let usize_max = this.data_layout().target_usize_max();
|
||||||
|
this.write_scalar(Scalar::from_target_usize(usize_max, this), dest)?;
|
||||||
this.go_to_block(ret);
|
this.go_to_block(ret);
|
||||||
Ok(true)
|
Ok(true)
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_middle::ty::TyCtxt;
|
use rustc_middle::ty::TyCtxt;
|
||||||
use rustc_target::abi::{Align, Size};
|
use rustc_target::abi::{Align, Size, HasDataLayout as _};
|
||||||
|
|
||||||
use crate::shims::os_str::bytes_to_os_str;
|
use crate::shims::os_str::bytes_to_os_str;
|
||||||
use crate::*;
|
use crate::*;
|
||||||
@ -753,7 +753,7 @@ fn read(
|
|||||||
// We cap the number of read bytes to the largest value that we are able to fit in both the
|
// We cap the number of read bytes to the largest value that we are able to fit in both the
|
||||||
// host's and target's `isize`. This saves us from having to handle overflows later.
|
// host's and target's `isize`. This saves us from having to handle overflows later.
|
||||||
let count = count
|
let count = count
|
||||||
.min(u64::try_from(this.target_isize_max()).unwrap())
|
.min(u64::try_from(this.data_layout().target_isize_max()).unwrap())
|
||||||
.min(u64::try_from(isize::MAX).unwrap());
|
.min(u64::try_from(isize::MAX).unwrap());
|
||||||
let communicate = this.machine.communicate();
|
let communicate = this.machine.communicate();
|
||||||
|
|
||||||
@ -807,7 +807,7 @@ fn write(
|
|||||||
// We cap the number of written bytes to the largest value that we are able to fit in both the
|
// We cap the number of written bytes to the largest value that we are able to fit in both the
|
||||||
// host's and target's `isize`. This saves us from having to handle overflows later.
|
// host's and target's `isize`. This saves us from having to handle overflows later.
|
||||||
let count = count
|
let count = count
|
||||||
.min(u64::try_from(this.target_isize_max()).unwrap())
|
.min(u64::try_from(this.data_layout().target_isize_max()).unwrap())
|
||||||
.min(u64::try_from(isize::MAX).unwrap());
|
.min(u64::try_from(isize::MAX).unwrap());
|
||||||
let communicate = this.machine.communicate();
|
let communicate = this.machine.communicate();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user