]> git.lizzy.rs Git - rust.git/blob - src/value_and_place.rs
Merge pull request #946 from bjorn3/dependabot/cargo/cranelift-codegen-cd900d7
[rust.git] / src / value_and_place.rs
1 use crate::prelude::*;
2
3 use cranelift_codegen::ir::immediates::Offset32;
4
5 fn codegen_field<'tcx>(
6     fx: &mut FunctionCx<'_, 'tcx, impl Backend>,
7     base: Pointer,
8     extra: Option<Value>,
9     layout: TyAndLayout<'tcx>,
10     field: mir::Field,
11 ) -> (Pointer, TyAndLayout<'tcx>) {
12     let field_offset = layout.fields.offset(field.index());
13     let field_layout = layout.field(&*fx, field.index());
14
15     let simple = |fx: &mut FunctionCx<_>| {
16         (
17             base.offset_i64(fx, i64::try_from(field_offset.bytes()).unwrap()),
18             field_layout,
19         )
20     };
21
22     if let Some(extra) = extra {
23         if !field_layout.is_unsized() {
24             return simple(fx);
25         }
26         match field_layout.ty.kind {
27             ty::Slice(..) | ty::Str | ty::Foreign(..) => return simple(fx),
28             ty::Adt(def, _) if def.repr.packed() => {
29                 assert_eq!(layout.align.abi.bytes(), 1);
30                 return simple(fx);
31             }
32             _ => {
33                 // We have to align the offset for DST's
34                 let unaligned_offset = field_offset.bytes();
35                 let (_, unsized_align) = crate::unsize::size_and_align_of_dst(fx, field_layout, extra);
36
37                 let one = fx.bcx.ins().iconst(pointer_ty(fx.tcx), 1);
38                 let align_sub_1 = fx.bcx.ins().isub(unsized_align, one);
39                 let and_lhs = fx.bcx.ins().iadd_imm(align_sub_1, unaligned_offset as i64);
40                 let zero = fx.bcx.ins().iconst(pointer_ty(fx.tcx), 0);
41                 let and_rhs = fx.bcx.ins().isub(zero, unsized_align);
42                 let offset = fx.bcx.ins().band(and_lhs, and_rhs);
43
44                 (
45                     base.offset_value(fx, offset),
46                     field_layout,
47                 )
48             }
49         }
50     } else {
51         simple(fx)
52     }
53 }
54
55 fn scalar_pair_calculate_b_offset(tcx: TyCtxt<'_>, a_scalar: &Scalar, b_scalar: &Scalar) -> Offset32 {
56     let b_offset = a_scalar
57         .value
58         .size(&tcx)
59         .align_to(b_scalar.value.align(&tcx).abi);
60     Offset32::new(b_offset.bytes().try_into().unwrap())
61 }
62
63 /// A read-only value
64 #[derive(Debug, Copy, Clone)]
65 pub(crate) struct CValue<'tcx>(CValueInner, TyAndLayout<'tcx>);
66
67 #[derive(Debug, Copy, Clone)]
68 enum CValueInner {
69     ByRef(Pointer, Option<Value>),
70     ByVal(Value),
71     ByValPair(Value, Value),
72 }
73
74 impl<'tcx> CValue<'tcx> {
75     pub(crate) fn by_ref(ptr: Pointer, layout: TyAndLayout<'tcx>) -> CValue<'tcx> {
76         CValue(CValueInner::ByRef(ptr, None), layout)
77     }
78
79     pub(crate) fn by_ref_unsized(ptr: Pointer, meta: Value, layout: TyAndLayout<'tcx>) -> CValue<'tcx> {
80         CValue(CValueInner::ByRef(ptr, Some(meta)), layout)
81     }
82
83     pub(crate) fn by_val(value: Value, layout: TyAndLayout<'tcx>) -> CValue<'tcx> {
84         CValue(CValueInner::ByVal(value), layout)
85     }
86
87     pub(crate) fn by_val_pair(value: Value, extra: Value, layout: TyAndLayout<'tcx>) -> CValue<'tcx> {
88         CValue(CValueInner::ByValPair(value, extra), layout)
89     }
90
91     pub(crate) fn layout(&self) -> TyAndLayout<'tcx> {
92         self.1
93     }
94
95     // FIXME remove
96     pub(crate) fn force_stack<'a>(self, fx: &mut FunctionCx<'_, 'tcx, impl Backend>) -> (Pointer, Option<Value>) {
97         let layout = self.1;
98         match self.0 {
99             CValueInner::ByRef(ptr, meta) => (ptr, meta),
100             CValueInner::ByVal(_) | CValueInner::ByValPair(_, _) => {
101                 let cplace = CPlace::new_stack_slot(fx, layout);
102                 cplace.write_cvalue(fx, self);
103                 (cplace.to_ptr(fx), None)
104             }
105         }
106     }
107
108     pub(crate) fn try_to_ptr(self) -> Option<(Pointer, Option<Value>)> {
109         match self.0 {
110             CValueInner::ByRef(ptr, meta) => Some((ptr, meta)),
111             CValueInner::ByVal(_) | CValueInner::ByValPair(_, _) => None,
112         }
113     }
114
115     /// Load a value with layout.abi of scalar
116     pub(crate) fn load_scalar<'a>(self, fx: &mut FunctionCx<'_, 'tcx, impl Backend>) -> Value {
117         let layout = self.1;
118         match self.0 {
119             CValueInner::ByRef(ptr, None) => {
120                 let clif_ty = match layout.abi {
121                     layout::Abi::Scalar(ref scalar) => scalar_to_clif_type(fx.tcx, scalar.clone()),
122                     layout::Abi::Vector { ref element, count } => {
123                         scalar_to_clif_type(fx.tcx, element.clone())
124                             .by(u16::try_from(count).unwrap()).unwrap()
125                     }
126                     _ => unreachable!(),
127                 };
128                 ptr.load(fx, clif_ty, MemFlags::new())
129             }
130             CValueInner::ByVal(value) => value,
131             CValueInner::ByRef(_, Some(_)) => bug!("load_scalar for unsized value not allowed"),
132             CValueInner::ByValPair(_, _) => bug!("Please use load_scalar_pair for ByValPair"),
133         }
134     }
135
136     /// Load a value pair with layout.abi of scalar pair
137     pub(crate) fn load_scalar_pair<'a>(
138         self,
139         fx: &mut FunctionCx<'_, 'tcx, impl Backend>,
140     ) -> (Value, Value) {
141         let layout = self.1;
142         match self.0 {
143             CValueInner::ByRef(ptr, None) => {
144                 let (a_scalar, b_scalar) = match &layout.abi {
145                     layout::Abi::ScalarPair(a, b) => (a, b),
146                     _ => unreachable!("load_scalar_pair({:?})", self),
147                 };
148                 let b_offset = scalar_pair_calculate_b_offset(fx.tcx, a_scalar, b_scalar);
149                 let clif_ty1 = scalar_to_clif_type(fx.tcx, a_scalar.clone());
150                 let clif_ty2 = scalar_to_clif_type(fx.tcx, b_scalar.clone());
151                 let val1 = ptr.load(fx, clif_ty1, MemFlags::new());
152                 let val2 = ptr.offset(fx, b_offset).load(fx, clif_ty2, MemFlags::new());
153                 (val1, val2)
154             }
155             CValueInner::ByRef(_, Some(_)) => bug!("load_scalar_pair for unsized value not allowed"),
156             CValueInner::ByVal(_) => bug!("Please use load_scalar for ByVal"),
157             CValueInner::ByValPair(val1, val2) => (val1, val2),
158         }
159     }
160
161     pub(crate) fn value_field<'a>(
162         self,
163         fx: &mut FunctionCx<'_, 'tcx, impl Backend>,
164         field: mir::Field,
165     ) -> CValue<'tcx> {
166         let layout = self.1;
167         match self.0 {
168             CValueInner::ByVal(val) => {
169                 match layout.abi {
170                     layout::Abi::Vector { element: _, count } => {
171                         let count = u8::try_from(count).expect("SIMD type with more than 255 lanes???");
172                         let field = u8::try_from(field.index()).unwrap();
173                         assert!(field < count);
174                         let lane = fx.bcx.ins().extractlane(val, field);
175                         let field_layout = layout.field(&*fx, usize::from(field));
176                         CValue::by_val(lane, field_layout)
177                     }
178                     _ => unreachable!("value_field for ByVal with abi {:?}", layout.abi),
179                 }
180             }
181             CValueInner::ByRef(ptr, None) => {
182                 let (field_ptr, field_layout) = codegen_field(fx, ptr, None, layout, field);
183                 CValue::by_ref(field_ptr, field_layout)
184             }
185             CValueInner::ByRef(_, Some(_)) => todo!(),
186             _ => bug!("place_field for {:?}", self),
187         }
188     }
189
190     pub(crate) fn unsize_value<'a>(self, fx: &mut FunctionCx<'_, 'tcx, impl Backend>, dest: CPlace<'tcx>) {
191         crate::unsize::coerce_unsized_into(fx, self, dest);
192     }
193
194     /// If `ty` is signed, `const_val` must already be sign extended.
195     pub(crate) fn const_val(
196         fx: &mut FunctionCx<'_, 'tcx, impl Backend>,
197         layout: TyAndLayout<'tcx>,
198         const_val: u128,
199     ) -> CValue<'tcx> {
200         use cranelift_codegen::ir::immediates::{Ieee32, Ieee64};
201
202         let clif_ty = fx.clif_type(layout.ty).unwrap();
203
204         match layout.ty.kind {
205             ty::TyKind::Bool => {
206                 assert!(const_val == 0 || const_val == 1, "Invalid bool 0x{:032X}", const_val);
207             }
208             _ => {}
209         }
210
211         let val = match layout.ty.kind {
212             ty::TyKind::Uint(UintTy::U128) | ty::TyKind::Int(IntTy::I128) => {
213                 let lsb = fx.bcx.ins().iconst(types::I64, const_val as u64 as i64);
214                 let msb = fx
215                     .bcx
216                     .ins()
217                     .iconst(types::I64, (const_val >> 64) as u64 as i64);
218                 fx.bcx.ins().iconcat(lsb, msb)
219             }
220             ty::TyKind::Bool | ty::TyKind::Char | ty::TyKind::Uint(_) | ty::TyKind::Ref(..)
221             | ty::TyKind::RawPtr(..) => {
222                 fx
223                     .bcx
224                     .ins()
225                     .iconst(clif_ty, u64::try_from(const_val).expect("uint") as i64)
226             }
227             ty::TyKind::Int(_) => {
228                 let const_val = rustc::mir::interpret::sign_extend(const_val, layout.size);
229                 fx.bcx.ins().iconst(clif_ty, i64::try_from(const_val as i128).unwrap())
230             }
231             ty::TyKind::Float(FloatTy::F32) => {
232                 fx.bcx.ins().f32const(Ieee32::with_bits(u32::try_from(const_val).unwrap()))
233             }
234             ty::TyKind::Float(FloatTy::F64) => {
235                 fx.bcx.ins().f64const(Ieee64::with_bits(u64::try_from(const_val).unwrap()))
236             }
237             _ => panic!(
238                 "CValue::const_val for non bool/char/float/integer/pointer type {:?} is not allowed",
239                 layout.ty
240             ),
241         };
242
243         CValue::by_val(val, layout)
244     }
245
246     pub(crate) fn unchecked_cast_to(self, layout: TyAndLayout<'tcx>) -> Self {
247         CValue(self.0, layout)
248     }
249 }
250
251 /// A place where you can write a value to or read a value from
252 #[derive(Debug, Copy, Clone)]
253 pub(crate) struct CPlace<'tcx> {
254     inner: CPlaceInner,
255     layout: TyAndLayout<'tcx>,
256 }
257
258 #[derive(Debug, Copy, Clone)]
259 pub(crate) enum CPlaceInner {
260     Var(Local),
261     Addr(Pointer, Option<Value>),
262     NoPlace,
263 }
264
265 impl<'tcx> CPlace<'tcx> {
266     pub(crate) fn layout(&self) -> TyAndLayout<'tcx> {
267         self.layout
268     }
269
270     pub(crate) fn inner(&self) -> &CPlaceInner {
271         &self.inner
272     }
273
274     pub(crate) fn no_place(layout: TyAndLayout<'tcx>) -> CPlace<'tcx> {
275         CPlace {
276             inner: CPlaceInner::NoPlace,
277             layout,
278         }
279     }
280
281     pub(crate) fn new_stack_slot(
282         fx: &mut FunctionCx<'_, 'tcx, impl Backend>,
283         layout: TyAndLayout<'tcx>,
284     ) -> CPlace<'tcx> {
285         assert!(!layout.is_unsized());
286         if layout.size.bytes() == 0 {
287             return CPlace {
288                 inner: CPlaceInner::NoPlace,
289                 layout,
290             };
291         }
292
293         let stack_slot = fx.bcx.create_stack_slot(StackSlotData {
294             kind: StackSlotKind::ExplicitSlot,
295             size: layout.size.bytes() as u32,
296             offset: None,
297         });
298         CPlace {
299             inner: CPlaceInner::Addr(Pointer::stack_slot(stack_slot), None),
300             layout,
301         }
302     }
303
304     pub(crate) fn new_var(
305         fx: &mut FunctionCx<'_, 'tcx, impl Backend>,
306         local: Local,
307         layout: TyAndLayout<'tcx>,
308     ) -> CPlace<'tcx> {
309         fx.bcx
310             .declare_var(mir_var(local), fx.clif_type(layout.ty).unwrap());
311         CPlace {
312             inner: CPlaceInner::Var(local),
313             layout,
314         }
315     }
316
317     pub(crate) fn for_ptr(ptr: Pointer, layout: TyAndLayout<'tcx>) -> CPlace<'tcx> {
318         CPlace {
319             inner: CPlaceInner::Addr(ptr, None),
320             layout,
321         }
322     }
323
324     pub(crate) fn for_ptr_with_extra(ptr: Pointer, extra: Value, layout: TyAndLayout<'tcx>) -> CPlace<'tcx> {
325         CPlace {
326             inner: CPlaceInner::Addr(ptr, Some(extra)),
327             layout,
328         }
329     }
330
331     pub(crate) fn to_cvalue(self, fx: &mut FunctionCx<'_, 'tcx, impl Backend>) -> CValue<'tcx> {
332         let layout = self.layout();
333         match self.inner {
334             CPlaceInner::Var(var) => {
335                 let val = fx.bcx.use_var(mir_var(var));
336                 fx.bcx.set_val_label(val, cranelift_codegen::ir::ValueLabel::from_u32(var.as_u32()));
337                 CValue::by_val(val, layout)
338             }
339             CPlaceInner::Addr(ptr, extra) => {
340                 if let Some(extra) = extra {
341                     CValue::by_ref_unsized(ptr, extra, layout)
342                 } else {
343                     CValue::by_ref(ptr, layout)
344                 }
345             }
346             CPlaceInner::NoPlace => CValue::by_ref(
347                 Pointer::const_addr(fx, i64::try_from(self.layout.align.pref.bytes()).unwrap()),
348                 layout,
349             ),
350         }
351     }
352
353     pub(crate) fn to_ptr(self, fx: &mut FunctionCx<'_, 'tcx, impl Backend>) -> Pointer {
354         match self.to_ptr_maybe_unsized(fx) {
355             (ptr, None) => ptr,
356             (_, Some(_)) => bug!("Expected sized cplace, found {:?}", self),
357         }
358     }
359
360     pub(crate) fn to_ptr_maybe_unsized(
361         self,
362         fx: &mut FunctionCx<'_, 'tcx, impl Backend>,
363     ) -> (Pointer, Option<Value>) {
364         match self.inner {
365             CPlaceInner::Addr(ptr, extra) => (ptr, extra),
366             CPlaceInner::NoPlace => {
367                 (
368                     Pointer::const_addr(fx, i64::try_from(self.layout.align.pref.bytes()).unwrap()),
369                     None,
370                 )
371             }
372             CPlaceInner::Var(_) => bug!("Expected CPlace::Addr, found CPlace::Var"),
373         }
374     }
375
376     pub(crate) fn write_cvalue(self, fx: &mut FunctionCx<'_, 'tcx, impl Backend>, from: CValue<'tcx>) {
377         #[cfg(debug_assertions)]
378         {
379             use cranelift_codegen::cursor::{Cursor, CursorPosition};
380             let cur_block = match fx.bcx.cursor().position() {
381                 CursorPosition::After(block) => block,
382                 _ => unreachable!(),
383             };
384             fx.add_comment(
385                 fx.bcx.func.layout.last_inst(cur_block).unwrap(),
386                 format!("write_cvalue: {:?}: {:?} <- {:?}: {:?}", self.inner(), self.layout().ty, from.0, from.layout().ty),
387             );
388         }
389
390         let from_ty = from.layout().ty;
391         let to_ty = self.layout().ty;
392
393         fn assert_assignable<'tcx>(
394             fx: &FunctionCx<'_, 'tcx, impl Backend>,
395             from_ty: Ty<'tcx>,
396             to_ty: Ty<'tcx>,
397         ) {
398             match (&from_ty.kind, &to_ty.kind) {
399                 (ty::Ref(_, t, Mutability::Not), ty::Ref(_, u, Mutability::Not))
400                 | (ty::Ref(_, t, Mutability::Mut), ty::Ref(_, u, Mutability::Not))
401                 | (ty::Ref(_, t, Mutability::Mut), ty::Ref(_, u, Mutability::Mut)) => {
402                     assert_assignable(fx, t, u);
403                     // &mut T -> &T is allowed
404                     // &'a T -> &'b T is allowed
405                 }
406                 (ty::Ref(_, _, Mutability::Not), ty::Ref(_, _, Mutability::Mut)) => panic!(
407                     "Cant assign value of type {} to place of type {}",
408                     from_ty, to_ty
409                 ),
410                 (ty::FnPtr(_), ty::FnPtr(_)) => {
411                     let from_sig = fx.tcx.normalize_erasing_late_bound_regions(
412                         ParamEnv::reveal_all(),
413                         &from_ty.fn_sig(fx.tcx),
414                     );
415                     let to_sig = fx.tcx.normalize_erasing_late_bound_regions(
416                         ParamEnv::reveal_all(),
417                         &to_ty.fn_sig(fx.tcx),
418                     );
419                     assert_eq!(
420                         from_sig, to_sig,
421                         "Can't write fn ptr with incompatible sig {:?} to place with sig {:?}\n\n{:#?}",
422                         from_sig, to_sig, fx,
423                     );
424                     // fn(&T) -> for<'l> fn(&'l T) is allowed
425                 }
426                 (ty::Dynamic(from_traits, _), ty::Dynamic(to_traits, _)) => {
427                     let from_traits = fx
428                         .tcx
429                         .normalize_erasing_late_bound_regions(ParamEnv::reveal_all(), from_traits);
430                     let to_traits = fx
431                         .tcx
432                         .normalize_erasing_late_bound_regions(ParamEnv::reveal_all(), to_traits);
433                     assert_eq!(
434                         from_traits, to_traits,
435                         "Can't write trait object of incompatible traits {:?} to place with traits {:?}\n\n{:#?}",
436                         from_traits, to_traits, fx,
437                     );
438                     // dyn for<'r> Trait<'r> -> dyn Trait<'_> is allowed
439                 }
440                 _ => {
441                     assert_eq!(
442                         from_ty,
443                         to_ty,
444                         "Can't write value with incompatible type {:?} to place with type {:?}\n\n{:#?}",
445                         from_ty,
446                         to_ty,
447                         fx,
448                     );
449                 }
450             }
451         }
452
453         assert_assignable(fx, from_ty, to_ty);
454
455         let dst_layout = self.layout();
456         let to_ptr = match self.inner {
457             CPlaceInner::Var(var) => {
458                 let data = from.load_scalar(fx);
459                 fx.bcx.set_val_label(data, cranelift_codegen::ir::ValueLabel::from_u32(var.as_u32()));
460                 fx.bcx.def_var(mir_var(var), data);
461                 return;
462             }
463             CPlaceInner::Addr(ptr, None) => ptr,
464             CPlaceInner::NoPlace => {
465                 if dst_layout.abi != Abi::Uninhabited {
466                     assert_eq!(dst_layout.size.bytes(), 0, "{:?}", dst_layout);
467                 }
468                 return;
469             }
470             CPlaceInner::Addr(_, Some(_)) => bug!("Can't write value to unsized place {:?}", self),
471         };
472
473         match self.layout().abi {
474             // FIXME make Abi::Vector work too
475             Abi::Scalar(_) => {
476                 let val = from.load_scalar(fx);
477                 to_ptr.store(fx, val, MemFlags::new());
478                 return;
479             }
480             Abi::ScalarPair(ref a_scalar, ref b_scalar) => {
481                 let (value, extra) = from.load_scalar_pair(fx);
482                 let b_offset = scalar_pair_calculate_b_offset(fx.tcx, a_scalar, b_scalar);
483                 to_ptr.store(fx, value, MemFlags::new());
484                 to_ptr.offset(fx, b_offset).store(fx, extra, MemFlags::new());
485                 return;
486             }
487             _ => {}
488         }
489
490         match from.0 {
491             CValueInner::ByVal(val) => {
492                 to_ptr.store(fx, val, MemFlags::new());
493             }
494             CValueInner::ByValPair(_, _) => {
495                 bug!(
496                     "Non ScalarPair abi {:?} for ByValPair CValue",
497                     dst_layout.abi
498                 );
499             }
500             CValueInner::ByRef(from_ptr, None) => {
501                 let from_addr = from_ptr.get_addr(fx);
502                 let to_addr = to_ptr.get_addr(fx);
503                 let src_layout = from.1;
504                 let size = dst_layout.size.bytes();
505                 let src_align = src_layout.align.abi.bytes() as u8;
506                 let dst_align = dst_layout.align.abi.bytes() as u8;
507                 fx.bcx.emit_small_memory_copy(
508                     fx.module.target_config(),
509                     to_addr,
510                     from_addr,
511                     size,
512                     dst_align,
513                     src_align,
514                     true,
515                 );
516             }
517             CValueInner::ByRef(_, Some(_)) => todo!(),
518         }
519     }
520
521     pub(crate) fn place_field(
522         self,
523         fx: &mut FunctionCx<'_, 'tcx, impl Backend>,
524         field: mir::Field,
525     ) -> CPlace<'tcx> {
526         let layout = self.layout();
527         let (base, extra) = self.to_ptr_maybe_unsized(fx);
528
529         let (field_ptr, field_layout) = codegen_field(fx, base, extra, layout, field);
530         if field_layout.is_unsized() {
531             CPlace::for_ptr_with_extra(field_ptr, extra.unwrap(), field_layout)
532         } else {
533             CPlace::for_ptr(field_ptr, field_layout)
534         }
535     }
536
537     pub(crate) fn place_index(
538         self,
539         fx: &mut FunctionCx<'_, 'tcx, impl Backend>,
540         index: Value,
541     ) -> CPlace<'tcx> {
542         let (elem_layout, ptr) = match self.layout().ty.kind {
543             ty::Array(elem_ty, _) => (fx.layout_of(elem_ty), self.to_ptr(fx)),
544             ty::Slice(elem_ty) => (fx.layout_of(elem_ty), self.to_ptr_maybe_unsized(fx).0),
545             _ => bug!("place_index({:?})", self.layout().ty),
546         };
547
548         let offset = fx
549             .bcx
550             .ins()
551             .imul_imm(index, elem_layout.size.bytes() as i64);
552
553         CPlace::for_ptr(ptr.offset_value(fx, offset), elem_layout)
554     }
555
556     pub(crate) fn place_deref(self, fx: &mut FunctionCx<'_, 'tcx, impl Backend>) -> CPlace<'tcx> {
557         let inner_layout = fx.layout_of(self.layout().ty.builtin_deref(true).unwrap().ty);
558         if has_ptr_meta(fx.tcx, inner_layout.ty) {
559             let (addr, extra) = self.to_cvalue(fx).load_scalar_pair(fx);
560             CPlace::for_ptr_with_extra(Pointer::new(addr), extra, inner_layout)
561         } else {
562             CPlace::for_ptr(Pointer::new(self.to_cvalue(fx).load_scalar(fx)), inner_layout)
563         }
564     }
565
566     pub(crate) fn write_place_ref(self, fx: &mut FunctionCx<'_, 'tcx, impl Backend>, dest: CPlace<'tcx>) {
567         if has_ptr_meta(fx.tcx, self.layout().ty) {
568             let (ptr, extra) = self.to_ptr_maybe_unsized(fx);
569             let ptr = CValue::by_val_pair(
570                 ptr.get_addr(fx),
571                 extra.expect("unsized type without metadata"),
572                 dest.layout(),
573             );
574             dest.write_cvalue(fx, ptr);
575         } else {
576             let ptr = CValue::by_val(self.to_ptr(fx).get_addr(fx), dest.layout());
577             dest.write_cvalue(fx, ptr);
578         }
579     }
580
581     pub(crate) fn unchecked_cast_to(self, layout: TyAndLayout<'tcx>) -> Self {
582         assert!(!self.layout().is_unsized());
583         match self.inner {
584             CPlaceInner::NoPlace => {
585                 assert!(layout.size.bytes() == 0);
586             }
587             _ => {}
588         }
589         CPlace {
590             inner: self.inner,
591             layout,
592         }
593     }
594
595     pub(crate) fn downcast_variant(
596         self,
597         fx: &FunctionCx<'_, 'tcx, impl Backend>,
598         variant: VariantIdx,
599     ) -> Self {
600         let layout = self.layout().for_variant(fx, variant);
601         self.unchecked_cast_to(layout)
602     }
603 }