Skip to content

Commit f116dd7

Browse files
authored
Rollup merge of #97653 - RalfJung:int-to-ptr, r=oli-obk
add cast kind of from_exposed_addr (int-to-ptr casts) This is basically the dual to #97582, for int2ptr casts. Cc `@tmiasko` #97649
2 parents 025cf96 + d5a590f commit f116dd7

File tree

10 files changed

+96
-39
lines changed

10 files changed

+96
-39
lines changed

compiler/rustc_borrowck/src/type_check/mod.rs

+37-13
Original file line numberDiff line numberDiff line change
@@ -2154,31 +2154,55 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
21542154
match (cast_ty_from, cast_ty_to) {
21552155
(Some(CastTy::Ptr(_) | CastTy::FnPtr), Some(CastTy::Int(_))) => (),
21562156
_ => {
2157-
span_mirbug!(self, rvalue, "Invalid cast {:?} -> {:?}", ty_from, ty)
2157+
span_mirbug!(
2158+
self,
2159+
rvalue,
2160+
"Invalid PointerExposeAddress cast {:?} -> {:?}",
2161+
ty_from,
2162+
ty
2163+
)
21582164
}
21592165
}
21602166
}
21612167

2162-
CastKind::Misc => {
2168+
CastKind::PointerFromExposedAddress => {
21632169
let ty_from = op.ty(body, tcx);
21642170
let cast_ty_from = CastTy::from_ty(ty_from);
21652171
let cast_ty_to = CastTy::from_ty(*ty);
21662172
match (cast_ty_from, cast_ty_to) {
2167-
(None, _)
2168-
| (_, None | Some(CastTy::FnPtr))
2169-
| (Some(CastTy::Float), Some(CastTy::Ptr(_)))
2170-
| (
2171-
Some(CastTy::Ptr(_) | CastTy::FnPtr),
2172-
Some(CastTy::Float | CastTy::Int(_)),
2173-
) => {
2174-
span_mirbug!(self, rvalue, "Invalid cast {:?} -> {:?}", ty_from, ty,)
2173+
(Some(CastTy::Int(_)), Some(CastTy::Ptr(_))) => (),
2174+
_ => {
2175+
span_mirbug!(
2176+
self,
2177+
rvalue,
2178+
"Invalid PointerFromExposedAddress cast {:?} -> {:?}",
2179+
ty_from,
2180+
ty
2181+
)
21752182
}
2183+
}
2184+
}
2185+
2186+
CastKind::Misc => {
2187+
let ty_from = op.ty(body, tcx);
2188+
let cast_ty_from = CastTy::from_ty(ty_from);
2189+
let cast_ty_to = CastTy::from_ty(*ty);
2190+
// Misc casts are either between floats and ints, or one ptr type to another.
2191+
match (cast_ty_from, cast_ty_to) {
21762192
(
2177-
Some(CastTy::Int(_)),
2178-
Some(CastTy::Int(_) | CastTy::Float | CastTy::Ptr(_)),
2193+
Some(CastTy::Int(_) | CastTy::Float),
2194+
Some(CastTy::Int(_) | CastTy::Float),
21792195
)
2180-
| (Some(CastTy::Float), Some(CastTy::Int(_) | CastTy::Float))
21812196
| (Some(CastTy::Ptr(_) | CastTy::FnPtr), Some(CastTy::Ptr(_))) => (),
2197+
_ => {
2198+
span_mirbug!(
2199+
self,
2200+
rvalue,
2201+
"Invalid Misc cast {:?} -> {:?}",
2202+
ty_from,
2203+
ty,
2204+
)
2205+
}
21822206
}
21832207
}
21842208
}

compiler/rustc_codegen_cranelift/src/base.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -608,7 +608,9 @@ fn codegen_stmt<'tcx>(
608608
lval.write_cvalue(fx, operand.cast_pointer_to(to_layout));
609609
}
610610
Rvalue::Cast(
611-
CastKind::Misc | CastKind::PointerExposeAddress,
611+
CastKind::Misc
612+
| CastKind::PointerExposeAddress
613+
| CastKind::PointerFromExposedAddress,
612614
ref operand,
613615
to_ty,
614616
) => {

compiler/rustc_codegen_ssa/src/mir/rvalue.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
269269
mir::CastKind::Pointer(
270270
PointerCast::MutToConstPointer | PointerCast::ArrayToPointer,
271271
)
272-
| mir::CastKind::Misc => {
272+
| mir::CastKind::Misc
273+
// Since int2ptr can have arbitrary integer types as input (so we have to do
274+
// sign extension and all that), it is currently best handled in the same code
275+
// path as the other integer-to-X casts.
276+
| mir::CastKind::PointerFromExposedAddress => {
273277
assert!(bx.cx().is_backend_immediate(cast));
274278
let ll_t_out = bx.cx().immediate_backend_type(cast);
275279
if operand.layout.abi.is_uninhabited() {

compiler/rustc_const_eval/src/interpret/cast.rs

+24-10
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
3737
self.write_immediate(res, dest)?;
3838
}
3939

40+
PointerFromExposedAddress => {
41+
let src = self.read_immediate(src)?;
42+
let res = self.pointer_from_exposed_address_cast(&src, cast_ty)?;
43+
self.write_immediate(res, dest)?;
44+
}
45+
4046
Misc => {
4147
let src = self.read_immediate(src)?;
4248
let res = self.misc_cast(&src, cast_ty)?;
@@ -201,6 +207,24 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
201207
Ok(self.cast_from_int_like(scalar, src.layout, cast_ty)?.into())
202208
}
203209

210+
pub fn pointer_from_exposed_address_cast(
211+
&mut self,
212+
src: &ImmTy<'tcx, M::PointerTag>,
213+
cast_ty: Ty<'tcx>,
214+
) -> InterpResult<'tcx, Immediate<M::PointerTag>> {
215+
assert!(src.layout.ty.is_integral());
216+
assert_matches!(cast_ty.kind(), ty::RawPtr(_));
217+
218+
// First cast to usize.
219+
let scalar = src.to_scalar()?;
220+
let addr = self.cast_from_int_like(scalar, src.layout, self.tcx.types.usize)?;
221+
let addr = addr.to_machine_usize(self)?;
222+
223+
// Then turn address into pointer.
224+
let ptr = M::ptr_from_addr_cast(&self, addr);
225+
Ok(Scalar::from_maybe_pointer(ptr, self).into())
226+
}
227+
204228
pub fn cast_from_int_like(
205229
&self,
206230
scalar: Scalar<M::PointerTag>, // input value (there is no ScalarTy so we separate data+layout)
@@ -225,16 +249,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
225249
Scalar::from_uint(v, size)
226250
}
227251

228-
RawPtr(_) => {
229-
assert!(src_layout.ty.is_integral());
230-
231-
let size = self.pointer_size();
232-
let addr = u64::try_from(size.truncate(v)).unwrap();
233-
234-
let ptr = M::ptr_from_addr_cast(&self, addr);
235-
Scalar::from_maybe_pointer(ptr, self)
236-
}
237-
238252
Float(FloatTy::F32) if signed => Scalar::from_f32(Single::from_i128(v as i128).value),
239253
Float(FloatTy::F64) if signed => Scalar::from_f64(Double::from_i128(v as i128).value),
240254
Float(FloatTy::F32) => Scalar::from_f32(Single::from_u128(v).value),

compiler/rustc_const_eval/src/transform/check_consts/check.rs

+8-10
Original file line numberDiff line numberDiff line change
@@ -519,32 +519,30 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
519519
}
520520
}
521521

