]> git.lizzy.rs Git - rust.git/blob - src/common.rs
Rustup to rustc 1.30.0-nightly (cb6d2dfa8 2018-09-16)
[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 && src_mut != dest_mut {
376                     false
377                 } else if t != u {
378                     false
379                 } else {
380                     true
381                 }) =>
382             {
383                 // &mut T -> &T is allowed
384                 // &'a T -> &'b T is allowed
385             }
386             _ => {
387                 assert_eq!(
388                     self.layout().ty,
389                     from.layout().ty,
390                     "Can't write value of incompatible type to place {:?} {:?}\n\n{:#?}",
391                     self.layout().ty.sty,
392                     from.layout().ty.sty,
393                     fx,
394                 );
395             }
396         }
397
398         match self {
399             CPlace::Var(var, _) => {
400                 let data = from.load_value(fx);
401                 fx.bcx.def_var(mir_var(var), data)
402             }
403             CPlace::Addr(addr, None, layout) => {
404                 let size = layout.size.bytes() as i32;
405
406                 match from {
407                     CValue::ByVal(val, _layout) => {
408                         fx.bcx.ins().store(MemFlags::new(), val, addr, 0);
409                     }
410                     CValue::ByValPair(val1, val2, _layout) => {
411                         let val1_offset = layout.fields.offset(0).bytes() as i32;
412                         let val2_offset = layout.fields.offset(1).bytes() as i32;
413                         fx.bcx.ins().store(MemFlags::new(), val1, addr, val1_offset);
414                         fx.bcx.ins().store(MemFlags::new(), val2, addr, val2_offset);
415                     }
416                     CValue::ByRef(from, _layout) => {
417                         let mut offset = 0;
418                         while size - offset >= 8 {
419                             let byte = fx.bcx.ins().load(
420                                 fx.module.pointer_type(),
421                                 MemFlags::new(),
422                                 from,
423                                 offset,
424                             );
425                             fx.bcx.ins().store(MemFlags::new(), byte, addr, offset);
426                             offset += 8;
427                         }
428                         while size - offset >= 4 {
429                             let byte = fx.bcx.ins().load(types::I32, MemFlags::new(), from, offset);
430                             fx.bcx.ins().store(MemFlags::new(), byte, addr, offset);
431                             offset += 4;
432                         }
433                         while offset < size {
434                             let byte = fx.bcx.ins().load(types::I8, MemFlags::new(), from, offset);
435                             fx.bcx.ins().store(MemFlags::new(), byte, addr, offset);
436                             offset += 1;
437                         }
438                     }
439                 }
440             }
441             CPlace::Addr(_, _, _) => bug!("Can't write value to unsized place {:?}", self),
442         }
443     }
444
445     pub fn place_field(
446         self,
447         fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
448         field: mir::Field,
449     ) -> CPlace<'tcx> {
450         match self {
451             CPlace::Var(var, layout) => {
452                 bug!("Tried to project {:?}, which is put in SSA var {:?}", layout.ty, var);
453             }
454             CPlace::Addr(base, extra, layout) => {
455                 let (field_ptr, field_layout) = codegen_field(fx, base, layout, field);
456                 CPlace::Addr(field_ptr, extra, field_layout)
457             }
458         }
459     }
460
461     pub fn place_index(
462         self,
463         fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
464         index: Value,
465     ) -> CPlace<'tcx> {
466         let (elem_layout, addr) = match self.layout().ty.sty {
467             ty::Array(elem_ty, _) => (fx.layout_of(elem_ty), self.expect_addr()),
468             ty::Slice(elem_ty) => (
469                 fx.layout_of(elem_ty),
470                 match self {
471                     CPlace::Addr(addr, _, _) => addr,
472                     CPlace::Var(_, _) => bug!("Expected CPlace::Addr found CPlace::Var"),
473                 },
474             ),
475             _ => bug!("place_index({:?})", self.layout().ty),
476         };
477
478         let offset = fx
479             .bcx
480             .ins()
481             .imul_imm(index, elem_layout.size.bytes() as i64);
482
483         CPlace::Addr(fx.bcx.ins().iadd(addr, offset), None, elem_layout)
484     }
485
486     pub fn place_deref(self, fx: &mut FunctionCx<'a, 'tcx, impl Backend>) -> CPlace<'tcx> {
487         let inner_layout = fx.layout_of(self.layout().ty.builtin_deref(true).unwrap().ty);
488         if !inner_layout.is_unsized() {
489             CPlace::Addr(self.to_cvalue(fx).load_value(fx), None, inner_layout)
490         } else {
491             match self.layout().abi {
492                 Abi::ScalarPair(ref a, ref b) => {
493                     let addr = self.expect_addr();
494                     let ptr =
495                         fx.bcx
496                             .ins()
497                             .load(scalar_to_cton_type(fx.tcx, a), MemFlags::new(), addr, 0);
498                     let extra = fx.bcx.ins().load(
499                         scalar_to_cton_type(fx.tcx, b),
500                         MemFlags::new(),
501                         addr,
502                         a.value.size(fx.tcx).bytes() as u32 as i32,
503                     );
504                     CPlace::Addr(ptr, Some(extra), inner_layout)
505                 }
506                 _ => bug!(
507                     "Fat ptr doesn't have abi ScalarPair, but it has {:?}",
508                     self.layout().abi
509                 ),
510             }
511         }
512     }
513
514     pub fn write_place_ref(self, fx: &mut FunctionCx<'a, 'tcx, impl Backend>, dest: CPlace<'tcx>) {
515         if !self.layout().is_unsized() {
516             let ptr = CValue::ByVal(self.expect_addr(), dest.layout());
517             dest.write_cvalue(fx, ptr);
518         } else {
519             match self {
520                 CPlace::Var(_, _) => bug!("expected CPlace::Addr found CPlace::Var"),
521                 CPlace::Addr(value, extra, _) => match dest.layout().abi {
522                     Abi::ScalarPair(ref a, _) => {
523                         fx.bcx
524                             .ins()
525                             .store(MemFlags::new(), value, dest.expect_addr(), 0);
526                         fx.bcx.ins().store(
527                             MemFlags::new(),
528                             extra.expect("unsized type without metadata"),
529                             dest.expect_addr(),
530                             a.value.size(fx.tcx).bytes() as u32 as i32,
531                         );
532                     }
533                     _ => bug!(
534                         "Non ScalarPair abi {:?} in write_place_ref dest",
535                         dest.layout().abi
536                     ),
537                 },
538             }
539         }
540     }
541
542     pub fn unchecked_cast_to(self, layout: TyLayout<'tcx>) -> Self {
543         match self {
544             CPlace::Var(var, _) => CPlace::Var(var, layout),
545             CPlace::Addr(addr, extra, _) => {
546                 assert!(!layout.is_unsized());
547                 CPlace::Addr(addr, extra, layout)
548             }
549         }
550     }
551
552     pub fn downcast_variant(self, fx: &FunctionCx<'a, 'tcx, impl Backend>, variant: usize) -> Self {
553         let layout = self.layout().for_variant(fx, variant);
554         self.unchecked_cast_to(layout)
555     }
556 }
557
558 pub fn cton_intcast<'a, 'tcx: 'a>(
559     fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
560     val: Value,
561     to: Type,
562     signed: bool,
563 ) -> Value {
564     let from = fx.bcx.func.dfg.value_type(val);
565     if from == to {
566         return val;
567     }
568     if to.wider_or_equal(from) {
569         if signed {
570             fx.bcx.ins().sextend(to, val)
571         } else {
572             fx.bcx.ins().uextend(to, val)
573         }
574     } else {
575         fx.bcx.ins().ireduce(to, val)
576     }
577 }
578
579 pub struct FunctionCx<'a, 'tcx: 'a, B: Backend + 'a> {
580     pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
581     pub module: &'a mut Module<B>,
582     pub instance: Instance<'tcx>,
583     pub mir: &'tcx Mir<'tcx>,
584     pub param_substs: &'tcx Substs<'tcx>,
585     pub bcx: FunctionBuilder<'a>,
586     pub ebb_map: HashMap<BasicBlock, Ebb>,
587     pub local_map: HashMap<Local, CPlace<'tcx>>,
588     pub comments: HashMap<Inst, String>,
589     pub constants: &'a mut crate::constant::ConstantCx,
590     pub caches: &'a mut Caches<'tcx>,
591
592     /// add_global_comment inserts a comment here
593     pub top_nop: Option<Inst>,
594 }
595
596 impl<'a, 'tcx: 'a, B: Backend + 'a> fmt::Debug for FunctionCx<'a, 'tcx, B> {
597     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
598         writeln!(f, "{:?}", self.param_substs)?;
599         writeln!(f, "{:?}", self.local_map)?;
600
601         let mut clif = String::new();
602         let mut writer = crate::pretty_clif::CommentWriter(self.comments.clone());
603         ::cranelift::codegen::write::decorate_function(
604             &mut writer,
605             &mut clif,
606             &self.bcx.func,
607             None,
608         ).unwrap();
609         writeln!(f, "\n{}", clif)
610     }
611 }
612
613 impl<'a, 'tcx: 'a, B: Backend> LayoutOf for &'a FunctionCx<'a, 'tcx, B> {
614     type Ty = Ty<'tcx>;
615     type TyLayout = TyLayout<'tcx>;
616
617     fn layout_of(self, ty: Ty<'tcx>) -> TyLayout<'tcx> {
618         let ty = self.monomorphize(&ty);
619         self.tcx.layout_of(ParamEnv::reveal_all().and(&ty)).unwrap()
620     }
621 }
622
623 impl<'a, 'tcx, B: Backend + 'a> layout::HasTyCtxt<'tcx> for &'a FunctionCx<'a, 'tcx, B> {
624     fn tcx<'b>(&'b self) -> TyCtxt<'b, 'tcx, 'tcx> {
625         self.tcx
626     }
627 }
628
629 impl<'a, 'tcx, B: Backend + 'a> layout::HasDataLayout for &'a FunctionCx<'a, 'tcx, B> {
630     fn data_layout(&self) -> &layout::TargetDataLayout {
631         &self.tcx.data_layout
632     }
633 }
634
635 impl<'a, 'tcx, B: Backend + 'a> HasTargetSpec for &'a FunctionCx<'a, 'tcx, B> {
636     fn target_spec(&self) -> &Target {
637         &self.tcx.sess.target.target
638     }
639 }
640
641 impl<'a, 'tcx: 'a, B: Backend + 'a> FunctionCx<'a, 'tcx, B> {
642     pub fn monomorphize<T>(&self, value: &T) -> T
643     where
644         T: TypeFoldable<'tcx>,
645     {
646         self.tcx.subst_and_normalize_erasing_regions(
647             self.param_substs,
648             ty::ParamEnv::reveal_all(),
649             value,
650         )
651     }
652
653     pub fn cton_type(&self, ty: Ty<'tcx>) -> Option<Type> {
654         cton_type_from_ty(self.tcx, self.monomorphize(&ty))
655     }
656
657     pub fn get_ebb(&self, bb: BasicBlock) -> Ebb {
658         *self.ebb_map.get(&bb).unwrap()
659     }
660
661     pub fn get_local_place(&mut self, local: Local) -> CPlace<'tcx> {
662         *self.local_map.get(&local).unwrap()
663     }
664 }