Path: blob/main/contrib/llvm-project/clang/lib/CodeGen/CGOpenCLRuntime.cpp
35234 views
//===----- CGOpenCLRuntime.cpp - Interface to OpenCL Runtimes -------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This provides an abstract class for OpenCL code generation. Concrete9// subclasses of this implement code generation for specific OpenCL10// runtime libraries.11//12//===----------------------------------------------------------------------===//1314#include "CGOpenCLRuntime.h"15#include "CodeGenFunction.h"16#include "TargetInfo.h"17#include "clang/CodeGen/ConstantInitBuilder.h"18#include "llvm/IR/DerivedTypes.h"19#include "llvm/IR/GlobalValue.h"20#include <assert.h>2122using namespace clang;23using namespace CodeGen;2425CGOpenCLRuntime::~CGOpenCLRuntime() {}2627void CGOpenCLRuntime::EmitWorkGroupLocalVarDecl(CodeGenFunction &CGF,28const VarDecl &D) {29return CGF.EmitStaticVarDecl(D, llvm::GlobalValue::InternalLinkage);30}3132llvm::Type *CGOpenCLRuntime::convertOpenCLSpecificType(const Type *T) {33assert(T->isOpenCLSpecificType() && "Not an OpenCL specific type!");3435// Check if the target has a specific translation for this type first.36if (llvm::Type *TransTy = CGM.getTargetCodeGenInfo().getOpenCLType(CGM, T))37return TransTy;3839if (T->isSamplerT())40return getSamplerType(T);4142return getPointerType(T);43}4445llvm::PointerType *CGOpenCLRuntime::getPointerType(const Type *T) {46uint32_t AddrSpc = CGM.getContext().getTargetAddressSpace(47CGM.getContext().getOpenCLTypeAddrSpace(T));48return llvm::PointerType::get(CGM.getLLVMContext(), AddrSpc);49}5051llvm::Type *CGOpenCLRuntime::getPipeType(const PipeType *T) {52if (llvm::Type *PipeTy = CGM.getTargetCodeGenInfo().getOpenCLType(CGM, T))53return PipeTy;5455if (T->isReadOnly())56return getPipeType(T, "opencl.pipe_ro_t", PipeROTy);57else58return getPipeType(T, "opencl.pipe_wo_t", PipeWOTy);59}6061llvm::Type *CGOpenCLRuntime::getPipeType(const PipeType *T, StringRef Name,62llvm::Type *&PipeTy) {63if (!PipeTy)64PipeTy = getPointerType(T);65return PipeTy;66}6768llvm::Type *CGOpenCLRuntime::getSamplerType(const Type *T) {69if (SamplerTy)70return SamplerTy;7172if (llvm::Type *TransTy = CGM.getTargetCodeGenInfo().getOpenCLType(73CGM, CGM.getContext().OCLSamplerTy.getTypePtr()))74SamplerTy = TransTy;75else76SamplerTy = getPointerType(T);77return SamplerTy;78}7980llvm::Value *CGOpenCLRuntime::getPipeElemSize(const Expr *PipeArg) {81const PipeType *PipeTy = PipeArg->getType()->castAs<PipeType>();82// The type of the last (implicit) argument to be passed.83llvm::Type *Int32Ty = llvm::IntegerType::getInt32Ty(CGM.getLLVMContext());84unsigned TypeSize = CGM.getContext()85.getTypeSizeInChars(PipeTy->getElementType())86.getQuantity();87return llvm::ConstantInt::get(Int32Ty, TypeSize, false);88}8990llvm::Value *CGOpenCLRuntime::getPipeElemAlign(const Expr *PipeArg) {91const PipeType *PipeTy = PipeArg->getType()->castAs<PipeType>();92// The type of the last (implicit) argument to be passed.93llvm::Type *Int32Ty = llvm::IntegerType::getInt32Ty(CGM.getLLVMContext());94unsigned TypeSize = CGM.getContext()95.getTypeAlignInChars(PipeTy->getElementType())96.getQuantity();97return llvm::ConstantInt::get(Int32Ty, TypeSize, false);98}99100llvm::PointerType *CGOpenCLRuntime::getGenericVoidPointerType() {101assert(CGM.getLangOpts().OpenCL);102return llvm::PointerType::get(103CGM.getLLVMContext(),104CGM.getContext().getTargetAddressSpace(LangAS::opencl_generic));105}106107// Get the block literal from an expression derived from the block expression.108// OpenCL v2.0 s6.12.5:109// Block variable declarations are implicitly qualified with const. Therefore110// all block variables must be initialized at declaration time and may not be111// reassigned.112static const BlockExpr *getBlockExpr(const Expr *E) {113const Expr *Prev = nullptr; // to make sure we do not stuck in infinite loop.114while(!isa<BlockExpr>(E) && E != Prev) {115Prev = E;116E = E->IgnoreCasts();117if (auto DR = dyn_cast<DeclRefExpr>(E)) {118E = cast<VarDecl>(DR->getDecl())->getInit();119}120}121return cast<BlockExpr>(E);122}123124/// Record emitted llvm invoke function and llvm block literal for the125/// corresponding block expression.126void CGOpenCLRuntime::recordBlockInfo(const BlockExpr *E,127llvm::Function *InvokeF,128llvm::Value *Block, llvm::Type *BlockTy) {129assert(!EnqueuedBlockMap.contains(E) && "Block expression emitted twice");130assert(isa<llvm::Function>(InvokeF) && "Invalid invoke function");131assert(Block->getType()->isPointerTy() && "Invalid block literal type");132EnqueuedBlockMap[E].InvokeFunc = InvokeF;133EnqueuedBlockMap[E].BlockArg = Block;134EnqueuedBlockMap[E].BlockTy = BlockTy;135EnqueuedBlockMap[E].KernelHandle = nullptr;136}137138llvm::Function *CGOpenCLRuntime::getInvokeFunction(const Expr *E) {139return EnqueuedBlockMap[getBlockExpr(E)].InvokeFunc;140}141142CGOpenCLRuntime::EnqueuedBlockInfo143CGOpenCLRuntime::emitOpenCLEnqueuedBlock(CodeGenFunction &CGF, const Expr *E) {144CGF.EmitScalarExpr(E);145146// The block literal may be assigned to a const variable. Chasing down147// to get the block literal.148const BlockExpr *Block = getBlockExpr(E);149150assert(EnqueuedBlockMap.contains(Block) && "Block expression not emitted");151152// Do not emit the block wrapper again if it has been emitted.153if (EnqueuedBlockMap[Block].KernelHandle) {154return EnqueuedBlockMap[Block];155}156157auto *F = CGF.getTargetHooks().createEnqueuedBlockKernel(158CGF, EnqueuedBlockMap[Block].InvokeFunc, EnqueuedBlockMap[Block].BlockTy);159160// The common part of the post-processing of the kernel goes here.161EnqueuedBlockMap[Block].KernelHandle = F;162return EnqueuedBlockMap[Block];163}164165166