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::ty::layout::{HasTyCtxt, HasTypingEnv, TyAndLayout};
11use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter};
12use rustc_middle::ty::{ConstInt, ScalarInt, Ty, TyCtxt};
13use rustc_middle::{bug, mir, span_bug, ty};
14use rustc_span::DUMMY_SP;
15use tracing::field::Empty;
16use tracing::trace;
17
18use super::{
19 CtfeProvenance, Frame, InterpCx, InterpResult, MPlaceTy, Machine, MemPlace, MemPlaceMeta,
20 OffsetMode, PlaceTy, Pointer, Projectable, Provenance, Scalar, alloc_range, err_ub,
21 from_known_layout, interp_ok, mir_assign_valid_types, throw_ub,
22};
23use crate::enter_trace_span;
24
25#[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)]
33pub enum Immediate<Prov: Provenance = CtfeProvenance> {
34 Scalar(Scalar<Prov>),
36 ScalarPair(Scalar<Prov>, Scalar<Prov>),
39 Uninit,
41}
42
43impl<Prov: Provenance> From<Scalar<Prov>> for Immediate<Prov> {
44 #[inline(always)]
45 fn from(val: Scalar<Prov>) -> Self {
46 Immediate::Scalar(val)
47 }
48}
49
50impl<Prov: Provenance> Immediate<Prov> {
51 pub fn new_pointer_with_meta(
52 ptr: Pointer<Option<Prov>>,
53 meta: MemPlaceMeta<Prov>,
54 cx: &impl HasDataLayout,
55 ) -> Self {
56 let ptr = Scalar::from_maybe_pointer(ptr, cx);
57 match meta {
58 MemPlaceMeta::None => Immediate::from(ptr),
59 MemPlaceMeta::Meta(meta) => Immediate::ScalarPair(ptr, meta),
60 }
61 }
62
63 pub fn new_slice(ptr: Pointer<Option<Prov>>, len: u64, cx: &impl HasDataLayout) -> Self {
64 Immediate::ScalarPair(
65 Scalar::from_maybe_pointer(ptr, cx),
66 Scalar::from_target_usize(len, cx),
67 )
68 }
69
70 pub fn new_dyn_trait(
71 val: Pointer<Option<Prov>>,
72 vtable: Pointer<Option<Prov>>,
73 cx: &impl HasDataLayout,
74 ) -> Self {
75 Immediate::ScalarPair(
76 Scalar::from_maybe_pointer(val, cx),
77 Scalar::from_maybe_pointer(vtable, cx),
78 )
79 }
80
81 #[inline]
82 #[cfg_attr(debug_assertions, track_caller)] pub fn to_scalar(self) -> Scalar<Prov> {
84 match self {
85 Immediate::Scalar(val) => val,
86 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"),
87 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"),
88 }
89 }
90
91 #[inline]
92 #[cfg_attr(debug_assertions, track_caller)] pub fn to_scalar_int(self) -> ScalarInt {
94 self.to_scalar().try_to_scalar_int().unwrap()
95 }
96
97 #[inline]
98 #[cfg_attr(debug_assertions, track_caller)] pub fn to_scalar_pair(self) -> (Scalar<Prov>, Scalar<Prov>) {
100 match self {
101 Immediate::ScalarPair(val1, val2) => (val1, val2),
102 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"),
103 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"),
104 }
105 }
106
107 #[inline]
109 #[cfg_attr(debug_assertions, track_caller)] pub fn to_scalar_and_meta(self) -> (Scalar<Prov>, MemPlaceMeta<Prov>) {
111 match self {
112 Immediate::ScalarPair(val1, val2) => (val1, MemPlaceMeta::Meta(val2)),
113 Immediate::Scalar(val) => (val, MemPlaceMeta::None),
114 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"),
115 }
116 }
117
118 pub fn assert_matches_abi(self, abi: BackendRepr, msg: &str, cx: &impl HasDataLayout) {
120 match (self, abi) {
121 (Immediate::Scalar(scalar), BackendRepr::Scalar(s)) => {
122 {
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");
123 if !#[allow(non_exhaustive_omitted_patterns)] match s.primitive() {
abi::Primitive::Pointer(..) => true,
_ => false,
}matches!(s.primitive(), abi::Primitive::Pointer(..)) {
124 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!(
126 matches!(scalar, Scalar::Int(..)),
127 "{msg}: scalar value should be an integer, but has provenance"
128 );
129 }
130 }
131 (
132 Immediate::ScalarPair(a_val, b_val),
133 BackendRepr::ScalarPair { a, b, b_offset: _ },
134 ) => {
135 {
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!(
136 a_val.size(),
137 a.size(cx),
138 "{msg}: first component of scalar pair has wrong size"
139 );
140 if !#[allow(non_exhaustive_omitted_patterns)] match a.primitive() {
abi::Primitive::Pointer(..) => true,
_ => false,
}matches!(a.primitive(), abi::Primitive::Pointer(..)) {
141 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!(
142 matches!(a_val, Scalar::Int(..)),
143 "{msg}: first component of scalar pair should be an integer, but has provenance"
144 );
145 }
146 {
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!(
147 b_val.size(),
148 b.size(cx),
149 "{msg}: second component of scalar pair has wrong size"
150 );
151 if !#[allow(non_exhaustive_omitted_patterns)] match b.primitive() {
abi::Primitive::Pointer(..) => true,
_ => false,
}matches!(b.primitive(), abi::Primitive::Pointer(..)) {
152 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!(
153 matches!(b_val, Scalar::Int(..)),
154 "{msg}: second component of scalar pair should be an integer, but has provenance"
155 );
156 }
157 }
158 (Immediate::Uninit, _) => {
159 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");
160 }
161 _ => {
162 ::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:?})",)
163 }
164 }
165 }
166
167 pub fn clear_provenance<'tcx>(&mut self) -> InterpResult<'tcx> {
168 match self {
169 Immediate::Scalar(s) => {
170 s.clear_provenance()?;
171 }
172 Immediate::ScalarPair(a, b) => {
173 a.clear_provenance()?;
174 b.clear_provenance()?;
175 }
176 Immediate::Uninit => {}
177 }
178 interp_ok(())
179 }
180
181 pub fn has_provenance(&self) -> bool {
182 match self {
183 Immediate::Scalar(scalar) => #[allow(non_exhaustive_omitted_patterns)] match scalar {
Scalar::Ptr { .. } => true,
_ => false,
}matches!(scalar, Scalar::Ptr { .. }),
184 Immediate::ScalarPair(s1, s2) => {
185 #[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 { .. })
186 }
187 Immediate::Uninit => false,
188 }
189 }
190}
191
192#[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)]
195pub struct ImmTy<'tcx, Prov: Provenance = CtfeProvenance> {
196 imm: Immediate<Prov>,
197 pub layout: TyAndLayout<'tcx>,
198}
199
200impl<Prov: Provenance> std::fmt::Display for ImmTy<'_, Prov> {
201 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
202 fn print_scalar<'a, 'tcx, Prov: Provenance>(
204 p: &mut FmtPrinter<'a, 'tcx>,
205 s: Scalar<Prov>,
206 ty: Ty<'tcx>,
207 ) -> Result<(), std::fmt::Error> {
208 match s {
209 Scalar::Int(int) => p.pretty_print_const_scalar_int(int, ty, true),
210 Scalar::Ptr(ptr, _sz) => {
211 p.pretty_print_const_pointer(ptr, ty)
215 }
216 }
217 }
218 ty::tls::with(|tcx| {
219 match self.imm {
220 Immediate::Scalar(s) => {
221 let ty = tcx.lift(self.layout.ty);
222 let s = FmtPrinter::print_string(tcx, Namespace::ValueNS, |p| {
223 print_scalar(p, s, ty)
224 })?;
225 f.write_str(&s)
226 }
227 Immediate::ScalarPair(a, b) => {
228 f.write_fmt(format_args!("({0:x}, {1:x}): {2}", a, b, self.layout.ty))write!(f, "({:x}, {:x}): {}", a, b, self.layout.ty)
230 }
231 Immediate::Uninit => {
232 f.write_fmt(format_args!("uninit: {0}", self.layout.ty))write!(f, "uninit: {}", self.layout.ty)
233 }
234 }
235 })
236 }
237}
238
239impl<Prov: Provenance> std::fmt::Debug for ImmTy<'_, Prov> {
240 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
241 f.debug_struct("ImmTy")
243 .field("imm", &self.imm)
244 .field("ty", &format_args!("{0}", self.layout.ty)format_args!("{}", self.layout.ty))
245 .finish()
246 }
247}
248
249impl<'tcx, Prov: Provenance> std::ops::Deref for ImmTy<'tcx, Prov> {
250 type Target = Immediate<Prov>;
251 #[inline(always)]
252 fn deref(&self) -> &Immediate<Prov> {
253 &self.imm
254 }
255}
256
257impl<'tcx, Prov: Provenance> ImmTy<'tcx, Prov> {
258 #[inline]
259 pub fn from_scalar(val: Scalar<Prov>, layout: TyAndLayout<'tcx>) -> Self {
260 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");
261 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);
262 ImmTy { imm: val.into(), layout }
263 }
264
265 #[inline]
266 pub fn from_scalar_pair(a: Scalar<Prov>, b: Scalar<Prov>, layout: TyAndLayout<'tcx>) -> Self {
267 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!(
268 matches!(layout.backend_repr, BackendRepr::ScalarPair { .. }),
269 "`ImmTy::from_scalar_pair` on non-scalar-pair layout"
270 );
271 let imm = Immediate::ScalarPair(a, b);
272 ImmTy { imm, layout }
273 }
274
275 #[inline(always)]
276 pub fn from_immediate(imm: Immediate<Prov>, layout: TyAndLayout<'tcx>) -> Self {
277 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!(
279 match (imm, layout.backend_repr) {
280 (Immediate::Scalar(..), BackendRepr::Scalar(..)) => true,
281 (Immediate::ScalarPair { .. }, BackendRepr::ScalarPair { .. }) => true,
282 (Immediate::Uninit, _) if layout.is_sized() => true,
283 _ => false,
284 },
285 "immediate {imm:?} does not fit to layout {layout:?}",
286 );
287 ImmTy { imm, layout }
288 }
289
290 #[inline]
291 pub fn uninit(layout: TyAndLayout<'tcx>) -> Self {
292 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");
293 ImmTy { imm: Immediate::Uninit, layout }
294 }
295
296 #[inline]
297 pub fn from_scalar_int(s: ScalarInt, layout: TyAndLayout<'tcx>) -> Self {
298 Self::from_scalar(Scalar::from(s), layout)
299 }
300
301 #[inline]
302 pub fn from_uint(i: impl Into<u128>, layout: TyAndLayout<'tcx>) -> Self {
303 Self::from_scalar(Scalar::from_uint(i, layout.size), layout)
304 }
305
306 #[inline]
307 pub fn from_int(i: impl Into<i128>, layout: TyAndLayout<'tcx>) -> Self {
308 Self::from_scalar(Scalar::from_int(i, layout.size), layout)
309 }
310
311 #[inline]
312 pub fn from_bool(b: bool, tcx: TyCtxt<'tcx>) -> Self {
313 let layout = tcx
315 .layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(tcx.types.bool))
316 .unwrap();
317 Self::from_scalar(Scalar::from_bool(b), layout)
318 }
319
320 #[inline]
321 pub fn from_ordering(c: std::cmp::Ordering, tcx: TyCtxt<'tcx>) -> Self {
322 let ty = tcx.ty_ordering_enum(DUMMY_SP);
324 let layout =
325 tcx.layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty)).unwrap();
326 Self::from_scalar(Scalar::Int(c.into()), layout)
327 }
328
329 pub fn from_pair(a: Self, b: Self, cx: &(impl HasTypingEnv<'tcx> + HasTyCtxt<'tcx>)) -> Self {
330 let layout = cx
331 .tcx()
332 .layout_of(
333 cx.typing_env().as_query_input(Ty::new_tup(cx.tcx(), &[a.layout.ty, b.layout.ty])),
334 )
335 .unwrap();
336 Self::from_scalar_pair(a.to_scalar(), b.to_scalar(), layout)
337 }
338
339 #[inline]
342 pub fn to_scalar_int(&self) -> InterpResult<'tcx, ScalarInt> {
343 let s = self.to_scalar().to_scalar_int()?;
344 {
match (&s.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::Some(format_args!("scalar immediate size does not match layout")));
}
}
}
};assert_eq!(s.size(), self.layout.size, "scalar immediate size does not match layout");
345 interp_ok(s)
346 }
347
348 #[inline]
349 pub fn to_const_int(self) -> ConstInt {
350 if !self.layout.ty.is_integral() {
::core::panicking::panic("assertion failed: self.layout.ty.is_integral()")
};assert!(self.layout.ty.is_integral());
351 let int = self.imm.to_scalar_int();
352 {
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);
353 ConstInt::new(int, self.layout.ty.is_signed(), self.layout.ty.is_ptr_sized_integral())
354 }
355
356 #[inline]
357 #[cfg_attr(debug_assertions, track_caller)] pub fn to_pair(self, cx: &(impl HasTyCtxt<'tcx> + HasTypingEnv<'tcx>)) -> (Self, Self) {
359 let layout = self.layout;
360 let (val0, val1) = self.to_scalar_pair();
361 (
362 ImmTy::from_scalar(val0, layout.field(cx, 0)),
363 ImmTy::from_scalar(val1, layout.field(cx, 1)),
364 )
365 }
366
367 fn offset_(&self, offset: Size, layout: TyAndLayout<'tcx>, cx: &impl HasDataLayout) -> Self {
371 if truecfg!(debug_assertions) {
373 self.assert_matches_abi(
374 self.layout.backend_repr,
375 "invalid input to Immediate::offset",
376 cx,
377 );
378 }
379 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!(
383 offset + layout.size <= self.layout.size,
384 "attempting to project to field at offset {} with size {} into immediate with layout {:#?}",
385 offset.bytes(),
386 layout.size.bytes(),
387 self.layout,
388 );
389 let inner_val: Immediate<_> = match (**self, self.layout.backend_repr) {
392 (Immediate::Uninit, _) => Immediate::Uninit,
394 _ if layout.is_uninhabited() => Immediate::Uninit,
398 _ if layout.is_zst() => Immediate::Uninit,
401 _ if #[allow(non_exhaustive_omitted_patterns)] match layout.backend_repr {
BackendRepr::Memory { .. } => true,
_ => false,
}matches!(layout.backend_repr, BackendRepr::Memory { .. })
404 && #[allow(non_exhaustive_omitted_patterns)] match layout.variants {
abi::Variants::Single { .. } => true,
_ => false,
}matches!(layout.variants, abi::Variants::Single { .. })
405 && #[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) =>
406 {
407 Immediate::Uninit
408 }
409 _ if layout.size == self.layout.size => {
411 {
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);
412 **self
413 }
414 (
416 Immediate::ScalarPair(a_val, b_val),
417 BackendRepr::ScalarPair { a: _, b: _, b_offset },
418 ) => Immediate::from(if offset.bytes() == 0 {
419 a_val
420 } else {
421 {
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);
422 b_val
423 }),
424 _ => ::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!(
426 "invalid field access on immediate {} at offset {}, original layout {:#?}",
427 self,
428 offset.bytes(),
429 self.layout
430 ),
431 };
432 inner_val.assert_matches_abi(
434 layout.backend_repr,
435 "invalid field type in Immediate::offset",
436 cx,
437 );
438
439 ImmTy::from_immediate(inner_val, layout)
440 }
441}
442
443impl<'tcx, Prov: Provenance> Projectable<'tcx, Prov> for ImmTy<'tcx, Prov> {
444 #[inline(always)]
445 fn layout(&self) -> TyAndLayout<'tcx> {
446 self.layout
447 }
448
449 #[inline(always)]
450 fn meta(&self) -> MemPlaceMeta<Prov> {
451 if true {
if !self.layout.is_sized() {
::core::panicking::panic("assertion failed: self.layout.is_sized()")
};
};debug_assert!(self.layout.is_sized()); MemPlaceMeta::None
453 }
454
455 fn offset_with_meta<M: Machine<'tcx, Provenance = Prov>>(
456 &self,
457 offset: Size,
458 _mode: OffsetMode,
459 meta: MemPlaceMeta<Prov>,
460 layout: TyAndLayout<'tcx>,
461 ecx: &InterpCx<'tcx, M>,
462 ) -> InterpResult<'tcx, Self> {
463 {
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))
465 }
466
467 #[inline(always)]
468 fn to_op<M: Machine<'tcx, Provenance = Prov>>(
469 &self,
470 _ecx: &InterpCx<'tcx, M>,
471 ) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> {
472 interp_ok(self.clone().into())
473 }
474}
475
476#[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)]
480pub(super) enum Operand<Prov: Provenance = CtfeProvenance> {
481 Immediate(Immediate<Prov>),
482 Indirect(MemPlace<Prov>),
483}
484
485#[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)]
486pub struct OpTy<'tcx, Prov: Provenance = CtfeProvenance> {
487 op: Operand<Prov>, pub layout: TyAndLayout<'tcx>,
489}
490
491impl<Prov: Provenance> std::fmt::Debug for OpTy<'_, Prov> {
492 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
493 f.debug_struct("OpTy")
495 .field("op", &self.op)
496 .field("ty", &format_args!("{0}", self.layout.ty)format_args!("{}", self.layout.ty))
497 .finish()
498 }
499}
500
501impl<'tcx, Prov: Provenance> From<ImmTy<'tcx, Prov>> for OpTy<'tcx, Prov> {
502 #[inline(always)]
503 fn from(val: ImmTy<'tcx, Prov>) -> Self {
504 OpTy { op: Operand::Immediate(val.imm), layout: val.layout }
505 }
506}
507
508impl<'tcx, Prov: Provenance> From<MPlaceTy<'tcx, Prov>> for OpTy<'tcx, Prov> {
509 #[inline(always)]
510 fn from(mplace: MPlaceTy<'tcx, Prov>) -> Self {
511 OpTy { op: Operand::Indirect(*mplace.mplace()), layout: mplace.layout }
512 }
513}
514
515impl<'tcx, Prov: Provenance> OpTy<'tcx, Prov> {
516 #[inline(always)]
517 pub(super) fn op(&self) -> &Operand<Prov> {
518 &self.op
519 }
520
521 pub fn is_immediate_uninit(&self) -> bool {
522 #[allow(non_exhaustive_omitted_patterns)] match self.op {
Operand::Immediate(Immediate::Uninit) => true,
_ => false,
}matches!(self.op, Operand::Immediate(Immediate::Uninit))
523 }
524}
525
526impl<'tcx, Prov: Provenance> Projectable<'tcx, Prov> for OpTy<'tcx, Prov> {
527 #[inline(always)]
528 fn layout(&self) -> TyAndLayout<'tcx> {
529 self.layout
530 }
531
532 #[inline]
533 fn meta(&self) -> MemPlaceMeta<Prov> {
534 match self.as_mplace_or_imm() {
535 Left(mplace) => mplace.meta(),
536 Right(_) => {
537 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");
538 MemPlaceMeta::None
539 }
540 }
541 }
542
543 fn offset_with_meta<M: Machine<'tcx, Provenance = Prov>>(
544 &self,
545 offset: Size,
546 mode: OffsetMode,
547 meta: MemPlaceMeta<Prov>,
548 layout: TyAndLayout<'tcx>,
549 ecx: &InterpCx<'tcx, M>,
550 ) -> InterpResult<'tcx, Self> {
551 match self.as_mplace_or_imm() {
552 Left(mplace) => {
553 interp_ok(mplace.offset_with_meta(offset, mode, meta, layout, ecx)?.into())
554 }
555 Right(imm) => {
556 {
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())
559 }
560 }
561 }
562
563 #[inline(always)]
564 fn to_op<M: Machine<'tcx, Provenance = Prov>>(
565 &self,
566 _ecx: &InterpCx<'tcx, M>,
567 ) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> {
568 interp_ok(self.clone())
569 }
570}
571
572impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
573 fn read_immediate_from_mplace_raw(
578 &self,
579 mplace: &MPlaceTy<'tcx, M::Provenance>,
580 ) -> InterpResult<'tcx, Option<ImmTy<'tcx, M::Provenance>>> {
581 if mplace.layout.is_unsized() {
582 return interp_ok(None);
584 }
585
586 let Some(alloc) = self.get_place_alloc(mplace)? else {
587 return interp_ok(Some(ImmTy::uninit(mplace.layout)));
589 };
590
591 interp_ok(match mplace.layout.backend_repr {
598 BackendRepr::Scalar(abi::Scalar::Initialized { value: s, .. }) => {
599 let size = s.size(self);
600 {
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");
601 let scalar = alloc.read_scalar(
602 alloc_range(Size::ZERO, size),
603 #[allow(non_exhaustive_omitted_patterns)] match s {
abi::Primitive::Pointer(_) => true,
_ => false,
}matches!(s, abi::Primitive::Pointer(_)),
604 )?;
605 Some(ImmTy::from_scalar(scalar, mplace.layout))
606 }
607 BackendRepr::ScalarPair {
608 a: abi::Scalar::Initialized { value: a, .. },
609 b: abi::Scalar::Initialized { value: b, .. },
610 b_offset,
611 } => {
612 let (a_size, b_size) = (a.size(self), b.size(self));
616 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(
618 alloc_range(Size::ZERO, a_size),
619 #[allow(non_exhaustive_omitted_patterns)] match a {
abi::Primitive::Pointer(_) => true,
_ => false,
}matches!(a, abi::Primitive::Pointer(_)),
620 )?;
621 let b_val = alloc.read_scalar(
622 alloc_range(b_offset, b_size),
623 #[allow(non_exhaustive_omitted_patterns)] match b {
abi::Primitive::Pointer(_) => true,
_ => false,
}matches!(b, abi::Primitive::Pointer(_)),
624 )?;
625 Some(ImmTy::from_immediate(Immediate::ScalarPair(a_val, b_val), mplace.layout))
626 }
627 _ => {
628 None
630 }
631 })
632 }
633
634 pub fn read_immediate_raw(
643 &self,
644 src: &impl Projectable<'tcx, M::Provenance>,
645 ) -> InterpResult<'tcx, Either<MPlaceTy<'tcx, M::Provenance>, ImmTy<'tcx, M::Provenance>>> {
646 interp_ok(match src.to_op(self)?.as_mplace_or_imm() {
647 Left(ref mplace) => {
648 if let Some(val) = self.read_immediate_from_mplace_raw(mplace)? {
649 Right(val)
650 } else {
651 Left(mplace.clone())
652 }
653 }
654 Right(val) => Right(val),
655 })
656 }
657
658 #[inline(always)]
662 pub fn read_immediate(
663 &self,
664 op: &impl Projectable<'tcx, M::Provenance>,
665 ) -> InterpResult<'tcx, ImmTy<'tcx, M::Provenance>> {
666 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!(
667 op.layout().backend_repr,
668 BackendRepr::Scalar(abi::Scalar::Initialized { .. })
669 | BackendRepr::ScalarPair {
670 a: abi::Scalar::Initialized { .. },
671 b: abi::Scalar::Initialized { .. },
672 b_offset: _,
673 }
674 ) {
675 ::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);
676 }
677 let imm = self.read_immediate_raw(op)?.right().unwrap();
678 if #[allow(non_exhaustive_omitted_patterns)] match *imm {
Immediate::Uninit => true,
_ => false,
}matches!(*imm, Immediate::Uninit) {
679 do yeet ::rustc_middle::mir::interpret::InterpErrorKind::UndefinedBehavior(::rustc_middle::mir::interpret::UndefinedBehaviorInfo::InvalidUninitBytes(None));throw_ub!(InvalidUninitBytes(None));
680 }
681 interp_ok(imm)
682 }
683
684 pub fn read_scalar(
686 &self,
687 op: &impl Projectable<'tcx, M::Provenance>,
688 ) -> InterpResult<'tcx, Scalar<M::Provenance>> {
689 interp_ok(self.read_immediate(op)?.to_scalar())
690 }
691
692 pub fn read_pointer(
697 &self,
698 op: &impl Projectable<'tcx, M::Provenance>,
699 ) -> InterpResult<'tcx, Pointer<Option<M::Provenance>>> {
700 interp_ok(self.read_scalar(op)?.to_pointer(self))
701 }
702 pub fn read_target_usize(
704 &self,
705 op: &impl Projectable<'tcx, M::Provenance>,
706 ) -> InterpResult<'tcx, u64> {
707 self.read_scalar(op)?.to_target_usize(self)
708 }
709 pub fn read_target_isize(
711 &self,
712 op: &impl Projectable<'tcx, M::Provenance>,
713 ) -> InterpResult<'tcx, i64> {
714 self.read_scalar(op)?.to_target_isize(self)
715 }
716
717 pub fn read_str(&self, mplace: &MPlaceTy<'tcx, M::Provenance>) -> InterpResult<'tcx, &str> {
719 let len = mplace.len(self)?;
720 let bytes = self.read_bytes_ptr_strip_provenance(mplace.ptr(), Size::from_bytes(len))?;
721 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)))?;
722 interp_ok(s)
723 }
724
725 pub fn local_to_op(
728 &self,
729 local: mir::Local,
730 layout: Option<TyAndLayout<'tcx>>,
731 ) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> {
732 let frame = self.frame();
733 let layout = self.layout_of_local(frame, local, layout)?;
734 let op = *frame.locals[local].access()?;
735 if #[allow(non_exhaustive_omitted_patterns)] match op {
Operand::Immediate(_) => true,
_ => false,
}matches!(op, Operand::Immediate(_)) {
736 if !!layout.is_unsized() {
::core::panicking::panic("assertion failed: !layout.is_unsized()")
};assert!(!layout.is_unsized());
737 if !self.validation_in_progress() {
738 M::after_local_read(self, local)?;
739 }
740 }
741 interp_ok(OpTy { op, layout })
742 }
743
744 pub fn ghost_local_in_frame_to_op(
751 &self,
752 frame: &Frame<'tcx, M::Provenance, M::FrameExtra>,
753 local: mir::Local,
754 ) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> {
755 let layout = self.layout_of_local(frame, local, None)?;
756 let op = *frame.locals[local].access()?;
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("/rustc-dev/a69a63265cfd9e006d43137f98301b8d274ad4c9/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 /rustc-dev/a69a63265cfd9e006d43137f98301b8d274ad4c9/compiler/rustc_const_eval/src/interpret/operand.rs:809",
"rustc_const_eval::interpret::operand",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/a69a63265cfd9e006d43137f98301b8d274ad4c9/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("/rustc-dev/a69a63265cfd9e006d43137f98301b8d274ad4c9/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 /rustc-dev/a69a63265cfd9e006d43137f98301b8d274ad4c9/compiler/rustc_const_eval/src/interpret/operand.rs:867",
"rustc_const_eval::interpret::operand",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/a69a63265cfd9e006d43137f98301b8d274ad4c9/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 }