Adapt backend to trans::partitioning dictating the codegen-unit setup.
This commit is contained in:
parent
2cd8cf92fc
commit
65e8a13441
|
@ -197,23 +197,70 @@ pub struct OutputFilenames {
|
||||||
pub outputs: HashMap<OutputType, Option<PathBuf>>,
|
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 {
|
impl OutputFilenames {
|
||||||
pub fn path(&self, flavor: OutputType) -> PathBuf {
|
pub fn path(&self, flavor: OutputType) -> PathBuf {
|
||||||
self.outputs.get(&flavor).and_then(|p| p.to_owned())
|
self.outputs.get(&flavor).and_then(|p| p.to_owned())
|
||||||
.or_else(|| self.single_output_file.clone())
|
.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());
|
let base = self.out_directory.join(&self.filestem());
|
||||||
match flavor {
|
|
||||||
OutputType::Bitcode => base.with_extension("bc"),
|
let mut extension = String::new();
|
||||||
OutputType::Assembly => base.with_extension("s"),
|
|
||||||
OutputType::LlvmAssembly => base.with_extension("ll"),
|
if let Some(codegen_unit_name) = codegen_unit_name {
|
||||||
OutputType::Object => base.with_extension("o"),
|
if codegen_unit_name.contains(NUMBERED_CODEGEN_UNIT_MARKER) {
|
||||||
OutputType::DepInfo => base.with_extension("d"),
|
// If we use the numbered naming scheme for modules, we don't want
|
||||||
OutputType::Exe => base,
|
// 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 {
|
pub fn with_extension(&self, extension: &str) -> PathBuf {
|
||||||
|
|
|
@ -1081,7 +1081,7 @@ pub fn phase_5_run_llvm_passes(sess: &Session,
|
||||||
|
|
||||||
// Remove assembly source, unless --save-temps was specified
|
// Remove assembly source, unless --save-temps was specified
|
||||||
if !sess.opts.cg.save_temps {
|
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 {
|
} else {
|
||||||
time(sess.time_passes(),
|
time(sess.time_passes(),
|
||||||
|
|
|
@ -205,7 +205,7 @@ pub fn link_binary(sess: &Session,
|
||||||
|
|
||||||
// Remove the temporary object file and metadata if we aren't saving temps
|
// Remove the temporary object file and metadata if we aren't saving temps
|
||||||
if !sess.opts.cg.save_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, &obj);
|
||||||
}
|
}
|
||||||
remove(sess, &outputs.with_extension("metadata.o"));
|
remove(sess, &outputs.with_extension("metadata.o"));
|
||||||
|
@ -316,7 +316,7 @@ fn link_binary_output(sess: &Session,
|
||||||
crate_type: config::CrateType,
|
crate_type: config::CrateType,
|
||||||
outputs: &OutputFilenames,
|
outputs: &OutputFilenames,
|
||||||
crate_name: &str) -> PathBuf {
|
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,
|
let default_filename = filename_for_input(sess, crate_type, crate_name,
|
||||||
outputs);
|
outputs);
|
||||||
let out_filename = outputs.outputs.get(&OutputType::Exe)
|
let out_filename = outputs.outputs.get(&OutputType::Exe)
|
||||||
|
@ -356,10 +356,11 @@ fn link_binary_output(sess: &Session,
|
||||||
out_filename
|
out_filename
|
||||||
}
|
}
|
||||||
|
|
||||||
fn object_filenames(sess: &Session, outputs: &OutputFilenames) -> Vec<PathBuf> {
|
fn object_filenames(trans: &CrateTranslation,
|
||||||
(0..sess.opts.cg.codegen_units).map(|i| {
|
outputs: &OutputFilenames)
|
||||||
let ext = format!("{}.o", i);
|
-> Vec<PathBuf> {
|
||||||
outputs.temp_path(OutputType::Object).with_extension(&ext)
|
trans.modules.iter().map(|module| {
|
||||||
|
outputs.temp_path(OutputType::Object, Some(&module.name[..]))
|
||||||
}).collect()
|
}).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -497,7 +498,7 @@ fn link_rlib<'a>(sess: &'a Session,
|
||||||
ab.add_file(&bc_deflated_filename);
|
ab.add_file(&bc_deflated_filename);
|
||||||
|
|
||||||
// See the bottom of back::write::run_passes for an explanation
|
// 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 =
|
let user_wants_numbered_bitcode =
|
||||||
sess.opts.output_types.contains_key(&OutputType::Bitcode) &&
|
sess.opts.output_types.contains_key(&OutputType::Bitcode) &&
|
||||||
sess.opts.cg.codegen_units > 1;
|
sess.opts.cg.codegen_units > 1;
|
||||||
|
|
|
@ -22,12 +22,12 @@ use libc;
|
||||||
use flate;
|
use flate;
|
||||||
|
|
||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
pub fn run(sess: &session::Session, llmod: ModuleRef,
|
pub fn run(sess: &session::Session, llmod: ModuleRef,
|
||||||
tm: TargetMachineRef, reachable: &[String],
|
tm: TargetMachineRef, reachable: &[String],
|
||||||
config: &ModuleConfig,
|
config: &ModuleConfig,
|
||||||
name_extra: &str,
|
temp_no_opt_bc_filename: &Path) {
|
||||||
output_names: &config::OutputFilenames) {
|
|
||||||
if sess.opts.cg.prefer_dynamic {
|
if sess.opts.cg.prefer_dynamic {
|
||||||
sess.struct_err("cannot prefer dynamic linking when performing LTO")
|
sess.struct_err("cannot prefer dynamic linking when performing LTO")
|
||||||
.note("only 'staticlib', 'bin', and 'cdylib' outputs are \
|
.note("only 'staticlib', 'bin', and 'cdylib' outputs are \
|
||||||
|
@ -132,8 +132,7 @@ pub fn run(sess: &session::Session, llmod: ModuleRef,
|
||||||
}
|
}
|
||||||
|
|
||||||
if sess.opts.cg.save_temps {
|
if sess.opts.cg.save_temps {
|
||||||
let path = output_names.with_extension(&format!("{}.no-opt.lto.bc", name_extra));
|
let cstr = path2cstr(temp_no_opt_bc_filename);
|
||||||
let cstr = path2cstr(&path);
|
|
||||||
unsafe {
|
unsafe {
|
||||||
llvm::LLVMWriteBitcodeToFile(llmod, cstr.as_ptr());
|
llvm::LLVMWriteBitcodeToFile(llmod, cstr.as_ptr());
|
||||||
}
|
}
|
||||||
|
|
|
@ -423,9 +423,9 @@ unsafe extern "C" fn diagnostic_handler(info: DiagnosticInfoRef, user: *mut c_vo
|
||||||
unsafe fn optimize_and_codegen(cgcx: &CodegenContext,
|
unsafe fn optimize_and_codegen(cgcx: &CodegenContext,
|
||||||
mtrans: ModuleTranslation,
|
mtrans: ModuleTranslation,
|
||||||
config: ModuleConfig,
|
config: ModuleConfig,
|
||||||
name_extra: String,
|
|
||||||
output_names: OutputFilenames) {
|
output_names: OutputFilenames) {
|
||||||
let ModuleTranslation { llmod, llcx } = mtrans;
|
let llmod = mtrans.llmod;
|
||||||
|
let llcx = mtrans.llcx;
|
||||||
let tm = config.tm;
|
let tm = config.tm;
|
||||||
|
|
||||||
// llcx doesn't outlive this function, so we can put this on the stack.
|
// llcx doesn't outlive this function, so we can put this on the stack.
|
||||||
|
@ -438,9 +438,10 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext,
|
||||||
llvm::LLVMSetInlineAsmDiagnosticHandler(llcx, inline_asm_handler, fv);
|
llvm::LLVMSetInlineAsmDiagnosticHandler(llcx, inline_asm_handler, fv);
|
||||||
llvm::LLVMContextSetDiagnosticHandler(llcx, diagnostic_handler, fv);
|
llvm::LLVMContextSetDiagnosticHandler(llcx, diagnostic_handler, fv);
|
||||||
|
|
||||||
|
let module_name = Some(&mtrans.name[..]);
|
||||||
|
|
||||||
if config.emit_no_opt_bc {
|
if config.emit_no_opt_bc {
|
||||||
let ext = format!("{}.no-opt.bc", name_extra);
|
let out = output_names.temp_path_ext("no-opt.bc", module_name);
|
||||||
let out = output_names.with_extension(&ext);
|
|
||||||
let out = path2cstr(&out);
|
let out = path2cstr(&out);
|
||||||
llvm::LLVMWriteBitcodeToFile(llmod, out.as_ptr());
|
llvm::LLVMWriteBitcodeToFile(llmod, out.as_ptr());
|
||||||
}
|
}
|
||||||
|
@ -512,13 +513,18 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext,
|
||||||
|
|
||||||
match cgcx.lto_ctxt {
|
match cgcx.lto_ctxt {
|
||||||
Some((sess, reachable)) if sess.lto() => {
|
Some((sess, reachable)) if sess.lto() => {
|
||||||
time(sess.time_passes(), "all lto passes", ||
|
time(sess.time_passes(), "all lto passes", || {
|
||||||
lto::run(sess, llmod, tm, reachable, &config,
|
let temp_no_opt_bc_filename =
|
||||||
&name_extra, &output_names));
|
output_names.temp_path_ext("no-opt.lto.bc", module_name);
|
||||||
|
lto::run(sess,
|
||||||
|
llmod,
|
||||||
|
tm,
|
||||||
|
reachable,
|
||||||
|
&config,
|
||||||
|
&temp_no_opt_bc_filename);
|
||||||
|
});
|
||||||
if config.emit_lto_bc {
|
if config.emit_lto_bc {
|
||||||
let name = format!("{}.lto.bc", name_extra);
|
let out = output_names.temp_path_ext("lto.bc", module_name);
|
||||||
let out = output_names.with_extension(&name);
|
|
||||||
let out = path2cstr(&out);
|
let out = path2cstr(&out);
|
||||||
llvm::LLVMWriteBitcodeToFile(llmod, out.as_ptr());
|
llvm::LLVMWriteBitcodeToFile(llmod, out.as_ptr());
|
||||||
}
|
}
|
||||||
|
@ -556,8 +562,8 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext,
|
||||||
let write_obj = config.emit_obj && !config.obj_is_bitcode;
|
let write_obj = config.emit_obj && !config.obj_is_bitcode;
|
||||||
let copy_bc_to_obj = config.emit_obj && config.obj_is_bitcode;
|
let copy_bc_to_obj = config.emit_obj && config.obj_is_bitcode;
|
||||||
|
|
||||||
let bc_out = output_names.with_extension(&format!("{}.bc", name_extra));
|
let bc_out = output_names.temp_path(OutputType::Bitcode, module_name);
|
||||||
let obj_out = output_names.with_extension(&format!("{}.o", name_extra));
|
let obj_out = output_names.temp_path(OutputType::Object, module_name);
|
||||||
|
|
||||||
if write_bc {
|
if write_bc {
|
||||||
let bc_out_c = path2cstr(&bc_out);
|
let bc_out_c = path2cstr(&bc_out);
|
||||||
|
@ -566,8 +572,7 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext,
|
||||||
|
|
||||||
time(config.time_passes, &format!("codegen passes [{}]", cgcx.worker), || {
|
time(config.time_passes, &format!("codegen passes [{}]", cgcx.worker), || {
|
||||||
if config.emit_ir {
|
if config.emit_ir {
|
||||||
let ext = format!("{}.ll", name_extra);
|
let out = output_names.temp_path(OutputType::LlvmAssembly, module_name);
|
||||||
let out = output_names.with_extension(&ext);
|
|
||||||
let out = path2cstr(&out);
|
let out = path2cstr(&out);
|
||||||
with_codegen(tm, llmod, config.no_builtins, |cpm| {
|
with_codegen(tm, llmod, config.no_builtins, |cpm| {
|
||||||
llvm::LLVMRustPrintModule(cpm, llmod, out.as_ptr());
|
llvm::LLVMRustPrintModule(cpm, llmod, out.as_ptr());
|
||||||
|
@ -576,7 +581,7 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext,
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.emit_asm {
|
if config.emit_asm {
|
||||||
let path = output_names.with_extension(&format!("{}.s", name_extra));
|
let path = output_names.temp_path(OutputType::Assembly, module_name);
|
||||||
|
|
||||||
// We can't use the same module for asm and binary output, because that triggers
|
// We can't use the same module for asm and binary output, because that triggers
|
||||||
// various errors like invalid IR or broken binaries, so we might have to clone the
|
// various errors like invalid IR or broken binaries, so we might have to clone the
|
||||||
|
@ -713,27 +718,29 @@ pub fn run_passes(sess: &Session,
|
||||||
|
|
||||||
{
|
{
|
||||||
let work = build_work_item(sess,
|
let work = build_work_item(sess,
|
||||||
trans.metadata_module,
|
trans.metadata_module.clone(),
|
||||||
metadata_config.clone(),
|
metadata_config.clone(),
|
||||||
crate_output.clone(),
|
crate_output.clone());
|
||||||
"metadata".to_string());
|
|
||||||
work_items.push(work);
|
work_items.push(work);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (index, mtrans) in trans.modules.iter().enumerate() {
|
for mtrans in trans.modules.iter() {
|
||||||
let work = build_work_item(sess,
|
let work = build_work_item(sess,
|
||||||
*mtrans,
|
mtrans.clone(),
|
||||||
modules_config.clone(),
|
modules_config.clone(),
|
||||||
crate_output.clone(),
|
crate_output.clone());
|
||||||
format!("{}", index));
|
|
||||||
work_items.push(work);
|
work_items.push(work);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process the work items, optionally using worker threads.
|
// Process the work items, optionally using worker threads.
|
||||||
if sess.opts.cg.codegen_units == 1 {
|
// NOTE: This code is not really adapted to incremental compilation where
|
||||||
|
// the compiler decides the number of codegen units (and will
|
||||||
|
// potentially create hundreds of them).
|
||||||
|
let num_workers = work_items.len() - 1;
|
||||||
|
if num_workers == 1 {
|
||||||
run_work_singlethreaded(sess, &trans.reachable, work_items);
|
run_work_singlethreaded(sess, &trans.reachable, work_items);
|
||||||
} else {
|
} else {
|
||||||
run_work_multithreaded(sess, work_items, sess.opts.cg.codegen_units);
|
run_work_multithreaded(sess, work_items, num_workers);
|
||||||
}
|
}
|
||||||
|
|
||||||
// All codegen is finished.
|
// All codegen is finished.
|
||||||
|
@ -748,32 +755,42 @@ pub fn run_passes(sess: &Session,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let copy_if_one_unit = |ext: &str,
|
let copy_if_one_unit = |output_type: OutputType,
|
||||||
output_type: OutputType,
|
|
||||||
keep_numbered: bool| {
|
keep_numbered: bool| {
|
||||||
if sess.opts.cg.codegen_units == 1 {
|
if trans.modules.len() == 1 {
|
||||||
// 1) Only one codegen unit. In this case it's no difficulty
|
// 1) Only one codegen unit. In this case it's no difficulty
|
||||||
// to copy `foo.0.x` to `foo.x`.
|
// to copy `foo.0.x` to `foo.x`.
|
||||||
copy_gracefully(&crate_output.with_extension(ext),
|
let module_name = Some(&(trans.modules[0].name)[..]);
|
||||||
|
let path = crate_output.temp_path(output_type, module_name);
|
||||||
|
copy_gracefully(&path,
|
||||||
&crate_output.path(output_type));
|
&crate_output.path(output_type));
|
||||||
if !sess.opts.cg.save_temps && !keep_numbered {
|
if !sess.opts.cg.save_temps && !keep_numbered {
|
||||||
// The user just wants `foo.x`, not `foo.0.x`.
|
// The user just wants `foo.x`, not `foo.#module-name#.x`.
|
||||||
remove(sess, &crate_output.with_extension(ext));
|
remove(sess, &path);
|
||||||
}
|
}
|
||||||
} else if crate_output.outputs.contains_key(&output_type) {
|
|
||||||
// 2) Multiple codegen units, with `--emit foo=some_name`. We have
|
|
||||||
// no good solution for this case, so warn the user.
|
|
||||||
sess.warn(&format!("ignoring emit path because multiple .{} files \
|
|
||||||
were produced", ext));
|
|
||||||
} else if crate_output.single_output_file.is_some() {
|
|
||||||
// 3) Multiple codegen units, with `-o some_name`. We have
|
|
||||||
// no good solution for this case, so warn the user.
|
|
||||||
sess.warn(&format!("ignoring -o because multiple .{} files \
|
|
||||||
were produced", ext));
|
|
||||||
} else {
|
} else {
|
||||||
// 4) Multiple codegen units, but no explicit name. We
|
let ext = crate_output.temp_path(output_type, None)
|
||||||
// just leave the `foo.0.x` files in place.
|
.extension()
|
||||||
// (We don't have to do any work in this case.)
|
.unwrap()
|
||||||
|
.to_str()
|
||||||
|
.unwrap()
|
||||||
|
.to_owned();
|
||||||
|
|
||||||
|
if crate_output.outputs.contains_key(&output_type) {
|
||||||
|
// 2) Multiple codegen units, with `--emit foo=some_name`. We have
|
||||||
|
// no good solution for this case, so warn the user.
|
||||||
|
sess.warn(&format!("ignoring emit path because multiple .{} files \
|
||||||
|
were produced", ext));
|
||||||
|
} else if crate_output.single_output_file.is_some() {
|
||||||
|
// 3) Multiple codegen units, with `-o some_name`. We have
|
||||||
|
// no good solution for this case, so warn the user.
|
||||||
|
sess.warn(&format!("ignoring -o because multiple .{} files \
|
||||||
|
were produced", ext));
|
||||||
|
} else {
|
||||||
|
// 4) Multiple codegen units, but no explicit name. We
|
||||||
|
// just leave the `foo.0.x` files in place.
|
||||||
|
// (We don't have to do any work in this case.)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -789,17 +806,19 @@ pub fn run_passes(sess: &Session,
|
||||||
// Copy to .bc, but always keep the .0.bc. There is a later
|
// Copy to .bc, but always keep the .0.bc. There is a later
|
||||||
// check to figure out if we should delete .0.bc files, or keep
|
// check to figure out if we should delete .0.bc files, or keep
|
||||||
// them for making an rlib.
|
// them for making an rlib.
|
||||||
copy_if_one_unit("0.bc", OutputType::Bitcode, true);
|
copy_if_one_unit(OutputType::Bitcode, true);
|
||||||
}
|
}
|
||||||
OutputType::LlvmAssembly => {
|
OutputType::LlvmAssembly => {
|
||||||
copy_if_one_unit("0.ll", OutputType::LlvmAssembly, false);
|
copy_if_one_unit(OutputType::LlvmAssembly, false);
|
||||||
}
|
}
|
||||||
OutputType::Assembly => {
|
OutputType::Assembly => {
|
||||||
copy_if_one_unit("0.s", OutputType::Assembly, false);
|
// TODO: These are probably wrong
|
||||||
|
copy_if_one_unit(OutputType::Assembly, false);
|
||||||
}
|
}
|
||||||
OutputType::Object => {
|
OutputType::Object => {
|
||||||
user_wants_objects = true;
|
user_wants_objects = true;
|
||||||
copy_if_one_unit("0.o", OutputType::Object, true);
|
// TODO: These are probably wrong
|
||||||
|
copy_if_one_unit(OutputType::Object, true);
|
||||||
}
|
}
|
||||||
OutputType::Exe |
|
OutputType::Exe |
|
||||||
OutputType::DepInfo => {}
|
OutputType::DepInfo => {}
|
||||||
|
@ -810,51 +829,55 @@ pub fn run_passes(sess: &Session,
|
||||||
// Clean up unwanted temporary files.
|
// Clean up unwanted temporary files.
|
||||||
|
|
||||||
// We create the following files by default:
|
// We create the following files by default:
|
||||||
// - crate.0.bc
|
// - crate.#module-name#.bc
|
||||||
// - crate.0.o
|
// - crate.#module-name#.o
|
||||||
// - crate.metadata.bc
|
// - crate.metadata.bc
|
||||||
// - crate.metadata.o
|
// - crate.metadata.o
|
||||||
// - crate.o (linked from crate.##.o)
|
// - crate.o (linked from crate.##.o)
|
||||||
// - crate.bc (copied from crate.0.bc)
|
// - crate.bc (copied from crate.##.bc)
|
||||||
// We may create additional files if requested by the user (through
|
// We may create additional files if requested by the user (through
|
||||||
// `-C save-temps` or `--emit=` flags).
|
// `-C save-temps` or `--emit=` flags).
|
||||||
|
|
||||||
if !sess.opts.cg.save_temps {
|
if !sess.opts.cg.save_temps {
|
||||||
// Remove the temporary .0.o objects. If the user didn't
|
// Remove the temporary .#module-name#.o objects. If the user didn't
|
||||||
// explicitly request bitcode (with --emit=bc), and the bitcode is not
|
// explicitly request bitcode (with --emit=bc), and the bitcode is not
|
||||||
// needed for building an rlib, then we must remove .0.bc as well.
|
// needed for building an rlib, then we must remove .#module-name#.bc as
|
||||||
|
// well.
|
||||||
|
|
||||||
// Specific rules for keeping .0.bc:
|
// Specific rules for keeping .#module-name#.bc:
|
||||||
// - If we're building an rlib (`needs_crate_bitcode`), then keep
|
// - If we're building an rlib (`needs_crate_bitcode`), then keep
|
||||||
// it.
|
// it.
|
||||||
// - If the user requested bitcode (`user_wants_bitcode`), and
|
// - If the user requested bitcode (`user_wants_bitcode`), and
|
||||||
// codegen_units > 1, then keep it.
|
// codegen_units > 1, then keep it.
|
||||||
// - If the user requested bitcode but codegen_units == 1, then we
|
// - If the user requested bitcode but codegen_units == 1, then we
|
||||||
// can toss .0.bc because we copied it to .bc earlier.
|
// can toss .#module-name#.bc because we copied it to .bc earlier.
|
||||||
// - If we're not building an rlib and the user didn't request
|
// - If we're not building an rlib and the user didn't request
|
||||||
// bitcode, then delete .0.bc.
|
// bitcode, then delete .#module-name#.bc.
|
||||||
// If you change how this works, also update back::link::link_rlib,
|
// If you change how this works, also update back::link::link_rlib,
|
||||||
// where .0.bc files are (maybe) deleted after making an rlib.
|
// where .#module-name#.bc files are (maybe) deleted after making an
|
||||||
|
// rlib.
|
||||||
let keep_numbered_bitcode = needs_crate_bitcode ||
|
let keep_numbered_bitcode = needs_crate_bitcode ||
|
||||||
(user_wants_bitcode && sess.opts.cg.codegen_units > 1);
|
(user_wants_bitcode && sess.opts.cg.codegen_units > 1);
|
||||||
|
|
||||||
let keep_numbered_objects = needs_crate_object ||
|
let keep_numbered_objects = needs_crate_object ||
|
||||||
(user_wants_objects && sess.opts.cg.codegen_units > 1);
|
(user_wants_objects && sess.opts.cg.codegen_units > 1);
|
||||||
|
|
||||||
for i in 0..trans.modules.len() {
|
for module_name in trans.modules.iter().map(|m| Some(&m.name[..])) {
|
||||||
if modules_config.emit_obj && !keep_numbered_objects {
|
if modules_config.emit_obj && !keep_numbered_objects {
|
||||||
let ext = format!("{}.o", i);
|
let path = crate_output.temp_path(OutputType::Object, module_name);
|
||||||
remove(sess, &crate_output.with_extension(&ext));
|
remove(sess, &path);
|
||||||
}
|
}
|
||||||
|
|
||||||
if modules_config.emit_bc && !keep_numbered_bitcode {
|
if modules_config.emit_bc && !keep_numbered_bitcode {
|
||||||
let ext = format!("{}.bc", i);
|
let path = crate_output.temp_path(OutputType::Bitcode, module_name);
|
||||||
remove(sess, &crate_output.with_extension(&ext));
|
remove(sess, &path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if metadata_config.emit_bc && !user_wants_bitcode {
|
if metadata_config.emit_bc && !user_wants_bitcode {
|
||||||
remove(sess, &crate_output.with_extension("metadata.bc"));
|
let path = crate_output.temp_path(OutputType::Bitcode,
|
||||||
|
Some(&trans.metadata_module.name[..]));
|
||||||
|
remove(sess, &path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -874,28 +897,31 @@ pub fn run_passes(sess: &Session,
|
||||||
struct WorkItem {
|
struct WorkItem {
|
||||||
mtrans: ModuleTranslation,
|
mtrans: ModuleTranslation,
|
||||||
config: ModuleConfig,
|
config: ModuleConfig,
|
||||||
output_names: OutputFilenames,
|
output_names: OutputFilenames
|
||||||
name_extra: String
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_work_item(sess: &Session,
|
fn build_work_item(sess: &Session,
|
||||||
mtrans: ModuleTranslation,
|
mtrans: ModuleTranslation,
|
||||||
config: ModuleConfig,
|
config: ModuleConfig,
|
||||||
output_names: OutputFilenames,
|
output_names: OutputFilenames)
|
||||||
name_extra: String)
|
|
||||||
-> WorkItem
|
-> WorkItem
|
||||||
{
|
{
|
||||||
let mut config = config;
|
let mut config = config;
|
||||||
config.tm = create_target_machine(sess);
|
config.tm = create_target_machine(sess);
|
||||||
WorkItem { mtrans: mtrans, config: config, output_names: output_names,
|
WorkItem {
|
||||||
name_extra: name_extra }
|
mtrans: mtrans,
|
||||||
|
config: config,
|
||||||
|
output_names: output_names
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_work_item(cgcx: &CodegenContext,
|
fn execute_work_item(cgcx: &CodegenContext,
|
||||||
work_item: WorkItem) {
|
work_item: WorkItem) {
|
||||||
unsafe {
|
unsafe {
|
||||||
optimize_and_codegen(cgcx, work_item.mtrans, work_item.config,
|
optimize_and_codegen(cgcx,
|
||||||
work_item.name_extra, work_item.output_names);
|
work_item.mtrans,
|
||||||
|
work_item.config,
|
||||||
|
work_item.output_names);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -914,6 +940,8 @@ fn run_work_singlethreaded(sess: &Session,
|
||||||
fn run_work_multithreaded(sess: &Session,
|
fn run_work_multithreaded(sess: &Session,
|
||||||
work_items: Vec<WorkItem>,
|
work_items: Vec<WorkItem>,
|
||||||
num_workers: usize) {
|
num_workers: usize) {
|
||||||
|
assert!(num_workers > 0);
|
||||||
|
|
||||||
// Run some workers to process the work items.
|
// Run some workers to process the work items.
|
||||||
let work_items_arc = Arc::new(Mutex::new(work_items));
|
let work_items_arc = Arc::new(Mutex::new(work_items));
|
||||||
let mut diag_emitter = SharedEmitter::new();
|
let mut diag_emitter = SharedEmitter::new();
|
||||||
|
@ -981,7 +1009,7 @@ pub fn run_assembler(sess: &Session, outputs: &OutputFilenames) {
|
||||||
let (pname, mut cmd, _) = get_linker(sess);
|
let (pname, mut cmd, _) = get_linker(sess);
|
||||||
|
|
||||||
cmd.arg("-c").arg("-o").arg(&outputs.path(OutputType::Object))
|
cmd.arg("-c").arg("-o").arg(&outputs.path(OutputType::Object))
|
||||||
.arg(&outputs.temp_path(OutputType::Assembly));
|
.arg(&outputs.temp_path(OutputType::Assembly, None));
|
||||||
debug!("{:?}", cmd);
|
debug!("{:?}", cmd);
|
||||||
|
|
||||||
match cmd.output() {
|
match cmd.output() {
|
||||||
|
|
|
@ -2630,6 +2630,7 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
});
|
});
|
||||||
|
|
||||||
let metadata_module = ModuleTranslation {
|
let metadata_module = ModuleTranslation {
|
||||||
|
name: "metadata".to_string(),
|
||||||
llcx: shared_ccx.metadata_llcx(),
|
llcx: shared_ccx.metadata_llcx(),
|
||||||
llmod: shared_ccx.metadata_llmod(),
|
llmod: shared_ccx.metadata_llmod(),
|
||||||
};
|
};
|
||||||
|
@ -2644,7 +2645,11 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
let crate_context_list = CrateContextList::new(&shared_ccx, codegen_units);
|
let crate_context_list = CrateContextList::new(&shared_ccx, codegen_units);
|
||||||
|
|
||||||
let modules = crate_context_list.iter()
|
let modules = crate_context_list.iter()
|
||||||
.map(|ccx| ModuleTranslation { llcx: ccx.llcx(), llmod: ccx.llmod() })
|
.map(|ccx| ModuleTranslation {
|
||||||
|
name: String::from(&ccx.codegen_unit().name[..]),
|
||||||
|
llcx: ccx.llcx(),
|
||||||
|
llmod: ccx.llmod()
|
||||||
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
// Skip crate items and just output metadata in -Z no-trans mode.
|
// Skip crate items and just output metadata in -Z no-trans mode.
|
||||||
|
@ -2790,6 +2795,7 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
let linker_info = LinkerInfo::new(&shared_ccx, &reachable_symbols);
|
let linker_info = LinkerInfo::new(&shared_ccx, &reachable_symbols);
|
||||||
|
|
||||||
CrateTranslation {
|
CrateTranslation {
|
||||||
modules: modules,
|
modules: modules,
|
||||||
metadata_module: metadata_module,
|
metadata_module: metadata_module,
|
||||||
|
|
|
@ -129,8 +129,9 @@ mod type_;
|
||||||
mod type_of;
|
mod type_of;
|
||||||
mod value;
|
mod value;
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Clone)]
|
||||||
pub struct ModuleTranslation {
|
pub struct ModuleTranslation {
|
||||||
|
pub name: String,
|
||||||
pub llcx: llvm::ContextRef,
|
pub llcx: llvm::ContextRef,
|
||||||
pub llmod: llvm::ModuleRef,
|
pub llmod: llvm::ModuleRef,
|
||||||
}
|
}
|
||||||
|
|
|
@ -121,6 +121,7 @@ use llvm;
|
||||||
use monomorphize;
|
use monomorphize;
|
||||||
use rustc::hir::def_id::DefId;
|
use rustc::hir::def_id::DefId;
|
||||||
use rustc::hir::map::DefPathData;
|
use rustc::hir::map::DefPathData;
|
||||||
|
use rustc::session::config::NUMBERED_CODEGEN_UNIT_MARKER;
|
||||||
use rustc::ty::TyCtxt;
|
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};
|
||||||
|
@ -283,7 +284,10 @@ fn merge_codegen_units<'tcx>(initial_partitioning: &mut PreInliningPartitioning<
|
||||||
}
|
}
|
||||||
|
|
||||||
fn numbered_codegen_unit_name(crate_name: &str, index: usize) -> InternedString {
|
fn numbered_codegen_unit_name(crate_name: &str, index: usize) -> InternedString {
|
||||||
token::intern_and_get_ident(&format!("{}.{}", crate_name, index)[..])
|
token::intern_and_get_ident(&format!("{}{}{}",
|
||||||
|
crate_name,
|
||||||
|
NUMBERED_CODEGEN_UNIT_MARKER,
|
||||||
|
index)[..])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue