diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -9520,9 +9520,12 @@ // Blocks def err_blocks_disable : Error<"blocks support disabled - compile with -fblocks" - " or %select{pick a deployment target that supports them|for OpenCL 2.0}0">; + " or %select{pick a deployment target that supports them|for OpenCL C 2.0" + " or OpenCL C 3.0 with __opencl_c_device_enqueue feature}0">; def err_block_returning_array_function : Error< "block cannot return %select{array|function}0 type %1">; +def err_constant_blocks_not_supported : Error<"constant blocks not supported yet" + " without __opencl_c_program_scope_global_variables feature for OpenCL C 3.0">; // Builtin annotation def err_builtin_annotation_first_arg : Error< diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -1568,6 +1568,7 @@ const LangOptions &getLangOpts() const { return LangOpts; } OpenCLOptions &getOpenCLOptions() { return OpenCLFeatures; } + const OpenCLOptions &getOpenCLOptions() const { return OpenCLFeatures; } FPOptions &getCurFPFeatures() { return CurFPFeatures; } DiagnosticsEngine &getDiagnostics() const { return Diags; } diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -8614,11 +8614,7 @@ { return Success(E); } bool VisitCallExpr(const CallExpr *E); bool VisitBuiltinCallExpr(const CallExpr *E, unsigned BuiltinOp); - bool VisitBlockExpr(const BlockExpr *E) { - if (!E->getBlockDecl()->hasCaptures()) - return Success(E); - return Error(E); - } + bool VisitBlockExpr(const BlockExpr *E); bool VisitCXXThisExpr(const CXXThisExpr *E) { // Can't look at 'this' when checking a potential constant expression. if (Info.checkingPotentialConstantExpression()) @@ -9549,6 +9545,23 @@ return true; } + +bool PointerExprEvaluator::VisitBlockExpr(const BlockExpr *E) { + if (!E->getBlockDecl()->hasCaptures()) { + if (!Info.Ctx.getLangOpts().OpenCL) + return Success(E); + + const auto &OpenCLFeaturesMap = + Info.Ctx.getTargetInfo().getSupportedOpenCLOpts(); + return (Info.Ctx.getLangOpts().getOpenCLCompatibleVersion() == 200) || + Info.Ctx.getTargetInfo().hasFeatureEnabled( + OpenCLFeaturesMap, + "__opencl_c_program_scope_global_variables") + ? Success(E) + : Error(E); + } + return Error(E); +} //===----------------------------------------------------------------------===// // Member Pointer Evaluation //===----------------------------------------------------------------------===// diff --git a/clang/lib/Basic/OpenCLOptions.cpp b/clang/lib/Basic/OpenCLOptions.cpp --- a/clang/lib/Basic/OpenCLOptions.cpp +++ b/clang/lib/Basic/OpenCLOptions.cpp @@ -113,7 +113,8 @@ static const llvm::StringMap DependentFeaturesMap = { {"__opencl_c_read_write_images", "__opencl_c_images"}, {"__opencl_c_3d_image_writes", "__opencl_c_images"}, - {"__opencl_c_pipes", "__opencl_c_generic_address_space"}}; + {"__opencl_c_pipes", "__opencl_c_generic_address_space"}, + {"__opencl_c_device_enqueue", "__opencl_c_generic_address_space"}}; auto OpenCLFeaturesMap = TI.getSupportedOpenCLOpts(); diff --git a/clang/lib/Basic/TargetInfo.cpp b/clang/lib/Basic/TargetInfo.cpp --- a/clang/lib/Basic/TargetInfo.cpp +++ b/clang/lib/Basic/TargetInfo.cpp @@ -416,6 +416,8 @@ OpenCLFeaturesMap, "__opencl_c_generic_address_space"); Opts.OpenCLPipes = hasFeatureEnabled(OpenCLFeaturesMap, "__opencl_c_pipes"); + Opts.Blocks = + hasFeatureEnabled(OpenCLFeaturesMap, "__opencl_c_device_enqueue"); } } diff --git a/clang/lib/CodeGen/CGBlocks.cpp b/clang/lib/CodeGen/CGBlocks.cpp --- a/clang/lib/CodeGen/CGBlocks.cpp +++ b/clang/lib/CodeGen/CGBlocks.cpp @@ -527,18 +527,22 @@ SmallVector elementTypes; initializeForBlockHeader(CGM, info, elementTypes); bool hasNonConstantCustomFields = false; + // OpenCL doesn't support global blocks if the feature for program scope + // global variables is not supported. + bool globalBlockIsSupported = + !CGM.getLangOpts().OpenCL || CGM.getOpenCLRuntime().blockCanBeGlobal(); if (auto *OpenCLHelper = CGM.getTargetCodeGenInfo().getTargetOpenCLBlockHelper()) hasNonConstantCustomFields = !OpenCLHelper->areAllCustomFieldValuesConstant(info); - if (!block->hasCaptures() && !hasNonConstantCustomFields) { + if (!block->hasCaptures() && !hasNonConstantCustomFields && + globalBlockIsSupported) { info.StructureType = llvm::StructType::get(CGM.getLLVMContext(), elementTypes, true); info.CanBeGlobal = true; return; - } - else if (C.getLangOpts().ObjC && - CGM.getLangOpts().getGC() == LangOptions::NonGC) + } else if (C.getLangOpts().ObjC && + CGM.getLangOpts().getGC() == LangOptions::NonGC) info.HasCapturedVariableLayout = true; // Collect the layout chunks. @@ -664,7 +668,8 @@ if (layout.empty()) { info.StructureType = llvm::StructType::get(CGM.getLLVMContext(), elementTypes, true); - info.CanBeGlobal = true; + if (globalBlockIsSupported) + info.CanBeGlobal = true; return; } @@ -1294,7 +1299,6 @@ // Compute information about the layout, etc., of this block. computeBlockInfo(*this, nullptr, blockInfo); - // Using that metadata, generate the actual block function. { CodeGenFunction::DeclMapTy LocalDeclMap; diff --git a/clang/lib/CodeGen/CGOpenCLRuntime.h b/clang/lib/CodeGen/CGOpenCLRuntime.h --- a/clang/lib/CodeGen/CGOpenCLRuntime.h +++ b/clang/lib/CodeGen/CGOpenCLRuntime.h @@ -95,6 +95,9 @@ /// \return LLVM block invoke function emitted for an expression derived from /// the block expression. llvm::Function *getInvokeFunction(const Expr *E); + + /// \return true if block can be emitted as global. + bool blockCanBeGlobal(); }; } diff --git a/clang/lib/CodeGen/CGOpenCLRuntime.cpp b/clang/lib/CodeGen/CGOpenCLRuntime.cpp --- a/clang/lib/CodeGen/CGOpenCLRuntime.cpp +++ b/clang/lib/CodeGen/CGOpenCLRuntime.cpp @@ -184,3 +184,17 @@ EnqueuedBlockMap[Block].Kernel = F; return EnqueuedBlockMap[Block]; } + +// Always generate global blocks for OpenCL C 2.0. +// For higher OpenCL versions check __opencl_c_program_scope_global_variable +// feature support. +bool CGOpenCLRuntime::blockCanBeGlobal() { + const auto &LO = CGM.getLangOpts(); + assert(LO.OpenCL && (LO.getOpenCLCompatibleVersion() >= 200) && + "Not expecting to generate blocks"); + if (LO.getOpenCLCompatibleVersion() == 200) + return true; + const auto &OpenCLFeaturesMap = CGM.getTarget().getSupportedOpenCLOpts(); + return CGM.getTarget().hasFeatureEnabled( + OpenCLFeaturesMap, "__opencl_c_program_scope_global_variables"); +} diff --git a/clang/lib/Headers/opencl-c-base.h b/clang/lib/Headers/opencl-c-base.h --- a/clang/lib/Headers/opencl-c-base.h +++ b/clang/lib/Headers/opencl-c-base.h @@ -498,12 +498,14 @@ #define MAX_WORK_DIM 3 +#ifdef __opencl_c_device_enqueue typedef struct { unsigned int workDimension; size_t globalWorkOffset[MAX_WORK_DIM]; size_t globalWorkSize[MAX_WORK_DIM]; size_t localWorkSize[MAX_WORK_DIM]; } ndrange_t; +#endif // __opencl_c_device_enqueue #endif // defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) diff --git a/clang/lib/Headers/opencl-c.h b/clang/lib/Headers/opencl-c.h --- a/clang/lib/Headers/opencl-c.h +++ b/clang/lib/Headers/opencl-c.h @@ -16447,6 +16447,7 @@ // OpenCL v2.0 s6.13.17 - Enqueue Kernels #if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) +#ifdef __opencl_c_device_enqueue ndrange_t __ovld ndrange_1D(size_t); ndrange_t __ovld ndrange_1D(size_t, size_t); ndrange_t __ovld ndrange_1D(size_t, size_t, size_t); @@ -16474,6 +16475,8 @@ void __ovld capture_event_profiling_info(clk_event_t, clk_profiling_info, __global void* value); queue_t __ovld get_default_queue(void); +#endif //__opencl_c_device_enqueue + #endif //defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) // OpenCL Extension v2.0 s9.17 - Sub-groups diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -324,9 +324,13 @@ Context.getTargetInfo().getSupportedOpenCLOpts(), getLangOpts()); addImplicitTypedef("sampler_t", Context.OCLSamplerTy); addImplicitTypedef("event_t", Context.OCLEventTy); - if (getLangOpts().getOpenCLCompatibleVersion() >= 200) { - addImplicitTypedef("clk_event_t", Context.OCLClkEventTy); - addImplicitTypedef("queue_t", Context.OCLQueueTy); + auto OCLCompatibleVersion = getLangOpts().getOpenCLCompatibleVersion(); + if (OCLCompatibleVersion >= 200) { + if ((OCLCompatibleVersion == 200) || + (OCLCompatibleVersion == 300 && getLangOpts().Blocks)) { + addImplicitTypedef("clk_event_t", Context.OCLClkEventTy); + addImplicitTypedef("queue_t", Context.OCLQueueTy); + } if (getLangOpts().OpenCLPipes) addImplicitTypedef("reserve_id_t", Context.OCLReserveIDTy); addImplicitTypedef("atomic_int", Context.getAtomicType(Context.IntTy)); @@ -394,7 +398,6 @@ } } - #define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \ if (getOpenCLOptions().isSupported(#Ext, getLangOpts())) { \ addImplicitTypedef(#ExtType, Context.Id##Ty); \ diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -8021,6 +8021,14 @@ } if (T->isBlockPointerType()) { + if ((T.getAddressSpace() == LangAS::opencl_constant) && + !getOpenCLOptions().areProgramScopeVariablesSupported( + getLangOpts())) { + Diag(NewVD->getLocation(), diag::err_constant_blocks_not_supported); + NewVD->setInvalidDecl(); + return; + } + // OpenCL v2.0 s6.12.5 - Any block declaration must be const qualified and // can't use 'extern' storage class. if (!T.isConstQualified()) { diff --git a/clang/test/CodeGenOpenCL/address-spaces-mangling.cl b/clang/test/CodeGenOpenCL/address-spaces-mangling.cl --- a/clang/test/CodeGenOpenCL/address-spaces-mangling.cl +++ b/clang/test/CodeGenOpenCL/address-spaces-mangling.cl @@ -9,9 +9,9 @@ // RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=CL2.0 -emit-llvm -o - | FileCheck -check-prefix=OCL-20 %s // RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=CL1.2 -emit-llvm -o - | FileCheck -check-prefix=OCL-12 %s // RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=CL3.0 -cl-ext=+__opencl_c_generic_address_space -emit-llvm -o - | FileCheck -check-prefix=OCL-20 %s -// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=CL3.0 -cl-ext=-__opencl_c_generic_address_space,-__opencl_c_pipes -emit-llvm -o - | FileCheck -check-prefix=OCL-12 %s +// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=CL3.0 -cl-ext=-__opencl_c_generic_address_space,-__opencl_c_pipes,-__opencl_c_device_enqueue -emit-llvm -o - | FileCheck -check-prefix=OCL-12 %s // RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=clc++2021 -cl-ext=+__opencl_c_generic_address_space -emit-llvm -o - | FileCheck -check-prefix=OCL-20 %s -// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=clc++2021 -cl-ext=-__opencl_c_generic_address_space,-__opencl_c_pipes -emit-llvm -o - | FileCheck -check-prefix=OCL-12 %s +// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=clc++2021 -cl-ext=-__opencl_c_generic_address_space,-__opencl_c_pipes,-__opencl_c_device_enqueue -emit-llvm -o - | FileCheck -check-prefix=OCL-12 %s // We can't name this f as private is equivalent to default // no specifier given address space so we get multiple definition diff --git a/clang/test/CodeGenOpenCL/address-spaces.cl b/clang/test/CodeGenOpenCL/address-spaces.cl --- a/clang/test/CodeGenOpenCL/address-spaces.cl +++ b/clang/test/CodeGenOpenCL/address-spaces.cl @@ -1,6 +1,6 @@ // RUN: %clang_cc1 %s -O0 -ffake-address-space-map -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,SPIR -// RUN: %clang_cc1 %s -O0 -cl-std=CL3.0 -cl-ext=-__opencl_c_generic_address_space,-__opencl_c_pipes -ffake-address-space-map -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,SPIR -// RUN: %clang_cc1 %s -O0 -cl-std=clc++2021 -cl-ext=-__opencl_c_generic_address_space,-__opencl_c_pipes -ffake-address-space-map -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,SPIR +// RUN: %clang_cc1 %s -O0 -cl-std=CL3.0 -cl-ext=-__opencl_c_generic_address_space,-__opencl_c_pipes,-__opencl_c_device_enqueue -ffake-address-space-map -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,SPIR +// RUN: %clang_cc1 %s -O0 -cl-std=clc++2021 -cl-ext=-__opencl_c_generic_address_space,-__opencl_c_pipes,-__opencl_c_device_enqueue -ffake-address-space-map -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,SPIR // RUN: %clang_cc1 %s -O0 -DCL20 -cl-std=CL2.0 -ffake-address-space-map -emit-llvm -o - | FileCheck %s --check-prefixes=CL20,CL20SPIR // RUN: %clang_cc1 %s -O0 -triple amdgcn-amd-amdhsa -emit-llvm -o - | FileCheck --check-prefixes=CHECK,AMDGCN %s // RUN: %clang_cc1 %s -O0 -triple amdgcn-amd-amdhsa -cl-std=CL3.0 -emit-llvm -o - | FileCheck --check-prefixes=CHECK,AMDGCN %s diff --git a/clang/test/CodeGenOpenCL/blocks.cl b/clang/test/CodeGenOpenCL/blocks.cl --- a/clang/test/CodeGenOpenCL/blocks.cl +++ b/clang/test/CodeGenOpenCL/blocks.cl @@ -2,6 +2,10 @@ // RUN: %clang_cc1 %s -cl-std=CL2.0 -emit-llvm -o - -O0 -triple amdgcn-amd-amdhsa | FileCheck -check-prefixes=COMMON,AMDGCN %s // RUN: %clang_cc1 %s -cl-std=CL2.0 -emit-llvm -o - -O0 -debug-info-kind=limited -triple spir-unknown-unknown | FileCheck -check-prefixes=CHECK-DEBUG %s // RUN: %clang_cc1 %s -cl-std=CL2.0 -emit-llvm -o - -O0 -debug-info-kind=limited -triple amdgcn-amd-amdhsa | FileCheck -check-prefixes=CHECK-DEBUG %s +// RUN: %clang_cc1 %s -cl-std=CL3.0 -cl-ext=+__opencl_c_device_enqueue,+__opencl_c_generic_address_space,+__opencl_c_program_scope_global_variables -emit-llvm -o - -O0 -triple spir-unknown-unknown | FileCheck -check-prefixes=COMMON,SPIR %s +// RUN: %clang_cc1 %s -cl-std=CL3.0 -cl-ext=+__opencl_c_device_enqueue,+__opencl_c_generic_address_space,+__opencl_c_program_scope_global_variables -emit-llvm -o - -O0 -triple amdgcn-amd-amdhsa | FileCheck -check-prefixes=COMMON,AMDGCN %s +// RUN: %clang_cc1 %s -cl-std=CL3.0 -cl-ext=+__opencl_c_device_enqueue,+__opencl_c_generic_address_space,+__opencl_c_program_scope_global_variables -emit-llvm -o - -O0 -debug-info-kind=limited -triple spir-unknown-unknown | FileCheck -check-prefixes=CHECK-DEBUG %s +// RUN: %clang_cc1 %s -cl-std=CL3.0 -cl-ext=+__opencl_c_device_enqueue,+__opencl_c_generic_address_space,+__opencl_c_program_scope_global_variables -emit-llvm -o - -O0 -debug-info-kind=limited -triple amdgcn-amd-amdhsa | FileCheck -check-prefixes=CHECK-DEBUG %s // SPIR: %struct.__opencl_block_literal_generic = type { i32, i32, i8 addrspace(4)* } // AMDGCN: %struct.__opencl_block_literal_generic = type { i32, i32, i8* } diff --git a/clang/test/CodeGenOpenCL/blocks_no_global_literal.cl b/clang/test/CodeGenOpenCL/blocks_no_global_literal.cl new file mode 100644 --- /dev/null +++ b/clang/test/CodeGenOpenCL/blocks_no_global_literal.cl @@ -0,0 +1,30 @@ +// RUN: %clang_cc1 %s -cl-std=CL3.0 -cl-ext=+__opencl_c_device_enqueue,+__opencl_c_generic_address_space,-__opencl_c_program_scope_global_variables -emit-llvm -o - -O0 -triple spir-unknown-unknown | FileCheck -check-prefixes=SPIR %s +// RUN: %clang_cc1 %s -cl-std=CL3.0 -cl-ext=+__opencl_c_device_enqueue,+__opencl_c_generic_address_space,-__opencl_c_program_scope_global_variables -emit-llvm -o - -O0 -triple amdgcn-amd-amdhsa | FileCheck -check-prefixes=AMDGCN %s + +// SPIR: %struct.__opencl_block_literal_generic = type { i32, i32, i8 addrspace(4)* } +// AMDGCN: %struct.__opencl_block_literal_generic = type { i32, i32, i8* } +// SPIR-NOT: @__block_literal_global = internal addrspace(1) constant { i32, i32, i8 addrspace(4)* } { i32 12, i32 4, i8 addrspace(4)* addrspacecast (i8* bitcast (void (i8 addrspace(4)*, i8 addrspace(3)*)* @block_A_block_invoke to i8*) to i8 addrspace(4)*) } +// AMDGCN-NOT: @__block_literal_global = internal addrspace(1) constant { i32, i32, i8* } { i32 16, i32 8, i8* bitcast (void (i8*, i8 addrspace(3)*)* @block_A_block_invoke to i8*) } + +void foo(local void *ptr){ + void (^block_A)(local void *) = ^(local void *a) { + return; + }; + // SPIR: %[[block:.*]] = alloca <{ i32, i32, i8 addrspace(4)* }> + // AMDGCN: %[[block:.*]] = alloca <{ i32, i32, i8* }> + // SPIR: %[[block_size:.*]] = getelementptr inbounds <{ i32, i32, i8 addrspace(4)* }>, <{ i32, i32, i8 addrspace(4)* }>* %[[block]], i32 0, i32 0 + // AMDGCN: %[[block_size:.*]] = getelementptr inbounds <{ i32, i32, i8* }>, <{ i32, i32, i8* }> addrspace(5)* %[[block]], i32 0, i32 0 + // SPIR: store i32 12, i32* %[[block_size]] + // AMDGCN: store i32 16, i32 addrspace(5)* %[[block_size]] + // SPIR: %[[block_align:.*]] = getelementptr inbounds <{ i32, i32, i8 addrspace(4)* }>, <{ i32, i32, i8 addrspace(4)* }>* %[[block]], i32 0, i32 1 + // AMDGCN: %[[block_align:.*]] = getelementptr inbounds <{ i32, i32, i8* }>, <{ i32, i32, i8* }> addrspace(5)* %[[block]], i32 0, i32 1 + // SPIR: store i32 4, i32* %[[block_align]] + // AMDGCN: store i32 8, i32 addrspace(5)* %[[block_align]] + // SPIR: %[[block_invoke:.*]] = getelementptr inbounds <{ i32, i32, i8 addrspace(4)* }>, <{ i32, i32, i8 addrspace(4)* }>* %[[block:.*]], i32 0, i32 2 + // SPIR: store i8 addrspace(4)* addrspacecast (i8* bitcast (void (i8 addrspace(4)*, i8 addrspace(3)*)* @__foo_block_invoke to i8*) to i8 addrspace(4)*), i8 addrspace(4)** %[[block_invoke]] + // AMDGCN: %[[block_invoke:.*]] = getelementptr inbounds <{ i32, i32, i8* }>, <{ i32, i32, i8* }> addrspace(5)* %[[block:.*]], i32 0, i32 2 + // AMDGCN: store i8* bitcast (void (i8*, i8 addrspace(3)*)* @__foo_block_invoke to i8*), i8* addrspace(5)* %[[block_invoke]] +} + +// SPIR-LABEL: define internal {{.*}}void @__foo_block_invoke(i8 addrspace(4)* %.block_descriptor, i8 addrspace(3)* %a) +// AMDGCN-LABEL: define internal {{.*}}void @__foo_block_invoke(i8* %.block_descriptor, i8 addrspace(3)* %a) diff --git a/clang/test/Frontend/opencl.cl b/clang/test/Frontend/opencl.cl --- a/clang/test/Frontend/opencl.cl +++ b/clang/test/Frontend/opencl.cl @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -verify -fsyntax-only -DSYNTAX +// RUN: %clang_cc1 %s -verify -fsyntax-only // RUN: %clang_cc1 %s -verify -fsyntax-only -cl-std=CL1.1 -DSYNTAX // RUN: %clang_cc1 %s -verify -fsyntax-only -cl-std=CL1.2 -DSYNTAX // RUN: %clang_cc1 %s -verify -fsyntax-only -cl-std=CL2.0 -DSYNTAX @@ -11,6 +11,7 @@ // RUN: %clang_cc1 -cl-std=CL1.2 -cl-strict-aliasing -fblocks %s 2>&1 | FileCheck --check-prefix=CHECK-INVALID-OPENCL-VERSION12 %s // RUN: %clang_cc1 -cl-std=CL2.0 -cl-strict-aliasing %s 2>&1 | FileCheck --check-prefix=CHECK-INVALID-OPENCL-VERSION20 %s // RUN: %clang_cc1 -cl-std=clc++1.0 -cl-strict-aliasing -fblocks %s 2>&1 | FileCheck --check-prefix=CHECK-INVALID-OPENCLCPP-VERSION10 %s +// RUN: %clang_cc1 %s -verify -fsyntax-only -cl-std=CL3.0 -cl-ext=-__opencl_c_device_enqueue,-__opencl_c_pipes,-__opencl_c_generic_address_space #ifdef SYNTAX class test{ @@ -25,7 +26,7 @@ typedef int (^bl_t)(void); #if defined(__OPENCL_C_VERSION__) || defined(__OPENCL_CPP_VERSION__) #if !defined(BLOCKS) && (defined(__OPENCL_CPP_VERSION__) || __OPENCL_C_VERSION__ != CL_VERSION_2_0) - // expected-error@-3{{blocks support disabled - compile with -fblocks or for OpenCL 2.0}} + // expected-error@-3{{blocks support disabled - compile with -fblocks or for OpenCL C 2.0 or OpenCL C 3.0 with __opencl_c_device_enqueue feature}} #endif #else // expected-error@-6{{blocks support disabled - compile with -fblocks or pick a deployment target that supports them}} diff --git a/clang/test/Misc/opencl-c-3.0.incorrect_options.cl b/clang/test/Misc/opencl-c-3.0.incorrect_options.cl --- a/clang/test/Misc/opencl-c-3.0.incorrect_options.cl +++ b/clang/test/Misc/opencl-c-3.0.incorrect_options.cl @@ -4,18 +4,22 @@ // RUN: not %clang_cc1 -cl-std=clc++2021 -triple spir-unknown-unknown -cl-ext=+__opencl_c_fp64,-cl_khr_fp64 %s 2>&1 | FileCheck -check-prefix=CHECK-FP64 %s // RUN: not %clang_cc1 -cl-std=CL3.0 -triple spir-unknown-unknown -cl-ext=+__opencl_c_read_write_images,-__opencl_c_images %s 2>&1 | FileCheck -check-prefix=CHECK-READ-WRITE-IMAGES %s // RUN: not %clang_cc1 -cl-std=clc++2021 -triple spir-unknown-unknown -cl-ext=+__opencl_c_read_write_images,-__opencl_c_images %s 2>&1 | FileCheck -check-prefix=CHECK-READ-WRITE-IMAGES %s -// RUN: not %clang_cc1 -cl-std=CL3.0 -triple spir-unknown-unknown -cl-ext=+__opencl_c_pipes,-__opencl_c_generic_address_space %s 2>&1 | FileCheck -check-prefix=CHECK-PIPES %s -// RUN: not %clang_cc1 -cl-std=clc++2021 -triple spir-unknown-unknown -cl-ext=+__opencl_c_pipes,-__opencl_c_generic_address_space %s 2>&1 | FileCheck -check-prefix=CHECK-PIPES %s +// RUN: not %clang_cc1 -cl-std=CL3.0 -triple spir-unknown-unknown -cl-ext=+__opencl_c_pipes,-__opencl_c_generic_address_space,-__opencl_c_device_enqueue %s 2>&1 | FileCheck -check-prefix=CHECK-PIPES %s +// RUN: not %clang_cc1 -cl-std=clc++2021 -triple spir-unknown-unknown -cl-ext=+__opencl_c_pipes,-__opencl_c_generic_address_space,-__opencl_c_device_enqueue %s 2>&1 | FileCheck -check-prefix=CHECK-PIPES %s // RUN: not %clang_cc1 -cl-std=CL3.0 -triple spir-unknown-unknown -cl-ext=+__opencl_c_3d_image_writes,+__opencl_c_images,-cl_khr_3d_image_writes %s 2>&1 | FileCheck -check-prefix=CHECK-3D-WRITE-IMAGES-DIFF %s // RUN: not %clang_cc1 -cl-std=CL3.0 -triple spir-unknown-unknown -cl-ext=+__opencl_c_3d_image_writes,-__opencl_c_images %s 2>&1 | FileCheck -check-prefix=CHECK-3D-WRITE-IMAGES-DEPS %s // RUN: not %clang_cc1 -cl-std=clc++2021 -triple spir-unknown-unknown -cl-ext=+__opencl_c_3d_image_writes,+__opencl_c_images,-cl_khr_3d_image_writes %s 2>&1 | FileCheck -check-prefix=CHECK-3D-WRITE-IMAGES-DIFF %s // RUN: not %clang_cc1 -cl-std=clc++2021 -triple spir-unknown-unknown -cl-ext=+__opencl_c_3d_image_writes,-__opencl_c_images %s 2>&1 | FileCheck -check-prefix=CHECK-3D-WRITE-IMAGES-DEPS %s +// RUN: not %clang_cc1 -cl-std=CL3.0 -triple spir-unknown-unknown -cl-ext=+__opencl_c_device_enqueue,-__opencl_c_generic_address_space,-__opencl_c_pipes %s 2>&1 | FileCheck -check-prefix=CHECK-DEVICE-ENQUEUE %s +// RUN: not %clang_cc1 -cl-std=clc++2021 -triple spir-unknown-unknown -cl-ext=+__opencl_c_device_enqueue,-__opencl_c_generic_address_space,-__opencl_c_pipes %s 2>&1 | FileCheck -check-prefix=CHECK-DEVICE-ENQUEUE %s // CHECK-FP64: error: options cl_khr_fp64 and __opencl_c_fp64 are set to different values // CHECK-READ-WRITE-IMAGES: error: feature __opencl_c_read_write_images requires support of __opencl_c_images feature -// CHECK-3D-WRITE-IMAGES-DIFF: options cl_khr_3d_image_writes and __opencl_c_3d_image_writes are set to different values +// CHECK-3D-WRITE-IMAGES-DIFF: error: options cl_khr_3d_image_writes and __opencl_c_3d_image_writes are set to different values // CHECK-3D-WRITE-IMAGES-DEPS: error: feature __opencl_c_3d_image_writes requires support of __opencl_c_images feature // CHECK-PIPES: error: feature __opencl_c_pipes requires support of __opencl_c_generic_address_space feature + +// CHECK-DEVICE-ENQUEUE: error: feature __opencl_c_device_enqueue requires support of __opencl_c_generic_address_space feature diff --git a/clang/test/SemaOpenCL/constant-blocks-unsupported-cl3.0.cl b/clang/test/SemaOpenCL/constant-blocks-unsupported-cl3.0.cl new file mode 100644 --- /dev/null +++ b/clang/test/SemaOpenCL/constant-blocks-unsupported-cl3.0.cl @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -verify -cl-std=CL3.0 -cl-ext=+__opencl_c_device_enqueue,+__opencl_c_generic_address_space,-__opencl_c_program_scope_global_variables %s + +void (^constant block_A)(int) = ^(void) { + return; +}; + +void f() { + void (^constant block_B)(int) = ^(void) { + return; + }; +// expected-error@-8 {{constant blocks not supported yet without __opencl_c_program_scope_global_variables feature for OpenCL C 3.0}} +// expected-error@-4 {{constant blocks not supported yet without __opencl_c_program_scope_global_variables feature for OpenCL C 3.0}} +} diff --git a/clang/test/SemaOpenCL/invalid-block.cl b/clang/test/SemaOpenCL/invalid-block.cl --- a/clang/test/SemaOpenCL/invalid-block.cl +++ b/clang/test/SemaOpenCL/invalid-block.cl @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -verify -fblocks -cl-std=CL2.0 %s +// RUN: %clang_cc1 -verify -fblocks -cl-std=CL3.0 -cl-ext=+__opencl_c_device_enqueue,+__opencl_c_generic_address_space %s // OpenCL v2.0 s6.12.5 void f0(int (^const bl)()); // expected-error{{declaring function parameter of type 'int (__generic ^const __private)(void)' is not allowed}} diff --git a/clang/test/SemaOpenCL/invalid-device-enqueue-types-cl3.0.cl b/clang/test/SemaOpenCL/invalid-device-enqueue-types-cl3.0.cl new file mode 100644 --- /dev/null +++ b/clang/test/SemaOpenCL/invalid-device-enqueue-types-cl3.0.cl @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -verify -fblocks -cl-std=CL3.0 -cl-ext=+__opencl_c_device_enqueue,+__opencl_c_generic_address_space %s +// RUN: %clang_cc1 -verify -fblocks -cl-std=CL3.0 -cl-ext=-__opencl_c_device_enqueue,-__opencl_c_generic_address_space,-__opencl_c_pipes %s + +void f() { + clk_event_t e; + queue_t q; +#ifndef __opencl_c_device_enqueue +// expected-error@-3 {{use of undeclared identifier 'clk_event_t'}} +// expected-error@-3 {{use of undeclared identifier 'queue_t'}} +#else +// expected-no-diagnostics +#endif +} diff --git a/clang/test/SemaOpenCL/invalid-pipes-cl1.2.cl b/clang/test/SemaOpenCL/invalid-pipes-cl1.2.cl --- a/clang/test/SemaOpenCL/invalid-pipes-cl1.2.cl +++ b/clang/test/SemaOpenCL/invalid-pipes-cl1.2.cl @@ -1,6 +1,6 @@ // RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=CL1.2 -// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=CL3.0 -cl-ext=-__opencl_c_pipes,-__opencl_c_generic_address_space -// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=clc++2021 -cl-ext=-__opencl_c_pipes,-__opencl_c_generic_address_space +// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=CL3.0 -cl-ext=-__opencl_c_pipes,-__opencl_c_generic_address_space,-__opencl_c_device_enqueue +// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=clc++2021 -cl-ext=-__opencl_c_pipes,-__opencl_c_generic_address_space,-__opencl_c_device_enqueue void foo(read_only pipe int p); #if __OPENCL_C_VERSION__ > 120 diff --git a/clang/test/SemaOpenCL/storageclass.cl b/clang/test/SemaOpenCL/storageclass.cl --- a/clang/test/SemaOpenCL/storageclass.cl +++ b/clang/test/SemaOpenCL/storageclass.cl @@ -1,10 +1,10 @@ // RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=CL1.2 -// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=CL3.0 -cl-ext=-__opencl_c_program_scope_global_variables,-__opencl_c_generic_address_space,-__opencl_c_pipes -// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=CL3.0 -cl-ext=+__opencl_c_program_scope_global_variables,-__opencl_c_generic_address_space,-__opencl_c_pipes +// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=CL3.0 -cl-ext=-__opencl_c_program_scope_global_variables,-__opencl_c_generic_address_space,-__opencl_c_pipes,-__opencl_c_device_enqueue +// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=CL3.0 -cl-ext=+__opencl_c_program_scope_global_variables,-__opencl_c_generic_address_space,-__opencl_c_pipes,-__opencl_c_device_enqueue // RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=CL3.0 -cl-ext=-__opencl_c_program_scope_global_variables,+__opencl_c_generic_address_space // RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=CL3.0 -cl-ext=+__opencl_c_program_scope_global_variables,+__opencl_c_generic_address_space -// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=clc++2021 -cl-ext=-__opencl_c_program_scope_global_variables,-__opencl_c_generic_address_space,-__opencl_c_pipes -// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=clc++2021 -cl-ext=+__opencl_c_program_scope_global_variables,-__opencl_c_generic_address_space,-__opencl_c_pipes +// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=clc++2021 -cl-ext=-__opencl_c_program_scope_global_variables,-__opencl_c_generic_address_space,-__opencl_c_pipes,-__opencl_c_device_enqueue +// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=clc++2021 -cl-ext=+__opencl_c_program_scope_global_variables,-__opencl_c_generic_address_space,-__opencl_c_pipes,-__opencl_c_device_enqueue // RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=clc++2021 -cl-ext=-__opencl_c_program_scope_global_variables,+__opencl_c_generic_address_space // RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=clc++2021 -cl-ext=+__opencl_c_program_scope_global_variables,+__opencl_c_generic_address_space static constant int G1 = 0;