clang 23.0.0git
CGOpenCLRuntime.cpp
Go to the documentation of this file.
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"
19#include "llvm/IR/DerivedTypes.h"
20#include "llvm/IR/GlobalValue.h"
21#include <assert.h>
22
23using namespace clang;
24using namespace CodeGen;
25
27
29 const VarDecl &D) {
30 return CGF.EmitStaticVarDecl(D, llvm::GlobalValue::InternalLinkage);
31}
32
34 assert(T->isOpenCLSpecificType() && "Not an OpenCL specific type!");
35
36 // Check if the target has a specific translation for this type first.
37 if (llvm::Type *TransTy = CGM.getTargetCodeGenInfo().getOpenCLType(CGM, T))
38 return TransTy;
39
40 if (T->isSamplerT())
41 return getSamplerType(T);
42
43 return getPointerType(T);
44}
45
46llvm::PointerType *CGOpenCLRuntime::getPointerType(const Type *T) {
47 uint32_t AddrSpc = CGM.getContext().getTargetAddressSpace(
48 CGM.getContext().getOpenCLTypeAddrSpace(T));
49 return llvm::PointerType::get(CGM.getLLVMContext(), AddrSpc);
50}
51
53 if (llvm::Type *PipeTy = CGM.getTargetCodeGenInfo().getOpenCLType(CGM, T))
54 return PipeTy;
55
56 if (!PipeTy)
58 return PipeTy;
59}
60
62 if (SamplerTy)
63 return SamplerTy;
64
65 if (llvm::Type *TransTy = CGM.getTargetCodeGenInfo().getOpenCLType(
66 CGM, CGM.getContext().OCLSamplerTy.getTypePtr()))
67 SamplerTy = TransTy;
68 else
70 return SamplerTy;
71}
72
73llvm::Value *CGOpenCLRuntime::getPipeElemSize(const Expr *PipeArg) {
74 const PipeType *PipeTy = PipeArg->getType()->castAs<PipeType>();
75 // The type of the last (implicit) argument to be passed.
76 llvm::Type *Int32Ty = llvm::IntegerType::getInt32Ty(CGM.getLLVMContext());
77 unsigned TypeSize = CGM.getContext()
78 .getTypeSizeInChars(PipeTy->getElementType())
79 .getQuantity();
80 return llvm::ConstantInt::get(Int32Ty, TypeSize, false);
81}
82
83llvm::Value *CGOpenCLRuntime::getPipeElemAlign(const Expr *PipeArg) {
84 const PipeType *PipeTy = PipeArg->getType()->castAs<PipeType>();
85 // The type of the last (implicit) argument to be passed.
86 llvm::Type *Int32Ty = llvm::IntegerType::getInt32Ty(CGM.getLLVMContext());
87 unsigned TypeSize = CGM.getContext()
88 .getTypeAlignInChars(PipeTy->getElementType())
89 .getQuantity();
90 return llvm::ConstantInt::get(Int32Ty, TypeSize, false);
91}
92
94 assert(CGM.getLangOpts().OpenCL);
95 return llvm::PointerType::get(
96 CGM.getLLVMContext(),
97 CGM.getContext().getTargetAddressSpace(LangAS::opencl_generic));
98}
99
100// Get the block literal from an expression derived from the block expression.
101// OpenCL v2.0 s6.12.5:
102// Block variable declarations are implicitly qualified with const. Therefore
103// all block variables must be initialized at declaration time and may not be
104// reassigned.
105static const BlockExpr *getBlockExpr(const Expr *E) {
106 const Expr *Prev = nullptr; // to make sure we do not stuck in infinite loop.
107 while(!isa<BlockExpr>(E) && E != Prev) {
108 Prev = E;
109 E = E->IgnoreCasts();
110 if (auto DR = dyn_cast<DeclRefExpr>(E)) {
111 E = cast<VarDecl>(DR->getDecl())->getInit();
112 }
113 }
114 return cast<BlockExpr>(E);
115}
116
117/// Record emitted llvm invoke function and llvm block literal for the
118/// corresponding block expression.
120 llvm::Function *InvokeF,
121 llvm::Value *Block, llvm::Type *BlockTy) {
122 assert(!EnqueuedBlockMap.contains(E) && "Block expression emitted twice");
123 assert(isa<llvm::Function>(InvokeF) && "Invalid invoke function");
124 assert(Block->getType()->isPointerTy() && "Invalid block literal type");
125 EnqueuedBlockInfo &BlockInfo = EnqueuedBlockMap[E];
126 BlockInfo.InvokeFunc = InvokeF;
127 BlockInfo.BlockArg = Block;
128 BlockInfo.BlockTy = BlockTy;
129 BlockInfo.KernelHandle = nullptr;
130}
131
132llvm::Function *CGOpenCLRuntime::getInvokeFunction(const Expr *E) {
133 return EnqueuedBlockMap[getBlockExpr(E)].InvokeFunc;
134}
135
138 CGF.EmitScalarExpr(E);
139
140 // The block literal may be assigned to a const variable. Chasing down
141 // to get the block literal.
142 const BlockExpr *Block = getBlockExpr(E);
143
144 auto It = EnqueuedBlockMap.find(Block);
145 assert(It != EnqueuedBlockMap.end() && "Block expression not emitted");
146 EnqueuedBlockInfo &BlockInfo = It->second;
147
148 // Do not emit the block wrapper again if it has been emitted.
149 if (BlockInfo.KernelHandle) {
150 return BlockInfo;
151 }
152
154 CGF, BlockInfo.InvokeFunc, BlockInfo.BlockTy);
155
156 // The common part of the post-processing of the kernel goes here.
157 BlockInfo.KernelHandle = F;
158 return BlockInfo;
159}
static const BlockExpr * getBlockExpr(const Expr *E)
BlockExpr - Adaptor class for mixing a BlockDecl with expressions.
Definition Expr.h:6671
EnqueuedBlockInfo emitOpenCLEnqueuedBlock(CodeGenFunction &CGF, const Expr *E)
llvm::PointerType * getPointerType(const Type *T)
llvm::Value * getPipeElemAlign(const Expr *PipeArg)
llvm::Function * getInvokeFunction(const Expr *E)
void recordBlockInfo(const BlockExpr *E, llvm::Function *InvokeF, llvm::Value *Block, llvm::Type *BlockTy)
Record invoke function and block literal emitted during normal codegen for a block expression.
llvm::PointerType * getGenericVoidPointerType()
llvm::DenseMap< const Expr *, EnqueuedBlockInfo > EnqueuedBlockMap
Maps block expression to block information.
llvm::Type * convertOpenCLSpecificType(const Type *T)
llvm::Type * getPipeType(const PipeType *T)
llvm::Value * getPipeElemSize(const Expr *PipeArg)
void EmitWorkGroupLocalVarDecl(CodeGenFunction &CGF, const VarDecl &D)
Emit the IR required for a work-group-local variable declaration, and add an entry to CGF's LocalDecl...
llvm::Type * getSamplerType(const Type *T)
CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...
void EmitStaticVarDecl(const VarDecl &D, llvm::GlobalValue::LinkageTypes Linkage)
Definition CGDecl.cpp:404
const TargetCodeGenInfo & getTargetHooks() const
llvm::Value * EmitScalarExpr(const Expr *E, bool IgnoreResultAssign=false)
EmitScalarExpr - Emit the computation of the specified expression of LLVM scalar type,...
virtual llvm::Value * createEnqueuedBlockKernel(CodeGenFunction &CGF, llvm::Function *BlockInvokeFunc, llvm::Type *BlockTy) const
Create an OpenCL kernel for an enqueued block.
This represents one expression.
Definition Expr.h:112
Expr * IgnoreCasts() LLVM_READONLY
Skip past any casts which might surround this expression until reaching a fixed point.
Definition Expr.cpp:3074
QualType getType() const
Definition Expr.h:144
PipeType - OpenCL20.
Definition TypeBase.h:8206
const T * castAs() const
Member-template castAs<specific type>.
Definition TypeBase.h:9285
Represents a variable declaration or definition.
Definition Decl.h:926
@ Type
The l-value was considered opaque, so the alignment was determined from a type.
Definition CGValue.h:155
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
Definition Address.h:330
U cast(CodeGen::Address addr)
Definition Address.h:327
Structure for enqueued block information.
llvm::Type * BlockTy
The first argument to enqueued block kernel.
llvm::Value * BlockArg
Enqueued block kernel reference.
llvm::Value * KernelHandle
Block invoke function.