//===- LibcallLoweringInfo.h ------------------------------------*- 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 // //===----------------------------------------------------------------------===// #ifndef LLVM_CODEGEN_LIBCALLLOWERINGINFO_H #define LLVM_CODEGEN_LIBCALLLOWERINGINFO_H #include "llvm/ADT/DenseMap.h" #include "llvm/IR/RuntimeLibcalls.h" #include "llvm/Pass.h" namespace llvm { class TargetSubtargetInfo; class TargetMachine; /// Tracks which library functions to use for a particular subtarget. class LibcallLoweringInfo { private: const RTLIB::RuntimeLibcallsInfo &RTLCI; /// Stores the implementation choice for each each libcall. RTLIB::LibcallImpl LibcallImpls[RTLIB::UNKNOWN_LIBCALL + 1] = { RTLIB::Unsupported}; public: LLVM_ABI LibcallLoweringInfo(const RTLIB::RuntimeLibcallsInfo &RTLCI, const TargetSubtargetInfo &Subtarget); const RTLIB::RuntimeLibcallsInfo &getRuntimeLibcallsInfo() const { return RTLCI; } /// Get the libcall routine name for the specified libcall. // FIXME: This should be removed. Only LibcallImpl should have a name. LLVM_ABI const char *getLibcallName(RTLIB::Libcall Call) const { // FIXME: Return StringRef return RTLIB::RuntimeLibcallsInfo::getLibcallImplName(LibcallImpls[Call]) .data(); } /// Return the lowering's selection of implementation call for \p Call LLVM_ABI RTLIB::LibcallImpl getLibcallImpl(RTLIB::Libcall Call) const { return LibcallImpls[Call]; } /// Rename the default libcall routine name for the specified libcall. LLVM_ABI void setLibcallImpl(RTLIB::Libcall Call, RTLIB::LibcallImpl Impl) { LibcallImpls[Call] = Impl; } // FIXME: Remove this wrapper in favor of directly using // getLibcallImplCallingConv LLVM_ABI CallingConv::ID getLibcallCallingConv(RTLIB::Libcall Call) const { return RTLCI.LibcallImplCallingConvs[LibcallImpls[Call]]; } /// Get the CallingConv that should be used for the specified libcall. LLVM_ABI CallingConv::ID getLibcallImplCallingConv(RTLIB::LibcallImpl Call) const { return RTLCI.LibcallImplCallingConvs[Call]; } /// Return a function impl compatible with RTLIB::MEMCPY, or /// RTLIB::Unsupported if fully unsupported. RTLIB::LibcallImpl getMemcpyImpl() const { RTLIB::LibcallImpl Memcpy = getLibcallImpl(RTLIB::MEMCPY); if (Memcpy == RTLIB::Unsupported) { // Fallback to memmove if memcpy isn't available. return getLibcallImpl(RTLIB::MEMMOVE); } return Memcpy; } }; /// Record a mapping from subtarget to LibcallLoweringInfo. class LibcallLoweringModuleAnalysisResult { private: using LibcallLoweringMap = DenseMap; mutable LibcallLoweringMap LoweringMap; const RTLIB::RuntimeLibcallsInfo *RTLCI = nullptr; public: LibcallLoweringModuleAnalysisResult() = default; LibcallLoweringModuleAnalysisResult(RTLIB::RuntimeLibcallsInfo &RTLCI) : RTLCI(&RTLCI) {} void init(const RTLIB::RuntimeLibcallsInfo *RT) { RTLCI = RT; } void clear() { RTLCI = nullptr; LoweringMap.clear(); } LLVM_ABI bool invalidate(Module &, const PreservedAnalyses &, ModuleAnalysisManager::Invalidator &); const LibcallLoweringInfo & getLibcallLowering(const TargetSubtargetInfo &Subtarget) const { return LoweringMap.try_emplace(&Subtarget, *RTLCI, Subtarget).first->second; } }; class LibcallLoweringModuleAnalysis : public AnalysisInfoMixin { private: friend AnalysisInfoMixin; LLVM_ABI static AnalysisKey Key; LibcallLoweringModuleAnalysisResult LibcallLoweringMap; public: using Result = LibcallLoweringModuleAnalysisResult; LLVM_ABI Result run(Module &M, ModuleAnalysisManager &); }; class LLVM_ABI LibcallLoweringInfoWrapper : public ImmutablePass { LibcallLoweringModuleAnalysisResult Result; public: static char ID; LibcallLoweringInfoWrapper(); const LibcallLoweringInfo & getLibcallLowering(const TargetSubtargetInfo &Subtarget) const { return Result.getLibcallLowering(Subtarget); } const LibcallLoweringModuleAnalysisResult &getResult() const { return Result; } bool doInitialization(Module &M) override; void getAnalysisUsage(AnalysisUsage &AU) const override; void releaseMemory() override; }; } // end namespace llvm #endif // LLVM_CODEGEN_LIBCALLLOWERINGINFO_H