diff options
author | Anastasia Stulova <anastasia.stulova@arm.com> | 2017-01-27 15:11:34 +0000 |
---|---|---|
committer | Anastasia Stulova <anastasia.stulova@arm.com> | 2017-01-27 15:11:34 +0000 |
commit | af0a7bbbe2ab749b08a78e6095d573e2ab23f4be (patch) | |
tree | 5d2f959991720eb2187d511c2da3b2cb4476af7d /clang/lib | |
parent | 9e962add708d450230cfa2d754082f1eaf95a2ec (diff) | |
download | bcm5719-llvm-af0a7bbbe2ab749b08a78e6095d573e2ab23f4be.tar.gz bcm5719-llvm-af0a7bbbe2ab749b08a78e6095d573e2ab23f4be.zip |
[OpenCL] Add missing address spaces in IR generation of blocks
Modify ObjC blocks impl wrt address spaces as follows:
- keep default private address space for blocks generated
as local variables (with captures);
- add global address space for global block literals (no captures);
- make the block invoke function and enqueue_kernel prototype with
the generic AS block pointer parameter to accommodate both
private and global AS cases from above;
- add block handling into default AS because it's implemented as
a special pointer type (BlockPointer) in the frontend and therefore
it is used as a pointer everywhere. This is also needed to accommodate
both private and global AS blocks for the two cases above.
- removes ObjC RT specific symbols (NSConcreteStackBlock and
NSConcreteGlobalBlock) in the OpenCL mode.
Review: https://reviews.llvm.org/D28814
llvm-svn: 293286
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/Expr.cpp | 5 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGBlocks.cpp | 79 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGBuiltin.cpp | 46 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 23 | ||||
-rw-r--r-- | clang/lib/Sema/SemaType.cpp | 6 |
5 files changed, 115 insertions, 44 deletions
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index 14f31d0c6b8..366e5bf404f 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -1571,8 +1571,9 @@ bool CastExpr::CastConsistency() const { goto CheckNoBasePath; case CK_AddressSpaceConversion: - assert(getType()->isPointerType()); - assert(getSubExpr()->getType()->isPointerType()); + assert(getType()->isPointerType() || getType()->isBlockPointerType()); + assert(getSubExpr()->getType()->isPointerType() || + getSubExpr()->getType()->isBlockPointerType()); assert(getType()->getPointeeType().getAddressSpace() != getSubExpr()->getType()->getPointeeType().getAddressSpace()); // These should not have an inheritance path. 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), diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index b3d02f1f51c..b1feefe9f0d 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -2493,6 +2493,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, llvm::Type *QueueTy = ConvertType(getContext().OCLQueueTy); llvm::Type *RangeTy = ConvertType(getContext().OCLNDRangeTy); + llvm::Type *GenericVoidPtrTy = Builder.getInt8PtrTy( + getContext().getTargetAddressSpace(LangAS::opencl_generic)); llvm::Value *Queue = EmitScalarExpr(E->getArg(0)); llvm::Value *Flags = EmitScalarExpr(E->getArg(1)); @@ -2502,12 +2504,12 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, // The most basic form of the call with parameters: // queue_t, kernel_enqueue_flags_t, ndrange_t, block(void) Name = "__enqueue_kernel_basic"; - llvm::Type *ArgTys[] = {QueueTy, Int32Ty, RangeTy, Int8PtrTy}; + llvm::Type *ArgTys[] = {QueueTy, Int32Ty, RangeTy, GenericVoidPtrTy}; llvm::FunctionType *FTy = llvm::FunctionType::get( Int32Ty, llvm::ArrayRef<llvm::Type *>(ArgTys, 4), false); - llvm::Value *Block = - Builder.CreateBitCast(EmitScalarExpr(E->getArg(3)), Int8PtrTy); + llvm::Value *Block = Builder.CreatePointerCast( + EmitScalarExpr(E->getArg(3)), GenericVoidPtrTy); return RValue::get(Builder.CreateCall( CGM.CreateRuntimeFunction(FTy, Name), {Queue, Flags, Range, Block})); @@ -2518,14 +2520,14 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, if (E->getArg(3)->getType()->isBlockPointerType()) { // No events passed, but has variadic arguments. Name = "__enqueue_kernel_vaargs"; - llvm::Value *Block = - Builder.CreateBitCast(EmitScalarExpr(E->getArg(3)), Int8PtrTy); + llvm::Value *Block = Builder.CreatePointerCast( + EmitScalarExpr(E->getArg(3)), GenericVoidPtrTy); // Create a vector of the arguments, as well as a constant value to // express to the runtime the number of variadic arguments. std::vector<llvm::Value *> Args = {Queue, Flags, Range, Block, ConstantInt::get(IntTy, NumArgs - 4)}; - std::vector<llvm::Type *> ArgTys = {QueueTy, IntTy, RangeTy, Int8PtrTy, - IntTy}; + std::vector<llvm::Type *> ArgTys = {QueueTy, IntTy, RangeTy, + GenericVoidPtrTy, IntTy}; // Each of the following arguments specifies the size of the corresponding // argument passed to the enqueued block. @@ -2555,12 +2557,12 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, // Convert to generic address space. EventList = Builder.CreatePointerCast(EventList, EventPtrTy); ClkEvent = Builder.CreatePointerCast(ClkEvent, EventPtrTy); - llvm::Value *Block = - Builder.CreateBitCast(EmitScalarExpr(E->getArg(6)), Int8PtrTy); + llvm::Value *Block = Builder.CreatePointerCast( + EmitScalarExpr(E->getArg(6)), GenericVoidPtrTy); - std::vector<llvm::Type *> ArgTys = {QueueTy, Int32Ty, RangeTy, - Int32Ty, EventPtrTy, EventPtrTy, - Int8PtrTy}; + std::vector<llvm::Type *> ArgTys = { + QueueTy, Int32Ty, RangeTy, Int32Ty, + EventPtrTy, EventPtrTy, GenericVoidPtrTy}; std::vector<llvm::Value *> Args = {Queue, Flags, Range, NumEvents, EventList, ClkEvent, Block}; @@ -2596,20 +2598,24 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, // OpenCL v2.0 s6.13.17.6 - Kernel query functions need bitcast of block // parameter. case Builtin::BIget_kernel_work_group_size: { + llvm::Type *GenericVoidPtrTy = Builder.getInt8PtrTy( + getContext().getTargetAddressSpace(LangAS::opencl_generic)); Value *Arg = EmitScalarExpr(E->getArg(0)); - Arg = Builder.CreateBitCast(Arg, Int8PtrTy); - return RValue::get( - Builder.CreateCall(CGM.CreateRuntimeFunction( - llvm::FunctionType::get(IntTy, Int8PtrTy, false), - "__get_kernel_work_group_size_impl"), - Arg)); + Arg = Builder.CreatePointerCast(Arg, GenericVoidPtrTy); + return RValue::get(Builder.CreateCall( + CGM.CreateRuntimeFunction( + llvm::FunctionType::get(IntTy, GenericVoidPtrTy, false), + "__get_kernel_work_group_size_impl"), + Arg)); } case Builtin::BIget_kernel_preferred_work_group_size_multiple: { + llvm::Type *GenericVoidPtrTy = Builder.getInt8PtrTy( + getContext().getTargetAddressSpace(LangAS::opencl_generic)); Value *Arg = EmitScalarExpr(E->getArg(0)); - Arg = Builder.CreateBitCast(Arg, Int8PtrTy); + Arg = Builder.CreatePointerCast(Arg, GenericVoidPtrTy); return RValue::get(Builder.CreateCall( CGM.CreateRuntimeFunction( - llvm::FunctionType::get(IntTy, Int8PtrTy, false), + llvm::FunctionType::get(IntTy, GenericVoidPtrTy, false), "__get_kernel_preferred_work_group_multiple_impl"), Arg)); } diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 43242390597..ca57a413e91 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -7405,7 +7405,13 @@ checkBlockPointerTypesForAssignment(Sema &S, QualType LHSType, Sema::AssignConvertType ConvTy = Sema::Compatible; // For blocks we enforce that qualifiers are identical. - if (lhptee.getLocalQualifiers() != rhptee.getLocalQualifiers()) + Qualifiers LQuals = lhptee.getLocalQualifiers(); + Qualifiers RQuals = rhptee.getLocalQualifiers(); + if (S.getLangOpts().OpenCL) { + LQuals.removeAddressSpace(); + RQuals.removeAddressSpace(); + } + if (LQuals != RQuals) ConvTy = Sema::CompatiblePointerDiscardsQualifiers; if (!S.Context.typesAreBlockPointerCompatible(LHSType, RHSType)) @@ -7630,7 +7636,12 @@ Sema::CheckAssignmentConstraints(QualType LHSType, ExprResult &RHS, // U^ -> void* if (RHSType->getAs<BlockPointerType>()) { if (LHSPointer->getPointeeType()->isVoidType()) { - Kind = CK_BitCast; + unsigned AddrSpaceL = LHSPointer->getPointeeType().getAddressSpace(); + unsigned AddrSpaceR = RHSType->getAs<BlockPointerType>() + ->getPointeeType() + .getAddressSpace(); + Kind = + AddrSpaceL != AddrSpaceR ? CK_AddressSpaceConversion : CK_BitCast; return Compatible; } } @@ -7642,7 +7653,13 @@ Sema::CheckAssignmentConstraints(QualType LHSType, ExprResult &RHS, if (isa<BlockPointerType>(LHSType)) { // U^ -> T^ if (RHSType->isBlockPointerType()) { - Kind = CK_BitCast; + unsigned AddrSpaceL = LHSType->getAs<BlockPointerType>() + ->getPointeeType() + .getAddressSpace(); + unsigned AddrSpaceR = RHSType->getAs<BlockPointerType>() + ->getPointeeType() + .getAddressSpace(); + Kind = AddrSpaceL != AddrSpaceR ? CK_AddressSpaceConversion : CK_BitCast; return checkBlockPointerTypesForAssignment(*this, LHSType, RHSType); } diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index e4995bd2206..92a2ecc2275 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -6942,8 +6942,10 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type, (TAL == TAL_DeclSpec || TAL == TAL_DeclChunk)) { Declarator &D = state.getDeclarator(); if (state.getCurrentChunkIndex() > 0 && - D.getTypeObject(state.getCurrentChunkIndex() - 1).Kind == - DeclaratorChunk::Pointer) { + (D.getTypeObject(state.getCurrentChunkIndex() - 1).Kind == + DeclaratorChunk::Pointer || + D.getTypeObject(state.getCurrentChunkIndex() - 1).Kind == + DeclaratorChunk::BlockPointer)) { type = state.getSema().Context.getAddrSpaceQualType( type, LangAS::opencl_generic); } else if (state.getCurrentChunkIndex() == 0 && |