Improve linkage assignment in trans::partitioning.
This commit is contained in:
parent
65e8a13441
commit
6c8c94b848
|
@ -2548,8 +2548,8 @@ fn iter_functions(llmod: llvm::ModuleRef) -> ValueIter {
|
||||||
///
|
///
|
||||||
/// This list is later used by linkers to determine the set of symbols needed to
|
/// This list is later used by linkers to determine the set of symbols needed to
|
||||||
/// be exposed from a dynamic library and it's also encoded into the metadata.
|
/// be exposed from a dynamic library and it's also encoded into the metadata.
|
||||||
pub fn filter_reachable_ids(scx: &SharedCrateContext) -> NodeSet {
|
pub fn filter_reachable_ids(tcx: TyCtxt, reachable: NodeSet) -> NodeSet {
|
||||||
scx.reachable().iter().map(|x| *x).filter(|&id| {
|
reachable.into_iter().filter(|&id| {
|
||||||
// Next, we want to ignore some FFI functions that are not exposed from
|
// Next, we want to ignore some FFI functions that are not exposed from
|
||||||
// this crate. Reachable FFI functions can be lumped into two
|
// this crate. Reachable FFI functions can be lumped into two
|
||||||
// categories:
|
// categories:
|
||||||
|
@ -2563,9 +2563,9 @@ pub fn filter_reachable_ids(scx: &SharedCrateContext) -> NodeSet {
|
||||||
//
|
//
|
||||||
// As a result, if this id is an FFI item (foreign item) then we only
|
// As a result, if this id is an FFI item (foreign item) then we only
|
||||||
// let it through if it's included statically.
|
// let it through if it's included statically.
|
||||||
match scx.tcx().map.get(id) {
|
match tcx.map.get(id) {
|
||||||
hir_map::NodeForeignItem(..) => {
|
hir_map::NodeForeignItem(..) => {
|
||||||
scx.sess().cstore.is_statically_included_foreign_item(id)
|
tcx.sess.cstore.is_statically_included_foreign_item(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only consider nodes that actually have exported symbols.
|
// Only consider nodes that actually have exported symbols.
|
||||||
|
@ -2575,8 +2575,8 @@ pub fn filter_reachable_ids(scx: &SharedCrateContext) -> NodeSet {
|
||||||
node: hir::ItemFn(..), .. }) |
|
node: hir::ItemFn(..), .. }) |
|
||||||
hir_map::NodeImplItem(&hir::ImplItem {
|
hir_map::NodeImplItem(&hir::ImplItem {
|
||||||
node: hir::ImplItemKind::Method(..), .. }) => {
|
node: hir::ImplItemKind::Method(..), .. }) => {
|
||||||
let def_id = scx.tcx().map.local_def_id(id);
|
let def_id = tcx.map.local_def_id(id);
|
||||||
let scheme = scx.tcx().lookup_item_type(def_id);
|
let scheme = tcx.lookup_item_type(def_id);
|
||||||
scheme.generics.types.is_empty()
|
scheme.generics.types.is_empty()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2598,6 +2598,7 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
let krate = tcx.map.krate();
|
let krate = tcx.map.krate();
|
||||||
|
|
||||||
let ty::CrateAnalysis { export_map, reachable, name, .. } = analysis;
|
let ty::CrateAnalysis { export_map, reachable, name, .. } = analysis;
|
||||||
|
let reachable = filter_reachable_ids(tcx, reachable);
|
||||||
|
|
||||||
let check_overflow = if let Some(v) = tcx.sess.opts.debugging_opts.force_overflow_checks {
|
let check_overflow = if let Some(v) = tcx.sess.opts.debugging_opts.force_overflow_checks {
|
||||||
v
|
v
|
||||||
|
@ -2621,12 +2622,9 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
reachable,
|
reachable,
|
||||||
check_overflow,
|
check_overflow,
|
||||||
check_dropflag);
|
check_dropflag);
|
||||||
|
|
||||||
let reachable_symbol_ids = filter_reachable_ids(&shared_ccx);
|
|
||||||
|
|
||||||
// Translate the metadata.
|
// Translate the metadata.
|
||||||
let metadata = time(tcx.sess.time_passes(), "write metadata", || {
|
let metadata = time(tcx.sess.time_passes(), "write metadata", || {
|
||||||
write_metadata(&shared_ccx, &reachable_symbol_ids)
|
write_metadata(&shared_ccx, shared_ccx.reachable())
|
||||||
});
|
});
|
||||||
|
|
||||||
let metadata_module = ModuleTranslation {
|
let metadata_module = ModuleTranslation {
|
||||||
|
@ -2755,7 +2753,7 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
let sess = shared_ccx.sess();
|
let sess = shared_ccx.sess();
|
||||||
let mut reachable_symbols = reachable_symbol_ids.iter().map(|&id| {
|
let mut reachable_symbols = shared_ccx.reachable().iter().map(|&id| {
|
||||||
let def_id = shared_ccx.tcx().map.local_def_id(id);
|
let def_id = shared_ccx.tcx().map.local_def_id(id);
|
||||||
Instance::mono(&shared_ccx, def_id).symbol_name(&shared_ccx)
|
Instance::mono(&shared_ccx, def_id).symbol_name(&shared_ccx)
|
||||||
}).collect::<Vec<_>>();
|
}).collect::<Vec<_>>();
|
||||||
|
@ -2911,7 +2909,8 @@ fn collect_and_partition_translation_items<'a, 'tcx>(scx: &SharedCrateContext<'a
|
||||||
partitioning::partition(scx.tcx(),
|
partitioning::partition(scx.tcx(),
|
||||||
items.iter().cloned(),
|
items.iter().cloned(),
|
||||||
strategy,
|
strategy,
|
||||||
&inlining_map)
|
&inlining_map,
|
||||||
|
scx.reachable())
|
||||||
});
|
});
|
||||||
|
|
||||||
if scx.sess().opts.debugging_opts.print_trans_items.is_some() {
|
if scx.sess().opts.debugging_opts.print_trans_items.is_some() {
|
||||||
|
|
|
@ -126,7 +126,7 @@ use rustc::ty::TyCtxt;
|
||||||
use rustc::ty::item_path::characteristic_def_id_of_type;
|
use rustc::ty::item_path::characteristic_def_id_of_type;
|
||||||
use syntax::parse::token::{self, InternedString};
|
use syntax::parse::token::{self, InternedString};
|
||||||
use trans_item::TransItem;
|
use trans_item::TransItem;
|
||||||
use util::nodemap::{FnvHashMap, FnvHashSet};
|
use util::nodemap::{FnvHashMap, FnvHashSet, NodeSet};
|
||||||
|
|
||||||
pub struct CodegenUnit<'tcx> {
|
pub struct CodegenUnit<'tcx> {
|
||||||
pub name: InternedString,
|
pub name: InternedString,
|
||||||
|
@ -147,14 +147,23 @@ const FALLBACK_CODEGEN_UNIT: &'static str = "__rustc_fallback_codegen_unit";
|
||||||
pub fn partition<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
pub fn partition<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
trans_items: I,
|
trans_items: I,
|
||||||
strategy: PartitioningStrategy,
|
strategy: PartitioningStrategy,
|
||||||
inlining_map: &InliningMap<'tcx>)
|
inlining_map: &InliningMap<'tcx>,
|
||||||
|
reachable: &NodeSet)
|
||||||
-> Vec<CodegenUnit<'tcx>>
|
-> Vec<CodegenUnit<'tcx>>
|
||||||
where I: Iterator<Item = TransItem<'tcx>>
|
where I: Iterator<Item = TransItem<'tcx>>
|
||||||
{
|
{
|
||||||
|
if let PartitioningStrategy::FixedUnitCount(1) = strategy {
|
||||||
|
// If there is only a single codegen-unit, we can use a very simple
|
||||||
|
// scheme and don't have to bother with doing much analysis.
|
||||||
|
return vec![single_codegen_unit(tcx, trans_items, reachable)];
|
||||||
|
}
|
||||||
|
|
||||||
// In the first step, we place all regular translation items into their
|
// In the first step, we place all regular translation items into their
|
||||||
// respective 'home' codegen unit. Regular translation items are all
|
// respective 'home' codegen unit. Regular translation items are all
|
||||||
// functions and statics defined in the local crate.
|
// functions and statics defined in the local crate.
|
||||||
let mut initial_partitioning = place_root_translation_items(tcx, trans_items);
|
let mut initial_partitioning = place_root_translation_items(tcx,
|
||||||
|
trans_items,
|
||||||
|
reachable);
|
||||||
|
|
||||||
// If the partitioning should produce a fixed count of codegen units, merge
|
// If the partitioning should produce a fixed count of codegen units, merge
|
||||||
// until that count is reached.
|
// until that count is reached.
|
||||||
|
@ -179,7 +188,8 @@ struct PreInliningPartitioning<'tcx> {
|
||||||
struct PostInliningPartitioning<'tcx>(Vec<CodegenUnit<'tcx>>);
|
struct PostInliningPartitioning<'tcx>(Vec<CodegenUnit<'tcx>>);
|
||||||
|
|
||||||
fn place_root_translation_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
fn place_root_translation_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
trans_items: I)
|
trans_items: I,
|
||||||
|
_reachable: &NodeSet)
|
||||||
-> PreInliningPartitioning<'tcx>
|
-> PreInliningPartitioning<'tcx>
|
||||||
where I: Iterator<Item = TransItem<'tcx>>
|
where I: Iterator<Item = TransItem<'tcx>>
|
||||||
{
|
{
|
||||||
|
@ -219,7 +229,18 @@ fn place_root_translation_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
TransItem::Static(..) => llvm::ExternalLinkage,
|
TransItem::Static(..) => llvm::ExternalLinkage,
|
||||||
TransItem::DropGlue(..) => unreachable!(),
|
TransItem::DropGlue(..) => unreachable!(),
|
||||||
// Is there any benefit to using ExternalLinkage?:
|
// Is there any benefit to using ExternalLinkage?:
|
||||||
TransItem::Fn(..) => llvm::WeakODRLinkage,
|
TransItem::Fn(ref instance) => {
|
||||||
|
if instance.substs.types.is_empty() {
|
||||||
|
// This is a non-generic functions, we always
|
||||||
|
// make it visible externally on the chance that
|
||||||
|
// it might be used in another codegen unit.
|
||||||
|
llvm::ExternalLinkage
|
||||||
|
} else {
|
||||||
|
// Monomorphizations of generic functions are
|
||||||
|
// always weak-odr
|
||||||
|
llvm::WeakODRLinkage
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -282,13 +303,6 @@ fn merge_codegen_units<'tcx>(initial_partitioning: &mut PreInliningPartitioning<
|
||||||
items: FnvHashMap()
|
items: FnvHashMap()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn numbered_codegen_unit_name(crate_name: &str, index: usize) -> InternedString {
|
|
||||||
token::intern_and_get_ident(&format!("{}{}{}",
|
|
||||||
crate_name,
|
|
||||||
NUMBERED_CODEGEN_UNIT_MARKER,
|
|
||||||
index)[..])
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn place_inlined_translation_items<'tcx>(initial_partitioning: PreInliningPartitioning<'tcx>,
|
fn place_inlined_translation_items<'tcx>(initial_partitioning: PreInliningPartitioning<'tcx>,
|
||||||
|
@ -319,6 +333,11 @@ fn place_inlined_translation_items<'tcx>(initial_partitioning: PreInliningPartit
|
||||||
// so we just add it here with AvailableExternallyLinkage
|
// so we just add it here with AvailableExternallyLinkage
|
||||||
new_codegen_unit.items.insert(trans_item,
|
new_codegen_unit.items.insert(trans_item,
|
||||||
llvm::AvailableExternallyLinkage);
|
llvm::AvailableExternallyLinkage);
|
||||||
|
} else if trans_item.is_from_extern_crate() && !trans_item.is_generic_fn() {
|
||||||
|
// An instantiation of this item is always available in the
|
||||||
|
// crate it was imported from.
|
||||||
|
new_codegen_unit.items.insert(trans_item,
|
||||||
|
llvm::AvailableExternallyLinkage);
|
||||||
} else {
|
} else {
|
||||||
// We can't be sure if this will also be instantiated
|
// We can't be sure if this will also be instantiated
|
||||||
// somewhere else, so we add an instance here with
|
// somewhere else, so we add an instance here with
|
||||||
|
@ -414,3 +433,54 @@ fn compute_codegen_unit_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
|
|
||||||
return token::intern_and_get_ident(&mod_path[..]);
|
return token::intern_and_get_ident(&mod_path[..]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn single_codegen_unit<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
|
trans_items: I,
|
||||||
|
reachable: &NodeSet)
|
||||||
|
-> CodegenUnit<'tcx>
|
||||||
|
where I: Iterator<Item = TransItem<'tcx>>
|
||||||
|
{
|
||||||
|
let mut items = FnvHashMap();
|
||||||
|
|
||||||
|
for trans_item in trans_items {
|
||||||
|
let linkage = trans_item.explicit_linkage(tcx).unwrap_or_else(|| {
|
||||||
|
match trans_item {
|
||||||
|
TransItem::Static(node_id) => {
|
||||||
|
if reachable.contains(&node_id) {
|
||||||
|
llvm::ExternalLinkage
|
||||||
|
} else {
|
||||||
|
llvm::InternalLinkage
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TransItem::DropGlue(_) => {
|
||||||
|
llvm::InternalLinkage
|
||||||
|
}
|
||||||
|
TransItem::Fn(instance) => {
|
||||||
|
if trans_item.is_generic_fn() ||
|
||||||
|
trans_item.is_from_extern_crate() ||
|
||||||
|
!reachable.contains(&tcx.map
|
||||||
|
.as_local_node_id(instance.def)
|
||||||
|
.unwrap()) {
|
||||||
|
llvm::InternalLinkage
|
||||||
|
} else {
|
||||||
|
llvm::ExternalLinkage
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
items.insert(trans_item, linkage);
|
||||||
|
}
|
||||||
|
|
||||||
|
CodegenUnit {
|
||||||
|
name: numbered_codegen_unit_name(&tcx.crate_name[..], 0),
|
||||||
|
items: items
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn numbered_codegen_unit_name(crate_name: &str, index: usize) -> InternedString {
|
||||||
|
token::intern_and_get_ident(&format!("{}{}{}",
|
||||||
|
crate_name,
|
||||||
|
NUMBERED_CODEGEN_UNIT_MARKER,
|
||||||
|
index)[..])
|
||||||
|
}
|
||||||
|
|
|
@ -184,6 +184,14 @@ impl<'a, 'tcx> TransItem<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_generic_fn(&self) -> bool {
|
||||||
|
match *self {
|
||||||
|
TransItem::Fn(ref instance) => !instance.substs.types.is_empty(),
|
||||||
|
TransItem::DropGlue(..) |
|
||||||
|
TransItem::Static(..) => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn explicit_linkage(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option<llvm::Linkage> {
|
pub fn explicit_linkage(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option<llvm::Linkage> {
|
||||||
let def_id = match *self {
|
let def_id = match *self {
|
||||||
TransItem::Fn(ref instance) => instance.def,
|
TransItem::Fn(ref instance) => instance.def,
|
||||||
|
|
|
@ -25,7 +25,7 @@ extern crate cgu_extern_drop_glue;
|
||||||
|
|
||||||
struct LocalStruct(cgu_extern_drop_glue::Struct);
|
struct LocalStruct(cgu_extern_drop_glue::Struct);
|
||||||
|
|
||||||
//~ TRANS_ITEM fn extern_drop_glue::user[0] @@ extern_drop_glue[WeakODR]
|
//~ TRANS_ITEM fn extern_drop_glue::user[0] @@ extern_drop_glue[External]
|
||||||
fn user()
|
fn user()
|
||||||
{
|
{
|
||||||
//~ TRANS_ITEM drop-glue extern_drop_glue::LocalStruct[0] @@ extern_drop_glue[OnceODR]
|
//~ TRANS_ITEM drop-glue extern_drop_glue::LocalStruct[0] @@ extern_drop_glue[OnceODR]
|
||||||
|
@ -37,7 +37,7 @@ mod mod1 {
|
||||||
|
|
||||||
struct LocalStruct(cgu_extern_drop_glue::Struct);
|
struct LocalStruct(cgu_extern_drop_glue::Struct);
|
||||||
|
|
||||||
//~ TRANS_ITEM fn extern_drop_glue::mod1[0]::user[0] @@ extern_drop_glue-mod1[WeakODR]
|
//~ TRANS_ITEM fn extern_drop_glue::mod1[0]::user[0] @@ extern_drop_glue-mod1[External]
|
||||||
fn user()
|
fn user()
|
||||||
{
|
{
|
||||||
//~ TRANS_ITEM drop-glue extern_drop_glue::mod1[0]::LocalStruct[0] @@ extern_drop_glue-mod1[OnceODR]
|
//~ TRANS_ITEM drop-glue extern_drop_glue::mod1[0]::LocalStruct[0] @@ extern_drop_glue-mod1[OnceODR]
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
// aux-build:cgu_generic_function.rs
|
// aux-build:cgu_generic_function.rs
|
||||||
extern crate cgu_generic_function;
|
extern crate cgu_generic_function;
|
||||||
|
|
||||||
//~ TRANS_ITEM fn extern_generic::user[0] @@ extern_generic[WeakODR]
|
//~ TRANS_ITEM fn extern_generic::user[0] @@ extern_generic[External]
|
||||||
fn user() {
|
fn user() {
|
||||||
let _ = cgu_generic_function::foo("abc");
|
let _ = cgu_generic_function::foo("abc");
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ fn user() {
|
||||||
mod mod1 {
|
mod mod1 {
|
||||||
use cgu_generic_function;
|
use cgu_generic_function;
|
||||||
|
|
||||||
//~ TRANS_ITEM fn extern_generic::mod1[0]::user[0] @@ extern_generic-mod1[WeakODR]
|
//~ TRANS_ITEM fn extern_generic::mod1[0]::user[0] @@ extern_generic-mod1[External]
|
||||||
fn user() {
|
fn user() {
|
||||||
let _ = cgu_generic_function::foo("abc");
|
let _ = cgu_generic_function::foo("abc");
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,7 @@ mod mod1 {
|
||||||
mod mod1 {
|
mod mod1 {
|
||||||
use cgu_generic_function;
|
use cgu_generic_function;
|
||||||
|
|
||||||
//~ TRANS_ITEM fn extern_generic::mod1[0]::mod1[0]::user[0] @@ extern_generic-mod1-mod1[WeakODR]
|
//~ TRANS_ITEM fn extern_generic::mod1[0]::mod1[0]::user[0] @@ extern_generic-mod1-mod1[External]
|
||||||
fn user() {
|
fn user() {
|
||||||
let _ = cgu_generic_function::foo("abc");
|
let _ = cgu_generic_function::foo("abc");
|
||||||
}
|
}
|
||||||
|
@ -45,14 +45,14 @@ mod mod1 {
|
||||||
mod mod2 {
|
mod mod2 {
|
||||||
use cgu_generic_function;
|
use cgu_generic_function;
|
||||||
|
|
||||||
//~ TRANS_ITEM fn extern_generic::mod2[0]::user[0] @@ extern_generic-mod2[WeakODR]
|
//~ TRANS_ITEM fn extern_generic::mod2[0]::user[0] @@ extern_generic-mod2[External]
|
||||||
fn user() {
|
fn user() {
|
||||||
let _ = cgu_generic_function::foo("abc");
|
let _ = cgu_generic_function::foo("abc");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mod mod3 {
|
mod mod3 {
|
||||||
//~ TRANS_ITEM fn extern_generic::mod3[0]::non_user[0] @@ extern_generic-mod3[WeakODR]
|
//~ TRANS_ITEM fn extern_generic::mod3[0]::non_user[0] @@ extern_generic-mod3[External]
|
||||||
fn non_user() {}
|
fn non_user() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,10 +21,10 @@ extern crate cgu_explicit_inlining;
|
||||||
// This test makes sure that items inlined from external crates are privately
|
// This test makes sure that items inlined from external crates are privately
|
||||||
// instantiated in every codegen unit they are used in.
|
// instantiated in every codegen unit they are used in.
|
||||||
|
|
||||||
//~ TRANS_ITEM fn cgu_explicit_inlining::inlined[0] @@ inlining_from_extern_crate[OnceODR] inlining_from_extern_crate-mod1[OnceODR]
|
//~ TRANS_ITEM fn cgu_explicit_inlining::inlined[0] @@ inlining_from_extern_crate[Available] inlining_from_extern_crate-mod1[Available]
|
||||||
//~ TRANS_ITEM fn cgu_explicit_inlining::always_inlined[0] @@ inlining_from_extern_crate[OnceODR] inlining_from_extern_crate-mod2[OnceODR]
|
//~ TRANS_ITEM fn cgu_explicit_inlining::always_inlined[0] @@ inlining_from_extern_crate[Available] inlining_from_extern_crate-mod2[Available]
|
||||||
|
|
||||||
//~ TRANS_ITEM fn inlining_from_extern_crate::user[0] @@ inlining_from_extern_crate[WeakODR]
|
//~ TRANS_ITEM fn inlining_from_extern_crate::user[0] @@ inlining_from_extern_crate[External]
|
||||||
pub fn user()
|
pub fn user()
|
||||||
{
|
{
|
||||||
cgu_explicit_inlining::inlined();
|
cgu_explicit_inlining::inlined();
|
||||||
|
@ -37,7 +37,7 @@ pub fn user()
|
||||||
mod mod1 {
|
mod mod1 {
|
||||||
use cgu_explicit_inlining;
|
use cgu_explicit_inlining;
|
||||||
|
|
||||||
//~ TRANS_ITEM fn inlining_from_extern_crate::mod1[0]::user[0] @@ inlining_from_extern_crate-mod1[WeakODR]
|
//~ TRANS_ITEM fn inlining_from_extern_crate::mod1[0]::user[0] @@ inlining_from_extern_crate-mod1[External]
|
||||||
pub fn user()
|
pub fn user()
|
||||||
{
|
{
|
||||||
cgu_explicit_inlining::inlined();
|
cgu_explicit_inlining::inlined();
|
||||||
|
@ -50,7 +50,7 @@ mod mod1 {
|
||||||
mod mod2 {
|
mod mod2 {
|
||||||
use cgu_explicit_inlining;
|
use cgu_explicit_inlining;
|
||||||
|
|
||||||
//~ TRANS_ITEM fn inlining_from_extern_crate::mod2[0]::user[0] @@ inlining_from_extern_crate-mod2[WeakODR]
|
//~ TRANS_ITEM fn inlining_from_extern_crate::mod2[0]::user[0] @@ inlining_from_extern_crate-mod2[External]
|
||||||
pub fn user()
|
pub fn user()
|
||||||
{
|
{
|
||||||
cgu_explicit_inlining::always_inlined();
|
cgu_explicit_inlining::always_inlined();
|
||||||
|
|
|
@ -23,7 +23,7 @@ struct Struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for Struct {
|
impl Drop for Struct {
|
||||||
//~ TRANS_ITEM fn local_drop_glue::{{impl}}[0]::drop[0] @@ local_drop_glue[WeakODR]
|
//~ TRANS_ITEM fn local_drop_glue::{{impl}}[0]::drop[0] @@ local_drop_glue[External]
|
||||||
fn drop(&mut self) {}
|
fn drop(&mut self) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ struct Outer {
|
||||||
_a: Struct
|
_a: Struct
|
||||||
}
|
}
|
||||||
|
|
||||||
//~ TRANS_ITEM fn local_drop_glue::user[0] @@ local_drop_glue[WeakODR]
|
//~ TRANS_ITEM fn local_drop_glue::user[0] @@ local_drop_glue[External]
|
||||||
fn user()
|
fn user()
|
||||||
{
|
{
|
||||||
let _ = Outer {
|
let _ = Outer {
|
||||||
|
@ -53,7 +53,7 @@ mod mod1
|
||||||
_b: (u32, Struct),
|
_b: (u32, Struct),
|
||||||
}
|
}
|
||||||
|
|
||||||
//~ TRANS_ITEM fn local_drop_glue::mod1[0]::user[0] @@ local_drop_glue-mod1[WeakODR]
|
//~ TRANS_ITEM fn local_drop_glue::mod1[0]::user[0] @@ local_drop_glue-mod1[External]
|
||||||
fn user()
|
fn user()
|
||||||
{
|
{
|
||||||
let _ = Struct2 {
|
let _ = Struct2 {
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
//~ TRANS_ITEM fn local_generic::generic[0]<&str> @@ local_generic.volatile[WeakODR]
|
//~ TRANS_ITEM fn local_generic::generic[0]<&str> @@ local_generic.volatile[WeakODR]
|
||||||
pub fn generic<T>(x: T) -> T { x }
|
pub fn generic<T>(x: T) -> T { x }
|
||||||
|
|
||||||
//~ TRANS_ITEM fn local_generic::user[0] @@ local_generic[WeakODR]
|
//~ TRANS_ITEM fn local_generic::user[0] @@ local_generic[External]
|
||||||
fn user() {
|
fn user() {
|
||||||
let _ = generic(0u32);
|
let _ = generic(0u32);
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ fn user() {
|
||||||
mod mod1 {
|
mod mod1 {
|
||||||
pub use super::generic;
|
pub use super::generic;
|
||||||
|
|
||||||
//~ TRANS_ITEM fn local_generic::mod1[0]::user[0] @@ local_generic-mod1[WeakODR]
|
//~ TRANS_ITEM fn local_generic::mod1[0]::user[0] @@ local_generic-mod1[External]
|
||||||
fn user() {
|
fn user() {
|
||||||
let _ = generic(0u64);
|
let _ = generic(0u64);
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,7 @@ mod mod1 {
|
||||||
mod mod1 {
|
mod mod1 {
|
||||||
use super::generic;
|
use super::generic;
|
||||||
|
|
||||||
//~ TRANS_ITEM fn local_generic::mod1[0]::mod1[0]::user[0] @@ local_generic-mod1-mod1[WeakODR]
|
//~ TRANS_ITEM fn local_generic::mod1[0]::mod1[0]::user[0] @@ local_generic-mod1-mod1[External]
|
||||||
fn user() {
|
fn user() {
|
||||||
let _ = generic('c');
|
let _ = generic('c');
|
||||||
}
|
}
|
||||||
|
@ -51,7 +51,7 @@ mod mod1 {
|
||||||
mod mod2 {
|
mod mod2 {
|
||||||
use super::generic;
|
use super::generic;
|
||||||
|
|
||||||
//~ TRANS_ITEM fn local_generic::mod2[0]::user[0] @@ local_generic-mod2[WeakODR]
|
//~ TRANS_ITEM fn local_generic::mod2[0]::user[0] @@ local_generic-mod2[External]
|
||||||
fn user() {
|
fn user() {
|
||||||
let _ = generic("abc");
|
let _ = generic("abc");
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
mod inline {
|
mod inline {
|
||||||
|
|
||||||
// Important: This function should show up in all codegen units where it is inlined
|
// Important: This function should show up in all codegen units where it is inlined
|
||||||
//~ TRANS_ITEM fn local_inlining::inline[0]::inlined_function[0] @@ local_inlining-inline[WeakODR] local_inlining-user1[Available] local_inlining-user2[Available]
|
//~ TRANS_ITEM fn local_inlining::inline[0]::inlined_function[0] @@ local_inlining-inline[External] local_inlining-user1[Available] local_inlining-user2[Available]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn inlined_function()
|
pub fn inlined_function()
|
||||||
{
|
{
|
||||||
|
@ -30,7 +30,7 @@ mod inline {
|
||||||
mod user1 {
|
mod user1 {
|
||||||
use super::inline;
|
use super::inline;
|
||||||
|
|
||||||
//~ TRANS_ITEM fn local_inlining::user1[0]::foo[0] @@ local_inlining-user1[WeakODR]
|
//~ TRANS_ITEM fn local_inlining::user1[0]::foo[0] @@ local_inlining-user1[External]
|
||||||
fn foo() {
|
fn foo() {
|
||||||
inline::inlined_function();
|
inline::inlined_function();
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,7 @@ mod user1 {
|
||||||
mod user2 {
|
mod user2 {
|
||||||
use super::inline;
|
use super::inline;
|
||||||
|
|
||||||
//~ TRANS_ITEM fn local_inlining::user2[0]::bar[0] @@ local_inlining-user2[WeakODR]
|
//~ TRANS_ITEM fn local_inlining::user2[0]::bar[0] @@ local_inlining-user2[External]
|
||||||
fn bar() {
|
fn bar() {
|
||||||
inline::inlined_function();
|
inline::inlined_function();
|
||||||
}
|
}
|
||||||
|
@ -47,7 +47,7 @@ mod user2 {
|
||||||
|
|
||||||
mod non_user {
|
mod non_user {
|
||||||
|
|
||||||
//~ TRANS_ITEM fn local_inlining::non_user[0]::baz[0] @@ local_inlining-non_user[WeakODR]
|
//~ TRANS_ITEM fn local_inlining::non_user[0]::baz[0] @@ local_inlining-non_user[External]
|
||||||
fn baz() {
|
fn baz() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
|
|
||||||
mod inline {
|
mod inline {
|
||||||
|
|
||||||
//~ TRANS_ITEM fn local_transitive_inlining::inline[0]::inlined_function[0] @@ local_transitive_inlining-inline[WeakODR] local_transitive_inlining-direct_user[Available] local_transitive_inlining-indirect_user[Available]
|
//~ TRANS_ITEM fn local_transitive_inlining::inline[0]::inlined_function[0] @@ local_transitive_inlining-inline[External] local_transitive_inlining-direct_user[Available] local_transitive_inlining-indirect_user[Available]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn inlined_function()
|
pub fn inlined_function()
|
||||||
{
|
{
|
||||||
|
@ -29,7 +29,7 @@ mod inline {
|
||||||
mod direct_user {
|
mod direct_user {
|
||||||
use super::inline;
|
use super::inline;
|
||||||
|
|
||||||
//~ TRANS_ITEM fn local_transitive_inlining::direct_user[0]::foo[0] @@ local_transitive_inlining-direct_user[WeakODR] local_transitive_inlining-indirect_user[Available]
|
//~ TRANS_ITEM fn local_transitive_inlining::direct_user[0]::foo[0] @@ local_transitive_inlining-direct_user[External] local_transitive_inlining-indirect_user[Available]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn foo() {
|
pub fn foo() {
|
||||||
inline::inlined_function();
|
inline::inlined_function();
|
||||||
|
@ -39,7 +39,7 @@ mod direct_user {
|
||||||
mod indirect_user {
|
mod indirect_user {
|
||||||
use super::direct_user;
|
use super::direct_user;
|
||||||
|
|
||||||
//~ TRANS_ITEM fn local_transitive_inlining::indirect_user[0]::bar[0] @@ local_transitive_inlining-indirect_user[WeakODR]
|
//~ TRANS_ITEM fn local_transitive_inlining::indirect_user[0]::bar[0] @@ local_transitive_inlining-indirect_user[External]
|
||||||
fn bar() {
|
fn bar() {
|
||||||
direct_user::foo();
|
direct_user::foo();
|
||||||
}
|
}
|
||||||
|
@ -47,7 +47,7 @@ mod indirect_user {
|
||||||
|
|
||||||
mod non_user {
|
mod non_user {
|
||||||
|
|
||||||
//~ TRANS_ITEM fn local_transitive_inlining::non_user[0]::baz[0] @@ local_transitive_inlining-non_user[WeakODR]
|
//~ TRANS_ITEM fn local_transitive_inlining::non_user[0]::baz[0] @@ local_transitive_inlining-non_user[External]
|
||||||
fn baz() {
|
fn baz() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,10 +25,10 @@ mod mod1 {
|
||||||
// Even though the impl is in `mod1`, the methods should end up in the
|
// Even though the impl is in `mod1`, the methods should end up in the
|
||||||
// parent module, since that is where their self-type is.
|
// parent module, since that is where their self-type is.
|
||||||
impl SomeType {
|
impl SomeType {
|
||||||
//~ TRANS_ITEM fn methods_are_with_self_type::mod1[0]::{{impl}}[0]::method[0] @@ methods_are_with_self_type[WeakODR]
|
//~ TRANS_ITEM fn methods_are_with_self_type::mod1[0]::{{impl}}[0]::method[0] @@ methods_are_with_self_type[External]
|
||||||
fn method(&self) {}
|
fn method(&self) {}
|
||||||
|
|
||||||
//~ TRANS_ITEM fn methods_are_with_self_type::mod1[0]::{{impl}}[0]::associated_fn[0] @@ methods_are_with_self_type[WeakODR]
|
//~ TRANS_ITEM fn methods_are_with_self_type::mod1[0]::{{impl}}[0]::associated_fn[0] @@ methods_are_with_self_type[External]
|
||||||
fn associated_fn() {}
|
fn associated_fn() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,10 +16,10 @@
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
#![crate_type="lib"]
|
#![crate_type="lib"]
|
||||||
|
|
||||||
//~ TRANS_ITEM fn regular_modules::foo[0] @@ regular_modules[WeakODR]
|
//~ TRANS_ITEM fn regular_modules::foo[0] @@ regular_modules[External]
|
||||||
fn foo() {}
|
fn foo() {}
|
||||||
|
|
||||||
//~ TRANS_ITEM fn regular_modules::bar[0] @@ regular_modules[WeakODR]
|
//~ TRANS_ITEM fn regular_modules::bar[0] @@ regular_modules[External]
|
||||||
fn bar() {}
|
fn bar() {}
|
||||||
|
|
||||||
//~ TRANS_ITEM static regular_modules::BAZ[0] @@ regular_modules[External]
|
//~ TRANS_ITEM static regular_modules::BAZ[0] @@ regular_modules[External]
|
||||||
|
@ -27,26 +27,26 @@ static BAZ: u64 = 0;
|
||||||
|
|
||||||
mod mod1 {
|
mod mod1 {
|
||||||
|
|
||||||
//~ TRANS_ITEM fn regular_modules::mod1[0]::foo[0] @@ regular_modules-mod1[WeakODR]
|
//~ TRANS_ITEM fn regular_modules::mod1[0]::foo[0] @@ regular_modules-mod1[External]
|
||||||
fn foo() {}
|
fn foo() {}
|
||||||
//~ TRANS_ITEM fn regular_modules::mod1[0]::bar[0] @@ regular_modules-mod1[WeakODR]
|
//~ TRANS_ITEM fn regular_modules::mod1[0]::bar[0] @@ regular_modules-mod1[External]
|
||||||
fn bar() {}
|
fn bar() {}
|
||||||
//~ TRANS_ITEM static regular_modules::mod1[0]::BAZ[0] @@ regular_modules-mod1[External]
|
//~ TRANS_ITEM static regular_modules::mod1[0]::BAZ[0] @@ regular_modules-mod1[External]
|
||||||
static BAZ: u64 = 0;
|
static BAZ: u64 = 0;
|
||||||
|
|
||||||
mod mod1 {
|
mod mod1 {
|
||||||
//~ TRANS_ITEM fn regular_modules::mod1[0]::mod1[0]::foo[0] @@ regular_modules-mod1-mod1[WeakODR]
|
//~ TRANS_ITEM fn regular_modules::mod1[0]::mod1[0]::foo[0] @@ regular_modules-mod1-mod1[External]
|
||||||
fn foo() {}
|
fn foo() {}
|
||||||
//~ TRANS_ITEM fn regular_modules::mod1[0]::mod1[0]::bar[0] @@ regular_modules-mod1-mod1[WeakODR]
|
//~ TRANS_ITEM fn regular_modules::mod1[0]::mod1[0]::bar[0] @@ regular_modules-mod1-mod1[External]
|
||||||
fn bar() {}
|
fn bar() {}
|
||||||
//~ TRANS_ITEM static regular_modules::mod1[0]::mod1[0]::BAZ[0] @@ regular_modules-mod1-mod1[External]
|
//~ TRANS_ITEM static regular_modules::mod1[0]::mod1[0]::BAZ[0] @@ regular_modules-mod1-mod1[External]
|
||||||
static BAZ: u64 = 0;
|
static BAZ: u64 = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
mod mod2 {
|
mod mod2 {
|
||||||
//~ TRANS_ITEM fn regular_modules::mod1[0]::mod2[0]::foo[0] @@ regular_modules-mod1-mod2[WeakODR]
|
//~ TRANS_ITEM fn regular_modules::mod1[0]::mod2[0]::foo[0] @@ regular_modules-mod1-mod2[External]
|
||||||
fn foo() {}
|
fn foo() {}
|
||||||
//~ TRANS_ITEM fn regular_modules::mod1[0]::mod2[0]::bar[0] @@ regular_modules-mod1-mod2[WeakODR]
|
//~ TRANS_ITEM fn regular_modules::mod1[0]::mod2[0]::bar[0] @@ regular_modules-mod1-mod2[External]
|
||||||
fn bar() {}
|
fn bar() {}
|
||||||
//~ TRANS_ITEM static regular_modules::mod1[0]::mod2[0]::BAZ[0] @@ regular_modules-mod1-mod2[External]
|
//~ TRANS_ITEM static regular_modules::mod1[0]::mod2[0]::BAZ[0] @@ regular_modules-mod1-mod2[External]
|
||||||
static BAZ: u64 = 0;
|
static BAZ: u64 = 0;
|
||||||
|
@ -55,26 +55,26 @@ mod mod1 {
|
||||||
|
|
||||||
mod mod2 {
|
mod mod2 {
|
||||||
|
|
||||||
//~ TRANS_ITEM fn regular_modules::mod2[0]::foo[0] @@ regular_modules-mod2[WeakODR]
|
//~ TRANS_ITEM fn regular_modules::mod2[0]::foo[0] @@ regular_modules-mod2[External]
|
||||||
fn foo() {}
|
fn foo() {}
|
||||||
//~ TRANS_ITEM fn regular_modules::mod2[0]::bar[0] @@ regular_modules-mod2[WeakODR]
|
//~ TRANS_ITEM fn regular_modules::mod2[0]::bar[0] @@ regular_modules-mod2[External]
|
||||||
fn bar() {}
|
fn bar() {}
|
||||||
//~ TRANS_ITEM static regular_modules::mod2[0]::BAZ[0] @@ regular_modules-mod2[External]
|
//~ TRANS_ITEM static regular_modules::mod2[0]::BAZ[0] @@ regular_modules-mod2[External]
|
||||||
static BAZ: u64 = 0;
|
static BAZ: u64 = 0;
|
||||||
|
|
||||||
mod mod1 {
|
mod mod1 {
|
||||||
//~ TRANS_ITEM fn regular_modules::mod2[0]::mod1[0]::foo[0] @@ regular_modules-mod2-mod1[WeakODR]
|
//~ TRANS_ITEM fn regular_modules::mod2[0]::mod1[0]::foo[0] @@ regular_modules-mod2-mod1[External]
|
||||||
fn foo() {}
|
fn foo() {}
|
||||||
//~ TRANS_ITEM fn regular_modules::mod2[0]::mod1[0]::bar[0] @@ regular_modules-mod2-mod1[WeakODR]
|
//~ TRANS_ITEM fn regular_modules::mod2[0]::mod1[0]::bar[0] @@ regular_modules-mod2-mod1[External]
|
||||||
fn bar() {}
|
fn bar() {}
|
||||||
//~ TRANS_ITEM static regular_modules::mod2[0]::mod1[0]::BAZ[0] @@ regular_modules-mod2-mod1[External]
|
//~ TRANS_ITEM static regular_modules::mod2[0]::mod1[0]::BAZ[0] @@ regular_modules-mod2-mod1[External]
|
||||||
static BAZ: u64 = 0;
|
static BAZ: u64 = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
mod mod2 {
|
mod mod2 {
|
||||||
//~ TRANS_ITEM fn regular_modules::mod2[0]::mod2[0]::foo[0] @@ regular_modules-mod2-mod2[WeakODR]
|
//~ TRANS_ITEM fn regular_modules::mod2[0]::mod2[0]::foo[0] @@ regular_modules-mod2-mod2[External]
|
||||||
fn foo() {}
|
fn foo() {}
|
||||||
//~ TRANS_ITEM fn regular_modules::mod2[0]::mod2[0]::bar[0] @@ regular_modules-mod2-mod2[WeakODR]
|
//~ TRANS_ITEM fn regular_modules::mod2[0]::mod2[0]::bar[0] @@ regular_modules-mod2-mod2[External]
|
||||||
fn bar() {}
|
fn bar() {}
|
||||||
//~ TRANS_ITEM static regular_modules::mod2[0]::mod2[0]::BAZ[0] @@ regular_modules-mod2-mod2[External]
|
//~ TRANS_ITEM static regular_modules::mod2[0]::mod2[0]::BAZ[0] @@ regular_modules-mod2-mod2[External]
|
||||||
static BAZ: u64 = 0;
|
static BAZ: u64 = 0;
|
||||||
|
|
|
@ -21,7 +21,7 @@ static FOO: u32 = 0;
|
||||||
//~ TRANS_ITEM static statics::BAR[0] @@ statics[External]
|
//~ TRANS_ITEM static statics::BAR[0] @@ statics[External]
|
||||||
static BAR: u32 = 0;
|
static BAR: u32 = 0;
|
||||||
|
|
||||||
//~ TRANS_ITEM fn statics::function[0] @@ statics[WeakODR]
|
//~ TRANS_ITEM fn statics::function[0] @@ statics[External]
|
||||||
fn function() {
|
fn function() {
|
||||||
//~ TRANS_ITEM static statics::function[0]::FOO[0] @@ statics[External]
|
//~ TRANS_ITEM static statics::function[0]::FOO[0] @@ statics[External]
|
||||||
static FOO: u32 = 0;
|
static FOO: u32 = 0;
|
||||||
|
@ -37,7 +37,7 @@ mod mod1 {
|
||||||
//~ TRANS_ITEM static statics::mod1[0]::BAR[0] @@ statics-mod1[External]
|
//~ TRANS_ITEM static statics::mod1[0]::BAR[0] @@ statics-mod1[External]
|
||||||
static BAR: u32 = 0;
|
static BAR: u32 = 0;
|
||||||
|
|
||||||
//~ TRANS_ITEM fn statics::mod1[0]::function[0] @@ statics-mod1[WeakODR]
|
//~ TRANS_ITEM fn statics::mod1[0]::function[0] @@ statics-mod1[External]
|
||||||
fn function() {
|
fn function() {
|
||||||
//~ TRANS_ITEM static statics::mod1[0]::function[0]::FOO[0] @@ statics-mod1[External]
|
//~ TRANS_ITEM static statics::mod1[0]::function[0]::FOO[0] @@ statics-mod1[External]
|
||||||
static FOO: u32 = 0;
|
static FOO: u32 = 0;
|
||||||
|
|
Loading…
Reference in New Issue