Improve linkage assignment in trans::partitioning.

This commit is contained in:
Michael Woerister 2016-05-19 12:35:36 -04:00
parent 65e8a13441
commit 6c8c94b848
13 changed files with 146 additions and 69 deletions

View File

@ -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
/// be exposed from a dynamic library and it's also encoded into the metadata.
pub fn filter_reachable_ids(scx: &SharedCrateContext) -> NodeSet {
scx.reachable().iter().map(|x| *x).filter(|&id| {
pub fn filter_reachable_ids(tcx: TyCtxt, reachable: NodeSet) -> NodeSet {
reachable.into_iter().filter(|&id| {
// Next, we want to ignore some FFI functions that are not exposed from
// this crate. Reachable FFI functions can be lumped into two
// 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
// let it through if it's included statically.
match scx.tcx().map.get(id) {
match tcx.map.get(id) {
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.
@ -2575,8 +2575,8 @@ pub fn filter_reachable_ids(scx: &SharedCrateContext) -> NodeSet {
node: hir::ItemFn(..), .. }) |
hir_map::NodeImplItem(&hir::ImplItem {
node: hir::ImplItemKind::Method(..), .. }) => {
let def_id = scx.tcx().map.local_def_id(id);
let scheme = scx.tcx().lookup_item_type(def_id);
let def_id = tcx.map.local_def_id(id);
let scheme = tcx.lookup_item_type(def_id);
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 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 {
v
@ -2621,12 +2622,9 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
reachable,
check_overflow,
check_dropflag);
let reachable_symbol_ids = filter_reachable_ids(&shared_ccx);
// Translate the 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 {
@ -2755,7 +2753,7 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
}
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);
Instance::mono(&shared_ccx, def_id).symbol_name(&shared_ccx)
}).collect::<Vec<_>>();
@ -2911,7 +2909,8 @@ fn collect_and_partition_translation_items<'a, 'tcx>(scx: &SharedCrateContext<'a
partitioning::partition(scx.tcx(),
items.iter().cloned(),
strategy,
&inlining_map)
&inlining_map,
scx.reachable())
});
if scx.sess().opts.debugging_opts.print_trans_items.is_some() {

View File

@ -126,7 +126,7 @@ use rustc::ty::TyCtxt;
use rustc::ty::item_path::characteristic_def_id_of_type;
use syntax::parse::token::{self, InternedString};
use trans_item::TransItem;
use util::nodemap::{FnvHashMap, FnvHashSet};
use util::nodemap::{FnvHashMap, FnvHashSet, NodeSet};
pub struct CodegenUnit<'tcx> {
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>,
trans_items: I,
strategy: PartitioningStrategy,
inlining_map: &InliningMap<'tcx>)
inlining_map: &InliningMap<'tcx>,
reachable: &NodeSet)
-> Vec<CodegenUnit<'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
// respective 'home' codegen unit. Regular translation items are all
// 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
// until that count is reached.
@ -179,7 +188,8 @@ struct PreInliningPartitioning<'tcx> {
struct PostInliningPartitioning<'tcx>(Vec<CodegenUnit<'tcx>>);
fn place_root_translation_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
trans_items: I)
trans_items: I,
_reachable: &NodeSet)
-> PreInliningPartitioning<'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::DropGlue(..) => unreachable!(),
// 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()
});
}
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>,
@ -319,6 +333,11 @@ fn place_inlined_translation_items<'tcx>(initial_partitioning: PreInliningPartit
// so we just add it here with AvailableExternallyLinkage
new_codegen_unit.items.insert(trans_item,
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 {
// We can't be sure if this will also be instantiated
// 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[..]);
}
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)[..])
}

View File

