CGOpenCLRuntime.cpp 6.7 KB

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