Skip to content

Commit 23868af

Browse files
committed
Correctly implement --emit
1 parent ad1886a commit 23868af

File tree

3 files changed

+201
-30
lines changed

3 files changed

+201
-30
lines changed

scripts/test_rustc_tests.sh

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,8 @@ rm -r tests/run-pass-valgrind/unsized-locals
5151

5252
# misc unimplemented things
5353
rm tests/ui/target-feature/missing-plusminus.rs # error not implemented
54-
rm -r tests/run-make/emit-named-files # requires full --emit support
5554
rm -r tests/run-make/repr128-dwarf # debuginfo test
5655
rm -r tests/run-make/split-debuginfo # same
57-
rm -r tests/run-make/symbols-include-type-name # --emit=asm not supported
5856
rm -r tests/run-make/target-specs # i686 not supported by Cranelift
5957
rm -r tests/run-make/mismatching-target-triples # same
6058
rm tests/ui/asm/x86_64/issue-96797.rs # const and sym inline asm operands don't work entirely correctly
@@ -92,6 +90,17 @@ rm tests/ui/abi/stack-protector.rs # requires stack protector support
9290
rm -r tests/run-make/emit-stack-sizes # requires support for -Z emit-stack-sizes
9391
rm -r tests/run-make/optimization-remarks-dir # remarks are LLVM specific
9492

93+
# requires asm, llvm-ir and/or llvm-bc emit support
94+
# =============================================
95+
rm -r tests/run-make/emit-named-files
96+
rm -r tests/run-make/issue-30063
97+
rm -r tests/run-make/multiple-emits
98+
rm -r tests/run-make/output-type-permutations
99+
rm -r tests/run-make/emit-to-stdout
100+
rm -r tests/run-make/compressed-debuginfo
101+
rm -r tests/run-make/symbols-include-type-name
102+
103+
95104
# giving different but possibly correct results
96105
# =============================================
97106
rm tests/ui/mir/mir_misc_casts.rs # depends on deduplication of constants
@@ -109,17 +118,8 @@ rm -r tests/run-make/compiler-builtins # Expects lib/rustlib/src/rust to contain
109118
# ============
110119
rm tests/incremental/spike-neg1.rs # errors out for some reason
111120
rm tests/incremental/spike-neg2.rs # same
112-
113-
rm -r tests/run-make/issue-51671 # wrong filename given in case of --emit=obj
114-
rm -r tests/run-make/issue-30063 # same
115-
rm -r tests/run-make/multiple-emits # same
116-
rm -r tests/run-make/output-type-permutations # same
117-
rm -r tests/run-make/used # same
118-
rm -r tests/run-make/no-alloc-shim
119-
rm -r tests/run-make/emit-to-stdout
120-
rm -r tests/run-make/compressed-debuginfo
121-
122121
rm -r tests/run-make/extern-fn-explicit-align # argument alignment not yet supported
122+
rm -r tests/run-make/panic-abort-eh_frame # .eh_frame emitted with panic=abort
123123

124124
# bugs in the test suite
125125
# ======================

src/driver/aot.rs

Lines changed: 183 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,25 @@
11
//! The AOT driver uses [`cranelift_object`] to write object files suitable for linking into a
22
//! standalone executable.
33
4-
use std::fs::File;
5-
use std::path::PathBuf;
4+
use std::fs::{self, File};
5+
use std::path::{Path, PathBuf};
66
use std::sync::Arc;
77
use std::thread::JoinHandle;
88

99
use cranelift_object::{ObjectBuilder, ObjectModule};
1010
use rustc_codegen_ssa::assert_module_sources::CguReuse;
11+
use rustc_codegen_ssa::back::link::ensure_removed;
1112
use rustc_codegen_ssa::back::metadata::create_compressed_metadata_file;
1213
use rustc_codegen_ssa::base::determine_cgu_reuse;
14+
use rustc_codegen_ssa::errors as ssa_errors;
1315
use rustc_codegen_ssa::{CodegenResults, CompiledModule, CrateInfo, ModuleKind};
1416
use rustc_data_structures::profiling::SelfProfilerRef;
1517
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
18+
use rustc_metadata::fs::copy_to_stdout;
1619
use rustc_metadata::EncodedMetadata;
1720
use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
1821
use rustc_middle::mir::mono::{CodegenUnit, MonoItem};
19-
use rustc_session::config::{DebugInfo, OutputFilenames, OutputType};
22+
use rustc_session::config::{DebugInfo, OutFileName, OutputFilenames, OutputType};
2023
use rustc_session::Session;
2124

