Skip to content

Commit 5d415e8

Browse files
committed
rustc: Handle #[inline(always)] at -O0
This commit updates the handling of `#[inline(always)]` functions at -O0 to ensure that it's always inlined regardless of the number of codegen units used. Closes #45201
1 parent a47c9f8 commit 5d415e8

File tree

4 files changed

+58
-9
lines changed

4 files changed

+58
-9
lines changed

src/librustc_trans/trans_item.rs

+24-8
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ use rustc::traits;
3131
use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
3232
use rustc::ty::subst::{Subst, Substs};
3333
use syntax::ast;
34-
use syntax::attr;
34+
use syntax::attr::{self, InlineAttr};
3535
use syntax_pos::Span;
3636
use syntax_pos::symbol::Symbol;
3737
use type_of;
@@ -175,16 +175,32 @@ pub trait TransItemExt<'a, 'tcx>: fmt::Debug {
175175

176176
match *self.as_trans_item() {
177177
TransItem::Fn(ref instance) => {
178-
if self.explicit_linkage(tcx).is_none() &&
179-
common::requests_inline(tcx, instance)
178+
// If this function isn't inlined or otherwise has explicit
179+
// linkage, then we'll be creating a globally shared version.
180+
if self.explicit_linkage(tcx).is_some() ||
181+
!common::requests_inline(tcx, instance)
180182
{
181-
if inline_in_all_cgus {
182-
InstantiationMode::LocalCopy
183-
} else {
183+
return InstantiationMode::GloballyShared { may_conflict: false }
184+
}
185+
186+
// At this point we don't have explicit linkage and we're an
187+
// inlined function. If we're inlining into all CGUs then we'll
188+
// be creating a local copy per CGU
189+
if inline_in_all_cgus {
190+
return InstantiationMode::LocalCopy
191+
}
192+
193+
// Finally, if this is `#[inline(always)]` we're sure to respect
194+
// that with an inline copy per CGU, but otherwise we'll be
195+
// creating one copy of this `#[inline]` function which may
196+
// conflict with upstream crates as it could be an exported
197+
// symbol.
198+
let attrs = instance.def.attrs(tcx);
199+
match attr::find_inline_attr(Some(tcx.sess.diagnostic()), &attrs) {
200+
InlineAttr::Always => InstantiationMode::LocalCopy,
201+
_ => {
184202
InstantiationMode::GloballyShared { may_conflict: true }
185203
}
186-
} else {
187-
InstantiationMode::GloballyShared { may_conflict: false }
188204
}
189205
}
190206
TransItem::Static(..) => {

src/test/codegen-units/partitioning/local-inlining-but-not-all.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
mod inline {
2121

2222
//~ TRANS_ITEM fn local_inlining_but_not_all::inline[0]::inlined_function[0] @@ local_inlining_but_not_all-inline[External]
23-
#[inline(always)]
23+
#[inline]
2424
pub fn inlined_function()
2525
{
2626

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
-include ../tools.mk
2+
3+
all:
4+
$(RUSTC) foo.rs --emit llvm-ir -C codegen-units=2
5+
if grep -w call $(TMPDIR)/*.ll; then \
6+
echo "found call instruction when one wasn't expected"; \
7+
exit 1; \
8+
fi
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Copyright 2017 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+
#![crate_type = "lib"]
12+
13+
pub mod a {
14+
#[inline(always)]
15+
pub fn foo() {
16+
}
17+
18+
pub fn bar() {
19+
}
20+
}
21+
22+
#[no_mangle]
23+
pub fn bar() {
24+
a::foo();
25+
}

0 commit comments

Comments
 (0)