1use std::assert_matches;
5
6use either::{Either, Left, Right};
7use rustc_abi as abi;
8use rustc_abi::{BackendRepr, HasDataLayout, Size};
9use rustc_hir::def::Namespace;
10use rustc_middle::mir::interpret::ScalarSizeMismatch;
11use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv, TyAndLayout};
12use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter};
13use rustc_middle::ty::{ConstInt, ScalarInt, Ty, TyCtxt};
14use rustc_middle::{bug, mir, span_bug, ty};
15use rustc_span::DUMMY_SP;
16use tracing::field::Empty;
17use tracing::trace;
18
19use super::{
20 CtfeProvenance, Frame, InterpCx, InterpResult, MPlaceTy, Machine, MemPlace, MemPlaceMeta,
21 OffsetMode, PlaceTy, Pointer, Projectable, Provenance, Scalar, alloc_range, err_ub,
22 from_known_layout, interp_ok, mir_assign_valid_types, throw_ub,
23};
24use crate::enter_trace_span;
25
26#[derive(#[automatically_derived]
impl<Prov: ::core::marker::Copy + Provenance> ::core::marker::Copy for
Immediate<Prov> {
}Copy, #[automatically_derived]
impl<Prov: ::core::clone::Clone + Provenance> ::core::clone::Clone for
Immediate<Prov> {
#[inline]
fn clone(&self) -> Immediate<Prov> {
match self {
Immediate::Scalar(__self_0) =>
Immediate::Scalar(::core::clone::Clone::clone(__self_0)),
Immediate::ScalarPair(__self_0, __self_1) =>
Immediate::ScalarPair(::core::clone::Clone::clone(__self_0),
::core::clone::Clone::clone(__self_1)),
Immediate::Uninit => Immediate::Uninit,
}
}
}Clone, #[automatically_derived]
impl<Prov: ::core::fmt::Debug + Provenance> ::core::fmt::Debug for
Immediate<Prov> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
Immediate::Scalar(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "Scalar",
&__self_0),
Immediate::ScalarPair(__self_0, __self_1) =>
::core::fmt::Formatter::debug_tuple_field2_finish(f,
"ScalarPair", __self_0, &__self_1),
Immediate::Uninit =>
::core::fmt::Formatter::write_str(f, "Uninit"),
}
}
}Debug)]
34pub enum Immediate<Prov: Provenance = CtfeProvenance> {
35 Scalar(Scalar<Prov>),
37 ScalarPair(Scalar<Prov>, Scalar<Prov>),
40 Uninit,
42}
43
44impl<Prov: Provenance> From<Scalar<Prov>> for Immediate<Prov> {
45 #[inline(always)]
46 fn from(val: Scalar<Prov>) -> Self {
47 Immediate::Scalar(val)
48 }
49}
50
51impl<Prov: Provenance> Immediate<Prov> {
52 pub fn new_pointer_with_meta(
53 ptr: Pointer<Option<Prov>>,
54 meta: MemPlaceMeta<Prov>,
55 cx: &impl HasDataLayout,
56 ) -> Self {
57 let ptr = Scalar::from_maybe_pointer(ptr, cx);
58 match meta {
59 MemPlaceMeta::None => Immediate::from(ptr),
60 MemPlaceMeta::Meta(meta) => Immediate::ScalarPair(ptr, meta),
61 }
62 }
63
64 pub fn new_slice(ptr: Pointer<Option<Prov>>, len: u64, cx: &impl HasDataLayout) -> Self {
65 Immediate::ScalarPair(
66 Scalar::from_maybe_pointer(ptr, cx),
67 Scalar::from_target_usize(len, cx),
68 )
69 }
70
71 pub fn new_dyn_trait(
72 val: Pointer<Option<Prov>>,
73 vtable: Pointer<Option<Prov>>,
74 cx: &impl HasDataLayout,
75 ) -> Self {
76 Immediate::ScalarPair(
77 Scalar::from_maybe_pointer(val, cx),
78 Scalar::from_maybe_pointer(vtable, cx),
79 )
80 }
81
82 #[inline]
83 #[cfg_attr(debug_assertions, track_caller)] pub fn to_scalar(self) -> Scalar<Prov> {
85 match self {
86 Immediate::Scalar(val) => val,
87 Immediate::ScalarPair { .. } => ::rustc_middle::util::bug::bug_fmt(format_args!("Got a scalar pair where a scalar was expected"))bug!("Got a scalar pair where a scalar was expected"),
88 Immediate::Uninit => ::rustc_middle::util::bug::bug_fmt(format_args!("Got uninit where a scalar was expected"))bug!("Got uninit where a scalar was expected"),
89 }
90 }
91
92 #[inline]
93 #[cfg_attr(debug_assertions, track_caller)] pub fn to_scalar_int(self) -> ScalarInt {
95 self.to_scalar().try_to_scalar_int().unwrap()
96 }
97
98 #[inline]
99 #[cfg_attr(debug_assertions, track_caller)] pub fn to_scalar_pair(self) -> (Scalar<Prov>, Scalar<Prov>) {
101 match self {
102 Immediate::ScalarPair(val1, val2) => (val1, val2),
103 Immediate::Scalar(..) => ::rustc_middle::util::bug::bug_fmt(format_args!("Got a scalar where a scalar pair was expected"))bug!("Got a scalar where a scalar pair was expected"),
104 Immediate::Uninit => ::rustc_middle::util::bug::bug_fmt(format_args!("Got uninit where a scalar pair was expected"))bug!("Got uninit where a scalar pair was expected"),
105 }
106 }
107
108 #[inline]
110 #[cfg_attr(debug_assertions, track_caller)] pub fn to_scalar_and_meta(self) -> (Scalar<Prov>, MemPlaceMeta<Prov>) {
112 match self {
113 Immediate::ScalarPair(val1, val2) => (val1, MemPlaceMeta::Meta(val2)),
114 Immediate::Scalar(val) => (val, MemPlaceMeta::None),
115 Immediate::Uninit => ::rustc_middle::util::bug::bug_fmt(format_args!("Got uninit where a scalar or scalar pair was expected"))bug!("Got uninit where a scalar or scalar pair was expected"),
116 }
117 }
118
119 pub fn assert_matches_abi(self, abi: BackendRepr, msg: &str, cx: &impl HasDataLayout) {
121 match (self, abi) {
122 (Immediate::Scalar(scalar), BackendRepr::Scalar(s)) => {
123 {
match (&scalar.size(), &s.size(cx)) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val,
::core::option::Option::Some(format_args!("{0}: scalar value has wrong size",
msg)));
}
}
}
};assert_eq!(scalar.size(), s.size(cx), "{msg}: scalar value has wrong size");
124 if !#[allow(non_exhaustive_omitted_patterns)] match s.primitive() {
abi::Primitive::Pointer(..) => true,
_ => false,
}matches!(s.primitive(), abi::Primitive::Pointer(..)) {
125 if !#[allow(non_exhaustive_omitted_patterns)] match scalar {
Scalar::Int(..) => true,
_ => false,
} {
{
::core::panicking::panic_fmt(format_args!("{0}: scalar value should be an integer, but has provenance",
msg));
}
};assert!(
127 matches!(scalar, Scalar::Int(..)),
128 "{msg}: scalar value should be an integer, but has provenance"
129 );
130 }
131 }
132 (
133 Immediate::ScalarPair(a_val, b_val),
134 BackendRepr::ScalarPair { a, b, b_offset: _ },
135 ) => {
136 {
match (&a_val.size(), &a.size(cx)) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val,
::core::option::Option::Some(format_args!("{0}: first component of scalar pair has wrong size",
msg)));
}
}
}
};assert_eq!(
137 a_val.size(),
138 a.size(cx),
139 "{msg}: first component of scalar pair has wrong size"
140 );
141 if !#[allow(non_exhaustive_omitted_patterns)] match a.primitive() {
abi::Primitive::Pointer(..) => true,
_ => false,
}matches!(a.primitive(), abi::Primitive::Pointer(..)) {
142 if !#[allow(non_exhaustive_omitted_patterns)] match a_val {
Scalar::Int(..) => true,
_ => false,
} {
{
::core::panicking::panic_fmt(format_args!("{0}: first component of scalar pair should be an integer, but has provenance",
msg));
}
};assert!(
143 matches!(a_val, Scalar::Int(..)),
144 "{msg}: first component of scalar pair should be an integer, but has provenance"
145 );
146 }
147 {
match (&b_val.size(), &b.size(cx)) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val,
::core::option::Option::Some(format_args!("{0}: second component of scalar pair has wrong size",
msg)));
}
}
}
};assert_eq!(
148 b_val.size(),
149 b.size(cx),
150 "{msg}: second component of scalar pair has wrong size"
151 );
152 if !#[allow(non_exhaustive_omitted_patterns)] match b.primitive() {
abi::Primitive::Pointer(..) => true,
_ => false,
}matches!(b.primitive(), abi::Primitive::Pointer(..)) {
153 if !#[allow(non_exhaustive_omitted_patterns)] match b_val {
Scalar::Int(..) => true,
_ => false,
} {
{
::core::panicking::panic_fmt(format_args!("{0}: second component of scalar pair should be an integer, but has provenance",
msg));
}
};assert!(
154 matches!(b_val, Scalar::Int(..)),
155 "{msg}: second component of scalar pair should be an integer, but has provenance"
156 );
157 }
158 }
159 (Immediate::Uninit, _) => {
160 if !abi.is_sized() {
{
::core::panicking::panic_fmt(format_args!("{0}: unsized immediates are not a thing",
msg));
}
};assert!(abi.is_sized(), "{msg}: unsized immediates are not a thing");
161 }
162 _ => {
163 ::rustc_middle::util::bug::bug_fmt(format_args!("{0}: value {1:?} does not match ABI {2:?})",
msg, self, abi))bug!("{msg}: value {self:?} does not match ABI {abi:?})",)
164 }
165 }
166 }
167
168 pub fn clear_provenance<'tcx>(&mut self) -> InterpResult<'tcx> {
169 match self {
170 Immediate::Scalar(s) => {
171 s.clear_provenance()?;
172 }
173 Immediate::ScalarPair(a, b) => {
174 a.clear_provenance()?;
175 b.clear_provenance()?;
176 }
177 Immediate::Uninit => {}
178 }
179 interp_ok(())
180 }
181
182 pub fn has_provenance(&self) -> bool {
183 match self {
184 Immediate::Scalar(scalar) => #[allow(non_exhaustive_omitted_patterns)] match scalar {
Scalar::Ptr { .. } => true,
_ => false,
}matches!(scalar, Scalar::Ptr { .. }),
185 Immediate::ScalarPair(s1, s2) => {
186 #[allow(non_exhaustive_omitted_patterns)] match s1 {
Scalar::Ptr { .. } => true,
_ => false,
}matches!(s1, Scalar::Ptr { .. }) || #[allow(non_exhaustive_omitted_patterns)] match s2 {
Scalar::Ptr { .. } => true,
_ => false,
}matches!(s2, Scalar::Ptr { .. })
187 }
188 Immediate::Uninit => false,
189 }
190 }
191}
192
193#[derive(#[automatically_derived]
impl<'tcx, Prov: ::core::clone::Clone + Provenance> ::core::clone::Clone for
ImmTy<'tcx, Prov> {
#[inline]
fn clone(&self) -> ImmTy<'tcx, Prov> {
ImmTy {
imm: ::core::clone::Clone::clone(&self.imm),
layout: ::core::clone::Clone::clone(&self.layout),
}
}
}Clone)]
196pub struct ImmTy<'tcx, Prov: Provenance = CtfeProvenance> {
197 imm: Immediate<Prov>,
198 pub layout: TyAndLayout<'tcx>,
199}
200
201impl<Prov: Provenance> std::fmt::Display for ImmTy<'_, Prov> {
202 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
203 fn print_scalar<'a, 'tcx, Prov: Provenance>(
205 p: &mut FmtPrinter<'a, 'tcx>,
206 s: Scalar<Prov>,
207 ty: Ty<'tcx>,
208 ) -> Result<(), std::fmt::Error> {
209 match s {
210 Scalar::Int(int) => p.pretty_print_const_scalar_int(int, ty, true),
211 Scalar::Ptr(ptr, _sz) => {
212 p.pretty_print_const_pointer(ptr, ty)
216 }
217 }
218 }
219 ty::tls::with(|tcx| {
220 match self.imm {
221 Immediate::Scalar(s) => {
222 let ty = tcx.lift(self.layout.ty);
223 let s = FmtPrinter::print_string(tcx, Namespace::ValueNS, |p| {
224 print_scalar(p, s, ty)
225 })?;
226 f.write_str(&s)
227 }
228 Immediate::ScalarPair(a, b) => {
229 f.write_fmt(format_args!("({0:x}, {1:x}): {2}", a, b, self.layout.ty))write!(f, "({:x}, {:x}): {}", a, b, self.layout.ty)
231 }
232 Immediate::Uninit => {
233 f.write_fmt(format_args!("uninit: {0}", self.layout.ty))write!(f, "uninit: {}", self.layout.ty)
234 }
235 }
236 })
237 }
238}
239
240impl<Prov: Provenance> std::fmt::Debug for ImmTy<'_, Prov> {
241 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
242 f.debug_struct("ImmTy")
244 .field("imm", &self.imm)
245 .field("ty", &format_args!("{0}", self.layout.ty)format_args!("{}", self.layout.ty))
246 .finish()
247 }
248}
249
250impl<'tcx, Prov: Provenance> std::ops::Deref for ImmTy<'tcx, Prov> {
251 type Target = Immediate<Prov>;
252 #[inline(always)]
253 fn deref(&self) -> &Immediate<Prov> {
254 &self.imm
255 }
256}
257
258impl<'tcx, Prov: Provenance> ImmTy<'tcx, Prov> {
259 #[inline]
260 pub fn from_scalar(val: Scalar<Prov>, layout: TyAndLayout<'tcx>) -> Self {
261 if true {
if !layout.backend_repr.is_scalar() {
{
::core::panicking::panic_fmt(format_args!("`ImmTy::from_scalar` on non-scalar layout"));
}
};
};debug_assert!(layout.backend_repr.is_scalar(), "`ImmTy::from_scalar` on non-scalar layout");
262 if true {
{
match (&val.size(), &layout.size) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
}
};
};debug_assert_eq!(val.size(), layout.size);
263 ImmTy { imm: val.into(), layout }
264 }
265
266 #[inline]
267 pub fn from_scalar_pair(a: Scalar<Prov>, b: Scalar<Prov>, layout: TyAndLayout<'tcx>) -> Self {
268 if true {
if !#[allow(non_exhaustive_omitted_patterns)] match layout.backend_repr {
BackendRepr::ScalarPair { .. } => true,
_ => false,
} {
{
::core::panicking::panic_fmt(format_args!("`ImmTy::from_scalar_pair` on non-scalar-pair layout"));
}
};
};debug_assert!(
269 matches!(layout.backend_repr, BackendRepr::ScalarPair { .. }),
270 "`ImmTy::from_scalar_pair` on non-scalar-pair layout"
271 );
272 let imm = Immediate::ScalarPair(a, b);
273 ImmTy { imm, layout }
274 }
275
276 #[inline(always)]
277 pub fn from_immediate(imm: Immediate<Prov>, layout: TyAndLayout<'tcx>) -> Self {
278 if true {
if !match (imm, layout.backend_repr) {
(Immediate::Scalar(..), BackendRepr::Scalar(..)) => true,
(Immediate::ScalarPair { .. }, BackendRepr::ScalarPair { .. })
=> true,
(Immediate::Uninit, _) if layout.is_sized() => true,
_ => false,
} {
{
::core::panicking::panic_fmt(format_args!("immediate {0:?} does not fit to layout {1:?}",
imm, layout));
}
};
};debug_assert!(
280 match (imm, layout.backend_repr) {
281 (Immediate::Scalar(..), BackendRepr::Scalar(..)) => true,
282 (Immediate::ScalarPair { .. }, BackendRepr::ScalarPair { .. }) => true,
283 (Immediate::Uninit, _) if layout.is_sized() => true,
284 _ => false,
285 },
286 "immediate {imm:?} does not fit to layout {layout:?}",
287 );
288 ImmTy { imm, layout }
289 }
290
291 #[inline]
292 pub fn uninit(layout: TyAndLayout<'tcx>) -> Self {
293 if true {
if !layout.is_sized() {
{
::core::panicking::panic_fmt(format_args!("immediates must be sized"));
}
};
};debug_assert!(layout.is_sized(), "immediates must be sized");
294 ImmTy { imm: Immediate::Uninit, layout }
295 }
296
297 #[inline]
298 pub fn from_scalar_int(s: ScalarInt, layout: TyAndLayout<'tcx>) -> Self {
299 Self::from_scalar(Scalar::from(s), layout)
300 }
301
302 #[inline]
303 pub fn from_uint(i: impl Into<u128>, layout: TyAndLayout<'tcx>) -> Self {
304 Self::from_scalar(Scalar::from_uint(i, layout.size), layout)
305 }
306
307 #[inline]
308 pub fn from_int(i: impl Into<i128>, layout: TyAndLayout<'tcx>) -> Self {
309 Self::from_scalar(Scalar::from_int(i, layout.size), layout)
310 }
311
312 #[inline]
313 pub fn from_bool(b: bool, tcx: TyCtxt<'tcx>) -> Self {
314 let layout = tcx
316 .layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(tcx.types.bool))
317 .unwrap();
318 Self::from_scalar(Scalar::from_bool(b), layout)
319 }
320
321 #[inline]
322 pub fn from_ordering(c: std::cmp::Ordering, tcx: TyCtxt<'tcx>) -> Self {
323 let ty = tcx.ty_ordering_enum(DUMMY_SP);
325 let layout =
326 tcx.layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty)).unwrap();
327 Self::from_scalar(Scalar::Int(c.into()), layout)
328 }
329
330 pub fn from_pair(a: Self, b: Self, cx: &(impl HasTypingEnv<'tcx> + HasTyCtxt<'tcx>)) -> Self {
331 let layout = cx
332 .tcx()
333 .layout_of(
334 cx.typing_env().as_query_input(Ty::new_tup(cx.tcx(), &[a.layout.ty, b.layout.ty])),
335 )
336 .unwrap();
337 Self::from_scalar_pair(a.to_scalar(), b.to_scalar(), layout)
338 }
339
340 #[inline]
343 pub fn to_scalar_int(&self) -> InterpResult<'tcx, ScalarInt> {
344 let s = self.to_scalar().to_scalar_int()?;
345 if s.size() != self.layout.size {
346 do yeet ::rustc_middle::mir::interpret::InterpErrorKind::UndefinedBehavior(::rustc_middle::mir::interpret::UndefinedBehaviorInfo::ScalarSizeMismatch(ScalarSizeMismatch {
target_size: self.layout.size.bytes(),
data_size: s.size().bytes(),
}));throw_ub!(ScalarSizeMismatch(ScalarSizeMismatch {
347 target_size: self.layout.size.bytes(),
348 data_size: s.size().bytes(),
349 }));
350 }
351 interp_ok(s)
352 }
353
354 #[inline]
355 pub fn to_const_int(self) -> ConstInt {
356 if !self.layout.ty.is_integral() {
::core::panicking::panic("assertion failed: self.layout.ty.is_integral()")
};assert!(self.layout.ty.is_integral());
357 let int = self.imm.to_scalar_int();
358 {
match (&int.size(), &self.layout.size) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
}
};assert_eq!(int.size(), self.layout.size);
359 ConstInt::new(int, self.layout.ty.is_signed(), self.layout.ty.is_ptr_sized_integral())
360 }
361
362 #[inline]
363 #[cfg_attr(debug_assertions, track_caller)] pub fn to_pair(self, cx: &(impl HasTyCtxt<'tcx> + HasTypingEnv<'tcx>)) -> (Self, Self) {
365 let layout = self.layout;
366 let (val0, val1) = self.to_scalar_pair();
367 (
368 ImmTy::from_scalar(val0, layout.field(cx, 0)),
369 ImmTy::from_scalar(val1, layout.field(cx, 1)),
370 )
371 }
372
373 fn offset_(&self, offset: Size, layout: TyAndLayout<'tcx>, cx: &impl HasDataLayout) -> Self {
377 if truecfg!(debug_assertions) {
379 self.assert_matches_abi(
380 self.layout.backend_repr,
381 "invalid input to Immediate::offset",
382 cx,
383 );
384 }
385 if !(offset + layout.size <= self.layout.size) {
{
::core::panicking::panic_fmt(format_args!("attempting to project to field at offset {0} with size {1} into immediate with layout {2:#?}",
offset.bytes(), layout.size.bytes(), self.layout));
}
};assert!(
389 offset + layout.size <= self.layout.size,
390 "attempting to project to field at offset {} with size {} into immediate with layout {:#?}",
391 offset.bytes(),
392 layout.size.bytes(),
393 self.layout,
394 );
395 let inner_val: Immediate<_> = match (**self, self.layout.backend_repr) {
398 (Immediate::Uninit, _) => Immediate::Uninit,
400 _ if layout.is_uninhabited() => Immediate::Uninit,
404 _ if layout.is_zst() => Immediate::Uninit,
407 _ if #[allow(non_exhaustive_omitted_patterns)] match layout.backend_repr {
BackendRepr::Memory { .. } => true,
_ => false,
}matches!(layout.backend_repr, BackendRepr::Memory { .. })
410 && #[allow(non_exhaustive_omitted_patterns)] match layout.variants {
abi::Variants::Single { .. } => true,
_ => false,
}matches!(layout.variants, abi::Variants::Single { .. })
411 && #[allow(non_exhaustive_omitted_patterns)] match &layout.fields {
abi::FieldsShape::Arbitrary { offsets, .. } if offsets.len() == 0 => true,
_ => false,
}matches!(&layout.fields, abi::FieldsShape::Arbitrary { offsets, .. } if offsets.len() == 0) =>
412 {
413 Immediate::Uninit
414 }
415 _ if layout.size == self.layout.size => {
417 {
match (&offset.bytes(), &0) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
}
};assert_eq!(offset.bytes(), 0);
418 **self
419 }
420 (
422 Immediate::ScalarPair(a_val, b_val),
423 BackendRepr::ScalarPair { a: _, b: _, b_offset },
424 ) => Immediate::from(if offset.bytes() == 0 {
425 a_val
426 } else {
427 {
match (&offset, &b_offset) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
}
};assert_eq!(offset, b_offset);
428 b_val
429 }),
430 _ => ::rustc_middle::util::bug::bug_fmt(format_args!("invalid field access on immediate {0} at offset {1}, original layout {2:#?}",
self, offset.bytes(), self.layout))bug!(
432 "invalid field access on immediate {} at offset {}, original layout {:#?}",
433 self,
434 offset.bytes(),
435 self.layout
436 ),
437 };
438 inner_val.assert_matches_abi(
440 layout.backend_repr,
441 "invalid field type in Immediate::offset",
442 cx,
443 );
444
445 ImmTy::from_immediate(inner_val, layout)
446 }
447}
448
449impl<'tcx, Prov: Provenance> Projectable<'tcx, Prov> for ImmTy<'tcx, Prov> {
450 #[inline(always)]
451 fn layout(&self) -> TyAndLayout<'tcx> {
452 self.layout
453 }
454
455 #[inline(always)]
456 fn meta(&self) -> MemPlaceMeta<Prov> {
457 if true {
if !self.layout.is_sized() {
::core::panicking::panic("assertion failed: self.layout.is_sized()")
};
};debug_assert!(self.layout.is_sized()); MemPlaceMeta::None
459 }
460
461 fn offset_with_meta<M: Machine<'tcx, Provenance = Prov>>(
462 &self,
463 offset: Size,
464 _mode: OffsetMode,
465 meta: MemPlaceMeta<Prov>,
466 layout: TyAndLayout<'tcx>,
467 ecx: &InterpCx<'tcx, M>,
468 ) -> InterpResult<'tcx, Self> {
469 {
match meta {
MemPlaceMeta::None => {}
ref left_val => {
::core::panicking::assert_matches_failed(left_val,
"MemPlaceMeta::None", ::core::option::Option::None);
}
}
};assert_matches!(meta, MemPlaceMeta::None); interp_ok(self.offset_(offset, layout, ecx))
471 }
472
473 #[inline(always)]
474 fn to_op<M: Machine<'tcx, Provenance = Prov>>(
475 &self,
476 _ecx: &InterpCx<'tcx, M>,
477 ) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> {
478 interp_ok(self.clone().into())
479 }
480}
481
482#[derive(#[automatically_derived]
impl<Prov: ::core::marker::Copy + Provenance> ::core::marker::Copy for
Operand<Prov> {
}Copy, #[automatically_derived]
impl<Prov: ::core::clone::Clone + Provenance> ::core::clone::Clone for
Operand<Prov> {
#[inline]
fn clone(&self) -> Operand<Prov> {
match self {
Operand::Immediate(__self_0) =>
Operand::Immediate(::core::clone::Clone::clone(__self_0)),
Operand::Indirect(__self_0) =>
Operand::Indirect(::core::clone::Clone::clone(__self_0)),
}
}
}Clone, #[automatically_derived]
impl<Prov: ::core::fmt::Debug + Provenance> ::core::fmt::Debug for
Operand<Prov> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
Operand::Immediate(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"Immediate", &__self_0),
Operand::Indirect(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"Indirect", &__self_0),
}
}
}Debug)]
486pub(super) enum Operand<Prov: Provenance = CtfeProvenance> {
487 Immediate(Immediate<Prov>),
488 Indirect(MemPlace<Prov>),
489}
490
491#[derive(#[automatically_derived]
impl<'tcx, Prov: ::core::clone::Clone + Provenance> ::core::clone::Clone for
OpTy<'tcx, Prov> {
#[inline]
fn clone(&self) -> OpTy<'tcx, Prov> {
OpTy {
op: ::core::clone::Clone::clone(&self.op),
layout: ::core::clone::Clone::clone(&self.layout),
}
}
}Clone)]
492pub struct OpTy<'tcx, Prov: Provenance = CtfeProvenance> {
493 op: Operand<Prov>, pub layout: TyAndLayout<'tcx>,
495}
496
497impl<Prov: Provenance> std::fmt::Debug for OpTy<'_, Prov> {
498 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
499 f.debug_struct("OpTy")
501 .field("op", &self.op)
502 .field("ty", &format_args!("{0}", self.layout.ty)format_args!("{}", self.layout.ty))
503 .finish()
504 }
505}
506
507impl<'tcx, Prov: Provenance> From<ImmTy<'tcx, Prov>> for OpTy<'tcx, Prov> {
508 #[inline(always)]
509 fn from(val: ImmTy<'tcx, Prov>) -> Self {
510 OpTy { op: Operand::Immediate(val.imm), layout: val.layout }
511 }
512}
513
514impl<'tcx, Prov: Provenance> From<MPlaceTy<'tcx, Prov>> for OpTy<'tcx, Prov> {
515 #[inline(always)]
516 fn from(mplace: MPlaceTy<'tcx, Prov>) -> Self {
517 OpTy { op: Operand::Indirect(*mplace.mplace()), layout: mplace.layout }
518 }
519}
520
521impl<'tcx, Prov: Provenance> OpTy<'tcx, Prov> {
522 #[inline(always)]
523 pub(super) fn op(&self) -> &Operand<Prov> {
524 &self.op
525 }
526
527 pub fn is_immediate_uninit(&self) -> bool {
528 #[allow(non_exhaustive_omitted_patterns)] match self.op {
Operand::Immediate(Immediate::Uninit) => true,
_ => false,
}matches!(self.op, Operand::Immediate(Immediate::Uninit))
529 }
530}
531
532impl<'tcx, Prov: Provenance> Projectable<'tcx, Prov> for OpTy<'tcx, Prov> {
533 #[inline(always)]
534 fn layout(&self) -> TyAndLayout<'tcx> {
535 self.layout
536 }
537
538 #[inline]
539 fn meta(&self) -> MemPlaceMeta<Prov> {
540 match self.as_mplace_or_imm() {
541 Left(mplace) => mplace.meta(),
542 Right(_) => {
543 if true {
if !self.layout.is_sized() {
{
::core::panicking::panic_fmt(format_args!("unsized immediates are not a thing"));
}
};
};debug_assert!(self.layout.is_sized(), "unsized immediates are not a thing");
544 MemPlaceMeta::None
545 }
546 }
547 }
548
549 fn offset_with_meta<M: Machine<'tcx, Provenance = Prov>>(
550 &self,
551 offset: Size,
552 mode: OffsetMode,
553 meta: MemPlaceMeta<Prov>,
554 layout: TyAndLayout<'tcx>,
555 ecx: &InterpCx<'tcx, M>,
556 ) -> InterpResult<'tcx, Self> {
557 match self.as_mplace_or_imm() {
558 Left(mplace) => {
559 interp_ok(mplace.offset_with_meta(offset, mode, meta, layout, ecx)?.into())
560 }
561 Right(imm) => {
562 {
match meta {
MemPlaceMeta::None => {}
ref left_val => {
::core::panicking::assert_matches_failed(left_val,
"MemPlaceMeta::None", ::core::option::Option::None);
}
}
};assert_matches!(meta, MemPlaceMeta::None); interp_ok(imm.offset_(offset, layout, ecx).into())
565 }
566 }
567 }
568
569 #[inline(always)]
570 fn to_op<M: Machine<'tcx, Provenance = Prov>>(
571 &self,
572 _ecx: &InterpCx<'tcx, M>,
573 ) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> {
574 interp_ok(self.clone())
575 }
576}
577
578impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
579 fn read_immediate_from_mplace_raw(
584 &self,
585 mplace: &MPlaceTy<'tcx, M::Provenance>,
586 ) -> InterpResult<'tcx, Option<ImmTy<'tcx, M::Provenance>>> {
587 if mplace.layout.is_unsized() {
588 return interp_ok(None);
590 }
591
592 let Some(alloc) = self.get_place_alloc(mplace)? else {
593 return interp_ok(Some(ImmTy::uninit(mplace.layout)));
595 };
596
597 interp_ok(match mplace.layout.backend_repr {
604 BackendRepr::Scalar(abi::Scalar::Initialized { value: s, .. }) => {
605 let size = s.size(self);
606 {
match (&size, &mplace.layout.size) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val,
::core::option::Option::Some(format_args!("abi::Scalar size does not match layout size")));
}
}
}
};assert_eq!(size, mplace.layout.size, "abi::Scalar size does not match layout size");
607 let scalar = alloc.read_scalar(
608 alloc_range(Size::ZERO, size),
609 #[allow(non_exhaustive_omitted_patterns)] match s {
abi::Primitive::Pointer(_) => true,
_ => false,
}matches!(s, abi::Primitive::Pointer(_)),
610 )?;
611 Some(ImmTy::from_scalar(scalar, mplace.layout))
612 }
613 BackendRepr::ScalarPair {
614 a: abi::Scalar::Initialized { value: a, .. },
615 b: abi::Scalar::Initialized { value: b, .. },
616 b_offset,
617 } => {
618 let (a_size, b_size) = (a.size(self), b.size(self));
622 if !(b_offset.bytes() > 0) {
::core::panicking::panic("assertion failed: b_offset.bytes() > 0")
};assert!(b_offset.bytes() > 0); let a_val = alloc.read_scalar(
624 alloc_range(Size::ZERO, a_size),
625 #[allow(non_exhaustive_omitted_patterns)] match a {
abi::Primitive::Pointer(_) => true,
_ => false,
}matches!(a, abi::Primitive::Pointer(_)),
626 )?;
627 let b_val = alloc.read_scalar(
628 alloc_range(b_offset, b_size),
629 #[allow(non_exhaustive_omitted_patterns)] match b {
abi::Primitive::Pointer(_) => true,
_ => false,
}matches!(b, abi::Primitive::Pointer(_)),
630 )?;
631 Some(ImmTy::from_immediate(Immediate::ScalarPair(a_val, b_val), mplace.layout))
632 }
633 _ => {
634 None
636 }
637 })
638 }
639
640 pub fn read_immediate_raw(
649 &self,
650 src: &impl Projectable<'tcx, M::Provenance>,
651 ) -> InterpResult<'tcx, Either<MPlaceTy<'tcx, M::Provenance>, ImmTy<'tcx, M::Provenance>>> {
652 interp_ok(match src.to_op(self)?.as_mplace_or_imm() {
653 Left(ref mplace) => {
654 if let Some(val) = self.read_immediate_from_mplace_raw(mplace)? {
655 Right(val)
656 } else {
657 Left(mplace.clone())
658 }
659 }
660 Right(val) => Right(val),
661 })
662 }
663
664 #[inline(always)]
668 pub fn read_immediate(
669 &self,
670 op: &impl Projectable<'tcx, M::Provenance>,
671 ) -> InterpResult<'tcx, ImmTy<'tcx, M::Provenance>> {
672 if !#[allow(non_exhaustive_omitted_patterns)] match op.layout().backend_repr {
BackendRepr::Scalar(abi::Scalar::Initialized { .. }) |
BackendRepr::ScalarPair {
a: abi::Scalar::Initialized { .. },
b: abi::Scalar::Initialized { .. },
b_offset: _ } => true,
_ => false,
}matches!(
673 op.layout().backend_repr,
674 BackendRepr::Scalar(abi::Scalar::Initialized { .. })
675 | BackendRepr::ScalarPair {
676 a: abi::Scalar::Initialized { .. },
677 b: abi::Scalar::Initialized { .. },
678 b_offset: _,
679 }
680 ) {
681 ::rustc_middle::util::bug::span_bug_fmt(self.cur_span(),
format_args!("primitive read not possible for type: {0}",
op.layout().ty));span_bug!(self.cur_span(), "primitive read not possible for type: {}", op.layout().ty);
682 }
683 let imm = self.read_immediate_raw(op)?.right().unwrap();
684 if #[allow(non_exhaustive_omitted_patterns)] match *imm {
Immediate::Uninit => true,
_ => false,
}matches!(*imm, Immediate::Uninit) {
685 do yeet ::rustc_middle::mir::interpret::InterpErrorKind::UndefinedBehavior(::rustc_middle::mir::interpret::UndefinedBehaviorInfo::InvalidUninitBytes(None));throw_ub!(InvalidUninitBytes(None));
686 }
687 interp_ok(imm)
688 }
689
690 pub fn read_scalar(
692 &self,
693 op: &impl Projectable<'tcx, M::Provenance>,
694 ) -> InterpResult<'tcx, Scalar<M::Provenance>> {
695 interp_ok(self.read_immediate(op)?.to_scalar())
696 }
697
698 pub fn read_pointer(
703 &self,
704 op: &impl Projectable<'tcx, M::Provenance>,
705 ) -> InterpResult<'tcx, Pointer<Option<M::Provenance>>> {
706 self.read_scalar(op)?.to_pointer(self)
707 }
708 pub fn read_target_usize(
710 &self,
711 op: &impl Projectable<'tcx, M::Provenance>,
712 ) -> InterpResult<'tcx, u64> {
713 self.read_scalar(op)?.to_target_usize(self)
714 }
715 pub fn read_target_isize(
717 &self,
718 op: &impl Projectable<'tcx, M::Provenance>,
719 ) -> InterpResult<'tcx, i64> {
720 self.read_scalar(op)?.to_target_isize(self)
721 }
722
723 pub fn read_str(&self, mplace: &MPlaceTy<'tcx, M::Provenance>) -> InterpResult<'tcx, &str> {
725 let len = mplace.len(self)?;
726 let bytes = self.read_bytes_ptr_strip_provenance(mplace.ptr(), Size::from_bytes(len))?;
727 let s = std::str::from_utf8(bytes).map_err(|err| ::rustc_middle::mir::interpret::InterpErrorKind::UndefinedBehavior(::rustc_middle::mir::interpret::UndefinedBehaviorInfo::InvalidStr(err))err_ub!(InvalidStr(err)))?;
728 interp_ok(s)
729 }
730
731 pub fn local_to_op(
733 &self,
734 local: mir::Local,
735 layout: Option<TyAndLayout<'tcx>>,
736 ) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> {
737 self.local_at_frame_to_op(self.frame(), local, layout)
738 }
739
740 pub fn local_at_frame_to_op(
746 &self,
747 frame: &Frame<'tcx, M::Provenance, M::FrameExtra>,
748 local: mir::Local,
749 layout: Option<TyAndLayout<'tcx>>,
750 ) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> {
751 let layout = self.layout_of_local(frame, local, layout)?;
752 let op = *frame.locals[local].access()?;
753 if #[allow(non_exhaustive_omitted_patterns)] match op {
Operand::Immediate(_) => true,
_ => false,
}matches!(op, Operand::Immediate(_)) {
754 if !!layout.is_unsized() {
::core::panicking::panic("assertion failed: !layout.is_unsized()")
};assert!(!layout.is_unsized());
755 }
756 M::after_local_read(self, frame, local)?;
757 interp_ok(OpTy { op, layout })
758 }
759
760 pub fn place_to_op(
764 &self,
765 place: &PlaceTy<'tcx, M::Provenance>,
766 ) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> {
767 match place.as_mplace_or_local() {
768 Left(mplace) => interp_ok(mplace.into()),
769 Right((local, offset, locals_addr, _)) => {
770 if true {
if !place.layout.is_sized() {
::core::panicking::panic("assertion failed: place.layout.is_sized()")
};
};debug_assert!(place.layout.is_sized()); if true {
{
match (&locals_addr, &self.frame().locals_addr()) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
}
};
};debug_assert_eq!(locals_addr, self.frame().locals_addr());
772 let base = self.local_to_op(local, None)?;
773 interp_ok(match offset {
774 Some(offset) => base.offset(offset, place.layout, self)?,
775 None => {
776 if true {
{
match (&place.layout, &base.layout) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
}
};
};debug_assert_eq!(place.layout, base.layout);
778 base
779 }
780 })
781 }
782 }
783 }
784
785 pub fn eval_place_to_op(
788 &self,
789 mir_place: mir::Place<'tcx>,
790 layout: Option<TyAndLayout<'tcx>>,
791 ) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> {
792 let _trace = <M as
crate::interpret::Machine>::enter_trace_span(||
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("step",
"rustc_const_eval::interpret::operand",
::tracing::Level::INFO,
::tracing_core::__macro_support::Option::Some("compiler/rustc_const_eval/src/interpret/operand.rs"),
::tracing_core::__macro_support::Option::Some(792u32),
::tracing_core::__macro_support::Option::Some("rustc_const_eval::interpret::operand"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("step")
}> =
::tracing::__macro_support::FieldName::new("step");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("mir_place")
}> =
::tracing::__macro_support::FieldName::new("mir_place");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("tracing_separate_thread")
}> =
::tracing::__macro_support::FieldName::new("tracing_separate_thread");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::INFO <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::INFO <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::display(&"eval_place_to_op")
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&mir_place)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&Empty as
&dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
})enter_trace_span!(
793 M,
794 step::eval_place_to_op,
795 ?mir_place,
796 tracing_separate_thread = Empty
797 );
798
799 let layout = if mir_place.projection.is_empty() { layout } else { None };
802
803 let mut op = self.local_to_op(mir_place.local, layout)?;
804 for elem in mir_place.projection.iter() {
806 op = self.project(&op, elem)?
807 }
808
809 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_const_eval/src/interpret/operand.rs:809",
"rustc_const_eval::interpret::operand",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("compiler/rustc_const_eval/src/interpret/operand.rs"),
::tracing_core::__macro_support::Option::Some(809u32),
::tracing_core::__macro_support::Option::Some("rustc_const_eval::interpret::operand"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("eval_place_to_op: got {0:?}",
op) as &dyn ::tracing::field::Value))])
});
} else { ; }
};trace!("eval_place_to_op: got {:?}", op);
810 if truecfg!(debug_assertions) {
812 let normalized_place_ty = self
813 .instantiate_from_current_frame_and_normalize_erasing_regions(
814 mir_place.ty(&self.frame().body.local_decls, *self.tcx).ty,
815 )?;
816 if !mir_assign_valid_types(
817 *self.tcx,
818 self.typing_env(),
819 self.layout_of(normalized_place_ty)?,
820 op.layout,
821 ) {
822 ::rustc_middle::util::bug::span_bug_fmt(self.cur_span(),
format_args!("eval_place of a MIR place with type {0} produced an interpreter operand with type {1}",
normalized_place_ty, op.layout.ty))span_bug!(
823 self.cur_span(),
824 "eval_place of a MIR place with type {} produced an interpreter operand with type {}",
825 normalized_place_ty,
826 op.layout.ty,
827 )
828 }
829 }
830 interp_ok(op)
831 }
832
833 #[inline]
837 pub fn eval_operand(
838 &self,
839 mir_op: &mir::Operand<'tcx>,
840 layout: Option<TyAndLayout<'tcx>>,
841 ) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> {
842 let _trace =
843 <M as
crate::interpret::Machine>::enter_trace_span(||
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("step",
"rustc_const_eval::interpret::operand",
::tracing::Level::INFO,
::tracing_core::__macro_support::Option::Some("compiler/rustc_const_eval/src/interpret/operand.rs"),
::tracing_core::__macro_support::Option::Some(843u32),
::tracing_core::__macro_support::Option::Some("rustc_const_eval::interpret::operand"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("step")
}> =
::tracing::__macro_support::FieldName::new("step");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("mir_op")
}> =
::tracing::__macro_support::FieldName::new("mir_op");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("tracing_separate_thread")
}> =
::tracing::__macro_support::FieldName::new("tracing_separate_thread");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::INFO <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::INFO <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::display(&"eval_operand")
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&mir_op)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&Empty as
&dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
})enter_trace_span!(M, step::eval_operand, ?mir_op, tracing_separate_thread = Empty);
844
845 use rustc_middle::mir::Operand::*;
846 let op = match mir_op {
847 &Copy(place) | &Move(place) => self.eval_place_to_op(place, layout)?,
849
850 &RuntimeChecks(checks) => {
851 let val = M::runtime_checks(self, checks)?;
852 ImmTy::from_bool(val, self.tcx()).into()
853 }
854
855 Constant(constant) => {
856 let c = self.instantiate_from_current_frame_and_normalize_erasing_regions(
857 constant.const_,
858 )?;
859
860 self.eval_mir_constant(&c, constant.span, layout)?
865 }
866 };
867 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_const_eval/src/interpret/operand.rs:867",
"rustc_const_eval::interpret::operand",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("compiler/rustc_const_eval/src/interpret/operand.rs"),
::tracing_core::__macro_support::Option::Some(867u32),
::tracing_core::__macro_support::Option::Some("rustc_const_eval::interpret::operand"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("{0:?}: {1:?}",
mir_op, op) as &dyn ::tracing::field::Value))])
});
} else { ; }
};trace!("{:?}: {:?}", mir_op, op);
868 interp_ok(op)
869 }
870
871 pub(crate) fn const_val_to_op(
872 &self,
873 val_val: mir::ConstValue,
874 ty: Ty<'tcx>,
875 layout: Option<TyAndLayout<'tcx>>,
876 ) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> {
877 let adjust_scalar = |scalar| -> InterpResult<'tcx, _> {
879 interp_ok(match scalar {
880 Scalar::Ptr(ptr, size) => Scalar::Ptr(self.global_root_pointer(ptr)?, size),
881 Scalar::Int(int) => Scalar::Int(int),
882 })
883 };
884 let layout =
885 from_known_layout(self.tcx, self.typing_env(), layout, || self.layout_of(ty).into())?;
886 let imm = match val_val {
887 mir::ConstValue::Indirect { alloc_id, offset } => {
888 let ptr = self.global_root_pointer(Pointer::new(
890 CtfeProvenance::from(alloc_id).as_immutable(),
891 offset,
892 ))?;
893 return interp_ok(self.ptr_to_mplace(ptr.into(), layout).into());
894 }
895 mir::ConstValue::Scalar(x) => adjust_scalar(x)?.into(),
896 mir::ConstValue::ZeroSized => Immediate::Uninit,
897 mir::ConstValue::Slice { alloc_id, meta } => {
898 let ptr = Pointer::new(CtfeProvenance::from(alloc_id).as_immutable(), Size::ZERO);
900 Immediate::new_slice(self.global_root_pointer(ptr)?.into(), meta, self)
901 }
902 };
903 interp_ok(OpTy { op: Operand::Immediate(imm), layout })
904 }
905}
906
907#[cfg(target_pointer_width = "64")]
909mod size_asserts {
910 use rustc_data_structures::static_assert_size;
911
912 use super::*;
913 const _: [(); 64] = [(); ::std::mem::size_of::<ImmTy<'_>>()];static_assert_size!(ImmTy<'_>, 64);
915 const _: [(); 48] = [(); ::std::mem::size_of::<Immediate>()];static_assert_size!(Immediate, 48);
916 const _: [(); 72] = [(); ::std::mem::size_of::<OpTy<'_>>()];static_assert_size!(OpTy<'_>, 72);
917 const _: [(); 56] = [(); ::std::mem::size_of::<Operand>()];static_assert_size!(Operand, 56);
918 }