azabaznov updated this revision to Diff 316627. azabaznov added a comment. Changes in the latest patch:
1. Removed XFAIL and OpenCL C 2.0 test running for r600 and NVPTX target 2. Fixed comments. 3. Core features are being set in `TargetInfo::adjust`. CHANGES SINCE LAST ACTION https://reviews.llvm.org/D92277/new/ https://reviews.llvm.org/D92277 Files: clang/include/clang/Basic/OpenCLExtensions.def clang/include/clang/Basic/OpenCLOptions.h clang/include/clang/Basic/TargetInfo.h clang/include/clang/Basic/TargetOptions.h clang/lib/Basic/CMakeLists.txt clang/lib/Basic/OpenCLOptions.cpp clang/lib/Basic/TargetInfo.cpp clang/lib/Basic/Targets.cpp clang/lib/Basic/Targets/AMDGPU.h clang/lib/Basic/Targets/NVPTX.h clang/lib/Basic/Targets/SPIR.h clang/lib/Basic/Targets/X86.h clang/lib/Frontend/InitPreprocessor.cpp clang/lib/Parse/ParsePragma.cpp clang/lib/Sema/Sema.cpp clang/lib/Serialization/ASTReader.cpp clang/lib/Serialization/ASTWriter.cpp clang/test/Misc/nvptx.languageOptsOpenCL.cl clang/test/Misc/r600.languageOptsOpenCL.cl
Index: clang/test/Misc/r600.languageOptsOpenCL.cl =================================================================== --- clang/test/Misc/r600.languageOptsOpenCL.cl +++ clang/test/Misc/r600.languageOptsOpenCL.cl @@ -2,27 +2,21 @@ // RUN: %clang_cc1 -x cl -cl-std=CL %s -verify -triple r600-unknown-unknown -target-cpu cayman // RUN: %clang_cc1 -x cl -cl-std=CL1.1 %s -verify -triple r600-unknown-unknown -target-cpu cayman // RUN: %clang_cc1 -x cl -cl-std=CL1.2 %s -verify -triple r600-unknown-unknown -target-cpu cayman -// RUN: %clang_cc1 -x cl -cl-std=CL2.0 %s -verify -triple r600-unknown-unknown -target-cpu cayman // RUN: %clang_cc1 -x cl -cl-std=CL %s -verify -triple r600-unknown-unknown -Wpedantic-core-features -DTEST_CORE_FEATURES -target-cpu cayman // RUN: %clang_cc1 -x cl -cl-std=CL1.1 %s -verify -triple r600-unknown-unknown -Wpedantic-core-features -DTEST_CORE_FEATURES -target-cpu cayman // RUN: %clang_cc1 -x cl -cl-std=CL1.2 %s -verify -triple r600-unknown-unknown -Wpedantic-core-features -DTEST_CORE_FEATURES -target-cpu cayman -// RUN: %clang_cc1 -x cl -cl-std=CL2.0 %s -verify -triple r600-unknown-unknown -Wpedantic-core-features -DTEST_CORE_FEATURES -target-cpu cayman // RUN: %clang_cc1 -x cl -cl-std=CL %s -verify -triple r600-unknown-unknown -target-cpu cypress // RUN: %clang_cc1 -x cl -cl-std=CL1.1 %s -verify -triple r600-unknown-unknown -target-cpu cypress // RUN: %clang_cc1 -x cl -cl-std=CL1.2 %s -verify -triple r600-unknown-unknown -target-cpu cypress -// RUN: %clang_cc1 -x cl -cl-std=CL2.0 %s -verify -triple r600-unknown-unknown -target-cpu cypress // RUN: %clang_cc1 -x cl -cl-std=CL %s -verify -triple r600-unknown-unknown -Wpedantic-core-features -DTEST_CORE_FEATURES -target-cpu cypress // RUN: %clang_cc1 -x cl -cl-std=CL1.1 %s -verify -triple r600-unknown-unknown -Wpedantic-core-features -DTEST_CORE_FEATURES -target-cpu cypress // RUN: %clang_cc1 -x cl -cl-std=CL1.2 %s -verify -triple r600-unknown-unknown -Wpedantic-core-features -DTEST_CORE_FEATURES -target-cpu cypress -// RUN: %clang_cc1 -x cl -cl-std=CL2.0 %s -verify -triple r600-unknown-unknown -Wpedantic-core-features -DTEST_CORE_FEATURES -target-cpu cypress // RUN: %clang_cc1 -x cl -cl-std=CL %s -verify -triple r600-unknown-unknown -target-cpu turks // RUN: %clang_cc1 -x cl -cl-std=CL1.1 %s -verify -triple r600-unknown-unknown -target-cpu turks // RUN: %clang_cc1 -x cl -cl-std=CL1.2 %s -verify -triple r600-unknown-unknown -target-cpu turks -// RUN: %clang_cc1 -x cl -cl-std=CL2.0 %s -verify -triple r600-unknown-unknown -target-cpu turks // RUN: %clang_cc1 -x cl -cl-std=CL %s -verify -triple r600-unknown-unknown -Wpedantic-core-features -DTEST_CORE_FEATURES -target-cpu turks // RUN: %clang_cc1 -x cl -cl-std=CL1.1 %s -verify -triple r600-unknown-unknown -Wpedantic-core-features -DTEST_CORE_FEATURES -target-cpu turks // RUN: %clang_cc1 -x cl -cl-std=CL1.2 %s -verify -triple r600-unknown-unknown -Wpedantic-core-features -DTEST_CORE_FEATURES -target-cpu turks -// RUN: %clang_cc1 -x cl -cl-std=CL2.0 %s -verify -triple r600-unknown-unknown -Wpedantic-core-features -DTEST_CORE_FEATURES -target-cpu turks // Extensions in all versions #ifndef cl_clang_storage_class_specifiers Index: clang/test/Misc/nvptx.languageOptsOpenCL.cl =================================================================== --- clang/test/Misc/nvptx.languageOptsOpenCL.cl +++ clang/test/Misc/nvptx.languageOptsOpenCL.cl @@ -2,19 +2,15 @@ // RUN: %clang_cc1 -x cl -cl-std=CL %s -verify -triple nvptx-unknown-unknown // RUN: %clang_cc1 -x cl -cl-std=CL1.1 %s -verify -triple nvptx-unknown-unknown // RUN: %clang_cc1 -x cl -cl-std=CL1.2 %s -verify -triple nvptx-unknown-unknown -// RUN: %clang_cc1 -x cl -cl-std=CL2.0 %s -verify -triple nvptx-unknown-unknown // RUN: %clang_cc1 -x cl -cl-std=CL %s -verify -triple nvptx-unknown-unknown -Wpedantic-core-features -DTEST_CORE_FEATURES // RUN: %clang_cc1 -x cl -cl-std=CL1.1 %s -verify -triple nvptx-unknown-unknown -Wpedantic-core-features -DTEST_CORE_FEATURES // RUN: %clang_cc1 -x cl -cl-std=CL1.2 %s -verify -triple nvptx-unknown-unknown -Wpedantic-core-features -DTEST_CORE_FEATURES -// RUN: %clang_cc1 -x cl -cl-std=CL2.0 %s -verify -triple nvptx-unknown-unknown -Wpedantic-core-features -DTEST_CORE_FEATURES // RUN: %clang_cc1 -x cl -cl-std=CL %s -verify -triple nvptx64-unknown-unknown // RUN: %clang_cc1 -x cl -cl-std=CL1.1 %s -verify -triple nvptx64-unknown-unknown // RUN: %clang_cc1 -x cl -cl-std=CL1.2 %s -verify -triple nvptx64-unknown-unknown -// RUN: %clang_cc1 -x cl -cl-std=CL2.0 %s -verify -triple nvptx64-unknown-unknown // RUN: %clang_cc1 -x cl -cl-std=CL %s -verify -triple nvptx64-unknown-unknown -Wpedantic-core-features -DTEST_CORE_FEATURES // RUN: %clang_cc1 -x cl -cl-std=CL1.1 %s -verify -triple nvptx64-unknown-unknown -Wpedantic-core-features -DTEST_CORE_FEATURES // RUN: %clang_cc1 -x cl -cl-std=CL1.2 %s -verify -triple nvptx64-unknown-unknown -Wpedantic-core-features -DTEST_CORE_FEATURES -// RUN: %clang_cc1 -x cl -cl-std=CL2.0 %s -verify -triple nvptx64-unknown-unknown -Wpedantic-core-features -DTEST_CORE_FEATURES // Extensions in all versions #ifndef cl_clang_storage_class_specifiers Index: clang/lib/Serialization/ASTWriter.cpp =================================================================== --- clang/lib/Serialization/ASTWriter.cpp +++ clang/lib/Serialization/ASTWriter.cpp @@ -3978,6 +3978,7 @@ Record.push_back(V.Enabled ? 1 : 0); Record.push_back(V.Avail); Record.push_back(V.Core); + Record.push_back(V.Opt); } Stream.EmitRecord(OPENCL_EXTENSIONS, Record); } Index: clang/lib/Serialization/ASTReader.cpp =================================================================== --- clang/lib/Serialization/ASTReader.cpp +++ clang/lib/Serialization/ASTReader.cpp @@ -3583,11 +3583,12 @@ case OPENCL_EXTENSIONS: for (unsigned I = 0, E = Record.size(); I != E; ) { auto Name = ReadString(Record, I); - auto &Opt = OpenCLExtensions.OptMap[Name]; - Opt.Supported = Record[I++] != 0; - Opt.Enabled = Record[I++] != 0; - Opt.Avail = Record[I++]; - Opt.Core = Record[I++]; + auto &OptInfo = OpenCLExtensions.OptMap[Name]; + OptInfo.Supported = Record[I++] != 0; + OptInfo.Enabled = Record[I++] != 0; + OptInfo.Avail = Record[I++]; + OptInfo.Core = Record[I++]; + OptInfo.Opt = Record[I++]; } break; @@ -7836,7 +7837,7 @@ NewOverrides.applyOverrides(SemaObj->getLangOpts()); } - SemaObj->OpenCLFeatures.copy(OpenCLExtensions); + SemaObj->OpenCLFeatures = OpenCLExtensions; SemaObj->OpenCLTypeExtMap = OpenCLTypeExtMap; SemaObj->OpenCLDeclExtMap = OpenCLDeclExtMap; Index: clang/lib/Sema/Sema.cpp =================================================================== --- clang/lib/Sema/Sema.cpp +++ clang/lib/Sema/Sema.cpp @@ -296,7 +296,7 @@ // core features. if (getLangOpts().OpenCL) { getOpenCLOptions().addSupport( - Context.getTargetInfo().getSupportedOpenCLOpts()); + Context.getTargetInfo().getSupportedOpenCLOpts(), getLangOpts()); getOpenCLOptions().enableSupportedCore(getLangOpts()); addImplicitTypedef("sampler_t", Context.OCLSamplerTy); addImplicitTypedef("event_t", Context.OCLEventTy); Index: clang/lib/Parse/ParsePragma.cpp =================================================================== --- clang/lib/Parse/ParsePragma.cpp +++ clang/lib/Parse/ParsePragma.cpp @@ -790,7 +790,7 @@ PP.Diag(NameLoc, diag::warn_pragma_unknown_extension) << Ident; else if (Opt.isSupportedExtension(Name, getLangOpts())) Opt.enable(Name, State == Enable); - else if (Opt.isSupportedCore(Name, getLangOpts())) + else if (Opt.isSupportedCoreOrOptionalCore(Name, getLangOpts())) PP.Diag(NameLoc, diag::warn_pragma_extension_is_core) << Ident; else PP.Diag(NameLoc, diag::warn_pragma_unsupported_extension) << Ident; Index: clang/lib/Frontend/InitPreprocessor.cpp =================================================================== --- clang/lib/Frontend/InitPreprocessor.cpp +++ clang/lib/Frontend/InitPreprocessor.cpp @@ -1120,10 +1120,7 @@ // OpenCL definitions. if (LangOpts.OpenCL) { -#define OPENCLEXT(Ext) \ - if (TI.getSupportedOpenCLOpts().isSupported(#Ext, LangOpts)) \ - Builder.defineMacro(#Ext); -#include "clang/Basic/OpenCLExtensions.def" + TI.getOpenCLFeatureDefines(LangOpts, Builder); if (TI.getTriple().isSPIR()) Builder.defineMacro("__IMAGE_SUPPORT__"); Index: clang/lib/Basic/Targets/X86.h =================================================================== --- clang/lib/Basic/Targets/X86.h +++ clang/lib/Basic/Targets/X86.h @@ -359,9 +359,7 @@ bool hasSjLjLowering() const override { return true; } - void setSupportedOpenCLOpts() override { - getSupportedOpenCLOpts().supportAll(); - } + void setSupportedOpenCLOpts() override { supportAllOpenCLOpts(); } uint64_t getPointerWidthV(unsigned AddrSpace) const override { if (AddrSpace == ptr32_sptr || AddrSpace == ptr32_uptr) Index: clang/lib/Basic/Targets/SPIR.h =================================================================== --- clang/lib/Basic/Targets/SPIR.h +++ clang/lib/Basic/Targets/SPIR.h @@ -100,7 +100,7 @@ void setSupportedOpenCLOpts() override { // Assume all OpenCL extensions and optional core features are supported // for SPIR since it is a generic target. - getSupportedOpenCLOpts().supportAll(); + supportAllOpenCLOpts(); } bool hasExtIntType() const override { return true; } Index: clang/lib/Basic/Targets/NVPTX.h =================================================================== --- clang/lib/Basic/Targets/NVPTX.h +++ clang/lib/Basic/Targets/NVPTX.h @@ -127,16 +127,16 @@ void setSupportedOpenCLOpts() override { auto &Opts = getSupportedOpenCLOpts(); - Opts.support("cl_clang_storage_class_specifiers"); - Opts.support("__cl_clang_function_pointers"); - Opts.support("__cl_clang_variadic_functions"); - - Opts.support("cl_khr_fp64"); - Opts.support("cl_khr_byte_addressable_store"); - Opts.support("cl_khr_global_int32_base_atomics"); - Opts.support("cl_khr_global_int32_extended_atomics"); - Opts.support("cl_khr_local_int32_base_atomics"); - Opts.support("cl_khr_local_int32_extended_atomics"); + Opts["cl_clang_storage_class_specifiers"] = true; + Opts["__cl_clang_function_pointers"] = true; + Opts["__cl_clang_variadic_functions"] = true; + + Opts["cl_khr_fp64"] = true; + Opts["cl_khr_byte_addressable_store"] = true; + Opts["cl_khr_global_int32_base_atomics"] = true; + Opts["cl_khr_global_int32_extended_atomics"] = true; + Opts["cl_khr_local_int32_base_atomics"] = true; + Opts["cl_khr_local_int32_extended_atomics"] = true; } /// \returns If a target requires an address within a target specific address Index: clang/lib/Basic/Targets/AMDGPU.h =================================================================== --- clang/lib/Basic/Targets/AMDGPU.h +++ clang/lib/Basic/Targets/AMDGPU.h @@ -284,33 +284,32 @@ void setSupportedOpenCLOpts() override { auto &Opts = getSupportedOpenCLOpts(); - Opts.support("cl_clang_storage_class_specifiers"); - Opts.support("__cl_clang_function_pointers"); - Opts.support("__cl_clang_variadic_functions"); + Opts["cl_clang_storage_class_specifiers"] = true; + Opts["__cl_clang_variadic_functions"] = true; + Opts["__cl_clang_function_pointers"] = true; bool IsAMDGCN = isAMDGCN(getTriple()); - if (hasFP64()) - Opts.support("cl_khr_fp64"); + Opts["cl_khr_fp64"] = hasFP64(); if (IsAMDGCN || GPUKind >= llvm::AMDGPU::GK_CEDAR) { - Opts.support("cl_khr_byte_addressable_store"); - Opts.support("cl_khr_global_int32_base_atomics"); - Opts.support("cl_khr_global_int32_extended_atomics"); - Opts.support("cl_khr_local_int32_base_atomics"); - Opts.support("cl_khr_local_int32_extended_atomics"); + Opts["cl_khr_byte_addressable_store"] = true; + Opts["cl_khr_global_int32_base_atomics"] = true; + Opts["cl_khr_global_int32_extended_atomics"] = true; + Opts["cl_khr_local_int32_base_atomics"] = true; + Opts["cl_khr_local_int32_extended_atomics"] = true; } if (IsAMDGCN) { - Opts.support("cl_khr_fp16"); - Opts.support("cl_khr_int64_base_atomics"); - Opts.support("cl_khr_int64_extended_atomics"); - Opts.support("cl_khr_mipmap_image"); - Opts.support("cl_khr_mipmap_image_writes"); - Opts.support("cl_khr_subgroups"); - Opts.support("cl_khr_3d_image_writes"); - Opts.support("cl_amd_media_ops"); - Opts.support("cl_amd_media_ops2"); + Opts["cl_khr_fp16"] = true; + Opts["cl_khr_int64_base_atomics"] = true; + Opts["cl_khr_int64_extended_atomics"] = true; + Opts["cl_khr_mipmap_image"] = true; + Opts["cl_khr_mipmap_image_writes"] = true; + Opts["cl_khr_subgroups"] = true; + Opts["cl_khr_3d_image_writes"] = true; + Opts["cl_amd_media_ops"] = true; + Opts["cl_amd_media_ops2"] = true; } } Index: clang/lib/Basic/Targets.cpp =================================================================== --- clang/lib/Basic/Targets.cpp +++ clang/lib/Basic/Targets.cpp @@ -705,7 +705,7 @@ return nullptr; Target->setSupportedOpenCLOpts(); - Target->setOpenCLExtensionOpts(); + Target->setCommandLineOpenCLOpts(); Target->setMaxAtomicWidth(); if (!Target->validateTarget(Diags)) @@ -715,3 +715,24 @@ return Target.release(); } + +/// getOpenCLFeatureDefines - Define OpenCL macros based on target settings +/// and language version +void TargetInfo::getOpenCLFeatureDefines(const LangOptions &Opts, + MacroBuilder &Builder) const { + + auto defineOpenCLExtMacro = [&](llvm::StringRef Name, unsigned AvailVer, + unsigned CoreVersions, + unsigned OptionalVersions) { + // Check if extension is supported by target or is a core feature + auto It = getTargetOpts().OpenCLFeaturesMap.find(Name); + if ((It != getTargetOpts().OpenCLFeaturesMap.end()) && It->getValue() && + OpenCLOptionInfo(AvailVer, CoreVersions, OptionalVersions) + .isAvailableIn(Opts)) + Builder.defineMacro(Name); + }; + +#define OPENCL_GENERIC_EXTENSION(Ext, Avail, Core, Opt) \ + defineOpenCLExtMacro(#Ext, Avail, Core, Opt); +#include "clang/Basic/OpenCLExtensions.def" +} Index: clang/lib/Basic/TargetInfo.cpp =================================================================== --- clang/lib/Basic/TargetInfo.cpp +++ clang/lib/Basic/TargetInfo.cpp @@ -356,6 +356,10 @@ } if (Opts.OpenCL) { + // Set core features based on OpenCL version + for (auto CoreExt : clang::getCoreFeatures(Opts)) + getTargetOpts().OpenCLFeaturesMap[CoreExt] = true; + // OpenCL C requires specific widths for types, irrespective of // what these normally are for the target. // We also define long long and long double here, although the Index: clang/lib/Basic/OpenCLOptions.cpp =================================================================== --- /dev/null +++ clang/lib/Basic/OpenCLOptions.cpp @@ -0,0 +1,110 @@ +//===--- OpenCLOptions.cpp---------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "clang/Basic/OpenCLOptions.h" + +namespace clang { + +bool OpenCLOptions::isKnown(llvm::StringRef Ext) const { + return OptMap.find(Ext) != OptMap.end(); +} + +bool OpenCLOptions::isEnabled(llvm::StringRef Ext) const { + auto E = OptMap.find(Ext); + return E != OptMap.end() && E->second.Enabled; +} + +bool OpenCLOptions::isSupported(llvm::StringRef Ext, + const LangOptions &LO) const { + auto E = OptMap.find(Ext); + if (E == OptMap.end()) { + return false; + } + auto I = OptMap.find(Ext)->getValue(); + return I.Supported && I.isAvailableIn(LO); +} + +bool OpenCLOptions::isSupportedCore(llvm::StringRef Ext, + const LangOptions &LO) const { + auto E = OptMap.find(Ext); + if (E == OptMap.end()) { + return false; + } + auto I = OptMap.find(Ext)->getValue(); + return I.Supported && I.isCoreIn(LO); +} + +bool OpenCLOptions::isSupportedOptionalCore(llvm::StringRef Ext, + const LangOptions &LO) const { + auto E = OptMap.find(Ext); + if (E == OptMap.end()) { + return false; + } + auto I = OptMap.find(Ext)->getValue(); + return I.Supported && I.isOptionalCoreIn(LO); +} + +bool OpenCLOptions::isSupportedCoreOrOptionalCore(llvm::StringRef Ext, + const LangOptions &LO) const { + return isSupportedCore(Ext, LO) || isSupportedOptionalCore(Ext, LO); +} + +bool OpenCLOptions::isSupportedExtension(llvm::StringRef Ext, + const LangOptions &LO) const { + auto E = OptMap.find(Ext); + if (E == OptMap.end()) { + return false; + } + auto I = OptMap.find(Ext)->getValue(); + return I.Supported && I.isAvailableIn(LO) && + !isSupportedCoreOrOptionalCore(Ext, LO); +} + +void OpenCLOptions::enable(llvm::StringRef Ext, bool V) { + OptMap[Ext].Enabled = V; +} + +void OpenCLOptions::support(llvm::StringRef Ext, bool V) { + assert(!Ext.empty() && "Extension is empty."); + assert(Ext[0] != '+' && Ext[0] != '-'); + OptMap[Ext].Supported = V; +} + +OpenCLOptions::OpenCLOptions() { +#define OPENCL_GENERIC_EXTENSION(Ext, AvailVer, CoreVer, OptVer) \ + OptMap[#Ext].Avail = AvailVer; \ + OptMap[#Ext].Core = CoreVer; \ + OptMap[#Ext].Opt = OptVer; +#include "clang/Basic/OpenCLExtensions.def" +} + +void OpenCLOptions::addSupport(const llvm::StringMap<bool> &FeaturesMap, + const LangOptions &Opts) { + for (const auto &F : FeaturesMap) { + const auto &Name = F.getKey(); + if (F.getValue() && isKnown(Name) && OptMap[Name].isAvailableIn(Opts)) + support(Name); + } +} + +void OpenCLOptions::disableAll() { + for (llvm::StringMap<OpenCLOptionInfo>::iterator I = OptMap.begin(), + E = OptMap.end(); + I != E; ++I) + I->second.Enabled = false; +} + +void OpenCLOptions::enableSupportedCore(const LangOptions &LO) { + for (llvm::StringMap<OpenCLOptionInfo>::iterator I = OptMap.begin(), + E = OptMap.end(); + I != E; ++I) + if (isSupportedCoreOrOptionalCore(I->getKey(), LO)) + I->second.Enabled = true; +} + +} // end namespace clang Index: clang/lib/Basic/CMakeLists.txt =================================================================== --- clang/lib/Basic/CMakeLists.txt +++ clang/lib/Basic/CMakeLists.txt @@ -56,6 +56,7 @@ LangStandards.cpp Module.cpp ObjCRuntime.cpp + OpenCLOptions.cpp OpenMPKinds.cpp OperatorPrecedence.cpp SanitizerBlacklist.cpp Index: clang/include/clang/Basic/TargetOptions.h =================================================================== --- clang/include/clang/Basic/TargetOptions.h +++ clang/include/clang/Basic/TargetOptions.h @@ -62,7 +62,7 @@ llvm::StringMap<bool> FeatureMap; /// Supported OpenCL extensions and optional core features. - OpenCLOptions SupportedOpenCLOptions; + llvm::StringMap<bool> OpenCLFeaturesMap; /// The list of OpenCL extensions to enable or disable, as written on /// the command line. Index: clang/include/clang/Basic/TargetInfo.h =================================================================== --- clang/include/clang/Basic/TargetInfo.h +++ clang/include/clang/Basic/TargetInfo.h @@ -1438,21 +1438,39 @@ /// Set supported OpenCL extensions and optional core features. virtual void setSupportedOpenCLOpts() {} + virtual void supportAllOpenCLOpts(bool V = true) { +#define OPENCLEXTNAME(Ext) getTargetOpts().OpenCLFeaturesMap[#Ext] = V; +#include "clang/Basic/OpenCLExtensions.def" + } + /// Set supported OpenCL extensions as written on command line - virtual void setOpenCLExtensionOpts() { + virtual void setCommandLineOpenCLOpts() { for (const auto &Ext : getTargetOpts().OpenCLExtensionsAsWritten) { - getTargetOpts().SupportedOpenCLOptions.support(Ext); + bool IsPrefixed = (Ext[0] == '+' || Ext[0] == '-'); + std::string Name = IsPrefixed ? Ext.substr(1) : Ext; + bool V = IsPrefixed ? Ext[0] == '+' : true; + + if (Name == "all") { + supportAllOpenCLOpts(V); + continue; + } + + getTargetOpts().OpenCLFeaturesMap[Name] = V; } } + /// Define OpenCL macros based on target settings and language version + void getOpenCLFeatureDefines(const LangOptions &Opts, + MacroBuilder &Builder) const; + /// Get supported OpenCL extensions and optional core features. - OpenCLOptions &getSupportedOpenCLOpts() { - return getTargetOpts().SupportedOpenCLOptions; + llvm::StringMap<bool> &getSupportedOpenCLOpts() { + return getTargetOpts().OpenCLFeaturesMap; } /// Get const supported OpenCL extensions and optional core features. - const OpenCLOptions &getSupportedOpenCLOpts() const { - return getTargetOpts().SupportedOpenCLOptions; + const llvm::StringMap<bool> &getSupportedOpenCLOpts() const { + return getTargetOpts().OpenCLFeaturesMap; } /// Get address space for OpenCL type. Index: clang/include/clang/Basic/OpenCLOptions.h =================================================================== --- clang/include/clang/Basic/OpenCLOptions.h +++ clang/include/clang/Basic/OpenCLOptions.h @@ -19,157 +19,156 @@ namespace clang { -/// OpenCL supported extensions and optional core features -class OpenCLOptions { - struct Info { - bool Supported; // Is this option supported - bool Enabled; // Is this option enabled - unsigned Avail; // Option starts to be available in this OpenCL version - unsigned Core; // Option becomes (optional) core feature in this OpenCL - // version - Info(bool S = false, bool E = false, unsigned A = 100, unsigned C = ~0U) - :Supported(S), Enabled(E), Avail(A), Core(C){} - }; - llvm::StringMap<Info> OptMap; -public: - /// Check if \c Ext is a recognized OpenCL extension. - /// - /// \param Ext - Extension to look up. - /// \returns \c true if \c Ext is known, \c false otherwise. - bool isKnown(llvm::StringRef Ext) const { - return OptMap.find(Ext) != OptMap.end(); - } +// This enum maps OpenCL version(s) into value. These values are used as +// a mask to indicate in which OpenCL version(s) extension is a core or +// optional core feature. +enum OpenCLVersionID : unsigned int { + OCL_C_10 = 0x1, + OCL_C_11 = 0x2, + OCL_C_12 = 0x4, + OCL_C_20 = 0x8, + OCL_C_30 = 0x10, + OCL_C_ALL = 0x1f, + OCL_C_11P = OCL_C_ALL ^ OCL_C_10, // OpenCL C 1.1+ + OCL_C_12P = OCL_C_ALL ^ (OCL_C_10 | OCL_C_11), // OpenCL C 1.2+ +}; - /// Check if \c Ext is an enabled OpenCL extension. - /// - /// \param Ext - Extension to look up. - /// \returns \c true if \c Ext is known and enabled, \c false otherwise. - bool isEnabled(llvm::StringRef Ext) const { - auto E = OptMap.find(Ext); - return E != OptMap.end() && E->second.Enabled; +static inline OpenCLVersionID encodeOpenCLVersion(unsigned OpenCLVersion) { + switch (OpenCLVersion) { + default: + llvm_unreachable("Unknown OpenCL versin code"); + case 100: + return OCL_C_10; + case 110: + return OCL_C_11; + case 120: + return OCL_C_12; + case 200: + return OCL_C_20; + case 300: + return OCL_C_30; } +} - /// Check if \c Ext is supported as either an extension or an (optional) core - /// feature for the given OpenCL version. - /// - /// \param Ext - Extension to look up. - /// \param LO - \c LangOptions specifying the OpenCL version. - /// \returns \c true if \c Ext is known and supported, \c false otherwise. - bool isSupported(llvm::StringRef Ext, const LangOptions &LO) const { - auto E = OptMap.find(Ext); - if (E == OptMap.end()) { - return false; - } - // In C++ mode all extensions should work at least as in v2.0. - auto CLVer = LO.OpenCLCPlusPlus ? 200 : LO.OpenCLVersion; - auto I = E->getValue(); - return I.Supported && I.Avail <= CLVer; - } +// Simple helper to check if OpenCL C version is contained in a given encoded +// OpenCL C version mask +static inline bool OpenCLVersionIsContainedInMask(const LangOptions &LO, + unsigned Mask) { + auto CLVer = LO.OpenCLCPlusPlus ? 200 : LO.OpenCLVersion; + OpenCLVersionID Code = encodeOpenCLVersion(CLVer); + return Mask & Code; +} - /// Check if \c Ext is supported as an (optional) OpenCL core features for - /// the given OpenCL version. - /// - /// \param Ext - Extension to look up. - /// \param LO - \c LangOptions specifying the OpenCL version. - /// \returns \c true if \c Ext is known and supported, \c false otherwise. - bool isSupportedCore(llvm::StringRef Ext, const LangOptions &LO) const { - auto E = OptMap.find(Ext); - if (E == OptMap.end()) { - return false; - } - // In C++ mode all extensions should work at least as in v2.0. - auto CLVer = LO.OpenCLCPlusPlus ? 200 : LO.OpenCLVersion; - auto I = E->getValue(); - return I.Supported && I.Avail <= CLVer && I.Core != ~0U && CLVer >= I.Core; - } +struct OpenCLOptionInfo { + // Option starts to be available in this OpenCL version + unsigned Avail; - /// Check if \c Ext is a supported OpenCL extension for the given OpenCL - /// version. - /// - /// \param Ext - Extension to look up. - /// \param LO - \c LangOptions specifying the OpenCL version. - /// \returns \c true if \c Ext is known and supported, \c false otherwise. - bool isSupportedExtension(llvm::StringRef Ext, const LangOptions &LO) const { - auto E = OptMap.find(Ext); - if (E == OptMap.end()) { - return false; - } + // Option becomes core feature in this OpenCL versions + unsigned Core; + + // Option becomes optional core feature in this OpenCL versions + unsigned Opt; + + // Is this option supported + bool Supported = false; + + // Is this option enabled + bool Enabled = false; + + OpenCLOptionInfo(unsigned A = 100, unsigned C = 0U, unsigned O = 0U) + : Avail(A), Core(C), Opt(O) {} + + bool isCore() const { return Core != 0U; } + + bool isOptionalCore() const { return Opt != 0U; } + + // Is option available in OpenCL version \p LO. + bool isAvailableIn(const LangOptions &LO) const { // In C++ mode all extensions should work at least as in v2.0. auto CLVer = LO.OpenCLCPlusPlus ? 200 : LO.OpenCLVersion; - auto I = E->getValue(); - return I.Supported && I.Avail <= CLVer && (I.Core == ~0U || CLVer < I.Core); + return CLVer >= Avail; } - void enable(llvm::StringRef Ext, bool V = true) { - OptMap[Ext].Enabled = V; + // Is core option in OpenCL version \p LO. + bool isCoreIn(const LangOptions &LO) const { + return isAvailableIn(LO) && OpenCLVersionIsContainedInMask(LO, Core); } - /// Enable or disable support for OpenCL extensions - /// \param Ext name of the extension optionally prefixed with - /// '+' or '-' - /// \param V used when \p Ext is not prefixed by '+' or '-' - void support(llvm::StringRef Ext, bool V = true) { - assert(!Ext.empty() && "Extension is empty."); - - switch (Ext[0]) { - case '+': - V = true; - Ext = Ext.drop_front(); - break; - case '-': - V = false; - Ext = Ext.drop_front(); - break; - } - - if (Ext.equals("all")) { - supportAll(V); - return; - } - OptMap[Ext].Supported = V; + // Is optional core option in OpenCL version \p LO. + bool isOptionalCoreIn(const LangOptions &LO) const { + return isAvailableIn(LO) && OpenCLVersionIsContainedInMask(LO, Opt); } +}; - OpenCLOptions(){ -#define OPENCLEXT_INTERNAL(Ext, AvailVer, CoreVer) \ - OptMap[#Ext].Avail = AvailVer; \ - OptMap[#Ext].Core = CoreVer; -#include "clang/Basic/OpenCLExtensions.def" - } +/// OpenCL supported extensions and optional core features +class OpenCLOptions { - void addSupport(const OpenCLOptions &Opts) { - for (auto &I:Opts.OptMap) - if (I.second.Supported) - OptMap[I.getKey()].Supported = true; - } + llvm::StringMap<OpenCLOptionInfo> OptMap; - void copy(const OpenCLOptions &Opts) { - OptMap = Opts.OptMap; - } +public: + bool isKnown(llvm::StringRef Ext) const; - // Turn on or off support of all options. - void supportAll(bool On = true) { - for (llvm::StringMap<Info>::iterator I = OptMap.begin(), - E = OptMap.end(); I != E; ++I) - I->second.Supported = On; - } + bool isEnabled(llvm::StringRef Ext) const; - void disableAll() { - for (llvm::StringMap<Info>::iterator I = OptMap.begin(), - E = OptMap.end(); I != E; ++I) - I->second.Enabled = false; - } + // Is supported as either an extension or an (optional) core feature for + // OpenCL version \p LO. + bool isSupported(llvm::StringRef Ext, const LangOptions &LO) const; - void enableSupportedCore(LangOptions LO) { - for (llvm::StringMap<Info>::iterator I = OptMap.begin(), E = OptMap.end(); - I != E; ++I) - if (isSupportedCore(I->getKey(), LO)) - I->second.Enabled = true; - } + // Is supported OpenCL core feature for OpenCL version \p LO. + // For supported extension, return false. + bool isSupportedCore(llvm::StringRef Ext, const LangOptions &LO) const; + + // Is supported optional core OpenCL feature for OpenCL version \p LO. + // For supported extension, return false. + bool isSupportedOptionalCore(llvm::StringRef Ext, + const LangOptions &LO) const; + + // Is supported optional core or core OpenCL feature for OpenCL version \p + // LO. For supported extension, return false. + bool isSupportedCoreOrOptionalCore(llvm::StringRef Ext, + const LangOptions &LO) const; + + // Is supported OpenCL extension for OpenCL version \p LO. + // For supported core or optional core feature, return false. + bool isSupportedExtension(llvm::StringRef Ext, const LangOptions &LO) const; + + void enable(llvm::StringRef Ext, bool V = true); + + /// Enable or disable support for OpenCL extensions + /// \param Ext name of the extension (not prefixed with '+' or '-') + /// \param V value to set for a extension + void support(llvm::StringRef Ext, bool V = true); + + OpenCLOptions(); + OpenCLOptions(const OpenCLOptions &) = default; + + // Set supported options based on target settings and language version + void addSupport(const llvm::StringMap<bool> &FeaturesMap, + const LangOptions &Opts); + + // Disable all extensions + void disableAll(); + + // Enable supported core and optional core features + void enableSupportedCore(const LangOptions &LO); friend class ASTWriter; friend class ASTReader; }; +// Get a list of all extensions which are core in OpenCL version \p LO. +static inline llvm::SmallVector<std::string, 16> +getCoreFeatures(const LangOptions &LO) { + llvm::SmallVector<std::string, 16> CoreFeatures; + +#define OPENCL_GENERIC_EXTENSION(Ext, Avail, Core, Opt) \ + if (OpenCLOptionInfo(Avail, Core, Opt).isCoreIn(LO)) \ + CoreFeatures.push_back(#Ext); +#include "clang/Basic/OpenCLExtensions.def" + + return CoreFeatures; +} + } // end namespace clang #endif Index: clang/include/clang/Basic/OpenCLExtensions.def =================================================================== --- clang/include/clang/Basic/OpenCLExtensions.def +++ clang/include/clang/Basic/OpenCLExtensions.def @@ -10,19 +10,23 @@ // //===----------------------------------------------------------------------===// -// Macro OPENCLEXT or OPENCLEXT_INTERNAL can be defined to enumerate the +// Macro OPENCLEXTNAME or OPENCL_GENERIC_EXTENSION can be defined to enumerate all // OpenCL extensions listed in this file. // // If the extensions are to be enumerated without the supported OpenCL version, -// define OPENCLEXT(ext) where ext is the name of the extension. +// define OPENCLEXTNAME(ext) where ext is the name of the extension. // // If the extensions are to be enumerated with supported OpenCL version, -// define OPENCLEXT_INTERNAL(ext, avail, core) where +// define OPENCL_GENERIC_EXTENSION(ext, avail, core, opt) where // ext - name of the extension or optional core feature. // avail - minimum OpenCL version supporting it. -// core - minimum OpenCL version when the extension becomes optional core -// feature or core feature. ~0U indicates not a core feature or an -// optional core feature. +// core - OpenCL versions mask when the extension becomes core feature. +// 0U indicates not a core feature. +// opt - OpenCL versions mask when the extension becomes optional core +// feature. 0U indicates not a optional core feature. +// +// Difference between optional core feature and core feature is that the +// later is unconditionally supported in specific OpenCL version. // // As per The OpenCL Extension Specification, Section 1.2, in this file, an // extension is defined if and only it either: @@ -32,63 +36,79 @@ // For such an extension, a preprocessor #define that matches the extension // name must be created and a #pragma is required if and only if the // compilation flow is impacted, e.g. due to a difference of syntax or -// semantics in the language compared to the core standard. +// semantics in the language compared to the core standard. #pragma directive +// has no effect for optional core and core features. -#ifndef OPENCLEXT_INTERNAL -#ifndef OPENCLEXT -#pragma error "macro OPENCLEXT or OPENCLEXT_INTERNAL is required" +#ifndef OPENCL_GENERIC_EXTENSION +#ifndef OPENCLEXTNAME +#pragma error "macro OPENCLEXTNAME or OPENCL_GENERIC_EXTENSION is required" #else -#define OPENCLEXT_INTERNAL(ext, ...) OPENCLEXT(ext) -#endif // OPENCLEXT -#endif // OPENCLEXT_INTERNAL +#define OPENCL_GENERIC_EXTENSION(ext, ...) OPENCLEXTNAME(ext) +#endif // OPENCLEXTNAME +#endif // OPENCL_GENERIC_EXTENSION + +// Declaration helpers +#define OPENCL_EXTENSION(ext, avail) OPENCL_GENERIC_EXTENSION(ext, avail, 0U, 0U) +#define OPENCL_COREFEATURE(ext, avail, core) OPENCL_GENERIC_EXTENSION(ext, avail, core, 0U) +#define OPENCL_OPTIONALCOREFEATURE(ext, avail, opt) OPENCL_GENERIC_EXTENSION(ext, avail, 0U, opt) // OpenCL 1.0. -OPENCLEXT_INTERNAL(cl_khr_3d_image_writes, 100, 200) -OPENCLEXT_INTERNAL(cl_khr_byte_addressable_store, 100, 110) -OPENCLEXT_INTERNAL(cl_khr_fp16, 100, ~0U) -OPENCLEXT_INTERNAL(cl_khr_fp64, 100, 120) -OPENCLEXT_INTERNAL(cl_khr_global_int32_base_atomics, 100, 110) -OPENCLEXT_INTERNAL(cl_khr_global_int32_extended_atomics, 100, 110) -OPENCLEXT_INTERNAL(cl_khr_local_int32_base_atomics, 100, 110) -OPENCLEXT_INTERNAL(cl_khr_local_int32_extended_atomics, 100, 110) -OPENCLEXT_INTERNAL(cl_khr_int64_base_atomics, 100, ~0U) -OPENCLEXT_INTERNAL(cl_khr_int64_extended_atomics, 100, ~0U) +OPENCL_COREFEATURE(cl_khr_byte_addressable_store, 100, OCL_C_11P) +OPENCL_COREFEATURE(cl_khr_global_int32_base_atomics, 100, OCL_C_11P) +OPENCL_COREFEATURE(cl_khr_global_int32_extended_atomics, 100, OCL_C_11P) +OPENCL_COREFEATURE(cl_khr_local_int32_base_atomics, 100, OCL_C_11P) +OPENCL_COREFEATURE(cl_khr_local_int32_extended_atomics, 100, OCL_C_11P) +OPENCL_OPTIONALCOREFEATURE(cl_khr_fp64, 100, OCL_C_12P) +OPENCL_EXTENSION(cl_khr_fp16, 100) +OPENCL_EXTENSION(cl_khr_int64_base_atomics, 100) +OPENCL_EXTENSION(cl_khr_int64_extended_atomics, 100) +OPENCL_GENERIC_EXTENSION(cl_khr_3d_image_writes, 100, OCL_C_20, OCL_C_30) // EMBEDDED_PROFILE -OPENCLEXT_INTERNAL(cles_khr_int64, 110, ~0U) +OPENCL_EXTENSION(cles_khr_int64, 110) // OpenCL 1.2. -OPENCLEXT_INTERNAL(cl_khr_depth_images, 120, ~0U) -OPENCLEXT_INTERNAL(cl_khr_gl_msaa_sharing, 120, ~0U) +OPENCL_EXTENSION(cl_khr_depth_images, 120) +OPENCL_EXTENSION(cl_khr_gl_msaa_sharing, 120) // OpenCL 2.0. -OPENCLEXT_INTERNAL(cl_khr_mipmap_image, 200, ~0U) -OPENCLEXT_INTERNAL(cl_khr_mipmap_image_writes, 200, ~0U) -OPENCLEXT_INTERNAL(cl_khr_srgb_image_writes, 200, ~0U) -OPENCLEXT_INTERNAL(cl_khr_subgroups, 200, ~0U) +OPENCL_EXTENSION(cl_khr_mipmap_image, 200) +OPENCL_EXTENSION(cl_khr_mipmap_image_writes, 200) +OPENCL_EXTENSION(cl_khr_srgb_image_writes, 200) +OPENCL_EXTENSION(cl_khr_subgroups, 200) +OPENCL_EXTENSION(cl_khr_subgroup_extended_types, 200) +OPENCL_EXTENSION(cl_khr_subgroup_non_uniform_vote, 200) +OPENCL_EXTENSION(cl_khr_subgroup_ballot, 200) +OPENCL_EXTENSION(cl_khr_subgroup_non_uniform_arithmetic, 200) +OPENCL_EXTENSION(cl_khr_subgroup_shuffle, 200) +OPENCL_EXTENSION(cl_khr_subgroup_shuffle_relative, 200) +OPENCL_EXTENSION(cl_khr_subgroup_clustered_reduce, 200) // Clang Extensions. -OPENCLEXT_INTERNAL(cl_clang_storage_class_specifiers, 100, ~0U) -OPENCLEXT_INTERNAL(__cl_clang_function_pointers, 100, ~0U) -OPENCLEXT_INTERNAL(__cl_clang_variadic_functions, 100, ~0U) +OPENCL_EXTENSION(cl_clang_storage_class_specifiers, 100) +OPENCL_EXTENSION(__cl_clang_function_pointers, 100) +OPENCL_EXTENSION(__cl_clang_variadic_functions, 100) // AMD OpenCL extensions -OPENCLEXT_INTERNAL(cl_amd_media_ops, 100, ~0U) -OPENCLEXT_INTERNAL(cl_amd_media_ops2, 100, ~0U) +OPENCL_EXTENSION(cl_amd_media_ops, 100) +OPENCL_EXTENSION(cl_amd_media_ops2, 100) // ARM OpenCL extensions -OPENCLEXT_INTERNAL(cl_arm_integer_dot_product_int8, 120, ~0U) -OPENCLEXT_INTERNAL(cl_arm_integer_dot_product_accumulate_int8, 120, ~0U) -OPENCLEXT_INTERNAL(cl_arm_integer_dot_product_accumulate_int16, 120, ~0U) -OPENCLEXT_INTERNAL(cl_arm_integer_dot_product_accumulate_saturate_int8, 120, ~0U) +OPENCL_EXTENSION(cl_arm_integer_dot_product_int8, 120) +OPENCL_EXTENSION(cl_arm_integer_dot_product_accumulate_int8, 120) +OPENCL_EXTENSION(cl_arm_integer_dot_product_accumulate_int16, 120) +OPENCL_EXTENSION(cl_arm_integer_dot_product_accumulate_saturate_int8, 120) // Intel OpenCL extensions -OPENCLEXT_INTERNAL(cl_intel_subgroups, 120, ~0U) -OPENCLEXT_INTERNAL(cl_intel_subgroups_short, 120, ~0U) -OPENCLEXT_INTERNAL(cl_intel_device_side_avc_motion_estimation, 120, ~0U) +OPENCL_EXTENSION(cl_intel_subgroups, 120) +OPENCL_EXTENSION(cl_intel_subgroups_short, 120) +OPENCL_EXTENSION(cl_intel_device_side_avc_motion_estimation, 120) + -#undef OPENCLEXT_INTERNAL +#undef OPENCL_OPTIONALCOREFEATURE +#undef OPENCL_COREFEATURE +#undef OPENCL_GENERIC_EXTENSION -#ifdef OPENCLEXT -#undef OPENCLEXT +#ifdef OPENCLEXTNAME +#undef OPENCLEXTNAME #endif
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits