Skip to content

Commit d119362

Browse files
authored
Auto merge of #33890 - michaelwoerister:collector-driven-trans, r=eddyb
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
2 parents e7751e4 + 1c03bfe commit d119362

38 files changed

+1389
-906
lines changed

src/librustc/session/config.rs

+56-9
Original file line numberDiff line numberDiff line change
@@ -197,23 +197,70 @@ pub struct OutputFilenames {
197197
pub outputs: HashMap<OutputType, Option<PathBuf>>,
198198
}
199199

200+
/// Codegen unit names generated by the numbered naming scheme will contain this
201+
/// marker right before the index of the codegen unit.
202+
pub const NUMBERED_CODEGEN_UNIT_MARKER: &'static str = ".cgu-";
203+
200204
impl OutputFilenames {
201205
pub fn path(&self, flavor: OutputType) -> PathBuf {
202206
self.outputs.get(&flavor).and_then(|p| p.to_owned())
203207
.or_else(|| self.single_output_file.clone())
204-
.unwrap_or_else(|| self.temp_path(flavor))
208+
.unwrap_or_else(|| self.temp_path(flavor, None))
205209
}
206210

207-
pub fn temp_path(&self, flavor: OutputType) -> PathBuf {
211+
/// Get the path where a compilation artifact of the given type for the
212+
/// given codegen unit should be placed on disk. If codegen_unit_name is
213+
/// None, a path distinct from those of any codegen unit will be generated.
214+
pub fn temp_path(&self,
215+
flavor: OutputType,
216+
codegen_unit_name: Option<&str>)
217+
-> PathBuf {
218+
let extension = match flavor {
219+
OutputType::Bitcode => "bc",
220+
OutputType::Assembly => "s",
221+
OutputType::LlvmAssembly => "ll",
222+
OutputType::Object => "o",
223+
OutputType::DepInfo => "d",
224+
OutputType::Exe => "",
225+
};
226+
227+
self.temp_path_ext(extension, codegen_unit_name)
228+
}
229+
230+
/// Like temp_path, but also supports things where there is no corresponding
231+
/// OutputType, like no-opt-bitcode or lto-bitcode.
232+
pub fn temp_path_ext(&self,
233+
ext: &str,
234+
codegen_unit_name: Option<&str>)
235+
-> PathBuf {
208236
let base = self.out_directory.join(&self.filestem());
209-
match flavor {
210-
OutputType::Bitcode => base.with_extension("bc"),
211-
OutputType::Assembly => base.with_extension("s"),
212-
OutputType::LlvmAssembly => base.with_extension("ll"),
213-
OutputType::Object => base.with_extension("o"),
214-
OutputType::DepInfo => base.with_extension("d"),
215-
OutputType::Exe => base,
237+
238+
let mut extension = String::new();
239+
240+
if let Some(codegen_unit_name) = codegen_unit_name {
241+
if codegen_unit_name.contains(NUMBERED_CODEGEN_UNIT_MARKER) {
242+
// If we use the numbered naming scheme for modules, we don't want
243+
// the files to look like <crate-name><extra>.<crate-name>.<index>.<ext>
244+
// but simply <crate-name><extra>.<index>.<ext>
245+
let marker_offset = codegen_unit_name.rfind(NUMBERED_CODEGEN_UNIT_MARKER)
246+
.unwrap();
247+
let index_offset = marker_offset + NUMBERED_CODEGEN_UNIT_MARKER.len();
248+
extension.push_str(&codegen_unit_name[index_offset .. ]);
249+
} else {
250+
extension.push_str(codegen_unit_name);
251+
};
252+
}
253+
254+
if !ext.is_empty() {
255+
if !extension.is_empty() {
256+
extension.push_str(".");
257+
}
258+
259+
extension.push_str(ext);
216260
}
261+
262+
let path = base.with_extension(&extension[..]);
263+
path
217264
}
218265

219266
pub fn with_extension(&self, extension: &str) -> PathBuf {

src/librustc_driver/driver.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1081,7 +1081,7 @@ pub fn phase_5_run_llvm_passes(sess: &Session,
10811081

10821082
// Remove assembly source, unless --save-temps was specified
10831083
if !sess.opts.cg.save_temps {
1084-
fs::remove_file(&outputs.temp_path(OutputType::Assembly)).unwrap();
1084+
fs::remove_file(&outputs.temp_path(OutputType::Assembly, None)).unwrap();
10851085
}
10861086
} else {
10871087
time(sess.time_passes(),

src/librustc_trans/abi.rs

+1
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,7 @@ impl ArgType {
229229
///
230230
/// I will do my best to describe this structure, but these
231231
/// comments are reverse-engineered and may be inaccurate. -NDM
232+
#[derive(Clone)]
232233
pub struct FnType {
233234
/// The LLVM types of each argument.
234235
pub args: Vec<ArgType>,

src/librustc_trans/back/link.rs

+8-7
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ pub fn link_binary(sess: &Session,
205205

206206
// Remove the temporary object file and metadata if we aren't saving temps
207207
if !sess.opts.cg.save_temps {
208-
for obj in object_filenames(sess, outputs) {
208+
for obj in object_filenames(trans, outputs) {
209209
remove(sess, &obj);
210210
}
211211
remove(sess, &outputs.with_extension("metadata.o"));
@@ -316,7 +316,7 @@ fn link_binary_output(sess: &Session,
316316
crate_type: config::CrateType,
317317
outputs: &OutputFilenames,
318318
crate_name: &str) -> PathBuf {
319-
let objects = object_filenames(sess, outputs);
319+
let objects = object_filenames(trans, outputs);
320320
let default_filename = filename_for_input(sess, crate_type, crate_name,
321321
outputs);
322322
let out_filename = outputs.outputs.get(&OutputType::Exe)
@@ -356,10 +356,11 @@ fn link_binary_output(sess: &Session,
356356
out_filename
357357
}
358358

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

@@ -497,7 +498,7 @@ fn link_rlib<'a>(sess: &'a Session,
497498
ab.add_file(&bc_deflated_filename);
498499

499500
// See the bottom of back::write::run_passes for an explanation
500-
// of when we do and don't keep .0.bc files around.
501+
// of when we do and don't keep .#module-name#.bc files around.
501502
let user_wants_numbered_bitcode =
502503
sess.opts.output_types.contains_key(&OutputType::Bitcode) &&
503504
sess.opts.cg.codegen_units > 1;

src/librustc_trans/back/lto.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,12 @@ use libc;
2222
use flate;
2323

2424
use std::ffi::CString;
25+
use std::path::Path;
2526

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

134134
if sess.opts.cg.save_temps {
135-
let path = output_names.with_extension(&format!("{}.no-opt.lto.bc", name_extra));
136-
let cstr = path2cstr(&path);
135+
let cstr = path2cstr(temp_no_opt_bc_filename);
137136
unsafe {
138137
llvm::LLVMWriteBitcodeToFile(llmod, cstr.as_ptr());
139138
}

src/librustc_trans/back/symbol_names.rs

+13
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,19 @@ impl ItemPathBuffer for SymbolPathBuffer {
304304
}
305305
}
306306

307+
pub fn exported_name_from_type_and_prefix<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
308+
t: ty::Ty<'tcx>,
309+
prefix: &str)
310+
-> String {
311+
let empty_def_path = DefPath {
312+
data: vec![],
313+
krate: cstore::LOCAL_CRATE,
314+
};
315+
let hash = get_symbol_hash(scx, &empty_def_path, t, &[]);
316+
let path = [token::intern_and_get_ident(prefix)];
317+
mangle(path.iter().cloned(), Some(&hash[..]))
318+
}
319+
307320
/// Only symbols that are invisible outside their compilation unit should use a
308321
/// name generated by this function.
309322
pub fn internal_name_from_type_and_suffix<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,

0 commit comments

Comments
 (0)