Skip to content

Commit

Permalink
Auto merge of #33890 - michaelwoerister:collector-driven-trans, r=eddyb
Browse files Browse the repository at this point in the history
Drive trans from the output of the translation item collector

This PR changes the way how translation works above the item level. Instead of walking the HIR and calling `trans_item()` on everything encountered (while instantiating monomorphizations on-demand), we now just process the list of translation items generated by the `trans::collector`. Using the collector has the benefit of being able to know the exact set of monomorphizations and symbols before actually running translation, something that is crucial for incremental compilation (but also has [other benefits](#33602)).

The collector has existed for quite a while now, but so far it's output was only used for running some auto-tests. With this PR it becomes the only source of truth about what gets translated.

One modification we had to make, compared to the initial approach, is that closures are not represented as their own `TransItems`. Doing so, while still supporting non-MIR-based translation, would have been prohibitively complex, and not worth the trouble since legacy-trans will disappear sooner or later. Once there is solely MIR-trans, it would be a good idea to make closures `TransItems` again.

This PR removes the most obvious functions and tables that are not needed anymore, but there's definitely still more cleanup possible later on (e.g. `monomorphize::monomorphic_fn()` does very little at this point). Since there are already more than 10 commits in here, doing this in a separate PR seems to be a better idea.

These changes definitely warrant a crater run.

Thanks @Aatch, for taking on one of the more tedious tasks during the dev-sprint!
Thanks @eddyb, for doing some nice refactorings to symbol name generation and making sure these landed so I could use them!

cc @rust-lang/compiler
cc @rust-lang/tools
  • Loading branch information
bors authored Jun 28, 2016
2 parents 366de83 + 18a46bc commit fa4e100
Show file tree
Hide file tree
Showing 38 changed files with 1,373 additions and 906 deletions.
65 changes: 56 additions & 9 deletions src/librustc/session/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,23 +197,70 @@ pub struct OutputFilenames {
pub outputs: HashMap<OutputType, Option<PathBuf>>,
}

/// Codegen unit names generated by the numbered naming scheme will contain this
/// marker right before the index of the codegen unit.
pub const NUMBERED_CODEGEN_UNIT_MARKER: &'static str = ".cgu-";

impl OutputFilenames {
pub fn path(&self, flavor: OutputType) -> PathBuf {
self.outputs.get(&flavor).and_then(|p| p.to_owned())
.or_else(|| self.single_output_file.clone())
.unwrap_or_else(|| self.temp_path(flavor))
.unwrap_or_else(|| self.temp_path(flavor, None))
}

pub fn temp_path(&self, flavor: OutputType) -> PathBuf {
/// Get the path where a compilation artifact of the given type for the
/// given codegen unit should be placed on disk. If codegen_unit_name is
/// None, a path distinct from those of any codegen unit will be generated.
pub fn temp_path(&self,
flavor: OutputType,
codegen_unit_name: Option<&str>)
-> PathBuf {
let extension = match flavor {
OutputType::Bitcode => "bc",
OutputType::Assembly => "s",
OutputType::LlvmAssembly => "ll",
OutputType::Object => "o",
OutputType::DepInfo => "d",
OutputType::Exe => "",
};

self.temp_path_ext(extension, codegen_unit_name)
}

/// Like temp_path, but also supports things where there is no corresponding
/// OutputType, like no-opt-bitcode or lto-bitcode.
pub fn temp_path_ext(&self,
ext: &str,
codegen_unit_name: Option<&str>)
-> PathBuf {
let base = self.out_directory.join(&self.filestem());
match flavor {
OutputType::Bitcode => base.with_extension("bc"),
OutputType::Assembly => base.with_extension("s"),
OutputType::LlvmAssembly => base.with_extension("ll"),
OutputType::Object => base.with_extension("o"),
OutputType::DepInfo => base.with_extension("d"),
OutputType::Exe => base,

let mut extension = String::new();

if let Some(codegen_unit_name) = codegen_unit_name {
if codegen_unit_name.contains(NUMBERED_CODEGEN_UNIT_MARKER) {
// If we use the numbered naming scheme for modules, we don't want
// the files to look like <crate-name><extra>.<crate-name>.<index>.<ext>
// but simply <crate-name><extra>.<index>.<ext>
let marker_offset = codegen_unit_name.rfind(NUMBERED_CODEGEN_UNIT_MARKER)
.unwrap();
let index_offset = marker_offset + NUMBERED_CODEGEN_UNIT_MARKER.len();
extension.push_str(&codegen_unit_name[index_offset .. ]);
} else {
extension.push_str(codegen_unit_name);
};
}

if !ext.is_empty() {
if !extension.is_empty() {
extension.push_str(".");
}

extension.push_str(ext);
}

let path = base.with_extension(&extension[..]);
path
}

pub fn with_extension(&self, extension: &str) -> PathBuf {
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_driver/driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1092,7 +1092,7 @@ pub fn phase_5_run_llvm_passes(sess: &Session,

// Remove assembly source, unless --save-temps was specified
if !sess.opts.cg.save_temps {
fs::remove_file(&outputs.temp_path(OutputType::Assembly)).unwrap();
fs::remove_file(&outputs.temp_path(OutputType::Assembly, None)).unwrap();
}
} else {
time(sess.time_passes(),
Expand Down
1 change: 1 addition & 0 deletions src/librustc_trans/abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,7 @@ impl ArgType {
///
/// I will do my best to describe this structure, but these
/// comments are reverse-engineered and may be inaccurate. -NDM
#[derive(Clone)]
pub struct FnType {
/// The LLVM types of each argument.
pub args: Vec<ArgType>,
Expand Down
15 changes: 8 additions & 7 deletions src/librustc_trans/back/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ pub fn link_binary(sess: &Session,

// Remove the temporary object file and metadata if we aren't saving temps
if !sess.opts.cg.save_temps {
for obj in object_filenames(sess, outputs) {
for obj in object_filenames(trans, outputs) {
remove(sess, &obj);
}
remove(sess, &outputs.with_extension("metadata.o"));
Expand Down Expand Up @@ -315,7 +315,7 @@ fn link_binary_output(sess: &Session,
crate_type: config::CrateType,
outputs: &OutputFilenames,
crate_name: &str) -> PathBuf {
let objects = object_filenames(sess, outputs);
let objects = object_filenames(trans, outputs);
let default_filename = filename_for_input(sess, crate_type, crate_name,
outputs);
let out_filename = outputs.outputs.get(&OutputType::Exe)
Expand Down Expand Up @@ -355,10 +355,11 @@ fn link_binary_output(sess: &Session,
out_filename
}

fn object_filenames(sess: &Session, outputs: &OutputFilenames) -> Vec<PathBuf> {
(0..sess.opts.cg.codegen_units).map(|i| {
let ext = format!("{}.o", i);
outputs.temp_path(OutputType::Object).with_extension(&ext)
fn object_filenames(trans: &CrateTranslation,
outputs: &OutputFilenames)
-> Vec<PathBuf> {
trans.modules.iter().map(|module| {
outputs.temp_path(OutputType::Object, Some(&module.name[..]))
}).collect()
}

Expand Down Expand Up @@ -496,7 +497,7 @@ fn link_rlib<'a>(sess: &'a Session,
ab.add_file(&bc_deflated_filename);

// See the bottom of back::write::run_passes for an explanation
// of when we do and don't keep .0.bc files around.
// of when we do and don't keep .#module-name#.bc files around.
let user_wants_numbered_bitcode =
sess.opts.output_types.contains_key(&OutputType::Bitcode) &&
sess.opts.cg.codegen_units > 1;
Expand Down
7 changes: 3 additions & 4 deletions src/librustc_trans/back/lto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,12 @@ use libc;
use flate;

use std::ffi::CString;
use std::path::Path;

pub fn run(sess: &session::Session, llmod: ModuleRef,
tm: TargetMachineRef, reachable: &[String],
config: &ModuleConfig,
name_extra: &str,
output_names: &config::OutputFilenames) {
temp_no_opt_bc_filename: &Path) {
if sess.opts.cg.prefer_dynamic {
sess.struct_err("cannot prefer dynamic linking when performing LTO")
.note("only 'staticlib', 'bin', and 'cdylib' outputs are \
Expand Down Expand Up @@ -132,8 +132,7 @@ pub fn run(sess: &session::Session, llmod: ModuleRef,
}

if sess.opts.cg.save_temps {
let path = output_names.with_extension(&format!("{}.no-opt.lto.bc", name_extra));
let cstr = path2cstr(&path);
let cstr = path2cstr(temp_no_opt_bc_filename);
unsafe {
llvm::LLVMWriteBitcodeToFile(llmod, cstr.as_ptr());
}
Expand Down
13 changes: 13 additions & 0 deletions src/librustc_trans/back/symbol_names.rs
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,19 @@ impl ItemPathBuffer for SymbolPathBuffer {
}
}

pub fn exported_name_from_type_and_prefix<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
t: ty::Ty<'tcx>,
prefix: &str)
-> String {
let empty_def_path = DefPath {
data: vec![],
krate: cstore::LOCAL_CRATE,
};
let hash = get_symbol_hash(scx, &empty_def_path, t, &[]);
let path = [token::intern_and_get_ident(prefix)];
mangle(path.iter().cloned(), Some(&hash[..]))
}

/// Only symbols that are invisible outside their compilation unit should use a
/// name generated by this function.
pub fn internal_name_from_type_and_suffix<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
Expand Down
Loading

0 comments on commit fa4e100

Please sign in to comment.