<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/95093>95093</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
[AArch64] Wrong code for variadic argument with preserve_none calling convention
</td>
</tr>
<tr>
<th>Labels</th>
<td>
backend:AArch64,
miscompilation
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
ostannard
</td>
</tr>
</table>
<pre>
When using the `preserve_none` calling convention attribute, we generate incorrect code for variadic arguments:
```c
#include <stdarg.h>
__attribute__((preserve_none))
int F1(int P5, ...) {
va_list vl;
va_start(vl, P5);
int P6 = va_arg(vl, int);
va_end(vl);
return P6;
}
```
```
$ /work/llvm/install/bin/clang --target=aarch64--none-elf -c test.c -O1 -o - -S
.text
.file "test.c"
.globl F1 // -- Begin function F1
.p2align 2
.type F1,@function
F1: // @F1
// %bb.0: // %entry
sub sp, sp, #224
mov x8, #-64 // =0xffffffffffffffc0
mov x9, sp
add x10, sp, #128
movk x8, #65408, lsl #32
add x9, x9, #128
stp x0, x1, [sp, #128]
stp x9, x8, [sp, #208]
add x9, x10, #64
add x10, sp, #224
mov x8, #-64 // =0xffffffffffffffc0
stp x2, x3, [sp, #144]
stp x4, x5, [sp, #160]
stp x6, x7, [sp, #176]
stp q0, q1, [sp]
stp q2, q3, [sp, #32]
stp q4, q5, [sp, #64]
stp q6, q7, [sp, #96]
stp x10, x9, [sp, #192]
tbz w8, #31, .LBB0_3
// %bb.1: // %vaarg.maybe_reg
add w9, w8, #8
cmn w8, #8
str w9, [sp, #216]
b.gt .LBB0_3
// %bb.2: // %vaarg.in_reg
ldr x9, [sp, #200]
add x8, x9, x8
b .LBB0_4
.LBB0_3: // %vaarg.on_stack
ldr x8, [sp, #192]
add x9, x8, #8
str x9, [sp, #192]
.LBB0_4: // %vaarg.end
ldr w0, [x8]
add sp, sp, #224
ret
.Lfunc_end0:
.size F1, .Lfunc_end0-F1
// -- End function
.ident "clang version 19.0.0git (git@github.com:llvm/llvm-project.git 79ce70b8033815b6abd3a9a5cc2335de70f1aaab)"
.section ".note.GNU-stack","",@progbits
.addrsig
```
The two constants of `-64` in the assembly correspond to the `gr_offs` field in the `va_list`, so this ends up loading the argument from the saved copy of `x0`, which the first (non-variadic) argument was passed in, instead of `x1`.
Without the `preserve_none` attribute, that constant is `-56`, so the argument is correctly loaded from `x1`:
```
$ /work/llvm/install/bin/clang --target=aarch64--none-elf -c test.c -O1 -o - -S
.text
.file "test.c"
.globl F1 // -- Begin function F1
.p2align 2
.type F1,@function
F1: // @F1
// %bb.0: // %entry
sub sp, sp, #224
mov x8, #-56 // =0xffffffffffffffc8
mov x9, sp
add x10, sp, #136
movk x8, #65408, lsl #32
add x9, x9, #128
stp x1, x2, [sp, #136]
stp x9, x8, [sp, #208]
add x9, x10, #56
add x10, sp, #224
mov x8, #-56 // =0xffffffffffffffc8
stp x3, x4, [sp, #152]
stp x5, x6, [sp, #168]
stp q0, q1, [sp]
stp q2, q3, [sp, #32]
stp q4, q5, [sp, #64]
stp q6, q7, [sp, #96]
str x9, [sp, #200]
stp x7, x10, [sp, #184]
tbz w8, #31, .LBB0_3
// %bb.1: // %vaarg.maybe_reg
add w9, w8, #8
cmn w8, #8
str w9, [sp, #216]
b.gt .LBB0_3
// %bb.2: // %vaarg.in_reg
ldr x9, [sp, #200]
add x8, x9, x8
b .LBB0_4
.LBB0_3: // %vaarg.on_stack
ldr x8, [sp, #192]
add x9, x8, #8
str x9, [sp, #192]
.LBB0_4: // %vaarg.end
ldr w0, [x8]
add sp, sp, #224
ret
.Lfunc_end0:
.size F1, .Lfunc_end0-F1
// -- End function
.ident "clang version 19.0.0git (git@github.com:llvm/llvm-project.git 79ce70b8033815b6abd3a9a5cc2335de70f1aaab)"
.section ".note.GNU-stack","",@progbits
.addrsig
```
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzsmFuP4ygWxz8NeUG2ML4_5KGq09mX1W5Lu6t-jLDBDlsOpIAkVf3pR-BL-ZJUdal6enpGY0V2gg-H_zkHwy8mWvNaMLYG8T2INytyMnup1lIbIgRRdFVI-rz-umcCnjQXNTR7BkGCjoppps5sJ6RgIEGwJE1j75dSnJkwXApIjFG8OBkG8Cd4YbBmgiliGOSilEqx0sBSUgYrqeCZKE4oLyFR9enAhNEgvANoA9AdSFD7KbvfOOSibE6UQRB-0oYSVft7EH7ubrvzbjeMvtsBnAGcTSXj3H6cLRcGbgOAM_vlS2zV-r4PcA5Bet-awDPZNVwbeG5A2LfZRm2IMgBn58Z2s53zkYFzmEAQbqwtUfVgyYWZmJ7Jjgna3R67UMyclIBfkqENpJtZYsaBzxtxBAHeXqR6AHjbNOcDwFsutCFNA_C24ALgbdkQUUPPM0TVzIBwQ4gq90nkeTZVHmsq6JXQMG38Enr_DqAnoQe9__Qa28M37MnMmireMAghwLjtDTCeWdSNLBoIt4GVCfAWeh68ZzUXsDqJ0s2jbTDrc8Sk4bWAc1_m-WhHs7X8BCLUO2ittgEI7_pBQIR6r30LjovCR9bm9ePFngmjnqcS9KmA-mgL3J4BDjGOpjYHeXbXp6yz8JLorcHCDXqqJkeJbnjNu9Endwml7d0ATcQFOFu4eZiIS-IIue-NbuzvEN_w7MZtz9cca3Ns7ZyAp8DZxfcTJfHmRp_Wdzbvg9Gyz0xPG6-NI_q-jLyU6wfXaQgGO2HhIgFRdDsBkesTL_ok6KXPYJw443RhnCY3B3h0SXgcVeWa5aOT_riQHuLbjp3yx4Xy5Hawj07_40J_flt-V8Ru9o1jzpfSTPHNXS99XUMXtv_P-3u0C68sCsF7FoUzsdvRgTwXbKdYfX3SXZzQQcDsUSkPYiowGyqsRt0nT0KwTE7h18ZebweGxytiL52Lpe6GtgMvE4zRaAYOz1T2Uo2nWXBFd21Vdc9aL_GKHCnsHls-3BC0WBMmFZ8tBjfy3af19enTC76i0e7cV-VdUOfx6fpC9dZWoZjpB7ebmUUENHBRb-Rr_m3Y9uDI0ptvnG8dLzvwZ0HhdPscRuOUCeO29BYbzkxpu0sHuY98VHMDAc5qbkBkf-xPhV_KAwjvOvawF--o5P9ZaXxrneYlS1GRoTDMgrhISEFDkpO4LHEYxpSlqAoIIYUjtvmOr1mLCABjX0jD_H_8639eO1-wXazcGbc4cFSyLrjRMxeEUqV5_QpS_XfPoLlIi7YWi42GsrIM7CWRJV8uHBQTrdmhaJ6hY1t9lIJCI3tertVOVpW29hVnDe17gQR1aGkHtZPBduEaMkE1PB1hIwntubtnY1gpeXAtmpwZhaU8PneanlDn57Ln5d7ZVFxpVxQhhddztqXbwd2FaHi0-q2slk61YYT2PgOQIH-cka_c7OXJ3PwzMCF_sydmyB3k2qUuTsbxjkLjGnZ_DppnFzyjbbi9kOX_gr9J909DunHy1mBXCGqJqK3X95FumPxs0nXrcYt7k00lfAVkfgDpxsnHSfdDdRqCcaDYsuskAfFtXmwZt0XYKelmS9L9Pmp1lu8j19-bWr-LpuaZScdlHqcmW6r6Ixj3g3A7S86vyrjd8SNQ9535_hAJz2X_okDsRv9JUPwO2v2Lw-6KrkOahzlZsXWQBhnK8zBIV_t1nBakihBmRVlFRVkFSRiXaYEpLVFJ0mjF1xjhCCVBgPIoC1M_zQKWVVFKE0YTGmMQIXYgvPFtKnyp6hXX-sTWeYzycNWQgjXavXvGuCDlg5044d3dnYOyIaoD16U8HHlDXIWwnYMrtXbZLU61BhGyBK1fBjHcNO6ddu8q3sCvSrr307feOMMLN3s4Ydkrb7VXJ9Ws98Yc3QtqN4VGlR_Ac1x5y6E2aA3wto37vMa_BQAA___nuPJR">