Change:
When compiling () The generated assembly includes a prologue with unexpected 's (as well as a trailing , already reported in ) Expected behaviour would be to have no prologue (and prevent compilation of a function that is not as this would require implementing an undefined ABI, contrarily to what seems to happen ). This is treacherous, as it dereferences some memory locations that may not be accessible, as happened to me and led to hours of debugging to finally figure out the compiled function was not the one defined. cc
IIRC this is invalid and rustc should reject such a function, naked functions can't take arguments and the compiler should probably enforce that.
Hmm, my understanding of the RFC (“The following variant is not an error because the C calling convention is well-defined and it is thus possible for the programmer to write a conforming function”, even if the example is not with an argument) would mean that if the function is declared , then the function can actually respect the said ABI, thus should be well-formed?
Is there an update on this? I was hit by this issue as well. I hit the problem when compiling a tock app (baremetal-ish and jumped to by the tock OS) A naked function with arguments would produce this prolog (RV32): Which would result in an invalid access as s0 would be 0. Removing the arguments would remove the prologue and fix the problem. Removing the naked cfg would also work as teh stack pointer was already setup by the OS and result in this. If arguments with naked functions aren't supported rustc should generate an error as this is a difficult problem to debug.
This is an LLVM bug. Has it been reported upstream?

Discussion:
use rustc_hir::{GeneratorKind, HirIdMap, Node}; use rustc_index::vec::{Idx, IndexVec}; use rustc_infer::infer::TyCtxtInferExt; <ins> use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; </ins> use rustc_middle::middle::region; use rustc_middle::mir::*; use rustc_middle::ty::subst::Subst;

argument_scope: region::Scope, ast_body: &'tcx hir::Expr<'tcx>, ) -> BlockAnd<()> { <ins> let tcx = self.hir.tcx(); let attrs = tcx.codegen_fn_attrs(fn_def_id); let naked = attrs.flags.contains(CodegenFnAttrFlags::NAKED); </ins> // 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)); <ins> // Emit function argument debuginfo only for non-naked functions. // See: https://github.com/rust-lang/rust/issues/42779 if naked { continue; } </ins> // 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() {

} } <del> let tcx = self.hir.tcx(); </del> let tcx_hir = tcx.hir(); let hir_typeck_results = self.hir.typeck_results();

// CHECK-NEXT: define void @naked_with_args(i{{[0-9]+( %0)?}}) pub fn naked_with_args(a: isize) { // CHECK-NEXT: {{.+}}: <del> // CHECK-NEXT: %a = alloca i{{[0-9]+}} </del> <ins> // CHECK-NEXT: %_1 = alloca i{{[0-9]+}} </ins> &a; // keep variable in an alloca // CHECK: ret void }

#[naked] pub fn naked_with_args_and_return(a: isize) -> isize { // CHECK-NEXT: {{.+}}: <del> // CHECK-NEXT: %a = alloca i{{[0-9]+}} </del> <ins> // CHECK-NEXT: %_1 = alloca i{{[0-9]+}} </ins> &a; // keep variable in an alloca // CHECK: ret i{{[0-9]+}} %{{[0-9]+}} a

<ins> // 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() { () } </ins>