diff --git a/src/librustc_codegen_ssa/mir/debuginfo.rs b/src/librustc_codegen_ssa/mir/debuginfo.rs index d166a27b5a982..d8a530d98faa7 100644 --- a/src/librustc_codegen_ssa/mir/debuginfo.rs +++ b/src/librustc_codegen_ssa/mir/debuginfo.rs @@ -1,6 +1,7 @@ use crate::traits::*; use rustc_hir::def_id::CrateNum; use rustc_index::vec::IndexVec; +use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::mir; use rustc_middle::ty; use rustc_session::config::DebugInfo; @@ -216,6 +217,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { LocalRef::Operand(None) => return, LocalRef::Operand(Some(operand)) => { + // Don't spill operands onto the stack in naked functions. + // See: https://github.com/rust-lang/rust/issues/42779 + let attrs = bx.tcx().codegen_fn_attrs(self.instance.def_id()); + if attrs.flags.contains(CodegenFnAttrFlags::NAKED) { + return; + } + // "Spill" the value onto the stack, for debuginfo, // without forcing non-debuginfo uses of the local // to also load from the stack every single time. diff --git a/src/librustc_mir_build/build/mod.rs b/src/librustc_mir_build/build/mod.rs index f3f3c3e33a46d..215a0c7dfdf27 100644 --- a/src/librustc_mir_build/build/mod.rs +++ b/src/librustc_mir_build/build/mod.rs @@ -10,7 +10,6 @@ use rustc_hir::lang_items; use rustc_hir::{GeneratorKind, HirIdMap, Node}; use rustc_index::vec::{Idx, IndexVec}; use rustc_infer::infer::TyCtxtInferExt; -use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::middle::region; use rustc_middle::mir::*; use rustc_middle::ty::subst::Subst; @@ -798,22 +797,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { argument_scope: region::Scope, ast_body: &'tcx hir::Expr<'tcx>, ) -> BlockAnd<()> { - let tcx = self.hir.tcx(); - let attrs = tcx.codegen_fn_attrs(fn_def_id); - let naked = attrs.flags.contains(CodegenFnAttrFlags::NAKED); - // Allocate locals for the function arguments for &ArgInfo(ty, _, arg_opt, _) in arguments.iter() { let source_info = SourceInfo::outermost(arg_opt.map_or(self.fn_span, |arg| arg.pat.span)); let arg_local = self.local_decls.push(LocalDecl::with_source_info(ty, source_info)); - // Emit function argument debuginfo only for non-naked functions. - // See: https://github.com/rust-lang/rust/issues/42779 - if naked { - continue; - } - // If this is a simple binding pattern, give debuginfo a nice name. if let Some(arg) = arg_opt { if let Some(ident) = arg.pat.simple_ident() { @@ -826,6 +815,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } + let tcx = self.hir.tcx(); let tcx_hir = tcx.hir(); let hir_typeck_results = self.hir.typeck_results(); diff --git a/src/test/codegen/naked-functions.rs b/src/test/codegen/naked-functions.rs index 758c6c4da9293..493c1b9f0ba6b 100644 --- a/src/test/codegen/naked-functions.rs +++ b/src/test/codegen/naked-functions.rs @@ -18,7 +18,7 @@ pub fn naked_empty() { // CHECK-NEXT: define void @naked_with_args(i{{[0-9]+( %0)?}}) pub fn naked_with_args(a: isize) { // CHECK-NEXT: {{.+}}: - // CHECK-NEXT: %_1 = alloca i{{[0-9]+}} + // CHECK-NEXT: %a = alloca i{{[0-9]+}} &a; // keep variable in an alloca // CHECK: ret void } @@ -39,7 +39,7 @@ pub fn naked_with_return() -> isize { #[naked] pub fn naked_with_args_and_return(a: isize) -> isize { // CHECK-NEXT: {{.+}}: - // CHECK-NEXT: %_1 = alloca i{{[0-9]+}} + // CHECK-NEXT: %a = alloca i{{[0-9]+}} &a; // keep variable in an alloca // CHECK: ret i{{[0-9]+}} %{{[0-9]+}} a diff --git a/src/test/debuginfo/function-arguments-naked.rs b/src/test/debuginfo/function-arguments-naked.rs deleted file mode 100644 index 5f3a1eb44e4e5..0000000000000 --- a/src/test/debuginfo/function-arguments-naked.rs +++ /dev/null @@ -1,42 +0,0 @@ -// min-lldb-version: 310 - -// We have to ignore android because of this issue: -// https://github.com/rust-lang/rust/issues/74847 -// ignore-android -// -// We need to use inline assembly, so just use one platform -// only-x86_64 - -// compile-flags:-g - -// === GDB TESTS =================================================================================== - -// gdb-command:run - -// gdb-command:info args -// gdb-check:No arguments. -// gdb-command:continue - -// === LLDB TESTS ================================================================================== - -// lldb-command:run - -// lldb-command:frame variable -// lldbg-check:(unsigned long) = 111 (unsigned long) = 222 -// lldbr-check:(unsigned long) = 111 (unsigned long) = 222 -// lldb-command:continue - - -#![feature(asm)] -#![feature(naked_functions)] -#![feature(omit_gdb_pretty_printer_section)] -#![omit_gdb_pretty_printer_section] - -fn main() { - naked(111, 222); -} - -#[naked] -extern "C" fn naked(x: usize, y: usize) { - unsafe { asm!("ret"); } // #break -}