LLVM crash when using argument of naked function
Zig Version
0.13
Steps to Reproduce and Observed Behavior
While playing with inline ASM I get a SEGFAULT in release. The following code does not do anything and is totally wrong, but the compiler should not SEGFAULT.
This program segfaults the compiler with exit code 139.
zig build-exe sample.zig -OReleaseSafe --> segfaults zig build-exe sample.zig -OReleaseFast --> segfaults zig build-exe sample.zig --> OK
// Type your code here, or load an example.
const std = @import("std");
fn hello(counter: *i32) callconv(.Naked) void {
counter.* = counter.* +% 1;
call(@ptrCast(&hello), counter);
// call("example.hello", counter);
}
inline fn call(tcfn: *const void, arg1: *i32) void {
asm volatile (
\\jmp *%[f]
:
: [f] "{rax}" (tcfn),
[arg1] "{esi}" (arg1),
);
}
fn square(num: i32) i32 {
var i: i32 = 0;
call(@ptrCast(&hello), &i);
// hello(0);
return num * num;
}
pub fn main() !void {
_ = square(100);
}
Expected Behavior
Anything but a SEGFAULT.
Repros on 0.14.0-dev.1338+93cb44c80 targeting x86_64-linux. LLVM error:
Can't get register for value!
UNREACHABLE executed at /home/mlugg/llvm/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp:1920!
LLVM IR reduction:
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
; Function Attrs: naked
define void @empty.hello(ptr %0) #0 {
Entry:
%1 = load i32, ptr %0, align 4
ret void
}
attributes #0 = { naked }
doesn't need -O3 to trigger.
Lovely, mind filing an upstream issue @Rexicon226?
oh, wait, maybe verify it's not fixed on llvm 19 first lol
oh, wait, maybe verify it's not fixed on llvm 19 first lol
It's not:
❯ ~/local/llvm19-debug/bin/llc test.ll
Can't get register for value!
UNREACHABLE executed at /Users/david/Code/llvm-project/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp:1959!
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
Lovely, mind filing an upstream issue @Rexicon226?
Can do in a minute.
Well actually, it seems they fixed it at some point between 19-master: https://zig.godbolt.org/z/63oWfMh9G
Why do we allow arguments in naked functions again?
IIRC naked functions are a little up in the air ATM. @alexrp has talked about constraining them to effectively only contain asm statements.
The bug here is that we allow people to reference arguments in a naked function in Sema.
LLVM is basically right to either reject or not handle IR that does this because, in the general case, there is no way to make it work in a naked function.
My change to allow arguments in naked functions should be reverted, you can name the arguments when you cast:
pub const foo: *const fn (helpful_name: u32) callconv(.C) u32 = @ptrCast(&fooNaked);
I'd also argue that you should be required to use a return type of noreturn for all naked functions since they are not callable and cannot contain return statements.