summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen/CGBlocks.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/CodeGen/CGBlocks.cpp')
-rw-r--r--clang/lib/CodeGen/CGBlocks.cpp79
1 files changed, 62 insertions, 17 deletions
diff --git a/clang/lib/CodeGen/CGBlocks.cpp b/clang/lib/CodeGen/CGBlocks.cpp
index b250b9a32b1..53288a69e2d 100644
--- a/clang/lib/CodeGen/CGBlocks.cpp
+++ b/clang/lib/CodeGen/CGBlocks.cpp
@@ -718,7 +718,12 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
// Otherwise, we have to emit this as a local block.
- llvm::Constant *isa = CGM.getNSConcreteStackBlock();
+ llvm::Constant *isa =
+ (!CGM.getContext().getLangOpts().OpenCL)
+ ? CGM.getNSConcreteStackBlock()
+ : CGM.getNullPointer(cast<llvm::PointerType>(
+ CGM.getNSConcreteStackBlock()->getType()),
+ QualType(getContext().VoidPtrTy));
isa = llvm::ConstantExpr::getBitCast(isa, VoidPtrTy);
// Build the block descriptor.
@@ -906,9 +911,8 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
// Cast to the converted block-pointer type, which happens (somewhat
// unfortunately) to be a pointer to function type.
- llvm::Value *result =
- Builder.CreateBitCast(blockAddr.getPointer(),
- ConvertType(blockInfo.getBlockExpr()->getType()));
+ llvm::Value *result = Builder.CreatePointerCast(
+ blockAddr.getPointer(), ConvertType(blockInfo.getBlockExpr()->getType()));
return result;
}
@@ -976,21 +980,41 @@ RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr *E,
llvm::Value *BlockPtr = EmitScalarExpr(E->getCallee());
// Get a pointer to the generic block literal.
+ // For OpenCL we generate generic AS void ptr to be able to reuse the same
+ // block definition for blocks with captures generated as private AS local
+ // variables and without captures generated as global AS program scope
+ // variables.
+ unsigned AddrSpace = 0;
+ if (getLangOpts().OpenCL)
+ AddrSpace = getContext().getTargetAddressSpace(LangAS::opencl_generic);
+
llvm::Type *BlockLiteralTy =
- llvm::PointerType::getUnqual(CGM.getGenericBlockLiteralType());
+ llvm::PointerType::get(CGM.getGenericBlockLiteralType(), AddrSpace);
// Bitcast the callee to a block literal.
- BlockPtr = Builder.CreateBitCast(BlockPtr, BlockLiteralTy, "block.literal");
+ BlockPtr =
+ Builder.CreatePointerCast(BlockPtr, BlockLiteralTy, "block.literal");
// Get the function pointer from the literal.
llvm::Value *FuncPtr =
Builder.CreateStructGEP(CGM.getGenericBlockLiteralType(), BlockPtr, 3);
- BlockPtr = Builder.CreateBitCast(BlockPtr, VoidPtrTy);
// Add the block literal.
CallArgList Args;
- Args.add(RValue::get(BlockPtr), getContext().VoidPtrTy);
+
+ QualType VoidPtrQualTy = getContext().VoidPtrTy;
+ llvm::Type *GenericVoidPtrTy = VoidPtrTy;
+ if (getLangOpts().OpenCL) {
+ GenericVoidPtrTy = Builder.getInt8PtrTy(
+ getContext().getTargetAddressSpace(LangAS::opencl_generic));
+ VoidPtrQualTy =
+ getContext().getPointerType(getContext().getAddrSpaceQualType(
+ getContext().VoidTy, LangAS::opencl_generic));
+ }
+
+ BlockPtr = Builder.CreatePointerCast(BlockPtr, GenericVoidPtrTy);
+ Args.add(RValue::get(BlockPtr), VoidPtrQualTy);
QualType FnType = BPT->getPointeeType();
@@ -1097,7 +1121,12 @@ static llvm::Constant *buildGlobalBlock(CodeGenModule &CGM,
auto fields = builder.beginStruct();
// isa
- fields.add(CGM.getNSConcreteGlobalBlock());
+ fields.add(
+ (!CGM.getContext().getLangOpts().OpenCL)
+ ? CGM.getNSConcreteGlobalBlock()
+ : CGM.getNullPointer(cast<llvm::PointerType>(
+ CGM.getNSConcreteGlobalBlock()->getType()),
+ QualType(CGM.getContext().VoidPtrTy)));
// __flags
BlockFlags flags = BLOCK_IS_GLOBAL | BLOCK_HAS_SIGNATURE;
@@ -1114,16 +1143,19 @@ static llvm::Constant *buildGlobalBlock(CodeGenModule &CGM,
// Descriptor
fields.add(buildBlockDescriptor(CGM, blockInfo));
- llvm::Constant *literal =
- fields.finishAndCreateGlobal("__block_literal_global",
- blockInfo.BlockAlign,
- /*constant*/ true);
+ unsigned AddrSpace = 0;
+ if (CGM.getContext().getLangOpts().OpenCL)
+ AddrSpace = CGM.getContext().getTargetAddressSpace(LangAS::opencl_global);
+
+ llvm::Constant *literal = fields.finishAndCreateGlobal(
+ "__block_literal_global", blockInfo.BlockAlign,
+ /*constant*/ true, llvm::GlobalVariable::InternalLinkage, AddrSpace);
// Return a constant of the appropriately-casted type.
llvm::Type *RequiredType =
CGM.getTypes().ConvertType(blockInfo.getBlockExpr()->getType());
llvm::Constant *Result =
- llvm::ConstantExpr::getBitCast(literal, RequiredType);
+ llvm::ConstantExpr::getPointerCast(literal, RequiredType);
CGM.setAddrOfGlobalBlock(blockInfo.BlockExpression, Result);
return Result;
}
@@ -1155,9 +1187,13 @@ void CodeGenFunction::setBlockContextParameter(const ImplicitParamDecl *D,
// Instead of messing around with LocalDeclMap, just set the value
// directly as BlockPointer.
- BlockPointer = Builder.CreateBitCast(arg,
- BlockInfo->StructureType->getPointerTo(),
- "block");
+ BlockPointer = Builder.CreatePointerCast(
+ arg,
+ BlockInfo->StructureType->getPointerTo(
+ getContext().getLangOpts().OpenCL
+ ? getContext().getTargetAddressSpace(LangAS::opencl_generic)
+ : 0),
+ "block");
}
Address CodeGenFunction::LoadBlockStruct() {
@@ -1196,6 +1232,15 @@ CodeGenFunction::GenerateBlockFunction(GlobalDecl GD,
// The first argument is the block pointer. Just take it as a void*
// and cast it later.
QualType selfTy = getContext().VoidPtrTy;
+
+ // For OpenCL passed block pointer can be private AS local variable or
+ // global AS program scope variable (for the case with and without captures).
+ // Generic AS is used therefore to be able to accomodate both private and
+ // generic AS in one implementation.
+ if (getLangOpts().OpenCL)
+ selfTy = getContext().getPointerType(getContext().getAddrSpaceQualType(
+ getContext().VoidTy, LangAS::opencl_generic));
+
IdentifierInfo *II = &CGM.getContext().Idents.get(".block_descriptor");
ImplicitParamDecl selfDecl(getContext(), const_cast<BlockDecl*>(blockDecl),
OpenPOWER on IntegriCloud