1615b7eeaSJoseph Huber //===- RuntimeLibcalls.cpp - Interface for runtime libcalls -----*- C++ -*-===// 2615b7eeaSJoseph Huber // 3615b7eeaSJoseph Huber // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4615b7eeaSJoseph Huber // See https://llvm.org/LICENSE.txt for license information. 5615b7eeaSJoseph Huber // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6615b7eeaSJoseph Huber // 7615b7eeaSJoseph Huber //===----------------------------------------------------------------------===// 8615b7eeaSJoseph Huber 9615b7eeaSJoseph Huber #include "llvm/IR/RuntimeLibcalls.h" 10615b7eeaSJoseph Huber 11615b7eeaSJoseph Huber using namespace llvm; 12615b7eeaSJoseph Huber using namespace RTLIB; 13615b7eeaSJoseph Huber 14615b7eeaSJoseph Huber /// Set default libcall names. If a target wants to opt-out of a libcall it 15615b7eeaSJoseph Huber /// should be placed here. 16615b7eeaSJoseph Huber void RuntimeLibcallsInfo::initLibcalls(const Triple &TT) { 17615b7eeaSJoseph Huber std::fill(std::begin(LibcallRoutineNames), std::end(LibcallRoutineNames), 18615b7eeaSJoseph Huber nullptr); 19615b7eeaSJoseph Huber 20615b7eeaSJoseph Huber #define HANDLE_LIBCALL(code, name) setLibcallName(RTLIB::code, name); 21615b7eeaSJoseph Huber #include "llvm/IR/RuntimeLibcalls.def" 22615b7eeaSJoseph Huber #undef HANDLE_LIBCALL 23615b7eeaSJoseph Huber 24615b7eeaSJoseph Huber // Initialize calling conventions to their default. 25615b7eeaSJoseph Huber for (int LC = 0; LC < RTLIB::UNKNOWN_LIBCALL; ++LC) 26615b7eeaSJoseph Huber setLibcallCallingConv((RTLIB::Libcall)LC, CallingConv::C); 27615b7eeaSJoseph Huber 28615b7eeaSJoseph Huber // Use the f128 variants of math functions on x86_64 29615b7eeaSJoseph Huber if (TT.getArch() == Triple::ArchType::x86_64 && TT.isGNUEnvironment()) { 30615b7eeaSJoseph Huber setLibcallName(RTLIB::REM_F128, "fmodf128"); 31615b7eeaSJoseph Huber setLibcallName(RTLIB::FMA_F128, "fmaf128"); 32615b7eeaSJoseph Huber setLibcallName(RTLIB::SQRT_F128, "sqrtf128"); 33615b7eeaSJoseph Huber setLibcallName(RTLIB::CBRT_F128, "cbrtf128"); 34615b7eeaSJoseph Huber setLibcallName(RTLIB::LOG_F128, "logf128"); 35615b7eeaSJoseph Huber setLibcallName(RTLIB::LOG_FINITE_F128, "__logf128_finite"); 36615b7eeaSJoseph Huber setLibcallName(RTLIB::LOG2_F128, "log2f128"); 37615b7eeaSJoseph Huber setLibcallName(RTLIB::LOG2_FINITE_F128, "__log2f128_finite"); 38615b7eeaSJoseph Huber setLibcallName(RTLIB::LOG10_F128, "log10f128"); 39615b7eeaSJoseph Huber setLibcallName(RTLIB::LOG10_FINITE_F128, "__log10f128_finite"); 40615b7eeaSJoseph Huber setLibcallName(RTLIB::EXP_F128, "expf128"); 41615b7eeaSJoseph Huber setLibcallName(RTLIB::EXP_FINITE_F128, "__expf128_finite"); 42615b7eeaSJoseph Huber setLibcallName(RTLIB::EXP2_F128, "exp2f128"); 43615b7eeaSJoseph Huber setLibcallName(RTLIB::EXP2_FINITE_F128, "__exp2f128_finite"); 44615b7eeaSJoseph Huber setLibcallName(RTLIB::EXP10_F128, "exp10f128"); 45615b7eeaSJoseph Huber setLibcallName(RTLIB::SIN_F128, "sinf128"); 46615b7eeaSJoseph Huber setLibcallName(RTLIB::COS_F128, "cosf128"); 47615b7eeaSJoseph Huber setLibcallName(RTLIB::TAN_F128, "tanf128"); 48615b7eeaSJoseph Huber setLibcallName(RTLIB::SINCOS_F128, "sincosf128"); 49615b7eeaSJoseph Huber setLibcallName(RTLIB::ASIN_F128, "asinf128"); 50615b7eeaSJoseph Huber setLibcallName(RTLIB::ACOS_F128, "acosf128"); 51615b7eeaSJoseph Huber setLibcallName(RTLIB::ATAN_F128, "atanf128"); 52875afa93STex Riddell setLibcallName(RTLIB::ATAN2_F128, "atan2f128"); 53615b7eeaSJoseph Huber setLibcallName(RTLIB::SINH_F128, "sinhf128"); 54615b7eeaSJoseph Huber setLibcallName(RTLIB::COSH_F128, "coshf128"); 55615b7eeaSJoseph Huber setLibcallName(RTLIB::TANH_F128, "tanhf128"); 56615b7eeaSJoseph Huber setLibcallName(RTLIB::POW_F128, "powf128"); 57615b7eeaSJoseph Huber setLibcallName(RTLIB::POW_FINITE_F128, "__powf128_finite"); 58615b7eeaSJoseph Huber setLibcallName(RTLIB::CEIL_F128, "ceilf128"); 59615b7eeaSJoseph Huber setLibcallName(RTLIB::TRUNC_F128, "truncf128"); 60615b7eeaSJoseph Huber setLibcallName(RTLIB::RINT_F128, "rintf128"); 61615b7eeaSJoseph Huber setLibcallName(RTLIB::NEARBYINT_F128, "nearbyintf128"); 62615b7eeaSJoseph Huber setLibcallName(RTLIB::ROUND_F128, "roundf128"); 63615b7eeaSJoseph Huber setLibcallName(RTLIB::ROUNDEVEN_F128, "roundevenf128"); 64615b7eeaSJoseph Huber setLibcallName(RTLIB::FLOOR_F128, "floorf128"); 65615b7eeaSJoseph Huber setLibcallName(RTLIB::COPYSIGN_F128, "copysignf128"); 66615b7eeaSJoseph Huber setLibcallName(RTLIB::FMIN_F128, "fminf128"); 67615b7eeaSJoseph Huber setLibcallName(RTLIB::FMAX_F128, "fmaxf128"); 68615b7eeaSJoseph Huber setLibcallName(RTLIB::LROUND_F128, "lroundf128"); 69615b7eeaSJoseph Huber setLibcallName(RTLIB::LLROUND_F128, "llroundf128"); 70615b7eeaSJoseph Huber setLibcallName(RTLIB::LRINT_F128, "lrintf128"); 71615b7eeaSJoseph Huber setLibcallName(RTLIB::LLRINT_F128, "llrintf128"); 72615b7eeaSJoseph Huber setLibcallName(RTLIB::LDEXP_F128, "ldexpf128"); 73615b7eeaSJoseph Huber setLibcallName(RTLIB::FREXP_F128, "frexpf128"); 74615b7eeaSJoseph Huber } 75615b7eeaSJoseph Huber 76615b7eeaSJoseph Huber // For IEEE quad-precision libcall names, PPC uses "kf" instead of "tf". 77615b7eeaSJoseph Huber if (TT.isPPC()) { 78615b7eeaSJoseph Huber setLibcallName(RTLIB::ADD_F128, "__addkf3"); 79615b7eeaSJoseph Huber setLibcallName(RTLIB::SUB_F128, "__subkf3"); 80615b7eeaSJoseph Huber setLibcallName(RTLIB::MUL_F128, "__mulkf3"); 81615b7eeaSJoseph Huber setLibcallName(RTLIB::DIV_F128, "__divkf3"); 82615b7eeaSJoseph Huber setLibcallName(RTLIB::POWI_F128, "__powikf2"); 83615b7eeaSJoseph Huber setLibcallName(RTLIB::FPEXT_F32_F128, "__extendsfkf2"); 84615b7eeaSJoseph Huber setLibcallName(RTLIB::FPEXT_F64_F128, "__extenddfkf2"); 85615b7eeaSJoseph Huber setLibcallName(RTLIB::FPROUND_F128_F32, "__trunckfsf2"); 86615b7eeaSJoseph Huber setLibcallName(RTLIB::FPROUND_F128_F64, "__trunckfdf2"); 87615b7eeaSJoseph Huber setLibcallName(RTLIB::FPTOSINT_F128_I32, "__fixkfsi"); 88615b7eeaSJoseph Huber setLibcallName(RTLIB::FPTOSINT_F128_I64, "__fixkfdi"); 89615b7eeaSJoseph Huber setLibcallName(RTLIB::FPTOSINT_F128_I128, "__fixkfti"); 90615b7eeaSJoseph Huber setLibcallName(RTLIB::FPTOUINT_F128_I32, "__fixunskfsi"); 91615b7eeaSJoseph Huber setLibcallName(RTLIB::FPTOUINT_F128_I64, "__fixunskfdi"); 92615b7eeaSJoseph Huber setLibcallName(RTLIB::FPTOUINT_F128_I128, "__fixunskfti"); 93615b7eeaSJoseph Huber setLibcallName(RTLIB::SINTTOFP_I32_F128, "__floatsikf"); 94615b7eeaSJoseph Huber setLibcallName(RTLIB::SINTTOFP_I64_F128, "__floatdikf"); 95615b7eeaSJoseph Huber setLibcallName(RTLIB::SINTTOFP_I128_F128, "__floattikf"); 96615b7eeaSJoseph Huber setLibcallName(RTLIB::UINTTOFP_I32_F128, "__floatunsikf"); 97615b7eeaSJoseph Huber setLibcallName(RTLIB::UINTTOFP_I64_F128, "__floatundikf"); 98615b7eeaSJoseph Huber setLibcallName(RTLIB::UINTTOFP_I128_F128, "__floatuntikf"); 99615b7eeaSJoseph Huber setLibcallName(RTLIB::OEQ_F128, "__eqkf2"); 100615b7eeaSJoseph Huber setLibcallName(RTLIB::UNE_F128, "__nekf2"); 101615b7eeaSJoseph Huber setLibcallName(RTLIB::OGE_F128, "__gekf2"); 102615b7eeaSJoseph Huber setLibcallName(RTLIB::OLT_F128, "__ltkf2"); 103615b7eeaSJoseph Huber setLibcallName(RTLIB::OLE_F128, "__lekf2"); 104615b7eeaSJoseph Huber setLibcallName(RTLIB::OGT_F128, "__gtkf2"); 105615b7eeaSJoseph Huber setLibcallName(RTLIB::UO_F128, "__unordkf2"); 106615b7eeaSJoseph Huber } 107615b7eeaSJoseph Huber 108615b7eeaSJoseph Huber // A few names are different on particular architectures or environments. 109615b7eeaSJoseph Huber if (TT.isOSDarwin()) { 110615b7eeaSJoseph Huber // For f16/f32 conversions, Darwin uses the standard naming scheme, 111615b7eeaSJoseph Huber // instead of the gnueabi-style __gnu_*_ieee. 112615b7eeaSJoseph Huber // FIXME: What about other targets? 113615b7eeaSJoseph Huber setLibcallName(RTLIB::FPEXT_F16_F32, "__extendhfsf2"); 114615b7eeaSJoseph Huber setLibcallName(RTLIB::FPROUND_F32_F16, "__truncsfhf2"); 115615b7eeaSJoseph Huber 116615b7eeaSJoseph Huber // Some darwins have an optimized __bzero/bzero function. 117615b7eeaSJoseph Huber switch (TT.getArch()) { 118615b7eeaSJoseph Huber case Triple::x86: 119615b7eeaSJoseph Huber case Triple::x86_64: 120615b7eeaSJoseph Huber if (TT.isMacOSX() && !TT.isMacOSXVersionLT(10, 6)) 121615b7eeaSJoseph Huber setLibcallName(RTLIB::BZERO, "__bzero"); 122615b7eeaSJoseph Huber break; 123615b7eeaSJoseph Huber case Triple::aarch64: 124615b7eeaSJoseph Huber case Triple::aarch64_32: 125615b7eeaSJoseph Huber setLibcallName(RTLIB::BZERO, "bzero"); 126615b7eeaSJoseph Huber break; 127615b7eeaSJoseph Huber default: 128615b7eeaSJoseph Huber break; 129615b7eeaSJoseph Huber } 130615b7eeaSJoseph Huber 131615b7eeaSJoseph Huber if (darwinHasSinCos(TT)) { 132615b7eeaSJoseph Huber setLibcallName(RTLIB::SINCOS_STRET_F32, "__sincosf_stret"); 133615b7eeaSJoseph Huber setLibcallName(RTLIB::SINCOS_STRET_F64, "__sincos_stret"); 134615b7eeaSJoseph Huber if (TT.isWatchABI()) { 135615b7eeaSJoseph Huber setLibcallCallingConv(RTLIB::SINCOS_STRET_F32, 136615b7eeaSJoseph Huber CallingConv::ARM_AAPCS_VFP); 137615b7eeaSJoseph Huber setLibcallCallingConv(RTLIB::SINCOS_STRET_F64, 138615b7eeaSJoseph Huber CallingConv::ARM_AAPCS_VFP); 139615b7eeaSJoseph Huber } 140615b7eeaSJoseph Huber } 141615b7eeaSJoseph Huber 142615b7eeaSJoseph Huber switch (TT.getOS()) { 143615b7eeaSJoseph Huber case Triple::MacOSX: 144615b7eeaSJoseph Huber if (TT.isMacOSXVersionLT(10, 9)) { 145615b7eeaSJoseph Huber setLibcallName(RTLIB::EXP10_F32, nullptr); 146615b7eeaSJoseph Huber setLibcallName(RTLIB::EXP10_F64, nullptr); 147615b7eeaSJoseph Huber } else { 148615b7eeaSJoseph Huber setLibcallName(RTLIB::EXP10_F32, "__exp10f"); 149615b7eeaSJoseph Huber setLibcallName(RTLIB::EXP10_F64, "__exp10"); 150615b7eeaSJoseph Huber } 151615b7eeaSJoseph Huber break; 152615b7eeaSJoseph Huber case Triple::IOS: 153615b7eeaSJoseph Huber if (TT.isOSVersionLT(7, 0)) { 154615b7eeaSJoseph Huber setLibcallName(RTLIB::EXP10_F32, nullptr); 155615b7eeaSJoseph Huber setLibcallName(RTLIB::EXP10_F64, nullptr); 156615b7eeaSJoseph Huber break; 157615b7eeaSJoseph Huber } 158615b7eeaSJoseph Huber [[fallthrough]]; 1597b99b1d4SFlorian Hahn case Triple::DriverKit: 160615b7eeaSJoseph Huber case Triple::TvOS: 161615b7eeaSJoseph Huber case Triple::WatchOS: 162615b7eeaSJoseph Huber case Triple::XROS: 163615b7eeaSJoseph Huber setLibcallName(RTLIB::EXP10_F32, "__exp10f"); 164615b7eeaSJoseph Huber setLibcallName(RTLIB::EXP10_F64, "__exp10"); 165615b7eeaSJoseph Huber break; 166615b7eeaSJoseph Huber default: 167615b7eeaSJoseph Huber break; 168615b7eeaSJoseph Huber } 1697b99b1d4SFlorian Hahn } else if (TT.getOS() == Triple::BridgeOS) { 1707b99b1d4SFlorian Hahn // TODO: BridgeOS should be included in isOSDarwin. 1717b99b1d4SFlorian Hahn setLibcallName(RTLIB::EXP10_F32, "__exp10f"); 1727b99b1d4SFlorian Hahn setLibcallName(RTLIB::EXP10_F64, "__exp10"); 173615b7eeaSJoseph Huber } else { 174615b7eeaSJoseph Huber setLibcallName(RTLIB::FPEXT_F16_F32, "__gnu_h2f_ieee"); 175615b7eeaSJoseph Huber setLibcallName(RTLIB::FPROUND_F32_F16, "__gnu_f2h_ieee"); 176615b7eeaSJoseph Huber } 177615b7eeaSJoseph Huber 178615b7eeaSJoseph Huber if (TT.isGNUEnvironment() || TT.isOSFuchsia() || 179615b7eeaSJoseph Huber (TT.isAndroid() && !TT.isAndroidVersionLT(9))) { 180615b7eeaSJoseph Huber setLibcallName(RTLIB::SINCOS_F32, "sincosf"); 181615b7eeaSJoseph Huber setLibcallName(RTLIB::SINCOS_F64, "sincos"); 182615b7eeaSJoseph Huber setLibcallName(RTLIB::SINCOS_F80, "sincosl"); 183615b7eeaSJoseph Huber setLibcallName(RTLIB::SINCOS_F128, "sincosl"); 184615b7eeaSJoseph Huber setLibcallName(RTLIB::SINCOS_PPCF128, "sincosl"); 185615b7eeaSJoseph Huber } 186615b7eeaSJoseph Huber 187615b7eeaSJoseph Huber if (TT.isPS()) { 188615b7eeaSJoseph Huber setLibcallName(RTLIB::SINCOS_F32, "sincosf"); 189615b7eeaSJoseph Huber setLibcallName(RTLIB::SINCOS_F64, "sincos"); 190615b7eeaSJoseph Huber } 191615b7eeaSJoseph Huber 192615b7eeaSJoseph Huber if (TT.isOSOpenBSD()) { 193615b7eeaSJoseph Huber setLibcallName(RTLIB::STACKPROTECTOR_CHECK_FAIL, nullptr); 194615b7eeaSJoseph Huber } 195615b7eeaSJoseph Huber 196615b7eeaSJoseph Huber if (TT.isOSWindows() && !TT.isOSCygMing()) { 197615b7eeaSJoseph Huber setLibcallName(RTLIB::LDEXP_F32, nullptr); 198615b7eeaSJoseph Huber setLibcallName(RTLIB::LDEXP_F80, nullptr); 199615b7eeaSJoseph Huber setLibcallName(RTLIB::LDEXP_F128, nullptr); 200615b7eeaSJoseph Huber setLibcallName(RTLIB::LDEXP_PPCF128, nullptr); 201615b7eeaSJoseph Huber 202615b7eeaSJoseph Huber setLibcallName(RTLIB::FREXP_F32, nullptr); 203615b7eeaSJoseph Huber setLibcallName(RTLIB::FREXP_F80, nullptr); 204615b7eeaSJoseph Huber setLibcallName(RTLIB::FREXP_F128, nullptr); 205615b7eeaSJoseph Huber setLibcallName(RTLIB::FREXP_PPCF128, nullptr); 206615b7eeaSJoseph Huber } 207615b7eeaSJoseph Huber 208615b7eeaSJoseph Huber // Disable most libcalls on AMDGPU. 209615b7eeaSJoseph Huber if (TT.isAMDGPU()) { 210615b7eeaSJoseph Huber for (int I = 0; I < RTLIB::UNKNOWN_LIBCALL; ++I) { 211615b7eeaSJoseph Huber if (I < RTLIB::ATOMIC_LOAD || I > RTLIB::ATOMIC_FETCH_NAND_16) 212615b7eeaSJoseph Huber setLibcallName(static_cast<RTLIB::Libcall>(I), nullptr); 213615b7eeaSJoseph Huber } 214615b7eeaSJoseph Huber } 215615b7eeaSJoseph Huber 216615b7eeaSJoseph Huber // Disable most libcalls on NVPTX. 217615b7eeaSJoseph Huber if (TT.isNVPTX()) { 218615b7eeaSJoseph Huber for (int I = 0; I < RTLIB::UNKNOWN_LIBCALL; ++I) 219615b7eeaSJoseph Huber if (I < RTLIB::ATOMIC_LOAD || I > RTLIB::ATOMIC_FETCH_NAND_16) 220615b7eeaSJoseph Huber setLibcallName(static_cast<RTLIB::Libcall>(I), nullptr); 221615b7eeaSJoseph Huber } 222615b7eeaSJoseph Huber 223615b7eeaSJoseph Huber if (TT.isOSMSVCRT()) { 224615b7eeaSJoseph Huber // MSVCRT doesn't have powi; fall back to pow 225615b7eeaSJoseph Huber setLibcallName(RTLIB::POWI_F32, nullptr); 226615b7eeaSJoseph Huber setLibcallName(RTLIB::POWI_F64, nullptr); 227615b7eeaSJoseph Huber } 228615b7eeaSJoseph Huber 229615b7eeaSJoseph Huber if (TT.getArch() == Triple::ArchType::avr) { 230615b7eeaSJoseph Huber // Division rtlib functions (not supported), use divmod functions instead 231615b7eeaSJoseph Huber setLibcallName(RTLIB::SDIV_I8, nullptr); 232615b7eeaSJoseph Huber setLibcallName(RTLIB::SDIV_I16, nullptr); 233615b7eeaSJoseph Huber setLibcallName(RTLIB::SDIV_I32, nullptr); 234615b7eeaSJoseph Huber setLibcallName(RTLIB::UDIV_I8, nullptr); 235615b7eeaSJoseph Huber setLibcallName(RTLIB::UDIV_I16, nullptr); 236615b7eeaSJoseph Huber setLibcallName(RTLIB::UDIV_I32, nullptr); 237615b7eeaSJoseph Huber 238615b7eeaSJoseph Huber // Modulus rtlib functions (not supported), use divmod functions instead 239615b7eeaSJoseph Huber setLibcallName(RTLIB::SREM_I8, nullptr); 240615b7eeaSJoseph Huber setLibcallName(RTLIB::SREM_I16, nullptr); 241615b7eeaSJoseph Huber setLibcallName(RTLIB::SREM_I32, nullptr); 242615b7eeaSJoseph Huber setLibcallName(RTLIB::UREM_I8, nullptr); 243615b7eeaSJoseph Huber setLibcallName(RTLIB::UREM_I16, nullptr); 244615b7eeaSJoseph Huber setLibcallName(RTLIB::UREM_I32, nullptr); 245615b7eeaSJoseph Huber } 246615b7eeaSJoseph Huber 247*dad9e4a1SNikita Popov if (!TT.isWasm()) { 248*dad9e4a1SNikita Popov // These libcalls are only available in compiler-rt, not libgcc. 249*dad9e4a1SNikita Popov if (TT.isArch32Bit()) { 250615b7eeaSJoseph Huber setLibcallName(RTLIB::SHL_I128, nullptr); 251615b7eeaSJoseph Huber setLibcallName(RTLIB::SRL_I128, nullptr); 252615b7eeaSJoseph Huber setLibcallName(RTLIB::SRA_I128, nullptr); 253615b7eeaSJoseph Huber setLibcallName(RTLIB::MUL_I128, nullptr); 254615b7eeaSJoseph Huber setLibcallName(RTLIB::MULO_I64, nullptr); 255615b7eeaSJoseph Huber } 256615b7eeaSJoseph Huber setLibcallName(RTLIB::MULO_I128, nullptr); 257615b7eeaSJoseph Huber } 258615b7eeaSJoseph Huber } 259