Auto merge of #55349 - bjorn3:rustc_mir_collect_and_partition_mono_items, r=oli-obk

Move collect_and_partition_mono_items to rustc_mir

Most of the logic of it is inside rustc_mir anyway.

Also removes the single function crate rustc_metadata_utils. Based on #55225
This commit is contained in:
bors 2018-11-04 12:20:55 +00:00
commit ac708826b0
20 changed files with 280 additions and 303 deletions

View file

@ -2141,11 +2141,13 @@ dependencies = [
"flate2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc 0.0.0",
"rustc_allocator 0.0.0",
"rustc_data_structures 0.0.0",
"rustc_incremental 0.0.0",
"rustc_metadata_utils 0.0.0",
"rustc_metadata 0.0.0",
"rustc_mir 0.0.0",
"rustc_target 0.0.0",
"serialize 0.0.0",
"syntax 0.0.0",
"syntax_pos 0.0.0",
]
@ -2289,7 +2291,6 @@ dependencies = [
"rustc 0.0.0",
"rustc_data_structures 0.0.0",
"rustc_errors 0.0.0",
"rustc_metadata_utils 0.0.0",
"rustc_target 0.0.0",
"serialize 0.0.0",
"syntax 0.0.0",
@ -2297,15 +2298,6 @@ dependencies = [
"syntax_pos 0.0.0",
]
[[package]]
name = "rustc_metadata_utils"
version = "0.0.0"
dependencies = [
"rustc 0.0.0",
"syntax 0.0.0",
"syntax_pos 0.0.0",
]
[[package]]
name = "rustc_mir"
version = "0.0.0"

View file

@ -52,28 +52,6 @@ enum Addition {
},
}
pub fn find_library(name: &str, search_paths: &[PathBuf], sess: &Session)
-> PathBuf {
// On Windows, static libraries sometimes show up as libfoo.a and other
// times show up as foo.lib
let oslibname = format!("{}{}{}",
sess.target.target.options.staticlib_prefix,
name,
sess.target.target.options.staticlib_suffix);
let unixlibname = format!("lib{}.a", name);
for path in search_paths {
debug!("looking for {} inside {:?}", name, path);
let test = path.join(&oslibname);
if test.exists() { return test }
if oslibname != unixlibname {
let test = path.join(&unixlibname);
if test.exists() { return test }
}
}
sess.fatal(&format!("could not find native static library `{}`, \
perhaps an -L flag is missing?", name));
}
fn is_relevant_child(c: &Child) -> bool {
match c.name() {
@ -128,7 +106,7 @@ fn src_archive(&mut self) -> Option<&ArchiveRO> {
/// Adds all of the contents of a native library to this archive. This will
/// search in the relevant locations for a library named `name`.
pub fn add_native_library(&mut self, name: &str) {
let location = find_library(name, &self.config.lib_search_paths,
let location = ::rustc_codegen_utils::find_library(name, &self.config.lib_search_paths,
self.config.sess);
self.add_archive(&location, |_| false).unwrap_or_else(|e| {
self.config.sess.fatal(&format!("failed to add native library {}: {}",

View file

@ -12,8 +12,6 @@
use cc::windows_registry;
use super::archive::{ArchiveBuilder, ArchiveConfig};
use super::bytecode::RLIB_BYTECODE_EXTENSION;
use super::linker::Linker;
use super::command::Command;
use super::rpath::RPathConfig;
use super::rpath;
use metadata::METADATA_FILENAME;
@ -31,6 +29,8 @@
use tempfile::{Builder as TempFileBuilder, TempDir};
use rustc_target::spec::{PanicStrategy, RelroLevel, LinkerFlavor};
use rustc_data_structures::fx::FxHashSet;
use rustc_codegen_utils::linker::Linker;
use rustc_codegen_utils::command::Command;
use context::get_reloc_model;
use llvm;
@ -701,7 +701,8 @@ fn link_natively(sess: &Session,
}
{
let mut linker = codegen_results.linker_info.to_linker(cmd, &sess, flavor);
let target_cpu = ::llvm_util::target_cpu(sess);
let mut linker = codegen_results.linker_info.to_linker(cmd, &sess, flavor, target_cpu);
link_args(&mut *linker, flavor, sess, crate_type, tmpdir,
out_filename, codegen_results);
cmd = linker.finalize();

View file

@ -9,7 +9,6 @@
// except according to those terms.
use back::bytecode::{DecodedBytecode, RLIB_BYTECODE_EXTENSION};
use back::symbol_export;
use back::write::{ModuleConfig, with_llvm_pmb, CodegenContext};
use back::write::{self, DiagnosticHandlers, pre_lto_bitcode_filename};
use errors::{FatalError, Handler};
@ -24,6 +23,7 @@
use rustc::session::config::{self, Lto};
use rustc::util::common::time_ext;
use rustc_data_structures::fx::FxHashMap;
use rustc_codegen_utils::symbol_export;
use time_graph::Timeline;
use {ModuleCodegen, ModuleLlvm, ModuleKind};

View file

@ -12,9 +12,6 @@
use back::bytecode::{self, RLIB_BYTECODE_EXTENSION};
use back::lto::{self, ModuleBuffer, ThinBuffer, SerializedModule};
use back::link::{self, get_linker, remove};
use back::command::Command;
use back::linker::LinkerInfo;
use back::symbol_export::ExportedSymbols;
use base;
use consts;
use memmap;
@ -38,6 +35,9 @@
use rustc_fs_util::{path2cstr, link_or_copy};
use rustc_data_structures::small_c_str::SmallCStr;
use rustc_data_structures::svh::Svh;
use rustc_codegen_utils::command::Command;
use rustc_codegen_utils::linker::LinkerInfo;
use rustc_codegen_utils::symbol_export::ExportedSymbols;
use errors::{self, Handler, Level, DiagnosticBuilder, FatalError, DiagnosticId};
use errors::emitter::{Emitter};
use syntax::attr;

View file

@ -54,7 +54,6 @@
use builder::{Builder, MemFlags};
use callee;
use common::{C_bool, C_bytes_in_context, C_i32, C_usize};
use rustc_mir::monomorphize::collector::{self, MonoItemCollectionMode};
use rustc_mir::monomorphize::item::DefPathBasedNames;
use common::{C_struct_in_context, C_array, val_ty};
use consts;
@ -64,13 +63,13 @@
use meth;
use mir;
use monomorphize::Instance;
use monomorphize::partitioning::{self, PartitioningStrategy, CodegenUnit, CodegenUnitExt};
use monomorphize::partitioning::{CodegenUnit, CodegenUnitExt};
use rustc_codegen_utils::symbol_names_test;
use time_graph;
use mono_item::{MonoItem, BaseMonoItemExt, MonoItemExt};
use mono_item::{MonoItem, MonoItemExt};
use type_::Type;
use type_of::LayoutLlvmExt;
use rustc::util::nodemap::{FxHashMap, DefIdSet};
use rustc::util::nodemap::FxHashMap;
use CrateInfo;
use rustc_data_structures::small_c_str::SmallCStr;
use rustc_data_structures::sync::Lrc;
@ -80,7 +79,6 @@
use std::ffi::CString;
use std::i32;
use std::ops::{Deref, DerefMut};
use std::sync::Arc;
use std::sync::mpsc;
use std::time::{Instant, Duration};
use syntax_pos::Span;
@ -1011,128 +1009,6 @@ fn assert_and_save_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
|| rustc_incremental::save_dep_graph(tcx));
}
fn collect_and_partition_mono_items<'a, 'tcx>(
tcx: TyCtxt<'a, 'tcx, 'tcx>,
cnum: CrateNum,
) -> (Arc<DefIdSet>, Arc<Vec<Arc<CodegenUnit<'tcx>>>>)
{
assert_eq!(cnum, LOCAL_CRATE);
let collection_mode = match tcx.sess.opts.debugging_opts.print_mono_items {
Some(ref s) => {
let mode_string = s.to_lowercase();
let mode_string = mode_string.trim();
if mode_string == "eager" {
MonoItemCollectionMode::Eager
} else {
if mode_string != "lazy" {
let message = format!("Unknown codegen-item collection mode '{}'. \
Falling back to 'lazy' mode.",
mode_string);
tcx.sess.warn(&message);
}
MonoItemCollectionMode::Lazy
}
}
None => {
if tcx.sess.opts.cg.link_dead_code {
MonoItemCollectionMode::Eager
} else {
MonoItemCollectionMode::Lazy
}
}
};
let (items, inlining_map) =
time(tcx.sess, "monomorphization collection", || {
collector::collect_crate_mono_items(tcx, collection_mode)
});
tcx.sess.abort_if_errors();
::rustc_mir::monomorphize::assert_symbols_are_distinct(tcx, items.iter());
let strategy = if tcx.sess.opts.incremental.is_some() {
PartitioningStrategy::PerModule
} else {
PartitioningStrategy::FixedUnitCount(tcx.sess.codegen_units())
};
let codegen_units = time(tcx.sess, "codegen unit partitioning", || {
partitioning::partition(tcx,
items.iter().cloned(),
strategy,
&inlining_map)
.into_iter()
.map(Arc::new)
.collect::<Vec<_>>()
});
let mono_items: DefIdSet = items.iter().filter_map(|mono_item| {
match *mono_item {
MonoItem::Fn(ref instance) => Some(instance.def_id()),
MonoItem::Static(def_id) => Some(def_id),
_ => None,
}
}).collect();
if tcx.sess.opts.debugging_opts.print_mono_items.is_some() {
let mut item_to_cgus: FxHashMap<_, Vec<_>> = Default::default();
for cgu in &codegen_units {
for (&mono_item, &linkage) in cgu.items() {
item_to_cgus.entry(mono_item)
.or_default()
.push((cgu.name().clone(), linkage));
}
}
let mut item_keys: Vec<_> = items
.iter()
.map(|i| {
let mut output = i.to_string(tcx);
output.push_str(" @@");
let mut empty = Vec::new();
let cgus = item_to_cgus.get_mut(i).unwrap_or(&mut empty);
cgus.as_mut_slice().sort_by_key(|&(ref name, _)| name.clone());
cgus.dedup();
for &(ref cgu_name, (linkage, _)) in cgus.iter() {
output.push_str(" ");
output.push_str(&cgu_name.as_str());
let linkage_abbrev = match linkage {
Linkage::External => "External",
Linkage::AvailableExternally => "Available",
Linkage::LinkOnceAny => "OnceAny",
Linkage::LinkOnceODR => "OnceODR",
Linkage::WeakAny => "WeakAny",
Linkage::WeakODR => "WeakODR",
Linkage::Appending => "Appending",
Linkage::Internal => "Internal",
Linkage::Private => "Private",
Linkage::ExternalWeak => "ExternalWeak",
Linkage::Common => "Common",
};
output.push_str("[");
output.push_str(linkage_abbrev);
output.push_str("]");
}
output
})
.collect();
item_keys.sort();
for item in item_keys {
println!("MONO_ITEM {}", item);
}
}
(Arc::new(mono_items), Arc::new(codegen_units))
}
impl CrateInfo {
pub fn new(tcx: TyCtxt) -> CrateInfo {
let mut info = CrateInfo {
@ -1222,12 +1098,6 @@ fn load_wasm_imports(&mut self, tcx: TyCtxt, cnum: CrateNum) {
}
}
fn is_codegened_item(tcx: TyCtxt, id: DefId) -> bool {
let (all_mono_items, _) =
tcx.collect_and_partition_mono_items(LOCAL_CRATE);
all_mono_items.contains(&id)
}
fn compile_codegen_unit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
cgu_name: InternedString)
-> Stats {
@ -1318,24 +1188,7 @@ fn module_codegen<'a, 'tcx>(
}
}
pub fn provide(providers: &mut Providers) {
providers.collect_and_partition_mono_items =
collect_and_partition_mono_items;
providers.is_codegened_item = is_codegened_item;
providers.codegen_unit = |tcx, name| {
let (_, all) = tcx.collect_and_partition_mono_items(LOCAL_CRATE);
all.iter()
.find(|cgu| *cgu.name() == name)
.cloned()
.unwrap_or_else(|| panic!("failed to find cgu with name {:?}", name))
};
provide_extern(providers);
}
pub fn provide_extern(providers: &mut Providers) {
pub fn provide_both(providers: &mut Providers) {
providers.dllimport_foreign_items = |tcx, krate| {
let module_map = tcx.foreign_modules(krate);
let module_map = module_map.iter()

View file

@ -71,7 +71,6 @@
pub use llvm_util::target_features;
use std::any::Any;
use std::path::{PathBuf};
use std::sync::mpsc;
use rustc_data_structures::sync::Lrc;
@ -87,20 +86,17 @@
use rustc::util::nodemap::{FxHashSet, FxHashMap};
use rustc::util::profiling::ProfileCategory;
use rustc_mir::monomorphize;
use rustc_codegen_utils::{CompiledModule, ModuleKind};
use rustc_codegen_utils::codegen_backend::CodegenBackend;
use rustc_data_structures::svh::Svh;
mod diagnostics;
mod back {
pub use rustc_codegen_utils::symbol_names;
mod archive;
pub mod bytecode;
mod command;
pub mod linker;
pub mod link;
pub mod lto;
pub mod symbol_export;
pub mod write;
mod rpath;
pub mod wasm;
@ -194,15 +190,15 @@ fn metadata_loader(&self) -> Box<dyn MetadataLoader + Sync> {
}
fn provide(&self, providers: &mut ty::query::Providers) {
back::symbol_names::provide(providers);
back::symbol_export::provide(providers);
base::provide(providers);
rustc_codegen_utils::symbol_export::provide(providers);
rustc_codegen_utils::symbol_names::provide(providers);
base::provide_both(providers);
attributes::provide(providers);
}
fn provide_extern(&self, providers: &mut ty::query::Providers) {
back::symbol_export::provide_extern(providers);
base::provide_extern(providers);
rustc_codegen_utils::symbol_export::provide_extern(providers);
base::provide_both(providers);
attributes::provide_extern(providers);
}
@ -281,13 +277,6 @@ struct CachedModuleCodegen {
source: WorkProduct,
}
#[derive(Copy, Clone, Debug, PartialEq)]
enum ModuleKind {
Regular,
Metadata,
Allocator,
}
impl ModuleCodegen {
fn into_compiled_module(self,
emit_obj: bool,
@ -321,15 +310,6 @@ fn into_compiled_module(self,
}
}
#[derive(Debug)]
struct CompiledModule {
name: String,
kind: ModuleKind,
object: Option<PathBuf>,
bytecode: Option<PathBuf>,
bytecode_compressed: Option<PathBuf>,
}
struct ModuleLlvm {
llcx: &'static mut llvm::Context,
llmod_raw: *const llvm::Module,
@ -377,7 +357,7 @@ struct CodegenResults {
crate_hash: Svh,
metadata: rustc::middle::cstore::EncodedMetadata,
windows_subsystem: Option<String>,
linker_info: back::linker::LinkerInfo,
linker_info: rustc_codegen_utils::linker::LinkerInfo,
crate_info: CrateInfo,
}

View file

@ -13,11 +13,13 @@ test = false
flate2 = "1.0"
log = "0.4"
serialize = { path = "../libserialize" }
syntax = { path = "../libsyntax" }
syntax_pos = { path = "../libsyntax_pos" }
rustc = { path = "../librustc" }
rustc_allocator = { path = "../librustc_allocator" }
rustc_target = { path = "../librustc_target" }
rustc_data_structures = { path = "../librustc_data_structures" }
rustc_metadata = { path = "../librustc_metadata" }
rustc_mir = { path = "../librustc_mir" }
rustc_incremental = { path = "../librustc_incremental" }
rustc_metadata_utils = { path = "../librustc_metadata_utils" }

View file

@ -30,20 +30,28 @@
#[macro_use]
extern crate log;
extern crate serialize;
#[macro_use]
extern crate rustc;
extern crate rustc_allocator;
extern crate rustc_target;
extern crate rustc_metadata;
extern crate rustc_mir;
extern crate rustc_incremental;
extern crate syntax;
extern crate syntax_pos;
#[macro_use] extern crate rustc_data_structures;
extern crate rustc_metadata_utils;
use std::path::PathBuf;
use rustc::session::Session;
use rustc::ty::TyCtxt;
pub mod command;
pub mod link;
pub mod linker;
pub mod codegen_backend;
pub mod symbol_export;
pub mod symbol_names;
pub mod symbol_names_test;
@ -61,4 +69,43 @@ pub fn check_for_rustc_errors_attr(tcx: TyCtxt) {
}
}
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum ModuleKind {
Regular,
Metadata,
Allocator,
}
#[derive(Debug)]
pub struct CompiledModule {
pub name: String,
pub kind: ModuleKind,
pub object: Option<PathBuf>,
pub bytecode: Option<PathBuf>,
pub bytecode_compressed: Option<PathBuf>,
}
pub fn find_library(name: &str, search_paths: &[PathBuf], sess: &Session)
-> PathBuf {
// On Windows, static libraries sometimes show up as libfoo.a and other
// times show up as foo.lib
let oslibname = format!("{}{}{}",
sess.target.target.options.staticlib_prefix,
name,
sess.target.target.options.staticlib_suffix);
let unixlibname = format!("lib{}.a", name);
for path in search_paths {
debug!("looking for {} inside {:?}", name, path);
let test = path.join(&oslibname);
if test.exists() { return test }
if oslibname != unixlibname {
let test = path.join(&unixlibname);
if test.exists() { return test }
}
}
sess.fatal(&format!("could not find native static library `{}`, \
perhaps an -L flag is missing?", name));
}
__build_diagnostic_array! { librustc_codegen_utils, DIAGNOSTICS }

View file

@ -13,7 +13,6 @@
use std::path::{Path, PathBuf};
use syntax::{ast, attr};
use syntax_pos::Span;
use rustc_metadata_utils::validate_crate_name;
pub fn out_filename(sess: &Session,
crate_type: config::CrateType,
@ -52,7 +51,7 @@ pub fn find_crate_name(sess: Option<&Session>,
attrs: &[ast::Attribute],
input: &Input) -> String {
let validate = |s: String, span: Option<Span>| {
validate_crate_name(sess, &s, span);
::rustc_metadata::validate_crate_name(sess, &s, span);
s
};

View file

@ -15,9 +15,7 @@
use std::io::{self, BufWriter};
use std::path::{Path, PathBuf};
use back::archive;
use back::command::Command;
use back::symbol_export;
use command::Command;
use rustc::hir::def_id::{LOCAL_CRATE, CrateNum};
use rustc::middle::dependency_format::Linkage;
use rustc::session::Session;
@ -26,7 +24,6 @@
use rustc::ty::TyCtxt;
use rustc_target::spec::{LinkerFlavor, LldFlavor};
use serialize::{json, Encoder};
use llvm_util;
/// For all the linkers we support, and information they might
/// need out of the shared crate context before we get rid of it.
@ -43,10 +40,13 @@ pub fn new(tcx: TyCtxt) -> LinkerInfo {
}
}
pub fn to_linker<'a>(&'a self,
cmd: Command,
sess: &'a Session,
flavor: LinkerFlavor) -> Box<dyn Linker+'a> {
pub fn to_linker<'a>(
&'a self,
cmd: Command,
sess: &'a Session,
flavor: LinkerFlavor,
target_cpu: &'a str,
) -> Box<dyn Linker+'a> {
match flavor {
LinkerFlavor::Lld(LldFlavor::Link) |
LinkerFlavor::Msvc => {
@ -70,6 +70,7 @@ pub fn to_linker<'a>(&'a self,
info: self,
hinted_static: false,
is_ld: false,
target_cpu,
}) as Box<dyn Linker>
}
@ -82,6 +83,7 @@ pub fn to_linker<'a>(&'a self,
info: self,
hinted_static: false,
is_ld: true,
target_cpu,
}) as Box<dyn Linker>
}
@ -144,6 +146,7 @@ pub struct GccLinker<'a> {
hinted_static: bool, // Keeps track of the current hinting mode.
// Link as ld
is_ld: bool,
target_cpu: &'a str,
}
impl<'a> GccLinker<'a> {
@ -204,7 +207,8 @@ fn push_cross_lang_lto_args(&mut self, plugin_path: Option<&OsStr>) {
};
self.linker_arg(&format!("-plugin-opt={}", opt_level));
self.linker_arg(&format!("-plugin-opt=mcpu={}", llvm_util::target_cpu(self.sess)));
let target_cpu = self.target_cpu;
self.linker_arg(&format!("-plugin-opt=mcpu={}", target_cpu));
match self.sess.lto() {
config::Lto::Thin |
@ -263,7 +267,7 @@ fn link_whole_staticlib(&mut self, lib: &str, search_path: &[PathBuf]) {
// -force_load is the macOS equivalent of --whole-archive, but it
// involves passing the full path to the library to link.
self.linker_arg("-force_load");
let lib = archive::find_library(lib, search_path, &self.sess);
let lib = ::find_library(lib, search_path, &self.sess);
self.linker_arg(&lib);
}
}
@ -898,7 +902,8 @@ fn cross_lang_lto(&mut self) {
fn exported_symbols(tcx: TyCtxt, crate_type: CrateType) -> Vec<String> {
let mut symbols = Vec::new();
let export_threshold = symbol_export::crates_export_threshold(&[crate_type]);
let export_threshold =
::symbol_export::crates_export_threshold(&[crate_type]);
for &(symbol, level) in tcx.exported_symbols(LOCAL_CRATE).iter() {
if level.is_below_threshold(export_threshold) {
symbols.push(symbol.symbol_name(tcx).to_string());

View file

@ -11,7 +11,7 @@
use rustc_data_structures::sync::Lrc;
use std::sync::Arc;
use monomorphize::Instance;
use rustc::ty::Instance;
use rustc::hir;
use rustc::hir::Node;
use rustc::hir::CodegenFnAttrFlags;

View file

@ -20,4 +20,3 @@ serialize = { path = "../libserialize" }
syntax = { path = "../libsyntax" }
syntax_ext = { path = "../libsyntax_ext" }
syntax_pos = { path = "../libsyntax_pos" }
rustc_metadata_utils = { path = "../librustc_metadata_utils" }

View file

@ -30,8 +30,6 @@
use rustc::util::nodemap::FxHashSet;
use rustc::hir::map::Definitions;
use rustc_metadata_utils::validate_crate_name;
use std::ops::Deref;
use std::path::PathBuf;
use std::{cmp, fs};
@ -1106,7 +1104,7 @@ pub fn process_extern_crate(
item.ident, orig_name);
let orig_name = match orig_name {
Some(orig_name) => {
validate_crate_name(Some(self.sess), &orig_name.as_str(),
::validate_crate_name(Some(self.sess), &orig_name.as_str(),
Some(item.span));
orig_name
}

View file

@ -38,7 +38,6 @@
extern crate rustc_errors as errors;
extern crate syntax_ext;
extern crate proc_macro;
extern crate rustc_metadata_utils;
#[macro_use]
extern crate rustc;
@ -64,4 +63,34 @@
pub mod dynamic_lib;
pub mod locator;
pub fn validate_crate_name(
sess: Option<&rustc::session::Session>,
s: &str,
sp: Option<syntax_pos::Span>
) {
let mut err_count = 0;
{
let mut say = |s: &str| {
match (sp, sess) {
(_, None) => bug!("{}", s),
(Some(sp), Some(sess)) => sess.span_err(sp, s),
(None, Some(sess)) => sess.err(s),
}
err_count += 1;
};
if s.is_empty() {
say("crate name must not be empty");
}
for c in s.chars() {
if c.is_alphanumeric() { continue }
if c == '_' { continue }
say(&format!("invalid character `{}` in crate name: `{}`", c, s));
}
}
if err_count > 0 {
sess.unwrap().abort_if_errors();
}
}
__build_diagnostic_array! { librustc_metadata, DIAGNOSTICS }

View file

@ -1,14 +0,0 @@
[package]
authors = ["The Rust Project Developers"]
name = "rustc_metadata_utils"
version = "0.0.0"
[lib]
name = "rustc_metadata_utils"
path = "lib.rs"
crate-type = ["dylib"]
[dependencies]
rustc = { path = "../librustc" }
syntax = { path = "../libsyntax" }
syntax_pos = { path = "../libsyntax_pos" }

View file

@ -1,42 +0,0 @@
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use]
extern crate rustc;
extern crate syntax_pos;
use rustc::session::Session;
use syntax_pos::Span;
pub fn validate_crate_name(sess: Option<&Session>, s: &str, sp: Option<Span>) {
let mut err_count = 0;
{
let mut say = |s: &str| {
match (sp, sess) {
(_, None) => bug!("{}", s),
(Some(sp), Some(sess)) => sess.span_err(sp, s),
(None, Some(sess)) => sess.err(s),
}
err_count += 1;
};
if s.is_empty() {
say("crate name must not be empty");
}
for c in s.chars() {
if c.is_alphanumeric() { continue }
if c == '_' { continue }
say(&format!("invalid character `{}` in crate name: `{}`", c, s));
}
}
if err_count > 0 {
sess.unwrap().abort_if_errors();
}
}

View file

@ -93,6 +93,7 @@ pub fn provide(providers: &mut Providers) {
borrow_check::provide(providers);
shim::provide(providers);
transform::provide(providers);
monomorphize::partitioning::provide(providers);
providers.const_eval = const_eval::const_eval_provider;
providers.const_eval_raw = const_eval::const_eval_raw_provider;
providers.check_match = hair::pattern::check_match;

View file

@ -102,21 +102,27 @@
//! source-level module, functions from the same module will be available for
//! inlining, even when they are not marked #[inline].
use monomorphize::collector::InliningMap;
use std::collections::hash_map::Entry;
use std::cmp;
use std::sync::Arc;
use syntax::ast::NodeId;
use syntax::symbol::InternedString;
use rustc::dep_graph::{WorkProductId, WorkProduct, DepNode, DepConstructor};
use rustc::hir::CodegenFnAttrFlags;
use rustc::hir::def_id::{DefId, LOCAL_CRATE, CRATE_DEF_INDEX};
use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE, CRATE_DEF_INDEX};
use rustc::hir::map::DefPathData;
use rustc::mir::mono::{Linkage, Visibility, CodegenUnitNameBuilder};
use rustc::middle::exported_symbols::SymbolExportLevel;
use rustc::ty::{self, TyCtxt, InstanceDef};
use rustc::ty::item_path::characteristic_def_id_of_type;
use rustc::util::nodemap::{FxHashMap, FxHashSet};
use std::collections::hash_map::Entry;
use std::cmp;
use syntax::ast::NodeId;
use syntax::symbol::InternedString;
use rustc::ty::query::Providers;
use rustc::util::common::time;
use rustc::util::nodemap::{DefIdSet, FxHashMap, FxHashSet};
use rustc::mir::mono::MonoItem;
use monomorphize::collector::InliningMap;
use monomorphize::collector::{self, MonoItemCollectionMode};
use monomorphize::item::{MonoItemExt, InstantiationMode};
pub use rustc::mir::mono::CodegenUnit;
@ -892,3 +898,146 @@ fn debug_dump<'a, 'b, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
}
}
}
fn collect_and_partition_mono_items<'a, 'tcx>(
tcx: TyCtxt<'a, 'tcx, 'tcx>,
cnum: CrateNum,
) -> (Arc<DefIdSet>, Arc<Vec<Arc<CodegenUnit<'tcx>>>>)
{
assert_eq!(cnum, LOCAL_CRATE);
let collection_mode = match tcx.sess.opts.debugging_opts.print_mono_items {
Some(ref s) => {
let mode_string = s.to_lowercase();
let mode_string = mode_string.trim();
if mode_string == "eager" {
MonoItemCollectionMode::Eager
} else {
if mode_string != "lazy" {
let message = format!("Unknown codegen-item collection mode '{}'. \
Falling back to 'lazy' mode.",
mode_string);
tcx.sess.warn(&message);
}
MonoItemCollectionMode::Lazy
}
}
None => {
if tcx.sess.opts.cg.link_dead_code {
MonoItemCollectionMode::Eager
} else {
MonoItemCollectionMode::Lazy
}
}
};
let (items, inlining_map) =
time(tcx.sess, "monomorphization collection", || {
collector::collect_crate_mono_items(tcx, collection_mode)
});
tcx.sess.abort_if_errors();
::monomorphize::assert_symbols_are_distinct(tcx, items.iter());
let strategy = if tcx.sess.opts.incremental.is_some() {
PartitioningStrategy::PerModule
} else {
PartitioningStrategy::FixedUnitCount(tcx.sess.codegen_units())
};
let codegen_units = time(tcx.sess, "codegen unit partitioning", || {
partition(
tcx,
items.iter().cloned(),
strategy,
&inlining_map
)
.into_iter()
.map(Arc::new)
.collect::<Vec<_>>()
});
let mono_items: DefIdSet = items.iter().filter_map(|mono_item| {
match *mono_item {
MonoItem::Fn(ref instance) => Some(instance.def_id()),
MonoItem::Static(def_id) => Some(def_id),
_ => None,
}
}).collect();
if tcx.sess.opts.debugging_opts.print_mono_items.is_some() {
let mut item_to_cgus: FxHashMap<_, Vec<_>> = Default::default();
for cgu in &codegen_units {
for (&mono_item, &linkage) in cgu.items() {
item_to_cgus.entry(mono_item)
.or_default()
.push((cgu.name().clone(), linkage));
}
}
let mut item_keys: Vec<_> = items
.iter()
.map(|i| {
let mut output = i.to_string(tcx);
output.push_str(" @@");
let mut empty = Vec::new();
let cgus = item_to_cgus.get_mut(i).unwrap_or(&mut empty);
cgus.as_mut_slice().sort_by_key(|&(ref name, _)| name.clone());
cgus.dedup();
for &(ref cgu_name, (linkage, _)) in cgus.iter() {
output.push_str(" ");
output.push_str(&cgu_name.as_str());
let linkage_abbrev = match linkage {
Linkage::External => "External",
Linkage::AvailableExternally => "Available",
Linkage::LinkOnceAny => "OnceAny",
Linkage::LinkOnceODR => "OnceODR",
Linkage::WeakAny => "WeakAny",
Linkage::WeakODR => "WeakODR",
Linkage::Appending => "Appending",
Linkage::Internal => "Internal",
Linkage::Private => "Private",
Linkage::ExternalWeak => "ExternalWeak",
Linkage::Common => "Common",
};
output.push_str("[");
output.push_str(linkage_abbrev);
output.push_str("]");
}
output
})
.collect();
item_keys.sort();
for item in item_keys {
println!("MONO_ITEM {}", item);
}
}
(Arc::new(mono_items), Arc::new(codegen_units))
}
pub fn provide(providers: &mut Providers) {
providers.collect_and_partition_mono_items =
collect_and_partition_mono_items;
providers.is_codegened_item = |tcx, def_id| {
let (all_mono_items, _) =
tcx.collect_and_partition_mono_items(LOCAL_CRATE);
all_mono_items.contains(&def_id)
};
providers.codegen_unit = |tcx, name| {
let (_, all) = tcx.collect_and_partition_mono_items(LOCAL_CRATE);
all.iter()
.find(|cgu| *cgu.name() == name)
.cloned()
.unwrap_or_else(|| panic!("failed to find cgu with name {:?}", name))
};
}