CGOpenCLRuntime.cpp 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. //===----- CGOpenCLRuntime.cpp - Interface to OpenCL Runtimes -------------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // This provides an abstract class for OpenCL code generation. Concrete
  10. // subclasses of this implement code generation for specific OpenCL
  11. // runtime libraries.
  12. //
  13. //===----------------------------------------------------------------------===//
  14. #include "CGOpenCLRuntime.h"
  15. #include "CodeGenFunction.h"
  16. #include "TargetInfo.h"
  17. #include "clang/CodeGen/ConstantInitBuilder.h"
  18. #include "llvm/IR/DerivedTypes.h"
  19. #include "llvm/IR/GlobalValue.h"
  20. #include <assert.h>
  21. using namespace clang;
  22. using namespace CodeGen;
  23. CGOpenCLRuntime::~CGOpenCLRuntime() {}
  24. void CGOpenCLRuntime::EmitWorkGroupLocalVarDecl(CodeGenFunction &CGF,
  25. const VarDecl &D) {
  26. return CGF.EmitStaticVarDecl(D, llvm::GlobalValue::InternalLinkage);
  27. }
  28. llvm::Type *CGOpenCLRuntime::convertOpenCLSpecificType(const Type *T) {
  29. assert(T->isOpenCLSpecificType() &&
  30. "Not an OpenCL specific type!");
  31. switch (cast<BuiltinType>(T)->getKind()) {
  32. default:
  33. llvm_unreachable("Unexpected opencl builtin type!");
  34. return nullptr;
  35. #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
  36. case BuiltinType::Id: \
  37. return getPointerType(T, "opencl." #ImgType "_" #Suffix "_t");
  38. #include "clang/Basic/OpenCLImageTypes.def"
  39. case BuiltinType::OCLSampler:
  40. return getSamplerType(T);
  41. case BuiltinType::OCLEvent:
  42. return getPointerType(T, "opencl.event_t");
  43. case BuiltinType::OCLClkEvent:
  44. return getPointerType(T, "opencl.clk_event_t");
  45. case BuiltinType::OCLQueue:
  46. return getPointerType(T, "opencl.queue_t");
  47. case BuiltinType::OCLReserveID:
  48. return getPointerType(T, "opencl.reserve_id_t");
  49. #define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
  50. case BuiltinType::Id: \
  51. return getPointerType(T, "opencl." #ExtType);
  52. #include "clang/Basic/OpenCLExtensionTypes.def"
  53. }
  54. }
  55. llvm::PointerType *CGOpenCLRuntime::getPointerType(const Type *T,
  56. StringRef Name) {
  57. auto I = CachedTys.find(Name);
  58. if (I != CachedTys.end())
  59. return I->second;
  60. llvm::LLVMContext &Ctx = CGM.getLLVMContext();
  61. uint32_t AddrSpc = CGM.getContext().getTargetAddressSpace(
  62. CGM.getContext().getOpenCLTypeAddrSpace(T));
  63. auto *PTy =
  64. llvm::PointerType::get(llvm::StructType::create(Ctx, Name), AddrSpc);
  65. CachedTys[Name] = PTy;
  66. return PTy;
  67. }
  68. llvm::Type *CGOpenCLRuntime::getPipeType(const PipeType *T) {
  69. if (T->isReadOnly())
  70. return getPipeType(T, "opencl.pipe_ro_t", PipeROTy);
  71. else
  72. return getPipeType(T, "opencl.pipe_wo_t", PipeWOTy);
  73. }
  74. llvm::Type *CGOpenCLRuntime::getPipeType(const PipeType *T, StringRef Name,
  75. llvm::Type *&PipeTy) {
  76. if (!PipeTy)
  77. PipeTy = llvm::PointerType::get(llvm::StructType::create(
  78. CGM.getLLVMContext(), Name),
  79. CGM.getContext().getTargetAddressSpace(
  80. CGM.getContext().getOpenCLTypeAddrSpace(T)));
  81. return PipeTy;
  82. }
  83. llvm::PointerType *CGOpenCLRuntime::getSamplerType(const Type *T) {
  84. if (!SamplerTy)
  85. SamplerTy = llvm::PointerType::get(llvm::StructType::create(
  86. CGM.getLLVMContext(), "opencl.sampler_t"),
  87. CGM.getContext().getTargetAddressSpace(
  88. CGM.getContext().getOpenCLTypeAddrSpace(T)));
  89. return SamplerTy;
  90. }
  91. llvm::Value *CGOpenCLRuntime::getPipeElemSize(const Expr *PipeArg) {
  92. const PipeType *PipeTy = PipeArg->getType()->castAs<PipeType>();
  93. // The type of the last (implicit) argument to be passed.
  94. llvm::Type *Int32Ty = llvm::IntegerType::getInt32Ty(CGM.getLLVMContext());
  95. unsigned TypeSize = CGM.getContext()
  96. .getTypeSizeInChars(PipeTy->getElementType())
  97. .getQuantity();
  98. return llvm::ConstantInt::get(Int32Ty, TypeSize, false);
  99. }
  100. llvm::Value *CGOpenCLRuntime::getPipeElemAlign(const Expr *PipeArg) {
  101. const PipeType *PipeTy = PipeArg->getType()->castAs<PipeType>();
  102. // The type of the last (implicit) argument to be passed.
  103. llvm::Type *Int32Ty = llvm::IntegerType::getInt32Ty(CGM.getLLVMContext());
  104. unsigned TypeSize = CGM.getContext()
  105. .getTypeAlignInChars(PipeTy->getElementType())
  106. .getQuantity();
  107. return llvm::ConstantInt::get(Int32Ty, TypeSize, false);
  108. }
  109. llvm::PointerType *CGOpenCLRuntime::getGenericVoidPointerType() {
  110. assert(CGM.getLangOpts().OpenCL);
  111. return llvm::IntegerType::getInt8PtrTy(
  112. CGM.getLLVMContext(),
  113. CGM.getContext().getTargetAddressSpace(LangAS::opencl_generic));
  114. }
  115. // Get the block literal from an expression derived from the block expression.
  116. // OpenCL v2.0 s6.12.5:
  117. // Block variable declarations are implicitly qualified with const. Therefore
  118. // all block variables must be initialized at declaration time and may not be
  119. // reassigned.
  120. static const BlockExpr *getBlockExpr(const Expr *E) {
  121. const Expr *Prev = nullptr; // to make sure we do not stuck in infinite loop.
  122. while(!isa<BlockExpr>(E) && E != Prev) {
  123. Prev = E;
  124. E = E->IgnoreCasts();
  125. if (auto DR = dyn_cast<DeclRefExpr>(E)) {
  126. E = cast<VarDecl>(DR->getDecl())->getInit();
  127. }
  128. }
  129. return cast<BlockExpr>(E);
  130. }
  131. /// Record emitted llvm invoke function and llvm block literal for the
  132. /// corresponding block expression.
  133. void CGOpenCLRuntime::recordBlockInfo(const BlockExpr *E,
  134. llvm::Function *InvokeF,
  135. llvm::Value *Block, llvm::Type *BlockTy) {
  136. assert(EnqueuedBlockMap.find(E) == EnqueuedBlockMap.end() &&
  137. "Block expression emitted twice");
  138. assert(isa<llvm::Function>(InvokeF) && "Invalid invoke function");
  139. assert(Block->getType()->isPointerTy() && "Invalid block literal type");
  140. EnqueuedBlockMap[E].InvokeFunc = InvokeF;
  141. EnqueuedBlockMap[E].BlockArg = Block;
  142. EnqueuedBlockMap[E].BlockTy = BlockTy;
  143. EnqueuedBlockMap[E].Kernel = nullptr;
  144. }
  145. llvm::Function *CGOpenCLRuntime::getInvokeFunction(const Expr *E) {
  146. return EnqueuedBlockMap[getBlockExpr(E)].InvokeFunc;
  147. }
  148. CGOpenCLRuntime::EnqueuedBlockInfo
  149. CGOpenCLRuntime::emitOpenCLEnqueuedBlock(CodeGenFunction &CGF, const Expr *E) {
  150. CGF.EmitScalarExpr(E);
  151. // The block literal may be assigned to a const variable. Chasing down
  152. // to get the block literal.
  153. const BlockExpr *Block = getBlockExpr(E);
  154. assert(EnqueuedBlockMap.find(Block) != EnqueuedBlockMap.end() &&
  155. "Block expression not emitted");
  156. // Do not emit the block wrapper again if it has been emitted.
  157. if (EnqueuedBlockMap[Block].Kernel) {
  158. return EnqueuedBlockMap[Block];
  159. }
  160. auto *F = CGF.getTargetHooks().createEnqueuedBlockKernel(
  161. CGF, EnqueuedBlockMap[Block].InvokeFunc, EnqueuedBlockMap[Block].BlockTy);
  162. // The common part of the post-processing of the kernel goes here.
  163. F->addFnAttr(llvm::Attribute::NoUnwind);
  164. F->setCallingConv(
  165. CGF.getTypes().ClangCallConvToLLVMCallConv(CallingConv::CC_OpenCLKernel));
  166. EnqueuedBlockMap[Block].Kernel = F;
  167. return EnqueuedBlockMap[Block];
  168. }