]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc/middle/trans/base.rs
rollup merge of #17355 : gamazeps/issue17210
[rust.git] / src / librustc / middle / trans / base.rs
index dc2aa16eb728494a612c869615a18043e3fc099b..72e0401e7ab772b2a7e1f07a2845c2de1591733c 100644 (file)
@@ -75,7 +75,6 @@
 use middle::trans::type_of::*;
 use middle::trans::value::Value;
 use middle::ty;
-use middle::typeck;
 use util::common::indenter;
 use util::ppaux::{Repr, ty_to_string};
 use util::sha2::Sha256;
@@ -192,21 +191,13 @@ pub fn decl_fn(ccx: &CrateContext, name: &str, cc: llvm::CallConv,
     match ty::get(output).sty {
         // functions returning bottom may unwind, but can never return normally
         ty::ty_bot => {
-            unsafe {
-                llvm::LLVMAddFunctionAttribute(llfn,
-                                               llvm::FunctionIndex as c_uint,
-                                               llvm::NoReturnAttribute as uint64_t)
-            }
+            llvm::SetFunctionAttribute(llfn, llvm::NoReturnAttribute)
         }
         _ => {}
     }
 
     if ccx.tcx().sess.opts.cg.no_redzone {
-        unsafe {
-            llvm::LLVMAddFunctionAttribute(llfn,
-                                           llvm::FunctionIndex as c_uint,
-                                           llvm::NoRedZoneAttribute as uint64_t)
-        }
+        llvm::SetFunctionAttribute(llfn, llvm::NoRedZoneAttribute)
     }
 
     llvm::SetFunctionCallConv(llfn, cc);
@@ -383,14 +374,10 @@ pub fn malloc_raw_dyn<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     Result::new(r.bcx, PointerCast(r.bcx, r.val, llty_ptr))
 }
 
-pub fn malloc_raw_dyn_proc<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                                       t: ty::t, alloc_fn: LangItem)
-                                       -> Result<'blk, 'tcx> {
+pub fn malloc_raw_dyn_proc<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, t: ty::t) -> Result<'blk, 'tcx> {
     let _icx = push_ctxt("malloc_raw_dyn_proc");
     let ccx = bcx.ccx();
 
-    let langcall = require_alloc_fn(bcx, t, alloc_fn);
-
     // Grab the TypeRef type of ptr_ty.
     let ptr_ty = ty::mk_uniq(bcx.tcx(), t);
     let ptr_llty = type_of(ccx, ptr_ty);
@@ -399,18 +386,15 @@ pub fn malloc_raw_dyn_proc<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     let size = llsize_of(bcx.ccx(), llty);
     let llalign = C_uint(ccx, llalign_of_min(bcx.ccx(), llty) as uint);
 
-    // Allocate space:
-    let drop_glue = glue::get_drop_glue(ccx, ty::mk_uniq(bcx.tcx(), t));
-    let r = callee::trans_lang_call(
-        bcx,
-        langcall,
-        [
-            PointerCast(bcx, drop_glue, Type::glue_fn(ccx, Type::i8p(ccx)).ptr_to()),
-            size,
-            llalign
-        ],
-        None);
-    Result::new(r.bcx, PointerCast(r.bcx, r.val, ptr_llty))
+    // Allocate space and store the destructor pointer:
+    let Result {bcx: bcx, val: llbox} = malloc_raw_dyn(bcx, ptr_llty, t, size, llalign);
+    let dtor_ptr = GEPi(bcx, llbox, [0u, abi::box_field_drop_glue]);
+    let drop_glue_field_ty = type_of(ccx, ty::mk_nil_ptr(bcx.tcx()));
+    let drop_glue = PointerCast(bcx, glue::get_drop_glue(ccx, ty::mk_uniq(bcx.tcx(), t)),
+                                drop_glue_field_ty);
+    Store(bcx, drop_glue, dtor_ptr);
+
+    Result::new(bcx, llbox)
 }
 
 
