]> git.lizzy.rs Git - rust.git/blob - src/common.rs
Rustfmt
[rust.git] / src / common.rs
1 use std::fmt;
2
3 use crate::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.cton_type(layout.ty).unwrap_or_else(|| {
147                     if layout.ty.is_box() && !fx
148                         .layout_of(layout.ty.builtin_deref(true).unwrap().ty)
149                         .is_unsized()
150                     {
151                         // Consider sized box to be a ptr
152                         pointer_ty(fx.tcx)
153                     } else {
154                         panic!("load_value of type {:?}", layout.ty);
155                     }
156                 });
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 dest.layout().ty.builtin_deref(true).unwrap().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(data, _) => match ty.sty {
240                         ty::Dynamic(_, _) => self.load_value_pair(fx),
241                         _ => {
242                             let ptr = self.load_value(fx);
243                             let vtable = crate::vtable::get_vtable(fx, ty, data.principal());
244                             (ptr, vtable)
245                         }
246                     },
247                     _ => bug!(
248                         "unsize of type {:?} to {:?}",
249                         self.layout().ty,
250                         dest.layout().ty
251                     ),
252                 };
253                 dest.write_cvalue(fx, CValue::ByValPair(ptr, extra, dest.layout()));
254             }
255             _ => {
256                 assert!(!self.layout().ty.is_enum(), "Tried to unsize enum");
257                 let field_count = self.layout().fields.count();
258                 let mut found_unsize_field = false;
259                 for idx in 0..field_count {
260                     let field_dest = dest.place_field(fx, mir::Field::new(idx));
261                     let field_src = self.value_field(fx, mir::Field::new(idx));
262                     if field_src.layout().ty.is_phantom_data() {
263                         // Ignore PhantomData so for example `Unique<()>` can coerce to `Unique<Debug>`
264                         //
265                         // ```rust
266                         // struct Unique<T: ?Sized> {
267                         //     pointer: NonZero<*const T>,
268                         //     _marker: PhantomData<T>,
269                         // }
270                         // ```
271                         continue;
272                     }
273                     if field_src.layout().ty != field_dest.layout().ty {
274                         assert!(!found_unsize_field);
275                         found_unsize_field = true;
276                         field_src.unsize_value(fx, field_dest);
277                     } else {
278                         field_dest.write_cvalue(fx, field_src);
279                     }
280                 }
281             }
282         }
283     }
284
285     pub fn const_val<'a>(
286         fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
287         ty: Ty<'tcx>,
288         const_val: i64,
289     ) -> CValue<'tcx>
290     where
291         'tcx: 'a,
292     {
293         let cton_ty = fx.cton_type(ty).unwrap();
294         let layout = fx.layout_of(ty);
295         CValue::ByVal(fx.bcx.ins().iconst(cton_ty, const_val), layout)
296     }
297
298     pub fn unchecked_cast_to(self, layout: TyLayout<'tcx>) -> Self {
299         match self {
300             CValue::ByRef(addr, _) => CValue::ByRef(addr, layout),
301             CValue::ByVal(val, _) => CValue::ByVal(val, layout),
302             CValue::ByValPair(val, extra, _) => CValue::ByValPair(val, extra, layout),
303         }
304     }
305 }
306
307 /// A place where you can write a value to or read a value from
308 #[derive(Debug, Copy, Clone)]
309 pub enum CPlace<'tcx> {
310     Var(Local, TyLayout<'tcx>),
311     Addr(Value, Option<Value>, TyLayout<'tcx>),
312 }
313
314 impl<'a, 'tcx: 'a> CPlace<'tcx> {
315     pub fn layout(&self) -> TyLayout<'tcx> {
316         match *self {
317             CPlace::Var(_, layout) | CPlace::Addr(_, _, layout) => layout,
318         }
319     }
320
321     pub fn temp(fx: &mut FunctionCx<'a, 'tcx, impl Backend>, ty: Ty<'tcx>) -> CPlace<'tcx> {
322         let layout = fx.layout_of(ty);
323         assert!(!layout.is_unsized());
324         let stack_slot = fx.bcx.create_stack_slot(StackSlotData {
325             kind: StackSlotKind::ExplicitSlot,
326             size: layout.size.bytes() as u32,
327             offset: None,
328         });
329         CPlace::Addr(
330             fx.bcx
331                 .ins()
332                 .stack_addr(fx.module.pointer_type(), stack_slot, 0),
333             None,
334             layout,
335         )
336     }
337
338     pub fn from_stack_slot(
339         fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
340         stack_slot: StackSlot,
341         ty: Ty<'tcx>,
342     ) -> CPlace<'tcx> {
343         let layout = fx.layout_of(ty);
344         assert!(!layout.is_unsized());
345         CPlace::Addr(
346             fx.bcx
347                 .ins()
348                 .stack_addr(fx.module.pointer_type(), stack_slot, 0),
349             None,
350             layout,
351         )
352     }
353
354     pub fn to_cvalue(self, fx: &mut FunctionCx<'a, 'tcx, impl Backend>) -> CValue<'tcx> {
355         match self {
356             CPlace::Var(var, layout) => CValue::ByVal(fx.bcx.use_var(mir_var(var)), layout),
357             CPlace::Addr(addr, extra, layout) => {
358                 assert!(extra.is_none(), "unsized values are not yet supported");
359                 CValue::ByRef(addr, layout)
360             }
361         }
362     }
363
364     pub fn expect_addr(self) -> Value {
365         match self {
366             CPlace::Addr(addr, None, _layout) => addr,
367             CPlace::Addr(_, _, _) => bug!("Expected sized CPlace::Addr, found {:?}", self),
368             CPlace::Var(_, _) => bug!("Expected CPlace::Addr, found CPlace::Var"),
369         }
370     }
371
372     pub fn write_cvalue(self, fx: &mut FunctionCx<'a, 'tcx, impl Backend>, from: CValue<'tcx>) {
373         match (&self.layout().ty.sty, &from.layout().ty.sty) {
374             (ty::Ref(_, t, dest_mut), ty::Ref(_, u, src_mut))
375                 if (if *dest_mut != crate::rustc::hir::Mutability::MutImmutable
376                     && src_mut != dest_mut
377                 {
378                     false
379                 } else if t != u {
380                     false
381                 } else {
382                     true
383                 }) =>
384             {
385                 // &mut T -> &T is allowed
386                 // &'a T -> &'b T is allowed
387             }
388             _ => {
389                 assert_eq!(
390                     self.layout().ty,
391                     from.layout().ty,
392                     "Can't write value of incompatible type to place {:?} {:?}\n\n{:#?}",
393                     self.layout().ty.sty,
394                     from.layout().ty.sty,
395                     fx,
396                 );
397             }
398         }
399
400         match self {
401             CPlace::Var(var, _) => {
402                 let data = from.load_value(fx);
403                 fx.bcx.def_var(mir_var(var), data)
404             }
405             CPlace::Addr(addr, None, layout) => {
406                 let size = layout.size.bytes() as i32;
407
408                 match from {
409                     CValue::ByVal(val, _layout) => {
410                         fx.bcx.ins().store(MemFlags::new(), val, addr, 0);
411                     }
412                     CValue::ByValPair(val1, val2, _layout) => {
413                         let val1_offset = layout.fields.offset(0).bytes() as i32;
414                         let val2_offset = layout.fields.offset(1).bytes() as i32;
415                         fx.bcx.ins().store(MemFlags::new(), val1, addr, val1_offset);
416                         fx.bcx.ins().store(MemFlags::new(), val2, addr, val2_offset);
417                     }
418                     CValue::ByRef(from, _layout) => {
419                         let mut offset = 0;
420                         while size - offset >= 8 {
421                             let byte = fx.bcx.ins().load(
422                                 fx.module.pointer_type(),
423                                 MemFlags::new(),
424                                 from,
425                                 offset,
426                             );
427                             fx.bcx.ins().store(MemFlags::new(), byte, addr, offset);
428                             offset += 8;
429                         }
430                         while size - offset >= 4 {
431                             let byte = fx.bcx.ins().load(types::I32, MemFlags::new(), from, offset);
432                             fx.bcx.ins().store(MemFlags::new(), byte, addr, offset);
433                             offset += 4;
434                         }
435                         while offset < size {
436                             let byte = fx.bcx.ins().load(types::I8, MemFlags::new(), from, offset);
437                             fx.bcx.ins().store(MemFlags::new(), byte, addr, offset);
438                             offset += 1;
439                         }
440                     }
441                 }
442             }
443             CPlace::Addr(_, _, _) => bug!("Can't write value to unsized place {:?}", self),
444         }
445     }
446
447     pub fn place_field(
448         self,
449         fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
450         field: mir::Field,
451     ) -> CPlace<'tcx> {
452         match self {
453             CPlace::Var(var, layout) => {
454                 bug!(
455                     "Tried to project {:?}, which is put in SSA var {:?}",
456                     layout.ty,
457                     var
458                 );
459             }
460             CPlace::Addr(base, extra, layout) => {
461                 let (field_ptr, field_layout) = codegen_field(fx, base, layout, field);
462                 CPlace::Addr(field_ptr, extra, field_layout)
463             }
464         }
465     }
466
467     pub fn place_index(
468         self,
469         fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
470         index: Value,
471     ) -> CPlace<'tcx> {
472         let (elem_layout, addr) = match self.layout().ty.sty {
473             ty::Array(elem_ty, _) => (fx.layout_of(elem_ty), self.expect_addr()),
474             ty::Slice(elem_ty) => (
475                 fx.layout_of(elem_ty),
476                 match self {
477                     CPlace::Addr(addr, _, _) => addr,
478                     CPlace::Var(_, _) => bug!("Expected CPlace::Addr found CPlace::Var"),
479                 },
480             ),
481             _ => bug!("place_index({:?})", self.layout().ty),
482         };
483
484         let offset = fx
485             .bcx
486             .ins()
487             .imul_imm(index, elem_layout.size.bytes() as i64);
488
489         CPlace::Addr(fx.bcx.ins().iadd(addr, offset), None, elem_layout)
490     }
491
492     pub fn place_deref(self, fx: &mut FunctionCx<'a, 'tcx, impl Backend>) -> CPlace<'tcx> {
493         let inner_layout = fx.layout_of(self.layout().ty.builtin_deref(true).unwrap().ty);
494         if !inner_layout.is_unsized() {
495             CPlace::Addr(self.to_cvalue(fx).load_value(fx), None, inner_layout)
496         } else {
497             match self.layout().abi {
498                 Abi::ScalarPair(ref a, ref b) => {
499                     let addr = self.expect_addr();
500                     let ptr =
501                         fx.bcx
502                             .ins()
503                             .load(scalar_to_cton_type(fx.tcx, a), MemFlags::new(), addr, 0);
504                     let extra = fx.bcx.ins().load(
505                         scalar_to_cton_type(fx.tcx, b),
506                         MemFlags::new(),
507                         addr,
508                         a.value.size(fx.tcx).bytes() as u32 as i32,
509                     );
510                     CPlace::Addr(ptr, Some(extra), inner_layout)
511                 }
512                 _ => bug!(
513                     "Fat ptr doesn't have abi ScalarPair, but it has {:?}",
514                     self.layout().abi
515                 ),
516             }
517         }
518     }
519
520     pub fn write_place_ref(self, fx: &mut FunctionCx<'a, 'tcx, impl Backend>, dest: CPlace<'tcx>) {
521         if !self.layout().is_unsized() {
522             let ptr = CValue::ByVal(self.expect_addr(), dest.layout());
523             dest.write_cvalue(fx, ptr);
524         } else {
525             match self {
526                 CPlace::Var(_, _) => bug!("expected CPlace::Addr found CPlace::Var"),
527                 CPlace::Addr(value, extra, _) => match dest.layout().abi {
528                     Abi::ScalarPair(ref a, _) => {
529                         fx.bcx
530                             .ins()
531                             .store(MemFlags::new(), value, dest.expect_addr(), 0);
532                         fx.bcx.ins().store(
533                             MemFlags::new(),
534                             extra.expect("unsized type without metadata"),
535                             dest.expect_addr(),
536                             a.value.size(fx.tcx).bytes() as u32 as i32,
537                         );
538                     }
539                     _ => bug!(
540                         "Non ScalarPair abi {:?} in write_place_ref dest",
541                         dest.layout().abi
542                     ),
543                 },
544             }
545         }
546     }
547
548     pub fn unchecked_cast_to(self, layout: TyLayout<'tcx>) -> Self {
549         match self {
550             CPlace::Var(var, _) => CPlace::Var(var, layout),
551             CPlace::Addr(addr, extra, _) => {
552                 assert!(!layout.is_unsized());
553                 CPlace::Addr(addr, extra, layout)
554             }
555         }
556     }
557
558     pub fn downcast_variant(self, fx: &FunctionCx<'a, 'tcx, impl Backend>, variant: usize) -> Self {
559         let layout = self.layout().for_variant(fx, variant);
560         self.unchecked_cast_to(layout)
561     }
562 }
563
564 pub fn cton_intcast<'a, 'tcx: 'a>(
565     fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
566     val: Value,
567     to: Type,
568     signed: bool,
569 ) -> Value {
570     let from = fx.bcx.func.dfg.value_type(val);
571     if from == to {
572         return val;
573     }
574     if to.wider_or_equal(from) {
575         if signed {
576             fx.bcx.ins().sextend(to, val)
577         } else {
578             fx.bcx.ins().uextend(to, val)
579         }
580     } else {
581         fx.bcx.ins().ireduce(to, val)
582     }
583 }
584
585 pub struct FunctionCx<'a, 'tcx: 'a, B: Backend + 'a> {
586     pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
587     pub module: &'a mut Module<B>,
588     pub instance: Instance<'tcx>,
589     pub mir: &'tcx Mir<'tcx>,
590     pub param_substs: &'tcx Substs<'tcx>,
591     pub bcx: FunctionBuilder<'a>,
592     pub ebb_map: HashMap<BasicBlock, Ebb>,
593     pub local_map: HashMap<Local, CPlace<'tcx>>,
594     pub comments: HashMap<Inst, String>,
595     pub constants: &'a mut crate::constant::ConstantCx,
596     pub caches: &'a mut Caches<'tcx>,
597
598     /// add_global_comment inserts a comment here
599     pub top_nop: Option<Inst>,
600 }
601
602 impl<'a, 'tcx: 'a, B: Backend + 'a> fmt::Debug for FunctionCx<'a, 'tcx, B> {
603     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
604         writeln!(f, "{:?}", self.param_substs)?;
605         writeln!(f, "{:?}", self.local_map)?;
606
607         let mut clif = String::new();
608         let mut writer = crate::pretty_clif::CommentWriter(self.comments.clone());
609         ::cranelift::codegen::write::decorate_function(
610             &mut writer,
611             &mut clif,
612             &self.bcx.func,
613             None,
614         ).unwrap();
615         writeln!(f, "\n{}", clif)
616     }
617 }
618
619 impl<'a, 'tcx: 'a, B: Backend> LayoutOf for &'a FunctionCx<'a, 'tcx, B> {
620     type Ty = Ty<'tcx>;
621     type TyLayout = TyLayout<'tcx>;
622
623     fn layout_of(self, ty: Ty<'tcx>) -> TyLayout<'tcx> {
624         let ty = self.monomorphize(&ty);
625         self.tcx.layout_of(ParamEnv::reveal_all().and(&ty)).unwrap()
626     }
627 }
628
629 impl<'a, 'tcx, B: Backend + 'a> layout::HasTyCtxt<'tcx> for &'a FunctionCx<'a, 'tcx, B> {
630     fn tcx<'b>(&'b self) -> TyCtxt<'b, 'tcx, 'tcx> {
631         self.tcx
632     }
633 }
634
635 impl<'a, 'tcx, B: Backend + 'a> layout::HasDataLayout for &'a FunctionCx<'a, 'tcx, B> {
636     fn data_layout(&self) -> &layout::TargetDataLayout {
637         &self.tcx.data_layout
638     }
639 }
640
641 impl<'a, 'tcx, B: Backend + 'a> HasTargetSpec for &'a FunctionCx<'a, 'tcx, B> {
642     fn target_spec(&self) -> &Target {
643         &self.tcx.sess.target.target
644     }
645 }
646
647 impl<'a, 'tcx: 'a, B: Backend + 'a> FunctionCx<'a, 'tcx, B> {
648     pub fn monomorphize<T>(&self, value: &T) -> T
649     where
650         T: TypeFoldable<'tcx>,
651     {
652         self.tcx.subst_and_normalize_erasing_regions(
653             self.param_substs,
654             ty::ParamEnv::reveal_all(),
655             value,
656         )
657     }
658
659     pub fn cton_type(&self, ty: Ty<'tcx>) -> Option<Type> {
660         cton_type_from_ty(self.tcx, self.monomorphize(&ty))
661     }
662
663     pub fn get_ebb(&self, bb: BasicBlock) -> Ebb {
664         *self.ebb_map.get(&bb).unwrap()
665     }
666
667     pub fn get_local_place(&mut self, local: Local) -> CPlace<'tcx> {
668         *self.local_map.get(&local).unwrap()
669     }
670 }