CGOpenCLRuntime.cpp 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  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. #define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
  60. case BuiltinType::Id: \
  61. return llvm::PointerType::get( \
  62. llvm::StructType::create(Ctx, "opencl." #ExtType), AddrSpc);
  63. #include "clang/Basic/OpenCLExtensionTypes.def"
  64. }
  65. }
  66. llvm::Type *CGOpenCLRuntime::getPipeType(const PipeType *T) {
  67. if (T->isReadOnly())
  68. return getPipeType(T, "opencl.pipe_ro_t", PipeROTy);
  69. else
  70. return getPipeType(T, "opencl.pipe_wo_t", PipeWOTy);
  71. }
  72. llvm::Type *CGOpenCLRuntime::getPipeType(const PipeType *T, StringRef Name,
  73. llvm::Type *&PipeTy) {
  74. if (!PipeTy)
  75. PipeTy = llvm::PointerType::get(llvm::StructType::create(
  76. CGM.getLLVMContext(), Name),
  77. CGM.getContext().getTargetAddressSpace(
  78. CGM.getContext().getOpenCLTypeAddrSpace(T)));
  79. return PipeTy;
  80. }
  81. llvm::PointerType *CGOpenCLRuntime::getSamplerType(const Type *T) {
  82. if (!SamplerTy)
  83. SamplerTy = llvm::PointerType::get(llvm::StructType::create(
  84. CGM.getLLVMContext(), "opencl.sampler_t"),
  85. CGM.getContext().getTargetAddressSpace(
  86. CGM.getContext().getOpenCLTypeAddrSpace(T)));
  87. return SamplerTy;
  88. }
  89. llvm::Value *CGOpenCLRuntime::getPipeElemSize(const Expr *PipeArg) {
  90. const PipeType *PipeTy = PipeArg->getType()->getAs<PipeType>();
  91. // The type of the last (implicit) argument to be passed.
  92. llvm::Type *Int32Ty = llvm::IntegerType::getInt32Ty(CGM.getLLVMContext());
  93. unsigned TypeSize = CGM.getContext()
  94. .getTypeSizeInChars(PipeTy->getElementType())
  95. .getQuantity();
  96. return llvm::ConstantInt::get(Int32Ty, TypeSize, false);
  97. }
  98. llvm::Value *CGOpenCLRuntime::getPipeElemAlign(const Expr *PipeArg) {
  99. const PipeType *PipeTy = PipeArg->getType()->getAs<PipeType>();
  100. // The type of the last (implicit) argument to be passed.
  101. llvm::Type *Int32Ty = llvm::IntegerType::getInt32Ty(CGM.getLLVMContext());
  102. unsigned TypeSize = CGM.getContext()
  103. .getTypeAlignInChars(PipeTy->getElementType())
  104. .getQuantity();
  105. return llvm::ConstantInt::get(Int32Ty, TypeSize, false);
  106. }
  107. llvm::PointerType *CGOpenCLRuntime::getGenericVoidPointerType() {
  108. assert(CGM.getLangOpts().OpenCL);
  109. return llvm::IntegerType::getInt8PtrTy(
  110. CGM.getLLVMContext(),
  111. CGM.getContext().getTargetAddressSpace(LangAS::opencl_generic));
  112. }
  113. /// Record emitted llvm invoke function and llvm block literal for the
  114. /// corresponding block expression.
  115. void CGOpenCLRuntime::recordBlockInfo(const BlockExpr *E,
  116. llvm::Function *InvokeF,
  117. llvm::Value *Block) {
  118. assert(EnqueuedBlockMap.find(E) == EnqueuedBlockMap.end() &&
  119. "Block expression emitted twice");
  120. assert(isa<llvm::Function>(InvokeF) && "Invalid invoke function");
  121. assert(Block->getType()->isPointerTy() && "Invalid block literal type");
  122. EnqueuedBlockMap[E].InvokeFunc = InvokeF;
  123. EnqueuedBlockMap[E].BlockArg = Block;
  124. EnqueuedBlockMap[E].Kernel = nullptr;
  125. }
  126. CGOpenCLRuntime::EnqueuedBlockInfo
  127. CGOpenCLRuntime::emitOpenCLEnqueuedBlock(CodeGenFunction &CGF, const Expr *E) {
  128. CGF.EmitScalarExpr(E);
  129. // The block literal may be assigned to a const variable. Chasing down
  130. // to get the block literal.
  131. if (auto DR = dyn_cast<DeclRefExpr>(E)) {
  132. E = cast<VarDecl>(DR->getDecl())->getInit();
  133. }
  134. E = E->IgnoreImplicit();
  135. if (auto Cast = dyn_cast<CastExpr>(E)) {
  136. E = Cast->getSubExpr();
  137. }
  138. auto *Block = cast<BlockExpr>(E);
  139. assert(EnqueuedBlockMap.find(Block) != EnqueuedBlockMap.end() &&
  140. "Block expression not emitted");
  141. // Do not emit the block wrapper again if it has been emitted.
  142. if (EnqueuedBlockMap[Block].Kernel) {
  143. return EnqueuedBlockMap[Block];
  144. }
  145. auto *F = CGF.getTargetHooks().createEnqueuedBlockKernel(
  146. CGF, EnqueuedBlockMap[Block].InvokeFunc,
  147. EnqueuedBlockMap[Block].BlockArg->stripPointerCasts());
  148. // The common part of the post-processing of the kernel goes here.
  149. F->addFnAttr(llvm::Attribute::NoUnwind);
  150. F->setCallingConv(
  151. CGF.getTypes().ClangCallConvToLLVMCallConv(CallingConv::CC_OpenCLKernel));
  152. EnqueuedBlockMap[Block].Kernel = F;
  153. return EnqueuedBlockMap[Block];
  154. }