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