Forces the SPIR kernel calling convention for OpenCL C kernels by default. This is to make the host-visible functions always to have 1:1 arguments with the clSetKernelArgument() calls and to avoid the need for target-specific handling while still enabling target-specific CC/ABI and optimizations for the rest of the program. Index: lib/Basic/Targets.cpp =================================================================== --- lib/Basic/Targets.cpp (revision 292207) +++ lib/Basic/Targets.cpp (working copy) @@ -2801,6 +2801,7 @@ case CC_Swift: case CC_X86Pascal: case CC_IntelOclBicc: + case CC_OpenCLKernel: return CCCR_OK; default: return CCCR_Warning; @@ -4380,6 +4381,7 @@ case CC_X86_64Win64: case CC_PreserveMost: case CC_PreserveAll: + case CC_OpenCLKernel: return CCCR_OK; default: return CCCR_Warning; @@ -4447,6 +4449,7 @@ case CC_X86VectorCall: case CC_IntelOclBicc: case CC_X86_64SysV: + case CC_OpenCLKernel: return CCCR_OK; default: return CCCR_Warning; @@ -5386,6 +5389,7 @@ case CC_AAPCS: case CC_AAPCS_VFP: case CC_Swift: + case CC_OpenCLKernel: return CCCR_OK; default: return CCCR_Warning; @@ -5543,6 +5547,7 @@ case CC_X86VectorCall: return CCCR_Ignore; case CC_C: + case CC_OpenCLKernel: return CCCR_OK; default: return CCCR_Warning; @@ -5853,6 +5858,7 @@ case CC_Swift: case CC_PreserveMost: case CC_PreserveAll: + case CC_OpenCLKernel: return CCCR_OK; default: return CCCR_Warning; @@ -7048,6 +7054,15 @@ ArrayRef getGCCRegAliases() const override { return None; } + CallingConvCheckResult checkCallingConvention(CallingConv CC) const override { + switch (CC) { + default: + return CCCR_Warning; + case CC_C: + case CC_OpenCLKernel: + return CCCR_OK; + } + } }; class BPFTargetInfo : public TargetInfo { Index: lib/CodeGen/ABIInfo.h =================================================================== --- lib/CodeGen/ABIInfo.h (revision 292207) +++ lib/CodeGen/ABIInfo.h (working copy) @@ -146,7 +146,6 @@ return info->supportsSwift(); } }; - } // end namespace CodeGen } // end namespace clang Index: lib/CodeGen/CGCall.cpp =================================================================== --- lib/CodeGen/CGCall.cpp (revision 292207) +++ lib/CodeGen/CGCall.cpp (working copy) @@ -665,6 +665,12 @@ signature.getRequiredArgs()); } +namespace clang { +namespace CodeGen { +void computeSPIRKernelABIInfo(CodeGenModule &CGM, CGFunctionInfo &FI); +} +} + /// Arrange the argument and result information for an abstract value /// of a given function type. This is the method which all of the /// above functions ultimately defer to. @@ -699,12 +705,16 @@ bool inserted = FunctionsBeingProcessed.insert(FI).second; (void)inserted; assert(inserted && "Recursively being processed?"); - + // Compute ABI information. - if (info.getCC() != CC_Swift) { + if (CC == llvm::CallingConv::SPIR_KERNEL) { + // Force target independent argument handling for the host visible + // kernel functions. + computeSPIRKernelABIInfo(CGM, *FI); + } else if (info.getCC() == CC_Swift) { + swiftcall::computeABIInfo(CGM, *FI); + } else { getABIInfo().computeInfo(*FI); - } else { - swiftcall::computeABIInfo(CGM, *FI); } // Loop over all of the computed argument and return value info. If any of Index: lib/CodeGen/TargetInfo.cpp =================================================================== --- lib/CodeGen/TargetInfo.cpp (revision 292207) +++ lib/CodeGen/TargetInfo.cpp (working copy) @@ -373,7 +373,16 @@ } unsigned TargetCodeGenInfo::getOpenCLKernelCallingConv() const { - return llvm::CallingConv::C; + // OpenCL kernels are called via explicit runtime APIs with arguments + // set with clSetKernelArg(). Return SPIR_KERNEL by default as the + // kernel calling convention to ensure the finger print is fixed such way + // that each OpenCL argument gets one matching argument in the produced + // kernel function argument list. In case using the C calling conv here, + // clSetKernelArg() might breaks depending on the target's specific + // conventions as different targets might split structs passed as values + // to multiple function arguments etc. + // See: https://github.com/pocl/pocl/issues/1 + return llvm::CallingConv::SPIR_KERNEL; } static bool isEmptyRecord(ASTContext &Context, QualType T, bool AllowArrays); @@ -7514,8 +7523,18 @@ CodeGen::CodeGenModule &M) const override; unsigned getOpenCLKernelCallingConv() const override; }; + } // End anonymous namespace. +namespace clang { +namespace CodeGen { +void computeSPIRKernelABIInfo(CodeGenModule &CGM, CGFunctionInfo &FI) { + DefaultABIInfo SPIRABI(CGM.getTypes()); + SPIRABI.computeInfo(FI); +} +} +} + /// Emit SPIR specific metadata: OpenCL and SPIR version. void SPIRTargetCodeGenInfo::emitTargetMD(const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &CGM) const { Index: lib/Sema/SemaType.cpp =================================================================== --- lib/Sema/SemaType.cpp (revision 292207) +++ lib/Sema/SemaType.cpp (working copy) @@ -3192,16 +3192,11 @@ for (const AttributeList *Attr = D.getDeclSpec().getAttributes().getList(); Attr; Attr = Attr->getNext()) { if (Attr->getKind() == AttributeList::AT_OpenCLKernel) { - llvm::Triple::ArchType arch = S.Context.getTargetInfo().getTriple().getArch(); - if (arch == llvm::Triple::spir || arch == llvm::Triple::spir64 || - arch == llvm::Triple::amdgcn) { - CC = CC_OpenCLKernel; - } + CC = CC_OpenCLKernel; break; } } } - return CC; }