Auto merge of #74105 - npmccallum:naked, r=matthewjasper

Suppress debuginfo on naked function arguments

A function that has no prologue cannot be reasonably expected to support
debuginfo. In fact, the existing code (before this patch) would generate
invalid instructions that caused crashes. We can solve this easily by
just not emitting the debuginfo in this case.

Fixes https://github.com/rust-lang/rust/issues/42779
cc https://github.com/rust-lang/rust/issues/32408
This commit is contained in:
bors 2020-07-30 10:58:59 +00:00
commit 1ce0cf070e
3 changed files with 53 additions and 3 deletions

View File

@ -10,6 +10,7 @@ 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;
@ -797,12 +798,22 @@ 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() {
@ -815,7 +826,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
}
}
let tcx = self.hir.tcx();
let tcx_hir = tcx.hir();
let hir_typeck_results = self.hir.typeck_results();

View File

@ -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: %a = alloca i{{[0-9]+}}
// CHECK-NEXT: %_1 = 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: %a = alloca i{{[0-9]+}}
// CHECK-NEXT: %_1 = alloca i{{[0-9]+}}
&a; // keep variable in an alloca
// CHECK: ret i{{[0-9]+}} %{{[0-9]+}}
a

View File

@ -0,0 +1,40 @@
// min-lldb-version: 310
// We have to ignore android because of this issue:
// https://github.com/rust-lang/rust/issues/74847
// ignore-android
// 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(naked_functions)]
#![feature(omit_gdb_pretty_printer_section)]
#![omit_gdb_pretty_printer_section]
fn main() {
naked(111, 222);
}
#[naked]
fn naked(x: usize, y: usize) {
zzz(); // #break
}
fn zzz() { () }