Skip to content

Commit 62c6006

Browse files
committed
Auto merge of #70441 - Dylan-DPC:rollup-qv7h2ph, r=Dylan-DPC
Rollup of 6 pull requests Successful merges: - #70384 (Refactor object file handling) - #70397 (add 'fn write_u16s' to Memory) - #70413 (Fix incorrect pattern warning "unreachable pattern") - #70428 (`error_bad_item_kind`: add help text) - #70429 (Clean up E0459 explanation) - #70437 (Miri float->int casts: be explicit that this is saturating) Failed merges: r? @ghost
2 parents 2fbb075 + 195147c commit 62c6006

File tree

15 files changed

+302
-92
lines changed

15 files changed

+302
-92
lines changed

src/librustc_codegen_llvm/back/write.rs

+47-40
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@ use crate::ModuleLlvm;
1616
use log::debug;
1717
use rustc::bug;
1818
use rustc::ty::TyCtxt;
19-
use rustc_codegen_ssa::back::write::{run_assembler, CodegenContext, EmbedBitcode, ModuleConfig};
19+
use rustc_codegen_ssa::back::write::{
20+
run_assembler, BitcodeSection, CodegenContext, EmitObj, ModuleConfig,
21+
};
2022
use rustc_codegen_ssa::traits::*;
2123
use rustc_codegen_ssa::{CompiledModule, ModuleCodegen, RLIB_BYTECODE_EXTENSION};
2224
use rustc_data_structures::small_c_str::SmallCStr;
@@ -651,7 +653,7 @@ pub(crate) unsafe fn codegen(
651653
let thin = ThinBuffer::new(llmod);
652654
let data = thin.data();
653655

654-
if config.emit_bc || config.obj_is_bitcode {
656+
if config.emit_bc || config.emit_obj == EmitObj::Bitcode {
655657
let _timer = cgcx.prof.generic_activity_with_arg(
656658
"LLVM_module_codegen_emit_bitcode",
657659
&module.name[..],
@@ -662,7 +664,7 @@ pub(crate) unsafe fn codegen(
662664
}
663665
}
664666

665-
if config.embed_bitcode == EmbedBitcode::Full {
667+
if config.emit_obj == EmitObj::ObjectCode(BitcodeSection::Full) {
666668
let _timer = cgcx.prof.generic_activity_with_arg(
667669
"LLVM_module_codegen_embed_bitcode",
668670
&module.name[..],
@@ -682,7 +684,7 @@ pub(crate) unsafe fn codegen(
682684
diag_handler.err(&msg);
683685
}
684686
}
685-
} else if config.embed_bitcode == EmbedBitcode::Marker {
687+
} else if config.emit_obj == EmitObj::ObjectCode(BitcodeSection::Marker) {
686688
embed_bitcode(cgcx, llcx, llmod, None);
687689
}
688690

@@ -732,9 +734,9 @@ pub(crate) unsafe fn codegen(
732734
})?;
733735
}
734736

735-
let config_emit_normal_obj = config.emit_obj && !config.obj_is_bitcode;
737+
let config_emit_object_code = matches!(config.emit_obj, EmitObj::ObjectCode(_));
736738

737-
if config.emit_asm || (config_emit_normal_obj && config.no_integrated_as) {
739+
if config.emit_asm || (config_emit_object_code && config.no_integrated_as) {
738740
let _timer = cgcx
739741
.prof
740742
.generic_activity_with_arg("LLVM_module_codegen_emit_asm", &module.name[..]);
@@ -743,60 +745,65 @@ pub(crate) unsafe fn codegen(
743745
// We can't use the same module for asm and binary output, because that triggers
744746
// various errors like invalid IR or broken binaries, so we might have to clone the
745747
// module to produce the asm output
746-
let llmod = if config.emit_obj { llvm::LLVMCloneModule(llmod) } else { llmod };
748+
let llmod = if config_emit_object_code { llvm::LLVMCloneModule(llmod) } else { llmod };
747749
with_codegen(tm, llmod, config.no_builtins, |cpm| {
748750
write_output_file(diag_handler, tm, cpm, llmod, &path, llvm::FileType::AssemblyFile)
749751
})?;
750752
}
751753

752-
if config_emit_normal_obj {
753-
if !config.no_integrated_as {
754-
let _timer = cgcx
755-
.prof
756-
.generic_activity_with_arg("LLVM_module_codegen_emit_obj", &module.name[..]);
757-
with_codegen(tm, llmod, config.no_builtins, |cpm| {
758-
write_output_file(
759-
diag_handler,
760-
tm,
761-
cpm,
762-
llmod,
763-
&obj_out,
764-
llvm::FileType::ObjectFile,
765-
)
766-
})?;
767-
} else {
768-
let _timer = cgcx
769-
.prof
770-
.generic_activity_with_arg("LLVM_module_codegen_asm_to_obj", &module.name[..]);
771-
let assembly = cgcx.output_filenames.temp_path(OutputType::Assembly, module_name);
772-
run_assembler(cgcx, diag_handler, &assembly, &obj_out);
773-
774-
if !config.emit_asm && !cgcx.save_temps {
775-
drop(fs::remove_file(&assembly));
754+
match config.emit_obj {
755+
EmitObj::ObjectCode(_) => {
756+
if !config.no_integrated_as {
757+
let _timer = cgcx.prof.generic_activity_with_arg(
758+
"LLVM_module_codegen_emit_obj",
759+
&module.name[..],
760+
);
761+
with_codegen(tm, llmod, config.no_builtins, |cpm| {
762+
write_output_file(
763+
diag_handler,
764+
tm,
765+
cpm,
766+
llmod,
767+
&obj_out,
768+
llvm::FileType::ObjectFile,
769+
)
770+
})?;
771+
} else {
772+
let _timer = cgcx.prof.generic_activity_with_arg(
773+
"LLVM_module_codegen_asm_to_obj",
774+
&module.name[..],
775+
);
776+
let assembly =
777+
cgcx.output_filenames.temp_path(OutputType::Assembly, module_name);
778+
run_assembler(cgcx, diag_handler, &assembly, &obj_out);
779+
780+
if !config.emit_asm && !cgcx.save_temps {
781+
drop(fs::remove_file(&assembly));
782+
}
776783
}
777784
}
778-
}
779785

780-
if config.obj_is_bitcode {
781-
if config.emit_obj {
786+
EmitObj::Bitcode => {
782787
debug!("copying bitcode {:?} to obj {:?}", bc_out, obj_out);
783788
if let Err(e) = link_or_copy(&bc_out, &obj_out) {
784789
diag_handler.err(&format!("failed to copy bitcode to object file: {}", e));
785790
}
786-
}
787791

788-
if !config.emit_bc {
789-
debug!("removing_bitcode {:?}", bc_out);
790-
if let Err(e) = fs::remove_file(&bc_out) {
791-
diag_handler.err(&format!("failed to remove bitcode: {}", e));
792+
if !config.emit_bc {
793+
debug!("removing_bitcode {:?}", bc_out);
794+
if let Err(e) = fs::remove_file(&bc_out) {
795+
diag_handler.err(&format!("failed to remove bitcode: {}", e));
796+
}
792797
}
793798
}
799+
800+
EmitObj::None => {}
794801
}
795802

796803
drop(handlers);
797804
}
798805
Ok(module.into_compiled_module(
799-
config.emit_obj,
806+
config.emit_obj != EmitObj::None,
800807
config.emit_bc,
801808
config.emit_bc_compressed,
802809
&cgcx.output_filenames,

src/librustc_codegen_ssa/back/write.rs

+49-33
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,31 @@ use std::thread;
5151

5252
const PRE_LTO_BC_EXT: &str = "pre-lto.bc";
5353

54-
/// The kind of bitcode to embed in object files.
55-
#[derive(PartialEq)]
56-
pub enum EmbedBitcode {
54+
/// What kind of object file to emit.
55+
#[derive(Clone, Copy, PartialEq)]
56+
pub enum EmitObj {
57+
// No object file.
5758
None,
59+
60+
// Just uncompressed llvm bitcode. Provides easy compatibility with
61+
// emscripten's ecc compiler, when used as the linker.
62+
Bitcode,
63+
64+
// Object code, possibly augmented with a bitcode section.
65+
ObjectCode(BitcodeSection),
66+
}
67+
68+
/// What kind of llvm bitcode section to embed in an object file.
69+
#[derive(Clone, Copy, PartialEq)]
70+
pub enum BitcodeSection {
71+
// No bitcode section.
72+
None,
73+
74+
// An empty bitcode section (to placate tools such as the iOS linker that
75+
// require this section even if they don't use it).
5876
Marker,
77+
78+
// A full, uncompressed bitcode section.
5979
Full,
6080
}
6181

@@ -84,7 +104,7 @@ pub struct ModuleConfig {
84104
pub emit_bc_compressed: bool,
85105
pub emit_ir: bool,
86106
pub emit_asm: bool,
87-
pub emit_obj: bool,
107+
pub emit_obj: EmitObj,
88108
// Miscellaneous flags. These are mostly copied from command-line
89109
// options.
90110
pub verify_llvm_ir: bool,
@@ -96,12 +116,7 @@ pub struct ModuleConfig {
96116
pub merge_functions: bool,
97117
pub inline_threshold: Option<usize>,
98118
pub new_llvm_pass_manager: Option<bool>,
99-
// Instead of creating an object file by doing LLVM codegen, just
100-
// make the object file bitcode. Provides easy compatibility with
101-
// emscripten's ecc compiler, when used as the linker.
102-
pub obj_is_bitcode: bool,
103119
pub no_integrated_as: bool,
104-
pub embed_bitcode: EmbedBitcode,
105120
}
106121

107122
impl ModuleConfig {
@@ -124,9 +139,7 @@ impl ModuleConfig {
124139
emit_bc_compressed: false,
125140
emit_ir: false,
126141
emit_asm: false,
127-
emit_obj: false,
128-
obj_is_bitcode: false,
129-
embed_bitcode: EmbedBitcode::None,
142+
emit_obj: EmitObj::None,
130143
no_integrated_as: false,
131144

132145
verify_llvm_ir: false,
@@ -147,17 +160,6 @@ impl ModuleConfig {
147160
self.no_builtins = no_builtins || sess.target.target.options.no_builtins;
148161
self.inline_threshold = sess.opts.cg.inline_threshold;
149162
self.new_llvm_pass_manager = sess.opts.debugging_opts.new_llvm_pass_manager;
150-
self.obj_is_bitcode =
151-
sess.target.target.options.obj_is_bitcode || sess.opts.cg.linker_plugin_lto.enabled();
152-
self.embed_bitcode =
153-
if sess.target.target.options.embed_bitcode || sess.opts.debugging_opts.embed_bitcode {
154-
match sess.opts.optimize {
155-
config::OptLevel::No | config::OptLevel::Less => EmbedBitcode::Marker,
156-
_ => EmbedBitcode::Full,
157-
}
158-
} else {
159-
EmbedBitcode::None
160-
};
161163

162164
// Copy what clang does by turning on loop vectorization at O2 and
163165
// slp vectorization at O3. Otherwise configure other optimization aspects
@@ -194,9 +196,9 @@ impl ModuleConfig {
194196

195197
pub fn bitcode_needed(&self) -> bool {
196198
self.emit_bc
197-
|| self.obj_is_bitcode
198199
|| self.emit_bc_compressed
199-
|| self.embed_bitcode == EmbedBitcode::Full
200+
|| self.emit_obj == EmitObj::Bitcode
201+
|| self.emit_obj == EmitObj::ObjectCode(BitcodeSection::Full)
200202
}
201203
}
202204

@@ -397,6 +399,20 @@ pub fn start_async_codegen<B: ExtraBackendMethods>(
397399
allocator_config.emit_bc_compressed = true;
398400
}
399401

402+
let emit_obj =
403+
if sess.target.target.options.obj_is_bitcode || sess.opts.cg.linker_plugin_lto.enabled() {
404+
EmitObj::Bitcode
405+
} else if sess.opts.debugging_opts.embed_bitcode {
406+
match sess.opts.optimize {
407+
config::OptLevel::No | config::OptLevel::Less => {
408+
EmitObj::ObjectCode(BitcodeSection::Marker)
409+
}
410+
_ => EmitObj::ObjectCode(BitcodeSection::Full),
411+
}
412+
} else {
413+
EmitObj::ObjectCode(BitcodeSection::None)
414+
};
415+
400416
modules_config.emit_pre_lto_bc = need_pre_lto_bitcode_for_incr_comp(sess);
401417

402418
modules_config.no_integrated_as =
@@ -416,20 +432,20 @@ pub fn start_async_codegen<B: ExtraBackendMethods>(
416432
// could be invoked specially with output_type_assembly, so
417433
// in this case we still want the metadata object file.
418434
if !sess.opts.output_types.contains_key(&OutputType::Assembly) {
419-
metadata_config.emit_obj = true;
420-
allocator_config.emit_obj = true;
435+
metadata_config.emit_obj = emit_obj;
436+
allocator_config.emit_obj = emit_obj;
421437
}
422438
}
423439
OutputType::Object => {
424-
modules_config.emit_obj = true;
440+
modules_config.emit_obj = emit_obj;
425441
}
426442
OutputType::Metadata => {
427-
metadata_config.emit_obj = true;
443+
metadata_config.emit_obj = emit_obj;
428444
}
429445
OutputType::Exe => {
430-
modules_config.emit_obj = true;
431-
metadata_config.emit_obj = true;
432-
allocator_config.emit_obj = true;
446+
modules_config.emit_obj = emit_obj;
447+
metadata_config.emit_obj = emit_obj;
448+
allocator_config.emit_obj = emit_obj;
433449
}
434450
OutputType::Mir => {}
435451
OutputType::DepInfo => {}
@@ -880,7 +896,7 @@ fn execute_copy_from_cache_work_item<B: ExtraBackendMethods>(
880896
}
881897
}
882898

883-
assert_eq!(object.is_some(), module_config.emit_obj);
899+
assert_eq!(object.is_some(), module_config.emit_obj != EmitObj::None);
884900
assert_eq!(bytecode.is_some(), module_config.emit_bc);
885901
assert_eq!(bytecode_compressed.is_some(), module_config.emit_bc_compressed);
886902

src/librustc_error_codes/error_codes/E0459.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
A link was used without a name parameter. Erroneous code example:
1+
A link was used without a name parameter.
2+
3+
Erroneous code example:
24

35
```compile_fail,E0459
46
#[link(kind = "dylib")] extern {}

src/librustc_mir/interpret/cast.rs

+4
Original file line numberDiff line numberDiff line change
@@ -229,13 +229,17 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
229229
// float -> uint
230230
Uint(t) => {
231231
let width = t.bit_width().unwrap_or_else(|| self.pointer_size().bits());
232+
// `to_u128` is a saturating cast, which is what we need
233+
// (https://doc.rust-lang.org/nightly/nightly-rustc/rustc_apfloat/trait.Float.html#method.to_i128_r).
232234
let v = f.to_u128(usize::try_from(width).unwrap()).value;
233235
// This should already fit the bit width
234236
Ok(Scalar::from_uint(v, Size::from_bits(width)))
235237
}
236238
// float -> int
237239
Int(t) => {
238240
let width = t.bit_width().unwrap_or_else(|| self.pointer_size().bits());
241+
// `to_i128` is a saturating cast, which is what we need
242+
// (https://doc.rust-lang.org/nightly/nightly-rustc/rustc_apfloat/trait.Float.html#method.to_i128_r).
239243
let v = f.to_i128(usize::try_from(width).unwrap()).value;
240244
Ok(Scalar::from_int(v, Size::from_bits(width)))
241245
}

src/librustc_mir/interpret/memory.rs

+42-2
Original file line numberDiff line numberDiff line change
@@ -833,17 +833,57 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
833833
ptr: Scalar<M::PointerTag>,
834834
src: impl IntoIterator<Item = u8>,
835835
) -> InterpResult<'tcx> {
836-
let src = src.into_iter();
836+
let mut src = src.into_iter();
837837
let size = Size::from_bytes(src.size_hint().0);
838838
// `write_bytes` checks that this lower bound `size` matches the upper bound and reality.
839839
let ptr = match self.check_ptr_access(ptr, size, Align::from_bytes(1).unwrap())? {
840840
Some(ptr) => ptr,
841-
None => return Ok(()), // zero-sized access
841+
None => {
842+
// zero-sized access
843+
src.next().expect_none("iterator said it was empty but returned an element");
844+
return Ok(());
845+
}
842846
};
843847
let tcx = self.tcx.tcx;
844848
self.get_raw_mut(ptr.alloc_id)?.write_bytes(&tcx, ptr, src)
845849
}
846850

851+
/// Writes the given stream of u16s into memory.
852+
///
853+
/// Performs appropriate bounds checks.
854+
pub fn write_u16s(
855+
&mut self,
856+
ptr: Scalar<M::PointerTag>,
857+
src: impl IntoIterator<Item = u16>,
858+
) -> InterpResult<'tcx> {
859+
let mut src = src.into_iter();
860+
let (lower, upper) = src.size_hint();
861+
let len = upper.expect("can only write bounded iterators");
862+
assert_eq!(lower, len, "can only write iterators with a precise length");
863+
864+
let size = Size::from_bytes(lower);
865+
let ptr = match self.check_ptr_access(ptr, size, Align::from_bytes(2).unwrap())? {
866+
Some(ptr) => ptr,
867+
None => {
868+
// zero-sized access
869+
src.next().expect_none("iterator said it was empty but returned an element");
870+
return Ok(());
871+
}
872+
};
873+
let tcx = self.tcx.tcx;
874+
let allocation = self.get_raw_mut(ptr.alloc_id)?;
875+
876+
for idx in 0..len {
877+
let val = Scalar::from_u16(
878+
src.next().expect("iterator was shorter than it said it would be"),
879+
);
880+
let offset_ptr = ptr.offset(Size::from_bytes(idx) * 2, &tcx)?; // `Size` multiplication
881+
allocation.write_scalar(&tcx, offset_ptr, val.into(), Size::from_bytes(2))?;
882+
}
883+
src.next().expect_none("iterator was longer than it said it would be");
884+
Ok(())
885+
}
886+
847887
/// Expects the caller to have checked bounds and alignment.
848888
pub fn copy(
849889
&mut self,

src/librustc_mir/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ Rust MIR: a lowered representation of Rust.
2424
#![feature(range_is_empty)]
2525
#![feature(stmt_expr_attributes)]
2626
#![feature(trait_alias)]
27+
#![feature(option_expect_none)]
2728
#![recursion_limit = "256"]
2829

2930
#[macro_use]

0 commit comments

Comments
 (0)