Skip to content

Commit dd08c30

Browse files
committed
Auto merge of #44133 - vorner:allocator-kind-autodetect, r=alexcrichton
Autodetect the type of allocator crate used Annotate the allocator crates (allocator_system, allocator_jemalloc) by the type of allocator they are. If one is requested as an exe allocator, detect its type by the flags. This has the effect that using this (de jure wrong) configuration in the target spec works instead of producing a really unhelpful and arcane linker error: "exe-allocation-crate": "alloc_system" Fixes #43524. There are two yet unsolved FIXME's, I'll be glad for some advice on what to do with them.
2 parents a7b7dce + 94297c6 commit dd08c30

File tree

3 files changed

+69
-36
lines changed

3 files changed

+69
-36
lines changed

src/liballoc_jemalloc/lib.rs

+3
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
// except according to those terms.
1010

1111
#![no_std]
12+
#![allow(unused_attributes)]
1213
#![unstable(feature = "alloc_jemalloc",
1314
reason = "this library is unlikely to be stabilized in its current \
1415
form or name",
@@ -19,8 +20,10 @@
1920
#![feature(libc)]
2021
#![feature(linkage)]
2122
#![feature(staged_api)]
23+
#![feature(rustc_attrs)]
2224
#![cfg_attr(dummy_jemalloc, allow(dead_code, unused_extern_crates))]
2325
#![cfg_attr(not(dummy_jemalloc), feature(allocator_api))]
26+
#![rustc_alloc_kind = "exe"]
2427

2528
extern crate alloc;
2629
extern crate alloc_system;

src/liballoc_system/lib.rs

+3
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
// except according to those terms.
1010

1111
#![no_std]
12+
#![allow(unused_attributes)]
1213
#![deny(warnings)]
1314
#![unstable(feature = "alloc_system",
1415
reason = "this library is unlikely to be stabilized in its current \
@@ -19,7 +20,9 @@
1920
#![feature(alloc)]
2021
#![feature(core_intrinsics)]
2122
#![feature(staged_api)]
23+
#![feature(rustc_attrs)]
2224
#![cfg_attr(any(unix, target_os = "redox"), feature(libc))]
25+
#![rustc_alloc_kind = "lib"]
2326

2427
// The minimum alignment guaranteed by the architecture. This value is used to
2528
// add fast paths for low alignment values. In practice, the alignment is a

src/librustc_metadata/creader.rs

+63-36
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use locator::{self, CratePaths};
1515
use native_libs::relevant_lib;
1616
use schema::CrateRoot;
1717

18-
use rustc::hir::def_id::{CrateNum, DefIndex};
18+
use rustc::hir::def_id::{CrateNum, DefIndex, CRATE_DEF_INDEX};
1919
use rustc::hir::svh::Svh;
2020
use rustc::middle::allocator::AllocatorKind;
2121
use rustc::middle::cstore::DepKind;
@@ -944,53 +944,80 @@ impl<'a> CrateLoader<'a> {
944944
// (need_lib_alloc and prefer_dynamic) then we select `None`, and if the
945945
// exe allocation crate doesn't exist for this target then we also
946946
// select `None`.
947-
let exe_allocation_crate =
947+
let exe_allocation_crate_data =
948948
if need_lib_alloc && !self.sess.opts.cg.prefer_dynamic {
949949
None
950950
} else {
951-
self.sess.target.target.options.exe_allocation_crate.as_ref()
951+
self.sess
952+
.target
953+
.target
954+
.options
955+
.exe_allocation_crate
956+
.as_ref()
957+
.map(|name| {
958+
// We've determined that we're injecting an "exe allocator" which means
959+
// that we're going to load up a whole new crate. An example of this is
960+
// that we're producing a normal binary on Linux which means we need to
961+
// load the `alloc_jemalloc` crate to link as an allocator.
962+
let name = Symbol::intern(name);
963+
let (cnum, data) = self.resolve_crate(&None,
964+
name,
965+
name,
966+
None,
967+
DUMMY_SP,
968+
PathKind::Crate,
969+
DepKind::Implicit);
970+
self.sess.injected_allocator.set(Some(cnum));
971+
data
972+
})
952973
};
953974

954-
match exe_allocation_crate {
955-
// We've determined that we're injecting an "exe allocator" which
956-
// means that we're going to load up a whole new crate. An example
957-
// of this is that we're producing a normal binary on Linux which
958-
// means we need to load the `alloc_jemalloc` crate to link as an
959-
// allocator.
960-
Some(krate) => {
961-
self.sess.allocator_kind.set(Some(AllocatorKind::DefaultExe));
962-
let name = Symbol::intern(krate);
963-
let dep_kind = DepKind::Implicit;
964-
let (cnum, _data) =
965-
self.resolve_crate(&None,
966-
name,
967-
name,
968-
None,
969-
DUMMY_SP,
970-
PathKind::Crate, dep_kind);
971-
self.sess.injected_allocator.set(Some(cnum));
975+
let allocation_crate_data = exe_allocation_crate_data.or_else(|| {
976+
if attr::contains_name(&krate.attrs, "default_lib_allocator") {
977+
// Prefer self as the allocator if there's a collision
978+
return None;
972979
}
973-
974980
// We're not actually going to inject an allocator, we're going to
975981
// require that something in our crate graph is the default lib
976982
// allocator. This is typically libstd, so this'll rarely be an
977983
// error.
978-
None => {
979-
self.sess.allocator_kind.set(Some(AllocatorKind::DefaultLib));
980-
let mut found_lib_allocator =
981-
attr::contains_name(&krate.attrs, "default_lib_allocator");
982-
self.cstore.iter_crate_data(|_, data| {
983-
if !found_lib_allocator {
984-
if data.has_default_lib_allocator() {
985-
found_lib_allocator = true;
986-
}
984+
let mut allocator = None;
985+
self.cstore.iter_crate_data(|_, data| {
986+
if allocator.is_none() && data.has_default_lib_allocator() {
987+
allocator = Some(data.clone());
988+
}
989+
});
990+
allocator
991+
});
992+
993+
match allocation_crate_data {
994+
Some(data) => {
995+
// We have an allocator. We detect separately what kind it is, to allow for some
996+
// flexibility in misconfiguration.
997+
let attrs = data.get_item_attrs(CRATE_DEF_INDEX);
998+
let kind_interned = attr::first_attr_value_str_by_name(&attrs, "rustc_alloc_kind")
999+
.map(Symbol::as_str);
1000+
let kind_str = kind_interned
1001+
.as_ref()
1002+
.map(|s| s as &str);
1003+
let alloc_kind = match kind_str {
1004+
None |
1005+
Some("lib") => AllocatorKind::DefaultLib,
1006+
Some("exe") => AllocatorKind::DefaultExe,
1007+
Some(other) => {
1008+
self.sess.err(&format!("Allocator kind {} not known", other));
1009+
return;
9871010
}
988-
});
989-
if found_lib_allocator {
990-
return
1011+
};
1012+
self.sess.allocator_kind.set(Some(alloc_kind));
1013+
},
1014+
None => {
1015+
if !attr::contains_name(&krate.attrs, "default_lib_allocator") {
1016+
self.sess.err("no #[default_lib_allocator] found but one is \
1017+
required; is libstd not linked?");
1018+
return;
9911019
}
992-
self.sess.err("no #[default_lib_allocator] found but one is \
993-
required; is libstd not linked?");
1020+
self.sess.allocator_kind.set(Some(AllocatorKind::DefaultLib));
9941021
}
9951022
}
9961023

0 commit comments

Comments
 (0)