1 extern crate rustc_target;
3 use syntax::ast::{IntTy, UintTy};
4 use self::rustc_target::spec::{HasTargetSpec, Target};
6 use cretonne_module::{Module, Linkage, FuncId};
10 pub type CurrentBackend = ::cretonne_simplejit::SimpleJITBackend;
12 #[derive(Debug, Copy, Clone, Eq, PartialEq)]
13 pub struct Variable(Local);
15 impl EntityRef for Variable {
16 fn new(u: usize) -> Self {
17 Variable(Local::new(u))
20 fn index(self) -> usize {
25 fn cton_type_from_ty(ty: Ty) -> Option<types::Type> {
27 TypeVariants::TyBool => types::I8,
28 TypeVariants::TyUint(size) => {
30 UintTy::U8 => types::I8,
31 UintTy::U16 => types::I16,
32 UintTy::U32 => types::I32,
33 UintTy::U64 => types::I64,
34 UintTy::U128 => unimplemented!(),
35 UintTy::Usize => types::I64,
38 TypeVariants::TyInt(size) => {
40 IntTy::I8 => types::I8,
41 IntTy::I16 => types::I16,
42 IntTy::I32 => types::I32,
43 IntTy::I64 => types::I64,
44 IntTy::I128 => unimplemented!(),
45 IntTy::Isize => types::I64,
48 TypeVariants::TyFnPtr(_) => types::I64,
49 TypeVariants::TyRef(..) | TypeVariants::TyRawPtr(..) => types::I64,
54 // FIXME(cretonne) fix types smaller than I32
55 pub fn fixup_cton_ty(ty: Type) -> Type {
57 types::I64X2 | types::I64 | types::I32 => ty,
62 // FIXME(cretonne) fix load.i8
63 fn load_workaround(fx: &mut FunctionCx, ty: Type, addr: Value, offset: i32) -> Value {
64 use cretonne::codegen::ir::types::*;
66 I8 => fx.bcx.ins().uload8(I32, MemFlags::new(), addr, offset),
67 I16 => fx.bcx.ins().uload16(I32, MemFlags::new(), addr, offset),
69 _ => fx.bcx.ins().load(ty, MemFlags::new(), addr, offset),
73 // FIXME(cretonne) fix store.i8
74 fn store_workaround(fx: &mut FunctionCx, ty: Type, addr: Value, val: Value, offset: i32) {
75 use cretonne::codegen::ir::types::*;
77 I8 => fx.bcx.ins().istore8(MemFlags::new(), val, addr, offset),
78 I16 => fx.bcx.ins().istore16(MemFlags::new(), val, addr, offset),
80 _ => fx.bcx.ins().store(MemFlags::new(), val, addr, offset),
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>),
91 impl<'tcx> CValue<'tcx> {
92 pub fn layout(&self) -> TyLayout<'tcx> {
94 CValue::ByRef(_, layout) |
95 CValue::ByVal(_, layout) |
96 CValue::Func(_, layout) => layout
100 pub fn force_stack<'a>(self, fx: &mut FunctionCx<'a, 'tcx>) -> Value where 'tcx: 'a {
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,
109 fx.bcx.ins().stack_store(value, stack_slot, 0);
110 fx.bcx.ins().stack_addr(types::I64, stack_slot, 0)
112 CValue::Func(func, ty) => {
113 let func = fx.bcx.ins().func_addr(types::I64, func);
114 CValue::ByVal(func, ty).force_stack(fx)
119 pub fn load_value<'a>(self, fx: &mut FunctionCx<'a, 'tcx>) -> Value where 'tcx: 'a{
121 CValue::ByRef(value, layout) => {
122 let cton_ty = fx.cton_type(layout.ty).expect(&format!("{:?}", layout.ty));
123 load_workaround(fx, cton_ty, value, 0)
125 CValue::ByVal(value, _layout) => value,
126 CValue::Func(func, _layout) => {
127 fx.bcx.ins().func_addr(types::I64, func)
132 pub fn expect_byref(self) -> (Value, TyLayout<'tcx>) {
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"),
140 pub fn value_field<'a>(self, fx: &mut FunctionCx<'a, 'tcx>, field: mir::Field) -> CValue<'tcx> where 'tcx: 'a {
141 use rustc::ty::util::IntTypeExt;
143 let (base, layout) = match self {
144 CValue::ByRef(addr, layout) => (addr, layout),
145 _ => bug!("place_field for {:?}", self),
147 let field_offset = layout.fields.offset(field.index());
148 let field_layout = if field.index() == 0 {
149 fx.layout_of(if let ty::TyAdt(adt_def, _) = layout.ty.sty {
150 adt_def.repr.discr_type().to_ty(fx.tcx)
152 // This can only be `0`, for now, so `u8` will suffice.
156 layout.field(&*fx, field.index())
158 if field_offset.bytes() > 0 {
159 let field_offset = fx.bcx.ins().iconst(types::I64, field_offset.bytes() as i64);
160 CValue::ByRef(fx.bcx.ins().iadd(base, field_offset), field_layout)
162 CValue::ByRef(base, field_layout)
166 pub fn const_val<'a>(fx: &mut FunctionCx<'a, 'tcx>, ty: Ty<'tcx>, const_val: i64) -> CValue<'tcx> where 'tcx: 'a {
167 let cton_ty = fx.cton_type(ty).unwrap();
168 let cton_ty = fixup_cton_ty(cton_ty);
169 let layout = fx.layout_of(ty);
170 CValue::ByVal(fx.bcx.ins().iconst(cton_ty, const_val), layout)
173 pub fn unchecked_cast_to(self, layout: TyLayout<'tcx>) -> Self {
175 CValue::ByRef(addr, _) => CValue::ByRef(addr, layout),
176 CValue::ByVal(val, _) => CValue::ByVal(val, layout),
177 CValue::Func(fun, _) => CValue::Func(fun, layout),
182 #[derive(Debug, Copy, Clone)]
183 pub enum CPlace<'tcx> {
184 Var(Variable, TyLayout<'tcx>),
185 Addr(Value, TyLayout<'tcx>),
188 impl<'a, 'tcx: 'a> CPlace<'tcx> {
189 pub fn layout(&self) -> TyLayout<'tcx> {
191 CPlace::Var(_, layout) |
192 CPlace::Addr(_, layout) => layout
196 pub fn from_stack_slot(fx: &mut FunctionCx<'a, 'tcx>, stack_slot: StackSlot, ty: Ty<'tcx>) -> CPlace<'tcx> {
197 let layout = fx.layout_of(ty);
198 CPlace::Addr(fx.bcx.ins().stack_addr(types::I64, stack_slot, 0), layout)
201 pub fn to_cvalue(self, fx: &mut FunctionCx<'a, 'tcx>) -> CValue<'tcx> {
203 CPlace::Var(var, layout) => CValue::ByVal(fx.bcx.use_var(var), layout),
204 CPlace::Addr(addr, layout) => CValue::ByRef(addr, layout),
208 pub fn expect_addr(self) -> Value {
210 CPlace::Addr(addr, _layout) => addr,
211 CPlace::Var(_, _) => bug!("Expected CPlace::Addr, found CPlace::Var"),
215 pub fn write_cvalue(self, fx: &mut FunctionCx<'a, 'tcx>, from: CValue<'tcx>) {
216 assert_eq!(self.layout().ty, from.layout().ty, "Can't write value of incompatible type to place");
219 CPlace::Var(var, _) => {
220 let data = from.load_value(fx);
221 fx.bcx.def_var(var, data)
223 CPlace::Addr(addr, layout) => {
224 let size = layout.size.bytes() as i32;
226 if let Some(cton_ty) = fx.cton_type(layout.ty) {
227 let data = from.load_value(fx);
228 store_workaround(fx, cton_ty, addr, data, 0);
231 let from = from.expect_byref();
232 let byte = load_workaround(fx, types::I8, from.0, i);
233 store_workaround(fx, types::I8, addr, byte, i);
240 pub fn place_field(self, fx: &mut FunctionCx<'a, 'tcx>, field: mir::Field) -> CPlace<'tcx> {
241 let base = self.expect_addr();
242 let layout = self.layout();
243 let field_offset = layout.fields.offset(field.index());
244 let field_ty = layout.field(&*fx, field.index());
245 if field_offset.bytes() > 0 {
246 let field_offset = fx.bcx.ins().iconst(types::I64, field_offset.bytes() as i64);
247 CPlace::Addr(fx.bcx.ins().iadd(base, field_offset), field_ty)
249 CPlace::Addr(base, field_ty)
253 pub fn unchecked_cast_to(self, layout: TyLayout<'tcx>) -> Self {
255 CPlace::Var(var, _) => CPlace::Var(var, layout),
256 CPlace::Addr(addr, _) => CPlace::Addr(addr, layout),
260 pub fn downcast_variant(self, fx: &FunctionCx<'a, 'tcx>, variant: usize) -> Self {
261 let layout = self.layout().for_variant(fx, variant);
262 self.unchecked_cast_to(layout)
266 pub fn cton_sig_from_fn_sig<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, sig: PolyFnSig<'tcx>, substs: &Substs<'tcx>) -> Signature {
267 let sig = tcx.subst_and_normalize_erasing_regions(substs, ParamEnv::reveal_all(), &sig);
268 cton_sig_from_mono_fn_sig(sig)
271 pub fn cton_sig_from_instance<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, inst: Instance<'tcx>) -> Signature {
272 let fn_ty = inst.ty(tcx);
273 let sig = fn_ty.fn_sig(tcx);
274 cton_sig_from_mono_fn_sig(sig)
277 pub fn cton_sig_from_mono_fn_sig<'a ,'tcx: 'a>(sig: PolyFnSig<'tcx>) -> Signature {
278 let sig = sig.skip_binder();
279 let inputs = sig.inputs();
280 let _output = sig.output();
281 assert!(!sig.variadic, "Variadic function are not yet supported");
282 let call_conv = match sig.abi {
283 _ => CallConv::SystemV,
286 params: Some(types::I64).into_iter() // First param is place to put return val
287 .chain(inputs.into_iter().map(|ty| fixup_cton_ty(cton_type_from_ty(ty).unwrap_or(types::I64))))
288 .map(AbiParam::new).collect(),
291 argument_bytes: None,
295 pub fn cton_intcast<'a, 'tcx: 'a>(fx: &mut FunctionCx<'a, 'tcx>, val: Value, from: Ty<'tcx>, to: Ty<'tcx>, signed: bool) -> Value {
296 let from = fx.cton_type(from).unwrap();
297 let to = fx.cton_type(to).unwrap();
301 if from.wider_or_equal(to) {
303 fx.bcx.ins().sextend(to, val)
305 fx.bcx.ins().uextend(to, val)
308 fx.bcx.ins().ireduce(to, val)
312 pub struct FunctionCx<'a, 'tcx: 'a> {
313 pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
314 pub module: &'a mut Module<CurrentBackend>,
315 pub def_id_fn_id_map: &'a mut HashMap<Instance<'tcx>, FuncId>,
316 pub instance: Instance<'tcx>,
317 pub mir: &'tcx Mir<'tcx>,
318 pub param_substs: &'tcx Substs<'tcx>,
319 pub bcx: FunctionBuilder<'a, Variable>,
320 pub ebb_map: HashMap<BasicBlock, Ebb>,
321 pub local_map: HashMap<Local, CPlace<'tcx>>,
324 impl<'a, 'tcx: 'a> LayoutOf for &'a FunctionCx<'a, 'tcx> {
326 type TyLayout = TyLayout<'tcx>;
328 fn layout_of(self, ty: Ty<'tcx>) -> TyLayout<'tcx> {
329 let ty = self.monomorphize(&ty);
330 self.tcx.layout_of(ParamEnv::reveal_all().and(&ty)).unwrap()
334 impl<'a, 'tcx> layout::HasTyCtxt<'tcx> for &'a FunctionCx<'a, 'tcx> {
335 fn tcx<'b>(&'b self) -> TyCtxt<'b, 'tcx, 'tcx> {
340 impl<'a, 'tcx> layout::HasDataLayout for &'a FunctionCx<'a, 'tcx> {
341 fn data_layout(&self) -> &layout::TargetDataLayout {
342 &self.tcx.data_layout
346 impl<'a, 'tcx> HasTargetSpec for &'a FunctionCx<'a, 'tcx> {
347 fn target_spec(&self) -> &Target {
348 &self.tcx.sess.target.target
352 impl<'a, 'tcx: 'a> FunctionCx<'a, 'tcx> {
353 pub fn monomorphize<T>(&self, value: &T) -> T
354 where T: TypeFoldable<'tcx>
356 self.tcx.subst_and_normalize_erasing_regions(
358 ty::ParamEnv::reveal_all(),
363 pub fn cton_type(&self, ty: Ty<'tcx>) -> Option<Type> {
364 cton_type_from_ty(self.monomorphize(&ty))
367 pub fn get_ebb(&self, bb: BasicBlock) -> Ebb {
368 *self.ebb_map.get(&bb).unwrap()
371 pub fn get_local_place(&mut self, local: Local) -> CPlace<'tcx> {
372 *self.local_map.get(&local).unwrap()
375 pub fn get_function_ref(&mut self, inst: Instance<'tcx>) -> FuncRef {
377 let module = &mut self.module;
378 let func_id = *self.def_id_fn_id_map.entry(inst).or_insert_with(|| {
379 let sig = cton_sig_from_instance(tcx, inst);
380 module.declare_function(&tcx.absolute_item_path_str(inst.def_id()), Linkage::Local, &sig).unwrap()
382 module.declare_func_in_func(func_id, &mut self.bcx.func)