blob: 56850e0d86c98ac84f135b9234a390c626d32917 [file] [log] [blame]
Guy Benyei11169dd2012-12-18 14:30:41 +00001//===----- 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
16#include "CGOpenCLRuntime.h"
17#include "CodeGenFunction.h"
Yaxun Liu37ceede2016-07-20 19:21:11 +000018#include "TargetInfo.h"
Yaxun Liuc2a87a02017-10-14 12:23:50 +000019#include "clang/CodeGen/ConstantInitBuilder.h"
Chandler Carruthffd55512013-01-02 11:45:17 +000020#include "llvm/IR/DerivedTypes.h"
21#include "llvm/IR/GlobalValue.h"
Guy Benyeid8a08ea2012-12-18 14:38:23 +000022#include <assert.h>
Guy Benyei11169dd2012-12-18 14:30:41 +000023
24using namespace clang;
25using namespace CodeGen;
26
Angel Garcia Gomez637d1e62015-10-20 13:23:58 +000027CGOpenCLRuntime::~CGOpenCLRuntime() {}
Guy Benyei11169dd2012-12-18 14:30:41 +000028
29void CGOpenCLRuntime::EmitWorkGroupLocalVarDecl(CodeGenFunction &CGF,
30 const VarDecl &D) {
31 return CGF.EmitStaticVarDecl(D, llvm::GlobalValue::InternalLinkage);
32}
Guy Benyeid8a08ea2012-12-18 14:38:23 +000033
34llvm::Type *CGOpenCLRuntime::convertOpenCLSpecificType(const Type *T) {
35 assert(T->isOpenCLSpecificType() &&
36 "Not an OpenCL specific type!");
37
Pekka Jaaskelainen3587b322014-01-09 13:37:30 +000038 llvm::LLVMContext& Ctx = CGM.getLLVMContext();
Sven van Haastregtefb4d4c2017-08-15 09:38:18 +000039 uint32_t AddrSpc = CGM.getContext().getTargetAddressSpace(
Sven van Haastregt3bb7eaf2017-12-06 10:11:28 +000040 CGM.getContext().getOpenCLTypeAddrSpace(T));
Guy Benyeid8a08ea2012-12-18 14:38:23 +000041 switch (cast<BuiltinType>(T)->getKind()) {
Alexey Bader465c1892016-09-23 14:20:00 +000042 default:
Guy Benyeid8a08ea2012-12-18 14:38:23 +000043 llvm_unreachable("Unexpected opencl builtin type!");
Craig Topper8a13c412014-05-21 05:09:00 +000044 return nullptr;
Alexey Bader954ba212016-04-08 13:40:33 +000045#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"), \
Sven van Haastregtefb4d4c2017-08-15 09:38:18 +000049 AddrSpc);
Alexey Baderb62f1442016-04-13 08:33:41 +000050#include "clang/Basic/OpenCLImageTypes.def"
Guy Benyei61054192013-02-07 10:55:47 +000051 case BuiltinType::OCLSampler:
Sven van Haastregtefb4d4c2017-08-15 09:38:18 +000052 return getSamplerType(T);
Guy Benyei1b4fb3e2013-01-20 12:31:11 +000053 case BuiltinType::OCLEvent:
Sven van Haastregtefb4d4c2017-08-15 09:38:18 +000054 return llvm::PointerType::get(
55 llvm::StructType::create(Ctx, "opencl.event_t"), AddrSpc);
Alexey Bader9c8453f2015-09-15 11:18:52 +000056 case BuiltinType::OCLClkEvent:
57 return llvm::PointerType::get(
Sven van Haastregtefb4d4c2017-08-15 09:38:18 +000058 llvm::StructType::create(Ctx, "opencl.clk_event_t"), AddrSpc);
Alexey Bader9c8453f2015-09-15 11:18:52 +000059 case BuiltinType::OCLQueue:
60 return llvm::PointerType::get(
Sven van Haastregtefb4d4c2017-08-15 09:38:18 +000061 llvm::StructType::create(Ctx, "opencl.queue_t"), AddrSpc);
Alexey Bader9c8453f2015-09-15 11:18:52 +000062 case BuiltinType::OCLReserveID:
63 return llvm::PointerType::get(
Sven van Haastregtefb4d4c2017-08-15 09:38:18 +000064 llvm::StructType::create(Ctx, "opencl.reserve_id_t"), AddrSpc);
Guy Benyeid8a08ea2012-12-18 14:38:23 +000065 }
66}
Xiuli Pan9c14e282016-01-09 12:53:17 +000067
Sven van Haastregtefb4d4c2017-08-15 09:38:18 +000068llvm::Type *CGOpenCLRuntime::getPipeType(const PipeType *T) {
Sven van Haastregt4700faa2018-04-27 10:37:04 +000069 if (T->isReadOnly())
70 return getPipeType(T, "opencl.pipe_ro_t", PipeROTy);
71 else
72 return getPipeType(T, "opencl.pipe_wo_t", PipeWOTy);
73}
Xiuli Pan9c14e282016-01-09 12:53:17 +000074
Sven van Haastregt4700faa2018-04-27 10:37:04 +000075llvm::Type *CGOpenCLRuntime::getPipeType(const PipeType *T, StringRef Name,
76 llvm::Type *&PipeTy) {
77 if (!PipeTy)
78 PipeTy = llvm::PointerType::get(llvm::StructType::create(
79 CGM.getLLVMContext(), Name),
80 CGM.getContext().getTargetAddressSpace(
81 CGM.getContext().getOpenCLTypeAddrSpace(T)));
Xiuli Pan9c14e282016-01-09 12:53:17 +000082 return PipeTy;
83}
Yaxun Liu0bc4b2d2016-07-28 19:26:30 +000084
Sven van Haastregtefb4d4c2017-08-15 09:38:18 +000085llvm::PointerType *CGOpenCLRuntime::getSamplerType(const Type *T) {
Yaxun Liu0bc4b2d2016-07-28 19:26:30 +000086 if (!SamplerTy)
87 SamplerTy = llvm::PointerType::get(llvm::StructType::create(
88 CGM.getLLVMContext(), "opencl.sampler_t"),
89 CGM.getContext().getTargetAddressSpace(
Sven van Haastregt3bb7eaf2017-12-06 10:11:28 +000090 CGM.getContext().getOpenCLTypeAddrSpace(T)));
Yaxun Liu0bc4b2d2016-07-28 19:26:30 +000091 return SamplerTy;
92}
Alexey Bader465c1892016-09-23 14:20:00 +000093
94llvm::Value *CGOpenCLRuntime::getPipeElemSize(const Expr *PipeArg) {
95 const PipeType *PipeTy = PipeArg->getType()->getAs<PipeType>();
96 // The type of the last (implicit) argument to be passed.
97 llvm::Type *Int32Ty = llvm::IntegerType::getInt32Ty(CGM.getLLVMContext());
98 unsigned TypeSize = CGM.getContext()
99 .getTypeSizeInChars(PipeTy->getElementType())
100 .getQuantity();
101 return llvm::ConstantInt::get(Int32Ty, TypeSize, false);
102}
103
104llvm::Value *CGOpenCLRuntime::getPipeElemAlign(const Expr *PipeArg) {
105 const PipeType *PipeTy = PipeArg->getType()->getAs<PipeType>();
106 // The type of the last (implicit) argument to be passed.
107 llvm::Type *Int32Ty = llvm::IntegerType::getInt32Ty(CGM.getLLVMContext());
108 unsigned TypeSize = CGM.getContext()
109 .getTypeAlignInChars(PipeTy->getElementType())
110 .getQuantity();
111 return llvm::ConstantInt::get(Int32Ty, TypeSize, false);
112}
Yaxun Liu10712d92017-10-04 20:32:17 +0000113
114llvm::PointerType *CGOpenCLRuntime::getGenericVoidPointerType() {
115 assert(CGM.getLangOpts().OpenCL);
116 return llvm::IntegerType::getInt8PtrTy(
117 CGM.getLLVMContext(),
118 CGM.getContext().getTargetAddressSpace(LangAS::opencl_generic));
119}
Yaxun Liuc2a87a02017-10-14 12:23:50 +0000120
Yaxun Liufa13d012018-02-15 16:39:19 +0000121/// Record emitted llvm invoke function and llvm block literal for the
122/// corresponding block expression.
123void CGOpenCLRuntime::recordBlockInfo(const BlockExpr *E,
124 llvm::Function *InvokeF,
125 llvm::Value *Block) {
126 assert(EnqueuedBlockMap.find(E) == EnqueuedBlockMap.end() &&
127 "Block expression emitted twice");
128 assert(isa<llvm::Function>(InvokeF) && "Invalid invoke function");
129 assert(Block->getType()->isPointerTy() && "Invalid block literal type");
130 EnqueuedBlockMap[E].InvokeFunc = InvokeF;
131 EnqueuedBlockMap[E].BlockArg = Block;
132 EnqueuedBlockMap[E].Kernel = nullptr;
133}
134
Yaxun Liuc2a87a02017-10-14 12:23:50 +0000135CGOpenCLRuntime::EnqueuedBlockInfo
136CGOpenCLRuntime::emitOpenCLEnqueuedBlock(CodeGenFunction &CGF, const Expr *E) {
Yaxun Liufa13d012018-02-15 16:39:19 +0000137 CGF.EmitScalarExpr(E);
138
Sven van Haastregtda3b6322018-10-02 13:02:24 +0000139 // The block literal may be assigned to a const variable. Chasing down
140 // to get the block literal.
141 if (auto DR = dyn_cast<DeclRefExpr>(E)) {
142 E = cast<VarDecl>(DR->getDecl())->getInit();
143 }
144 E = E->IgnoreImplicit();
145 if (auto Cast = dyn_cast<CastExpr>(E)) {
146 E = Cast->getSubExpr();
147 }
148 auto *Block = cast<BlockExpr>(E);
149
Yaxun Liufa13d012018-02-15 16:39:19 +0000150 assert(EnqueuedBlockMap.find(Block) != EnqueuedBlockMap.end() &&
151 "Block expression not emitted");
152
153 // Do not emit the block wrapper again if it has been emitted.
154 if (EnqueuedBlockMap[Block].Kernel) {
155 return EnqueuedBlockMap[Block];
Yaxun Liuc2a87a02017-10-14 12:23:50 +0000156 }
157
Yaxun Liuc2a87a02017-10-14 12:23:50 +0000158 auto *F = CGF.getTargetHooks().createEnqueuedBlockKernel(
Yaxun Liufa13d012018-02-15 16:39:19 +0000159 CGF, EnqueuedBlockMap[Block].InvokeFunc,
160 EnqueuedBlockMap[Block].BlockArg->stripPointerCasts());
Yaxun Liuc2a87a02017-10-14 12:23:50 +0000161
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));
Yaxun Liufa13d012018-02-15 16:39:19 +0000166 EnqueuedBlockMap[Block].Kernel = F;
167 return EnqueuedBlockMap[Block];
Yaxun Liuc2a87a02017-10-14 12:23:50 +0000168}