<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/122840>122840</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
Clang incorrectly adds tailcalls after `setjmp(...)` with `-fno-builtin`
</td>
</tr>
<tr>
<th>Labels</th>
<td>
clang:codegen
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
alanzhao1
</td>
</tr>
</table>
<pre>
Originally reported by Chromium at https://g-issues.chromium.org/issues/380508212
Example:
```c
#include <setjmp.h>
struct JpegCommon {
jmp_buf jmpbuf;
int cinfo;
};
int jpeg_start_decompress(int *);
int jpeg_common_start_decompress(struct JpegCommon* jpeg_common) {
if (setjmp(jpeg_common->jmpbuf) == -1) {
return 0;
}
return jpeg_start_decompress(&jpeg_common->cinfo);
}
```
If this file is compiled with `-fno-builtin`, then Clang will optimize the call to `jpeg_start_decompress(...)` as a tailcall:
```asm
jpeg_common_start_decompress:
push rbx
mov rbx, rdi
call _setjmp@PLT
cmp eax, -1
je .LBB0_1
add rbx, 200
mov rdi, rbx
pop rbx
jmp jpeg_start_decompress@PLT
.LBB0_1:
xor eax, eax
pop rbx
ret
```
This is incorrect. Control flow may resume at `setjmp(...)` from another function. Because of this, the contents of the execution stack must be preserved. The tail call optimization shown above is incorrect because `jpeg_start_decompress(...)` may mess up the stack for when we later enter `jpeg_common_start_decompress(...)` at `setjmp(...)` via a `longjmp(..)` call.
This incorrect codegen only occurs with `-fno-builtin` - if we don't pass `-fno-builtin`, Clang correctly emits a call instruction (thereby preserving the stack).
godbolt: https://godbolt.org/z/1anGj6e3s
</pre>
<img width="1" height="1" alt="" src="http://email.email.llvm.org/o/eJyMVU1v8zYM_jXKhYghy_nywYc0bYYNL7Adei9kmbaVyZKhj6Tprx9kO6nXNsMMI4pFUnwekiK5c7LRiAVZP5H184IH3xpbcMX1R8tNuihNdS3-tLKRmit1BYu9sR4rKK9waK3pZOiAe2i97x3J9oQdCTs2S-lcQJeISSUxtiHsOO4Sdsx2dE13LGWE7gndv7zzrlcY7YdvsqHjK-IHy6QWKlQIJDs49KeuT1qSvYy6ztsgPPzRY3MwXWc0kO0ToXuAU9e_laGOaxlqko27UnsQUtdm3CDb5-kP3UfRqcfmzXlu_VuFwnS9RecI20UZYXvC8u_qYvD7k9U3cITt5zaE5Xe4soZoMfAjbDfTWpLsZSIR9bNnkj3DMp0ZW_TBaqA3kpFVXKf9R6QI23xxM0bmTnI45p6NkfbvNfhWOqilQpAO4nlSYQUX6VsgG7qstVmWQSovdbRiB_Atajgorhu4SKXA9F528gOjAARXCryJpo-AJkkSQW0ocAccPJcqWn0vGO46Qvf_mZXBBqanD66Nqy3f425nznD7ZAewlZzpDjgB4G3K0Yr-9et1Lu_6YUU-GC_TKDvhKEx-PT3Rt3Smzqtq7otROhPegVRyADLC600PM7TTc5r8_hy8G8obgJH-u7FzrHGZBeVHNxb992J4jZUQXy2MtSh8AgejvTUKamUu0PHYM1zoMHYJsqH3-v5MaW1NB1wb36KFOmjhpdEJPKHgwSGYsd6mMgJhtEft3biPgO8oQrQA57n4G7rgPJQIkT3aM1YJvLY4lMyYwan2-GjTmosGXpoz_osGlJP3_1WUkWWHzkHoB0wjktpYuMTCvyAo7tEC6vh7O_Jx25iV-6OgnSUHHmXK6OYmnGSRZjLPz52VMBU2qMFodQUjRLDu0bWFZexIF4Qqtqmth5479-B6jzd7cqKugJ308Z4O8ZZ67IIx3ITtYpaxvN7yI3XzGTLC8gl3Y6rSKE-y_dfRMgqmgfJB2DHl-rfTBjO3qIqsyrOcL7BIt9lml27y7XrRFqxc0XW1KreUllTUdEdxU-csW7N8l-Z8t5AFo2xN03RFU5pn60SsUhQ15UKs6pwJJCuKHZcqUeo8DLPFMMqKlLHdii4UL1G5YYgyJmIwSLafYk0Yi5PVFtF0WYYmXkklnXefh3npFRZjFO_JUtfYIty92Tng9VQ-P9TDgywuglXFlwhK34YyEaYj7BghTMuyt-aEws_n9MTvXLB_AgAA__8Ml5Aw">