1219820Sjeff/*===-- int128_builtins.cpp - Implement __muloti4 --------------------------=== 2219820Sjeff * 3219820Sjeff * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4219820Sjeff * See https://llvm.org/LICENSE.txt for license information. 5219820Sjeff * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6219820Sjeff * 7219820Sjeff * ===----------------------------------------------------------------------=== 8219820Sjeff * 9219820Sjeff * This file implements __muloti4, and is stolen from the compiler_rt library. 10219820Sjeff * 11219820Sjeff * FIXME: we steal and re-compile it into filesystem, which uses __int128_t, 12219820Sjeff * and requires this builtin when sanitized. See llvm.org/PR30643 13219820Sjeff * 14219820Sjeff * ===----------------------------------------------------------------------=== 15219820Sjeff */ 16219820Sjeff#include <__config> 17219820Sjeff#include <climits> 18219820Sjeff 19219820Sjeff#if !defined(_LIBCPP_HAS_NO_INT128) 20219820Sjeff 21219820Sjeffextern "C" __attribute__((no_sanitize("undefined"))) _LIBCPP_FUNC_VIS 22219820Sjeff__int128_t __muloti4(__int128_t a, __int128_t b, int* overflow) { 23219820Sjeff const int N = (int)(sizeof(__int128_t) * CHAR_BIT); 24219820Sjeff const __int128_t MIN = (__int128_t)1 << (N - 1); 25219820Sjeff const __int128_t MAX = ~MIN; 26219820Sjeff *overflow = 0; 27219820Sjeff __int128_t result = a * b; 28219820Sjeff if (a == MIN) { 29219820Sjeff if (b != 0 && b != 1) 30219820Sjeff *overflow = 1; 31219820Sjeff return result; 32219820Sjeff } 33219820Sjeff if (b == MIN) { 34219820Sjeff if (a != 0 && a != 1) 35219820Sjeff *overflow = 1; 36219820Sjeff return result; 37219820Sjeff } 38219820Sjeff __int128_t sa = a >> (N - 1); 39219820Sjeff __int128_t abs_a = (a ^ sa) - sa; 40219820Sjeff __int128_t sb = b >> (N - 1); 41219820Sjeff __int128_t abs_b = (b ^ sb) - sb; 42219820Sjeff if (abs_a < 2 || abs_b < 2) 43219820Sjeff return result; 44219820Sjeff if (sa == sb) { 45219820Sjeff if (abs_a > MAX / abs_b) 46219820Sjeff *overflow = 1; 47219820Sjeff } else { 48219820Sjeff if (abs_a > MIN / -abs_b) 49219820Sjeff *overflow = 1; 50219820Sjeff } 51219820Sjeff return result; 52219820Sjeff} 53219820Sjeff 54219820Sjeff#endif 55219820Sjeff