//===- RuntimeLibcalls.h - Interface for runtime libcalls -------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This file implements a common interface to work with library calls into a // runtime that may be emitted by a given backend. // // FIXME: This should probably move to Analysis // //===----------------------------------------------------------------------===// #ifndef LLVM_IR_RUNTIME_LIBCALLS_H #define LLVM_IR_RUNTIME_LIBCALLS_H #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/Bitset.h" #include "llvm/ADT/Sequence.h" #include "llvm/ADT/StringTable.h" #include "llvm/IR/CallingConv.h" #include "llvm/IR/InstrTypes.h" #include "llvm/IR/PassManager.h" #include "llvm/IR/SystemLibraries.h" #include "llvm/Support/AtomicOrdering.h" #include "llvm/Support/CodeGen.h" #include "llvm/Support/Compiler.h" #include "llvm/TargetParser/Triple.h" /// TableGen will produce 2 enums, RTLIB::Libcall and /// RTLIB::LibcallImpl. RTLIB::Libcall describes abstract functionality the /// compiler may choose to access, RTLIB::LibcallImpl describes a particular ABI /// implementation, which includes a name and type signature. #define GET_RUNTIME_LIBCALL_ENUM #include "llvm/IR/RuntimeLibcalls.inc" namespace llvm { template <> struct enum_iteration_traits { static constexpr bool is_iterable = true; }; template <> struct enum_iteration_traits { static constexpr bool is_iterable = true; }; class LibcallLoweringInfo; namespace RTLIB { // Return an iterator over all Libcall values. static inline auto libcalls() { return enum_seq(static_cast(0), RTLIB::UNKNOWN_LIBCALL); } static inline auto libcall_impls() { return enum_seq(static_cast(1), static_cast(RTLIB::NumLibcallImpls)); } /// Manage a bitset representing the list of available libcalls for a module. class LibcallImplBitset : public Bitset { public: constexpr LibcallImplBitset() = default; constexpr LibcallImplBitset( const std::array &Src) : Bitset(Src) {} }; /// A simple container for information about the supported runtime calls. struct RuntimeLibcallsInfo { private: /// Bitset of libcalls a module may emit a call to. LibcallImplBitset AvailableLibcallImpls; public: friend class llvm::LibcallLoweringInfo; RuntimeLibcallsInfo() = default; LLVM_ABI explicit RuntimeLibcallsInfo( const Triple &TT, ExceptionHandling ExceptionModel = ExceptionHandling::None, FloatABI::ABIType FloatABI = FloatABI::Default, EABI EABIVersion = EABI::Default, StringRef ABIName = "", VectorLibrary VecLib = VectorLibrary::NoLibrary); explicit RuntimeLibcallsInfo(const Module &M); LLVM_ABI bool invalidate(Module &M, const PreservedAnalyses &PA, ModuleAnalysisManager::Invalidator &); /// Get the libcall routine name for the specified libcall implementation. static StringRef getLibcallImplName(RTLIB::LibcallImpl CallImpl) { if (CallImpl == RTLIB::Unsupported) return StringRef(); return StringRef(RuntimeLibcallImplNameTable.getCString( RuntimeLibcallNameOffsetTable[CallImpl]), RuntimeLibcallNameSizeTable[CallImpl]); } /// Set the CallingConv that should be used for the specified libcall /// implementation void setLibcallImplCallingConv(RTLIB::LibcallImpl Call, CallingConv::ID CC) { LibcallImplCallingConvs[Call] = CC; } /// Get the CallingConv that should be used for the specified libcall. CallingConv::ID getLibcallImplCallingConv(RTLIB::LibcallImpl Call) const { return LibcallImplCallingConvs[Call]; } /// Return the libcall provided by \p Impl static RTLIB::Libcall getLibcallFromImpl(RTLIB::LibcallImpl Impl) { return ImplToLibcall[Impl]; } unsigned getNumAvailableLibcallImpls() const { return AvailableLibcallImpls.count(); } bool isAvailable(RTLIB::LibcallImpl Impl) const { return AvailableLibcallImpls.test(Impl); } void setAvailable(RTLIB::LibcallImpl Impl) { AvailableLibcallImpls.set(Impl); } /// Check if a function name is a recognized runtime call of any kind. This /// does not consider if this call is available for any current compilation, /// just that it is a known call somewhere. This returns the set of all /// LibcallImpls which match the name; multiple implementations with the same /// name may exist but differ in interpretation based on the target context. /// /// Generated by tablegen. LLVM_ABI static inline iota_range lookupLibcallImplName(StringRef Name){ // Inlining the early exit on the string name appears to be worthwhile when // querying a real set of symbols #define GET_LOOKUP_LIBCALL_IMPL_NAME_BODY #include "llvm/IR/RuntimeLibcalls.inc" } /// Check if this is valid libcall for the current module, otherwise /// RTLIB::Unsupported. LLVM_ABI RTLIB::LibcallImpl getSupportedLibcallImpl(StringRef FuncName) const { for (RTLIB::LibcallImpl Impl : lookupLibcallImplName(FuncName)) { if (isAvailable(Impl)) return Impl; } return RTLIB::Unsupported; } /// \returns the function type and attributes for the \p LibcallImpl, /// depending on the target \p TT. If the function has incomplete type /// information, return nullptr for the function type. std::pair getFunctionTy(LLVMContext &Ctx, const Triple &TT, const DataLayout &DL, RTLIB::LibcallImpl LibcallImpl) const; /// Returns true if the function has a vector mask argument, which is assumed /// to be the last argument. static bool hasVectorMaskArgument(RTLIB::LibcallImpl Impl); private: LLVM_ABI static iota_range lookupLibcallImplNameImpl(StringRef Name); static_assert(static_cast(CallingConv::C) == 0, "default calling conv should be encoded as 0"); /// Stores the CallingConv that should be used for each libcall /// implementation.; CallingConv::ID LibcallImplCallingConvs[RTLIB::NumLibcallImpls] = {}; /// Names of concrete implementations of runtime calls. e.g. __ashlsi3 for /// SHL_I32 LLVM_ABI static const char RuntimeLibcallImplNameTableStorage[]; LLVM_ABI static const StringTable RuntimeLibcallImplNameTable; LLVM_ABI static const uint16_t RuntimeLibcallNameOffsetTable[]; LLVM_ABI static const uint8_t RuntimeLibcallNameSizeTable[]; /// Map from a concrete LibcallImpl implementation to its RTLIB::Libcall kind. LLVM_ABI static const RTLIB::Libcall ImplToLibcall[RTLIB::NumLibcallImpls]; /// Utility function for tablegenerated lookup function. Return a range of /// enum values that apply for the function name at \p NameOffsetEntry with /// the value \p StrOffset. static inline iota_range libcallImplNameHit(uint16_t NameOffsetEntry, uint16_t StrOffset); static bool darwinHasSinCosStret(const Triple &TT) { if (!TT.isOSDarwin()) return false; // Don't bother with 32 bit x86. if (TT.getArch() == Triple::x86) return false; // Macos < 10.9 has no sincos_stret. if (TT.isMacOSX()) return !TT.isMacOSXVersionLT(10, 9) && TT.isArch64Bit(); // iOS < 7.0 has no sincos_stret. if (TT.isiOS()) return !TT.isOSVersionLT(7, 0); // Any other darwin such as WatchOS/TvOS is new enough. return true; } static bool darwinHasMemsetPattern(const Triple &TT) { // memset_pattern{4,8,16} is only available on iOS 3.0 and Mac OS X 10.5 and // later. All versions of watchOS support it. if (TT.isMacOSX()) return !TT.isMacOSXVersionLT(10, 5); if (TT.isiOS()) return !TT.isOSVersionLT(3, 0); return TT.isWatchOS(); } static bool hasAEABILibcalls(const Triple &TT) { return TT.isTargetAEABI() || TT.isTargetGNUAEABI() || TT.isTargetMuslAEABI() || TT.isOSFuchsia() || TT.isAndroid(); } LLVM_READONLY static bool isAAPCS_ABI(const Triple &TT, StringRef ABIName); static bool darwinHasExp10(const Triple &TT); /// Return true if the target has sincosf/sincos/sincosl functions static bool hasSinCos(const Triple &TT) { return TT.isGNUEnvironment() || TT.isOSFuchsia() || TT.isAndroid(); } static bool hasSinCos_f32_f64(const Triple &TT) { return hasSinCos(TT) || TT.isPS(); } /// Generated by tablegen. void setTargetRuntimeLibcallSets(const Triple &TT, ExceptionHandling ExceptionModel, FloatABI::ABIType FloatABI, EABI ABIType, StringRef ABIName); /// Set default libcall names. If a target wants to opt-out of a libcall it /// should be placed here. LLVM_ABI void initLibcalls(const Triple &TT, ExceptionHandling ExceptionModel, FloatABI::ABIType FloatABI, EABI ABIType, StringRef ABIName); }; } // namespace RTLIB } // namespace llvm #endif // LLVM_IR_RUNTIME_LIBCALLS_H