Skip to content

Commit 05b1b3e

Browse files
authored
Auto merge of #33890 - michaelwoerister:collector-driven-trans, r=michaelwoerister
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 e41cdab + 06b4eb9 commit 05b1b3e

37 files changed

+1363
-905
lines changed

src/librustc/session/config.rs

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

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

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

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

src/librustc_driver/driver.rs

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

10691069
// Remove assembly source, unless --save-temps was specified
10701070
if !sess.opts.cg.save_temps {
1071-
fs::remove_file(&outputs.temp_path(OutputType::Assembly)).unwrap();
1071+
fs::remove_file(&outputs.temp_path(OutputType::Assembly, None)).unwrap();
10721072
}
10731073
} else {
10741074
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
@@ -204,7 +204,7 @@ pub fn link_binary(sess: &Session,
204204

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

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

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

498499
// See the bottom of back::write::run_passes for an explanation
499-
// of when we do and don't keep .0.bc files around.
500+
// of when we do and don't keep .#module-name#.bc files around.
500501
let user_wants_numbered_bitcode =
501502
sess.opts.output_types.contains_key(&OutputType::Bitcode) &&
502503
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)