]> git.lizzy.rs Git - rust.git/blob - src/common.rs
Implement Box rvalue
[rust.git] / src / common.rs
1 use std::fmt;
2
3 use rustc_target::spec::{HasTargetSpec, Target};
4
5 use cranelift_module::Module;
6
7 use crate::prelude::*;
8
9 pub fn mir_var(loc: Local) -> Variable {
10     Variable::with_u32(loc.index() as u32)
11 }
12
13 pub fn pointer_ty(tcx: TyCtxt) -> types::Type {
14     match tcx.data_layout.pointer_size.bits() {
15         16 => types::I16,
16         32 => types::I32,
17         64 => types::I64,
18         bits => bug!("ptr_sized_integer: unknown pointer bit size {}", bits),
19     }
20 }
21
22 fn scalar_to_cton_type(tcx: TyCtxt, scalar: &Scalar) -> Type {
23     match scalar.value.size(tcx).bits() {
24         8 => types::I8,
25         16 => types::I16,
26         32 => types::I32,
27         64 => types::I64,
28         size => bug!("Unsupported scalar size {}", size),
29     }
30 }
31
32 pub fn cton_type_from_ty<'a, 'tcx: 'a>(
33     tcx: TyCtxt<'a, 'tcx, 'tcx>,
34     ty: Ty<'tcx>,
35 ) -> Option<types::Type> {
36     Some(match ty.sty {
37         ty::Bool => types::I8,
38         ty::Uint(size) => match size {
39             UintTy::U8 => types::I8,
40             UintTy::U16 => types::I16,
41             UintTy::U32 => types::I32,
42             UintTy::U64 => types::I64,
43             UintTy::U128 => unimpl!("u128"),
44             UintTy::Usize => pointer_ty(tcx),
45         },
46         ty::Int(size) => match size {
47             IntTy::I8 => types::I8,
48             IntTy::I16 => types::I16,
49             IntTy::I32 => types::I32,
50             IntTy::I64 => types::I64,
51             IntTy::I128 => unimpl!("i128"),
52             IntTy::Isize => pointer_ty(tcx),
53         },
54         ty::Char => types::I32,
55         ty::Float(size) => match size {
56             FloatTy::F32 => types::F32,
57             FloatTy::F64 => types::F64,
58         },
59         ty::FnPtr(_) => pointer_ty(tcx),
60         ty::RawPtr(TypeAndMut { ty, mutbl: _ }) | ty::Ref(_, ty, _) => {
61             if ty.is_sized(tcx.at(DUMMY_SP), ParamEnv::reveal_all()) {
62                 pointer_ty(tcx)
63             } else {
64                 return None;
65             }
66         }
67         ty::Param(_) => bug!("{:?}: {:?}", ty, ty.sty),
68         _ => return None,
69     })
70 }
71
72 fn codegen_field<'a, 'tcx: 'a>(
73     fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
74     base: Value,
75     layout: TyLayout<'tcx>,
76     field: mir::Field,
77 ) -> (Value, TyLayout<'tcx>) {
78     let field_offset = layout.fields.offset(field.index());
79     let field_ty = layout.field(&*fx, field.index());
80     if field_offset.bytes() > 0 {
81         (
82             fx.bcx.ins().iadd_imm(base, field_offset.bytes() as i64),
83             field_ty,
84         )
85     } else {
86         (base, field_ty)
87     }
88 }
89
90 /// A read-only value
91 #[derive(Debug, Copy, Clone)]
92 pub enum CValue<'tcx> {
93     ByRef(Value, TyLayout<'tcx>),
94     ByVal(Value, TyLayout<'tcx>),
95     ByValPair(Value, Value, TyLayout<'tcx>),
96 }
97
98 impl<'tcx> CValue<'tcx> {
99     pub fn layout(&self) -> TyLayout<'tcx> {
100         match *self {
101             CValue::ByRef(_, layout)
102             | CValue::ByVal(_, layout)
103             | CValue::ByValPair(_, _, layout) => layout,
104         }
105     }
106
107     pub fn force_stack<'a>(self, fx: &mut FunctionCx<'a, 'tcx, impl Backend>) -> Value
108     where
109         'tcx: 'a,
110     {
111         match self {
112             CValue::ByRef(value, _layout) => value,
113             CValue::ByVal(value, layout) => {
114                 let stack_slot = fx.bcx.create_stack_slot(StackSlotData {
115                     kind: StackSlotKind::ExplicitSlot,
116                     size: layout.size.bytes() as u32,
117                     offset: None,
118                 });
119                 fx.bcx.ins().stack_store(value, stack_slot, 0);
120                 fx.bcx
121                     .ins()
122                     .stack_addr(fx.module.pointer_type(), stack_slot, 0)
123             }
124             CValue::ByValPair(value, extra, layout) => {
125                 let stack_slot = fx.bcx.create_stack_slot(StackSlotData {
126                     kind: StackSlotKind::ExplicitSlot,
127                     size: layout.size.bytes() as u32,
128                     offset: None,
129                 });
130                 let base = fx.bcx.ins().stack_addr(types::I64, stack_slot, 0);
131                 let a_addr = codegen_field(fx, base, layout, mir::Field::new(0)).0;
132                 let b_addr = codegen_field(fx, base, layout, mir::Field::new(1)).0;
133                 fx.bcx.ins().store(MemFlags::new(), value, a_addr, 0);
134                 fx.bcx.ins().store(MemFlags::new(), extra, b_addr, 0);
135                 base
136             }
137         }
138     }
139
140     pub fn load_value<'a>(self, fx: &mut FunctionCx<'a, 'tcx, impl Backend>) -> Value
141     where
142         'tcx: 'a,
143     {
144         match self {
145             CValue::ByRef(addr, layout) => {
146                 let cton_ty = fx
147                     .cton_type(layout.ty)
148                     .unwrap_or_else(|| {
149                         if layout.ty.is_box() && !fx.layout_of(layout.ty.builtin_deref(true).unwrap().ty).is_unsized() {
150                             // Consider sized box to be a ptr
151                             pointer_ty(fx.tcx)
152                         } else {
153                             panic!("load_value of type {:?}", layout.ty);
154                         }
155                     });
156                 fx.bcx.ins().load(cton_ty, MemFlags::new(), addr, 0)
157             }
158             CValue::ByVal(value, _layout) => value,
159             CValue::ByValPair(_, _, _layout) => bug!("Please use load_value_pair for ByValPair"),
160         }
161     }
162
163     pub fn load_value_pair<'a>(self, fx: &mut FunctionCx<'a, 'tcx, impl Backend>) -> (Value, Value)
164     where
165         'tcx: 'a,
166     {
167         match self {
168             CValue::ByRef(addr, layout) => {
169                 assert_eq!(
170                     layout.size.bytes(),
171                     fx.tcx.data_layout.pointer_size.bytes() * 2
172                 );
173                 let val1_offset = layout.fields.offset(0).bytes() as i32;
174                 let val2_offset = layout.fields.offset(1).bytes() as i32;
175                 let val1 =
176                     fx.bcx
177                         .ins()
178                         .load(fx.module.pointer_type(), MemFlags::new(), addr, val1_offset);
179                 let val2 =
180                     fx.bcx
181                         .ins()
182                         .load(fx.module.pointer_type(), MemFlags::new(), addr, val2_offset);
183                 (val1, val2)
184             }
185             CValue::ByVal(_, _layout) => bug!("Please use load_value for ByVal"),
186             CValue::ByValPair(val1, val2, _layout) => (val1, val2),
187         }
188     }
189
190     pub fn expect_byref(self) -> (Value, TyLayout<'tcx>) {
191         match self {
192             CValue::ByRef(value, layout) => (value, layout),
193             CValue::ByVal(_, _) => bug!("Expected CValue::ByRef, found CValue::ByVal: {:?}", self),
194             CValue::ByValPair(_, _, _) => bug!(
195                 "Expected CValue::ByRef, found CValue::ByValPair: {:?}",
196                 self
197             ),
198         }
199     }
200
201     pub fn value_field<'a>(
202         self,
203         fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
204         field: mir::Field,
205     ) -> CValue<'tcx>
206     where
207         'tcx: 'a,
208     {
209         let (base, layout) = match self {
210             CValue::ByRef(addr, layout) => (addr, layout),
211             _ => bug!("place_field for {:?}", self),
212         };
213
214         let (field_ptr, field_layout) = codegen_field(fx, base, layout, field);
215         CValue::ByRef(field_ptr, field_layout)
216     }
217
218     pub fn unsize_value<'a>(self, fx: &mut FunctionCx<'a, 'tcx, impl Backend>, dest: CPlace<'tcx>) {
219         if self.layout().ty == dest.layout().ty {
220             dest.write_cvalue(fx, self); // FIXME this shouldn't happen (rust-lang/rust#53602)
221             return;
222         }
223         match &self.layout().ty.sty {
224             ty::Ref(_, ty, _) | ty::RawPtr(TypeAndMut { ty, mutbl: _ }) => {
225                 let (ptr, extra) = match dest.layout().ty.builtin_deref(true).unwrap().ty.sty {
226                     ty::Slice(slice_elem_ty) => match ty.sty {
227                         ty::Array(array_elem_ty, size) => {
228                             assert_eq!(slice_elem_ty, array_elem_ty);
229                             let ptr = self.load_value(fx);
230                             let extra = fx
231                                 .bcx
232                                 .ins()
233                                 .iconst(fx.module.pointer_type(), size.unwrap_usize(fx.tcx) as i64);
234                             (ptr, extra)
235                         }
236                         _ => bug!("unsize non array {:?} to slice", ty),
237                     },
238                     ty::Dynamic(_, _) => match ty.sty {
239                         ty::Dynamic(_, _) => self.load_value_pair(fx),
240                         _ => unimpl!("unsize of type ... to {:?}", dest.layout().ty),
241                     },
242                     _ => bug!(
243                         "unsize of type {:?} to {:?}",
244                         self.layout().ty,
245                         dest.layout().ty
246                     ),
247                 };
248                 dest.write_cvalue(fx, CValue::ByValPair(ptr, extra, dest.layout()));
249             }
250             ty => unimpl!("unsize of non ptr {:?}", ty),
251         }
252     }
253
254     pub fn const_val<'a>(
255         fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
256         ty: Ty<'tcx>,
257         const_val: i64,
258     ) -> CValue<'tcx>
259     where
260         'tcx: 'a,
261     {
262         let cton_ty = fx.cton_type(ty).unwrap();
263         let layout = fx.layout_of(ty);
264         CValue::ByVal(fx.bcx.ins().iconst(cton_ty, const_val), layout)
265     }
266
267     pub fn unchecked_cast_to(self, layout: TyLayout<'tcx>) -> Self {
268         match self {
269             CValue::ByRef(addr, _) => CValue::ByRef(addr, layout),
270             CValue::ByVal(val, _) => CValue::ByVal(val, layout),
271             CValue::ByValPair(val, extra, _) => CValue::ByValPair(val, extra, layout),
272         }
273     }
274 }
275
276 /// A place where you can write a value to or read a value from
277 #[derive(Debug, Copy, Clone)]
278 pub enum CPlace<'tcx> {
279     Var(Local, TyLayout<'tcx>),
280     Addr(Value, Option<Value>, TyLayout<'tcx>),
281 }
282
283 impl<'a, 'tcx: 'a> CPlace<'tcx> {
284     pub fn layout(&self) -> TyLayout<'tcx> {
285         match *self {
286             CPlace::Var(_, layout) | CPlace::Addr(_, _, layout) => layout,
287         }
288     }
289
290     pub fn temp(fx: &mut FunctionCx<'a, 'tcx, impl Backend>, ty: Ty<'tcx>) -> CPlace<'tcx> {
291         let layout = fx.layout_of(ty);
292         assert!(!layout.is_unsized());
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::Addr(
299             fx.bcx
300                 .ins()
301                 .stack_addr(fx.module.pointer_type(), stack_slot, 0),
302             None,
303             layout,
304         )
305     }
306
307     pub fn from_stack_slot(
308         fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
309         stack_slot: StackSlot,
310         ty: Ty<'tcx>,
311     ) -> CPlace<'tcx> {
312         let layout = fx.layout_of(ty);
313         assert!(!layout.is_unsized());
314         CPlace::Addr(
315             fx.bcx
316                 .ins()
317                 .stack_addr(fx.module.pointer_type(), stack_slot, 0),
318             None,
319             layout,
320         )
321     }
322
323     pub fn to_cvalue(self, fx: &mut FunctionCx<'a, 'tcx, impl Backend>) -> CValue<'tcx> {
324         match self {
325             CPlace::Var(var, layout) => CValue::ByVal(fx.bcx.use_var(mir_var(var)), layout),
326             CPlace::Addr(addr, extra, layout) => {
327                 assert!(extra.is_none(), "unsized values are not yet supported");
328                 CValue::ByRef(addr, layout)
329             }
330         }
331     }
332
333     pub fn expect_addr(self) -> Value {
334         match self {
335             CPlace::Addr(addr, None, _layout) => addr,
336             CPlace::Addr(_, _, _) => bug!("Expected sized CPlace::Addr, found {:?}", self),
337             CPlace::Var(_, _) => bug!("Expected CPlace::Addr, found CPlace::Var"),
338         }
339     }
340
341     pub fn write_cvalue(self, fx: &mut FunctionCx<'a, 'tcx, impl Backend>, from: CValue<'tcx>) {
342         match (&self.layout().ty.sty, &from.layout().ty.sty) {
343             (ty::Ref(_, t, dest_mut), ty::Ref(_, u, src_mut))
344                 if (if *dest_mut != ::rustc::hir::Mutability::MutImmutable && src_mut != dest_mut {
345                     false
346                 } else if t != u {
347                     false
348                 } else {
349                     true
350                 }) =>
351             {
352                 // &mut T -> &T is allowed
353                 // &'a T -> &'b T is allowed
354             }
355             _ => {
356                 assert_eq!(
357                     self.layout().ty,
358                     from.layout().ty,
359                     "Can't write value of incompatible type to place {:?} {:?}\n\n{:#?}",
360                     self.layout().ty.sty,
361                     from.layout().ty.sty,
362                     fx,
363                 );
364             }
365         }
366
367         match self {
368             CPlace::Var(var, _) => {
369                 let data = from.load_value(fx);
370                 fx.bcx.def_var(mir_var(var), data)
371             }
372             CPlace::Addr(addr, None, layout) => {
373                 let size = layout.size.bytes() as i32;
374
375                 match from {
376                     CValue::ByVal(val, _layout) => {
377                         fx.bcx.ins().store(MemFlags::new(), val, addr, 0);
378                     }
379                     CValue::ByValPair(val1, val2, _layout) => {
380                         let val1_offset = layout.fields.offset(0).bytes() as i32;
381                         let val2_offset = layout.fields.offset(1).bytes() as i32;
382                         fx.bcx.ins().store(MemFlags::new(), val1, addr, val1_offset);
383                         fx.bcx.ins().store(MemFlags::new(), val2, addr, val2_offset);
384                     }
385                     CValue::ByRef(from, _layout) => {
386                         let mut offset = 0;
387                         while size - offset >= 8 {
388                             let byte = fx.bcx.ins().load(
389                                 fx.module.pointer_type(),
390                                 MemFlags::new(),
391                                 from,
392                                 offset,
393                             );
394                             fx.bcx.ins().store(MemFlags::new(), byte, addr, offset);
395                             offset += 8;
396                         }
397                         while size - offset >= 4 {
398                             let byte = fx.bcx.ins().load(types::I32, MemFlags::new(), from, offset);
399                             fx.bcx.ins().store(MemFlags::new(), byte, addr, offset);
400                             offset += 4;
401                         }
402                         while offset < size {
403                             let byte = fx.bcx.ins().load(types::I8, MemFlags::new(), from, offset);
404                             fx.bcx.ins().store(MemFlags::new(), byte, addr, offset);
405                             offset += 1;
406                         }
407                     }
408                 }
409             }
410             CPlace::Addr(_, _, _) => bug!("Can't write value to unsized place {:?}", self),
411         }
412     }
413
414     pub fn place_field(
415         self,
416         fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
417         field: mir::Field,
418     ) -> CPlace<'tcx> {
419         let layout = self.layout();
420         if layout.is_unsized() {
421             unimpl!("unsized place_field");
422         }
423
424         let base = self.expect_addr();
425         let (field_ptr, field_layout) = codegen_field(fx, base, layout, field);
426         CPlace::Addr(field_ptr, None, field_layout)
427     }
428
429     pub fn place_index(
430         self,
431         fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
432         index: Value,
433     ) -> CPlace<'tcx> {
434         let (elem_layout, addr) = match self.layout().ty.sty {
435             ty::Array(elem_ty, _) => (fx.layout_of(elem_ty), self.expect_addr()),
436             ty::Slice(elem_ty) => (
437                 fx.layout_of(elem_ty),
438                 match self {
439                     CPlace::Addr(addr, _, _) => addr,
440                     CPlace::Var(_, _) => bug!("Expected CPlace::Addr found CPlace::Var"),
441                 },
442             ),
443             _ => bug!("place_index({:?})", self.layout().ty),
444         };
445
446         let offset = fx
447             .bcx
448             .ins()
449             .imul_imm(index, elem_layout.size.bytes() as i64);
450
451         CPlace::Addr(fx.bcx.ins().iadd(addr, offset), None, elem_layout)
452     }
453
454     pub fn place_deref(self, fx: &mut FunctionCx<'a, 'tcx, impl Backend>) -> CPlace<'tcx> {
455         let inner_layout = fx.layout_of(self.layout().ty.builtin_deref(true).unwrap().ty);
456         if !inner_layout.is_unsized() {
457             CPlace::Addr(self.to_cvalue(fx).load_value(fx), None, inner_layout)
458         } else {
459             match self.layout().abi {
460                 Abi::ScalarPair(ref a, ref b) => {
461                     let addr = self.expect_addr();
462                     let ptr =
463                         fx.bcx
464                             .ins()
465                             .load(scalar_to_cton_type(fx.tcx, a), MemFlags::new(), addr, 0);
466                     let extra = fx.bcx.ins().load(
467                         scalar_to_cton_type(fx.tcx, b),
468                         MemFlags::new(),
469                         addr,
470                         a.value.size(fx.tcx).bytes() as u32 as i32,
471                     );
472                     CPlace::Addr(ptr, Some(extra), inner_layout)
473                 }
474                 _ => bug!(
475                     "Fat ptr doesn't have abi ScalarPair, but it has {:?}",
476                     self.layout().abi
477                 ),
478             }
479         }
480     }
481
482     pub fn write_place_ref(self, fx: &mut FunctionCx<'a, 'tcx, impl Backend>, dest: CPlace<'tcx>) {
483         if !self.layout().is_unsized() {
484             let ptr = CValue::ByVal(self.expect_addr(), dest.layout());
485             dest.write_cvalue(fx, ptr);
486         } else {
487             match self {
488                 CPlace::Var(_, _) => bug!("expected CPlace::Addr found CPlace::Var"),
489                 CPlace::Addr(value, extra, _) => match dest.layout().abi {
490                     Abi::ScalarPair(ref a, _) => {
491                         fx.bcx
492                             .ins()
493                             .store(MemFlags::new(), value, dest.expect_addr(), 0);
494                         fx.bcx.ins().store(
495                             MemFlags::new(),
496                             extra.expect("unsized type without metadata"),
497                             dest.expect_addr(),
498                             a.value.size(fx.tcx).bytes() as u32 as i32,
499                         );
500                     }
501                     _ => bug!(
502                         "Non ScalarPair abi {:?} in write_place_ref dest",
503                         dest.layout().abi
504                     ),
505                 },
506             }
507         }
508     }
509
510     pub fn unchecked_cast_to(self, layout: TyLayout<'tcx>) -> Self {
511         match self {
512             CPlace::Var(var, _) => CPlace::Var(var, layout),
513             CPlace::Addr(addr, extra, _) => {
514                 assert!(!layout.is_unsized());
515                 CPlace::Addr(addr, extra, layout)
516             }
517         }
518     }
519
520     pub fn downcast_variant(self, fx: &FunctionCx<'a, 'tcx, impl Backend>, variant: usize) -> Self {
521         let layout = self.layout().for_variant(fx, variant);
522         self.unchecked_cast_to(layout)
523     }
524 }
525
526 pub fn cton_intcast<'a, 'tcx: 'a>(
527     fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
528     val: Value,
529     to: Type,
530     signed: bool,
531 ) -> Value {
532     let from = fx.bcx.func.dfg.value_type(val);
533     if from == to {
534         return val;
535     }
536     if to.wider_or_equal(from) {
537         if signed {
538             fx.bcx.ins().sextend(to, val)
539         } else {
540             fx.bcx.ins().uextend(to, val)
541         }
542     } else {
543         fx.bcx.ins().ireduce(to, val)
544     }
545 }
546
547 pub struct FunctionCx<'a, 'tcx: 'a, B: Backend + 'a> {
548     pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
549     pub module: &'a mut Module<B>,
550     pub instance: Instance<'tcx>,
551     pub mir: &'tcx Mir<'tcx>,
552     pub param_substs: &'tcx Substs<'tcx>,
553     pub bcx: FunctionBuilder<'a>,
554     pub ebb_map: HashMap<BasicBlock, Ebb>,
555     pub local_map: HashMap<Local, CPlace<'tcx>>,
556     pub comments: HashMap<Inst, String>,
557     pub constants: &'a mut crate::constant::ConstantCx,
558     pub caches: &'a mut Caches,
559
560     /// add_global_comment inserts a comment here
561     pub top_nop: Option<Inst>,
562 }
563
564 impl<'a, 'tcx: 'a, B: Backend + 'a> fmt::Debug for FunctionCx<'a, 'tcx, B> {
565     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
566         writeln!(f, "{:?}", self.param_substs)?;
567         writeln!(f, "{:?}", self.local_map)?;
568
569         let mut clif = String::new();
570         let mut writer = crate::pretty_clif::CommentWriter(self.comments.clone());
571         ::cranelift::codegen::write::decorate_function(
572             &mut writer,
573             &mut clif,
574             &self.bcx.func,
575             None,
576         ).unwrap();
577         writeln!(f, "\n{}", clif)
578     }
579 }
580
581 impl<'a, 'tcx: 'a, B: Backend> LayoutOf for &'a FunctionCx<'a, 'tcx, B> {
582     type Ty = Ty<'tcx>;
583     type TyLayout = TyLayout<'tcx>;
584
585     fn layout_of(self, ty: Ty<'tcx>) -> TyLayout<'tcx> {
586         let ty = self.monomorphize(&ty);
587         self.tcx.layout_of(ParamEnv::reveal_all().and(&ty)).unwrap()
588     }
589 }
590
591 impl<'a, 'tcx, B: Backend + 'a> layout::HasTyCtxt<'tcx> for &'a FunctionCx<'a, 'tcx, B> {
592     fn tcx<'b>(&'b self) -> TyCtxt<'b, 'tcx, 'tcx> {
593         self.tcx
594     }
595 }
596
597 impl<'a, 'tcx, B: Backend + 'a> layout::HasDataLayout for &'a FunctionCx<'a, 'tcx, B> {
598     fn data_layout(&self) -> &layout::TargetDataLayout {
599         &self.tcx.data_layout
600     }
601 }
602
603 impl<'a, 'tcx, B: Backend + 'a> HasTargetSpec for &'a FunctionCx<'a, 'tcx, B> {
604     fn target_spec(&self) -> &Target {
605         &self.tcx.sess.target.target
606     }
607 }
608
609 impl<'a, 'tcx: 'a, B: Backend + 'a> FunctionCx<'a, 'tcx, B> {
610     pub fn monomorphize<T>(&self, value: &T) -> T
611     where
612         T: TypeFoldable<'tcx>,
613     {
614         self.tcx.subst_and_normalize_erasing_regions(
615             self.param_substs,
616             ty::ParamEnv::reveal_all(),
617             value,
618         )
619     }
620
621     pub fn cton_type(&self, ty: Ty<'tcx>) -> Option<Type> {
622         cton_type_from_ty(self.tcx, self.monomorphize(&ty))
623     }
624
625     pub fn get_ebb(&self, bb: BasicBlock) -> Ebb {
626         *self.ebb_map.get(&bb).unwrap()
627     }
628
629     pub fn get_local_place(&mut self, local: Local) -> CPlace<'tcx> {
630         *self.local_map.get(&local).unwrap()
631     }
632 }