]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc_trans/trans/mir/rvalue.rs
hir, mir: Separate HIR expressions / MIR operands from InlineAsm.
[rust.git] / src / librustc_trans / trans / mir / rvalue.rs
index 541df43b49b9a19f32f0e9aeb95799ff75739def..17c8aef244bb95c04a8c6d2d3505864698bda25d 100644 (file)
 use llvm::ValueRef;
 use rustc::middle::ty::{self, Ty};
 use middle::ty::cast::{CastTy, IntTy};
+use middle::const_eval::ConstVal;
+use rustc_const_eval::ConstInt;
 use rustc::mir::repr as mir;
 
 use trans::asm;
 use trans::base;
-use trans::common::{self, BlockAndBuilder, Result};
+use trans::callee::Callee;
+use trans::common::{self, C_uint, BlockAndBuilder, Result};
+use trans::datum::{Datum, Lvalue};
 use trans::debuginfo::DebugLoc;
 use trans::declare;
-use trans::expr;
 use trans::adt;
 use trans::machine;
 use trans::type_::Type;
 use trans::type_of;
 use trans::tvec;
+use trans::value::Value;
 use trans::Disr;
 
 use super::MirContext;
 use super::operand::{OperandRef, OperandValue};
-use super::lvalue::LvalueRef;
+use super::lvalue::{LvalueRef, get_dataptr, get_meta};
 
 impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
     pub fn trans_rvalue(&mut self,
@@ -37,9 +41,8 @@ pub fn trans_rvalue(&mut self,
                         rvalue: &mir::Rvalue<'tcx>)
                         -> BlockAndBuilder<'bcx, 'tcx>
     {
-        debug!("trans_rvalue(dest.llval={}, rvalue={:?})",
-               bcx.val_to_string(dest.llval),
-               rvalue);
+        debug!("trans_rvalue(dest.llval={:?}, rvalue={:?})",
+               Value(dest.llval), rvalue);
 
         match *rvalue {
            mir::Rvalue::Use(ref operand) => {
@@ -51,7 +54,7 @@ pub fn trans_rvalue(&mut self,
                bcx
            }
 
-            mir::Rvalue::Cast(mir::CastKind::Unsize, ref operand, cast_ty) => {
+            mir::Rvalue::Cast(mir::CastKind::Unsize, ref source, cast_ty) => {
                 if common::type_is_fat_ptr(bcx.tcx(), cast_ty) {
                     // into-coerce of a thin pointer to a fat pointer - just
                     // use the operand path.
@@ -64,7 +67,7 @@ pub fn trans_rvalue(&mut self,
                 // this to be eliminated by MIR translation, but
                 // `CoerceUnsized` can be passed by a where-clause,
                 // so the (generic) MIR may not be able to expand it.
-                let operand = self.trans_operand(&bcx, operand);
+                let operand = self.trans_operand(&bcx, source);
                 bcx.with_block(|bcx| {
                     match operand.val {
                         OperandValue::FatPtr(..) => unreachable!(),
@@ -89,14 +92,16 @@ pub fn trans_rvalue(&mut self,
                         }
                     }
                 });
+                self.set_operand_dropped(&bcx, source);
                 bcx
             }
 
             mir::Rvalue::Repeat(ref elem, ref count) => {
                 let tr_elem = self.trans_operand(&bcx, elem);
-                let size = self.trans_constval(&bcx, &count.value, count.ty).immediate();
+                let count = ConstVal::Integral(ConstInt::Usize(count.value));
+                let size = self.trans_constval(&bcx, &count, bcx.tcx().types.usize).immediate();
+                let base = get_dataptr(&bcx, dest.llval);
                 let bcx = bcx.map_block(|block| {
-                    let base = expr::get_dataptr(block, dest.llval);
                     tvec::iter_vec_raw(block, base, tr_elem.ty, size, |block, llslot, _| {
                         self.store_operand_direct(block, llslot, tr_elem);
                         block
@@ -119,15 +124,39 @@ pub fn trans_rvalue(&mut self,
                             // Do not generate stores and GEPis for zero-sized fields.
                             if !common::type_is_zero_size(bcx.ccx(), op.ty) {
                                 let val = adt::MaybeSizedValue::sized(dest.llval);
-                                let lldest_i = bcx.with_block(|bcx| {
-                                    adt::trans_field_ptr(bcx, &repr, val, disr, i)
-                                });
+                                let lldest_i = adt::trans_field_ptr_builder(&bcx, &repr,
+                                                                            val, disr, i);
                                 self.store_operand(&bcx, lldest_i, op);
-                                self.set_operand_dropped(&bcx, operand);
                             }
+                            self.set_operand_dropped(&bcx, operand);
                         }
                     },
                     _ => {
+                        // FIXME Shouldn't need to manually trigger closure instantiations.
+                        if let mir::AggregateKind::Closure(def_id, substs) = *kind {
+                            use rustc_front::hir;
+                            use syntax::ast::DUMMY_NODE_ID;
+                            use syntax::codemap::DUMMY_SP;
+                            use syntax::ptr::P;
+                            use trans::closure;
+
+                            closure::trans_closure_expr(closure::Dest::Ignore(bcx.ccx()),
+                                                        &hir::FnDecl {
+                                                            inputs: P::new(),
+                                                            output: hir::NoReturn(DUMMY_SP),
+                                                            variadic: false
+                                                        },
+                                                        &hir::Block {
+                                                            stmts: P::new(),
+                                                            expr: None,
+                                                            id: DUMMY_NODE_ID,
+                                                            rules: hir::DefaultBlock,
+                                                            span: DUMMY_SP
+                                                        },
+                                                        DUMMY_NODE_ID, def_id,
+                                                        &bcx.monomorphize(substs));
+                        }
+
                         for (i, operand) in operands.iter().enumerate() {
                             let op = self.trans_operand(&bcx, operand);
                             // Do not generate stores and GEPis for zero-sized fields.
@@ -137,8 +166,8 @@ pub fn trans_rvalue(&mut self,
                                 // not be structs but arrays.
                                 let dest = bcx.gepi(dest.llval, &[0, i]);
                                 self.store_operand(&bcx, dest, op);
-                                self.set_operand_dropped(&bcx, operand);
                             }
+                            self.set_operand_dropped(&bcx, operand);
                         }
                     }
                 }
@@ -148,26 +177,42 @@ pub fn trans_rvalue(&mut self,
             mir::Rvalue::Slice { ref input, from_start, from_end } => {
                 let ccx = bcx.ccx();
                 let input = self.trans_lvalue(&bcx, input);
-                let (llbase, lllen) = bcx.with_block(|bcx| {
-                    tvec::get_base_and_len(bcx,
-                                           input.llval,
-                                           input.ty.to_ty(bcx.tcx()))
-                });
-                let llbase1 = bcx.gepi(llbase, &[from_start]);
-                let adj = common::C_uint(ccx, from_start + from_end);
+                let ty = input.ty.to_ty(bcx.tcx());
+                let (llbase1, lllen) = match ty.sty {
+                    ty::TyArray(_, n) => {
+                        (bcx.gepi(input.llval, &[0, from_start]), C_uint(ccx, n))
+                    }
+                    ty::TySlice(_) | ty::TyStr => {
+                        (bcx.gepi(input.llval, &[from_start]), input.llextra)
+                    }
+                    _ => unreachable!("cannot slice {}", ty)
+                };
+                let adj = C_uint(ccx, from_start + from_end);
                 let lllen1 = bcx.sub(lllen, adj);
-                let (lladdrdest, llmetadest) = bcx.with_block(|bcx| {
-                    (expr::get_dataptr(bcx, dest.llval), expr::get_meta(bcx, dest.llval))
-                });
-                bcx.store(llbase1, lladdrdest);
-                bcx.store(lllen1, llmetadest);
+                bcx.store(llbase1, get_dataptr(&bcx, dest.llval));
+                bcx.store(lllen1, get_meta(&bcx, dest.llval));
                 bcx
             }
 
-            mir::Rvalue::InlineAsm(ref inline_asm) => {
-                bcx.map_block(|bcx| {
-                    asm::trans_inline_asm(bcx, inline_asm)
-                })
+            mir::Rvalue::InlineAsm { ref asm, ref outputs, ref inputs } => {
+                let outputs = outputs.iter().map(|output| {
+                    let lvalue = self.trans_lvalue(&bcx, output);
+                    Datum::new(lvalue.llval, lvalue.ty.to_ty(bcx.tcx()),
+                               Lvalue::new("out"))
+                }).collect();
+
+                let input_vals = inputs.iter().map(|input| {
+                    self.trans_operand(&bcx, input).immediate()
+                }).collect();
+
+                bcx.with_block(|bcx| {
+                    asm::trans_inline_asm(bcx, asm, outputs, input_vals);
+                });
+
+                for input in inputs {
+                    self.set_operand_dropped(&bcx, input);
+                }
+                bcx
             }
 
             _ => {
@@ -187,15 +232,26 @@ pub fn trans_rvalue_operand(&mut self,
         assert!(rvalue_creates_operand(rvalue), "cannot trans {:?} to operand", rvalue);
 
         match *rvalue {
-            mir::Rvalue::Cast(ref kind, ref operand, cast_ty) => {
-                let operand = self.trans_operand(&bcx, operand);
-                debug!("cast operand is {}", operand.repr(&bcx));
+            mir::Rvalue::Cast(ref kind, ref source, cast_ty) => {
+                let operand = self.trans_operand(&bcx, source);
+                debug!("cast operand is {:?}", operand);
                 let cast_ty = bcx.monomorphize(&cast_ty);
 
                 let val = match *kind {
-                    mir::CastKind::ReifyFnPointer |
+                    mir::CastKind::ReifyFnPointer => {
+                        match operand.ty.sty {
+                            ty::TyFnDef(def_id, substs, _) => {
+                                OperandValue::Immediate(
+                                    Callee::def(bcx.ccx(), def_id, substs)
+                                        .reify(bcx.ccx()).val)
+                            }
+                            _ => {
+                                unreachable!("{} cannot be reified to a fn ptr", operand.ty)
+                            }
+                        }
+                    }
                     mir::CastKind::UnsafeFnPointer => {
-                        // these are no-ops at the LLVM level
+                        // this is a no-op at the LLVM level
                         operand.val
                     }
                     mir::CastKind::Unsize => {
@@ -210,6 +266,7 @@ pub fn trans_rvalue_operand(&mut self,
                                 // example,
                                 //   &'a fmt::Debug+Send => &'a fmt::Debug,
                                 // and is a no-op at the LLVM level
+                                self.set_operand_dropped(&bcx, source);
                                 operand.val
                             }
                             OperandValue::Immediate(lldata) => {
@@ -218,12 +275,13 @@ pub fn trans_rvalue_operand(&mut self,
                                     base::unsize_thin_ptr(bcx, lldata,
                                                           operand.ty, cast_ty)
                                 });
+                                self.set_operand_dropped(&bcx, source);
                                 OperandValue::FatPtr(lldata, llextra)
                             }
                             OperandValue::Ref(_) => {
                                 bcx.sess().bug(
-                                    &format!("by-ref operand {} in trans_rvalue_operand",
-                                             operand.repr(&bcx)));
+                                    &format!("by-ref operand {:?} in trans_rvalue_operand",
+                                             operand));
                             }
                         }
                     }
@@ -231,17 +289,14 @@ pub fn trans_rvalue_operand(&mut self,
                         debug_assert!(common::type_is_immediate(bcx.ccx(), cast_ty));
                         let r_t_in = CastTy::from_ty(operand.ty).expect("bad input type for cast");
                         let r_t_out = CastTy::from_ty(cast_ty).expect("bad output type for cast");
-                        let ll_t_in = type_of::arg_type_of(bcx.ccx(), operand.ty);
-                        let ll_t_out = type_of::arg_type_of(bcx.ccx(), cast_ty);
-                        let (llval, ll_t_in, signed) = if let CastTy::Int(IntTy::CEnum) = r_t_in {
+                        let ll_t_in = type_of::immediate_type_of(bcx.ccx(), operand.ty);
+                        let ll_t_out = type_of::immediate_type_of(bcx.ccx(), cast_ty);
+                        let llval = operand.immediate();
+                        let signed = if let CastTy::Int(IntTy::CEnum) = r_t_in {
                             let repr = adt::represent_type(bcx.ccx(), operand.ty);
-                            let llval = operand.immediate();
-                            let discr = bcx.with_block(|bcx| {
-                                adt::trans_get_discr(bcx, &repr, llval, None, true)
-                            });
-                            (discr, common::val_ty(discr), adt::is_discr_signed(&repr))
+                            adt::is_discr_signed(&repr)
                         } else {
-                            (operand.immediate(), ll_t_in, operand.ty.is_signed())
+                            operand.ty.is_signed()
                         };
 
                         let newval = match (r_t_in, r_t_out) {
@@ -293,8 +348,8 @@ pub fn trans_rvalue_operand(&mut self,
                         OperandValue::Immediate(newval)
                     }
                     mir::CastKind::Misc => { // Casts from a fat-ptr.
-                        let ll_cast_ty = type_of::arg_type_of(bcx.ccx(), cast_ty);
-                        let ll_from_ty = type_of::arg_type_of(bcx.ccx(), operand.ty);
+                        let ll_cast_ty = type_of::immediate_type_of(bcx.ccx(), cast_ty);
+                        let ll_from_ty = type_of::immediate_type_of(bcx.ccx(), operand.ty);
                         if let OperandValue::FatPtr(data_ptr, meta_ptr) = operand.val {
                             if common::type_is_fat_ptr(bcx.tcx(), cast_ty) {
                                 let ll_cft = ll_cast_ty.field_types();
@@ -408,7 +463,7 @@ pub fn trans_rvalue_operand(&mut self,
                 let llty = type_of::type_of(bcx.ccx(), content_ty);
                 let llsize = machine::llsize_of(bcx.ccx(), llty);
                 let align = type_of::align_of(bcx.ccx(), content_ty);
-                let llalign = common::C_uint(bcx.ccx(), align);
+                let llalign = C_uint(bcx.ccx(), align);
                 let llty_ptr = llty.ptr_to();
                 let box_ty = bcx.tcx().mk_box(content_ty);
                 let mut llval = None;
@@ -433,7 +488,7 @@ pub fn trans_rvalue_operand(&mut self,
             mir::Rvalue::Repeat(..) |
             mir::Rvalue::Aggregate(..) |
             mir::Rvalue::Slice { .. } |
-            mir::Rvalue::InlineAsm(..) => {
+            mir::Rvalue::InlineAsm { .. } => {
                 bcx.tcx().sess.bug(&format!("cannot generate operand from rvalue {:?}", rvalue));
             }
         }
@@ -496,15 +551,14 @@ pub fn trans_scalar_binop(&mut self,
                 if use_fmod {
                     let f64t = Type::f64(bcx.ccx());
                     let fty = Type::func(&[f64t, f64t], &f64t);
-                    let llfn = declare::declare_cfn(bcx.ccx(), "fmod", fty,
-                                                    tcx.types.f64);
+                    let llfn = declare::declare_cfn(bcx.ccx(), "fmod", fty);
                     if input_ty == tcx.types.f32 {
                         let lllhs = bcx.fpext(lhs, f64t);
                         let llrhs = bcx.fpext(rhs, f64t);
-                        let llres = bcx.call(llfn, &[lllhs, llrhs], None, None);
+                        let llres = bcx.call(llfn, &[lllhs, llrhs], None);
                         bcx.fptrunc(llres, Type::f32(bcx.ccx()))
                     } else {
-                        bcx.call(llfn, &[lhs, rhs], None, None)
+                        bcx.call(llfn, &[lhs, rhs], None)
                     }
                 } else {
                     bcx.frem(lhs, rhs)
@@ -558,7 +612,7 @@ pub fn rvalue_creates_operand<'tcx>(rvalue: &mir::Rvalue<'tcx>) -> bool {
         mir::Rvalue::Repeat(..) |
         mir::Rvalue::Aggregate(..) |
         mir::Rvalue::Slice { .. } |
-        mir::Rvalue::InlineAsm(..) =>
+        mir::Rvalue::InlineAsm { .. } =>
             false,
     }