Skip to content

Commit

Permalink
Auto merge of #111287 - matthiaskrgr:rollup-9lzax2c, r=matthiaskrgr
Browse files Browse the repository at this point in the history
Rollup of 7 pull requests

Successful merges:

 - #110577 (Use fulfillment to check `Drop` impl compatibility)
 - #110610 (Add Terminator conversion from MIR to SMIR, part #1)
 - #110985 (Fix spans in LLVM-generated inline asm errors)
 - #110989 (Make the BUG_REPORT_URL configurable by tools )
 - #111167 (debuginfo: split method declaration and definition)
 - #111230 (add hint for =< as <=)
 - #111279 (More robust debug assertions for `Instance::resolve` on built-in traits with non-standard trait items)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
  • Loading branch information
bors committed May 6, 2023
2 parents 333b920 + 3cb1a46 commit 905d5a3
Show file tree
Hide file tree
Showing 42 changed files with 1,067 additions and 413 deletions.
1 change: 1 addition & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4093,6 +4093,7 @@ dependencies = [
name = "rustc_smir"
version = "0.0.0"
dependencies = [
"rustc_hir",
"rustc_middle",
"rustc_span",
"tracing",
Expand Down
85 changes: 51 additions & 34 deletions compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
let tcx = self.tcx;

let def_id = instance.def_id();
let containing_scope = get_containing_scope(self, instance);
let (containing_scope, is_method) = get_containing_scope(self, instance);
let span = tcx.def_span(def_id);
let loc = self.lookup_debug_loc(span.lo());
let file_metadata = file_metadata(self, &loc.file);
Expand Down Expand Up @@ -378,8 +378,29 @@ impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
}
}

unsafe {
return llvm::LLVMRustDIBuilderCreateFunction(
// When we're adding a method to a type DIE, we only want a DW_AT_declaration there, because
// LLVM LTO can't unify type definitions when a child DIE is a full subprogram definition.
// When we use this `decl` below, the subprogram definition gets created at the CU level
// with a DW_AT_specification pointing back to the type's declaration.
let decl = is_method.then(|| unsafe {
llvm::LLVMRustDIBuilderCreateMethod(
DIB(self),
containing_scope,
name.as_ptr().cast(),
name.len(),
linkage_name.as_ptr().cast(),
linkage_name.len(),
file_metadata,
loc.line,
function_type_metadata,
flags,
spflags & !DISPFlags::SPFlagDefinition,
template_parameters,
)
});

return unsafe {
llvm::LLVMRustDIBuilderCreateFunction(
DIB(self),
containing_scope,
name.as_ptr().cast(),
Expand All @@ -394,9 +415,9 @@ impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
spflags,
maybe_definition_llfn,
template_parameters,
None,
);
}
decl,
)
};

fn get_function_signature<'ll, 'tcx>(
cx: &CodegenCx<'ll, 'tcx>,
Expand Down Expand Up @@ -493,14 +514,16 @@ impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
names
}