@ -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> {
let def_id = match *self {
TransItem::Fn(ref instance) => instance.def,

View File

@ -25,7 +25,7 @@ extern crate cgu_extern_drop_glue;
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()
{
//~ 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);
//~ 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()
{
//~ TRANS_ITEM drop-glue extern_drop_glue::mod1[0]::LocalStruct[0] @@ extern_drop_glue-mod1[OnceODR]

View File

@ -19,7 +19,7 @@
// aux-build:cgu_generic_function.rs
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() {
let _ = cgu_generic_function::foo("abc");
}
@ -27,7 +27,7 @@ fn user() {
mod mod1 {
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() {
let _ = cgu_generic_function::foo("abc");
}
@ -35,7 +35,7 @@ mod mod1 {
mod mod1 {
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() {
let _ = cgu_generic_function::foo("abc");
}
@ -45,14 +45,14 @@ mod mod1 {
mod mod2 {
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() {
let _ = cgu_generic_function::foo("abc");
}
}
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() {}
}

View File

@ -21,10 +21,10 @@ extern crate cgu_explicit_inlining;
// This test makes sure that items inlined from external crates are privately
// 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::always_inlined[0] @@ inlining_from_extern_crate[OnceODR] inlining_from_extern_crate-mod2[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[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()
{
cgu_explicit_inlining::inlined();
@ -37,7 +37,7 @@ pub fn user()
mod mod1 {
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()
{
cgu_explicit_inlining::inlined();
@ -50,7 +50,7 @@ mod mod1 {
mod mod2 {
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()
{
cgu_explicit_inlining::always_inlined();

View File

@ -23,7 +23,7 @@ struct 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) {}
}
@ -32,7 +32,7 @@ struct Outer {
_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()
{
let _ = Outer {
@ -53,7 +53,7 @@ mod mod1
_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()
{
let _ = Struct2 {

View File

@ -25,7 +25,7 @@
//~ TRANS_ITEM fn local_generic::generic[0]<&str> @@ local_generic.volatile[WeakODR]
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() {
let _ = generic(0u32);
}
@ -33,7 +33,7 @@ fn user() {
mod mod1 {
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() {
let _ = generic(0u64);
}
@ -41,7 +41,7 @@ mod mod1 {
mod mod1 {
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() {
let _ = generic('c');
}
@ -51,7 +51,7 @@ mod mod1 {
mod mod2 {
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() {
let _ = generic("abc");
}

View File

@ -19,7 +19,7 @@
mod inline {
// 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)]
pub fn inlined_function()
{
@ -30,7 +30,7 @@ mod inline {
mod user1 {
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() {
inline::inlined_function();
}
@ -39,7 +39,7 @@ mod user1 {
mod user2 {
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() {
inline::inlined_function();
}
@ -47,7 +47,7 @@ mod user2 {
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() {
}

View File

@ -18,7 +18,7 @@
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)]
pub fn inlined_function()
{
@ -29,7 +29,7 @@ mod inline {
mod direct_user {
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)]
pub fn foo() {
inline::inlined_function();
@ -39,7 +39,7 @@ mod direct_user {
mod indirect_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() {
direct_user::foo();
}
@ -47,7 +47,7 @@ mod indirect_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() {
}

View File

@ -25,10 +25,10 @@ mod mod1 {
// Even though the impl is in `mod1`, the methods should end up in the
// parent module, since that is where their self-type is.
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) {}
//~ 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() {}
}

View File

@ -16,10 +16,10 @@
#![allow(dead_code)]
#![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() {}
//~ TRANS_ITEM fn regular_modules::bar[0] @@ regular_modules[WeakODR]
//~ TRANS_ITEM fn regular_modules::bar[0] @@ regular_modules[External]
fn bar() {}
//~ TRANS_ITEM static regular_modules::BAZ[0] @@ regular_modules[External]
@ -27,26 +27,26 @@ static BAZ: u64 = 0;
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() {}
//~ 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() {}
//~ TRANS_ITEM static regular_modules::mod1[0]::BAZ[0] @@ regular_modules-mod1[External]
static BAZ: u64 = 0;
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() {}
//~ 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() {}
//~ TRANS_ITEM static regular_modules::mod1[0]::mod1[0]::BAZ[0] @@ regular_modules-mod1-mod1[External]
static BAZ: u64 = 0;
}
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() {}
//~ 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() {}
//~ TRANS_ITEM static regular_modules::mod1[0]::mod2[0]::BAZ[0] @@ regular_modules-mod1-mod2[External]
static BAZ: u64 = 0;
@ -55,26 +55,26 @@ mod mod1 {
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() {}
//~ 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() {}
//~ TRANS_ITEM static regular_modules::mod2[0]::BAZ[0] @@ regular_modules-mod2[External]
static BAZ: u64 = 0;
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() {}
//~ 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() {}
//~ TRANS_ITEM static regular_modules::mod2[0]::mod1[0]::BAZ[0] @@ regular_modules-mod2-mod1[External]
static BAZ: u64 = 0;
}
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() {}
//~ 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() {}
//~ TRANS_ITEM static regular_modules::mod2[0]::mod2[0]::BAZ[0] @@ regular_modules-mod2-mod2[External]
static BAZ: u64 = 0;

View File

@ -21,7 +21,7 @@ static FOO: u32 = 0;
//~ TRANS_ITEM static statics::BAR[0] @@ statics[External]
static BAR: u32 = 0;
//~ TRANS_ITEM fn statics::function[0] @@ statics[WeakODR]
//~ TRANS_ITEM fn statics::function[0] @@ statics[External]
fn function() {
//~ TRANS_ITEM static statics::function[0]::FOO[0] @@ statics[External]
static FOO: u32 = 0;
@ -37,7 +37,7 @@ mod mod1 {
//~ TRANS_ITEM static statics::mod1[0]::BAR[0] @@ statics-mod1[External]
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() {
//~ TRANS_ITEM static statics::mod1[0]::function[0]::FOO[0] @@ statics-mod1[External]
static FOO: u32 = 0;