xref: /netbsd-src/external/apache2/llvm/dist/libcxx/src/filesystem/int128_builtins.cpp (revision 4d6fc14bc9b0c5bf3e30be318c143ee82cadd108)
1*4d6fc14bSjoerg /*===-- int128_builtins.cpp - Implement __muloti4 --------------------------===
2*4d6fc14bSjoerg  *
3*4d6fc14bSjoerg  * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*4d6fc14bSjoerg  * See https://llvm.org/LICENSE.txt for license information.
5*4d6fc14bSjoerg  * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*4d6fc14bSjoerg  *
7*4d6fc14bSjoerg  * ===----------------------------------------------------------------------===
8*4d6fc14bSjoerg  *
9*4d6fc14bSjoerg  * This file implements __muloti4, and is stolen from the compiler_rt library.
10*4d6fc14bSjoerg  *
11*4d6fc14bSjoerg  * FIXME: we steal and re-compile it into filesystem, which uses __int128_t,
12*4d6fc14bSjoerg  * and requires this builtin when sanitized. See llvm.org/PR30643
13*4d6fc14bSjoerg  *
14*4d6fc14bSjoerg  * ===----------------------------------------------------------------------===
15*4d6fc14bSjoerg  */
16*4d6fc14bSjoerg #include "__config"
17*4d6fc14bSjoerg #include "climits"
18*4d6fc14bSjoerg 
19*4d6fc14bSjoerg #if !defined(_LIBCPP_HAS_NO_INT128)
20*4d6fc14bSjoerg 
21*4d6fc14bSjoerg extern "C" __attribute__((no_sanitize("undefined"))) _LIBCPP_FUNC_VIS
__muloti4(__int128_t a,__int128_t b,int * overflow)22*4d6fc14bSjoerg __int128_t __muloti4(__int128_t a, __int128_t b, int* overflow) {
23*4d6fc14bSjoerg   const int N = (int)(sizeof(__int128_t) * CHAR_BIT);
24*4d6fc14bSjoerg   const __int128_t MIN = (__int128_t)1 << (N - 1);
25*4d6fc14bSjoerg   const __int128_t MAX = ~MIN;
26*4d6fc14bSjoerg   *overflow = 0;
27*4d6fc14bSjoerg   __int128_t result = a * b;
28*4d6fc14bSjoerg   if (a == MIN) {
29*4d6fc14bSjoerg     if (b != 0 && b != 1)
30*4d6fc14bSjoerg       *overflow = 1;
31*4d6fc14bSjoerg     return result;
32*4d6fc14bSjoerg   }
33*4d6fc14bSjoerg   if (b == MIN) {
34*4d6fc14bSjoerg     if (a != 0 && a != 1)
35*4d6fc14bSjoerg       *overflow = 1;
36*4d6fc14bSjoerg     return result;
37*4d6fc14bSjoerg   }
38*4d6fc14bSjoerg   __int128_t sa = a >> (N - 1);
39*4d6fc14bSjoerg   __int128_t abs_a = (a ^ sa) - sa;
40*4d6fc14bSjoerg   __int128_t sb = b >> (N - 1);
41*4d6fc14bSjoerg   __int128_t abs_b = (b ^ sb) - sb;
42*4d6fc14bSjoerg   if (abs_a < 2 || abs_b < 2)
43*4d6fc14bSjoerg     return result;
44*4d6fc14bSjoerg   if (sa == sb) {
45*4d6fc14bSjoerg     if (abs_a > MAX / abs_b)
46*4d6fc14bSjoerg       *overflow = 1;
47*4d6fc14bSjoerg   } else {
48*4d6fc14bSjoerg     if (abs_a > MIN / -abs_b)
49*4d6fc14bSjoerg       *overflow = 1;
50*4d6fc14bSjoerg   }
51*4d6fc14bSjoerg   return result;
52*4d6fc14bSjoerg }
53*4d6fc14bSjoerg 
54*4d6fc14bSjoerg #endif
55