/// Returns a scope, plus `true` if that's a type scope for "class" methods,
/// otherwise `false` for plain namespace scopes.
fn get_containing_scope<'ll, 'tcx>(
cx: &CodegenCx<'ll, 'tcx>,
instance: Instance<'tcx>,
) -> &'ll DIScope {
) -> (&'ll DIScope, bool) {
// First, let's see if this is a method within an inherent impl. Because
// if yes, we want to make the result subroutine DIE a child of the
// subroutine's self-type.
let self_type = cx.tcx.impl_of_method(instance.def_id()).and_then(|impl_def_id| {
if let Some(impl_def_id) = cx.tcx.impl_of_method(instance.def_id()) {
// If the method does *not* belong to a trait, proceed
if cx.tcx.trait_id_of_impl(impl_def_id).is_none() {
let impl_self_ty = cx.tcx.subst_and_normalize_erasing_regions(
Expand All @@ -511,39 +534,33 @@ impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {

// Only "class" methods are generally understood by LLVM,
// so avoid methods on other types (e.g., `<*mut T>::null`).
match impl_self_ty.kind() {
ty::Adt(def, ..) if !def.is_box() => {
// Again, only create type information if full debuginfo is enabled
if cx.sess().opts.debuginfo == DebugInfo::Full
&& !impl_self_ty.has_param()
{
Some(type_di_node(cx, impl_self_ty))
} else {
Some(namespace::item_namespace(cx, def.did()))
}
if let ty::Adt(def, ..) = impl_self_ty.kind() && !def.is_box() {
// Again, only create type information if full debuginfo is enabled
if cx.sess().opts.debuginfo == DebugInfo::Full && !impl_self_ty.has_param()
{
return (type_di_node(cx, impl_self_ty), true);
} else {
return (namespace::item_namespace(cx, def.did()), false);
}
_ => None,
}
} else {
// For trait method impls we still use the "parallel namespace"
// strategy
None
}
});
}

self_type.unwrap_or_else(|| {
namespace::item_namespace(
cx,
DefId {
krate: instance.def_id().krate,
index: cx
.tcx
.def_key(instance.def_id())
.parent
.expect("get_containing_scope: missing parent?"),
},
)
})
let scope = namespace::item_namespace(
cx,
DefId {
krate: instance.def_id().krate,
index: cx
.tcx
.def_key(instance.def_id())
.parent
.expect("get_containing_scope: missing parent?"),
},
);
(scope, false)
}
}

Expand Down
15 changes: 15 additions & 0 deletions compiler/rustc_codegen_llvm/src/llvm/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1987,6 +1987,21 @@ extern "C" {
Decl: Option<&'a DIDescriptor>,
) -> &'a DISubprogram;

pub fn LLVMRustDIBuilderCreateMethod<'a>(
Builder: &DIBuilder<'a>,
Scope: &'a DIDescriptor,
Name: *const c_char,
NameLen: size_t,
LinkageName: *const c_char,
LinkageNameLen: size_t,
File: &'a DIFile,
LineNo: c_uint,
Ty: &'a DIType,
Flags: DIFlags,
SPFlags: DISPFlags,
TParam: &'a DIArray,
) -> &'a DISubprogram;

pub fn LLVMRustDIBuilderCreateBasicType<'a>(
Builder: &DIBuilder<'a>,
Name: *const c_char,
Expand Down
12 changes: 9 additions & 3 deletions compiler/rustc_codegen_ssa/src/back/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1821,9 +1821,15 @@ impl SharedEmitterMain {
let source = sess
.source_map()
.new_source_file(FileName::inline_asm_source_code(&buffer), buffer);
let source_span = Span::with_root_ctxt(source.start_pos, source.end_pos);
let spans: Vec<_> =
spans.iter().map(|sp| source_span.from_inner(*sp)).collect();
let spans: Vec<_> = spans
.iter()
.map(|sp| {
Span::with_root_ctxt(
source.normalized_byte_pos(sp.start as u32),
source.normalized_byte_pos(sp.end as u32),
)
})
.collect();
err.span_note(spans, "instantiated into assembly here");
}

Expand Down
103 changes: 57 additions & 46 deletions compiler/rustc_driver_impl/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ use rustc_data_structures::profiling::{
use rustc_data_structures::sync::SeqCst;
use rustc_errors::registry::{InvalidErrorCode, Registry};
use rustc_errors::{
DiagnosticMessage, ErrorGuaranteed, PResult, SubdiagnosticMessage, TerminalUrl,
DiagnosticMessage, ErrorGuaranteed, Handler, PResult, SubdiagnosticMessage, TerminalUrl,
};
use rustc_feature::find_gated_cfg;
use rustc_fluent_macro::fluent_messages;
Expand Down Expand Up @@ -55,7 +55,7 @@ use std::panic::{self, catch_unwind};
use std::path::PathBuf;
use std::process::{self, Command, Stdio};
use std::str;
use std::sync::LazyLock;
use std::sync::OnceLock;
use std::time::Instant;

// This import blocks the use of panicking `print` and `println` in all the code
Expand Down Expand Up @@ -119,7 +119,7 @@ pub const EXIT_SUCCESS: i32 = 0;
/// Exit status code used for compilation failures and invalid flags.
pub const EXIT_FAILURE: i32 = 1;

const BUG_REPORT_URL: &str = "https://github.com/rust-lang/rust/issues/new\
pub const DEFAULT_BUG_REPORT_URL: &str = "https://github.com/rust-lang/rust/issues/new\
?labels=C-bug%2C+I-ICE%2C+T-compiler&template=ice.md";

const ICE_REPORT_COMPILER_FLAGS: &[&str] = &["-Z", "-C", "--crate-type"];
Expand Down Expand Up @@ -1196,43 +1196,66 @@ pub fn catch_with_exit_code(f: impl FnOnce() -> interface::Result<()>) -> i32 {
}
}

static DEFAULT_HOOK: LazyLock<Box<dyn Fn(&panic::PanicInfo<'_>) + Sync + Send + 'static>> =
LazyLock::new(|| {
let hook = panic::take_hook();
panic::set_hook(Box::new(|info| {
// If the error was caused by a broken pipe then this is not a bug.
// Write the error and return immediately. See #98700.
#[cfg(windows)]
if let Some(msg) = info.payload().downcast_ref::<String>() {
if msg.starts_with("failed printing to stdout: ") && msg.ends_with("(os error 232)")
{
early_error_no_abort(ErrorOutputType::default(), &msg);
return;
}
};
/// Stores the default panic hook, from before [`install_ice_hook`] was called.
static DEFAULT_HOOK: OnceLock<Box<dyn Fn(&panic::PanicInfo<'_>) + Sync + Send + 'static>> =
OnceLock::new();

/// Installs a panic hook that will print the ICE message on unexpected panics.
///
/// The hook is intended to be useable even by external tools. You can pass a custom
/// `bug_report_url`, or report arbitrary info in `extra_info`. Note that `extra_info` is called in
/// a context where *the thread is currently panicking*, so it must not panic or the process will
/// abort.
///
/// If you have no extra info to report, pass the empty closure `|_| ()` as the argument to
/// extra_info.
///
/// A custom rustc driver can skip calling this to set up a custom ICE hook.
pub fn install_ice_hook(bug_report_url: &'static str, extra_info: fn(&Handler)) {
// If the user has not explicitly overridden "RUST_BACKTRACE", then produce
// full backtraces. When a compiler ICE happens, we want to gather
// as much information as possible to present in the issue opened
// by the user. Compiler developers and other rustc users can
// opt in to less-verbose backtraces by manually setting "RUST_BACKTRACE"
// (e.g. `RUST_BACKTRACE=1`)
if std::env::var("RUST_BACKTRACE").is_err() {
std::env::set_var("RUST_BACKTRACE", "full");
}

// Invoke the default handler, which prints the actual panic message and optionally a backtrace
// Don't do this for delayed bugs, which already emit their own more useful backtrace.
if !info.payload().is::<rustc_errors::DelayedBugPanic>() {
(*DEFAULT_HOOK)(info);
let default_hook = DEFAULT_HOOK.get_or_init(panic::take_hook);

// Separate the output with an empty line
eprintln!();
panic::set_hook(Box::new(move |info| {
// If the error was caused by a broken pipe then this is not a bug.
// Write the error and return immediately. See #98700.
#[cfg(windows)]
if let Some(msg) = info.payload().downcast_ref::<String>() {
if msg.starts_with("failed printing to stdout: ") && msg.ends_with("(os error 232)") {
early_error_no_abort(ErrorOutputType::default(), &msg);
return;
}
};

// Print the ICE message
report_ice(info, BUG_REPORT_URL);
}));
hook
});
// Invoke the default handler, which prints the actual panic message and optionally a backtrace
// Don't do this for delayed bugs, which already emit their own more useful backtrace.
if !info.payload().is::<rustc_errors::DelayedBugPanic>() {
(*default_hook)(info);

// Separate the output with an empty line
eprintln!();
}

// Print the ICE message
report_ice(info, bug_report_url, extra_info);
}));
}

/// Prints the ICE message, including query stack, but without backtrace.
///
/// The message will point the user at `bug_report_url` to report the ICE.
///
/// When `install_ice_hook` is called, this function will be called as the panic
/// hook.
pub fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) {
pub fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str, extra_info: fn(&Handler)) {
let fallback_bundle =
rustc_errors::fallback_fluent_bundle(crate::DEFAULT_LOCALE_RESOURCES.to_vec(), false);
let emitter = Box::new(rustc_errors::emitter::EmitterWriter::stderr(
Expand Down Expand Up @@ -1277,29 +1300,17 @@ pub fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) {

interface::try_print_query_stack(&handler, num_frames);

// We don't trust this callback not to panic itself, so run it at the end after we're sure we've
// printed all the relevant info.
extra_info(&handler);

#[cfg(windows)]
if env::var("RUSTC_BREAK_ON_ICE").is_ok() {
// Trigger a debugger if we crashed during bootstrap
unsafe { windows::Win32::System::Diagnostics::Debug::DebugBreak() };
}
}

/// Installs a panic hook that will print the ICE message on unexpected panics.
///
/// A custom rustc driver can skip calling this to set up a custom ICE hook.
pub fn install_ice_hook() {
// If the user has not explicitly overridden "RUST_BACKTRACE", then produce
// full backtraces. When a compiler ICE happens, we want to gather
// as much information as possible to present in the issue opened
// by the user. Compiler developers and other rustc users can
// opt in to less-verbose backtraces by manually setting "RUST_BACKTRACE"
// (e.g. `RUST_BACKTRACE=1`)
if std::env::var("RUST_BACKTRACE").is_err() {
std::env::set_var("RUST_BACKTRACE", "full");
}
LazyLock::force(&DEFAULT_HOOK);
}

/// This allows tools to enable rust logging without having to magically match rustc's
/// tracing crate version.
pub fn init_rustc_env_logger() {
Expand Down Expand Up @@ -1370,7 +1381,7 @@ pub fn main() -> ! {
init_rustc_env_logger();
signal_handler::install();
let mut callbacks = TimePassesCallbacks::default();
install_ice_hook();
install_ice_hook(DEFAULT_BUG_REPORT_URL, |_| ());
let exit_code = catch_with_exit_code(|| {
let args = env::args_os()
.enumerate()
Expand Down

0 comments on commit 905d5a3

Please sign in to comment.