Files
gps/tools/local/circt/include/llvm/IR/RuntimeLibcalls.h
T
2026-07-12 11:01:51 +03:00

260 lines
9.2 KiB
C++

//===- 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<RTLIB::Libcall> {
static constexpr bool is_iterable = true;
};
template <> struct enum_iteration_traits<RTLIB::LibcallImpl> {
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<RTLIB::Libcall>(0), RTLIB::UNKNOWN_LIBCALL);
}
static inline auto libcall_impls() {
return enum_seq(static_cast<RTLIB::LibcallImpl>(1),
static_cast<RTLIB::LibcallImpl>(RTLIB::NumLibcallImpls));
}
/// Manage a bitset representing the list of available libcalls for a module.
class LibcallImplBitset : public Bitset<RTLIB::NumLibcallImpls> {
public:
constexpr LibcallImplBitset() = default;
constexpr LibcallImplBitset(
const std::array<uint64_t, (RTLIB::NumLibcallImpls + 63) / 64> &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);
LLVM_ABI 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.
static inline iota_range<RTLIB::LibcallImpl>
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.
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.
LLVM_ABI std::pair<FunctionType *, AttributeList>
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.
LLVM_ABI static bool hasVectorMaskArgument(RTLIB::LibcallImpl Impl);
private:
LLVM_ABI static iota_range<RTLIB::LibcallImpl>
lookupLibcallImplNameImpl(StringRef Name);
static_assert(static_cast<int>(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<RTLIB::LibcallImpl>
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