522-
Rvalue::Cast(
523-
CastKind::Pointer(PointerCast::MutToConstPointer | PointerCast::ArrayToPointer),
524-
_,
525-
_,
526-
) => {}
527-
528522
Rvalue::Cast(
529523
CastKind::Pointer(
530-
PointerCast::UnsafeFnPointer
524+
PointerCast::MutToConstPointer
525+
| PointerCast::ArrayToPointer
526+
| PointerCast::UnsafeFnPointer
531527
| PointerCast::ClosureFnPointer(_)
532528
| PointerCast::ReifyFnPointer,
533529
),
534530
_,
535531
_,
536532
) => {
537-
// Nothing to do here. Function pointer casts are allowed now.
533+
// These are all okay; they only change the type, not the data.
538534
}
539535

540536
Rvalue::Cast(CastKind::Pointer(PointerCast::Unsize), _, _) => {
541-
// Nothing to check here (`check_local_or_return_ty` ensures no trait objects occur
542-
// in the type of any local, which also excludes casts).
537+
// Unsizing is implemented for CTFE.
543538
}
544539

545540
Rvalue::Cast(CastKind::PointerExposeAddress, _, _) => {
546541
self.check_op(ops::RawPtrToIntCast);
547542
}
543+
Rvalue::Cast(CastKind::PointerFromExposedAddress, _, _) => {
544+
// Since no pointer can ever get exposed (rejected above), this is easy to support.
545+
}
548546

