1 //===--- OpenCLOptions.h ----------------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 /// 9 /// \file 10 /// Defines the clang::OpenCLOptions class. 11 /// 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_CLANG_BASIC_OPENCLOPTIONS_H 15 #define LLVM_CLANG_BASIC_OPENCLOPTIONS_H 16 17 #include "clang/Basic/LangOptions.h" 18 #include "llvm/ADT/StringMap.h" 19 20 namespace clang { 21 22 class DiagnosticsEngine; 23 class TargetInfo; 24 25 namespace { 26 // This enum maps OpenCL version(s) into value. These values are used as 27 // a mask to indicate in which OpenCL version(s) extension is a core or 28 // optional core feature. 29 enum OpenCLVersionID : unsigned int { 30 OCL_C_10 = 0x1, 31 OCL_C_11 = 0x2, 32 OCL_C_12 = 0x4, 33 OCL_C_20 = 0x8, 34 OCL_C_30 = 0x10, 35 OCL_C_ALL = 0x1f, 36 OCL_C_11P = OCL_C_ALL ^ OCL_C_10, // OpenCL C 1.1+ 37 OCL_C_12P = OCL_C_ALL ^ (OCL_C_10 | OCL_C_11), // OpenCL C 1.2+ 38 }; 39 40 static inline OpenCLVersionID encodeOpenCLVersion(unsigned OpenCLVersion) { 41 switch (OpenCLVersion) { 42 default: 43 llvm_unreachable("Unknown OpenCL version code"); 44 case 100: 45 return OCL_C_10; 46 case 110: 47 return OCL_C_11; 48 case 120: 49 return OCL_C_12; 50 case 200: 51 return OCL_C_20; 52 case 300: 53 return OCL_C_30; 54 } 55 } 56 57 // Check if OpenCL C version is contained in a given encoded OpenCL C version 58 // mask. 59 static inline bool isOpenCLVersionContainedInMask(const LangOptions &LO, 60 unsigned Mask) { 61 auto CLVer = LO.getOpenCLCompatibleVersion(); 62 OpenCLVersionID Code = encodeOpenCLVersion(CLVer); 63 return Mask & Code; 64 } 65 66 } // end anonymous namespace 67 68 /// OpenCL supported extensions and optional core features 69 class OpenCLOptions { 70 71 public: 72 // OpenCL C v1.2 s6.5 - All program scope variables must be declared in the 73 // __constant address space. 74 // OpenCL C v2.0 s6.5.1 - Variables defined at program scope and static 75 // variables inside a function can also be declared in the global 76 // address space. 77 // OpenCL C v3.0 s6.7.1 - Variables at program scope or static or extern 78 // variables inside functions can be declared in global address space if 79 // the __opencl_c_program_scope_global_variables feature is supported 80 // C++ for OpenCL inherits rule from OpenCL C v2.0. 81 bool areProgramScopeVariablesSupported(const LangOptions &Opts) const { 82 return Opts.getOpenCLCompatibleVersion() == 200 || 83 (Opts.getOpenCLCompatibleVersion() == 300 && 84 isSupported("__opencl_c_program_scope_global_variables", Opts)); 85 } 86 87 struct OpenCLOptionInfo { 88 // Does this option have pragma. 89 bool WithPragma = false; 90 91 // Option starts to be available in this OpenCL version 92 unsigned Avail = 100U; 93 94 // Option becomes core feature in this OpenCL versions 95 unsigned Core = 0U; 96 97 // Option becomes optional core feature in this OpenCL versions 98 unsigned Opt = 0U; 99 100 // Is this option supported 101 bool Supported = false; 102 103 // Is this option enabled 104 bool Enabled = false; 105 106 OpenCLOptionInfo() = default; 107 OpenCLOptionInfo(bool Pragma, unsigned AvailV, unsigned CoreV, 108 unsigned OptV) 109 : WithPragma(Pragma), Avail(AvailV), Core(CoreV), Opt(OptV) {} 110 111 bool isCore() const { return Core != 0U; } 112 113 bool isOptionalCore() const { return Opt != 0U; } 114 115 // Is option available in OpenCL version \p LO. 116 bool isAvailableIn(const LangOptions &LO) const { 117 // In C++ mode all extensions should work at least as in v2.0. 118 return LO.getOpenCLCompatibleVersion() >= Avail; 119 } 120 121 // Is core option in OpenCL version \p LO. 122 bool isCoreIn(const LangOptions &LO) const { 123 return isAvailableIn(LO) && isOpenCLVersionContainedInMask(LO, Core); 124 } 125 126 // Is optional core option in OpenCL version \p LO. 127 bool isOptionalCoreIn(const LangOptions &LO) const { 128 return isAvailableIn(LO) && isOpenCLVersionContainedInMask(LO, Opt); 129 } 130 }; 131 132 bool isKnown(llvm::StringRef Ext) const; 133 134 // For core or optional core feature check that it is supported 135 // by a target, for any other option (extension) check that it is 136 // enabled via pragma 137 bool isAvailableOption(llvm::StringRef Ext, const LangOptions &LO) const; 138 139 bool isWithPragma(llvm::StringRef Ext) const; 140 141 // Is supported as either an extension or an (optional) core feature for 142 // OpenCL version \p LO. 143 bool isSupported(llvm::StringRef Ext, const LangOptions &LO) const; 144 145 // Is supported OpenCL core feature for OpenCL version \p LO. 146 // For supported extension, return false. 147 bool isSupportedCore(llvm::StringRef Ext, const LangOptions &LO) const; 148 149 // Is supported optional core OpenCL feature for OpenCL version \p LO. 150 // For supported extension, return false. 151 bool isSupportedOptionalCore(llvm::StringRef Ext, 152 const LangOptions &LO) const; 153 154 // Is supported optional core or core OpenCL feature for OpenCL version \p 155 // LO. For supported extension, return false. 156 bool isSupportedCoreOrOptionalCore(llvm::StringRef Ext, 157 const LangOptions &LO) const; 158 159 // Is supported OpenCL extension for OpenCL version \p LO. 160 // For supported core or optional core feature, return false. 161 bool isSupportedExtension(llvm::StringRef Ext, const LangOptions &LO) const; 162 163 // FIXME: Whether extension should accept pragma should not 164 // be reset dynamically. But it currently required when 165 // registering new extensions via pragmas. 166 void acceptsPragma(llvm::StringRef Ext, bool V = true); 167 168 void enable(llvm::StringRef Ext, bool V = true); 169 170 /// Enable or disable support for OpenCL extensions 171 /// \param Ext name of the extension (not prefixed with '+' or '-') 172 /// \param V value to set for a extension 173 void support(llvm::StringRef Ext, bool V = true); 174 175 OpenCLOptions(); 176 177 // Set supported options based on target settings and language version 178 void addSupport(const llvm::StringMap<bool> &FeaturesMap, 179 const LangOptions &Opts); 180 181 // Disable all extensions 182 void disableAll(); 183 184 friend class ASTWriter; 185 friend class ASTReader; 186 187 using OpenCLOptionInfoMap = llvm::StringMap<OpenCLOptionInfo>; 188 189 template <typename... Args> 190 static bool isOpenCLOptionCoreIn(const LangOptions &LO, Args &&... args) { 191 return OpenCLOptionInfo(std::forward<Args>(args)...).isCoreIn(LO); 192 } 193 194 template <typename... Args> 195 static bool isOpenCLOptionAvailableIn(const LangOptions &LO, 196 Args &&... args) { 197 return OpenCLOptionInfo(std::forward<Args>(args)...).isAvailableIn(LO); 198 } 199 200 // Diagnose feature dependencies for OpenCL C 3.0. Return false if target 201 // doesn't follow these requirements. 202 static bool diagnoseUnsupportedFeatureDependencies(const TargetInfo &TI, 203 DiagnosticsEngine &Diags); 204 205 // Diagnose that features and equivalent extension are set to same values. 206 // Return false if target doesn't follow these requirements. 207 static bool diagnoseFeatureExtensionDifferences(const TargetInfo &TI, 208 DiagnosticsEngine &Diags); 209 210 private: 211 // Option is enabled via pragma 212 bool isEnabled(llvm::StringRef Ext) const; 213 214 OpenCLOptionInfoMap OptMap; 215 }; 216 217 } // end namespace clang 218 219 #endif 220