Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 4 pull requests #59636

Merged
merged 16 commits into from
Apr 2, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 22 additions & 1 deletion src/bootstrap/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -634,7 +634,28 @@ impl<'a> Builder<'a> {
if compiler.is_snapshot(self) {
self.rustc_snapshot_libdir()
} else {
self.sysroot(compiler).join(libdir(&compiler.host))
match self.config.libdir_relative() {
Some(relative_libdir) if compiler.stage >= 1
=> self.sysroot(compiler).join(relative_libdir),
_ => self.sysroot(compiler).join(libdir(&compiler.host))
}
}
}

/// Returns the compiler's relative libdir where it stores the dynamic libraries that
/// it itself links against.
///
/// For example this returns `lib` on Unix and `bin` on
/// Windows.
pub fn libdir_relative(&self, compiler: Compiler) -> &Path {
if compiler.is_snapshot(self) {
libdir(&self.config.build).as_ref()
} else {
match self.config.libdir_relative() {
Some(relative_libdir) if compiler.stage >= 1
=> relative_libdir,
_ => libdir(&compiler.host).as_ref()
}
}
}

Expand Down
8 changes: 4 additions & 4 deletions src/bootstrap/compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use filetime::FileTime;
use serde_json;

use crate::dist;
use crate::util::{exe, libdir, is_dylib};
use crate::util::{exe, is_dylib};
use crate::{Compiler, Mode, GitRepo};
use crate::native;

