Coverage Report

Created: 2022-07-16 07:03

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