]> git.lizzy.rs Git - rust.git/blob - src/common.rs
Rustup to rustc 1.29.0-nightly (866a71325 2018-07-29)
[rust.git] / src / common.rs
1 use std::fmt;
2
3 use rustc_target::spec::{HasTargetSpec, Target};
4
5 use cranelift_module::{Module, FuncId, DataId};
6
7 use crate::prelude::*;
8
9 pub type CurrentBackend = ::cranelift_simplejit::SimpleJITBackend;
10
11 #[derive(Debug, Copy, Clone, Eq, PartialEq)]
12 pub struct Variable(Local);
13
14 impl EntityRef for Variable {
15     fn new(u: usize) -> Self {
16         Variable(Local::new(u))
17     }
18
19     fn index(self) -> usize {
20         self.0.index()
21     }
22 }
23
24 pub fn cton_type_from_ty<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: Ty<'tcx>) -> Option<types::Type> {
25     Some(match ty.sty {
26         TypeVariants::TyBool => types::I8,
27         TypeVariants::TyUint(size) => {
28             match size {
29                 UintTy::U8 => types::I8,
30                 UintTy::U16 => types::I16,
31                 UintTy::U32 => types::I32,
32                 UintTy::U64 => types::I64,
33                 UintTy::U128 => unimplemented!("u128"),
34                 UintTy::Usize => types::I64,
35             }
36         }
37         TypeVariants::TyInt(size) => {
38             match size {
39                 IntTy::I8 => types::I8,
40                 IntTy::I16 => types::I16,
41                 IntTy::I32 => types::I32,
42                 IntTy::I64 => types::I64,
43                 IntTy::I128 => unimplemented!("i128"),
44                 IntTy::Isize => types::I64,
45             }
46         }
47         TypeVariants::TyChar => types::I32,
48         TypeVariants::TyFloat(size) => {
49             match size {
50                 FloatTy::F32 => types::I32,
51                 FloatTy::F64 => types::I64,
52             }
53         }
54         TypeVariants::TyFnPtr(_) => types::I64,
55         TypeVariants::TyRawPtr(TypeAndMut { ty, mutbl: _ }) | TypeVariants::TyRef(_, ty, _) => {
56             if ty.is_sized(tcx.at(DUMMY_SP), ParamEnv::reveal_all()) {
57                 types::I64
58             } else {
59                 return None;
60             }
61         }
62         TypeVariants::TyParam(_)  => bug!("{:?}: {:?}", ty, ty.sty),
63         _ => return None,
64     })
65 }
66
67 fn codegen_field<'a, 'tcx: 'a>(
68     fx: &mut FunctionCx<'a, 'tcx>,
69     base: Value,
70     layout: TyLayout<'tcx>,
71     field: mir::Field
72 ) -> (Value, TyLayout<'tcx>) {
73     let field_offset = layout.fields.offset(field.index());
74     let field_ty = layout.field(&*fx, field.index());
75     if field_offset.bytes() > 0 {
76         let field_offset = fx.bcx.ins().iconst(types::I64, field_offset.bytes() as i64);
77         (fx.bcx.ins().iadd(base, field_offset), field_ty)
78     } else {
79         (base, field_ty)
80     }
81 }
82
83 /// A read-only value
84 #[derive(Debug, Copy, Clone)]
85 pub enum CValue<'tcx> {
86     ByRef(Value, TyLayout<'tcx>),
87     ByVal(Value, TyLayout<'tcx>),
88     Func(FuncRef, TyLayout<'tcx>),
89 }
90
91 impl<'tcx> CValue<'tcx> {
92     pub fn layout(&self) -> TyLayout<'tcx> {
93         match *self {
94             CValue::ByRef(_, layout) |
95             CValue::ByVal(_, layout) |
96             CValue::Func(_, layout) => layout
97         }
98     }
99
100     pub fn force_stack<'a>(self, fx: &mut FunctionCx<'a, 'tcx>) -> Value where 'tcx: 'a {
101         match self {
102             CValue::ByRef(value, _layout) => value,
103             CValue::ByVal(value, layout) => {
104                 let stack_slot = fx.bcx.create_stack_slot(StackSlotData {
105                     kind: StackSlotKind::ExplicitSlot,
106                     size: layout.size.bytes() as u32,
107                     offset: None,
108                 });
109                 fx.bcx.ins().stack_store(value, stack_slot, 0);
110                 fx.bcx.ins().stack_addr(types::I64, stack_slot, 0)
111             }
112             CValue::Func(func, ty) => {
113                 let func = fx.bcx.ins().func_addr(types::I64, func);
114                 CValue::ByVal(func, ty).force_stack(fx)
115             }
116         }
117     }
118
119     pub fn load_value<'a>(self, fx: &mut FunctionCx<'a, 'tcx>) -> Value where 'tcx: 'a{
120         match self {
121             CValue::ByRef(addr, layout) => {
122                 let cton_ty = fx.cton_type(layout.ty).expect(&format!("load_value of type {:?}", layout.ty));
123                 fx.bcx.ins().load(cton_ty, MemFlags::new(), addr, 0)
124             }
125             CValue::ByVal(value, _layout) => value,
126             CValue::Func(func, _layout) => {
127                 fx.bcx.ins().func_addr(types::I64, func)
128             }
129         }
130     }
131
132     pub fn expect_byref(self) -> (Value, TyLayout<'tcx>) {
133         match self {
134             CValue::ByRef(value, layout) => (value, layout),
135             CValue::ByVal(_, _) => bug!("Expected CValue::ByRef, found CValue::ByVal"),
136             CValue::Func(_, _) => bug!("Expected CValue::ByRef, found CValue::Func"),
137         }
138     }
139
140     pub fn value_field<'a>(self, fx: &mut FunctionCx<'a, 'tcx>, field: mir::Field) -> CValue<'tcx> where 'tcx: 'a {
141         let (base, layout) = match self {
142             CValue::ByRef(addr, layout) => (addr, layout),
143             _ => bug!("place_field for {:?}", self),
144         };
145
146         let (field_ptr, field_layout) = codegen_field(fx, base, layout, field);
147         CValue::ByRef(field_ptr, field_layout)
148     }
149
150     pub fn const_val<'a>(fx: &mut FunctionCx<'a, 'tcx>, ty: Ty<'tcx>, const_val: i64) -> CValue<'tcx> where 'tcx: 'a {
151         let cton_ty = fx.cton_type(ty).unwrap();
152         let layout = fx.layout_of(ty);
153         CValue::ByVal(fx.bcx.ins().iconst(cton_ty, const_val), layout)
154     }
155
156     pub fn unchecked_cast_to(self, layout: TyLayout<'tcx>) -> Self {
157         match self {
158             CValue::ByRef(addr, _) => CValue::ByRef(addr, layout),
159             CValue::ByVal(val, _) => CValue::ByVal(val, layout),
160             CValue::Func(fun, _) => CValue::Func(fun, layout),
161         }
162     }
163 }
164
165 /// A place where you can write a value to or read a value from
166 #[derive(Debug, Copy, Clone)]
167 pub enum CPlace<'tcx> {
168     Var(Variable, TyLayout<'tcx>),
169     Addr(Value, TyLayout<'tcx>),
170 }
171
172 impl<'a, 'tcx: 'a> CPlace<'tcx> {
173     pub fn layout(&self) -> TyLayout<'tcx> {
174         match *self {
175             CPlace::Var(_, layout) |
176             CPlace::Addr(_, layout) => layout,
177         }
178     }
179
180     pub fn from_stack_slot(fx: &mut FunctionCx<'a, 'tcx>, stack_slot: StackSlot, ty: Ty<'tcx>) -> CPlace<'tcx> {
181         let layout = fx.layout_of(ty);
182         CPlace::Addr(fx.bcx.ins().stack_addr(types::I64, stack_slot, 0), layout)
183     }
184
185     pub fn to_cvalue(self, fx: &mut FunctionCx<'a, 'tcx>) -> CValue<'tcx> {
186         match self {
187             CPlace::Var(var, layout) => CValue::ByVal(fx.bcx.use_var(var), layout),
188             CPlace::Addr(addr, layout) => CValue::ByRef(addr, layout),
189         }
190     }
191
192     pub fn expect_addr(self) -> Value {
193         match self {
194             CPlace::Addr(addr, _layout) => addr,
195             CPlace::Var(_, _) => bug!("Expected CPlace::Addr, found CPlace::Var"),
196         }
197     }
198
199     pub fn write_cvalue(self, fx: &mut FunctionCx<'a, 'tcx>, from: CValue<'tcx>) {
200         match (&self.layout().ty.sty, &from.layout().ty.sty) {
201             (TypeVariants::TyRef(_, t, dest_mut), TypeVariants::TyRef(_, u, src_mut)) if (
202                 if *dest_mut != ::rustc::hir::Mutability::MutImmutable && src_mut != dest_mut {
203                     false
204                 } else if t != u {
205                     false
206                 } else {
207                     true
208                 }
209             ) => {
210                 // &mut T -> &T is allowed
211                 // &'a T -> &'b T is allowed
212             }
213             _ => {
214                 assert_eq!(
215                     self.layout().ty, from.layout().ty,
216                     "Can't write value of incompatible type to place {:?} {:?}\n\n{:#?}",
217                     self.layout().ty.sty, from.layout().ty.sty,
218                     fx,
219                 );
220             }
221         }
222
223         match self {
224             CPlace::Var(var, _) => {
225                 let data = from.load_value(fx);
226                 fx.bcx.def_var(var, data)
227             },
228             CPlace::Addr(addr, layout) => {
229                 let size = layout.size.bytes() as i32;
230
231                 if let Some(_) = fx.cton_type(layout.ty) {
232                     let data = from.load_value(fx);
233                     fx.bcx.ins().store(MemFlags::new(), data, addr, 0);
234                 } else {
235                     let from = from.expect_byref();
236                     let mut offset = 0;
237                     while size - offset >= 8 {
238                         let byte = fx.bcx.ins().load(types::I64, MemFlags::new(), from.0, offset);
239                         fx.bcx.ins().store(MemFlags::new(), byte, addr, offset);
240                         offset += 8;
241                     }
242                     while size - offset >= 4 {
243                         let byte = fx.bcx.ins().load(types::I32, MemFlags::new(), from.0, offset);
244                         fx.bcx.ins().store(MemFlags::new(), byte, addr, offset);
245                         offset += 4;
246                     }
247                     while offset < size {
248                         let byte = fx.bcx.ins().load(types::I8, MemFlags::new(), from.0, offset);
249                         fx.bcx.ins().store(MemFlags::new(), byte, addr, offset);
250                         offset += 1;
251                     }
252                 }
253             }
254         }
255     }
256
257     pub fn place_field(self, fx: &mut FunctionCx<'a, 'tcx>, field: mir::Field) -> CPlace<'tcx> {
258         let base = self.expect_addr();
259         let layout = self.layout();
260
261         let (field_ptr, field_layout) = codegen_field(fx, base, layout, field);
262         CPlace::Addr(field_ptr, field_layout)
263     }
264
265     pub fn unchecked_cast_to(self, layout: TyLayout<'tcx>) -> Self {
266         match self {
267             CPlace::Var(var, _) => CPlace::Var(var, layout),
268             CPlace::Addr(addr, _) => CPlace::Addr(addr, layout),
269         }
270     }
271
272     pub fn downcast_variant(self, fx: &FunctionCx<'a, 'tcx>, variant: usize) -> Self {
273         let layout = self.layout().for_variant(fx, variant);
274         self.unchecked_cast_to(layout)
275     }
276 }
277
278 pub fn cton_intcast<'a, 'tcx: 'a>(fx: &mut FunctionCx<'a, 'tcx>, val: Value, from: Ty<'tcx>, to: Ty<'tcx>, signed: bool) -> Value {
279     let from = fx.cton_type(from).unwrap();
280     let to = fx.cton_type(to).unwrap();
281     if from == to {
282         return val;
283     }
284     if to.wider_or_equal(from) {
285         if signed {
286             fx.bcx.ins().sextend(to, val)
287         } else {
288             fx.bcx.ins().uextend(to, val)
289         }
290     } else {
291         fx.bcx.ins().ireduce(to, val)
292     }
293 }
294
295 pub struct FunctionCx<'a, 'tcx: 'a> {
296     pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
297     pub module: &'a mut Module<CurrentBackend>,
298     pub def_id_fn_id_map: &'a mut HashMap<Instance<'tcx>, FuncId>,
299     pub instance: Instance<'tcx>,
300     pub mir: &'tcx Mir<'tcx>,
301     pub param_substs: &'tcx Substs<'tcx>,
302     pub bcx: FunctionBuilder<'a, Variable>,
303     pub ebb_map: HashMap<BasicBlock, Ebb>,
304     pub local_map: HashMap<Local, CPlace<'tcx>>,
305     pub comments: HashMap<Inst, String>,
306     pub constants: &'a mut HashMap<AllocId, DataId>,
307 }
308
309 impl<'a, 'tcx: 'a> fmt::Debug for FunctionCx<'a, 'tcx> {
310     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
311         writeln!(f, "{:?}", self.def_id_fn_id_map)?;
312         writeln!(f, "{:?}", self.param_substs)?;
313         writeln!(f, "{:?}", self.local_map)?;
314
315         let mut clif = String::new();
316         let mut writer = crate::pretty_clif::CommentWriter(self.comments.clone());
317         ::cranelift::codegen::write::decorate_function(
318             &mut writer,
319             &mut clif,
320             &self.bcx.func,
321             None,
322         ).unwrap();
323         writeln!(f, "\n{}", clif)
324     }
325 }
326
327 impl<'a, 'tcx: 'a> LayoutOf for &'a FunctionCx<'a, 'tcx> {
328     type Ty = Ty<'tcx>;
329     type TyLayout = TyLayout<'tcx>;
330
331     fn layout_of(self, ty: Ty<'tcx>) -> TyLayout<'tcx> {
332         let ty = self.monomorphize(&ty);
333         self.tcx.layout_of(ParamEnv::reveal_all().and(&ty)).unwrap()
334     }
335 }
336
337 impl<'a, 'tcx> layout::HasTyCtxt<'tcx> for &'a FunctionCx<'a, 'tcx> {
338     fn tcx<'b>(&'b self) -> TyCtxt<'b, 'tcx, 'tcx> {
339         self.tcx
340     }
341 }
342
343 impl<'a, 'tcx> layout::HasDataLayout for &'a FunctionCx<'a, 'tcx> {
344     fn data_layout(&self) -> &layout::TargetDataLayout {
345         &self.tcx.data_layout
346     }
347 }
348
349 impl<'a, 'tcx> HasTargetSpec for &'a FunctionCx<'a, 'tcx> {
350     fn target_spec(&self) -> &Target {
351         &self.tcx.sess.target.target
352     }
353 }
354
355 impl<'a, 'tcx: 'a> FunctionCx<'a, 'tcx> {
356     pub fn monomorphize<T>(&self, value: &T) -> T
357         where T: TypeFoldable<'tcx>
358     {
359         self.tcx.subst_and_normalize_erasing_regions(
360             self.param_substs,
361             ty::ParamEnv::reveal_all(),
362             value,
363         )
364     }
365
366     pub fn cton_type(&self, ty: Ty<'tcx>) -> Option<Type> {
367         cton_type_from_ty(self.tcx, self.monomorphize(&ty))
368     }
369
370     pub fn get_ebb(&self, bb: BasicBlock) -> Ebb {
371         *self.ebb_map.get(&bb).unwrap()
372     }
373
374     pub fn get_local_place(&mut self, local: Local) -> CPlace<'tcx> {
375         *self.local_map.get(&local).unwrap()
376     }
377 }