<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/62743>62743</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
Clang and compiler-rt disagree on preconditions for __aeabi_llsr and __aeabi_llsr
</td>
</tr>
<tr>
<th>Labels</th>
<td>
new issue
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
davidben
</td>
</tr>
</table>
<pre>
`uint64_t{a} >> b` in C is only defined for `0 <= b < 64`. On 32-bit platforms, `uint64_t` is sometimes implemented with an intrinsic. But what are the preconditions on that intrinsic?
The compiler-rt implementations say they share the precondition. See the "Precondition:" comment. In code, they seem to also assume this. The `b & bits_in_word` check only makes sense because of the bound, and if `b` were too large, those functions (themselves written in C) would hit the C-level UB.
https://github.com/llvm/llvm-project/blob/689de4c6759fa810d827aee06a0ab060b01172ce/compiler-rt/lib/builtins/ashldi3.c
https://github.com/llvm/llvm-project/blob/2f4c96097a3cbf9d07eab699efd25f767bb4fdd5/compiler-rt/lib/builtins/lshrdi3.c
However, Clang seems to believe otherwise:
https://godbolt.org/z/rjPx5j6ne
First, note `-fsanitize=undefined` does not add checks to the guarded functions, only the unguarded functions. So Clang seems to believe that `r > 63 ? 0 : x >> r` is sufficient to dispatch the preconditions. However, the generated code for the guarded functions looks like:
```
guarded_rshift:
push {r4, lr}
mov r4, r2
bl __aeabi_llsr
cmp r4, #63
movhi r0, #0
movhi r1, #0
pop {r4, lr}
bx lr
guarded_lshift:
push {r4, lr}
mov r4, r2
bl __aeabi_llsl
cmp r4, #63
movhi r0, #0
movhi r1, #0
pop {r4, lr}
bx lr
```
There's no branch before calling `__aeabi_llsr` and `__aeabi_llsl`. Clang seems to be transforming this into:
```
uint64_t guarded_rshift(uint64_t x, unsigned r) {
// WAS: return r > 63 ? 0 : x >> r;
uint64_t t = __aeabi_llsr(x, r);
return r > 63 ? 0 : t;
}
```
That is, Clang believe those functions are defined for all inputs. It doesn't seem to care what the output is, but it is relying on them to not diverge. This contradicts with the compiler-rt implementation, so I think one needs to change. We have to either believe:
1. The intrinsics are defined for all inputs. The compiler-rt comments and implementation are wrong. Or...
2. The intrinsics have the documented preconditions. Clang's output above was invalid.
(No preferences on my end which option makes more sense.)
We ran into this experimenting with Rust in Chrome, because Rust also pulls in a copy of these functions. When building that with trapping overflow, we get a miscompile. But I expect a UBSan-built compiler-rt would have the same issues. Possibly fun times if one ever does LTO here... (We'll file a bug with Rust that they need to make sure their functions match whatever's decided here, depending on which it is.)
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzMV91u47oRfhr6ZhBBpmzJvvDFJjlGFyi6i-45yGVAiiOLuxQpkJQd79MXQ8mOnOymKAoUDQLLNjn_38x8FiHog0XcsfU9Wz8uxBBb53dKHLWSaBfSqfOOlfmgbSxXz5FV94JVj8CKP1jxB0hW5qAtPIAO4Kw5g8JGW1TQOA-szHNgxQMrHkHSGyhXrMwz-GKh4HdSR-iNiI3zXWD8AeZ2SG-A4DqMusMAuusNdmgjKjjp2IKwoG302gZdZ3A_RDi1IoLwCLFF6D3WziodtbPkGkQ6vUqwYs_yR5Z_Gl__bBFq1_XaoL_z8dWaGOWDOJPWM4T2VwYy-Ibjt4zzr7MDVnxinJNqUpbBZwu1U0jBjuoQO4gOhAkORAhDR2p0yIA8YmUugfESpI7hWdvnk_OKMlO3WP8Y892JHxggoA0IEmsxBATXJF-kG6wiU8Iq0E1SR9InpBCcAyP8YfLFBYRmsPUYLuOb2GIX0BwxwMnrGNGmOjO-hZMbjIJWx2Tl4c7gEQ38dZ-NuWxj7EMKfM_4_qBjO8isdh3je2OOl8dd7913rCPje2mcZHxfbrYKV3VZrbeN2CxzteGVQMxLkQuZl7nMl8uK18j4flYqUqdJXA7aRG0D43sRWqN0kdX_nUO8WdXbMt9Woqhls1V5hUKW2y02iq-bqqykXDVKrf-9Qya0fubQ-Po3d8Ijesr_gxH2kMAQCA0SjcYjgost-pMOSM7_KhSnpDMxc_7A-P4n43v__evL-ntpcW5or32IZMa6mEB11wRhddQ_kRWPg51alqChHAa6BkKpEWXJIarzYRBeUWNfUEIaEwTpdLDvzjP45n4XWWpGVuaeBgmUBbBiDzQrPsHLZbb4ywwYmkbXGm0kDUqHXsS6fd_kGcwymjxGi17QwKCeSxPpl4GAce5HAKN_vCZ6ei3z6T99nCSffWh1E693Yfrrh9ACq-79ijwwnlWPtxc6d0zP8YLnt6fSjM_nZ4FC6mdjgp9u1F0_E2S8KIt3mltNF_LpQv6b8-Wb896Nmj9yW76MT-Nv02D-V2kw_5dpeAOO6yLxyHhFXQTSC1u3ILFxHqEWxmh7INjflLjM04C-_dqkPfmueyB6YQMtTNJEm4JWmvsYtpedCm_wyzfXkxeKebCJCyjwNOVZdf8a_zhv4OnTN2pRj3HwFj5u3mImfrUTgbjATfh8k4yTzRuZ3xuJ13vXGv2mFrTxw-uAfZ0-t-uOVvqctwhjQNt-iCGDzzENRct4Fa_ruiaJRDdooLgh9sPFkqR39AE8mjNVKXGPUY4mq9JH9AekDa8D1M5GL5SuYxhpTfyQiZCF4OAzld4SA0CwiCqho26FJb1PCK2gKB2gpg1yifsNSpYjybhSoo_z8JYhTZQmjOTixsmk5-SdPWTwxWfZxAv4O3ujmy2CcvUwcbs3Iz0VLvXTlGUh3RHhJAj4R2G0ym6Qzzf_cKSjQY-2xsT8ujOgVXBqdd2C65OLI23qqC8Td8oIfjNFTwh-ZJhubDN86dFrcpJqmkr1zyHERIpa77rEoy4ELJ0kTtcPxpCrIKB2_XmiZnP0ZfDUogViC2psahEnKHjR9wlBR_SNcScycaK9FkFAp8NUj5H9fk4u1nT01_03Ye8S_7ip2UTcLlkPokPQIQwYMvjqQtDSnMkxmCh3kwBGK3UkBn__8wvQfMuyjCjiEw06Y6DRBkGAHOZ5iVN3nBNACYyUcgjDSJ-1n_VflxY69dO4vqsACmtNS3ocpw-gsEerpnYaK5m6jOq2ULtCbYutWOBuWW5WfL0py_Wi3S1XG1mUouFSSCVLKdWG5_VmXRXbrcT1ZqF3POdFvl6Wy6qoVuus3mzq9XK5lWuJoioVW-XYCW0yYojEsxYpX7uSV6tiYYREE9JPJ84tnsZkMs7pl5TfJVYph0Ngq9zoEMOrlqijwd04laiB5lVSOoiDR6RIb3_FUE_OZ2cSnX-xGLzZ_cd0d4QAMXCK6l8BAAD__2w4dUY">