Expand Down Expand Up @@ -1005,13 +1005,13 @@ impl Step for Assemble {

// Link in all dylibs to the libdir
let sysroot = builder.sysroot(target_compiler);
let sysroot_libdir = sysroot.join(libdir(&*host));
t!(fs::create_dir_all(&sysroot_libdir));
let rustc_libdir = builder.rustc_libdir(target_compiler);
t!(fs::create_dir_all(&rustc_libdir));
let src_libdir = builder.sysroot_libdir(build_compiler, host);
for f in builder.read_dir(&src_libdir) {
let filename = f.file_name().into_string().unwrap();
if is_dylib(&filename) {
builder.copy(&f.path(), &sysroot_libdir.join(&filename));
builder.copy(&f.path(), &rustc_libdir.join(&filename));
}
}

Expand Down
15 changes: 9 additions & 6 deletions src/bootstrap/dist.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use build_helper::output;

use crate::{Compiler, Mode, LLVM_TOOLS};
use crate::channel;
use crate::util::{libdir, is_dylib, exe};
use crate::util::{is_dylib, exe};
use crate::builder::{Builder, RunConfig, ShouldRun, Step};
use crate::compile;
use crate::tool::{self, Tool};
Expand Down Expand Up @@ -473,21 +473,23 @@ impl Step for Rustc {
fn prepare_image(builder: &Builder<'_>, compiler: Compiler, image: &Path) {
let host = compiler.host;
let src = builder.sysroot(compiler);
let libdir = libdir(&host);
let libdir = builder.rustc_libdir(compiler);

// Copy rustc/rustdoc binaries
t!(fs::create_dir_all(image.join("bin")));
builder.cp_r(&src.join("bin"), &image.join("bin"));

builder.install(&builder.rustdoc(compiler), &image.join("bin"), 0o755);

let libdir_relative = builder.libdir_relative(compiler);

// Copy runtime DLLs needed by the compiler
if libdir != "bin" {
for entry in builder.read_dir(&src.join(libdir)) {
if libdir_relative.to_str() != Some("bin") {
for entry in builder.read_dir(&libdir) {
let name = entry.file_name();
if let Some(s) = name.to_str() {
if is_dylib(s) {
builder.install(&entry.path(), &image.join(libdir), 0o644);
builder.install(&entry.path(), &image.join(&libdir_relative), 0o644);
}
}
}
Expand Down Expand Up @@ -516,7 +518,8 @@ impl Step for Rustc {
.join("bin")
.join(&exe);
// for the rationale about this rename check `compile::copy_lld_to_sysroot`
let dst = image.join("lib/rustlib")
let dst = image.join(libdir_relative)
.join("rustlib")
.join(&*host)
.join("bin")
.join(&exe);
Expand Down
1 change: 1 addition & 0 deletions src/bootstrap/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1275,6 +1275,7 @@ impl Build {
fn install(&self, src: &Path, dstdir: &Path, perms: u32) {
if self.config.dry_run { return; }
let dst = dstdir.join(src.file_name().unwrap());
self.verbose_than(1, &format!("Install {:?} to {:?}", src, dst));
t!(fs::create_dir_all(dstdir));
drop(fs::remove_file(&dst));
{
Expand Down
15 changes: 15 additions & 0 deletions src/libcore/ops/arith.rs
Original file line number Diff line number Diff line change
Expand Up @@ -537,6 +537,21 @@ rem_impl_integer! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }

macro_rules! rem_impl_float {
($($t:ty)*) => ($(

/// The remainder from the division of two floats.
///
/// The remainder has the same sign as the dividend and is computed as:
/// `x - (x / y).trunc() * y`.
///
/// # Examples
/// ```
/// let x: f32 = 50.50;
/// let y: f32 = 8.125;
/// let remainder = x - (x / y).trunc() * y;
///
/// // The answer to both operations is 1.75
/// assert_eq!(x % y, remainder);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
impl Rem for $t {
type Output = $t;
Expand Down
66 changes: 62 additions & 4 deletions src/librustc_codegen_llvm/debuginfo/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,32 @@ impl TypeMap<'ll, 'tcx> {
}
}

// Removes a Ty to metadata mapping
// This is useful when computing the metadata for a potentially
// recursive type (e.g. a function ptr of the form:
//
// fn foo() -> impl Copy { foo }
//
// This kind of type cannot be properly represented
// via LLVM debuginfo. As a workaround,
// we register a temporary Ty to metadata mapping
// for the function before we compute its actual metadata.
// If the metadata computation ends up recursing back to the
// original function, it will use the temporary mapping
// for the inner self-reference, preventing us from
// recursing forever.
//
// This function is used to remove the temporary metadata
// mapping after we've computed the actual metadata
fn remove_type(
&mut self,
type_: Ty<'tcx>,
) {
if self.type_to_metadata.remove(type_).is_none() {
bug!("Type metadata Ty '{}' is not in the TypeMap!", type_);
}
}

// Adds a UniqueTypeId to metadata mapping to the TypeMap. The method will
// fail if the mapping already exists.
fn register_unique_id_with_metadata(
Expand Down Expand Up @@ -608,17 +634,49 @@ pub fn type_metadata(
}
}
ty::FnDef(..) | ty::FnPtr(_) => {
let fn_metadata = subroutine_type_metadata(cx,
unique_type_id,
t.fn_sig(cx.tcx),
usage_site_span).metadata;

if let Some(metadata) = debug_context(cx).type_map
.borrow()
.find_metadata_for_unique_id(unique_type_id)
{
return metadata;
}

// It's possible to create a self-referential
// type in Rust by using 'impl trait':
//
// fn foo() -> impl Copy { foo }
//
// See TypeMap::remove_type for more detals
// about the workaround

let temp_type = {
unsafe {
// The choice of type here is pretty arbitrary -
// anything reading the debuginfo for a recursive
// type is going to see *somthing* weird - the only
// question is what exactly it will see
let (size, align) = cx.size_and_align_of(t);
llvm::LLVMRustDIBuilderCreateBasicType(
DIB(cx),
SmallCStr::new("<recur_type>").as_ptr(),
size.bits(),
align.bits() as u32,
DW_ATE_unsigned)
}
};

let type_map = &debug_context(cx).type_map;
type_map.borrow_mut().register_type_with_metadata(t, temp_type);

let fn_metadata = subroutine_type_metadata(cx,
unique_type_id,
t.fn_sig(cx.tcx),
usage_site_span).metadata;

type_map.borrow_mut().remove_type(t);


// This is actually a function pointer, so wrap it in pointer DI
MetadataCreationResult::new(pointer_type_metadata(cx, t, fn_metadata), false)

Expand Down
62 changes: 49 additions & 13 deletions src/librustc_codegen_llvm/debuginfo/type_names.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use rustc::hir::def_id::DefId;
use rustc::ty::subst::SubstsRef;
use rustc::ty::{self, Ty};
use rustc_codegen_ssa::traits::*;
use rustc_data_structures::fx::FxHashSet;

use rustc::hir;

Expand All @@ -17,7 +18,8 @@ pub fn compute_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
qualified: bool)
-> String {
let mut result = String::with_capacity(64);
push_debuginfo_type_name(cx, t, qualified, &mut result);
let mut visited = FxHashSet::default();
push_debuginfo_type_name(cx, t, qualified, &mut result, &mut visited);
result
}

Expand All @@ -26,7 +28,9 @@ pub fn compute_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
t: Ty<'tcx>,
qualified: bool,
output: &mut String) {
output: &mut String,
visited: &mut FxHashSet<Ty<'tcx>>) {

// When targeting MSVC, emit C++ style type names for compatibility with
// .natvis visualizers (and perhaps other existing native debuggers?)
let cpp_like_names = cx.sess().target.target.options.is_like_msvc;
Expand All @@ -42,12 +46,12 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
ty::Foreign(def_id) => push_item_name(cx, def_id, qualified, output),
ty::Adt(def, substs) => {
push_item_name(cx, def.did, qualified, output);
push_type_params(cx, substs, output);
push_type_params(cx, substs, output, visited);
},
ty::Tuple(component_types) => {
output.push('(');
for &component_type in component_types {
push_debuginfo_type_name(cx, component_type, true, output);
push_debuginfo_type_name(cx, component_type, true, output, visited);
output.push_str(", ");
}
if !component_types.is_empty() {
Expand All @@ -65,7 +69,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
hir::MutMutable => output.push_str("mut "),
}

push_debuginfo_type_name(cx, inner_type, true, output);
push_debuginfo_type_name(cx, inner_type, true, output, visited);

if cpp_like_names {
output.push('*');
Expand All @@ -79,15 +83,15 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
output.push_str("mut ");
}

push_debuginfo_type_name(cx, inner_type, true, output);
push_debuginfo_type_name(cx, inner_type, true, output, visited);

if cpp_like_names {
output.push('*');
}
},
ty::Array(inner_type, len) => {
output.push('[');
push_debuginfo_type_name(cx, inner_type, true, output);
push_debuginfo_type_name(cx, inner_type, true, output, visited);
output.push_str(&format!("; {}", len.unwrap_usize(cx.tcx)));
output.push(']');
},
Expand All @@ -98,7 +102,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
output.push('[');
}

push_debuginfo_type_name(cx, inner_type, true, output);
push_debuginfo_type_name(cx, inner_type, true, output, visited);

if cpp_like_names {
output.push('>');
Expand All @@ -113,12 +117,31 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
&principal,
);
push_item_name(cx, principal.def_id, false, output);
push_type_params(cx, principal.substs, output);
push_type_params(cx, principal.substs, output, visited);
} else {
output.push_str("dyn '_");
}
},
ty::FnDef(..) | ty::FnPtr(_) => {
// We've encountered a weird 'recursive type'
// Currently, the only way to generate such a type
// is by using 'impl trait':
//
// fn foo() -> impl Copy { foo }
//
// There's not really a sensible name we can generate,
// since we don't include 'impl trait' types (e.g. ty::Opaque)
// in the output
//
// Since we need to generate *something*, we just
// use a dummy string that should make it clear
// that something unusual is going on
if !visited.insert(t) {
output.push_str("<recursive_type>");
return;
}


let sig = t.fn_sig(cx.tcx);
if sig.unsafety() == hir::Unsafety::Unsafe {
output.push_str("unsafe ");
Expand All @@ -136,7 +159,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
let sig = cx.tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig);
if !sig.inputs().is_empty() {
for &parameter_type in sig.inputs() {
push_debuginfo_type_name(cx, parameter_type, true, output);
push_debuginfo_type_name(cx, parameter_type, true, output, visited);
output.push_str(", ");
}
output.pop();
Expand All @@ -155,8 +178,20 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,

if !sig.output().is_unit() {
output.push_str(" -> ");
push_debuginfo_type_name(cx, sig.output(), true, output);
push_debuginfo_type_name(cx, sig.output(), true, output, visited);
}


// We only keep the type in 'visited'
// for the duration of the body of this method.
// It's fine for a particular function type
// to show up multiple times in one overall type
// (e.g. MyType<fn() -> u8, fn() -> u8>
//
// We only care about avoiding recursing
// directly back to the type we're currently
// processing
visited.remove(t);
},
ty::Closure(..) => {
output.push_str("closure");
Expand Down Expand Up @@ -200,15 +235,16 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
// common denominator - otherwise we would run into conflicts.
fn push_type_params<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
substs: SubstsRef<'tcx>,
output: &mut String) {
output: &mut String,
visited: &mut FxHashSet<Ty<'tcx>>) {
if substs.types().next().is_none() {
return;
}

output.push('<');

for type_parameter in substs.types() {
push_debuginfo_type_name(cx, type_parameter, true, output);
push_debuginfo_type_name(cx, type_parameter, true, output, visited);
output.push_str(", ");
}

Expand Down
Loading