Skip to content

Commit 9ea3878

Browse files
committedOct 21, 2017
Auto merge of #45399 - alexcrichton:compress-parallel, r=michaelwoerister
rustc: Move bytecode compression into codegen This commit moves compression of the bytecode from the `link` module to the `write` module, namely allowing it to be (a) cached by incremental compilation and (b) produced in parallel. The parallelization may show up as some nice wins during normal compilation and the caching in incremental mode should be beneficial for incremental compiles! (no more need to recompress the entire crate's bitcode on all builds)
2 parents 4279e2b + 8197a0b commit 9ea3878

File tree

7 files changed

+193
-175
lines changed

7 files changed

+193
-175
lines changed
 

‎src/librustc/dep_graph/graph.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
1212
StableHashingContextProvider};
1313
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
1414
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
15-
use session::config::OutputType;
1615
use std::cell::{Ref, RefCell};
1716
use std::env;
1817
use std::hash::Hash;
@@ -647,7 +646,14 @@ impl DepGraph {
647646
pub struct WorkProduct {
648647
pub cgu_name: String,
649648
/// Saved files associated with this CGU
650-
pub saved_files: Vec<(OutputType, String)>,
649+
pub saved_files: Vec<(WorkProductFileKind, String)>,
650+
}
651+
652+
#[derive(Clone, Copy, Debug, RustcEncodable, RustcDecodable)]
653+
pub enum WorkProductFileKind {
654+
Object,
655+
Bytecode,
656+
BytecodeCompressed,
651657
}
652658

653659
pub(super) struct CurrentDepGraph {

‎src/librustc/dep_graph/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ mod serialized;
2121
pub use self::dep_tracking_map::{DepTrackingMap, DepTrackingMapConfig};
2222
pub use self::dep_node::{DepNode, DepKind, DepConstructor, WorkProductId, label_strs};
2323
pub use self::graph::{DepGraph, WorkProduct, DepNodeIndex, DepNodeColor};
24+
pub use self::graph::WorkProductFileKind;
2425
pub use self::prev::PreviousDepGraph;
2526
pub use self::query::DepGraphQuery;
2627
pub use self::safe::AssertDepGraphSafe;

‎src/librustc_incremental/persist/work_product.rs

+9-5
Original file line numberDiff line numberDiff line change
@@ -11,29 +11,33 @@
1111
//! This module contains files for saving intermediate work-products.
1212
1313
use persist::fs::*;
14-
use rustc::dep_graph::{WorkProduct, WorkProductId, DepGraph};
14+
use rustc::dep_graph::{WorkProduct, WorkProductId, DepGraph, WorkProductFileKind};
1515
use rustc::session::Session;
16-
use rustc::session::config::OutputType;
1716
use rustc::util::fs::link_or_copy;
1817
use std::path::PathBuf;
1918
use std::fs as std_fs;
2019

2120
pub fn save_trans_partition(sess: &Session,
2221
dep_graph: &DepGraph,
2322
cgu_name: &str,
24-
files: &[(OutputType, PathBuf)]) {
23+
files: &[(WorkProductFileKind, PathBuf)]) {
2524
debug!("save_trans_partition({:?},{:?})",
2625
cgu_name,
2726
files);
2827
if sess.opts.incremental.is_none() {
29-
return;
28+
return
3029
}
3130
let work_product_id = WorkProductId::from_cgu_name(cgu_name);
3231

3332
let saved_files: Option<Vec<_>> =
3433
files.iter()
3534
.map(|&(kind, ref path)| {
36-
let file_name = format!("cgu-{}.{}", cgu_name, kind.extension());
35+
let extension = match kind {
36+
WorkProductFileKind::Object => "o",
37+
WorkProductFileKind::Bytecode => "bc",
38+
WorkProductFileKind::BytecodeCompressed => "bc-compressed",
39+
};
40+
let file_name = format!("cgu-{}.{}", cgu_name, extension);
3741
let path_in_incr_dir = in_incr_comp_dir_sess(sess, &file_name);
3842
match link_or_copy(path, &path_in_incr_dir) {
3943
Ok(_) => Some((kind, file_name)),

‎src/librustc_trans/back/link.rs

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

1111
use super::archive::{ArchiveBuilder, ArchiveConfig};
12-
use super::bytecode::{self, RLIB_BYTECODE_EXTENSION};
12+
use super::bytecode::RLIB_BYTECODE_EXTENSION;
1313
use super::linker::Linker;
1414
use super::command::Command;
1515
use super::rpath::RPathConfig;
@@ -37,7 +37,7 @@ use std::env;
3737
use std::ffi::OsString;
3838
use std::fmt;
3939
use std::fs::{self, File};
40-
use std::io::{self, Read, Write, BufWriter};
40+
use std::io::{self, Write, BufWriter};
4141
use std::path::{Path, PathBuf};
4242
use std::process::{Output, Stdio};
4343
use std::str;
@@ -126,14 +126,6 @@ fn command_path(sess: &Session) -> OsString {
126126
env::join_paths(new_path).unwrap()
127127
}
128128

129-
fn metadata_obj(outputs: &OutputFilenames) -> PathBuf {
130-
outputs.temp_path(OutputType::Object, Some(METADATA_MODULE_NAME))
131-
}
132-
133-
fn allocator_obj(outputs: &OutputFilenames) -> PathBuf {
134-
outputs.temp_path(OutputType::Object, Some(ALLOCATOR_MODULE_NAME))
135-
}
136-
137129
pub fn remove(sess: &Session, path: &Path) {
138130
match fs::remove_file(path) {
139131
Ok(..) => {}
@@ -175,13 +167,23 @@ pub fn link_binary(sess: &Session,
175167
// Remove the temporary object file and metadata if we aren't saving temps
176168
if !sess.opts.cg.save_temps {
177169
if sess.opts.output_types.should_trans() {
178-
for obj in trans.modules.iter() {
179-
remove(sess, &obj.object);
170+
for obj in trans.modules.iter().filter_map(|m| m.object.as_ref()) {
171+
remove(sess, obj);
180172
}
181173
}
182-
remove(sess, &metadata_obj(outputs));
183-
if trans.allocator_module.is_some() {
184-
remove(sess, &allocator_obj(outputs));
174+
for obj in trans.modules.iter().filter_map(|m| m.bytecode_compressed.as_ref()) {
175+
remove(sess, obj);
176+
}
177+
if let Some(ref obj) = trans.metadata_module.object {
178+
remove(sess, obj);
179+
}
180+
if let Some(ref allocator) = trans.allocator_module {
181+
if let Some(ref obj) = allocator.object {
182+
remove(sess, obj);
183+
}
184+
if let Some(ref bc) = allocator.bytecode_compressed {
185+
remove(sess, bc);
186+
}
185187
}
186188
}
187189

@@ -256,8 +258,8 @@ fn link_binary_output(sess: &Session,
256258
crate_type: config::CrateType,
257259
outputs: &OutputFilenames,
258260
crate_name: &str) -> Vec<PathBuf> {
259-
for module in trans.modules.iter() {
260-
check_file_is_writeable(&module.object, sess);
261+
for obj in trans.modules.iter().filter_map(|m| m.object.as_ref()) {
262+
check_file_is_writeable(obj, sess);
261263
}
262264

263265
let tmpdir = match TempDir::new("rustc") {
@@ -280,20 +282,14 @@ fn link_binary_output(sess: &Session,
280282
link_rlib(sess,
281283
trans,
282284
RlibFlavor::Normal,
283-
outputs,
284285
&out_filename,
285286
tmpdir.path()).build();
286287
}
287288
config::CrateTypeStaticlib => {
288-
link_staticlib(sess,
289-
trans,
290-
outputs,
291-
&out_filename,
292-
tmpdir.path());
289+
link_staticlib(sess, trans, &out_filename, tmpdir.path());
293290
}
294291
_ => {
295-
link_natively(sess, crate_type, &out_filename,
296-
trans, outputs, tmpdir.path());
292+
link_natively(sess, crate_type, &out_filename, trans, tmpdir.path());
297293
}
298294
}
299295
out_filenames.push(out_filename);
@@ -349,14 +345,13 @@ enum RlibFlavor {
349345
fn link_rlib<'a>(sess: &'a Session,
350346
trans: &CrateTranslation,
351347
flavor: RlibFlavor,
352-
outputs: &OutputFilenames,
353348
out_filename: &Path,
354349
tmpdir: &Path) -> ArchiveBuilder<'a> {
355350
info!("preparing rlib to {:?}", out_filename);
356351
let mut ab = ArchiveBuilder::new(archive_config(sess, out_filename, None));
357352

358-
for module in trans.modules.iter() {
359-
ab.add_file(&module.object);
353+
for obj in trans.modules.iter().filter_map(|m| m.object.as_ref()) {
354+
ab.add_file(obj);
360355
}
361356

362357
// Note that in this loop we are ignoring the value of `lib.cfg`. That is,
@@ -421,56 +416,9 @@ fn link_rlib<'a>(sess: &'a Session,
421416
ab.add_file(&metadata);
422417

423418
// For LTO purposes, the bytecode of this library is also inserted
424-
// into the archive. If codegen_units > 1, we insert each of the
425-
// bitcode files.
426-
for module in trans.modules.iter() {
427-
// Note that we make sure that the bytecode filename in the
428-
// archive is never exactly 16 bytes long by adding a 16 byte
429-
// extension to it. This is to work around a bug in LLDB that
430-
// would cause it to crash if the name of a file in an archive
431-
// was exactly 16 bytes.
432-
let bc_filename = module.object.with_extension("bc");
433-
let bc_encoded_filename = tmpdir.join({
434-
module.object.with_extension(RLIB_BYTECODE_EXTENSION).file_name().unwrap()
435-
});
436-
437-
let mut bc_data = Vec::new();
438-
match fs::File::open(&bc_filename).and_then(|mut f| {
439-
f.read_to_end(&mut bc_data)
440-
}) {
441-
Ok(..) => {}
442-
Err(e) => sess.fatal(&format!("failed to read bytecode: {}",
443-
e))
444-
}
445-
446-
let encoded = bytecode::encode(&module.llmod_id, &bc_data);
447-
448-
let mut bc_file_deflated = match fs::File::create(&bc_encoded_filename) {
449-
Ok(file) => file,
450-
Err(e) => {
451-
sess.fatal(&format!("failed to create compressed \
452-
bytecode file: {}", e))
453-
}
454-
};
455-
456-
match bc_file_deflated.write_all(&encoded) {
457-
Ok(()) => {}
458-
Err(e) => {
459-
sess.fatal(&format!("failed to write compressed \
460-
bytecode: {}", e));
461-
}
462-
};
463-
464-
ab.add_file(&bc_encoded_filename);
465-
466-
// See the bottom of back::write::run_passes for an explanation
467-
// of when we do and don't keep .#module-name#.bc files around.
468-
let user_wants_numbered_bitcode =
469-
sess.opts.output_types.contains_key(&OutputType::Bitcode) &&
470-
sess.codegen_units() > 1;
471-
if !sess.opts.cg.save_temps && !user_wants_numbered_bitcode {
472-
remove(sess, &bc_filename);
473-
}
419+
// into the archive.
420+
for bytecode in trans.modules.iter().filter_map(|m| m.bytecode_compressed.as_ref()) {
421+
ab.add_file(bytecode);
474422
}
475423

476424
// After adding all files to the archive, we need to update the
@@ -482,8 +430,11 @@ fn link_rlib<'a>(sess: &'a Session,
482430
}
483431

484432
RlibFlavor::StaticlibBase => {
485-
if trans.allocator_module.is_some() {
486-
ab.add_file(&allocator_obj(outputs));
433+
let obj = trans.allocator_module
434+
.as_ref()
435+
.and_then(|m| m.object.as_ref());
436+
if let Some(obj) = obj {
437+
ab.add_file(obj);
487438
}
488439
}
489440
}
@@ -505,13 +456,11 @@ fn link_rlib<'a>(sess: &'a Session,
505456
// metadata file).
506457
fn link_staticlib(sess: &Session,
507458
trans: &CrateTranslation,
508-
outputs: &OutputFilenames,
509459
out_filename: &Path,
510460
tempdir: &Path) {
511461
let mut ab = link_rlib(sess,
512462
trans,
513463
RlibFlavor::StaticlibBase,
514-
outputs,
515464
out_filename,
516465
tempdir);
517466
let mut all_native_libs = vec![];
@@ -616,7 +565,6 @@ fn link_natively(sess: &Session,
616565
crate_type: config::CrateType,
617566
out_filename: &Path,
618567
trans: &CrateTranslation,
619-
outputs: &OutputFilenames,
620568
tmpdir: &Path) {
621569
info!("preparing {:?} to {:?}", crate_type, out_filename);
622570
let flavor = sess.linker_flavor();
@@ -656,7 +604,7 @@ fn link_natively(sess: &Session,
656604
{
657605
let mut linker = trans.linker_info.to_linker(cmd, &sess);
658606
link_args(&mut *linker, sess, crate_type, tmpdir,
659-
out_filename, outputs, trans);
607+
out_filename, trans);
660608
cmd = linker.finalize();
661609
}
662610
if let Some(args) = sess.target.target.options.late_link_args.get(&flavor) {
@@ -878,7 +826,6 @@ fn link_args(cmd: &mut Linker,
878826
crate_type: config::CrateType,
879827
tmpdir: &Path,
880828
out_filename: &Path,
881-
outputs: &OutputFilenames,
882829
trans: &CrateTranslation) {
883830

884831
// The default library location, we need this to find the runtime.
@@ -889,8 +836,8 @@ fn link_args(cmd: &mut Linker,
889836
let t = &sess.target.target;
890837

891838
cmd.include_path(&fix_windows_verbatim_for_gcc(&lib_path));
892-
for module in trans.modules.iter() {
893-
cmd.add_object(&module.object);
839+
for obj in trans.modules.iter().filter_map(|m| m.object.as_ref()) {
840+
cmd.add_object(obj);
894841
}
895842
cmd.output_filename(out_filename);
896843

@@ -913,11 +860,16 @@ fn link_args(cmd: &mut Linker,
913860
// object file, so we link that in here.
914861
if crate_type == config::CrateTypeDylib ||
915862
crate_type == config::CrateTypeProcMacro {
916-
cmd.add_object(&metadata_obj(outputs));
863+
if let Some(obj) = trans.metadata_module.object.as_ref() {
864+
cmd.add_object(obj);
865+
}
917866
}
918867

919-
if trans.allocator_module.is_some() {
920-
cmd.add_object(&allocator_obj(outputs));
868+
let obj = trans.allocator_module
869+
.as_ref()
870+
.and_then(|m| m.object.as_ref());
871+
if let Some(obj) = obj {
872+
cmd.add_object(obj);
921873
}
922874

923875
// Try to strip as much out of the generated object by removing unused
@@ -1185,9 +1137,9 @@ fn add_upstream_rust_crates(cmd: &mut Linker,
11851137

11861138
for f in archive.src_files() {
11871139
if f.ends_with(RLIB_BYTECODE_EXTENSION) || f == METADATA_FILENAME {
1188-
archive.remove_file(&f);
1189-
continue
1190-
}
1140+
archive.remove_file(&f);
1141+
continue
1142+
}
11911143
}
11921144

11931145
archive.build();

‎src/librustc_trans/back/lto.rs

+12-6
Original file line numberDiff line numberDiff line change
@@ -343,8 +343,7 @@ fn thin_lto(diag_handler: &Handler,
343343
info!("local module: {} - {}", i, module.llmod_id);
344344
let llvm = module.llvm().expect("can't lto pretranslated module");
345345
let name = CString::new(module.llmod_id.clone()).unwrap();
346-
let buffer = llvm::LLVMRustThinLTOBufferCreate(llvm.llmod);
347-
let buffer = ThinBuffer(buffer);
346+
let buffer = ThinBuffer::new(llvm.llmod);
348347
thin_modules.push(llvm::ThinLTOModule {
349348
identifier: name.as_ptr(),
350349
data: buffer.data().as_ptr(),
@@ -499,13 +498,13 @@ unsafe impl Send for ModuleBuffer {}
499498
unsafe impl Sync for ModuleBuffer {}
500499

501500
impl ModuleBuffer {
502-
fn new(m: ModuleRef) -> ModuleBuffer {
501+
pub fn new(m: ModuleRef) -> ModuleBuffer {
503502
ModuleBuffer(unsafe {
504503
llvm::LLVMRustModuleBufferCreate(m)
505504
})
506505
}
507506

508-
fn data(&self) -> &[u8] {
507+
pub fn data(&self) -> &[u8] {
509508
unsafe {
510509
let ptr = llvm::LLVMRustModuleBufferPtr(self.0);
511510
let len = llvm::LLVMRustModuleBufferLen(self.0);
@@ -545,13 +544,20 @@ impl Drop for ThinData {
545544
}
546545
}
547546

548-
struct ThinBuffer(*mut llvm::ThinLTOBuffer);
547+
pub struct ThinBuffer(*mut llvm::ThinLTOBuffer);
549548

550549
unsafe impl Send for ThinBuffer {}
551550
unsafe impl Sync for ThinBuffer {}
552551

553552
impl ThinBuffer {
554-
fn data(&self) -> &[u8] {
553+
pub fn new(m: ModuleRef) -> ThinBuffer {
554+
unsafe {
555+
let buffer = llvm::LLVMRustThinLTOBufferCreate(m);
556+
ThinBuffer(buffer)
557+
}
558+
}
559+
560+
pub fn data(&self) -> &[u8] {
555561
unsafe {
556562
let ptr = llvm::LLVMRustThinLTOBufferPtr(self.0) as *const _;
557563
let len = llvm::LLVMRustThinLTOBufferLen(self.0);

‎src/librustc_trans/back/write.rs

+93-62
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,15 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
use back::lto;
11+
use back::bytecode::{self, RLIB_BYTECODE_EXTENSION};
12+
use back::lto::{self, ModuleBuffer, ThinBuffer};
1213
use back::link::{self, get_linker, remove};
1314
use back::linker::LinkerInfo;
1415
use back::symbol_export::ExportedSymbols;
1516
use base;
1617
use consts;
1718
use rustc_incremental::{save_trans_partition, in_incr_comp_dir};
18-
use rustc::dep_graph::DepGraph;
19+
use rustc::dep_graph::{DepGraph, WorkProductFileKind};
1920
use rustc::middle::cstore::{LinkMeta, EncodedMetadata};
2021
use rustc::session::config::{self, OutputFilenames, OutputType, OutputTypes, Passes, SomePasses,
2122
AllPasses, Sanitizer};
@@ -44,7 +45,7 @@ use rustc_demangle;
4445

4546
use std::any::Any;
4647
use std::ffi::{CString, CStr};
47-
use std::fs;
48+
use std::fs::{self, File};
4849
use std::io;
4950
use std::io::Write;
5051
use std::mem;
@@ -228,6 +229,7 @@ pub struct ModuleConfig {
228229
// Flags indicating which outputs to produce.
229230
emit_no_opt_bc: bool,
230231
emit_bc: bool,
232+
emit_bc_compressed: bool,
231233
emit_lto_bc: bool,
232234
emit_ir: bool,
233235
emit_asm: bool,
@@ -257,6 +259,7 @@ impl ModuleConfig {
257259

258260
emit_no_opt_bc: false,
259261
emit_bc: false,
262+
emit_bc_compressed: false,
260263
emit_lto_bc: false,
261264
emit_ir: false,
262265
emit_asm: false,
@@ -627,20 +630,34 @@ unsafe fn codegen(cgcx: &CodegenContext,
627630
let bc_out = cgcx.output_filenames.temp_path(OutputType::Bitcode, module_name);
628631
let obj_out = cgcx.output_filenames.temp_path(OutputType::Object, module_name);
629632

630-
if write_bc {
631-
let bc_out_c = path2cstr(&bc_out);
632-
if llvm::LLVMRustThinLTOAvailable() {
633-
with_codegen(tm, llmod, config.no_builtins, |cpm| {
634-
llvm::LLVMRustWriteThinBitcodeToFile(
635-
cpm,
636-
llmod,
637-
bc_out_c.as_ptr(),
638-
)
639-
});
633+
634+
if write_bc || config.emit_bc_compressed {
635+
let thin;
636+
let old;
637+
let data = if llvm::LLVMRustThinLTOAvailable() {
638+
thin = ThinBuffer::new(llmod);
639+
thin.data()
640640
} else {
641-
llvm::LLVMWriteBitcodeToFile(llmod, bc_out_c.as_ptr());
641+
old = ModuleBuffer::new(llmod);
642+
old.data()
643+
};
644+
timeline.record("make-bc");
645+
646+
if write_bc {
647+
if let Err(e) = File::create(&bc_out).and_then(|mut f| f.write_all(data)) {
648+
diag_handler.err(&format!("failed to write bytecode: {}", e));
649+
}
650+
timeline.record("write-bc");
651+
}
652+
653+
if config.emit_bc_compressed {
654+
let dst = bc_out.with_extension(RLIB_BYTECODE_EXTENSION);
655+
let data = bytecode::encode(&mtrans.llmod_id, data);
656+
if let Err(e) = File::create(&dst).and_then(|mut f| f.write_all(&data)) {
657+
diag_handler.err(&format!("failed to write bytecode: {}", e));
658+
}
659+
timeline.record("compress-bc");
642660
}
643-
timeline.record("bc");
644661
}
645662

646663
time(config.time_passes, &format!("codegen passes [{}]", module_name.unwrap()),
@@ -736,6 +753,7 @@ unsafe fn codegen(cgcx: &CodegenContext,
736753
drop(handlers);
737754
Ok(mtrans.into_compiled_module(config.emit_obj,
738755
config.emit_bc,
756+
config.emit_bc_compressed,
739757
&cgcx.output_filenames))
740758
}
741759

@@ -822,11 +840,12 @@ pub fn start_async_translation(tcx: TyCtxt,
822840
allocator_config.emit_bc = true;
823841
}
824842

825-
// Emit bitcode files for the crate if we're emitting an rlib.
826-
// Whenever an rlib is created, the bitcode is inserted into the
827-
// archive in order to allow LTO against it.
843+
// Emit compressed bitcode files for the crate if we're emitting an rlib.
844+
// Whenever an rlib is created, the bitcode is inserted into the archive in
845+
// order to allow LTO against it.
828846
if need_crate_bitcode_for_rlib(sess) {
829-
modules_config.emit_bc = true;
847+
modules_config.emit_bc_compressed = true;
848+
allocator_config.emit_bc_compressed = true;
830849
}
831850

832851
for output_type in output_types_override.keys() {
@@ -906,29 +925,25 @@ pub fn start_async_translation(tcx: TyCtxt,
906925

907926
fn copy_module_artifacts_into_incr_comp_cache(sess: &Session,
908927
dep_graph: &DepGraph,
909-
compiled_modules: &CompiledModules,
910-
crate_output: &OutputFilenames) {
928+
compiled_modules: &CompiledModules) {
911929
if sess.opts.incremental.is_none() {
912930
return;
913931
}
914932

915933
for module in compiled_modules.modules.iter() {
916934
let mut files = vec![];
917935

918-
if module.emit_obj {
919-
let path = crate_output.temp_path(OutputType::Object, Some(&module.name));
920-
files.push((OutputType::Object, path));
936+
if let Some(ref path) = module.object {
937+
files.push((WorkProductFileKind::Object, path.clone()));
921938
}
922-
923-
if module.emit_bc {
924-
let path = crate_output.temp_path(OutputType::Bitcode, Some(&module.name));
925-
files.push((OutputType::Bitcode, path));
939+
if let Some(ref path) = module.bytecode {
940+
files.push((WorkProductFileKind::Bytecode, path.clone()));
941+
}
942+
if let Some(ref path) = module.bytecode_compressed {
943+
files.push((WorkProductFileKind::BytecodeCompressed, path.clone()));
926944
}
927945

928-
save_trans_partition(sess,
929-
dep_graph,
930-
&module.name,
931-
&files);
946+
save_trans_partition(sess, dep_graph, &module.name, &files);
932947
}
933948
}
934949

@@ -1032,8 +1047,6 @@ fn produce_final_output_artifacts(sess: &Session,
10321047
// well.
10331048

10341049
// Specific rules for keeping .#module-name#.bc:
1035-
// - If we're building an rlib (`needs_crate_bitcode`), then keep
1036-
// it.
10371050
// - If the user requested bitcode (`user_wants_bitcode`), and
10381051
// codegen_units > 1, then keep it.
10391052
// - If the user requested bitcode but codegen_units == 1, then we
@@ -1043,41 +1056,37 @@ fn produce_final_output_artifacts(sess: &Session,
10431056
// If you change how this works, also update back::link::link_rlib,
10441057
// where .#module-name#.bc files are (maybe) deleted after making an
10451058
// rlib.
1046-
let needs_crate_bitcode = need_crate_bitcode_for_rlib(sess);
10471059
let needs_crate_object = crate_output.outputs.contains_key(&OutputType::Exe);
10481060

1049-
let keep_numbered_bitcode = needs_crate_bitcode ||
1050-
(user_wants_bitcode && sess.codegen_units() > 1);
1061+
let keep_numbered_bitcode = user_wants_bitcode && sess.codegen_units() > 1;
10511062

10521063
let keep_numbered_objects = needs_crate_object ||
10531064
(user_wants_objects && sess.codegen_units() > 1);
10541065

10551066
for module in compiled_modules.modules.iter() {
1056-
let module_name = Some(&module.name[..]);
1057-
1058-
if module.emit_obj && !keep_numbered_objects {
1059-
let path = crate_output.temp_path(OutputType::Object, module_name);
1060-
remove(sess, &path);
1067+
if let Some(ref path) = module.object {
1068+
if !keep_numbered_objects {
1069+
remove(sess, path);
1070+
}
10611071
}
10621072

1063-
if module.emit_bc && !keep_numbered_bitcode {
1064-
let path = crate_output.temp_path(OutputType::Bitcode, module_name);
1065-
remove(sess, &path);
1073+
if let Some(ref path) = module.bytecode {
1074+
if !keep_numbered_bitcode {
1075+
remove(sess, path);
1076+
}
10661077
}
10671078
}
10681079

1069-
if compiled_modules.metadata_module.emit_bc && !user_wants_bitcode {
1070-
let path = crate_output.temp_path(OutputType::Bitcode,
1071-
Some(&compiled_modules.metadata_module.name));
1072-
remove(sess, &path);
1073-
}
1074-
1075-
if let Some(ref allocator_module) = compiled_modules.allocator_module {
1076-
if allocator_module.emit_bc && !user_wants_bitcode {
1077-
let path = crate_output.temp_path(OutputType::Bitcode,
1078-
Some(&allocator_module.name));
1080+
if !user_wants_bitcode {
1081+
if let Some(ref path) = compiled_modules.metadata_module.bytecode {
10791082
remove(sess, &path);
10801083
}
1084+
1085+
if let Some(ref allocator_module) = compiled_modules.allocator_module {
1086+
if let Some(ref path) = allocator_module.bytecode {
1087+
remove(sess, path);
1088+
}
1089+
}
10811090
}
10821091
}
10831092

@@ -1149,8 +1158,28 @@ fn execute_work_item(cgcx: &CodegenContext,
11491158
.as_ref()
11501159
.unwrap();
11511160
let name = &mtrans.name;
1161+
let mut object = None;
1162+
let mut bytecode = None;
1163+
let mut bytecode_compressed = None;
11521164
for (kind, saved_file) in wp.saved_files {
1153-
let obj_out = cgcx.output_filenames.temp_path(kind, Some(name));
1165+
let obj_out = match kind {
1166+
WorkProductFileKind::Object => {
1167+
let path = cgcx.output_filenames.temp_path(OutputType::Object, Some(name));
1168+
object = Some(path.clone());
1169+
path
1170+
}
1171+
WorkProductFileKind::Bytecode => {
1172+
let path = cgcx.output_filenames.temp_path(OutputType::Bitcode, Some(name));
1173+
bytecode = Some(path.clone());
1174+
path
1175+
}
1176+
WorkProductFileKind::BytecodeCompressed => {
1177+
let path = cgcx.output_filenames.temp_path(OutputType::Bitcode, Some(name))
1178+
.with_extension(RLIB_BYTECODE_EXTENSION);
1179+
bytecode_compressed = Some(path.clone());
1180+
path
1181+
}
1182+
};
11541183
let source_file = in_incr_comp_dir(&incr_comp_session_dir,
11551184
&saved_file);
11561185
debug!("copying pre-existing module `{}` from {:?} to {}",
@@ -1167,16 +1196,18 @@ fn execute_work_item(cgcx: &CodegenContext,
11671196
}
11681197
}
11691198
}
1170-
let object = cgcx.output_filenames.temp_path(OutputType::Object, Some(name));
1199+
assert_eq!(object.is_some(), config.emit_obj);
1200+
assert_eq!(bytecode.is_some(), config.emit_bc);
1201+
assert_eq!(bytecode_compressed.is_some(), config.emit_bc_compressed);
11711202

11721203
Ok(WorkItemResult::Compiled(CompiledModule {
1173-
object,
11741204
llmod_id: mtrans.llmod_id.clone(),
11751205
name: module_name,
11761206
kind: ModuleKind::Regular,
11771207
pre_existing: true,
1178-
emit_bc: config.emit_bc,
1179-
emit_obj: config.emit_obj,
1208+
object,
1209+
bytecode,
1210+
bytecode_compressed,
11801211
}))
11811212
} else {
11821213
debug!("llvm-optimizing {:?}", module_name);
@@ -2053,8 +2084,7 @@ impl OngoingCrateTranslation {
20532084

20542085
copy_module_artifacts_into_incr_comp_cache(sess,
20552086
dep_graph,
2056-
&compiled_modules,
2057-
&self.output_filenames);
2087+
&compiled_modules);
20582088
produce_final_output_artifacts(sess,
20592089
&compiled_modules,
20602090
&self.output_filenames);
@@ -2075,6 +2105,7 @@ impl OngoingCrateTranslation {
20752105

20762106
modules: compiled_modules.modules,
20772107
allocator_module: compiled_modules.allocator_module,
2108+
metadata_module: compiled_modules.metadata_module,
20782109
};
20792110

20802111
if self.no_integrated_as {

‎src/librustc_trans/lib.rs

+25-7
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ extern crate serialize;
6464
extern crate cc; // Used to locate MSVC
6565

6666
pub use base::trans_crate;
67+
use back::bytecode::RLIB_BYTECODE_EXTENSION;
6768

6869
pub use metadata::LlvmMetadataLoader;
6970
pub use llvm_util::{init, target_features, print_version, print_passes, print, enable_llvm_debug};
@@ -90,7 +91,7 @@ mod diagnostics;
9091

9192
pub mod back {
9293
mod archive;
93-
mod bytecode;
94+
pub mod bytecode;
9495
mod command;
9596
pub(crate) mod linker;
9697
pub mod link;
@@ -227,21 +228,37 @@ impl ModuleTranslation {
227228
pub fn into_compiled_module(self,
228229
emit_obj: bool,
229230
emit_bc: bool,
231+
emit_bc_compressed: bool,
230232
outputs: &OutputFilenames) -> CompiledModule {
231233
let pre_existing = match self.source {
232234
ModuleSource::Preexisting(_) => true,
233235
ModuleSource::Translated(_) => false,
234236
};
235-
let object = outputs.temp_path(OutputType::Object, Some(&self.name));
237+
let object = if emit_obj {
238+
Some(outputs.temp_path(OutputType::Object, Some(&self.name)))
239+
} else {
240+
None
241+
};
242+
let bytecode = if emit_bc {
243+
Some(outputs.temp_path(OutputType::Bitcode, Some(&self.name)))
244+
} else {
245+
None
246+
};
247+
let bytecode_compressed = if emit_bc_compressed {
248+
Some(outputs.temp_path(OutputType::Bitcode, Some(&self.name))
249+
.with_extension(RLIB_BYTECODE_EXTENSION))
250+
} else {
251+
None
252+
};
236253

237254
CompiledModule {
238255
llmod_id: self.llmod_id,
239256
name: self.name.clone(),
240257
kind: self.kind,
241258
pre_existing,
242-
emit_obj,
243-
emit_bc,
244259
object,
260+
bytecode,
261+
bytecode_compressed,
245262
}
246263
}
247264
}
@@ -250,11 +267,11 @@ impl ModuleTranslation {
250267
pub struct CompiledModule {
251268
pub name: String,
252269
pub llmod_id: String,
253-
pub object: PathBuf,
254270
pub kind: ModuleKind,
255271
pub pre_existing: bool,
256-
pub emit_obj: bool,
257-
pub emit_bc: bool,
272+
pub object: Option<PathBuf>,
273+
pub bytecode: Option<PathBuf>,
274+
pub bytecode_compressed: Option<PathBuf>,
258275
}
259276

260277
pub enum ModuleSource {
@@ -289,6 +306,7 @@ pub struct CrateTranslation {
289306
pub crate_name: Symbol,
290307
pub modules: Vec<CompiledModule>,
291308
allocator_module: Option<CompiledModule>,
309+
metadata_module: CompiledModule,
292310
pub link: rustc::middle::cstore::LinkMeta,
293311
pub metadata: rustc::middle::cstore::EncodedMetadata,
294312
windows_subsystem: Option<String>,

0 commit comments

Comments
 (0)
Please sign in to comment.