[OpenCL] Blocks are allowed to capture arrays


I’m working on the following patch: https://reviews.llvm.org/D26794

In the beginning of the work it was a bug in spec: https://cvs.khronos.org/bugzilla/show_bug.cgi?id=15659 and it was fixed in rev. 39 (example 5, chapter 6.12.5): https://cvs.khronos.org/svn/repos/OpenCL/trunk/Khronos/specs/opencl20-openclc-rev39.pdf

After these changes in specification, block capture semantics follows regular C argument passing convention, i.e. arrays are captured by reference (decayed to pointers) and structs are captured by value. But in current implementation array will be captured by value in both cases.

I added new check in function EmitBlockLiteral in file CGBlocks.cpp where I check if type is array, I do some operations for keeping reference to initial array. I think that the code in this check should work correctly (I saw how it works for cpp lambdas). But I cannot check it because type of captured variable in block is [4 x i32]. For keeping reference I expect that it should be [4 x i32]* or i8*.

I tried to get the pointer on array by two different ways:

  1. I extended an if statement in file SemaExpr.cpp in function: captureInBlock. In the following statement I added OpenCL check:

if (HasBlocksAttr || CaptureType->isReferenceType() ||

(S.getLangOpts().OpenMP && S.IsOpenMPCapturedDecl(Var)) ||

(S.getLangOpts().OpenCL && CaptureType->isArrayType())) {

// Block capture by reference does not change the capture or // declaration reference types.

ByRef = true;

And also, in the same file in function ActOnBlockStmtExpr. I added check if captured value is reference capture:

BlockDecl::Capture NewCap(Cap.getVariable(), Cap.isBlockCapture() || Cap.isReferenceCapture(),

Cap.isNested(), Cap.getInitExpr());

I thought that it will get me a reference to the array. But it doesn’t work and fails when I try to get llvm ir with the following assert: “clang: ./llvm/include/llvm/IR/Instructions.h:832: llvm::Type* llvm::checkGEPType(llvm::Type*): Assertion `Ty && “Invalid GetElementPtrInst indices for type!”’ failed.

And in the AST I have capturing variable in block by reference:

`-BlockDecl 0xa14cd00 <col:17, col:35> col:17

|-capture byref Var 0xa14cab0 ‘arr’ ‘int [4]’

`-CompoundStmt 0xa171b58 <col:20, col:35>

`-ReturnStmt 0xa171b40 <col:21, col:33>

`-ImplicitCastExpr 0xa171b28 <col:28, col:33> ‘int’

`-ArraySubscriptExpr 0xa171b00 <col:28, col:33> ‘int’ lvalue

|-ImplicitCastExpr 0xa171ae8 col:28 ‘int *’

| `-DeclRefExpr 0xa171a70 col:28 ‘int [4]’ lvalue Var 0xa14cab0 ‘arr’ ‘int [4]’

`-IntegerLiteral 0xa171a98 col:32 ‘int’ 1

  1. Also, I tried to set capture type to a reference on the array. In file SemaExpr.cpp in function tryCaptureVariable after a loop: “} while (!VarDC->Equals(DC));”, I added the following lines:\

if (getLangOpts().OpenCL && CaptureType.getTypePtr()->isArrayType()) {

CaptureType = Context.getLValueReferenceType(CaptureType);


But nothing interesting has happen. No changes in AST or llvm ir.

Could you please help me? What is the better way to get the pointer on array?

Best regards,