@@ -547,8 +531,7 @@ pub fn get_res_dtor(ccx: &CrateContext,
         // Since we're in trans we don't care for any region parameters
         let ref substs = subst::Substs::erased(substs.types.clone());
 
-        let vtables = typeck::check::vtable::trans_resolve_method(ccx.tcx(), did.node, substs);
-        let (val, _) = monomorphize::monomorphic_fn(ccx, did, substs, vtables, None);
+        let (val, _) = monomorphize::monomorphic_fn(ccx, did, substs, None);
 
         val
     } else if did.krate == ast::LOCAL_CRATE {
@@ -1322,18 +1305,32 @@ pub fn make_return_slot_pointer(fcx: &FunctionContext, output_type: ty::t) -> Va
 }
 
 struct CheckForNestedReturnsVisitor {
-    found: bool
+    found: bool,
+    in_return: bool
+}
+
+impl CheckForNestedReturnsVisitor {
+    fn explicit() -> CheckForNestedReturnsVisitor {
+        CheckForNestedReturnsVisitor { found: false, in_return: false }
+    }
+    fn implicit() -> CheckForNestedReturnsVisitor {
+        CheckForNestedReturnsVisitor { found: false, in_return: true }
+    }
 }
 
-impl Visitor<bool> for CheckForNestedReturnsVisitor {
-    fn visit_expr(&mut self, e: &ast::Expr, in_return: bool) {
+impl<'v> Visitor<'v> for CheckForNestedReturnsVisitor {
+    fn visit_expr(&mut self, e: &ast::Expr) {
         match e.node {
-            ast::ExprRet(..) if in_return => {
-                self.found = true;
-                return;
+            ast::ExprRet(..) => {
+                if self.in_return {
+                    self.found = true;
+                } else {
+                    self.in_return = true;
+                    visit::walk_expr(self, e);
+                    self.in_return = false;
+                }
             }
-            ast::ExprRet(..) => visit::walk_expr(self, e, true),
-            _ => visit::walk_expr(self, e, in_return)
+            _ => visit::walk_expr(self, e)
         }
     }
 }
@@ -1342,11 +1339,11 @@ fn has_nested_returns(tcx: &ty::ctxt, id: ast::NodeId) -> bool {
     match tcx.map.find(id) {
         Some(ast_map::NodeItem(i)) => {
             match i.node {
-                ast::ItemFn(_, _, _, _, blk) => {
-                    let mut explicit = CheckForNestedReturnsVisitor { found: false };
-                    let mut implicit = CheckForNestedReturnsVisitor { found: false };
-                    visit::walk_item(&mut explicit, &*i, false);
-                    visit::walk_expr_opt(&mut implicit, blk.expr, true);
+                ast::ItemFn(_, _, _, _, ref blk) => {
+                    let mut explicit = CheckForNestedReturnsVisitor::explicit();
+                    let mut implicit = CheckForNestedReturnsVisitor::implicit();
+                    visit::walk_item(&mut explicit, &*i);
+                    visit::walk_expr_opt(&mut implicit, &blk.expr);
                     explicit.found || implicit.found
                 }
                 _ => tcx.sess.bug("unexpected item variant in has_nested_returns")
@@ -1354,13 +1351,13 @@ fn has_nested_returns(tcx: &ty::ctxt, id: ast::NodeId) -> bool {
         }
         Some(ast_map::NodeTraitItem(trait_method)) => {
             match *trait_method {
-                ast::ProvidedMethod(m) => {
+                ast::ProvidedMethod(ref m) => {
                     match m.node {
-                        ast::MethDecl(_, _, _, _, _, _, blk, _) => {
-                            let mut explicit = CheckForNestedReturnsVisitor { found: false };
-                            let mut implicit = CheckForNestedReturnsVisitor { found: false };
-                            visit::walk_method_helper(&mut explicit, &*m, false);
-                            visit::walk_expr_opt(&mut implicit, blk.expr, true);
+                        ast::MethDecl(_, _, _, _, _, _, ref blk, _) => {
+                            let mut explicit = CheckForNestedReturnsVisitor::explicit();
+                            let mut implicit = CheckForNestedReturnsVisitor::implicit();
+                            visit::walk_method_helper(&mut explicit, &**m);
+                            visit::walk_expr_opt(&mut implicit, &blk.expr);
                             explicit.found || implicit.found
                         }
                         ast::MethMac(_) => tcx.sess.bug("unexpanded macro")
@@ -1370,41 +1367,41 @@ fn has_nested_returns(tcx: &ty::ctxt, id: ast::NodeId) -> bool {
                     tcx.sess.bug("unexpected variant: required trait method \
                                   in has_nested_returns")
                 }
+                ast::TypeTraitItem(_) => {
+                    tcx.sess.bug("unexpected variant: type trait item in \
+                                  has_nested_returns")
+                }
             }
         }
-        Some(ast_map::NodeImplItem(ref ii)) => {
-            match **ii {
+        Some(ast_map::NodeImplItem(ii)) => {
+            match *ii {
                 ast::MethodImplItem(ref m) => {
                     match m.node {
-                        ast::MethDecl(_, _, _, _, _, _, blk, _) => {
-                            let mut explicit = CheckForNestedReturnsVisitor {
-                                found: false,
-                            };
-                            let mut implicit = CheckForNestedReturnsVisitor {
-                                found: false,
-                            };
-                            visit::walk_method_helper(&mut explicit,
-                                                      &**m,
-                                                      false);
-                            visit::walk_expr_opt(&mut implicit,
-                                                 blk.expr,
-                                                 true);
+                        ast::MethDecl(_, _, _, _, _, _, ref blk, _) => {
+                            let mut explicit = CheckForNestedReturnsVisitor::explicit();
+                            let mut implicit = CheckForNestedReturnsVisitor::implicit();
+                            visit::walk_method_helper(&mut explicit, &**m);
+                            visit::walk_expr_opt(&mut implicit, &blk.expr);
                             explicit.found || implicit.found
                         }
                         ast::MethMac(_) => tcx.sess.bug("unexpanded macro")
                     }
                 }
+                ast::TypeImplItem(_) => {
+                    tcx.sess.bug("unexpected variant: type impl item in \
+                                  has_nested_returns")
+                }
             }
         }
         Some(ast_map::NodeExpr(e)) => {
             match e.node {
-                ast::ExprFnBlock(_, _, blk) |
-                ast::ExprProc(_, blk) |
-                ast::ExprUnboxedFn(_, _, _, blk) => {
-                    let mut explicit = CheckForNestedReturnsVisitor { found: false };
-                    let mut implicit = CheckForNestedReturnsVisitor { found: false };
-                    visit::walk_expr(&mut explicit, &*e, false);
-                    visit::walk_expr_opt(&mut implicit, blk.expr, true);
+                ast::ExprFnBlock(_, _, ref blk) |
+                ast::ExprProc(_, ref blk) |
+                ast::ExprUnboxedFn(_, _, _, ref blk) => {
+                    let mut explicit = CheckForNestedReturnsVisitor::explicit();
+                    let mut implicit = CheckForNestedReturnsVisitor::implicit();
+                    visit::walk_expr(&mut explicit, e);
+                    visit::walk_expr_opt(&mut implicit, &blk.expr);
                     explicit.found || implicit.found
                 }
                 _ => tcx.sess.bug("unexpected expr variant in has_nested_returns")
@@ -1463,7 +1460,6 @@ pub fn new_fn_ctxt<'a, 'tcx>(ccx: &'a CrateContext<'a, 'tcx>,
           needs_ret_allocas: nested_returns,
           personality: Cell::new(None),
           caller_expects_out_pointer: uses_outptr,
-          llargs: RefCell::new(NodeMap::new()),
           lllocals: RefCell::new(NodeMap::new()),
           llupvars: RefCell::new(NodeMap::new()),
           id: id,
@@ -1634,7 +1630,7 @@ fn copy_args_to_allocas<'blk, 'tcx>(fcx: &FunctionContext<'blk, 'tcx>,
 
     let arg_scope_id = cleanup::CustomScope(arg_scope);
 
-    for (i, arg_datum) in arg_datums.move_iter().enumerate() {
+    for (i, arg_datum) in arg_datums.into_iter().enumerate() {
         // For certain mode/type combinations, the raw llarg values are passed
         // by value.  However, within the fn body itself, we want to always
         // have all locals and arguments be by-ref so that we can cancel the
@@ -1643,7 +1639,7 @@ fn copy_args_to_allocas<'blk, 'tcx>(fcx: &FunctionContext<'blk, 'tcx>,
         // This alloca should be optimized away by LLVM's mem-to-reg pass in
         // the event it's not truly needed.
 
-        bcx = _match::store_arg(bcx, args[i].pat, arg_datum, arg_scope_id);
+        bcx = _match::store_arg(bcx, &*args[i].pat, arg_datum, arg_scope_id);
 
         if fcx.ccx.sess().opts.debuginfo == FullDebugInfo {
             debuginfo::create_argument_metadata(bcx, &args[i]);
@@ -1665,7 +1661,7 @@ fn copy_unboxed_closure_args_to_allocas<'blk, 'tcx>(
 
     assert_eq!(arg_datums.len(), 1);
 
-    let arg_datum = arg_datums.move_iter().next().unwrap();
+    let arg_datum = arg_datums.into_iter().next().unwrap();
 
     // Untuple the rest of the arguments.
     let tuple_datum =
@@ -1695,7 +1691,7 @@ fn copy_unboxed_closure_args_to_allocas<'blk, 'tcx>(
                           tuple_element_datum.to_rvalue_datum(bcx,
                                                               "arg"));
         bcx = _match::store_arg(bcx,
-                                args[j].pat,
+                                &*args[j].pat,
                                 tuple_element_datum,
                                 arg_scope_id);
 
@@ -2002,7 +1998,7 @@ pub fn trans_named_tuple_constructor<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
     if !type_is_zero_size(ccx, result_ty) {
         match args {
             callee::ArgExprs(exprs) => {
-                let fields = exprs.iter().map(|x| *x).enumerate().collect::<Vec<_>>();
+                let fields = exprs.iter().map(|x| &**x).enumerate().collect::<Vec<_>>();
                 bcx = expr::trans_adt(bcx, result_ty, disr, fields.as_slice(),
                                       None, expr::SaveIn(llresult));
             }
@@ -2065,7 +2061,7 @@ fn trans_enum_variant_or_tuple_like_struct(ccx: &CrateContext,
     if !type_is_zero_size(fcx.ccx, result_ty) {
         let dest = fcx.get_ret_slot(bcx, result_ty, "eret_slot");
         let repr = adt::represent_type(ccx, result_ty);
-        for (i, arg_datum) in arg_datums.move_iter().enumerate() {
+        for (i, arg_datum) in arg_datums.into_iter().enumerate() {
             let lldestptr = adt::trans_field_ptr(bcx,
                                                  &*repr,
                                                  dest,
@@ -2135,8 +2131,8 @@ pub struct TransItemVisitor<'a, 'tcx: 'a> {
     pub ccx: &'a CrateContext<'a, 'tcx>,
 }
 
-impl<'a, 'tcx> Visitor<()> for TransItemVisitor<'a, 'tcx> {
-    fn visit_item(&mut self, i: &ast::Item, _:()) {
+impl<'a, 'tcx, 'v> Visitor<'v> for TransItemVisitor<'a, 'tcx> {
+    fn visit_item(&mut self, i: &ast::Item) {
         trans_item(self.ccx, i);
     }
 }
@@ -2236,7 +2232,7 @@ pub fn trans_item(ccx: &CrateContext, item: &ast::Item) {
         // Be sure to travel more than just one layer deep to catch nested
         // items in blocks and such.
         let mut v = TransItemVisitor{ ccx: ccx };
-        v.visit_block(&**body, ());
+        v.visit_block(&**body);
       }
       ast::ItemImpl(ref generics, _, _, ref impl_items) => {
         meth::trans_impl(ccx,
@@ -2254,7 +2250,7 @@ pub fn trans_item(ccx: &CrateContext, item: &ast::Item) {
       ast::ItemStatic(_, m, ref expr) => {
           // Recurse on the expression to catch items in blocks
           let mut v = TransItemVisitor{ ccx: ccx };
-          v.visit_expr(&**expr, ());
+          v.visit_expr(&**expr);
 
           let trans_everywhere = attr::requests_inline(item.attrs.as_slice());
           for (ref ccx, is_origin) in ccx.maybe_iter(!from_external && trans_everywhere) {
@@ -2293,7 +2289,7 @@ pub fn trans_item(ccx: &CrateContext, item: &ast::Item) {
         // methods with items will not get translated and will cause ICE's when
         // metadata time comes around.
         let mut v = TransItemVisitor{ ccx: ccx };
-        visit::walk_item(&mut v, item, ());
+        visit::walk_item(&mut v, item);
       }
       _ => {/* fall through */ }
     }
@@ -2782,19 +2778,24 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef {
         ast_map::NodeTraitItem(trait_method) => {
             debug!("get_item_val(): processing a NodeTraitItem");
             match *trait_method {
-                ast::RequiredMethod(_) => {
-                    ccx.sess().bug("unexpected variant: required trait method in \
-                                   get_item_val()");
+                ast::RequiredMethod(_) | ast::TypeTraitItem(_) => {
+                    ccx.sess().bug("unexpected variant: required trait \
+                                    method in get_item_val()");
                 }
-                ast::ProvidedMethod(m) => {
-                    register_method(ccx, id, &*m)
+                ast::ProvidedMethod(ref m) => {
+                    register_method(ccx, id, &**m)
                 }
             }
         }
 
         ast_map::NodeImplItem(ii) => {
             match *ii {
-                ast::MethodImplItem(m) => register_method(ccx, id, &*m),
+                ast::MethodImplItem(ref m) => register_method(ccx, id, &**m),
+                ast::TypeImplItem(ref typedef) => {
+                    ccx.sess().span_bug(typedef.span,
+                                        "unexpected variant: required impl \
+                                         method in get_item_val()")
+                }
             }
         }
 
@@ -3036,9 +3037,10 @@ fn next(&mut self) -> Option<ValueRef> {
     }
 }
 
-pub fn trans_crate(krate: ast::Crate,
-                   analysis: CrateAnalysis) -> (ty::ctxt, CrateTranslation) {
+pub fn trans_crate<'tcx>(analysis: CrateAnalysis<'tcx>)
+                         -> (ty::ctxt<'tcx>, CrateTranslation) {
     let CrateAnalysis { ty_cx: tcx, exp_map2, reachable, name, .. } = analysis;
+    let krate = tcx.map.krate();
 
     // Before we touch LLVM, make sure that multithreading is enabled.
     unsafe {
@@ -3058,7 +3060,7 @@ pub fn trans_crate(krate: ast::Crate,
         }
     }
 
-    let link_meta = link::build_link_meta(&tcx.sess, &krate, name);
+    let link_meta = link::build_link_meta(&tcx.sess, krate, name);
 
     let codegen_units = tcx.sess.opts.cg.codegen_units;
     let shared_ccx = SharedCrateContext::new(link_meta.crate_name.as_slice(),
@@ -3090,7 +3092,7 @@ pub fn trans_crate(krate: ast::Crate,
     }
 
     // Translate the metadata.
-    let metadata = write_metadata(&shared_ccx, &krate);
+    let metadata = write_metadata(&shared_ccx, krate);
 
     if shared_ccx.sess().trans_stats() {
         let stats = shared_ccx.stats();
@@ -3135,7 +3137,7 @@ pub fn trans_crate(krate: ast::Crate,
     // the final product, so LTO needs to preserve them.
     shared_ccx.sess().cstore.iter_crate_data(|cnum, _| {
         let syms = csearch::get_reachable_extern_fns(&shared_ccx.sess().cstore, cnum);
-        reachable.extend(syms.move_iter().map(|did| {
+        reachable.extend(syms.into_iter().map(|did| {
             csearch::get_symbol(&shared_ccx.sess().cstore, did)
         }));
     });