(index<- )        ./librustc/middle/trans/inline.rs

    git branch:    * master           5200215 auto merge of #14035 : alexcrichton/rust/experimental, r=huonw
    modified:    Fri May  9 13:02:28 2014
   1  // Copyright 2012 The Rust Project Developers. See the COPYRIGHT
   2  // file at the top-level directory of this distribution and at
   3  // http://rust-lang.org/COPYRIGHT.
   4  //
   5  // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
   6  // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
   7  // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
   8  // option. This file may not be copied, modified, or distributed
   9  // except according to those terms.
  10  
  11  use lib::llvm::{AvailableExternallyLinkage, SetLinkage};
  12  use metadata::csearch;
  13  use middle::astencode;
  14  use middle::trans::base::{push_ctxt, trans_item, get_item_val, trans_fn};
  15  use middle::trans::common::*;
  16  use middle::ty;
  17  
  18  use syntax::ast;
  19  use syntax::ast_util::local_def;
  20  use syntax::attr;
  21  
  22  pub fn maybe_instantiate_inline(ccx: &CrateContext, fn_idast::DefId)
  23      -> ast::DefId {
  24      let _icx = push_ctxt("maybe_instantiate_inline");
  25      match ccx.external.borrow().find(&fn_id) {
  26          Some(&Some(node_id)) => {
  27              // Already inline
  28              debug!("maybe_instantiate_inline({}): already inline as node id {}",
  29                     ty::item_path_str(ccx.tcx(), fn_id), node_id);
  30              return local_def(node_id);
  31          }
  32          Some(&None) => {
  33              return fn_id; // Not inlinable
  34          }
  35          None => {
  36              // Not seen yet
  37          }
  38      }
  39  
  40      let csearch_result =
  41          csearch::maybe_get_item_ast(
  42              ccx.tcx(), fn_id,
  43              |a,b,c,d| astencode::decode_inlined_item(a, b, c, d));
  44      return match csearch_result {
  45          csearch::not_found => {
  46              ccx.external.borrow_mut().insert(fn_id, None);
  47              fn_id
  48          }
  49          csearch::found(ast::IIItem(item)) => {
  50              ccx.external.borrow_mut().insert(fn_id, Some(item.id));
  51              ccx.external_srcs.borrow_mut().insert(item.id, fn_id);
  52  
  53              ccx.stats.n_inlines.set(ccx.stats.n_inlines.get() + 1);
  54              trans_item(ccx, item);
  55  
  56              // We're bringing an external global into this crate, but we don't
  57              // want to create two copies of the global. If we do this, then if
  58              // you take the address of the global in two separate crates you get
  59              // two different addresses. This is bad for things like conditions,
  60              // but it could possibly have other adverse side effects. We still
  61              // want to achieve the optimizations related to this global,
  62              // however, so we use the available_externally linkage which llvm
  63              // provides
  64              match item.node {
  65                  ast::ItemStatic(..) => {
  66                      let g = get_item_val(ccx, item.id);
  67                      // see the comment in get_item_val() as to why this check is
  68                      // performed here.
  69                      if !attr::contains_name(item.attrs.as_slice(),
  70                                              "address_insignificant") {
  71                          SetLinkage(g, AvailableExternallyLinkage);
  72                      }
  73                  }
  74                  _ => {}
  75              }
  76  
  77              local_def(item.id)
  78          }
  79          csearch::found(ast::IIForeign(item)) => {
  80              ccx.external.borrow_mut().insert(fn_id, Some(item.id));
  81              ccx.external_srcs.borrow_mut().insert(item.id, fn_id);
  82              local_def(item.id)
  83          }
  84          csearch::found_parent(parent_id, ast::IIItem(item)) => {
  85              ccx.external.borrow_mut().insert(parent_id, Some(item.id));
  86              ccx.external_srcs.borrow_mut().insert(item.id, parent_id);
  87  
  88            let mut my_id = 0;
  89            match item.node {
  90              ast::ItemEnum(_, _) => {
  91                let vs_here = ty::enum_variants(ccx.tcx(), local_def(item.id));
  92                let vs_there = ty::enum_variants(ccx.tcx(), parent_id);
  93                for (here, there) in vs_here.iter().zip(vs_there.iter()) {
  94                    if there.id == fn_id { my_id = here.id.node; }
  95                    ccx.external.borrow_mut().insert(there.id, Some(here.id.node));
  96                }
  97              }
  98              ast::ItemStruct(ref struct_def, _) => {
  99                match struct_def.ctor_id {
 100                  None => {}
 101                  Some(ctor_id) => {
 102                      ccx.external.borrow_mut().insert(fn_id, Some(ctor_id));
 103                      my_id = ctor_id;
 104                  }
 105                }
 106              }
 107              _ => ccx.sess().bug("maybe_instantiate_inline: item has a \
 108                                   non-enum, non-struct parent")
 109            }
 110            trans_item(ccx, item);
 111            local_def(my_id)
 112          }
 113          csearch::found_parent(_, _) => {
 114              ccx.sess().bug("maybe_get_item_ast returned a found_parent \
 115               with a non-item parent");
 116          }
 117          csearch::found(ast::IIMethod(impl_did, is_provided, mth)) => {
 118              ccx.external.borrow_mut().insert(fn_id, Some(mth.id));
 119              ccx.external_srcs.borrow_mut().insert(mth.id, fn_id);
 120  
 121            ccx.stats.n_inlines.set(ccx.stats.n_inlines.get() + 1);
 122  
 123            // If this is a default method, we can't look up the
 124            // impl type. But we aren't going to translate anyways, so don't.
 125            if is_provided { return local_def(mth.id); }
 126  
 127              let impl_tpt = ty::lookup_item_type(ccx.tcx(), impl_did);
 128              let num_type_params =
 129                  impl_tpt.generics.type_param_defs().len() +
 130                  mth.generics.ty_params.len();
 131  
 132            if num_type_params == 0 {
 133                let llfn = get_item_val(ccx, mth.id);
 134                trans_fn(ccx, mth.decl, mth.body, llfn, None, mth.id, []);
 135            }
 136            local_def(mth.id)
 137          }
 138      };
 139  }