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