| //===-- AMDGPULibFunc.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 _AMDGPU_LIBFUNC_H_ |
| #define _AMDGPU_LIBFUNC_H_ |
| |
| #include "llvm/ADT/StringRef.h" |
| |
| namespace llvm { |
| |
| class FunctionCallee; |
| class FunctionType; |
| class Function; |
| class Module; |
| |
| class AMDGPULibFuncBase { |
| public: |
| enum EFuncId { |
| EI_NONE, |
| |
| // IMPORTANT: enums below should go in ascending by 1 value order |
| // because they are used as indexes in the mangling rules table. |
| // don't use explicit value assignment. |
| // |
| // There are two types of library functions: those with mangled |
| // name and those with unmangled name. The enums for the library |
| // functions with mangled name are defined before enums for the |
| // library functions with unmangled name. The enum for the last |
| // library function with mangled name is EI_LAST_MANGLED. |
| // |
| // Library functions with mangled name. |
| EI_ABS, |
| EI_ABS_DIFF, |
| EI_ACOS, |
| EI_ACOSH, |
| EI_ACOSPI, |
| EI_ADD_SAT, |
| EI_ALL, |
| EI_ANY, |
| EI_ASIN, |
| EI_ASINH, |
| EI_ASINPI, |
| EI_ASYNC_WORK_GROUP_COPY, |
| EI_ASYNC_WORK_GROUP_STRIDED_COPY, |
| EI_ATAN, |
| EI_ATAN2, |
| EI_ATAN2PI, |
| EI_ATANH, |
| EI_ATANPI, |
| EI_ATOMIC_ADD, |
| EI_ATOMIC_AND, |
| EI_ATOMIC_CMPXCHG, |
| EI_ATOMIC_DEC, |
| EI_ATOMIC_INC, |
| EI_ATOMIC_MAX, |
| EI_ATOMIC_MIN, |
| EI_ATOMIC_OR, |
| EI_ATOMIC_SUB, |
| EI_ATOMIC_XCHG, |
| EI_ATOMIC_XOR, |
| EI_BITSELECT, |
| EI_CBRT, |
| EI_CEIL, |
| EI_CLAMP, |
| EI_CLZ, |
| EI_COMMIT_READ_PIPE, |
| EI_COMMIT_WRITE_PIPE, |
| EI_COPYSIGN, |
| EI_COS, |
| EI_COSH, |
| EI_COSPI, |
| EI_CROSS, |
| EI_CTZ, |
| EI_DEGREES, |
| EI_DISTANCE, |
| EI_DIVIDE, |
| EI_DOT, |
| EI_ERF, |
| EI_ERFC, |
| EI_EXP, |
| EI_EXP10, |
| EI_EXP2, |
| EI_EXPM1, |
| EI_FABS, |
| EI_FAST_DISTANCE, |
| EI_FAST_LENGTH, |
| EI_FAST_NORMALIZE, |
| EI_FDIM, |
| EI_FLOOR, |
| EI_FMA, |
| EI_FMAX, |
| EI_FMIN, |
| EI_FMOD, |
| EI_FRACT, |
| EI_FREXP, |
| EI_GET_IMAGE_ARRAY_SIZE, |
| EI_GET_IMAGE_CHANNEL_DATA_TYPE, |
| EI_GET_IMAGE_CHANNEL_ORDER, |
| EI_GET_IMAGE_DIM, |
| EI_GET_IMAGE_HEIGHT, |
| EI_GET_IMAGE_WIDTH, |
| EI_GET_PIPE_MAX_PACKETS, |
| EI_GET_PIPE_NUM_PACKETS, |
| EI_HADD, |
| EI_HYPOT, |
| EI_ILOGB, |
| EI_ISEQUAL, |
| EI_ISFINITE, |
| EI_ISGREATER, |
| EI_ISGREATEREQUAL, |
| EI_ISINF, |
| EI_ISLESS, |
| EI_ISLESSEQUAL, |
| EI_ISLESSGREATER, |
| EI_ISNAN, |
| EI_ISNORMAL, |
| EI_ISNOTEQUAL, |
| EI_ISORDERED, |
| EI_ISUNORDERED, |
| EI_LDEXP, |
| EI_LENGTH, |
| EI_LGAMMA, |
| EI_LGAMMA_R, |
| EI_LOG, |
| EI_LOG10, |
| EI_LOG1P, |
| EI_LOG2, |
| EI_LOGB, |
| EI_MAD, |
| EI_MAD24, |
| EI_MAD_HI, |
| EI_MAD_SAT, |
| EI_MAX, |
| EI_MAXMAG, |
| EI_MIN, |
| EI_MINMAG, |
| EI_MIX, |
| EI_MODF, |
| EI_MUL24, |
| EI_MUL_HI, |
| EI_NAN, |
| EI_NEXTAFTER, |
| EI_NORMALIZE, |
| EI_POPCOUNT, |
| EI_POW, |
| EI_POWN, |
| EI_POWR, |
| EI_PREFETCH, |
| EI_RADIANS, |
| EI_RECIP, |
| EI_REMAINDER, |
| EI_REMQUO, |
| EI_RESERVE_READ_PIPE, |
| EI_RESERVE_WRITE_PIPE, |
| EI_RHADD, |
| EI_RINT, |
| EI_ROOTN, |
| EI_ROTATE, |
| EI_ROUND, |
| EI_RSQRT, |
| EI_SELECT, |
| EI_SHUFFLE, |
| EI_SHUFFLE2, |
| EI_SIGN, |
| EI_SIGNBIT, |
| EI_SIN, |
| EI_SINCOS, |
| EI_SINH, |
| EI_SINPI, |
| EI_SMOOTHSTEP, |
| EI_SQRT, |
| EI_STEP, |
| EI_SUB_GROUP_BROADCAST, |
| EI_SUB_GROUP_COMMIT_READ_PIPE, |
| EI_SUB_GROUP_COMMIT_WRITE_PIPE, |
| EI_SUB_GROUP_REDUCE_ADD, |
| EI_SUB_GROUP_REDUCE_MAX, |
| EI_SUB_GROUP_REDUCE_MIN, |
| EI_SUB_GROUP_RESERVE_READ_PIPE, |
| EI_SUB_GROUP_RESERVE_WRITE_PIPE, |
| EI_SUB_GROUP_SCAN_EXCLUSIVE_ADD, |
| EI_SUB_GROUP_SCAN_EXCLUSIVE_MAX, |
| EI_SUB_GROUP_SCAN_EXCLUSIVE_MIN, |
| EI_SUB_GROUP_SCAN_INCLUSIVE_ADD, |
| EI_SUB_GROUP_SCAN_INCLUSIVE_MAX, |
| EI_SUB_GROUP_SCAN_INCLUSIVE_MIN, |
| EI_SUB_SAT, |
| EI_TAN, |
| EI_TANH, |
| EI_TANPI, |
| EI_TGAMMA, |
| EI_TRUNC, |
| EI_UPSAMPLE, |
| EI_VEC_STEP, |
| EI_VSTORE, |
| EI_VSTORE16, |
| EI_VSTORE2, |
| EI_VSTORE3, |
| EI_VSTORE4, |
| EI_VSTORE8, |
| EI_WORK_GROUP_COMMIT_READ_PIPE, |
| EI_WORK_GROUP_COMMIT_WRITE_PIPE, |
| EI_WORK_GROUP_REDUCE_ADD, |
| EI_WORK_GROUP_REDUCE_MAX, |
| EI_WORK_GROUP_REDUCE_MIN, |
| EI_WORK_GROUP_RESERVE_READ_PIPE, |
| EI_WORK_GROUP_RESERVE_WRITE_PIPE, |
| EI_WORK_GROUP_SCAN_EXCLUSIVE_ADD, |
| EI_WORK_GROUP_SCAN_EXCLUSIVE_MAX, |
| EI_WORK_GROUP_SCAN_EXCLUSIVE_MIN, |
| EI_WORK_GROUP_SCAN_INCLUSIVE_ADD, |
| EI_WORK_GROUP_SCAN_INCLUSIVE_MAX, |
| EI_WORK_GROUP_SCAN_INCLUSIVE_MIN, |
| EI_WRITE_IMAGEF, |
| EI_WRITE_IMAGEI, |
| EI_WRITE_IMAGEUI, |
| EI_NCOS, |
| EI_NEXP2, |
| EI_NFMA, |
| EI_NLOG2, |
| EI_NRCP, |
| EI_NRSQRT, |
| EI_NSIN, |
| EI_NSQRT, |
| EI_FTZ, |
| EI_FLDEXP, |
| EI_CLASS, |
| EI_RCBRT, |
| EI_LAST_MANGLED = |
| EI_RCBRT, /* The last library function with mangled name */ |
| |
| // Library functions with unmangled name. |
| EI_READ_PIPE_2, |
| EI_READ_PIPE_4, |
| EI_WRITE_PIPE_2, |
| EI_WRITE_PIPE_4, |
| |
| EX_INTRINSICS_COUNT |
| }; |
| |
| enum ENamePrefix { |
| NOPFX, |
| NATIVE, |
| HALF |
| }; |
| |
| enum EType { |
| B8 = 1, |
| B16 = 2, |
| B32 = 3, |
| B64 = 4, |
| SIZE_MASK = 7, |
| FLOAT = 0x10, |
| INT = 0x20, |
| UINT = 0x30, |
| BASE_TYPE_MASK = 0x30, |
| U8 = UINT | B8, |
| U16 = UINT | B16, |
| U32 = UINT | B32, |
| U64 = UINT | B64, |
| I8 = INT | B8, |
| I16 = INT | B16, |
| I32 = INT | B32, |
| I64 = INT | B64, |
| F16 = FLOAT | B16, |
| F32 = FLOAT | B32, |
| F64 = FLOAT | B64, |
| IMG1DA = 0x80, |
| IMG1DB, |
| IMG2DA, |
| IMG1D, |
| IMG2D, |
| IMG3D, |
| SAMPLER, |
| EVENT, |
| DUMMY |
| }; |
| |
| enum EPtrKind { |
| BYVALUE = 0, |
| ADDR_SPACE = 0xF, // Address space takes value 0x1 ~ 0xF. |
| CONST = 0x10, |
| VOLATILE = 0x20 |
| }; |
| |
| struct Param { |
| unsigned char ArgType; |
| unsigned char VectorSize; |
| unsigned char PtrKind; |
| |
| unsigned char Reserved; |
| |
| void reset() { |
| ArgType = 0; |
| VectorSize = 1; |
| PtrKind = 0; |
| } |
| Param() { reset(); } |
| |
| template <typename Stream> |
| void mangleItanium(Stream& os); |
| }; |
| static bool isMangled(EFuncId Id) { |
| return static_cast<unsigned>(Id) <= static_cast<unsigned>(EI_LAST_MANGLED); |
| } |
| |
| static unsigned getEPtrKindFromAddrSpace(unsigned AS) { |
| assert(((AS + 1) & ~ADDR_SPACE) == 0); |
| return AS + 1; |
| } |
| |
| static unsigned getAddrSpaceFromEPtrKind(unsigned Kind) { |
| Kind = Kind & ADDR_SPACE; |
| assert(Kind >= 1); |
| return Kind - 1; |
| } |
| }; |
| |
| class AMDGPULibFuncImpl : public AMDGPULibFuncBase { |
| public: |
| AMDGPULibFuncImpl() {} |
| virtual ~AMDGPULibFuncImpl() {} |
| |
| /// Get unmangled name for mangled library function and name for unmangled |
| /// library function. |
| virtual std::string getName() const = 0; |
| virtual unsigned getNumArgs() const = 0; |
| EFuncId getId() const { return FuncId; } |
| ENamePrefix getPrefix() const { return FKind; } |
| |
| bool isMangled() const { return AMDGPULibFuncBase::isMangled(FuncId); } |
| |
| void setId(EFuncId id) { FuncId = id; } |
| virtual bool parseFuncName(StringRef &mangledName) = 0; |
| |
| /// \return The mangled function name for mangled library functions |
| /// and unmangled function name for unmangled library functions. |
| virtual std::string mangle() const = 0; |
| |
| void setName(StringRef N) { Name = std::string(N); } |
| void setPrefix(ENamePrefix pfx) { FKind = pfx; } |
| |
| virtual FunctionType *getFunctionType(Module &M) const = 0; |
| |
| protected: |
| EFuncId FuncId; |
| std::string Name; |
| ENamePrefix FKind; |
| }; |
| |
| /// Wrapper class for AMDGPULIbFuncImpl |
| class AMDGPULibFunc : public AMDGPULibFuncBase { |
| public: |
| explicit AMDGPULibFunc() : Impl(std::unique_ptr<AMDGPULibFuncImpl>()) {} |
| AMDGPULibFunc(const AMDGPULibFunc &F); |
| /// Clone a mangled library func with the Id \p Id and argument info from \p |
| /// CopyFrom. |
| explicit AMDGPULibFunc(EFuncId Id, const AMDGPULibFunc &CopyFrom); |
| /// Construct an unmangled library function on the fly. |
| explicit AMDGPULibFunc(StringRef FName, FunctionType *FT); |
| |
| AMDGPULibFunc &operator=(const AMDGPULibFunc &F); |
| |
| /// Get unmangled name for mangled library function and name for unmangled |
| /// library function. |
| std::string getName() const { return Impl->getName(); } |
| unsigned getNumArgs() const { return Impl->getNumArgs(); } |
| EFuncId getId() const { return Impl->getId(); } |
| ENamePrefix getPrefix() const { return Impl->getPrefix(); } |
| /// Get leading parameters for mangled lib functions. |
| Param *getLeads(); |
| const Param *getLeads() const; |
| |
| bool isMangled() const { return Impl->isMangled(); } |
| void setId(EFuncId Id) { Impl->setId(Id); } |
| bool parseFuncName(StringRef &MangledName) { |
| return Impl->parseFuncName(MangledName); |
| } |
| |
| /// \return The mangled function name for mangled library functions |
| /// and unmangled function name for unmangled library functions. |
| std::string mangle() const { return Impl->mangle(); } |
| |
| void setName(StringRef N) { Impl->setName(N); } |
| void setPrefix(ENamePrefix PFX) { Impl->setPrefix(PFX); } |
| |
| FunctionType *getFunctionType(Module &M) const { |
| return Impl->getFunctionType(M); |
| } |
| static Function *getFunction(llvm::Module *M, const AMDGPULibFunc &fInfo); |
| |
| static FunctionCallee getOrInsertFunction(llvm::Module *M, |
| const AMDGPULibFunc &fInfo); |
| static bool parse(StringRef MangledName, AMDGPULibFunc &Ptr); |
| |
| private: |
| /// Initialize as a mangled library function. |
| void initMangled(); |
| std::unique_ptr<AMDGPULibFuncImpl> Impl; |
| }; |
| |
| class AMDGPUMangledLibFunc : public AMDGPULibFuncImpl { |
| public: |
| Param Leads[2]; |
| |
| explicit AMDGPUMangledLibFunc(); |
| explicit AMDGPUMangledLibFunc(EFuncId id, |
| const AMDGPUMangledLibFunc ©From); |
| |
| std::string getName() const override; |
| unsigned getNumArgs() const override; |
| FunctionType *getFunctionType(Module &M) const override; |
| static StringRef getUnmangledName(StringRef MangledName); |
| |
| bool parseFuncName(StringRef &mangledName) override; |
| |
| // Methods for support type inquiry through isa, cast, and dyn_cast: |
| static bool classof(const AMDGPULibFuncImpl *F) { return F->isMangled(); } |
| |
| std::string mangle() const override; |
| |
| private: |
| std::string mangleNameItanium() const; |
| |
| std::string mangleName(StringRef Name) const; |
| bool parseUnmangledName(StringRef MangledName); |
| |
| template <typename Stream> void writeName(Stream &OS) const; |
| }; |
| |
| class AMDGPUUnmangledLibFunc : public AMDGPULibFuncImpl { |
| FunctionType *FuncTy; |
| |
| public: |
| explicit AMDGPUUnmangledLibFunc(); |
| explicit AMDGPUUnmangledLibFunc(StringRef FName, FunctionType *FT) { |
| Name = std::string(FName); |
| FuncTy = FT; |
| } |
| std::string getName() const override { return Name; } |
| unsigned getNumArgs() const override; |
| FunctionType *getFunctionType(Module &M) const override { return FuncTy; } |
| |
| bool parseFuncName(StringRef &Name) override; |
| |
| // Methods for support type inquiry through isa, cast, and dyn_cast: |
| static bool classof(const AMDGPULibFuncImpl *F) { return !F->isMangled(); } |
| |
| std::string mangle() const override { return Name; } |
| |
| void setFunctionType(FunctionType *FT) { FuncTy = FT; } |
| }; |
| } |
| #endif // _AMDGPU_LIBFUNC_H_ |