-
Notifications
You must be signed in to change notification settings - Fork 13.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Naked functions with parameters generate load/store instructions in debug mode #34043
Comments
CC @ticki |
Seems to be a result of unwinding. |
Yes, the ; Function Attrs: naked uwtable
define void @naked_fn(i8*, i8*) unnamed_addr #0 !dbg !10 {
entry-block:
%a = alloca i8*
%b = alloca i8*
store i8* %0, i8** %a
call void @llvm.dbg.declare(metadata i8** %a, metadata !19, metadata !20), !dbg !21
store i8* %1, i8** %b
call void @llvm.dbg.declare(metadata i8** %b, metadata !22, metadata !20), !dbg !21
unreachable, !dbg !23
} (Both this and the IR @philpax posted are in debug mode) |
That's even more interesting. |
The current implementation doesn't really support arguments though, a correct implementation would enforce that they don't need allocas (which... depends on ABI and MIR optimization passes). |
@eddyb Yeah. It should preferably error when given arguments. |
Hmm; naked functions without arguments seem rather limited in scope. Would that just be a temporary limitation? |
@philpax You can still pass arguments through inline assembly. In the long term, it should support arguments, though. |
I don't mean to bump an old thread, but I am curious on the state of this. I have come across this issue as well, but it only seems to appear in debug builds, not in release builds, although this could be a result of the optimizer. |
@Chaser53 It's not entirely. You can compile your code without debuginfo and it should be better. I should mention I already hit a gdb bug in #40367 (which is only a minor improvement), so that's not encouraging, but I'll try to get a C reproduction for it and/or work around it. |
Just ran into this. The generated code results in undefined behaviour if you ever call a naked function with arguments compiled with #![feature(asm, naked_functions)]
#[naked]
#[no_mangle]
pub unsafe extern "C" fn naked(_arg: u64) {
asm!("ret" :::: "intel");
}
#[no_mangle]
pub extern "C" fn non_naked(_arg: u64) {
return;
} 00000000000004f0 <naked>:
4f0: 48 89 7d f0 mov %rdi,-0x10(%rbp)
4f4: 48 8b 7d f0 mov -0x10(%rbp),%rdi
4f8: 48 89 7d f8 mov %rdi,-0x8(%rbp)
4fc: c3 retq
4fd: c3 retq
4fe: 66 90 xchg %ax,%ax
0000000000000500 <non_naked>:
500: 55 push %rbp
501: 48 89 e5 mov %rsp,%rbp
504: 48 89 7d f0 mov %rdi,-0x10(%rbp)
508: 48 8b 7d f0 mov -0x10(%rbp),%rdi
50c: 48 89 7d f8 mov %rdi,-0x8(%rbp)
510: 5d pop %rbp
511: c3 retq The naked function immediately starts moving stuff to rbp. Under the System V abi rbp is just another general purpose register, it could be null or anything else. Compare to the non naked function which first sets rbp to the stack pointer before pushing stuff. |
The IR with ; Function Attrs: naked nounwind uwtable
define void @naked(i64) unnamed_addr #0 !dbg !4 {
start:
%_arg = alloca i64
%arg0 = alloca i64
store i64 %0, i64* %arg0
call void @llvm.dbg.declare(metadata i64* %arg0, metadata !10, metadata !11), !dbg !12
call void @llvm.dbg.declare(metadata i64* %_arg, metadata !13, metadata !11), !dbg !15
%1 = load i64, i64* %arg0, !dbg !16
store i64 %1, i64* %_arg, !dbg !16
call void asm inteldialect "ret", "~{dirflag},~{fpsr},~{flags}"(), !dbg !17, !srcloc !18
ret void, !dbg !19
}
; Function Attrs: nounwind uwtable
define void @non_naked(i64) unnamed_addr #1 !dbg !20 {
start:
%_arg = alloca i64
%arg0 = alloca i64
store i64 %0, i64* %arg0
call void @llvm.dbg.declare(metadata i64* %arg0, metadata !21, metadata !11), !dbg !22
call void @llvm.dbg.declare(metadata i64* %_arg, metadata !23, metadata !11), !dbg !25
%1 = load i64, i64* %arg0, !dbg !26
store i64 %1, i64* %_arg, !dbg !26
ret void, !dbg !27
} Without ; Function Attrs: naked nounwind uwtable
define void @naked(i64) unnamed_addr #0 {
start:
call void asm inteldialect "ret", "~{dirflag},~{fpsr},~{flags}"(), !srcloc !0
ret void
}
; Function Attrs: nounwind uwtable
define void @non_naked(i64) unnamed_addr #1 {
start:
ret void
} This means that we have to switch from |
Triage: https://godbolt.org/z/WwgiGH looks like maybe this has been fixed?
|
@steveklabnik this issue is about debug mode, and I think we don't have issues without debuginfo anymore, it's just debuginfo that still causes code to be generated. An easy fix I didn't consider years ago would've been to "just" not emit debuginfo in such functions. |
This should be fixed here: #74105 |
Closing as fixed. Please let us know if this is still an issue. |
results in
Most of these instructions should not be present, and result in undesired codegen prior to any user code (i.e. assembly).
The text was updated successfully, but these errors were encountered: