about summary refs log tree commit diff
diff options
context:
space:
mode:
authorTyler Mandry <tmandry@gmail.com>2020-08-13 18:00:10 -0700
committerGitHub <noreply@github.com>2020-08-13 18:00:10 -0700
commit1f73e898ee1da743bf9b27e529e070424ca25acf (patch)
tree1566be836da875beb7e1bf01a777c553fbb4dea9
parent8c361aa28d42b3fe95675e461f2d96b05de681de (diff)
parent050fb380aaa5f95ca27d6365cea06ea614c4cbf7 (diff)
downloadrust-1f73e898ee1da743bf9b27e529e070424ca25acf.tar.gz
rust-1f73e898ee1da743bf9b27e529e070424ca25acf.zip
Rollup merge of #75417 - npmccallum:naked, r=matthewjasper
Don't spill operands onto the stack in naked functions

Currently, the code spills operands onto the stack for the purpose of
debuginfo. However, naked functions can only contain an asm block. Therefore,
attempting to spill the operands on the stack is undefined behavior.

Fixes https://github.com/rust-lang/rust/issues/42779
cc https://github.com/rust-lang/rust/issues/32408

Note that this PR reverts https://github.com/rust-lang/rust/pull/74105 which ultimately didn't fix the problem.

cc @haraldh @Amanieu @matthewjasper
-rw-r--r--src/librustc_codegen_ssa/mir/debuginfo.rs8
-rw-r--r--src/librustc_mir_build/build/mod.rs12
-rw-r--r--src/test/codegen/naked-functions.rs4
-rw-r--r--src/test/debuginfo/function-arguments-naked.rs42
4 files changed, 11 insertions, 55 deletions
diff --git a/src/librustc_codegen_ssa/mir/debuginfo.rs b/src/librustc_codegen_ssa/mir/debuginfo.rs
index d166a27b5a9..d8a530d98fa 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 f3f3c3e33a4..215a0c7dfdf 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 758c6c4da92..493c1b9f0ba 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 5f3a1eb44e4..00000000000
--- 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
-}