|  | //===-- AMDGPULibFunc.h ---------------------------------------------------===// | 
|  | // | 
|  | //                     The LLVM Compiler Infrastructure | 
|  | // | 
|  | // This file is distributed under the University of Illinois Open Source | 
|  | // License. See LICENSE.TXT for details. | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | #ifndef _AMDGPU_LIBFUNC_H_ | 
|  | #define _AMDGPU_LIBFUNC_H_ | 
|  |  | 
|  | #include "llvm/ADT/StringRef.h" | 
|  |  | 
|  | namespace llvm { | 
|  |  | 
|  | 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 = 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 Function *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 = 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_ |