Skip to content

Commit

Permalink
Auto merge of rust-lang#70441 - Dylan-DPC:rollup-qv7h2ph, r=Dylan-DPC
Browse files Browse the repository at this point in the history
Rollup of 6 pull requests

Successful merges:

 - rust-lang#70384 (Refactor object file handling)
 - rust-lang#70397 (add 'fn write_u16s' to Memory)
 - rust-lang#70413 (Fix incorrect pattern warning "unreachable pattern")
 - rust-lang#70428 (`error_bad_item_kind`: add help text)
 - rust-lang#70429 (Clean up E0459 explanation)
 - rust-lang#70437 (Miri float->int casts: be explicit that this is saturating)

Failed merges:

r? @ghost
  • Loading branch information
bors committed Mar 26, 2020
2 parents 2fbb075 + 195147c commit 62c6006
Show file tree
Hide file tree
Showing 15 changed files with 302 additions and 92 deletions.
87 changes: 47 additions & 40 deletions src/librustc_codegen_llvm/back/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ use crate::ModuleLlvm;
use log::debug;
use rustc::bug;
use rustc::ty::TyCtxt;
use rustc_codegen_ssa::back::write::{run_assembler, CodegenContext, EmbedBitcode, ModuleConfig};
use rustc_codegen_ssa::back::write::{
run_assembler, BitcodeSection, CodegenContext, EmitObj, ModuleConfig,
};
use rustc_codegen_ssa::traits::*;
use rustc_codegen_ssa::{CompiledModule, ModuleCodegen, RLIB_BYTECODE_EXTENSION};
use rustc_data_structures::small_c_str::SmallCStr;
Expand Down Expand Up @@ -651,7 +653,7 @@ pub(crate) unsafe fn codegen(
let thin = ThinBuffer::new(llmod);
let data = thin.data();

if config.emit_bc || config.obj_is_bitcode {
if config.emit_bc || config.emit_obj == EmitObj::Bitcode {
let _timer = cgcx.prof.generic_activity_with_arg(
"LLVM_module_codegen_emit_bitcode",
&module.name[..],
Expand All @@ -662,7 +664,7 @@ pub(crate) unsafe fn codegen(
}
}

if config.embed_bitcode == EmbedBitcode::Full {
if config.emit_obj == EmitObj::ObjectCode(BitcodeSection::Full) {
let _timer = cgcx.prof.generic_activity_with_arg(
"LLVM_module_codegen_embed_bitcode",
&module.name[..],
Expand All @@ -682,7 +684,7 @@ pub(crate) unsafe fn codegen(
diag_handler.err(&msg);
}
}
} else if config.embed_bitcode == EmbedBitcode::Marker {
} else if config.emit_obj == EmitObj::ObjectCode(BitcodeSection::Marker) {
embed_bitcode(cgcx, llcx, llmod, None);
}

Expand Down Expand Up @@ -732,9 +734,9 @@ pub(crate) unsafe fn codegen(
})?;
}

let config_emit_normal_obj = config.emit_obj && !config.obj_is_bitcode;
let config_emit_object_code = matches!(config.emit_obj, EmitObj::ObjectCode(_));

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

if config_emit_normal_obj {
if !config.no_integrated_as {
let _timer = cgcx
.prof
.generic_activity_with_arg("LLVM_module_codegen_emit_obj", &module.name[..]);
with_codegen(tm, llmod, config.no_builtins, |cpm| {
write_output_file(
diag_handler,
tm,
cpm,
llmod,
&obj_out,
llvm::FileType::ObjectFile,
)
})?;
} else {
let _timer = cgcx
.prof
.generic_activity_with_arg("LLVM_module_codegen_asm_to_obj", &module.name[..]);
let assembly = cgcx.output_filenames.temp_path(OutputType::Assembly, module_name);
run_assembler(cgcx, diag_handler, &assembly, &obj_out);

if !config.emit_asm && !cgcx.save_temps {
drop(fs::remove_file(&assembly));
match config.emit_obj {
EmitObj::ObjectCode(_) => {
if !config.no_integrated_as {
let _timer = cgcx.prof.generic_activity_with_arg(
"LLVM_module_codegen_emit_obj",
&module.name[..],
);
with_codegen(tm, llmod, config.no_builtins, |cpm| {
write_output_file(
diag_handler,
tm,
cpm,
llmod,
&obj_out,
llvm::FileType::ObjectFile,
)
})?;
} else {
let _timer = cgcx.prof.generic_activity_with_arg(
"LLVM_module_codegen_asm_to_obj",
&module.name[..],
);
let assembly =
cgcx.output_filenames.temp_path(OutputType::Assembly, module_name);
run_assembler(cgcx, diag_handler, &assembly, &obj_out);

if !config.emit_asm && !cgcx.save_temps {
drop(fs::remove_file(&assembly));
}
}
}
}

if config.obj_is_bitcode {
if config.emit_obj {
EmitObj::Bitcode => {
debug!("copying bitcode {:?} to obj {:?}", bc_out, obj_out);
if let Err(e) = link_or_copy(&bc_out, &obj_out) {
diag_handler.err(&format!("failed to copy bitcode to object file: {}", e));
}
}

if !config.emit_bc {
debug!("removing_bitcode {:?}", bc_out);
if let Err(e) = fs::remove_file(&bc_out) {
diag_handler.err(&format!("failed to remove bitcode: {}", e));
if !config.emit_bc {
debug!("removing_bitcode {:?}", bc_out);
if let Err(e) = fs::remove_file(&bc_out) {
diag_handler.err(&format!("failed to remove bitcode: {}", e));
}
}
}

EmitObj::None => {}
}

drop(handlers);
}
Ok(module.into_compiled_module(
config.emit_obj,
config.emit_obj != EmitObj::None,
config.emit_bc,
config.emit_bc_compressed,
&cgcx.output_filenames,
Expand Down
82 changes: 49 additions & 33 deletions src/librustc_codegen_ssa/back/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,31 @@ use std::thread;

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

/// The kind of bitcode to embed in object files.
#[derive(PartialEq)]
pub enum EmbedBitcode {
/// What kind of object file to emit.
#[derive(Clone, Copy, PartialEq)]
pub enum EmitObj {
// No object file.
None,

// Just uncompressed llvm bitcode. Provides easy compatibility with
// emscripten's ecc compiler, when used as the linker.
Bitcode,

// Object code, possibly augmented with a bitcode section.
ObjectCode(BitcodeSection),
}

/// What kind of llvm bitcode section to embed in an object file.
#[derive(Clone, Copy, PartialEq)]
pub enum BitcodeSection {
// No bitcode section.
None,

// An empty bitcode section (to placate tools such as the iOS linker that
// require this section even if they don't use it).
Marker,

// A full, uncompressed bitcode section.
Full,
}

Expand Down Expand Up @@ -84,7 +104,7 @@ pub struct ModuleConfig {
pub emit_bc_compressed: bool,
pub emit_ir: bool,
pub emit_asm: bool,
pub emit_obj: bool,
pub emit_obj: EmitObj,
// Miscellaneous flags. These are mostly copied from command-line
// options.
pub verify_llvm_ir: bool,
Expand All @@ -96,12 +116,7 @@ pub struct ModuleConfig {
pub merge_functions: bool,
pub inline_threshold: Option<usize>,
pub new_llvm_pass_manager: Option<bool>,
// Instead of creating an object file by doing LLVM codegen, just
// make the object file bitcode. Provides easy compatibility with
// emscripten's ecc compiler, when used as the linker.
pub obj_is_bitcode: bool,
pub no_integrated_as: bool,
pub embed_bitcode: EmbedBitcode,
}

impl ModuleConfig {
Expand All @@ -124,9 +139,7 @@ impl ModuleConfig {
emit_bc_compressed: false,
emit_ir: false,
emit_asm: false,
emit_obj: false,
obj_is_bitcode: false,
embed_bitcode: EmbedBitcode::None,
emit_obj: EmitObj::None,
no_integrated_as: false,

verify_llvm_ir: false,
Expand All @@ -147,17 +160,6 @@ impl ModuleConfig {
self.no_builtins = no_builtins || sess.target.target.options.no_builtins;
self.inline_threshold = sess.opts.cg.inline_threshold;
self.new_llvm_pass_manager = sess.opts.debugging_opts.new_llvm_pass_manager;
self.obj_is_bitcode =
sess.target.target.options.obj_is_bitcode || sess.opts.cg.linker_plugin_lto.enabled();
self.embed_bitcode =
if sess.target.target.options.embed_bitcode || sess.opts.debugging_opts.embed_bitcode {
match sess.opts.optimize {
config::OptLevel::No | config::OptLevel::Less => EmbedBitcode::Marker,
_ => EmbedBitcode::Full,
}
} else {
EmbedBitcode::None
};

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

pub fn bitcode_needed(&self) -> bool {
self.emit_bc
|| self.obj_is_bitcode
|| self.emit_bc_compressed
|| self.embed_bitcode == EmbedBitcode::Full
|| self.emit_obj == EmitObj::Bitcode
|| self.emit_obj == EmitObj::ObjectCode(BitcodeSection::Full)
}
}

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

let emit_obj =
if sess.target.target.options.obj_is_bitcode || sess.opts.cg.linker_plugin_lto.enabled() {
EmitObj::Bitcode
} else if sess.opts.debugging_opts.embed_bitcode {
match sess.opts.optimize {
config::OptLevel::No | config::OptLevel::Less => {
EmitObj::ObjectCode(BitcodeSection::Marker)
}
_ => EmitObj::ObjectCode(BitcodeSection::Full),
}
} else {
EmitObj::ObjectCode(BitcodeSection::None)
};

modules_config.emit_pre_lto_bc = need_pre_lto_bitcode_for_incr_comp(sess);

modules_config.no_integrated_as =
Expand All @@ -416,20 +432,20 @@ pub fn start_async_codegen<B: ExtraBackendMethods>(
// could be invoked specially with output_type_assembly, so
// in this case we still want the metadata object file.
if !sess.opts.output_types.contains_key(&OutputType::Assembly) {
metadata_config.emit_obj = true;
allocator_config.emit_obj = true;
metadata_config.emit_obj = emit_obj;
allocator_config.emit_obj = emit_obj;
}
}
OutputType::Object => {
modules_config.emit_obj = true;
modules_config.emit_obj = emit_obj;
}
OutputType::Metadata => {
metadata_config.emit_obj = true;
metadata_config.emit_obj = emit_obj;
}
OutputType::Exe => {
modules_config.emit_obj = true;
metadata_config.emit_obj = true;
allocator_config.emit_obj = true;
modules_config.emit_obj = emit_obj;
metadata_config.emit_obj = emit_obj;
allocator_config.emit_obj = emit_obj;
}
OutputType::Mir => {}
OutputType::DepInfo => {}
Expand Down Expand Up @@ -880,7 +896,7 @@ fn execute_copy_from_cache_work_item<B: ExtraBackendMethods>(
}
}

assert_eq!(object.is_some(), module_config.emit_obj);
assert_eq!(object.is_some(), module_config.emit_obj != EmitObj::None);
assert_eq!(bytecode.is_some(), module_config.emit_bc);
assert_eq!(bytecode_compressed.is_some(), module_config.emit_bc_compressed);

Expand Down
4 changes: 3 additions & 1 deletion src/librustc_error_codes/error_codes/E0459.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
A link was used without a name parameter. Erroneous code example:
A link was used without a name parameter.

Erroneous code example:

```compile_fail,E0459
#[link(kind = "dylib")] extern {}
Expand Down
4 changes: 4 additions & 0 deletions src/librustc_mir/interpret/cast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -229,13 +229,17 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
// float -> uint
Uint(t) => {
let width = t.bit_width().unwrap_or_else(|| self.pointer_size().bits());
// `to_u128` is a saturating cast, which is what we need
// (https://doc.rust-lang.org/nightly/nightly-rustc/rustc_apfloat/trait.Float.html#method.to_i128_r).
let v = f.to_u128(usize::try_from(width).unwrap()).value;
// This should already fit the bit width
Ok(Scalar::from_uint(v, Size::from_bits(width)))
}
// float -> int
Int(t) => {
let width = t.bit_width().unwrap_or_else(|| self.pointer_size().bits());
// `to_i128` is a saturating cast, which is what we need
// (https://doc.rust-lang.org/nightly/nightly-rustc/rustc_apfloat/trait.Float.html#method.to_i128_r).
let v = f.to_i128(usize::try_from(width).unwrap()).value;
Ok(Scalar::from_int(v, Size::from_bits(width)))
}
Expand Down
44 changes: 42 additions & 2 deletions src/librustc_mir/interpret/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -833,17 +833,57 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
ptr: Scalar<M::PointerTag>,
src: impl IntoIterator<Item = u8>,
) -> InterpResult<'tcx> {
let src = src.into_iter();
let mut src = src.into_iter();
let size = Size::from_bytes(src.size_hint().0);
// `write_bytes` checks that this lower bound `size` matches the upper bound and reality.
let ptr = match self.check_ptr_access(ptr, size, Align::from_bytes(1).unwrap())? {
Some(ptr) => ptr,
None => return Ok(()), // zero-sized access
None => {
// zero-sized access
src.next().expect_none("iterator said it was empty but returned an element");
return Ok(());
}
};
let tcx = self.tcx.tcx;
self.get_raw_mut(ptr.alloc_id)?.write_bytes(&tcx, ptr, src)
}

/// Writes the given stream of u16s into memory.
///
/// Performs appropriate bounds checks.
pub fn write_u16s(
&mut self,
ptr: Scalar<M::PointerTag>,
src: impl IntoIterator<Item = u16>,
) -> InterpResult<'tcx> {
let mut src = src.into_iter();
let (lower, upper) = src.size_hint();
let len = upper.expect("can only write bounded iterators");
assert_eq!(lower, len, "can only write iterators with a precise length");

let size = Size::from_bytes(lower);
let ptr = match self.check_ptr_access(ptr, size, Align::from_bytes(2).unwrap())? {
Some(ptr) => ptr,
None => {
// zero-sized access
src.next().expect_none("iterator said it was empty but returned an element");
return Ok(());
}
};
let tcx = self.tcx.tcx;
let allocation = self.get_raw_mut(ptr.alloc_id)?;

for idx in 0..len {
let val = Scalar::from_u16(
src.next().expect("iterator was shorter than it said it would be"),
);
let offset_ptr = ptr.offset(Size::from_bytes(idx) * 2, &tcx)?; // `Size` multiplication
allocation.write_scalar(&tcx, offset_ptr, val.into(), Size::from_bytes(2))?;
}
src.next().expect_none("iterator was longer than it said it would be");
Ok(())
}

/// Expects the caller to have checked bounds and alignment.
pub fn copy(
&mut self,
Expand Down
1 change: 1 addition & 0 deletions src/librustc_mir/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ Rust MIR: a lowered representation of Rust.
#![feature(range_is_empty)]
#![feature(stmt_expr_attributes)]
#![feature(trait_alias)]
#![feature(option_expect_none)]
#![recursion_limit = "256"]

#[macro_use]
Expand Down
Loading

0 comments on commit 62c6006

Please sign in to comment.