10b57cec5SDimitry Andric //===-- TargetLibraryInfo.cpp - Runtime library information ----------------==//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file implements the TargetLibraryInfo class.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "llvm/Analysis/TargetLibraryInfo.h"
14c9157d92SDimitry Andric #include "llvm/ADT/DenseMap.h"
15c9157d92SDimitry Andric #include "llvm/ADT/SmallString.h"
160b57cec5SDimitry Andric #include "llvm/IR/Constants.h"
17480093f4SDimitry Andric #include "llvm/InitializePasses.h"
180b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h"
19fe013be4SDimitry Andric #include "llvm/TargetParser/Triple.h"
200b57cec5SDimitry Andric using namespace llvm;
210b57cec5SDimitry Andric 
220b57cec5SDimitry Andric static cl::opt<TargetLibraryInfoImpl::VectorLibrary> ClVectorLibrary(
230b57cec5SDimitry Andric     "vector-library", cl::Hidden, cl::desc("Vector functions library"),
240b57cec5SDimitry Andric     cl::init(TargetLibraryInfoImpl::NoLibrary),
250b57cec5SDimitry Andric     cl::values(clEnumValN(TargetLibraryInfoImpl::NoLibrary, "none",
260b57cec5SDimitry Andric                           "No vector functions library"),
270b57cec5SDimitry Andric                clEnumValN(TargetLibraryInfoImpl::Accelerate, "Accelerate",
280b57cec5SDimitry Andric                           "Accelerate framework"),
29fe6060f1SDimitry Andric                clEnumValN(TargetLibraryInfoImpl::DarwinLibSystemM,
30fe6060f1SDimitry Andric                           "Darwin_libsystem_m", "Darwin libsystem_m"),
31e8d8bef9SDimitry Andric                clEnumValN(TargetLibraryInfoImpl::LIBMVEC_X86, "LIBMVEC-X86",
32e8d8bef9SDimitry Andric                           "GLIBC Vector Math library"),
330b57cec5SDimitry Andric                clEnumValN(TargetLibraryInfoImpl::MASSV, "MASSV",
340b57cec5SDimitry Andric                           "IBM MASS vector library"),
350b57cec5SDimitry Andric                clEnumValN(TargetLibraryInfoImpl::SVML, "SVML",
36bdd1243dSDimitry Andric                           "Intel SVML library"),
37bdd1243dSDimitry Andric                clEnumValN(TargetLibraryInfoImpl::SLEEFGNUABI, "sleefgnuabi",
38fe013be4SDimitry Andric                           "SIMD Library for Evaluating Elementary Functions"),
39fe013be4SDimitry Andric                clEnumValN(TargetLibraryInfoImpl::ArmPL, "ArmPL",
40fe013be4SDimitry Andric                           "Arm Performance Libraries")));
410b57cec5SDimitry Andric 
428bcb0991SDimitry Andric StringLiteral const TargetLibraryInfoImpl::StandardNames[LibFunc::NumLibFuncs] =
438bcb0991SDimitry Andric     {
440b57cec5SDimitry Andric #define TLI_DEFINE_STRING
450b57cec5SDimitry Andric #include "llvm/Analysis/TargetLibraryInfo.def"
460b57cec5SDimitry Andric };
470b57cec5SDimitry Andric 
getVectorFunctionABIVariantString() const48c9157d92SDimitry Andric std::string VecDesc::getVectorFunctionABIVariantString() const {
49c9157d92SDimitry Andric   assert(!VectorFnName.empty() && "Vector function name must not be empty.");
50c9157d92SDimitry Andric   SmallString<256> Buffer;
51c9157d92SDimitry Andric   llvm::raw_svector_ostream Out(Buffer);
52c9157d92SDimitry Andric   Out << VABIPrefix << "_" << ScalarFnName << "(" << VectorFnName << ")";
53c9157d92SDimitry Andric   return std::string(Out.str());
54c9157d92SDimitry Andric }
55c9157d92SDimitry Andric 
56bdd1243dSDimitry Andric // Recognized types of library function arguments and return types.
57bdd1243dSDimitry Andric enum FuncArgTypeID : char {
58bdd1243dSDimitry Andric   Void = 0, // Must be zero.
59bdd1243dSDimitry Andric   Bool,     // 8 bits on all targets
60bdd1243dSDimitry Andric   Int16,
61bdd1243dSDimitry Andric   Int32,
62bdd1243dSDimitry Andric   Int,
63bdd1243dSDimitry Andric   IntPlus, // Int or bigger.
64bdd1243dSDimitry Andric   Long,    // Either 32 or 64 bits.
65bdd1243dSDimitry Andric   IntX,    // Any integer type.
66bdd1243dSDimitry Andric   Int64,
67bdd1243dSDimitry Andric   LLong,    // 64 bits on all targets.
68bdd1243dSDimitry Andric   SizeT,    // size_t.
69bdd1243dSDimitry Andric   SSizeT,   // POSIX ssize_t.
70bdd1243dSDimitry Andric   Flt,      // IEEE float.
71bdd1243dSDimitry Andric   Dbl,      // IEEE double.
72bdd1243dSDimitry Andric   LDbl,     // Any floating type (TODO: tighten this up).
73bdd1243dSDimitry Andric   Floating, // Any floating type.
74bdd1243dSDimitry Andric   Ptr,      // Any pointer type.
75bdd1243dSDimitry Andric   Struct,   // Any struct type.
76bdd1243dSDimitry Andric   Ellip,    // The ellipsis (...).
77bdd1243dSDimitry Andric   Same,     // Same argument type as the previous one.
78bdd1243dSDimitry Andric };
79bdd1243dSDimitry Andric 
80bdd1243dSDimitry Andric typedef std::array<FuncArgTypeID, 8> FuncProtoTy;
81bdd1243dSDimitry Andric 
82bdd1243dSDimitry Andric static const FuncProtoTy Signatures[] = {
83bdd1243dSDimitry Andric #define TLI_DEFINE_SIG
84bdd1243dSDimitry Andric #include "llvm/Analysis/TargetLibraryInfo.def"
85bdd1243dSDimitry Andric };
86bdd1243dSDimitry Andric 
87bdd1243dSDimitry Andric static_assert(sizeof Signatures / sizeof *Signatures == LibFunc::NumLibFuncs,
88bdd1243dSDimitry Andric               "Missing library function signatures");
89bdd1243dSDimitry Andric 
hasSinCosPiStret(const Triple & T)900b57cec5SDimitry Andric static bool hasSinCosPiStret(const Triple &T) {
910b57cec5SDimitry Andric   // Only Darwin variants have _stret versions of combined trig functions.
920b57cec5SDimitry Andric   if (!T.isOSDarwin())
930b57cec5SDimitry Andric     return false;
940b57cec5SDimitry Andric 
950b57cec5SDimitry Andric   // The ABI is rather complicated on x86, so don't do anything special there.
960b57cec5SDimitry Andric   if (T.getArch() == Triple::x86)
970b57cec5SDimitry Andric     return false;
980b57cec5SDimitry Andric 
990b57cec5SDimitry Andric   if (T.isMacOSX() && T.isMacOSXVersionLT(10, 9))
1000b57cec5SDimitry Andric     return false;
1010b57cec5SDimitry Andric 
1020b57cec5SDimitry Andric   if (T.isiOS() && T.isOSVersionLT(7, 0))
1030b57cec5SDimitry Andric     return false;
1040b57cec5SDimitry Andric 
1050b57cec5SDimitry Andric   return true;
1060b57cec5SDimitry Andric }
1070b57cec5SDimitry Andric 
hasBcmp(const Triple & TT)1080b57cec5SDimitry Andric static bool hasBcmp(const Triple &TT) {
1090b57cec5SDimitry Andric   // Posix removed support from bcmp() in 2001, but the glibc and several
1100b57cec5SDimitry Andric   // implementations of the libc still have it.
1110b57cec5SDimitry Andric   if (TT.isOSLinux())
1120b57cec5SDimitry Andric     return TT.isGNUEnvironment() || TT.isMusl();
1130b57cec5SDimitry Andric   // Both NetBSD and OpenBSD are planning to remove the function. Windows does
1140b57cec5SDimitry Andric   // not have it.
1158bcb0991SDimitry Andric   return TT.isOSFreeBSD() || TT.isOSSolaris();
1160b57cec5SDimitry Andric }
1170b57cec5SDimitry Andric 
isCallingConvCCompatible(CallingConv::ID CC,StringRef TT,FunctionType * FuncTy)118fe6060f1SDimitry Andric static bool isCallingConvCCompatible(CallingConv::ID CC, StringRef TT,
119fe6060f1SDimitry Andric                                      FunctionType *FuncTy) {
120fe6060f1SDimitry Andric   switch (CC) {
121fe6060f1SDimitry Andric   default:
122fe6060f1SDimitry Andric     return false;
123fe6060f1SDimitry Andric   case llvm::CallingConv::C:
124fe6060f1SDimitry Andric     return true;
125fe6060f1SDimitry Andric   case llvm::CallingConv::ARM_APCS:
126fe6060f1SDimitry Andric   case llvm::CallingConv::ARM_AAPCS:
127fe6060f1SDimitry Andric   case llvm::CallingConv::ARM_AAPCS_VFP: {
128fe6060f1SDimitry Andric 
129fe6060f1SDimitry Andric     // The iOS ABI diverges from the standard in some cases, so for now don't
130fe6060f1SDimitry Andric     // try to simplify those calls.
131fe6060f1SDimitry Andric     if (Triple(TT).isiOS())
132fe6060f1SDimitry Andric       return false;
133fe6060f1SDimitry Andric 
134fe6060f1SDimitry Andric     if (!FuncTy->getReturnType()->isPointerTy() &&
135fe6060f1SDimitry Andric         !FuncTy->getReturnType()->isIntegerTy() &&
136fe6060f1SDimitry Andric         !FuncTy->getReturnType()->isVoidTy())
137fe6060f1SDimitry Andric       return false;
138fe6060f1SDimitry Andric 
139fe6060f1SDimitry Andric     for (auto *Param : FuncTy->params()) {
140fe6060f1SDimitry Andric       if (!Param->isPointerTy() && !Param->isIntegerTy())
141fe6060f1SDimitry Andric         return false;
142fe6060f1SDimitry Andric     }
143fe6060f1SDimitry Andric     return true;
144fe6060f1SDimitry Andric   }
145fe6060f1SDimitry Andric   }
146fe6060f1SDimitry Andric   return false;
147fe6060f1SDimitry Andric }
148fe6060f1SDimitry Andric 
isCallingConvCCompatible(CallBase * CI)149fe6060f1SDimitry Andric bool TargetLibraryInfoImpl::isCallingConvCCompatible(CallBase *CI) {
150fe6060f1SDimitry Andric   return ::isCallingConvCCompatible(CI->getCallingConv(),
151fe6060f1SDimitry Andric                                     CI->getModule()->getTargetTriple(),
152fe6060f1SDimitry Andric                                     CI->getFunctionType());
153fe6060f1SDimitry Andric }
154fe6060f1SDimitry Andric 
isCallingConvCCompatible(Function * F)155fe6060f1SDimitry Andric bool TargetLibraryInfoImpl::isCallingConvCCompatible(Function *F) {
156fe6060f1SDimitry Andric   return ::isCallingConvCCompatible(F->getCallingConv(),
157fe6060f1SDimitry Andric                                     F->getParent()->getTargetTriple(),
158fe6060f1SDimitry Andric                                     F->getFunctionType());
159fe6060f1SDimitry Andric }
160fe6060f1SDimitry Andric 
1610b57cec5SDimitry Andric /// Initialize the set of available library functions based on the specified
1620b57cec5SDimitry Andric /// target triple. This should be carefully written so that a missing target
1630b57cec5SDimitry Andric /// triple gets a sane set of defaults.
initialize(TargetLibraryInfoImpl & TLI,const Triple & T,ArrayRef<StringLiteral> StandardNames)1640b57cec5SDimitry Andric static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T,
1658bcb0991SDimitry Andric                        ArrayRef<StringLiteral> StandardNames) {
1660b57cec5SDimitry Andric   // Set IO unlocked variants as unavailable
1670b57cec5SDimitry Andric   // Set them as available per system below
168349cc55cSDimitry Andric   TLI.setUnavailable(LibFunc_getc_unlocked);
1690b57cec5SDimitry Andric   TLI.setUnavailable(LibFunc_getchar_unlocked);
1700b57cec5SDimitry Andric   TLI.setUnavailable(LibFunc_putc_unlocked);
1710b57cec5SDimitry Andric   TLI.setUnavailable(LibFunc_putchar_unlocked);
1720b57cec5SDimitry Andric   TLI.setUnavailable(LibFunc_fputc_unlocked);
1730b57cec5SDimitry Andric   TLI.setUnavailable(LibFunc_fgetc_unlocked);
1740b57cec5SDimitry Andric   TLI.setUnavailable(LibFunc_fread_unlocked);
1750b57cec5SDimitry Andric   TLI.setUnavailable(LibFunc_fwrite_unlocked);
1760b57cec5SDimitry Andric   TLI.setUnavailable(LibFunc_fputs_unlocked);
1770b57cec5SDimitry Andric   TLI.setUnavailable(LibFunc_fgets_unlocked);
1780b57cec5SDimitry Andric 
179bdd1243dSDimitry Andric   bool ShouldExtI32Param, ShouldExtI32Return;
180bdd1243dSDimitry Andric   bool ShouldSignExtI32Param, ShouldSignExtI32Return;
181bdd1243dSDimitry Andric   TargetLibraryInfo::initExtensionsForTriple(ShouldExtI32Param,
182bdd1243dSDimitry Andric        ShouldExtI32Return, ShouldSignExtI32Param, ShouldSignExtI32Return, T);
1830b57cec5SDimitry Andric   TLI.setShouldExtI32Param(ShouldExtI32Param);
1840b57cec5SDimitry Andric   TLI.setShouldExtI32Return(ShouldExtI32Return);
1850b57cec5SDimitry Andric   TLI.setShouldSignExtI32Param(ShouldSignExtI32Param);
186bdd1243dSDimitry Andric   TLI.setShouldSignExtI32Return(ShouldSignExtI32Return);
1870b57cec5SDimitry Andric 
188fe6060f1SDimitry Andric   // Let's assume by default that the size of int is 32 bits, unless the target
189fe6060f1SDimitry Andric   // is a 16-bit architecture because then it most likely is 16 bits. If that
190fe6060f1SDimitry Andric   // isn't true for a target those defaults should be overridden below.
191fe6060f1SDimitry Andric   TLI.setIntSize(T.isArch16Bit() ? 16 : 32);
192fe6060f1SDimitry Andric 
193349cc55cSDimitry Andric   // There is really no runtime library on AMDGPU, apart from
194349cc55cSDimitry Andric   // __kmpc_alloc/free_shared.
1955ffd83dbSDimitry Andric   if (T.isAMDGPU()) {
196349cc55cSDimitry Andric     TLI.disableAllFunctions();
197fe6060f1SDimitry Andric     TLI.setAvailable(llvm::LibFunc___kmpc_alloc_shared);
198fe6060f1SDimitry Andric     TLI.setAvailable(llvm::LibFunc___kmpc_free_shared);
1990b57cec5SDimitry Andric     return;
2000b57cec5SDimitry Andric   }
2010b57cec5SDimitry Andric 
2024824e7fdSDimitry Andric   // memset_pattern{4,8,16} is only available on iOS 3.0 and Mac OS X 10.5 and
2034824e7fdSDimitry Andric   // later. All versions of watchOS support it.
2040b57cec5SDimitry Andric   if (T.isMacOSX()) {
2050b57cec5SDimitry Andric     // available IO unlocked variants on Mac OS X
2060b57cec5SDimitry Andric     TLI.setAvailable(LibFunc_getc_unlocked);
2070b57cec5SDimitry Andric     TLI.setAvailable(LibFunc_getchar_unlocked);
2080b57cec5SDimitry Andric     TLI.setAvailable(LibFunc_putc_unlocked);
2090b57cec5SDimitry Andric     TLI.setAvailable(LibFunc_putchar_unlocked);
210c9157d92SDimitry Andric     TLI.setUnavailable(LibFunc_memrchr);
2110b57cec5SDimitry Andric 
2124824e7fdSDimitry Andric     if (T.isMacOSXVersionLT(10, 5)) {
2134824e7fdSDimitry Andric       TLI.setUnavailable(LibFunc_memset_pattern4);
2144824e7fdSDimitry Andric       TLI.setUnavailable(LibFunc_memset_pattern8);
2150b57cec5SDimitry Andric       TLI.setUnavailable(LibFunc_memset_pattern16);
2164824e7fdSDimitry Andric     }
2170b57cec5SDimitry Andric   } else if (T.isiOS()) {
2184824e7fdSDimitry Andric     if (T.isOSVersionLT(3, 0)) {
2194824e7fdSDimitry Andric       TLI.setUnavailable(LibFunc_memset_pattern4);
2204824e7fdSDimitry Andric       TLI.setUnavailable(LibFunc_memset_pattern8);
2210b57cec5SDimitry Andric       TLI.setUnavailable(LibFunc_memset_pattern16);
2224824e7fdSDimitry Andric     }
2230b57cec5SDimitry Andric   } else if (!T.isWatchOS()) {
2244824e7fdSDimitry Andric     TLI.setUnavailable(LibFunc_memset_pattern4);
2254824e7fdSDimitry Andric     TLI.setUnavailable(LibFunc_memset_pattern8);
2260b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_memset_pattern16);
2270b57cec5SDimitry Andric   }
2280b57cec5SDimitry Andric 
2290b57cec5SDimitry Andric   if (!hasSinCosPiStret(T)) {
2300b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_sinpi);
2310b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_sinpif);
2320b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_cospi);
2330b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_cospif);
2340b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_sincospi_stret);
2350b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_sincospif_stret);
2360b57cec5SDimitry Andric   }
2370b57cec5SDimitry Andric 
2380b57cec5SDimitry Andric   if (!hasBcmp(T))
2390b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_bcmp);
2400b57cec5SDimitry Andric 
2410b57cec5SDimitry Andric   if (T.isMacOSX() && T.getArch() == Triple::x86 &&
2420b57cec5SDimitry Andric       !T.isMacOSXVersionLT(10, 7)) {
2430b57cec5SDimitry Andric     // x86-32 OSX has a scheme where fwrite and fputs (and some other functions
2440b57cec5SDimitry Andric     // we don't care about) have two versions; on recent OSX, the one we want
2450b57cec5SDimitry Andric     // has a $UNIX2003 suffix. The two implementations are identical except
2460b57cec5SDimitry Andric     // for the return value in some edge cases.  However, we don't want to
2470b57cec5SDimitry Andric     // generate code that depends on the old symbols.
2480b57cec5SDimitry Andric     TLI.setAvailableWithName(LibFunc_fwrite, "fwrite$UNIX2003");
2490b57cec5SDimitry Andric     TLI.setAvailableWithName(LibFunc_fputs, "fputs$UNIX2003");
2500b57cec5SDimitry Andric   }
2510b57cec5SDimitry Andric 
2520b57cec5SDimitry Andric   // iprintf and friends are only available on XCore, TCE, and Emscripten.
2530b57cec5SDimitry Andric   if (T.getArch() != Triple::xcore && T.getArch() != Triple::tce &&
2540b57cec5SDimitry Andric       T.getOS() != Triple::Emscripten) {
2550b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_iprintf);
2560b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_siprintf);
2570b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_fiprintf);
2580b57cec5SDimitry Andric   }
2590b57cec5SDimitry Andric 
2600b57cec5SDimitry Andric   // __small_printf and friends are only available on Emscripten.
2610b57cec5SDimitry Andric   if (T.getOS() != Triple::Emscripten) {
2620b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_small_printf);
2630b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_small_sprintf);
2640b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_small_fprintf);
2650b57cec5SDimitry Andric   }
2660b57cec5SDimitry Andric 
2670b57cec5SDimitry Andric   if (T.isOSWindows() && !T.isOSCygMing()) {
2680b57cec5SDimitry Andric     // XXX: The earliest documentation available at the moment is for VS2015/VC19:
2690b57cec5SDimitry Andric     // https://docs.microsoft.com/en-us/cpp/c-runtime-library/floating-point-support?view=vs-2015
2700b57cec5SDimitry Andric     // XXX: In order to use an MSVCRT older than VC19,
2710b57cec5SDimitry Andric     // the specific library version must be explicit in the target triple,
2720b57cec5SDimitry Andric     // e.g., x86_64-pc-windows-msvc18.
2730b57cec5SDimitry Andric     bool hasPartialC99 = true;
2740b57cec5SDimitry Andric     if (T.isKnownWindowsMSVCEnvironment()) {
2750eae32dcSDimitry Andric       VersionTuple Version = T.getEnvironmentVersion();
2760eae32dcSDimitry Andric       hasPartialC99 = (Version.getMajor() == 0 || Version.getMajor() >= 19);
2770b57cec5SDimitry Andric     }
2780b57cec5SDimitry Andric 
2790b57cec5SDimitry Andric     // Latest targets support C89 math functions, in part.
2800b57cec5SDimitry Andric     bool isARM = (T.getArch() == Triple::aarch64 ||
2810b57cec5SDimitry Andric                   T.getArch() == Triple::arm);
2820b57cec5SDimitry Andric     bool hasPartialFloat = (isARM ||
2830b57cec5SDimitry Andric                             T.getArch() == Triple::x86_64);
2840b57cec5SDimitry Andric 
2850b57cec5SDimitry Andric     // Win32 does not support float C89 math functions, in general.
2860b57cec5SDimitry Andric     if (!hasPartialFloat) {
2870b57cec5SDimitry Andric       TLI.setUnavailable(LibFunc_acosf);
2880b57cec5SDimitry Andric       TLI.setUnavailable(LibFunc_asinf);
2890b57cec5SDimitry Andric       TLI.setUnavailable(LibFunc_atan2f);
2900b57cec5SDimitry Andric       TLI.setUnavailable(LibFunc_atanf);
2910b57cec5SDimitry Andric       TLI.setUnavailable(LibFunc_ceilf);
2920b57cec5SDimitry Andric       TLI.setUnavailable(LibFunc_cosf);
2930b57cec5SDimitry Andric       TLI.setUnavailable(LibFunc_coshf);
2940b57cec5SDimitry Andric       TLI.setUnavailable(LibFunc_expf);
2950b57cec5SDimitry Andric       TLI.setUnavailable(LibFunc_floorf);
2960b57cec5SDimitry Andric       TLI.setUnavailable(LibFunc_fmodf);
2970b57cec5SDimitry Andric       TLI.setUnavailable(LibFunc_log10f);
2980b57cec5SDimitry Andric       TLI.setUnavailable(LibFunc_logf);
2990b57cec5SDimitry Andric       TLI.setUnavailable(LibFunc_modff);
3000b57cec5SDimitry Andric       TLI.setUnavailable(LibFunc_powf);
3015ffd83dbSDimitry Andric       TLI.setUnavailable(LibFunc_remainderf);
3020b57cec5SDimitry Andric       TLI.setUnavailable(LibFunc_sinf);
3030b57cec5SDimitry Andric       TLI.setUnavailable(LibFunc_sinhf);
3040b57cec5SDimitry Andric       TLI.setUnavailable(LibFunc_sqrtf);
3050b57cec5SDimitry Andric       TLI.setUnavailable(LibFunc_tanf);
3060b57cec5SDimitry Andric       TLI.setUnavailable(LibFunc_tanhf);
3070b57cec5SDimitry Andric     }
3080b57cec5SDimitry Andric     if (!isARM)
3090b57cec5SDimitry Andric       TLI.setUnavailable(LibFunc_fabsf);
3100b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_frexpf);
3110b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_ldexpf);
3120b57cec5SDimitry Andric 
3130b57cec5SDimitry Andric     // Win32 does not support long double C89 math functions.
3140b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_acosl);
3150b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_asinl);
3160b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_atan2l);
3170b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_atanl);
3180b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_ceill);
3190b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_cosl);
3200b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_coshl);
3210b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_expl);
3220b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_fabsl);
3230b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_floorl);
3240b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_fmodl);
3250b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_frexpl);
3260b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_ldexpl);
3270b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_log10l);
3280b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_logl);
3290b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_modfl);
3300b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_powl);
3315ffd83dbSDimitry Andric     TLI.setUnavailable(LibFunc_remainderl);
3320b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_sinl);
3330b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_sinhl);
3340b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_sqrtl);
3350b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_tanl);
3360b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_tanhl);
3370b57cec5SDimitry Andric 
3380b57cec5SDimitry Andric     // Win32 does not fully support C99 math functions.
3390b57cec5SDimitry Andric     if (!hasPartialC99) {
3400b57cec5SDimitry Andric       TLI.setUnavailable(LibFunc_acosh);
3410b57cec5SDimitry Andric       TLI.setUnavailable(LibFunc_acoshf);
3420b57cec5SDimitry Andric       TLI.setUnavailable(LibFunc_asinh);
3430b57cec5SDimitry Andric       TLI.setUnavailable(LibFunc_asinhf);
3440b57cec5SDimitry Andric       TLI.setUnavailable(LibFunc_atanh);
3450b57cec5SDimitry Andric       TLI.setUnavailable(LibFunc_atanhf);
3460b57cec5SDimitry Andric       TLI.setAvailableWithName(LibFunc_cabs, "_cabs");
3470b57cec5SDimitry Andric       TLI.setUnavailable(LibFunc_cabsf);
3480b57cec5SDimitry Andric       TLI.setUnavailable(LibFunc_cbrt);
3490b57cec5SDimitry Andric       TLI.setUnavailable(LibFunc_cbrtf);
3500b57cec5SDimitry Andric       TLI.setAvailableWithName(LibFunc_copysign, "_copysign");
3510b57cec5SDimitry Andric       TLI.setAvailableWithName(LibFunc_copysignf, "_copysignf");
3520b57cec5SDimitry Andric       TLI.setUnavailable(LibFunc_exp2);
3530b57cec5SDimitry Andric       TLI.setUnavailable(LibFunc_exp2f);
3540b57cec5SDimitry Andric       TLI.setUnavailable(LibFunc_expm1);
3550b57cec5SDimitry Andric       TLI.setUnavailable(LibFunc_expm1f);
3560b57cec5SDimitry Andric       TLI.setUnavailable(LibFunc_fmax);
3570b57cec5SDimitry Andric       TLI.setUnavailable(LibFunc_fmaxf);
3580b57cec5SDimitry Andric       TLI.setUnavailable(LibFunc_fmin);
3590b57cec5SDimitry Andric       TLI.setUnavailable(LibFunc_fminf);
3600b57cec5SDimitry Andric       TLI.setUnavailable(LibFunc_log1p);
3610b57cec5SDimitry Andric       TLI.setUnavailable(LibFunc_log1pf);
3620b57cec5SDimitry Andric       TLI.setUnavailable(LibFunc_log2);
3630b57cec5SDimitry Andric       TLI.setUnavailable(LibFunc_log2f);
3640b57cec5SDimitry Andric       TLI.setAvailableWithName(LibFunc_logb, "_logb");
3650b57cec5SDimitry Andric       if (hasPartialFloat)
3660b57cec5SDimitry Andric         TLI.setAvailableWithName(LibFunc_logbf, "_logbf");
3670b57cec5SDimitry Andric       else
3680b57cec5SDimitry Andric         TLI.setUnavailable(LibFunc_logbf);
3690b57cec5SDimitry Andric       TLI.setUnavailable(LibFunc_rint);
3700b57cec5SDimitry Andric       TLI.setUnavailable(LibFunc_rintf);
3710b57cec5SDimitry Andric       TLI.setUnavailable(LibFunc_round);
3720b57cec5SDimitry Andric       TLI.setUnavailable(LibFunc_roundf);
3730b57cec5SDimitry Andric       TLI.setUnavailable(LibFunc_trunc);
3740b57cec5SDimitry Andric       TLI.setUnavailable(LibFunc_truncf);
3750b57cec5SDimitry Andric     }
3760b57cec5SDimitry Andric 
3770b57cec5SDimitry Andric     // Win32 does not support long double C99 math functions.
3780b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_acoshl);
3790b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_asinhl);
3800b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_atanhl);
3810b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_cabsl);
3820b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_cbrtl);
3830b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_copysignl);
3840b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_exp2l);
3850b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_expm1l);
3860b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_fmaxl);
3870b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_fminl);
3880b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_log1pl);
3890b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_log2l);
3900b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_logbl);
3910b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_nearbyintl);
3920b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_rintl);
3930b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_roundl);
3940b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_truncl);
3950b57cec5SDimitry Andric 
3960b57cec5SDimitry Andric     // Win32 does not support these functions, but
3970b57cec5SDimitry Andric     // they are generally available on POSIX-compliant systems.
3980b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_access);
399fe6060f1SDimitry Andric     TLI.setUnavailable(LibFunc_chmod);
400fe6060f1SDimitry Andric     TLI.setUnavailable(LibFunc_closedir);
401fe6060f1SDimitry Andric     TLI.setUnavailable(LibFunc_fdopen);
402fe6060f1SDimitry Andric     TLI.setUnavailable(LibFunc_fileno);
403fe6060f1SDimitry Andric     TLI.setUnavailable(LibFunc_fseeko);
404fe6060f1SDimitry Andric     TLI.setUnavailable(LibFunc_fstat);
405fe6060f1SDimitry Andric     TLI.setUnavailable(LibFunc_ftello);
406fe6060f1SDimitry Andric     TLI.setUnavailable(LibFunc_gettimeofday);
407fe6060f1SDimitry Andric     TLI.setUnavailable(LibFunc_memccpy);
408fe6060f1SDimitry Andric     TLI.setUnavailable(LibFunc_mkdir);
409fe6060f1SDimitry Andric     TLI.setUnavailable(LibFunc_open);
410fe6060f1SDimitry Andric     TLI.setUnavailable(LibFunc_opendir);
411fe6060f1SDimitry Andric     TLI.setUnavailable(LibFunc_pclose);
412fe6060f1SDimitry Andric     TLI.setUnavailable(LibFunc_popen);
413fe6060f1SDimitry Andric     TLI.setUnavailable(LibFunc_read);
414fe6060f1SDimitry Andric     TLI.setUnavailable(LibFunc_rmdir);
415fe6060f1SDimitry Andric     TLI.setUnavailable(LibFunc_stat);
416fe6060f1SDimitry Andric     TLI.setUnavailable(LibFunc_strcasecmp);
417fe6060f1SDimitry Andric     TLI.setUnavailable(LibFunc_strncasecmp);
418fe6060f1SDimitry Andric     TLI.setUnavailable(LibFunc_unlink);
419fe6060f1SDimitry Andric     TLI.setUnavailable(LibFunc_utime);
420fe6060f1SDimitry Andric     TLI.setUnavailable(LibFunc_write);
421fe6060f1SDimitry Andric   }
422fe6060f1SDimitry Andric 
423fe6060f1SDimitry Andric   if (T.isOSWindows() && !T.isWindowsCygwinEnvironment()) {
424fe6060f1SDimitry Andric     // These functions aren't available in either MSVC or MinGW environments.
4250b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_bcmp);
4260b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_bcopy);
4270b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_bzero);
4280b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_chown);
4290b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_ctermid);
4300b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_ffs);
4310b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_flockfile);
4320b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_fstatvfs);
4330b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_ftrylockfile);
4340b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_funlockfile);
4350b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_getitimer);
4360b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_getlogin_r);
4370b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_getpwnam);
4380b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_htonl);
4390b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_htons);
4400b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_lchown);
4410b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_lstat);
442bdd1243dSDimitry Andric     TLI.setUnavailable(LibFunc_memrchr);
4430b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_ntohl);
4440b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_ntohs);
4450b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_pread);
4460b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_pwrite);
4470b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_readlink);
4480b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_realpath);
4490b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_setitimer);
4500b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_statvfs);
4510b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_stpcpy);
4520b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_stpncpy);
4530b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_times);
4540b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_uname);
4550b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_unsetenv);
4560b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_utimes);
4570b57cec5SDimitry Andric   }
4580b57cec5SDimitry Andric 
459349cc55cSDimitry Andric   // Pick just one set of new/delete variants.
460349cc55cSDimitry Andric   if (T.isOSMSVCRT()) {
461349cc55cSDimitry Andric     // MSVC, doesn't have the Itanium new/delete.
462349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_ZdaPv);
463349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_ZdaPvRKSt9nothrow_t);
464349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_ZdaPvSt11align_val_t);
465349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_ZdaPvSt11align_val_tRKSt9nothrow_t);
466349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_ZdaPvj);
467349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_ZdaPvjSt11align_val_t);
468349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_ZdaPvm);
469349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_ZdaPvmSt11align_val_t);
470349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_ZdlPv);
471349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_ZdlPvRKSt9nothrow_t);
472349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_ZdlPvSt11align_val_t);
473349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_ZdlPvSt11align_val_tRKSt9nothrow_t);
474349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_ZdlPvj);
475349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_ZdlPvjSt11align_val_t);
476349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_ZdlPvm);
477349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_ZdlPvmSt11align_val_t);
478349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_Znaj);
479349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_ZnajRKSt9nothrow_t);
480349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_ZnajSt11align_val_t);
481349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_ZnajSt11align_val_tRKSt9nothrow_t);
482349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_Znam);
483349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_ZnamRKSt9nothrow_t);
484fe013be4SDimitry Andric     TLI.setUnavailable(LibFunc_ZnamRKSt9nothrow_t12__hot_cold_t);
485349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_ZnamSt11align_val_t);
486349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_ZnamSt11align_val_tRKSt9nothrow_t);
487349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_Znwj);
488349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_ZnwjRKSt9nothrow_t);
489349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_ZnwjSt11align_val_t);
490349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_ZnwjSt11align_val_tRKSt9nothrow_t);
491349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_Znwm);
492349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_ZnwmRKSt9nothrow_t);
493fe013be4SDimitry Andric     TLI.setUnavailable(LibFunc_ZnwmRKSt9nothrow_t12__hot_cold_t);
494349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_ZnwmSt11align_val_t);
495349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_ZnwmSt11align_val_tRKSt9nothrow_t);
496fe013be4SDimitry Andric     TLI.setUnavailable(LibFunc_Znwm12__hot_cold_t);
497fe013be4SDimitry Andric     TLI.setUnavailable(LibFunc_ZnwmSt11align_val_t12__hot_cold_t);
498fe013be4SDimitry Andric     TLI.setUnavailable(LibFunc_ZnwmSt11align_val_tRKSt9nothrow_t12__hot_cold_t);
499fe013be4SDimitry Andric     TLI.setUnavailable(LibFunc_Znam12__hot_cold_t);
500fe013be4SDimitry Andric     TLI.setUnavailable(LibFunc_ZnamSt11align_val_t12__hot_cold_t);
501fe013be4SDimitry Andric     TLI.setUnavailable(LibFunc_ZnamSt11align_val_tRKSt9nothrow_t12__hot_cold_t);
502349cc55cSDimitry Andric   } else {
503349cc55cSDimitry Andric     // Not MSVC, assume it's Itanium.
504349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_msvc_new_int);
505349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_msvc_new_int_nothrow);
506349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_msvc_new_longlong);
507349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_msvc_new_longlong_nothrow);
508349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_msvc_delete_ptr32);
509349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_msvc_delete_ptr32_nothrow);
510349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_msvc_delete_ptr32_int);
511349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_msvc_delete_ptr64);
512349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_msvc_delete_ptr64_nothrow);
513349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_msvc_delete_ptr64_longlong);
514349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_msvc_new_array_int);
515349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_msvc_new_array_int_nothrow);
516349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_msvc_new_array_longlong);
517349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_msvc_new_array_longlong_nothrow);
518349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_msvc_delete_array_ptr32);
519349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_msvc_delete_array_ptr32_nothrow);
520349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_msvc_delete_array_ptr32_int);
521349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_msvc_delete_array_ptr64);
522349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_msvc_delete_array_ptr64_nothrow);
523349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_msvc_delete_array_ptr64_longlong);
524349cc55cSDimitry Andric   }
525349cc55cSDimitry Andric 
5260b57cec5SDimitry Andric   switch (T.getOS()) {
5270b57cec5SDimitry Andric   case Triple::MacOSX:
5280b57cec5SDimitry Andric     // exp10 and exp10f are not available on OS X until 10.9 and iOS until 7.0
5290b57cec5SDimitry Andric     // and their names are __exp10 and __exp10f. exp10l is not available on
5300b57cec5SDimitry Andric     // OS X or iOS.
5310b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_exp10l);
5320b57cec5SDimitry Andric     if (T.isMacOSXVersionLT(10, 9)) {
5330b57cec5SDimitry Andric       TLI.setUnavailable(LibFunc_exp10);
5340b57cec5SDimitry Andric       TLI.setUnavailable(LibFunc_exp10f);
5350b57cec5SDimitry Andric     } else {
5360b57cec5SDimitry Andric       TLI.setAvailableWithName(LibFunc_exp10, "__exp10");
5370b57cec5SDimitry Andric       TLI.setAvailableWithName(LibFunc_exp10f, "__exp10f");
5380b57cec5SDimitry Andric     }
5390b57cec5SDimitry Andric     break;
5400b57cec5SDimitry Andric   case Triple::IOS:
5410b57cec5SDimitry Andric   case Triple::TvOS:
5420b57cec5SDimitry Andric   case Triple::WatchOS:
543*a58f00eaSDimitry Andric   case Triple::XROS:
5440b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_exp10l);
545480093f4SDimitry Andric     if (!T.isWatchOS() &&
546480093f4SDimitry Andric         (T.isOSVersionLT(7, 0) || (T.isOSVersionLT(9, 0) && T.isX86()))) {
5470b57cec5SDimitry Andric       TLI.setUnavailable(LibFunc_exp10);
5480b57cec5SDimitry Andric       TLI.setUnavailable(LibFunc_exp10f);
5490b57cec5SDimitry Andric     } else {
5500b57cec5SDimitry Andric       TLI.setAvailableWithName(LibFunc_exp10, "__exp10");
5510b57cec5SDimitry Andric       TLI.setAvailableWithName(LibFunc_exp10f, "__exp10f");
5520b57cec5SDimitry Andric     }
5530b57cec5SDimitry Andric     break;
5540b57cec5SDimitry Andric   case Triple::Linux:
5550b57cec5SDimitry Andric     // exp10, exp10f, exp10l is available on Linux (GLIBC) but are extremely
5560b57cec5SDimitry Andric     // buggy prior to glibc version 2.18. Until this version is widely deployed
5570b57cec5SDimitry Andric     // or we have a reasonable detection strategy, we cannot use exp10 reliably
5580b57cec5SDimitry Andric     // on Linux.
5590b57cec5SDimitry Andric     //
5600b57cec5SDimitry Andric     // Fall through to disable all of them.
561bdd1243dSDimitry Andric     [[fallthrough]];
5620b57cec5SDimitry Andric   default:
5630b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_exp10);
5640b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_exp10f);
5650b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_exp10l);
5660b57cec5SDimitry Andric   }
5670b57cec5SDimitry Andric 
5680b57cec5SDimitry Andric   // ffsl is available on at least Darwin, Mac OS X, iOS, FreeBSD, and
5690b57cec5SDimitry Andric   // Linux (GLIBC):
5700b57cec5SDimitry Andric   // http://developer.apple.com/library/mac/#documentation/Darwin/Reference/ManPages/man3/ffsl.3.html
5710b57cec5SDimitry Andric   // http://svn.freebsd.org/base/head/lib/libc/string/ffsl.c
5720b57cec5SDimitry Andric   // http://www.gnu.org/software/gnulib/manual/html_node/ffsl.html
5730b57cec5SDimitry Andric   switch (T.getOS()) {
5740b57cec5SDimitry Andric   case Triple::Darwin:
5750b57cec5SDimitry Andric   case Triple::MacOSX:
5760b57cec5SDimitry Andric   case Triple::IOS:
5770b57cec5SDimitry Andric   case Triple::TvOS:
5780b57cec5SDimitry Andric   case Triple::WatchOS:
579*a58f00eaSDimitry Andric   case Triple::XROS:
5800b57cec5SDimitry Andric   case Triple::FreeBSD:
5810b57cec5SDimitry Andric   case Triple::Linux:
5820b57cec5SDimitry Andric     break;
5830b57cec5SDimitry Andric   default:
5840b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_ffsl);
5850b57cec5SDimitry Andric   }
5860b57cec5SDimitry Andric 
5870b57cec5SDimitry Andric   // ffsll is available on at least FreeBSD and Linux (GLIBC):
5880b57cec5SDimitry Andric   // http://svn.freebsd.org/base/head/lib/libc/string/ffsll.c
5890b57cec5SDimitry Andric   // http://www.gnu.org/software/gnulib/manual/html_node/ffsll.html
5900b57cec5SDimitry Andric   switch (T.getOS()) {
5910b57cec5SDimitry Andric   case Triple::Darwin:
5920b57cec5SDimitry Andric   case Triple::MacOSX:
5930b57cec5SDimitry Andric   case Triple::IOS:
5940b57cec5SDimitry Andric   case Triple::TvOS:
5950b57cec5SDimitry Andric   case Triple::WatchOS:
596*a58f00eaSDimitry Andric   case Triple::XROS:
5970b57cec5SDimitry Andric   case Triple::FreeBSD:
5980b57cec5SDimitry Andric   case Triple::Linux:
5990b57cec5SDimitry Andric     break;
6000b57cec5SDimitry Andric   default:
6010b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_ffsll);
6020b57cec5SDimitry Andric   }
6030b57cec5SDimitry Andric 
6040b57cec5SDimitry Andric   // The following functions are available on at least FreeBSD:
6050b57cec5SDimitry Andric   // http://svn.freebsd.org/base/head/lib/libc/string/fls.c
6060b57cec5SDimitry Andric   // http://svn.freebsd.org/base/head/lib/libc/string/flsl.c
6070b57cec5SDimitry Andric   // http://svn.freebsd.org/base/head/lib/libc/string/flsll.c
6080b57cec5SDimitry Andric   if (!T.isOSFreeBSD()) {
6090b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_fls);
6100b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_flsl);
6110b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_flsll);
6120b57cec5SDimitry Andric   }
6130b57cec5SDimitry Andric 
6140b57cec5SDimitry Andric   // The following functions are only available on GNU/Linux (using glibc).
6150b57cec5SDimitry Andric   // Linux variants without glibc (eg: bionic, musl) may have some subset.
6160b57cec5SDimitry Andric   if (!T.isOSLinux() || !T.isGNUEnvironment()) {
6170b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_dunder_strdup);
6180b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_dunder_strtok_r);
6190b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_dunder_isoc99_scanf);
6200b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_dunder_isoc99_sscanf);
6210b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_under_IO_getc);
6220b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_under_IO_putc);
6230b57cec5SDimitry Andric     // But, Android and musl have memalign.
6240b57cec5SDimitry Andric     if (!T.isAndroid() && !T.isMusl())
6250b57cec5SDimitry Andric       TLI.setUnavailable(LibFunc_memalign);
6260b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_fopen64);
6270b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_fseeko64);
6280b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_fstat64);
6290b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_fstatvfs64);
6300b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_ftello64);
6310b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_lstat64);
6320b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_open64);
6330b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_stat64);
6340b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_statvfs64);
6350b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_tmpfile64);
6360b57cec5SDimitry Andric 
6370b57cec5SDimitry Andric     // Relaxed math functions are included in math-finite.h on Linux (GLIBC).
6388c27c554SDimitry Andric     // Note that math-finite.h is no longer supported by top-of-tree GLIBC,
6398c27c554SDimitry Andric     // so we keep these functions around just so that they're recognized by
6408c27c554SDimitry Andric     // the ConstantFolder.
6410b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_acos_finite);
6420b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_acosf_finite);
6430b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_acosl_finite);
6440b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_acosh_finite);
6450b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_acoshf_finite);
6460b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_acoshl_finite);
6470b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_asin_finite);
6480b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_asinf_finite);
6490b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_asinl_finite);
6500b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_atan2_finite);
6510b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_atan2f_finite);
6520b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_atan2l_finite);
6530b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_atanh_finite);
6540b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_atanhf_finite);
6550b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_atanhl_finite);
6560b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_cosh_finite);
6570b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_coshf_finite);
6580b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_coshl_finite);
6590b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_exp10_finite);
6600b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_exp10f_finite);
6610b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_exp10l_finite);
6620b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_exp2_finite);
6630b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_exp2f_finite);
6640b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_exp2l_finite);
6650b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_exp_finite);
6660b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_expf_finite);
6670b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_expl_finite);
6680b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_log10_finite);
6690b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_log10f_finite);
6700b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_log10l_finite);
6710b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_log2_finite);
6720b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_log2f_finite);
6730b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_log2l_finite);
6740b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_log_finite);
6750b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_logf_finite);
6760b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_logl_finite);
6770b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_pow_finite);
6780b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_powf_finite);
6790b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_powl_finite);
6800b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_sinh_finite);
6810b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_sinhf_finite);
6820b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_sinhl_finite);
683349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_sqrt_finite);
684349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_sqrtf_finite);
685349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_sqrtl_finite);
6860b57cec5SDimitry Andric   }
6870b57cec5SDimitry Andric 
6880b57cec5SDimitry Andric   if ((T.isOSLinux() && T.isGNUEnvironment()) ||
6890b57cec5SDimitry Andric       (T.isAndroid() && !T.isAndroidVersionLT(28))) {
6900b57cec5SDimitry Andric     // available IO unlocked variants on GNU/Linux and Android P or later
6910b57cec5SDimitry Andric     TLI.setAvailable(LibFunc_getc_unlocked);
6920b57cec5SDimitry Andric     TLI.setAvailable(LibFunc_getchar_unlocked);
6930b57cec5SDimitry Andric     TLI.setAvailable(LibFunc_putc_unlocked);
6940b57cec5SDimitry Andric     TLI.setAvailable(LibFunc_putchar_unlocked);
6950b57cec5SDimitry Andric     TLI.setAvailable(LibFunc_fputc_unlocked);
6960b57cec5SDimitry Andric     TLI.setAvailable(LibFunc_fgetc_unlocked);
6970b57cec5SDimitry Andric     TLI.setAvailable(LibFunc_fread_unlocked);
6980b57cec5SDimitry Andric     TLI.setAvailable(LibFunc_fwrite_unlocked);
6990b57cec5SDimitry Andric     TLI.setAvailable(LibFunc_fputs_unlocked);
7000b57cec5SDimitry Andric     TLI.setAvailable(LibFunc_fgets_unlocked);
7010b57cec5SDimitry Andric   }
7020b57cec5SDimitry Andric 
703349cc55cSDimitry Andric   if (T.isAndroid() && T.isAndroidVersionLT(21)) {
704349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_stpcpy);
705349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_stpncpy);
706349cc55cSDimitry Andric   }
707349cc55cSDimitry Andric 
70881ad6265SDimitry Andric   if (T.isPS()) {
70981ad6265SDimitry Andric     // PS4/PS5 do have memalign.
710349cc55cSDimitry Andric     TLI.setAvailable(LibFunc_memalign);
711349cc55cSDimitry Andric 
71281ad6265SDimitry Andric     // PS4/PS5 do not have new/delete with "unsigned int" size parameter;
71381ad6265SDimitry Andric     // they only have the "unsigned long" versions.
714349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_ZdaPvj);
715349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_ZdaPvjSt11align_val_t);
716349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_ZdlPvj);
717349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_ZdlPvjSt11align_val_t);
718349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_Znaj);
719349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_ZnajRKSt9nothrow_t);
720349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_ZnajSt11align_val_t);
721349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_ZnajSt11align_val_tRKSt9nothrow_t);
722349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_Znwj);
723349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_ZnwjRKSt9nothrow_t);
724349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_ZnwjSt11align_val_t);
725349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_ZnwjSt11align_val_tRKSt9nothrow_t);
726349cc55cSDimitry Andric 
727349cc55cSDimitry Andric     // None of the *_chk functions.
728349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_memccpy_chk);
729349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_memcpy_chk);
730349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_memmove_chk);
731349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_mempcpy_chk);
732349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_memset_chk);
733349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_snprintf_chk);
734349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_sprintf_chk);
735349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_stpcpy_chk);
736349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_stpncpy_chk);
737349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_strcat_chk);
738349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_strcpy_chk);
739349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_strlcat_chk);
740349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_strlcpy_chk);
741349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_strlen_chk);
742349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_strncat_chk);
743349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_strncpy_chk);
744349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_vsnprintf_chk);
745349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_vsprintf_chk);
746349cc55cSDimitry Andric 
747349cc55cSDimitry Andric     // Various Posix system functions.
748349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_access);
749349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_chmod);
750349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_chown);
751349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_closedir);
752349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_ctermid);
753349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_execl);
754349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_execle);
755349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_execlp);
756349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_execv);
757349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_execvP);
758349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_execve);
759349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_execvp);
760349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_execvpe);
761349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_fork);
762349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_fstat);
763349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_fstatvfs);
764349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_getenv);
765349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_getitimer);
766349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_getlogin_r);
767349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_getpwnam);
768349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_gettimeofday);
769349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_lchown);
770349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_lstat);
771349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_mkdir);
772349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_open);
773349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_opendir);
774349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_pclose);
775349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_popen);
776349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_pread);
777349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_pwrite);
778349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_read);
779349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_readlink);
780349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_realpath);
781349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_rename);
782349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_rmdir);
783349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_setitimer);
784349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_stat);
785349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_statvfs);
786349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_system);
787349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_times);
788349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_tmpfile);
789349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_unlink);
790349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_uname);
791349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_unsetenv);
792349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_utime);
793349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_utimes);
794349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_valloc);
795349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_write);
796349cc55cSDimitry Andric 
797349cc55cSDimitry Andric     // Miscellaneous other functions not provided.
798349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_atomic_load);
799349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_atomic_store);
800349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc___kmpc_alloc_shared);
801349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc___kmpc_free_shared);
802349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_dunder_strndup);
803349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_bcmp);
804349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_bcopy);
805349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_bzero);
806349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_cabs);
807349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_cabsf);
808349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_cabsl);
809349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_ffs);
810349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_flockfile);
811349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_fseeko);
812349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_ftello);
813349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_ftrylockfile);
814349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_funlockfile);
815349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_htonl);
816349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_htons);
817349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_isascii);
818349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_memccpy);
819349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_mempcpy);
820349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_memrchr);
821349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_ntohl);
822349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_ntohs);
823349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_reallocf);
824349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_roundeven);
825349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_roundevenf);
826349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_roundevenl);
827349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_stpcpy);
828349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_stpncpy);
829349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_strlcat);
830349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_strlcpy);
831349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_strndup);
832349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_strnlen);
833349cc55cSDimitry Andric     TLI.setUnavailable(LibFunc_toascii);
834349cc55cSDimitry Andric   }
835349cc55cSDimitry Andric 
8360b57cec5SDimitry Andric   // As currently implemented in clang, NVPTX code has no standard library to
8370b57cec5SDimitry Andric   // speak of.  Headers provide a standard-ish library implementation, but many
8380b57cec5SDimitry Andric   // of the signatures are wrong -- for example, many libm functions are not
8390b57cec5SDimitry Andric   // extern "C".
8400b57cec5SDimitry Andric   //
8410b57cec5SDimitry Andric   // libdevice, an IR library provided by nvidia, is linked in by the front-end,
8420b57cec5SDimitry Andric   // but only used functions are provided to llvm.  Moreover, most of the
8430b57cec5SDimitry Andric   // functions in libdevice don't map precisely to standard library functions.
8440b57cec5SDimitry Andric   //
8450b57cec5SDimitry Andric   // FIXME: Having no standard library prevents e.g. many fastmath
8460b57cec5SDimitry Andric   // optimizations, so this situation should be fixed.
8470b57cec5SDimitry Andric   if (T.isNVPTX()) {
8480b57cec5SDimitry Andric     TLI.disableAllFunctions();
8490b57cec5SDimitry Andric     TLI.setAvailable(LibFunc_nvvm_reflect);
850fe6060f1SDimitry Andric     TLI.setAvailable(llvm::LibFunc_malloc);
851fe6060f1SDimitry Andric     TLI.setAvailable(llvm::LibFunc_free);
852fe6060f1SDimitry Andric 
853fe6060f1SDimitry Andric     // TODO: We could enable the following two according to [0] but we haven't
854fe6060f1SDimitry Andric     //       done an evaluation wrt. the performance implications.
855fe6060f1SDimitry Andric     // [0]
856fe6060f1SDimitry Andric     // https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#dynamic-global-memory-allocation-and-operations
857fe6060f1SDimitry Andric     //
858fe6060f1SDimitry Andric     //    TLI.setAvailable(llvm::LibFunc_memcpy);
859fe6060f1SDimitry Andric     //    TLI.setAvailable(llvm::LibFunc_memset);
860fe6060f1SDimitry Andric 
861fe6060f1SDimitry Andric     TLI.setAvailable(llvm::LibFunc___kmpc_alloc_shared);
862fe6060f1SDimitry Andric     TLI.setAvailable(llvm::LibFunc___kmpc_free_shared);
8630b57cec5SDimitry Andric   } else {
8640b57cec5SDimitry Andric     TLI.setUnavailable(LibFunc_nvvm_reflect);
8650b57cec5SDimitry Andric   }
8660b57cec5SDimitry Andric 
867e8d8bef9SDimitry Andric   // These vec_malloc/free routines are only available on AIX.
868e8d8bef9SDimitry Andric   if (!T.isOSAIX()) {
869e8d8bef9SDimitry Andric     TLI.setUnavailable(LibFunc_vec_calloc);
870e8d8bef9SDimitry Andric     TLI.setUnavailable(LibFunc_vec_malloc);
871e8d8bef9SDimitry Andric     TLI.setUnavailable(LibFunc_vec_realloc);
872e8d8bef9SDimitry Andric     TLI.setUnavailable(LibFunc_vec_free);
873e8d8bef9SDimitry Andric   }
874e8d8bef9SDimitry Andric 
875bdd1243dSDimitry Andric   TLI.addVectorizableFunctionsFromVecLib(ClVectorLibrary, T);
8760b57cec5SDimitry Andric }
8770b57cec5SDimitry Andric 
TargetLibraryInfoImpl()8780b57cec5SDimitry Andric TargetLibraryInfoImpl::TargetLibraryInfoImpl() {
8790b57cec5SDimitry Andric   // Default to everything being available.
8800b57cec5SDimitry Andric   memset(AvailableArray, -1, sizeof(AvailableArray));
8810b57cec5SDimitry Andric 
8820b57cec5SDimitry Andric   initialize(*this, Triple(), StandardNames);
8830b57cec5SDimitry Andric }
8840b57cec5SDimitry Andric 
TargetLibraryInfoImpl(const Triple & T)8850b57cec5SDimitry Andric TargetLibraryInfoImpl::TargetLibraryInfoImpl(const Triple &T) {
8860b57cec5SDimitry Andric   // Default to everything being available.
8870b57cec5SDimitry Andric   memset(AvailableArray, -1, sizeof(AvailableArray));
8880b57cec5SDimitry Andric 
8890b57cec5SDimitry Andric   initialize(*this, T, StandardNames);
8900b57cec5SDimitry Andric }
8910b57cec5SDimitry Andric 
TargetLibraryInfoImpl(const TargetLibraryInfoImpl & TLI)8920b57cec5SDimitry Andric TargetLibraryInfoImpl::TargetLibraryInfoImpl(const TargetLibraryInfoImpl &TLI)
8930b57cec5SDimitry Andric     : CustomNames(TLI.CustomNames), ShouldExtI32Param(TLI.ShouldExtI32Param),
8940b57cec5SDimitry Andric       ShouldExtI32Return(TLI.ShouldExtI32Return),
895fe6060f1SDimitry Andric       ShouldSignExtI32Param(TLI.ShouldSignExtI32Param),
896bdd1243dSDimitry Andric       ShouldSignExtI32Return(TLI.ShouldSignExtI32Return),
897fe6060f1SDimitry Andric       SizeOfInt(TLI.SizeOfInt) {
8980b57cec5SDimitry Andric   memcpy(AvailableArray, TLI.AvailableArray, sizeof(AvailableArray));
8990b57cec5SDimitry Andric   VectorDescs = TLI.VectorDescs;
9000b57cec5SDimitry Andric   ScalarDescs = TLI.ScalarDescs;
9010b57cec5SDimitry Andric }
9020b57cec5SDimitry Andric 
TargetLibraryInfoImpl(TargetLibraryInfoImpl && TLI)9030b57cec5SDimitry Andric TargetLibraryInfoImpl::TargetLibraryInfoImpl(TargetLibraryInfoImpl &&TLI)
9040b57cec5SDimitry Andric     : CustomNames(std::move(TLI.CustomNames)),
9050b57cec5SDimitry Andric       ShouldExtI32Param(TLI.ShouldExtI32Param),
9060b57cec5SDimitry Andric       ShouldExtI32Return(TLI.ShouldExtI32Return),
907fe6060f1SDimitry Andric       ShouldSignExtI32Param(TLI.ShouldSignExtI32Param),
908bdd1243dSDimitry Andric       ShouldSignExtI32Return(TLI.ShouldSignExtI32Return),
909fe6060f1SDimitry Andric       SizeOfInt(TLI.SizeOfInt) {
9100b57cec5SDimitry Andric   std::move(std::begin(TLI.AvailableArray), std::end(TLI.AvailableArray),
9110b57cec5SDimitry Andric             AvailableArray);
9120b57cec5SDimitry Andric   VectorDescs = TLI.VectorDescs;
9130b57cec5SDimitry Andric   ScalarDescs = TLI.ScalarDescs;
9140b57cec5SDimitry Andric }
9150b57cec5SDimitry Andric 
operator =(const TargetLibraryInfoImpl & TLI)9160b57cec5SDimitry Andric TargetLibraryInfoImpl &TargetLibraryInfoImpl::operator=(const TargetLibraryInfoImpl &TLI) {
9170b57cec5SDimitry Andric   CustomNames = TLI.CustomNames;
9180b57cec5SDimitry Andric   ShouldExtI32Param = TLI.ShouldExtI32Param;
9190b57cec5SDimitry Andric   ShouldExtI32Return = TLI.ShouldExtI32Return;
9200b57cec5SDimitry Andric   ShouldSignExtI32Param = TLI.ShouldSignExtI32Param;
921bdd1243dSDimitry Andric   ShouldSignExtI32Return = TLI.ShouldSignExtI32Return;
922fe6060f1SDimitry Andric   SizeOfInt = TLI.SizeOfInt;
9230b57cec5SDimitry Andric   memcpy(AvailableArray, TLI.AvailableArray, sizeof(AvailableArray));
9240b57cec5SDimitry Andric   return *this;
9250b57cec5SDimitry Andric }
9260b57cec5SDimitry Andric 
operator =(TargetLibraryInfoImpl && TLI)9270b57cec5SDimitry Andric TargetLibraryInfoImpl &TargetLibraryInfoImpl::operator=(TargetLibraryInfoImpl &&TLI) {
9280b57cec5SDimitry Andric   CustomNames = std::move(TLI.CustomNames);
9290b57cec5SDimitry Andric   ShouldExtI32Param = TLI.ShouldExtI32Param;
9300b57cec5SDimitry Andric   ShouldExtI32Return = TLI.ShouldExtI32Return;
9310b57cec5SDimitry Andric   ShouldSignExtI32Param = TLI.ShouldSignExtI32Param;
932bdd1243dSDimitry Andric   ShouldSignExtI32Return = TLI.ShouldSignExtI32Return;
933fe6060f1SDimitry Andric   SizeOfInt = TLI.SizeOfInt;
9340b57cec5SDimitry Andric   std::move(std::begin(TLI.AvailableArray), std::end(TLI.AvailableArray),
9350b57cec5SDimitry Andric             AvailableArray);
9360b57cec5SDimitry Andric   return *this;
9370b57cec5SDimitry Andric }
9380b57cec5SDimitry Andric 
sanitizeFunctionName(StringRef funcName)9390b57cec5SDimitry Andric static StringRef sanitizeFunctionName(StringRef funcName) {
9400b57cec5SDimitry Andric   // Filter out empty names and names containing null bytes, those can't be in
9410b57cec5SDimitry Andric   // our table.
942349cc55cSDimitry Andric   if (funcName.empty() || funcName.contains('\0'))
9430b57cec5SDimitry Andric     return StringRef();
9440b57cec5SDimitry Andric 
9450b57cec5SDimitry Andric   // Check for \01 prefix that is used to mangle __asm declarations and
9460b57cec5SDimitry Andric   // strip it if present.
9470b57cec5SDimitry Andric   return GlobalValue::dropLLVMManglingEscape(funcName);
9480b57cec5SDimitry Andric }
9490b57cec5SDimitry Andric 
950c9157d92SDimitry Andric static DenseMap<StringRef, LibFunc>
buildIndexMap(ArrayRef<StringLiteral> StandardNames)951c9157d92SDimitry Andric buildIndexMap(ArrayRef<StringLiteral> StandardNames) {
952c9157d92SDimitry Andric   DenseMap<StringRef, LibFunc> Indices;
953c9157d92SDimitry Andric   unsigned Idx = 0;
954c9157d92SDimitry Andric   Indices.reserve(LibFunc::NumLibFuncs);
955c9157d92SDimitry Andric   for (const auto &Func : StandardNames)
956c9157d92SDimitry Andric     Indices[Func] = static_cast<LibFunc>(Idx++);
957c9157d92SDimitry Andric   return Indices;
958c9157d92SDimitry Andric }
959c9157d92SDimitry Andric 
getLibFunc(StringRef funcName,LibFunc & F) const9608bcb0991SDimitry Andric bool TargetLibraryInfoImpl::getLibFunc(StringRef funcName, LibFunc &F) const {
9610b57cec5SDimitry Andric   funcName = sanitizeFunctionName(funcName);
9620b57cec5SDimitry Andric   if (funcName.empty())
9630b57cec5SDimitry Andric     return false;
9640b57cec5SDimitry Andric 
965c9157d92SDimitry Andric   static const DenseMap<StringRef, LibFunc> Indices =
966c9157d92SDimitry Andric       buildIndexMap(StandardNames);
967c9157d92SDimitry Andric 
968c9157d92SDimitry Andric   if (auto Loc = Indices.find(funcName); Loc != Indices.end()) {
969c9157d92SDimitry Andric     F = Loc->second;
9700b57cec5SDimitry Andric     return true;
9710b57cec5SDimitry Andric   }
9720b57cec5SDimitry Andric   return false;
9730b57cec5SDimitry Andric }
9740b57cec5SDimitry Andric 
975bdd1243dSDimitry Andric // Return true if ArgTy matches Ty.
976bdd1243dSDimitry Andric 
matchType(FuncArgTypeID ArgTy,const Type * Ty,unsigned IntBits,unsigned SizeTBits)977bdd1243dSDimitry Andric static bool matchType(FuncArgTypeID ArgTy, const Type *Ty, unsigned IntBits,
978bdd1243dSDimitry Andric                       unsigned SizeTBits) {
979bdd1243dSDimitry Andric   switch (ArgTy) {
980bdd1243dSDimitry Andric   case Void:
981bdd1243dSDimitry Andric     return Ty->isVoidTy();
982bdd1243dSDimitry Andric   case Bool:
983bdd1243dSDimitry Andric     return Ty->isIntegerTy(8);
984bdd1243dSDimitry Andric   case Int16:
985bdd1243dSDimitry Andric     return Ty->isIntegerTy(16);
986bdd1243dSDimitry Andric   case Int32:
987bdd1243dSDimitry Andric     return Ty->isIntegerTy(32);
988bdd1243dSDimitry Andric   case Int:
989bdd1243dSDimitry Andric     return Ty->isIntegerTy(IntBits);
990bdd1243dSDimitry Andric   case IntPlus:
991bdd1243dSDimitry Andric     return Ty->isIntegerTy() && Ty->getPrimitiveSizeInBits() >= IntBits;
992bdd1243dSDimitry Andric   case IntX:
993bdd1243dSDimitry Andric     return Ty->isIntegerTy();
994bdd1243dSDimitry Andric   case Long:
995bdd1243dSDimitry Andric     // TODO: Figure out and use long size.
996bdd1243dSDimitry Andric     return Ty->isIntegerTy() && Ty->getPrimitiveSizeInBits() >= IntBits;
997bdd1243dSDimitry Andric   case Int64:
998bdd1243dSDimitry Andric     return Ty->isIntegerTy(64);
999bdd1243dSDimitry Andric   case LLong:
1000bdd1243dSDimitry Andric     return Ty->isIntegerTy(64);
1001bdd1243dSDimitry Andric   case SizeT:
1002bdd1243dSDimitry Andric   case SSizeT:
1003bdd1243dSDimitry Andric     return Ty->isIntegerTy(SizeTBits);
1004bdd1243dSDimitry Andric   case Flt:
1005bdd1243dSDimitry Andric     return Ty->isFloatTy();
1006bdd1243dSDimitry Andric   case Dbl:
1007bdd1243dSDimitry Andric     return Ty->isDoubleTy();
1008bdd1243dSDimitry Andric     // TODO: Tighten this up.
1009bdd1243dSDimitry Andric   case LDbl:
1010bdd1243dSDimitry Andric     return Ty->isFloatingPointTy();
1011bdd1243dSDimitry Andric   case Floating:
1012bdd1243dSDimitry Andric     return Ty->isFloatingPointTy();
1013bdd1243dSDimitry Andric   case Ptr:
1014bdd1243dSDimitry Andric     return Ty->isPointerTy();
1015bdd1243dSDimitry Andric   case Struct:
1016bdd1243dSDimitry Andric     return Ty->isStructTy();
1017bdd1243dSDimitry Andric   default:
1018bdd1243dSDimitry Andric     break;
1019bdd1243dSDimitry Andric   }
1020bdd1243dSDimitry Andric 
1021bdd1243dSDimitry Andric   llvm_unreachable("Invalid type");
1022bdd1243dSDimitry Andric }
1023bdd1243dSDimitry Andric 
isValidProtoForLibFunc(const FunctionType & FTy,LibFunc F,const Module & M) const10240b57cec5SDimitry Andric bool TargetLibraryInfoImpl::isValidProtoForLibFunc(const FunctionType &FTy,
10250b57cec5SDimitry Andric                                                    LibFunc F,
1026349cc55cSDimitry Andric                                                    const Module &M) const {
10270b57cec5SDimitry Andric   unsigned NumParams = FTy.getNumParams();
10280b57cec5SDimitry Andric 
10290b57cec5SDimitry Andric   switch (F) {
1030bdd1243dSDimitry Andric     // Special handling for <complex.h> functions:
10310b57cec5SDimitry Andric   case LibFunc_cabs:
10320b57cec5SDimitry Andric   case LibFunc_cabsf:
10330b57cec5SDimitry Andric   case LibFunc_cabsl: {
10340b57cec5SDimitry Andric     Type *RetTy = FTy.getReturnType();
10350b57cec5SDimitry Andric     if (!RetTy->isFloatingPointTy())
10360b57cec5SDimitry Andric       return false;
10370b57cec5SDimitry Andric 
1038bdd1243dSDimitry Andric     Type *ParamTy = FTy.getParamType(0);
10390b57cec5SDimitry Andric     // NOTE: These prototypes are target specific and currently support
10400b57cec5SDimitry Andric     // "complex" passed as an array or discrete real & imaginary parameters.
10410b57cec5SDimitry Andric     // Add other calling conventions to enable libcall optimizations.
10420b57cec5SDimitry Andric     if (NumParams == 1)
1043bdd1243dSDimitry Andric       return (ParamTy->isArrayTy() && ParamTy->getArrayNumElements() == 2 &&
1044bdd1243dSDimitry Andric               ParamTy->getArrayElementType() == RetTy);
10450b57cec5SDimitry Andric     else if (NumParams == 2)
1046bdd1243dSDimitry Andric       return ParamTy == RetTy && FTy.getParamType(1) == RetTy;
1047bdd1243dSDimitry Andric 
10480b57cec5SDimitry Andric     return false;
10490b57cec5SDimitry Andric   }
1050bdd1243dSDimitry Andric     // Special handling for the sincospi functions that return either
1051bdd1243dSDimitry Andric     // a struct or vector:
1052bdd1243dSDimitry Andric   case LibFunc_sincospi_stret:
1053bdd1243dSDimitry Andric   case LibFunc_sincospif_stret: {
1054bdd1243dSDimitry Andric     if (NumParams != 1)
1055bdd1243dSDimitry Andric       return false;
1056bdd1243dSDimitry Andric 
1057bdd1243dSDimitry Andric     Type *RetTy = FTy.getReturnType();
1058bdd1243dSDimitry Andric     Type *ParamTy = FTy.getParamType(0);
1059bdd1243dSDimitry Andric     if (auto *Ty = dyn_cast<StructType>(RetTy)) {
1060bdd1243dSDimitry Andric       if (Ty->getNumElements() != 2)
1061bdd1243dSDimitry Andric         return false;
1062bdd1243dSDimitry Andric       return (Ty->getElementType(0) == ParamTy &&
1063bdd1243dSDimitry Andric               Ty->getElementType(1) == ParamTy);
1064bdd1243dSDimitry Andric     }
1065bdd1243dSDimitry Andric 
1066bdd1243dSDimitry Andric     if (auto *Ty = dyn_cast<FixedVectorType>(RetTy)) {
1067bdd1243dSDimitry Andric       if (Ty->getNumElements() != 2)
1068bdd1243dSDimitry Andric         return false;
1069bdd1243dSDimitry Andric       return Ty->getElementType() == ParamTy;
1070bdd1243dSDimitry Andric     }
1071bdd1243dSDimitry Andric 
1072bdd1243dSDimitry Andric     return false;
1073bdd1243dSDimitry Andric   }
1074bdd1243dSDimitry Andric 
1075bdd1243dSDimitry Andric   default:
10760b57cec5SDimitry Andric     break;
10770b57cec5SDimitry Andric   }
10780b57cec5SDimitry Andric 
1079bdd1243dSDimitry Andric   unsigned IntBits = getIntSize();
1080bdd1243dSDimitry Andric   unsigned SizeTBits = getSizeTSize(M);
1081bdd1243dSDimitry Andric   unsigned Idx = 0;
1082bdd1243dSDimitry Andric 
1083bdd1243dSDimitry Andric   // Iterate over the type ids in the function prototype, matching each
1084bdd1243dSDimitry Andric   // against the function's type FTy, starting with its return type.
1085bdd1243dSDimitry Andric   // Return true if both match in number and kind, inclduing the ellipsis.
1086bdd1243dSDimitry Andric   Type *Ty = FTy.getReturnType(), *LastTy = Ty;
1087bdd1243dSDimitry Andric   const auto &ProtoTypes = Signatures[F];
1088bdd1243dSDimitry Andric   for (auto TyID : ProtoTypes) {
1089bdd1243dSDimitry Andric     if (Idx && TyID == Void)
1090bdd1243dSDimitry Andric       // Except in the first position where it designates the function's
1091bdd1243dSDimitry Andric       // return type Void ends the argument list.
1092bdd1243dSDimitry Andric       break;
1093bdd1243dSDimitry Andric 
1094bdd1243dSDimitry Andric     if (TyID == Ellip) {
1095bdd1243dSDimitry Andric       // The ellipsis ends the protoype list but is not a part of FTy's
1096bdd1243dSDimitry Andric       // argument list.  Except when it's last it must be followed by
1097bdd1243dSDimitry Andric       // Void.
1098bdd1243dSDimitry Andric       assert(Idx == ProtoTypes.size() - 1 || ProtoTypes[Idx + 1] == Void);
1099bdd1243dSDimitry Andric       return FTy.isFunctionVarArg();
1100bdd1243dSDimitry Andric     }
1101bdd1243dSDimitry Andric 
1102bdd1243dSDimitry Andric     if (TyID == Same) {
1103bdd1243dSDimitry Andric       assert(Idx != 0 && "Type ID 'Same' must not be first!");
1104bdd1243dSDimitry Andric       if (Ty != LastTy)
1105bdd1243dSDimitry Andric         return false;
1106bdd1243dSDimitry Andric     } else {
1107bdd1243dSDimitry Andric       if (!Ty || !matchType(TyID, Ty, IntBits, SizeTBits))
1108bdd1243dSDimitry Andric         return false;
1109bdd1243dSDimitry Andric       LastTy = Ty;
1110bdd1243dSDimitry Andric     }
1111bdd1243dSDimitry Andric 
1112bdd1243dSDimitry Andric     if (Idx == NumParams) {
1113bdd1243dSDimitry Andric       // There's at least one and at most two more type ids than there are
1114bdd1243dSDimitry Andric       // arguments in FTy's argument list.
1115bdd1243dSDimitry Andric       Ty = nullptr;
1116bdd1243dSDimitry Andric       ++Idx;
1117bdd1243dSDimitry Andric       continue;
1118bdd1243dSDimitry Andric     }
1119bdd1243dSDimitry Andric 
1120bdd1243dSDimitry Andric     Ty = FTy.getParamType(Idx++);
1121bdd1243dSDimitry Andric   }
1122bdd1243dSDimitry Andric 
1123bdd1243dSDimitry Andric   // Return success only if all entries on both lists have been processed
1124bdd1243dSDimitry Andric   // and the function is not a variadic one.
1125bdd1243dSDimitry Andric   return Idx == NumParams + 1 && !FTy.isFunctionVarArg();
11260b57cec5SDimitry Andric }
11270b57cec5SDimitry Andric 
getLibFunc(const Function & FDecl,LibFunc & F) const11280b57cec5SDimitry Andric bool TargetLibraryInfoImpl::getLibFunc(const Function &FDecl,
11290b57cec5SDimitry Andric                                        LibFunc &F) const {
11300b57cec5SDimitry Andric   // Intrinsics don't overlap w/libcalls; if our module has a large number of
11310b57cec5SDimitry Andric   // intrinsics, this ends up being an interesting compile time win since we
11320b57cec5SDimitry Andric   // avoid string normalization and comparison.
11330b57cec5SDimitry Andric   if (FDecl.isIntrinsic()) return false;
11340b57cec5SDimitry Andric 
1135349cc55cSDimitry Andric   const Module *M = FDecl.getParent();
1136349cc55cSDimitry Andric   assert(M && "Expecting FDecl to be connected to a Module.");
1137349cc55cSDimitry Andric 
1138c9157d92SDimitry Andric   if (FDecl.LibFuncCache == Function::UnknownLibFunc)
1139c9157d92SDimitry Andric     if (!getLibFunc(FDecl.getName(), FDecl.LibFuncCache))
1140c9157d92SDimitry Andric       FDecl.LibFuncCache = NotLibFunc;
1141c9157d92SDimitry Andric 
1142c9157d92SDimitry Andric   if (FDecl.LibFuncCache == NotLibFunc)
1143c9157d92SDimitry Andric     return false;
1144c9157d92SDimitry Andric 
1145c9157d92SDimitry Andric   F = FDecl.LibFuncCache;
1146c9157d92SDimitry Andric   return isValidProtoForLibFunc(*FDecl.getFunctionType(), F, *M);
11470b57cec5SDimitry Andric }
11480b57cec5SDimitry Andric 
getLibFunc(unsigned int Opcode,Type * Ty,LibFunc & F) const1149e710425bSDimitry Andric bool TargetLibraryInfoImpl::getLibFunc(unsigned int Opcode, Type *Ty,
1150e710425bSDimitry Andric                                        LibFunc &F) const {
1151e710425bSDimitry Andric   // Must be a frem instruction with float or double arguments.
1152e710425bSDimitry Andric   if (Opcode != Instruction::FRem || (!Ty->isDoubleTy() && !Ty->isFloatTy()))
1153e710425bSDimitry Andric     return false;
1154e710425bSDimitry Andric 
1155e710425bSDimitry Andric   F = Ty->isDoubleTy() ? LibFunc_fmod : LibFunc_fmodf;
1156e710425bSDimitry Andric   return true;
1157e710425bSDimitry Andric }
1158e710425bSDimitry Andric 
disableAllFunctions()11590b57cec5SDimitry Andric void TargetLibraryInfoImpl::disableAllFunctions() {
11600b57cec5SDimitry Andric   memset(AvailableArray, 0, sizeof(AvailableArray));
11610b57cec5SDimitry Andric }
11620b57cec5SDimitry Andric 
compareByScalarFnName(const VecDesc & LHS,const VecDesc & RHS)11630b57cec5SDimitry Andric static bool compareByScalarFnName(const VecDesc &LHS, const VecDesc &RHS) {
1164c9157d92SDimitry Andric   return LHS.getScalarFnName() < RHS.getScalarFnName();
11650b57cec5SDimitry Andric }
11660b57cec5SDimitry Andric 
compareByVectorFnName(const VecDesc & LHS,const VecDesc & RHS)11670b57cec5SDimitry Andric static bool compareByVectorFnName(const VecDesc &LHS, const VecDesc &RHS) {
1168c9157d92SDimitry Andric   return LHS.getVectorFnName() < RHS.getVectorFnName();
11690b57cec5SDimitry Andric }
11700b57cec5SDimitry Andric 
compareWithScalarFnName(const VecDesc & LHS,StringRef S)11710b57cec5SDimitry Andric static bool compareWithScalarFnName(const VecDesc &LHS, StringRef S) {
1172c9157d92SDimitry Andric   return LHS.getScalarFnName() < S;
11730b57cec5SDimitry Andric }
11740b57cec5SDimitry Andric 
addVectorizableFunctions(ArrayRef<VecDesc> Fns)11750b57cec5SDimitry Andric void TargetLibraryInfoImpl::addVectorizableFunctions(ArrayRef<VecDesc> Fns) {
1176e8d8bef9SDimitry Andric   llvm::append_range(VectorDescs, Fns);
11770b57cec5SDimitry Andric   llvm::sort(VectorDescs, compareByScalarFnName);
11780b57cec5SDimitry Andric 
1179e8d8bef9SDimitry Andric   llvm::append_range(ScalarDescs, Fns);
11800b57cec5SDimitry Andric   llvm::sort(ScalarDescs, compareByVectorFnName);
11810b57cec5SDimitry Andric }
11820b57cec5SDimitry Andric 
addVectorizableFunctionsFromVecLib(enum VectorLibrary VecLib,const llvm::Triple & TargetTriple)11830b57cec5SDimitry Andric void TargetLibraryInfoImpl::addVectorizableFunctionsFromVecLib(
1184bdd1243dSDimitry Andric     enum VectorLibrary VecLib, const llvm::Triple &TargetTriple) {
11850b57cec5SDimitry Andric   switch (VecLib) {
11860b57cec5SDimitry Andric   case Accelerate: {
11870b57cec5SDimitry Andric     const VecDesc VecFuncs[] = {
11880b57cec5SDimitry Andric     #define TLI_DEFINE_ACCELERATE_VECFUNCS
11890b57cec5SDimitry Andric     #include "llvm/Analysis/VecFuncs.def"
11900b57cec5SDimitry Andric     };
11910b57cec5SDimitry Andric     addVectorizableFunctions(VecFuncs);
11920b57cec5SDimitry Andric     break;
11930b57cec5SDimitry Andric   }
1194fe6060f1SDimitry Andric   case DarwinLibSystemM: {
1195fe6060f1SDimitry Andric     const VecDesc VecFuncs[] = {
1196fe6060f1SDimitry Andric     #define TLI_DEFINE_DARWIN_LIBSYSTEM_M_VECFUNCS
1197fe6060f1SDimitry Andric     #include "llvm/Analysis/VecFuncs.def"
1198fe6060f1SDimitry Andric     };
1199fe6060f1SDimitry Andric     addVectorizableFunctions(VecFuncs);
1200fe6060f1SDimitry Andric     break;
1201fe6060f1SDimitry Andric   }
1202e8d8bef9SDimitry Andric   case LIBMVEC_X86: {
1203e8d8bef9SDimitry Andric     const VecDesc VecFuncs[] = {
1204e8d8bef9SDimitry Andric     #define TLI_DEFINE_LIBMVEC_X86_VECFUNCS
1205e8d8bef9SDimitry Andric     #include "llvm/Analysis/VecFuncs.def"
1206e8d8bef9SDimitry Andric     };
1207e8d8bef9SDimitry Andric     addVectorizableFunctions(VecFuncs);
1208e8d8bef9SDimitry Andric     break;
1209e8d8bef9SDimitry Andric   }
12100b57cec5SDimitry Andric   case MASSV: {
12110b57cec5SDimitry Andric     const VecDesc VecFuncs[] = {
12120b57cec5SDimitry Andric     #define TLI_DEFINE_MASSV_VECFUNCS
12130b57cec5SDimitry Andric     #include "llvm/Analysis/VecFuncs.def"
12140b57cec5SDimitry Andric     };
12150b57cec5SDimitry Andric     addVectorizableFunctions(VecFuncs);
12160b57cec5SDimitry Andric     break;
12170b57cec5SDimitry Andric   }
12180b57cec5SDimitry Andric   case SVML: {
12190b57cec5SDimitry Andric     const VecDesc VecFuncs[] = {
12200b57cec5SDimitry Andric     #define TLI_DEFINE_SVML_VECFUNCS
12210b57cec5SDimitry Andric     #include "llvm/Analysis/VecFuncs.def"
12220b57cec5SDimitry Andric     };
12230b57cec5SDimitry Andric     addVectorizableFunctions(VecFuncs);
12240b57cec5SDimitry Andric     break;
12250b57cec5SDimitry Andric   }
1226bdd1243dSDimitry Andric   case SLEEFGNUABI: {
1227bdd1243dSDimitry Andric     const VecDesc VecFuncs_VF2[] = {
1228bdd1243dSDimitry Andric #define TLI_DEFINE_SLEEFGNUABI_VF2_VECFUNCS
1229c9157d92SDimitry Andric #define TLI_DEFINE_VECFUNC(SCAL, VEC, VF, VABI_PREFIX)                         \
1230c9157d92SDimitry Andric   {SCAL, VEC, VF, /* MASK = */ false, VABI_PREFIX},
1231bdd1243dSDimitry Andric #include "llvm/Analysis/VecFuncs.def"
1232bdd1243dSDimitry Andric     };
1233bdd1243dSDimitry Andric     const VecDesc VecFuncs_VF4[] = {
1234bdd1243dSDimitry Andric #define TLI_DEFINE_SLEEFGNUABI_VF4_VECFUNCS
1235c9157d92SDimitry Andric #define TLI_DEFINE_VECFUNC(SCAL, VEC, VF, VABI_PREFIX)                         \
1236c9157d92SDimitry Andric   {SCAL, VEC, VF, /* MASK = */ false, VABI_PREFIX},
1237fe013be4SDimitry Andric #include "llvm/Analysis/VecFuncs.def"
1238fe013be4SDimitry Andric     };
1239fe013be4SDimitry Andric     const VecDesc VecFuncs_VFScalable[] = {
1240fe013be4SDimitry Andric #define TLI_DEFINE_SLEEFGNUABI_SCALABLE_VECFUNCS
1241c9157d92SDimitry Andric #define TLI_DEFINE_VECFUNC(SCAL, VEC, VF, MASK, VABI_PREFIX)                   \
1242c9157d92SDimitry Andric   {SCAL, VEC, VF, MASK, VABI_PREFIX},
1243bdd1243dSDimitry Andric #include "llvm/Analysis/VecFuncs.def"
1244bdd1243dSDimitry Andric     };
1245bdd1243dSDimitry Andric 
1246bdd1243dSDimitry Andric     switch (TargetTriple.getArch()) {
1247bdd1243dSDimitry Andric     default:
1248bdd1243dSDimitry Andric       break;
1249bdd1243dSDimitry Andric     case llvm::Triple::aarch64:
1250bdd1243dSDimitry Andric     case llvm::Triple::aarch64_be:
1251bdd1243dSDimitry Andric       addVectorizableFunctions(VecFuncs_VF2);
1252bdd1243dSDimitry Andric       addVectorizableFunctions(VecFuncs_VF4);
1253fe013be4SDimitry Andric       addVectorizableFunctions(VecFuncs_VFScalable);
1254fe013be4SDimitry Andric       break;
1255fe013be4SDimitry Andric     }
1256fe013be4SDimitry Andric     break;
1257fe013be4SDimitry Andric   }
1258fe013be4SDimitry Andric   case ArmPL: {
1259fe013be4SDimitry Andric     const VecDesc VecFuncs[] = {
1260fe013be4SDimitry Andric #define TLI_DEFINE_ARMPL_VECFUNCS
1261c9157d92SDimitry Andric #define TLI_DEFINE_VECFUNC(SCAL, VEC, VF, MASK, VABI_PREFIX)                   \
1262c9157d92SDimitry Andric   {SCAL, VEC, VF, MASK, VABI_PREFIX},
1263fe013be4SDimitry Andric #include "llvm/Analysis/VecFuncs.def"
1264fe013be4SDimitry Andric     };
1265fe013be4SDimitry Andric 
1266fe013be4SDimitry Andric     switch (TargetTriple.getArch()) {
1267fe013be4SDimitry Andric     default:
1268fe013be4SDimitry Andric       break;
1269fe013be4SDimitry Andric     case llvm::Triple::aarch64:
1270fe013be4SDimitry Andric     case llvm::Triple::aarch64_be:
1271fe013be4SDimitry Andric       addVectorizableFunctions(VecFuncs);
1272bdd1243dSDimitry Andric       break;
1273bdd1243dSDimitry Andric     }
1274bdd1243dSDimitry Andric     break;
1275bdd1243dSDimitry Andric   }
12760b57cec5SDimitry Andric   case NoLibrary:
12770b57cec5SDimitry Andric     break;
12780b57cec5SDimitry Andric   }
12790b57cec5SDimitry Andric }
12800b57cec5SDimitry Andric 
isFunctionVectorizable(StringRef funcName) const12810b57cec5SDimitry Andric bool TargetLibraryInfoImpl::isFunctionVectorizable(StringRef funcName) const {
12820b57cec5SDimitry Andric   funcName = sanitizeFunctionName(funcName);
12830b57cec5SDimitry Andric   if (funcName.empty())
12840b57cec5SDimitry Andric     return false;
12850b57cec5SDimitry Andric 
12860b57cec5SDimitry Andric   std::vector<VecDesc>::const_iterator I =
12870b57cec5SDimitry Andric       llvm::lower_bound(VectorDescs, funcName, compareWithScalarFnName);
1288c9157d92SDimitry Andric   return I != VectorDescs.end() && StringRef(I->getScalarFnName()) == funcName;
12890b57cec5SDimitry Andric }
12900b57cec5SDimitry Andric 
getVectorizedFunction(StringRef F,const ElementCount & VF,bool Masked) const1291fe013be4SDimitry Andric StringRef TargetLibraryInfoImpl::getVectorizedFunction(StringRef F,
1292fe013be4SDimitry Andric                                                        const ElementCount &VF,
1293fe013be4SDimitry Andric                                                        bool Masked) const {
1294c9157d92SDimitry Andric   const VecDesc *VD = getVectorMappingInfo(F, VF, Masked);
1295c9157d92SDimitry Andric   if (VD)
1296c9157d92SDimitry Andric     return VD->getVectorFnName();
1297c9157d92SDimitry Andric   return StringRef();
1298c9157d92SDimitry Andric }
1299c9157d92SDimitry Andric 
1300c9157d92SDimitry Andric const VecDesc *
getVectorMappingInfo(StringRef F,const ElementCount & VF,bool Masked) const1301c9157d92SDimitry Andric TargetLibraryInfoImpl::getVectorMappingInfo(StringRef F, const ElementCount &VF,
1302c9157d92SDimitry Andric                                             bool Masked) const {
13030b57cec5SDimitry Andric   F = sanitizeFunctionName(F);
13040b57cec5SDimitry Andric   if (F.empty())
1305c9157d92SDimitry Andric     return nullptr;
13060b57cec5SDimitry Andric   std::vector<VecDesc>::const_iterator I =
13070b57cec5SDimitry Andric       llvm::lower_bound(VectorDescs, F, compareWithScalarFnName);
1308c9157d92SDimitry Andric   while (I != VectorDescs.end() && StringRef(I->getScalarFnName()) == F) {
1309c9157d92SDimitry Andric     if ((I->getVectorizationFactor() == VF) && (I->isMasked() == Masked))
1310c9157d92SDimitry Andric       return &(*I);
13110b57cec5SDimitry Andric     ++I;
13120b57cec5SDimitry Andric   }
1313c9157d92SDimitry Andric   return nullptr;
13140b57cec5SDimitry Andric }
13150b57cec5SDimitry Andric 
run(const Function & F,FunctionAnalysisManager &)1316480093f4SDimitry Andric TargetLibraryInfo TargetLibraryAnalysis::run(const Function &F,
13170b57cec5SDimitry Andric                                              FunctionAnalysisManager &) {
1318480093f4SDimitry Andric   if (!BaselineInfoImpl)
1319480093f4SDimitry Andric     BaselineInfoImpl =
1320480093f4SDimitry Andric         TargetLibraryInfoImpl(Triple(F.getParent()->getTargetTriple()));
1321480093f4SDimitry Andric   return TargetLibraryInfo(*BaselineInfoImpl, &F);
13220b57cec5SDimitry Andric }
13230b57cec5SDimitry Andric 
getWCharSize(const Module & M) const13240b57cec5SDimitry Andric unsigned TargetLibraryInfoImpl::getWCharSize(const Module &M) const {
13250b57cec5SDimitry Andric   if (auto *ShortWChar = cast_or_null<ConstantAsMetadata>(
13260b57cec5SDimitry Andric       M.getModuleFlag("wchar_size")))
13270b57cec5SDimitry Andric     return cast<ConstantInt>(ShortWChar->getValue())->getZExtValue();
13280b57cec5SDimitry Andric   return 0;
13290b57cec5SDimitry Andric }
13300b57cec5SDimitry Andric 
getSizeTSize(const Module & M) const1331bdd1243dSDimitry Andric unsigned TargetLibraryInfoImpl::getSizeTSize(const Module &M) const {
1332bdd1243dSDimitry Andric   // There is really no guarantee that sizeof(size_t) is equal to sizeof(int*).
1333bdd1243dSDimitry Andric   // If that isn't true then it should be possible to derive the SizeTTy from
1334bdd1243dSDimitry Andric   // the target triple here instead and do an early return.
1335bdd1243dSDimitry Andric 
1336bdd1243dSDimitry Andric   // Historically LLVM assume that size_t has same size as intptr_t (hence
1337bdd1243dSDimitry Andric   // deriving the size from sizeof(int*) in address space zero). This should
1338bdd1243dSDimitry Andric   // work for most targets. For future consideration: DataLayout also implement
1339bdd1243dSDimitry Andric   // getIndexSizeInBits which might map better to size_t compared to
1340bdd1243dSDimitry Andric   // getPointerSizeInBits. Hard coding address space zero here might be
1341bdd1243dSDimitry Andric   // unfortunate as well. Maybe getDefaultGlobalsAddressSpace() or
1342bdd1243dSDimitry Andric   // getAllocaAddrSpace() is better.
1343bdd1243dSDimitry Andric   unsigned AddressSpace = 0;
1344bdd1243dSDimitry Andric   return M.getDataLayout().getPointerSizeInBits(AddressSpace);
1345bdd1243dSDimitry Andric }
1346bdd1243dSDimitry Andric 
TargetLibraryInfoWrapperPass()13470b57cec5SDimitry Andric TargetLibraryInfoWrapperPass::TargetLibraryInfoWrapperPass()
1348480093f4SDimitry Andric     : ImmutablePass(ID), TLA(TargetLibraryInfoImpl()) {
13490b57cec5SDimitry Andric   initializeTargetLibraryInfoWrapperPassPass(*PassRegistry::getPassRegistry());
13500b57cec5SDimitry Andric }
13510b57cec5SDimitry Andric 
TargetLibraryInfoWrapperPass(const Triple & T)13520b57cec5SDimitry Andric TargetLibraryInfoWrapperPass::TargetLibraryInfoWrapperPass(const Triple &T)
1353480093f4SDimitry Andric     : ImmutablePass(ID), TLA(TargetLibraryInfoImpl(T)) {
13540b57cec5SDimitry Andric   initializeTargetLibraryInfoWrapperPassPass(*PassRegistry::getPassRegistry());
13550b57cec5SDimitry Andric }
13560b57cec5SDimitry Andric 
TargetLibraryInfoWrapperPass(const TargetLibraryInfoImpl & TLIImpl)13570b57cec5SDimitry Andric TargetLibraryInfoWrapperPass::TargetLibraryInfoWrapperPass(
13580b57cec5SDimitry Andric     const TargetLibraryInfoImpl &TLIImpl)
1359480093f4SDimitry Andric     : ImmutablePass(ID), TLA(TLIImpl) {
13600b57cec5SDimitry Andric   initializeTargetLibraryInfoWrapperPassPass(*PassRegistry::getPassRegistry());
13610b57cec5SDimitry Andric }
13620b57cec5SDimitry Andric 
13630b57cec5SDimitry Andric AnalysisKey TargetLibraryAnalysis::Key;
13640b57cec5SDimitry Andric 
13650b57cec5SDimitry Andric // Register the basic pass.
13660b57cec5SDimitry Andric INITIALIZE_PASS(TargetLibraryInfoWrapperPass, "targetlibinfo",
13670b57cec5SDimitry Andric                 "Target Library Information", false, true)
13680b57cec5SDimitry Andric char TargetLibraryInfoWrapperPass::ID = 0;
13690b57cec5SDimitry Andric 
anchor()13700b57cec5SDimitry Andric void TargetLibraryInfoWrapperPass::anchor() {}
1371480093f4SDimitry Andric 
getWidestVF(StringRef ScalarF,ElementCount & FixedVF,ElementCount & ScalableVF) const1372fe6060f1SDimitry Andric void TargetLibraryInfoImpl::getWidestVF(StringRef ScalarF,
1373fe6060f1SDimitry Andric                                         ElementCount &FixedVF,
1374fe6060f1SDimitry Andric                                         ElementCount &ScalableVF) const {
1375480093f4SDimitry Andric   ScalarF = sanitizeFunctionName(ScalarF);
1376fe6060f1SDimitry Andric   // Use '0' here because a type of the form <vscale x 1 x ElTy> is not the
1377fe6060f1SDimitry Andric   // same as a scalar.
1378fe6060f1SDimitry Andric   ScalableVF = ElementCount::getScalable(0);
1379fe6060f1SDimitry Andric   FixedVF = ElementCount::getFixed(1);
1380480093f4SDimitry Andric   if (ScalarF.empty())
1381fe6060f1SDimitry Andric     return;
1382480093f4SDimitry Andric 
1383480093f4SDimitry Andric   std::vector<VecDesc>::const_iterator I =
1384480093f4SDimitry Andric       llvm::lower_bound(VectorDescs, ScalarF, compareWithScalarFnName);
1385c9157d92SDimitry Andric   while (I != VectorDescs.end() && StringRef(I->getScalarFnName()) == ScalarF) {
1386fe6060f1SDimitry Andric     ElementCount *VF =
1387c9157d92SDimitry Andric         I->getVectorizationFactor().isScalable() ? &ScalableVF : &FixedVF;
1388c9157d92SDimitry Andric     if (ElementCount::isKnownGT(I->getVectorizationFactor(), *VF))
1389c9157d92SDimitry Andric       *VF = I->getVectorizationFactor();
1390480093f4SDimitry Andric     ++I;
1391480093f4SDimitry Andric   }
1392480093f4SDimitry Andric }
1393