1 // Copyright 2014 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.
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.
11 use llvm
::{AvailableExternallyLinkage, InternalLinkage, SetLinkage}
;
12 use metadata
::csearch
;
13 use middle
::astencode
;
14 use middle
::subst
::Substs
;
15 use trans
::base
::{push_ctxt, trans_item, get_item_val, trans_fn}
;
20 use syntax
::ast_util
::{local_def, PostExpansionMethod}
;
22 fn instantiate_inline(ccx
: &CrateContext
, fn_id
: ast
::DefId
)
23 -> Option
<ast
::DefId
> {
24 let _icx
= push_ctxt("maybe_instantiate_inline");
25 match ccx
.external().borrow().get(&fn_id
) {
26 Some(&Some(node_id
)) => {
28 debug
!("maybe_instantiate_inline({}): already inline as node id {}",
29 ty
::item_path_str(ccx
.tcx(), fn_id
), node_id
);
30 return Some(local_def(node_id
));
33 return None
; // Not inlinable
41 csearch
::maybe_get_item_ast(
43 box |a
,b
,c
,d
| astencode
::decode_inlined_item(a
, b
, c
, d
));
45 let inline_def
= match csearch_result
{
46 csearch
::FoundAst
::NotFound
=> {
47 ccx
.external().borrow_mut().insert(fn_id
, None
);
50 csearch
::FoundAst
::Found(&ast
::IIItem(ref item
)) => {
51 ccx
.external().borrow_mut().insert(fn_id
, Some(item
.id
));
52 ccx
.external_srcs().borrow_mut().insert(item
.id
, fn_id
);
54 ccx
.stats().n_inlines
.set(ccx
.stats().n_inlines
.get() + 1);
55 trans_item(ccx
, &**item
);
57 let linkage
= match item
.node
{
58 ast
::ItemFn(_
, _
, _
, ref generics
, _
) => {
59 if generics
.is_type_parameterized() {
60 // Generics have no symbol, so they can't be given any
64 if ccx
.sess().opts
.cg
.codegen_units
== 1 {
65 // We could use AvailableExternallyLinkage here,
66 // but InternalLinkage allows LLVM to optimize more
67 // aggressively (at the cost of sometimes
71 // With multiple compilation units, duplicated code
72 // is more of a problem. Also, `codegen_units > 1`
73 // means the user is okay with losing some
75 Some(AvailableExternallyLinkage
)
79 ast
::ItemConst(..) => None
,
85 let g
= get_item_val(ccx
, item
.id
);
86 SetLinkage(g
, linkage
);
93 csearch
::FoundAst
::Found(&ast
::IIForeign(ref item
)) => {
94 ccx
.external().borrow_mut().insert(fn_id
, Some(item
.id
));
95 ccx
.external_srcs().borrow_mut().insert(item
.id
, fn_id
);
98 csearch
::FoundAst
::FoundParent(parent_id
, &ast
::IIItem(ref item
)) => {
99 ccx
.external().borrow_mut().insert(parent_id
, Some(item
.id
));
100 ccx
.external_srcs().borrow_mut().insert(item
.id
, parent_id
);
104 ast
::ItemEnum(_
, _
) => {
105 let vs_here
= ty
::enum_variants(ccx
.tcx(), local_def(item
.id
));
106 let vs_there
= ty
::enum_variants(ccx
.tcx(), parent_id
);
107 for (here
, there
) in vs_here
.iter().zip(vs_there
.iter()) {
108 if there
.id
== fn_id { my_id = here.id.node; }
109 ccx
.external().borrow_mut().insert(there
.id
, Some(here
.id
.node
));
112 ast
::ItemStruct(ref struct_def
, _
) => {
113 match struct_def
.ctor_id
{
116 ccx
.external().borrow_mut().insert(fn_id
, Some(ctor_id
));
121 _
=> ccx
.sess().bug("maybe_instantiate_inline: item has a \
122 non-enum, non-struct parent")
124 trans_item(ccx
, &**item
);
127 csearch
::FoundAst
::FoundParent(_
, _
) => {
128 ccx
.sess().bug("maybe_get_item_ast returned a FoundParent \
129 with a non-item parent");
131 csearch
::FoundAst
::Found(&ast
::IITraitItem(_
, ref trait_item
)) => {
133 ast
::RequiredMethod(_
) => ccx
.sess().bug("found RequiredMethod IITraitItem"),
134 ast
::ProvidedMethod(ref mth
) => {
135 ccx
.external().borrow_mut().insert(fn_id
, Some(mth
.id
));
136 ccx
.external_srcs().borrow_mut().insert(mth
.id
, fn_id
);
138 ccx
.stats().n_inlines
.set(ccx
.stats().n_inlines
.get() + 1);
140 // If this is a default method, we can't look up the
141 // impl type. But we aren't going to translate anyways, so
145 ast
::TypeTraitItem(_
) => {
146 ccx
.sess().bug("found TypeTraitItem IITraitItem")
150 csearch
::FoundAst
::Found(&ast
::IIImplItem(impl_did
, ref impl_item
)) => {
152 ast
::MethodImplItem(ref mth
) => {
153 ccx
.external().borrow_mut().insert(fn_id
, Some(mth
.id
));
154 ccx
.external_srcs().borrow_mut().insert(mth
.id
, fn_id
);
156 ccx
.stats().n_inlines
.set(ccx
.stats().n_inlines
.get() + 1);
158 let impl_tpt
= ty
::lookup_item_type(ccx
.tcx(), impl_did
);
159 let unparameterized
= impl_tpt
.generics
.types
.is_empty() &&
160 mth
.pe_generics().ty_params
.is_empty();
162 let empty_substs
= ccx
.tcx().mk_substs(Substs
::trans_empty());
164 let llfn
= get_item_val(ccx
, mth
.id
);
172 // Use InternalLinkage so LLVM can optimize more
174 SetLinkage(llfn
, InternalLinkage
);
178 ast
::TypeImplItem(_
) => {
179 ccx
.sess().bug("found TypeImplItem IIImplItem")
185 return Some(inline_def
);
188 pub fn get_local_instance(ccx
: &CrateContext
, fn_id
: ast
::DefId
)
189 -> Option
<ast
::DefId
> {
190 if fn_id
.krate
== ast
::LOCAL_CRATE
{
193 instantiate_inline(ccx
, fn_id
)
197 pub fn maybe_instantiate_inline(ccx
: &CrateContext
, fn_id
: ast
::DefId
) -> ast
::DefId
{
198 get_local_instance(ccx
, fn_id
).unwrap_or(fn_id
)