Skip to content

Commit 626605c

Browse files
committed
consistently treat None-tagged pointers as ints; get rid of some deprecated Scalar methods
1 parent d4f7dd6 commit 626605c

File tree

29 files changed

+144
-138
lines changed

29 files changed

+144
-138
lines changed

compiler/rustc_codegen_llvm/src/common.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ impl ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> {
243243
self.const_bitcast(llval, llty)
244244
}
245245
}
246-
Scalar::Ptr(ptr) => {
246+
Scalar::Ptr(ptr, _size) => {
247247
let (alloc_id, offset) = ptr.into_parts();
248248
let (base_addr, base_addr_space) = match self.tcx.global_alloc(alloc_id) {
249249
GlobalAlloc::Memory(alloc) => {

compiler/rustc_codegen_llvm/src/consts.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use rustc_codegen_ssa::traits::*;
1111
use rustc_hir::def_id::DefId;
1212
use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
1313
use rustc_middle::mir::interpret::{
14-
read_target_uint, Allocation, ErrorHandled, GlobalAlloc, Pointer,
14+
read_target_uint, Allocation, ErrorHandled, GlobalAlloc, Pointer, Scalar as InterpScalar,
1515
};
1616
use rustc_middle::mir::mono::MonoItem;
1717
use rustc_middle::ty::{self, Instance, Ty};
@@ -55,7 +55,10 @@ pub fn const_alloc_to_llvm(cx: &CodegenCx<'ll, '_>, alloc: &Allocation) -> &'ll
5555
};
5656

5757
llvals.push(cx.scalar_to_backend(
58-
Pointer::new(alloc_id, Size::from_bytes(ptr_offset)).into(),
58+
InterpScalar::from_pointer(
59+
Pointer::new(alloc_id, Size::from_bytes(ptr_offset)),
60+
&cx.tcx,
61+
),
5962
&Scalar { value: Primitive::Pointer, valid_range: 0..=!0 },
6063
cx.type_i8p_ext(address_space),
6164
));

compiler/rustc_codegen_ssa/src/mir/operand.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -90,10 +90,10 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
9090
Abi::ScalarPair(ref a, _) => a,
9191
_ => bug!("from_const: invalid ScalarPair layout: {:#?}", layout),
9292
};
93-
let a = Scalar::from(Pointer::new(
94-
bx.tcx().create_memory_alloc(data),
95-
Size::from_bytes(start),
96-
));
93+
let a = Scalar::from_pointer(
94+
Pointer::new(bx.tcx().create_memory_alloc(data), Size::from_bytes(start)),
95+
&bx.tcx(),
96+
);
9797
let a_llval = bx.scalar_to_backend(
9898
a,
9999
a_scalar,

compiler/rustc_middle/src/mir/interpret/allocation.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,7 @@ impl<Tag: Copy, Extra> Allocation<Tag, Extra> {
333333
// Maybe a pointer.
334334
if let Some(&prov) = self.relocations.get(&range.start) {
335335
let ptr = Pointer::new(prov, Size::from_bytes(bits));
336-
return Ok(ScalarMaybeUninit::Scalar(ptr.into()));
336+
return Ok(ScalarMaybeUninit::from_pointer(ptr, cx));
337337
}
338338
}
339339
// We don't. Just return the bits.
@@ -363,7 +363,7 @@ impl<Tag: Copy, Extra> Allocation<Tag, Extra> {
363363
}
364364
};
365365

366-
let (bytes, provenance) = match val.to_bits_or_ptr(range.size, cx) {
366+
let (bytes, provenance) = match val.to_bits_or_ptr(range.size) {
367367
Err(val) => {
368368
let (provenance, offset) = val.into_parts();
369369
(u128::from(offset.bytes()), Some(provenance))

compiler/rustc_middle/src/mir/interpret/pointer.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ impl<T: HasDataLayout> PointerArithmetic for T {}
8787
/// mostly opaque; the `Machine` trait extends it with some more operations that also have access to
8888
/// some global state.
8989
pub trait Provenance: Copy {
90-
/// Says whether the `offset` field of `Pointer` is the actual physical address.
90+
/// Says whether the `offset` field of `Pointer`s with this provenance is the actual physical address.
9191
/// If `true, ptr-to-int casts work by simply discarding the provenance.
9292
/// If `false`, ptr-to-int casts are not supported.
9393
const OFFSET_IS_ADDR: bool;

compiler/rustc_middle/src/mir/interpret/value.rs

+66-79
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,11 @@ pub enum Scalar<Tag = AllocId> {
128128
/// A pointer into an `Allocation`. An `Allocation` in the `memory` module has a list of
129129
/// relocations, but a `Scalar` is only large enough to contain one, so we just represent the
130130
/// relocation and its associated offset together as a `Pointer` here.
131-
Ptr(Pointer<Tag>),
131+
///
132+
/// We also store the size of the pointer, such that a `Scalar` always knows how big it is.
133+
/// The size is always the pointer size of the current target, but this is not information
134+
/// that we always have readily available.
135+
Ptr(Pointer<Tag>, u8),
132136
}
133137

134138
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
@@ -139,7 +143,7 @@ pub enum Scalar<Tag = AllocId> {
139143
impl<Tag: Provenance> fmt::Debug for Scalar<Tag> {
140144
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
141145
match self {
142-
Scalar::Ptr(ptr) => write!(f, "{:?}", ptr),
146+
Scalar::Ptr(ptr, _size) => write!(f, "{:?}", ptr),
143147
Scalar::Int(int) => write!(f, "{:?}", int),
144148
}
145149
}
@@ -148,7 +152,7 @@ impl<Tag: Provenance> fmt::Debug for Scalar<Tag> {
148152
impl<Tag: Provenance> fmt::Display for Scalar<Tag> {
149153
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
150154
match self {
151-
Scalar::Ptr(ptr) => write!(f, "pointer to {:?}", ptr),
155+
Scalar::Ptr(ptr, _size) => write!(f, "pointer to {:?}", ptr),
152156
Scalar::Int(int) => write!(f, "{:?}", int),
153157
}
154158
}
@@ -168,13 +172,6 @@ impl<Tag> From<Double> for Scalar<Tag> {
168172
}
169173
}
170174

171-
impl<Tag> From<Pointer<Tag>> for Scalar<Tag> {
172-
#[inline(always)]
173-
fn from(ptr: Pointer<Tag>) -> Self {
174-
Scalar::Ptr(ptr)
175-
}
176-
}
177-
178175
impl<Tag> From<ScalarInt> for Scalar<Tag> {
179176
#[inline(always)]
180177
fn from(ptr: ScalarInt) -> Self {
@@ -185,21 +182,26 @@ impl<Tag> From<ScalarInt> for Scalar<Tag> {
185182
impl<'tcx, Tag> Scalar<Tag> {
186183
pub const ZST: Self = Scalar::Int(ScalarInt::ZST);
187184

188-
#[inline]
189-
pub fn null_ptr(cx: &impl HasDataLayout) -> Self {
190-
Scalar::Int(ScalarInt::null(cx.data_layout().pointer_size))
185+
#[inline(always)]
186+
pub fn from_pointer(ptr: Pointer<Tag>, cx: &impl HasDataLayout) -> Self {
187+
Scalar::Ptr(ptr, u8::try_from(cx.pointer_size().bytes()).unwrap())
191188
}
192189

193190
/// Create a Scalar from a pointer with an `Option<_>` tag (where `None` represents a plain integer).
194191
pub fn from_maybe_pointer(ptr: Pointer<Option<Tag>>, cx: &impl HasDataLayout) -> Self {
195192
match ptr.into_parts() {
196-
(Some(tag), offset) => Scalar::Ptr(Pointer::new(tag, offset)),
193+
(Some(tag), offset) => Scalar::from_pointer(Pointer::new(tag, offset), cx),
197194
(None, offset) => {
198195
Scalar::Int(ScalarInt::try_from_uint(offset.bytes(), cx.pointer_size()).unwrap())
199196
}
200197
}
201198
}
202199

200+
#[inline]
201+
pub fn null_ptr(cx: &impl HasDataLayout) -> Self {
202+
Scalar::Int(ScalarInt::null(cx.pointer_size()))
203+
}
204+
203205
#[inline(always)]
204206
fn ptr_op(
205207
self,
@@ -209,7 +211,10 @@ impl<'tcx, Tag> Scalar<Tag> {
209211
) -> InterpResult<'tcx, Self> {
210212
match self {
211213
Scalar::Int(int) => Ok(Scalar::Int(int.ptr_sized_op(dl, f_int)?)),
212-
Scalar::Ptr(ptr) => Ok(Scalar::Ptr(f_ptr(ptr)?)),
214+
Scalar::Ptr(ptr, sz) => {
215+
debug_assert_eq!(u64::from(sz), dl.pointer_size().bytes());
216+
Ok(Scalar::Ptr(f_ptr(ptr)?, sz))
217+
}
213218
}
214219
}
215220

@@ -334,59 +339,18 @@ impl<'tcx, Tag> Scalar<Tag> {
334339
/// This is almost certainly not the method you want! You should dispatch on the type
335340
/// and use `to_{u8,u16,...}`/`scalar_to_ptr` to perform ptr-to-int / int-to-ptr casts as needed.
336341
///
337-
/// This method only exists for the benefit of low-level memory operations
338-
/// as well as the implementation of the above methods.
342+
/// This method only exists for the benefit of low-level memory operations.
339343
#[inline]
340-
pub fn to_bits_or_ptr(
341-
self,
342-
target_size: Size,
343-
cx: &impl HasDataLayout,
344-
) -> Result<u128, Pointer<Tag>> {
344+
pub fn to_bits_or_ptr(self, target_size: Size) -> Result<u128, Pointer<Tag>> {
345345
assert_ne!(target_size.bytes(), 0, "you should never look at the bits of a ZST");
346346
match self {
347347
Scalar::Int(int) => Ok(int.assert_bits(target_size)),
348-
Scalar::Ptr(ptr) => {
349-
assert_eq!(target_size, cx.data_layout().pointer_size);
348+
Scalar::Ptr(ptr, sz) => {
349+
assert_eq!(target_size.bytes(), u64::from(sz));
350350
Err(ptr)
351351
}
352352
}
353353
}
354-
355-
/// Do not call this method! It does not do ptr-to-int casts when needed.
356-
#[inline(always)]
357-
pub fn assert_bits(self, target_size: Size) -> u128 {
358-
self.assert_int().assert_bits(target_size)
359-
}
360-
361-
/// Do not call this method! It does not do ptr-to-int casts when needed.
362-
#[inline]
363-
pub fn assert_int(self) -> ScalarInt {
364-
match self {
365-
Scalar::Ptr(_) => bug!("expected an int but got an abstract pointer"),
366-
Scalar::Int(int) => int,
367-
}
368-
}
369-
370-
/// Do not call this method! It does not do int-to-ptr casts when needed.
371-
#[inline]
372-
pub fn assert_ptr(self) -> Pointer<Tag> {
373-
match self {
374-
Scalar::Ptr(p) => p,
375-
Scalar::Int { .. } => bug!("expected a Pointer but got Raw bits"),
376-
}
377-
}
378-
379-
/// Do not call this method! Dispatch based on the type instead.
380-
#[inline]
381-
pub fn is_bits(self) -> bool {
382-
matches!(self, Scalar::Int { .. })
383-
}
384-
385-
/// Do not call this method! Dispatch based on the type instead.
386-
#[inline]
387-
pub fn is_ptr(self) -> bool {
388-
matches!(self, Scalar::Ptr(_))
389-
}
390354
}
391355

392356
impl<'tcx, Tag: Provenance> Scalar<Tag> {
@@ -396,7 +360,7 @@ impl<'tcx, Tag: Provenance> Scalar<Tag> {
396360
#[inline]
397361
pub fn erase_for_fmt(self) -> Scalar {
398362
match self {
399-
Scalar::Ptr(ptr) => Scalar::Ptr(ptr.erase_for_fmt()),
363+
Scalar::Ptr(ptr, sz) => Scalar::Ptr(ptr.erase_for_fmt(), sz),
400364
Scalar::Int(int) => Scalar::Int(int),
401365
}
402366
}
@@ -405,25 +369,45 @@ impl<'tcx, Tag: Provenance> Scalar<Tag> {
405369
/// likely want to use instead.
406370
///
407371
/// Will perform ptr-to-int casts if needed and possible.
372+
#[inline]
373+
pub fn try_to_int(self) -> Option<ScalarInt> {
374+
match self {
375+
Scalar::Int(int) => Some(int),
376+
Scalar::Ptr(ptr, sz) => {
377+
if Tag::OFFSET_IS_ADDR {
378+
Some(
379+
ScalarInt::try_from_uint(ptr.offset.bytes(), Size::from_bytes(sz)).unwrap(),
380+
)
381+
} else {
382+
None
383+
}
384+
}
385+
}
386+
}
387+
388+
#[inline(always)]
389+
pub fn assert_int(self) -> ScalarInt {
390+
self.try_to_int().unwrap()
391+
}
392+
408393
#[inline]
409394
pub fn to_bits(self, target_size: Size) -> InterpResult<'tcx, u128> {
410395
assert_ne!(target_size.bytes(), 0, "you should never look at the bits of a ZST");
411-
match self {
412-
Scalar::Int(int) => int.to_bits(target_size).map_err(|size| {
396+
self.try_to_int()
397+
.ok_or_else(|| err_unsup!(ReadPointerAsBytes))?
398+
.to_bits(target_size)
399+
.map_err(|size| {
413400
err_ub!(ScalarSizeMismatch {
414401
target_size: target_size.bytes(),
415402
data_size: size.bytes(),
416403
})
417404
.into()
418-
}),
419-
Scalar::Ptr(ptr) => {
420-
if Tag::OFFSET_IS_ADDR {
421-
Ok(ptr.offset.bytes().into())
422-
} else {
423-
throw_unsup!(ReadPointerAsBytes)
424-
}
425-
}
426-
}
405+
})
406+
}
407+
408+
#[inline(always)]
409+
pub fn assert_bits(self, target_size: Size) -> u128 {
410+
self.to_bits(target_size).unwrap()
427411
}
428412

429413
pub fn to_bool(self) -> InterpResult<'tcx, bool> {
@@ -547,13 +531,6 @@ impl<Tag> From<Scalar<Tag>> for ScalarMaybeUninit<Tag> {
547531
}
548532
}
549533

550-
impl<Tag> From<Pointer<Tag>> for ScalarMaybeUninit<Tag> {
551-
#[inline(always)]
552-
fn from(s: Pointer<Tag>) -> Self {
553-
ScalarMaybeUninit::Scalar(s.into())
554-
}
555-
}
556-
557534
// We want the `Debug` output to be readable as it is used by `derive(Debug)` for
558535
// all the Miri types.
559536
impl<Tag: Provenance> fmt::Debug for ScalarMaybeUninit<Tag> {
@@ -575,6 +552,16 @@ impl<Tag: Provenance> fmt::Display for ScalarMaybeUninit<Tag> {
575552
}
576553

577554
impl<Tag> ScalarMaybeUninit<Tag> {
555+
#[inline]
556+
pub fn from_pointer(ptr: Pointer<Tag>, cx: &impl HasDataLayout) -> Self {
557+
ScalarMaybeUninit::Scalar(Scalar::from_pointer(ptr, cx))
558+
}
559+
560+
#[inline]
561+
pub fn from_maybe_pointer(ptr: Pointer<Option<Tag>>, cx: &impl HasDataLayout) -> Self {
562+
ScalarMaybeUninit::Scalar(Scalar::from_maybe_pointer(ptr, cx))
563+
}
564+
578565
#[inline]
579566
pub fn check_init(self) -> InterpResult<'static, Scalar<Tag>> {
580567
match self {

compiler/rustc_middle/src/mir/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2458,7 +2458,7 @@ pub enum ConstantKind<'tcx> {
24582458
impl Constant<'tcx> {
24592459
pub fn check_static_ptr(&self, tcx: TyCtxt<'_>) -> Option<DefId> {
24602460
match self.literal.const_for_ty()?.val.try_to_scalar() {
2461-
Some(Scalar::Ptr(ptr)) => match tcx.global_alloc(ptr.provenance) {
2461+
Some(Scalar::Ptr(ptr, _size)) => match tcx.global_alloc(ptr.provenance) {
24622462
GlobalAlloc::Static(def_id) => {
24632463
assert!(!tcx.is_thread_local_static(def_id));
24642464
Some(def_id)

compiler/rustc_middle/src/ty/print/pretty.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -974,7 +974,7 @@ pub trait PrettyPrinter<'tcx>:
974974
print_ty: bool,
975975
) -> Result<Self::Const, Self::Error> {
976976
match scalar {
977-
Scalar::Ptr(ptr) => self.pretty_print_const_scalar_ptr(ptr, ty, print_ty),
977+
Scalar::Ptr(ptr, _size) => self.pretty_print_const_scalar_ptr(ptr, ty, print_ty),
978978
Scalar::Int(int) => self.pretty_print_const_scalar_int(int, ty, print_ty),
979979
}
980980
}

compiler/rustc_middle/src/ty/relate.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -595,7 +595,10 @@ fn check_const_value_eq<R: TypeRelation<'tcx>>(
595595
(ConstValue::Scalar(Scalar::Int(a_val)), ConstValue::Scalar(Scalar::Int(b_val))) => {
596596
a_val == b_val
597597
}
598-
(ConstValue::Scalar(Scalar::Ptr(a_val)), ConstValue::Scalar(Scalar::Ptr(b_val))) => {
598+
(
599+
ConstValue::Scalar(Scalar::Ptr(a_val, _a_size)),
600+
ConstValue::Scalar(Scalar::Ptr(b_val, _b_size)),
601+
) => {
599602
a_val == b_val
600603
|| match (tcx.global_alloc(a_val.provenance), tcx.global_alloc(b_val.provenance)) {
601604
(GlobalAlloc::Function(a_instance), GlobalAlloc::Function(b_instance)) => {

compiler/rustc_middle/src/ty/vtable.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::convert::TryFrom;
22

3-
use crate::mir::interpret::{alloc_range, AllocId, Allocation, Pointer, Scalar};
3+
use crate::mir::interpret::{alloc_range, AllocId, Allocation, Pointer, Scalar, ScalarMaybeUninit};
44
use crate::ty::fold::TypeFoldable;
55
use crate::ty::{self, DefId, SubstsRef, Ty, TyCtxt};
66
use rustc_ast::Mutability;
@@ -74,7 +74,7 @@ impl<'tcx> TyCtxt<'tcx> {
7474
let instance = ty::Instance::resolve_drop_in_place(tcx, ty);
7575
let fn_alloc_id = tcx.create_fn_alloc(instance);
7676
let fn_ptr = Pointer::from(fn_alloc_id);
77-
fn_ptr.into()
77+
ScalarMaybeUninit::from_pointer(fn_ptr, &tcx)
7878
}
7979
VtblEntry::MetadataSize => Scalar::from_uint(size, ptr_size).into(),
8080
VtblEntry::MetadataAlign => Scalar::from_uint(align, ptr_size).into(),
@@ -90,7 +90,7 @@ impl<'tcx> TyCtxt<'tcx> {
9090
.polymorphize(tcx);
9191
let fn_alloc_id = tcx.create_fn_alloc(instance);
9292
let fn_ptr = Pointer::from(fn_alloc_id);
93-
fn_ptr.into()
93+
ScalarMaybeUninit::from_pointer(fn_ptr, &tcx)
9494
}
9595
};
9696
vtable

compiler/rustc_mir/src/const_eval/eval_queries.rs

+2
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ pub(super) fn op_to_const<'tcx>(
139139
op.try_as_mplace()
140140
};
141141

142+
// We know `offset` is relative to the allocation, so we can use `into_parts`.
142143
let to_const_value = |mplace: &MPlaceTy<'_>| match mplace.ptr.into_parts() {
143144
(Some(alloc_id), offset) => {
144145
let alloc = ecx.tcx.global_alloc(alloc_id).unwrap_memory();
@@ -164,6 +165,7 @@ pub(super) fn op_to_const<'tcx>(
164165
ScalarMaybeUninit::Uninit => to_const_value(&op.assert_mem_place()),
165166
},
166167
Immediate::ScalarPair(a, b) => {
168+
// We know `offset` is relative to the allocation, so we can use `into_parts`.
167169
let (data, start) = match ecx.scalar_to_ptr(a.check_init().unwrap()).into_parts() {
168170
(Some(alloc_id), offset) => {
169171
(ecx.tcx.global_alloc(alloc_id).unwrap_memory(), offset.bytes())

0 commit comments

Comments
 (0)