2225
use crate::concurrency_limiter::{ConcurrencyLimiter, ConcurrencyLimiterToken};
@@ -53,6 +56,7 @@ impl OngoingCodegen {
5356
pub(crate) fn join(
5457
self,
5558
sess: &Session,
59+
outputs: &OutputFilenames,
5660
backend_config: &BackendConfig,
5761
) -> (CodegenResults, FxIndexMap<WorkProductId, WorkProduct>) {
5862
let mut work_products = FxIndexMap::default();
@@ -110,17 +114,183 @@ impl OngoingCodegen {
110114

111115
sess.dcx().abort_if_errors();
112116

113-
(
114-
CodegenResults {
115-
modules,
116-
allocator_module: self.allocator_module,
117-
metadata_module: self.metadata_module,
118-
metadata: self.metadata,
119-
crate_info: self.crate_info,
120-
},
121-
work_products,
122-
)
117+
let codegen_results = CodegenResults {
118+
modules,
119+
allocator_module: self.allocator_module,
120+
metadata_module: self.metadata_module,
121+
metadata: self.metadata,
122+
crate_info: self.crate_info,
123+
};
124+
125+
produce_final_output_artifacts(sess, &codegen_results, outputs);
126+
127+
(codegen_results, work_products)
128+
}
129+
}
130+
131+
// Adapted from https://github.com/rust-lang/rust/blob/73476d49904751f8d90ce904e16dfbc278083d2c/compiler/rustc_codegen_ssa/src/back/write.rs#L547C1-L706C2
132+
fn produce_final_output_artifacts(
133+
sess: &Session,
134+
codegen_results: &CodegenResults,
135+
crate_output: &OutputFilenames,
136+
) {
137+
let user_wants_bitcode = false;
138+
let mut user_wants_objects = false;
139+
140+
// Produce final compile outputs.
141+
let copy_gracefully = |from: &Path, to: &OutFileName| match to {
142+
OutFileName::Stdout => {
143+
if let Err(e) = copy_to_stdout(from) {
144+
sess.dcx().emit_err(ssa_errors::CopyPath::new(from, to.as_path(), e));
145+
}
146+
}
147+
OutFileName::Real(path) => {
148+
if let Err(e) = fs::copy(from, path) {
149+
sess.dcx().emit_err(ssa_errors::CopyPath::new(from, path, e));
150+
}
151+
}
152+
};
153+
154+
let copy_if_one_unit = |output_type: OutputType, keep_numbered: bool| {
155+
if codegen_results.modules.len() == 1 {
156+
// 1) Only one codegen unit. In this case it's no difficulty
157+
// to copy `foo.0.x` to `foo.x`.
158+
let module_name = Some(&codegen_results.modules[0].name[..]);
159+
let path = crate_output.temp_path(output_type, module_name);
160+
let output = crate_output.path(output_type);
161+
if !output_type.is_text_output() && output.is_tty() {
162+
sess.dcx()
163+
.emit_err(ssa_errors::BinaryOutputToTty { shorthand: output_type.shorthand() });
164+
} else {
165+
copy_gracefully(&path, &output);
166+
}
167+
if !sess.opts.cg.save_temps && !keep_numbered {
168+
// The user just wants `foo.x`, not `foo.#module-name#.x`.
169+
ensure_removed(sess.dcx(), &path);
170+
}
171+
} else {
172+
let extension = crate_output
173+
.temp_path(output_type, None)
174+
.extension()
175+
.unwrap()
176+
.to_str()
177+
.unwrap()
178+
.to_owned();
179+
180+
if crate_output.outputs.contains_explicit_name(&output_type) {
181+
// 2) Multiple codegen units, with `--emit foo=some_name`. We have
182+
// no good solution for this case, so warn the user.
183+
sess.dcx().emit_warn(ssa_errors::IgnoringEmitPath { extension });
184+
} else if crate_output.single_output_file.is_some() {
185+
// 3) Multiple codegen units, with `-o some_name`. We have
186+
// no good solution for this case, so warn the user.
187+
sess.dcx().emit_warn(ssa_errors::IgnoringOutput { extension });
188+
} else {
189+
// 4) Multiple codegen units, but no explicit name. We
190+
// just leave the `foo.0.x` files in place.
191+
// (We don't have to do any work in this case.)
192+
}
193+
}
194+
};
195+
196+
// Flag to indicate whether the user explicitly requested bitcode.
197+
// Otherwise, we produced it only as a temporary output, and will need
198+
// to get rid of it.
199+
for output_type in crate_output.outputs.keys() {
200+
match *output_type {
201+
OutputType::Bitcode => {
202+
// Cranelift doesn't have bitcode
203+
// user_wants_bitcode = true;
204+
// // Copy to .bc, but always keep the .0.bc. There is a later
205+
// // check to figure out if we should delete .0.bc files, or keep
206+
// // them for making an rlib.
207+
// copy_if_one_unit(OutputType::Bitcode, true);
208+
}
209+
OutputType::LlvmAssembly => {
210+
// Cranelift IR text already emitted during codegen
211+
// copy_if_one_unit(OutputType::LlvmAssembly, false);
212+
}
213+
OutputType::Assembly => {
214+
// Currently no support for emitting raw assembly files
215+
// copy_if_one_unit(OutputType::Assembly, false);
216+
}
217+
OutputType::Object => {
218+
user_wants_objects = true;
219+
copy_if_one_unit(OutputType::Object, true);
220+
}
221+
OutputType::Mir | OutputType::Metadata | OutputType::Exe | OutputType::DepInfo => {}
222+
}
223+
}
224+
225+
// Clean up unwanted temporary files.
226+
227+
// We create the following files by default:
228+
// - #crate#.#module-name#.bc
229+
// - #crate#.#module-name#.o
230+
// - #crate#.crate.metadata.bc
231+
// - #crate#.crate.metadata.o
232+
// - #crate#.o (linked from crate.##.o)
233+
// - #crate#.bc (copied from crate.##.bc)
234+
// We may create additional files if requested by the user (through
235+
// `-C save-temps` or `--emit=` flags).
236+
237+
if !sess.opts.cg.save_temps {
238+
// Remove the temporary .#module-name#.o objects. If the user didn't
239+
// explicitly request bitcode (with --emit=bc), and the bitcode is not
240+
// needed for building an rlib, then we must remove .#module-name#.bc as
241+
// well.
242+
243+
// Specific rules for keeping .#module-name#.bc:
244+
// - If the user requested bitcode (`user_wants_bitcode`), and
245+
// codegen_units > 1, then keep it.
246+
// - If the user requested bitcode but codegen_units == 1, then we
247+
// can toss .#module-name#.bc because we copied it to .bc earlier.
248+
// - If we're not building an rlib and the user didn't request
249+
// bitcode, then delete .#module-name#.bc.
250+
// If you change how this works, also update back::link::link_rlib,
251+
// where .#module-name#.bc files are (maybe) deleted after making an
252+
// rlib.
253+
let needs_crate_object = crate_output.outputs.contains_key(&OutputType::Exe);
254+
255+
let keep_numbered_bitcode = user_wants_bitcode && sess.codegen_units().as_usize() > 1;
256+
257+
let keep_numbered_objects =
258+
needs_crate_object || (user_wants_objects && sess.codegen_units().as_usize() > 1);
259+
260+
for module in codegen_results.modules.iter() {
261+
if let Some(ref path) = module.object {
262+
if !keep_numbered_objects {
263+
ensure_removed(sess.dcx(), path);
264+
}
265+
}
266+
267+
if let Some(ref path) = module.dwarf_object {
268+
if !keep_numbered_objects {
269+
ensure_removed(sess.dcx(), path);
270+
}
271+
}
272+
273+
if let Some(ref path) = module.bytecode {
274+
if !keep_numbered_bitcode {
275+
ensure_removed(sess.dcx(), path);
276+
}
277+
}
278+
}
279+
280+
if !user_wants_bitcode {
281+
if let Some(ref allocator_module) = codegen_results.allocator_module {
282+
if let Some(ref path) = allocator_module.bytecode {
283+
ensure_removed(sess.dcx(), path);
284+
}
285+
}
286+
}
123287
}
288+
289+
// We leave the following files around by default:
290+
// - #crate#.o
291+
// - #crate#.crate.metadata.o
292+
// - #crate#.bc
293+
// These are used in linking steps and will be cleaned up afterward.
124294
}
125295

126296
fn make_module(sess: &Session, backend_config: &BackendConfig, name: String) -> ObjectModule {

src/lib.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -233,12 +233,13 @@ impl CodegenBackend for CraneliftCodegenBackend {
233233
&self,
234234
ongoing_codegen: Box<dyn Any>,
235235
sess: &Session,
236-
_outputs: &OutputFilenames,
236+
outputs: &OutputFilenames,
237237
) -> (CodegenResults, FxIndexMap<WorkProductId, WorkProduct>) {
238-
ongoing_codegen
239-
.downcast::<driver::aot::OngoingCodegen>()
240-
.unwrap()
241-
.join(sess, self.config.borrow().as_ref().unwrap())
238+
ongoing_codegen.downcast::<driver::aot::OngoingCodegen>().unwrap().join(
239+
sess,
240+
outputs,
241+
self.config.borrow().as_ref().unwrap(),
242+
)
242243
}
243244

244245
fn link(

0 commit comments

Comments
 (0)