549547
Rvalue::Cast(CastKind::Misc, _, _) => {}
550548

compiler/rustc_const_eval/src/transform/promote_consts.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -504,7 +504,8 @@ impl<'tcx> Validator<'_, 'tcx> {
504504
// ptr-to-int casts are not possible in consts and thus not promotable
505505
Rvalue::Cast(CastKind::PointerExposeAddress, _, _) => return Err(Unpromotable),
506506

507-
// int-to-ptr casts are fine, they just use the integer value at pointer type.
507+
// all other casts including int-to-ptr casts are fine, they just use the integer value
508+
// at pointer type.
508509
Rvalue::Cast(_, operand, _) => {
509510
self.validate_operand(operand)?;
510511
}

compiler/rustc_middle/src/mir/mod.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -2613,12 +2613,18 @@ impl<'tcx> Rvalue<'tcx> {
26132613

26142614
#[derive(Clone, Copy, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)]
26152615
pub enum CastKind {
2616-
Misc,
26172616
/// An exposing pointer to address cast. A cast between a pointer and an integer type, or
26182617
/// between a function pointer and an integer type.
26192618
/// See the docs on `expose_addr` for more details.
26202619
PointerExposeAddress,
2620+
/// An address-to-pointer cast that picks up an exposed provenance.
2621+
/// See the docs on `from_exposed_addr` for more details.
2622+
PointerFromExposedAddress,
2623+
/// All sorts of pointer-to-pointer casts. Note that reference-to-raw-ptr casts are
2624+
/// translated into `&raw mut/const *r`, i.e., they are not actually casts.
26212625
Pointer(PointerCast),
2626+
/// Remaining unclassified casts.
2627+
Misc,
26222628
}
26232629

26242630
#[derive(Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)]

compiler/rustc_mir_build/src/build/expr/as_rvalue.rs

+3
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
196196
(Some(CastTy::Ptr(_) | CastTy::FnPtr), Some(CastTy::Int(_))) => {
197197
CastKind::PointerExposeAddress
198198
}
199+
(Some(CastTy::Int(_)), Some(CastTy::Ptr(_))) => {
200+
CastKind::PointerFromExposedAddress
201+
}
199202
(_, _) => CastKind::Misc,
200203
};
201204
let source = unpack!(

src/test/mir-opt/const_prop/reify_fn_ptr.main.ConstProp.diff

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
// + literal: Const { ty: fn() {main}, val: Value(Scalar(<ZST>)) }
2020
_2 = move _3 as usize (PointerExposeAddress); // scope 0 at $DIR/reify_fn_ptr.rs:4:13: 4:26
2121
StorageDead(_3); // scope 0 at $DIR/reify_fn_ptr.rs:4:25: 4:26
22-
_1 = move _2 as *const fn() (Misc); // scope 0 at $DIR/reify_fn_ptr.rs:4:13: 4:41
22+
_1 = move _2 as *const fn() (PointerFromExposedAddress); // scope 0 at $DIR/reify_fn_ptr.rs:4:13: 4:41
2323
StorageDead(_2); // scope 0 at $DIR/reify_fn_ptr.rs:4:40: 4:41
2424
StorageDead(_1); // scope 0 at $DIR/reify_fn_ptr.rs:4:41: 4:42
2525
nop; // scope 0 at $DIR/reify_fn_ptr.rs:3:11: 5:2

src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,12 @@ fn check_rvalue<'tcx>(
131131
Rvalue::Cast(CastKind::Misc, operand, _) => {
132132
check_operand(tcx, operand, span, body)
133133
},
134-
Rvalue::Cast(CastKind::Pointer(PointerCast::MutToConstPointer | PointerCast::ArrayToPointer), operand, _) => {
134+
Rvalue::Cast(
135+
CastKind::PointerFromExposedAddress
136+
| CastKind::Pointer(PointerCast::MutToConstPointer | PointerCast::ArrayToPointer),
137+
operand,
138+
_
139+
) => {
135140
check_operand(tcx, operand, span, body)
136141
},
137142
Rvalue::Cast(

0 commit comments

Comments
 (0)