//===--- OpenCLOptions.h ----------------------------------------*- 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 // //===----------------------------------------------------------------------===// /// /// \file /// Defines the clang::OpenCLOptions class. /// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_BASIC_OPENCLOPTIONS_H #define LLVM_CLANG_BASIC_OPENCLOPTIONS_H #include "clang/Basic/LangOptions.h" #include "llvm/ADT/StringMap.h" namespace clang { class DiagnosticsEngine; class TargetInfo; namespace { // 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+ }; static inline OpenCLVersionID encodeOpenCLVersion(unsigned OpenCLVersion) { switch (OpenCLVersion) { default: llvm_unreachable("Unknown OpenCL version 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 OpenCL C version is contained in a given encoded OpenCL C version // mask. static inline bool isOpenCLVersionContainedInMask(const LangOptions &LO, unsigned Mask) { auto CLVer = LO.getOpenCLCompatibleVersion(); OpenCLVersionID Code = encodeOpenCLVersion(CLVer); return Mask & Code; } } // end anonymous namespace /// OpenCL supported extensions and optional core features class OpenCLOptions { public: // OpenCL C v1.2 s6.5 - All program scope variables must be declared in the // __constant address space. // OpenCL C v2.0 s6.5.1 - Variables defined at program scope and static // variables inside a function can also be declared in the global // address space. // OpenCL C v3.0 s6.7.1 - Variables at program scope or static or extern // variables inside functions can be declared in global address space if // the __opencl_c_program_scope_global_variables feature is supported // C++ for OpenCL inherits rule from OpenCL C v2.0. bool areProgramScopeVariablesSupported(const LangOptions &Opts) const { return Opts.getOpenCLCompatibleVersion() == 200 || (Opts.getOpenCLCompatibleVersion() == 300 && isSupported("__opencl_c_program_scope_global_variables", Opts)); } struct OpenCLOptionInfo { // Does this option have pragma. bool WithPragma = false; // Option starts to be available in this OpenCL version unsigned Avail = 100U; // Option becomes core feature in this OpenCL versions unsigned Core = 0U; // Option becomes optional core feature in this OpenCL versions unsigned Opt = 0U; // Is this option supported bool Supported = false; // Is this option enabled bool Enabled = false; OpenCLOptionInfo() = default; OpenCLOptionInfo(bool Pragma, unsigned AvailV, unsigned CoreV, unsigned OptV) : WithPragma(Pragma), Avail(AvailV), Core(CoreV), Opt(OptV) {} 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. return LO.getOpenCLCompatibleVersion() >= Avail; } // Is core option in OpenCL version \p LO. bool isCoreIn(const LangOptions &LO) const { return isAvailableIn(LO) && isOpenCLVersionContainedInMask(LO, Core); } // Is optional core option in OpenCL version \p LO. bool isOptionalCoreIn(const LangOptions &LO) const { return isAvailableIn(LO) && isOpenCLVersionContainedInMask(LO, Opt); } }; bool isKnown(llvm::StringRef Ext) const; // For core or optional core feature check that it is supported // by a target, for any other option (extension) check that it is // enabled via pragma bool isAvailableOption(llvm::StringRef Ext, const LangOptions &LO) const; bool isWithPragma(llvm::StringRef Ext) const; // 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; // 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; // FIXME: Whether extension should accept pragma should not // be reset dynamically. But it currently required when // registering new extensions via pragmas. void acceptsPragma(llvm::StringRef Ext, bool V = true); 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(); // Set supported options based on target settings and language version void addSupport(const llvm::StringMap &FeaturesMap, const LangOptions &Opts); // Disable all extensions void disableAll(); friend class ASTWriter; friend class ASTReader; using OpenCLOptionInfoMap = llvm::StringMap; template static bool isOpenCLOptionCoreIn(const LangOptions &LO, Args &&... args) { return OpenCLOptionInfo(std::forward(args)...).isCoreIn(LO); } template static bool isOpenCLOptionAvailableIn(const LangOptions &LO, Args &&... args) { return OpenCLOptionInfo(std::forward(args)...).isAvailableIn(LO); } // Diagnose feature dependencies for OpenCL C 3.0. Return false if target // doesn't follow these requirements. static bool diagnoseUnsupportedFeatureDependencies(const TargetInfo &TI, DiagnosticsEngine &Diags); // Diagnose that features and equivalent extension are set to same values. // Return false if target doesn't follow these requirements. static bool diagnoseFeatureExtensionDifferences(const TargetInfo &TI, DiagnosticsEngine &Diags); private: // Option is enabled via pragma bool isEnabled(llvm::StringRef Ext) const; OpenCLOptionInfoMap OptMap; }; } // end namespace clang #endif