@@ -70,6 +70,23 @@ static size_t getOCLCpp11AtomicMaxNumOps(StringRef Name) {
7070 .Default (0 );
7171}
7272
73+ static Type *getBlockStructType (Value *Parameter) {
74+ // In principle, this information should be passed to us from Clang via
75+ // an elementtype attribute. However, said attribute requires that the
76+ // function call be an intrinsic, which it is not. Instead, we rely on being
77+ // able to trace this to the declaration of a variable: OpenCL C specification
78+ // section 6.12.5 should guarantee that we can do this.
79+ Value *UnderlyingObject = Parameter->stripPointerCasts ();
80+ Type *ParamType = nullptr ;
81+ if (auto *GV = dyn_cast<GlobalValue>(UnderlyingObject))
82+ ParamType = GV->getValueType ();
83+ else if (auto *Alloca = dyn_cast<AllocaInst>(UnderlyingObject))
84+ ParamType = Alloca->getAllocatedType ();
85+ else
86+ llvm_unreachable (" Blocks in OpenCL C must be traceable to allocation site" );
87+ return ParamType;
88+ }
89+
7390class OCLToSPIRVBase : public InstVisitor <OCLToSPIRVBase> {
7491public:
7592 OCLToSPIRVBase () : M(nullptr ), Ctx(nullptr ), CLVer(0 ) {}
@@ -674,11 +691,9 @@ CallInst *OCLToSPIRVBase::visitCallAtomicCmpXchg(CallInst *CI) {
674691 M, CI,
675692 [&](CallInst *CI, std::vector<Value *> &Args, Type *&RetTy) {
676693 Expected = Args[1 ]; // temporary save second argument.
677- Args[1 ] = new LoadInst (Args[1 ]->getType ()->getPointerElementType (),
678- Args[1 ], " exp" , false , CI);
679694 RetTy = Args[2 ]->getType ();
680- assert ( Args[0 ]-> getType ()-> getPointerElementType ()-> isIntegerTy () &&
681- Args[1 ]->getType ()->isIntegerTy () &&
695+ Args[1 ] = new LoadInst (RetTy, Args[ 1 ], " exp " , false , CI);
696+ assert ( Args[1 ]->getType ()->isIntegerTy () &&
682697 Args[2 ]->getType ()->isIntegerTy () &&
683698 " In SPIR-V 1.0 arguments of OpAtomicCompareExchange must be "
684699 " an integer type scalars" );
@@ -1584,9 +1599,7 @@ void OCLToSPIRVBase::visitCallEnqueueKernel(CallInst *CI,
15841599 // Param Size: Size of block literal structure
15851600 // Param Aligment: Aligment of block literal structure
15861601 // TODO: these numbers should be obtained from block literal structure
1587- Type *ParamType = getUnderlyingObject (BlockLiteral)->getType ();
1588- if (PointerType *PT = dyn_cast<PointerType>(ParamType))
1589- ParamType = PT->getPointerElementType ();
1602+ Type *ParamType = getBlockStructType (BlockLiteral);
15901603 Args.push_back (getInt32 (M, DL.getTypeStoreSize (ParamType)));
15911604 Args.push_back (getInt32 (M, DL.getPrefTypeAlignment (ParamType)));
15921605
@@ -1636,10 +1649,7 @@ void OCLToSPIRVBase::visitCallKernelQuery(CallInst *CI,
16361649 M, CI,
16371650 [=](CallInst *CI, std::vector<Value *> &Args) {
16381651 Value *Param = *Args.rbegin ();
1639- Type *ParamType = getUnderlyingObject (Param)->getType ();
1640- if (PointerType *PT = dyn_cast<PointerType>(ParamType)) {
1641- ParamType = PT->getPointerElementType ();
1642- }
1652+ Type *ParamType = getBlockStructType (Param);
16431653 // Last arg corresponds to SPIRV Param operand.
16441654 // Insert Invoke in front of Param.
16451655 // Add Param Size and Param Align at the end.
0 commit comments