1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
|
//===----- CGOpenCLRuntime.cpp - Interface to OpenCL Runtimes -------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This provides an abstract class for OpenCL code generation. Concrete
// subclasses of this implement code generation for specific OpenCL
// runtime libraries.
//
//===----------------------------------------------------------------------===//
#include "CGOpenCLRuntime.h"
#include "CodeGenFunction.h"
#include "TargetInfo.h"
#include "clang/CodeGen/ConstantInitBuilder.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/GlobalValue.h"
#include <assert.h>
using namespace clang;
using namespace CodeGen;
CGOpenCLRuntime::~CGOpenCLRuntime() {}
void CGOpenCLRuntime::EmitWorkGroupLocalVarDecl(CodeGenFunction &CGF,
const VarDecl &D) {
return CGF.EmitStaticVarDecl(D, llvm::GlobalValue::InternalLinkage);
}
llvm::Type *CGOpenCLRuntime::convertOpenCLSpecificType(const Type *T) {
assert(T->isOpenCLSpecificType() &&
"Not an OpenCL specific type!");
llvm::LLVMContext& Ctx = CGM.getLLVMContext();
uint32_t AddrSpc = CGM.getContext().getTargetAddressSpace(
CGM.getContext().getOpenCLTypeAddrSpace(T));
switch (cast<BuiltinType>(T)->getKind()) {
default:
llvm_unreachable("Unexpected opencl builtin type!");
return nullptr;
#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
case BuiltinType::Id: \
return llvm::PointerType::get( \
llvm::StructType::create(Ctx, "opencl." #ImgType "_" #Suffix "_t"), \
AddrSpc);
#include "clang/Basic/OpenCLImageTypes.def"
case BuiltinType::OCLSampler:
return getSamplerType(T);
case BuiltinType::OCLEvent:
return llvm::PointerType::get(
llvm::StructType::create(Ctx, "opencl.event_t"), AddrSpc);
case BuiltinType::OCLClkEvent:
return llvm::PointerType::get(
llvm::StructType::create(Ctx, "opencl.clk_event_t"), AddrSpc);
case BuiltinType::OCLQueue:
return llvm::PointerType::get(
llvm::StructType::create(Ctx, "opencl.queue_t"), AddrSpc);
case BuiltinType::OCLReserveID:
return llvm::PointerType::get(
llvm::StructType::create(Ctx, "opencl.reserve_id_t"), AddrSpc);
}
}
llvm::Type *CGOpenCLRuntime::getPipeType(const PipeType *T) {
if (!PipeTy){
uint32_t PipeAddrSpc = CGM.getContext().getTargetAddressSpace(
CGM.getContext().getOpenCLTypeAddrSpace(T));
PipeTy = llvm::PointerType::get(llvm::StructType::create(
CGM.getLLVMContext(), "opencl.pipe_t"), PipeAddrSpc);
}
return PipeTy;
}
llvm::PointerType *CGOpenCLRuntime::getSamplerType(const Type *T) {
if (!SamplerTy)
SamplerTy = llvm::PointerType::get(llvm::StructType::create(
CGM.getLLVMContext(), "opencl.sampler_t"),
CGM.getContext().getTargetAddressSpace(
CGM.getContext().getOpenCLTypeAddrSpace(T)));
return SamplerTy;
}
llvm::Value *CGOpenCLRuntime::getPipeElemSize(const Expr *PipeArg) {
const PipeType *PipeTy = PipeArg->getType()->getAs<PipeType>();
// The type of the last (implicit) argument to be passed.
llvm::Type *Int32Ty = llvm::IntegerType::getInt32Ty(CGM.getLLVMContext());
unsigned TypeSize = CGM.getContext()
.getTypeSizeInChars(PipeTy->getElementType())
.getQuantity();
return llvm::ConstantInt::get(Int32Ty, TypeSize, false);
}
llvm::Value *CGOpenCLRuntime::getPipeElemAlign(const Expr *PipeArg) {
const PipeType *PipeTy = PipeArg->getType()->getAs<PipeType>();
// The type of the last (implicit) argument to be passed.
llvm::Type *Int32Ty = llvm::IntegerType::getInt32Ty(CGM.getLLVMContext());
unsigned TypeSize = CGM.getContext()
.getTypeAlignInChars(PipeTy->getElementType())
.getQuantity();
return llvm::ConstantInt::get(Int32Ty, TypeSize, false);
}
llvm::PointerType *CGOpenCLRuntime::getGenericVoidPointerType() {
assert(CGM.getLangOpts().OpenCL);
return llvm::IntegerType::getInt8PtrTy(
CGM.getLLVMContext(),
CGM.getContext().getTargetAddressSpace(LangAS::opencl_generic));
}
CGOpenCLRuntime::EnqueuedBlockInfo
CGOpenCLRuntime::emitOpenCLEnqueuedBlock(CodeGenFunction &CGF, const Expr *E) {
// The block literal may be assigned to a const variable. Chasing down
// to get the block literal.
if (auto DR = dyn_cast<DeclRefExpr>(E)) {
E = cast<VarDecl>(DR->getDecl())->getInit();
}
if (auto Cast = dyn_cast<CastExpr>(E)) {
E = Cast->getSubExpr();
}
auto *Block = cast<BlockExpr>(E);
// The same block literal may be enqueued multiple times. Cache it if
// possible.
auto Loc = EnqueuedBlockMap.find(Block);
if (Loc != EnqueuedBlockMap.end()) {
return Loc->second;
}
// Emit block literal as a common block expression and get the block invoke
// function.
llvm::Function *Invoke;
auto *V = CGF.EmitBlockLiteral(cast<BlockExpr>(Block), &Invoke);
auto *F = CGF.getTargetHooks().createEnqueuedBlockKernel(
CGF, Invoke, V->stripPointerCasts());
// The common part of the post-processing of the kernel goes here.
F->addFnAttr(llvm::Attribute::NoUnwind);
F->setCallingConv(
CGF.getTypes().ClangCallConvToLLVMCallConv(CallingConv::CC_OpenCLKernel));
EnqueuedBlockInfo Info{F, V};
EnqueuedBlockMap[Block] = Info;
return Info;
}
|