1 //===----- CGOpenCLRuntime.cpp - Interface to OpenCL Runtimes -------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This provides an abstract class for OpenCL code generation. Concrete
11 // subclasses of this implement code generation for specific OpenCL
14 //===----------------------------------------------------------------------===//
16 #include "CGOpenCLRuntime.h"
17 #include "CodeGenFunction.h"
18 #include "TargetInfo.h"
19 #include "clang/CodeGen/ConstantInitBuilder.h"
20 #include "llvm/IR/DerivedTypes.h"
21 #include "llvm/IR/GlobalValue.h"
24 using namespace clang;
25 using namespace CodeGen;
27 CGOpenCLRuntime::~CGOpenCLRuntime() {}
29 void CGOpenCLRuntime::EmitWorkGroupLocalVarDecl(CodeGenFunction &CGF,
31 return CGF.EmitStaticVarDecl(D, llvm::GlobalValue::InternalLinkage);
34 llvm::Type *CGOpenCLRuntime::convertOpenCLSpecificType(const Type *T) {
35 assert(T->isOpenCLSpecificType() &&
36 "Not an OpenCL specific type!");
38 llvm::LLVMContext& Ctx = CGM.getLLVMContext();
39 uint32_t AddrSpc = CGM.getContext().getTargetAddressSpace(
40 CGM.getContext().getOpenCLTypeAddrSpace(T));
41 switch (cast<BuiltinType>(T)->getKind()) {
43 llvm_unreachable("Unexpected opencl builtin type!");
45 #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
46 case BuiltinType::Id: \
47 return llvm::PointerType::get( \
48 llvm::StructType::create(Ctx, "opencl." #ImgType "_" #Suffix "_t"), \
50 #include "clang/Basic/OpenCLImageTypes.def"
51 case BuiltinType::OCLSampler:
52 return getSamplerType(T);
53 case BuiltinType::OCLEvent:
54 return llvm::PointerType::get(
55 llvm::StructType::create(Ctx, "opencl.event_t"), AddrSpc);
56 case BuiltinType::OCLClkEvent:
57 return llvm::PointerType::get(
58 llvm::StructType::create(Ctx, "opencl.clk_event_t"), AddrSpc);
59 case BuiltinType::OCLQueue:
60 return llvm::PointerType::get(
61 llvm::StructType::create(Ctx, "opencl.queue_t"), AddrSpc);
62 case BuiltinType::OCLReserveID:
63 return llvm::PointerType::get(
64 llvm::StructType::create(Ctx, "opencl.reserve_id_t"), AddrSpc);
68 llvm::Type *CGOpenCLRuntime::getPipeType(const PipeType *T) {
70 uint32_t PipeAddrSpc = CGM.getContext().getTargetAddressSpace(
71 CGM.getContext().getOpenCLTypeAddrSpace(T));
72 PipeTy = llvm::PointerType::get(llvm::StructType::create(
73 CGM.getLLVMContext(), "opencl.pipe_t"), PipeAddrSpc);
79 llvm::PointerType *CGOpenCLRuntime::getSamplerType(const Type *T) {
81 SamplerTy = llvm::PointerType::get(llvm::StructType::create(
82 CGM.getLLVMContext(), "opencl.sampler_t"),
83 CGM.getContext().getTargetAddressSpace(
84 CGM.getContext().getOpenCLTypeAddrSpace(T)));
88 llvm::Value *CGOpenCLRuntime::getPipeElemSize(const Expr *PipeArg) {
89 const PipeType *PipeTy = PipeArg->getType()->getAs<PipeType>();
90 // The type of the last (implicit) argument to be passed.
91 llvm::Type *Int32Ty = llvm::IntegerType::getInt32Ty(CGM.getLLVMContext());
92 unsigned TypeSize = CGM.getContext()
93 .getTypeSizeInChars(PipeTy->getElementType())
95 return llvm::ConstantInt::get(Int32Ty, TypeSize, false);
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())
105 return llvm::ConstantInt::get(Int32Ty, TypeSize, false);
108 llvm::PointerType *CGOpenCLRuntime::getGenericVoidPointerType() {
109 assert(CGM.getLangOpts().OpenCL);
110 return llvm::IntegerType::getInt8PtrTy(
111 CGM.getLLVMContext(),
112 CGM.getContext().getTargetAddressSpace(LangAS::opencl_generic));
115 CGOpenCLRuntime::EnqueuedBlockInfo
116 CGOpenCLRuntime::emitOpenCLEnqueuedBlock(CodeGenFunction &CGF, const Expr *E) {
117 // The block literal may be assigned to a const variable. Chasing down
118 // to get the block literal.
119 if (auto DR = dyn_cast<DeclRefExpr>(E)) {
120 E = cast<VarDecl>(DR->getDecl())->getInit();
122 if (auto Cast = dyn_cast<CastExpr>(E)) {
123 E = Cast->getSubExpr();
125 auto *Block = cast<BlockExpr>(E);
127 // The same block literal may be enqueued multiple times. Cache it if
129 auto Loc = EnqueuedBlockMap.find(Block);
130 if (Loc != EnqueuedBlockMap.end()) {
134 // Emit block literal as a common block expression and get the block invoke
136 llvm::Function *Invoke;
137 auto *V = CGF.EmitBlockLiteral(cast<BlockExpr>(Block), &Invoke);
138 auto *F = CGF.getTargetHooks().createEnqueuedBlockKernel(
139 CGF, Invoke, V->stripPointerCasts());
141 // The common part of the post-processing of the kernel goes here.
142 F->addFnAttr(llvm::Attribute::NoUnwind);
144 CGF.getTypes().ClangCallConvToLLVMCallConv(CallingConv::CC_OpenCLKernel));
145 EnqueuedBlockInfo Info{F, V};
146 EnqueuedBlockMap[Block] = Info;