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 /// OpenCL supported extensions and optional core features 23 class OpenCLOptions { 24 struct Info { 25 bool Supported; // Is this option supported 26 bool Enabled; // Is this option enabled 27 unsigned Avail; // Option starts to be available in this OpenCL version 28 unsigned Core; // Option becomes (optional) core feature in this OpenCL 29 // version 30 Info(bool S = false, bool E = false, unsigned A = 100, unsigned C = ~0U) SupportedInfo31 :Supported(S), Enabled(E), Avail(A), Core(C){} 32 }; 33 llvm::StringMap<Info> OptMap; 34 public: 35 /// Check if \c Ext is a recognized OpenCL extension. 36 /// 37 /// \param Ext - Extension to look up. 38 /// \returns \c true if \c Ext is known, \c false otherwise. isKnown(llvm::StringRef Ext)39 bool isKnown(llvm::StringRef Ext) const { 40 return OptMap.find(Ext) != OptMap.end(); 41 } 42 43 /// Check if \c Ext is an enabled OpenCL extension. 44 /// 45 /// \param Ext - Extension to look up. 46 /// \returns \c true if \c Ext is known and enabled, \c false otherwise. isEnabled(llvm::StringRef Ext)47 bool isEnabled(llvm::StringRef Ext) const { 48 auto E = OptMap.find(Ext); 49 return E != OptMap.end() && E->second.Enabled; 50 } 51 52 /// Check if \c Ext is supported as either an extension or an (optional) core 53 /// feature for the given OpenCL version. 54 /// 55 /// \param Ext - Extension to look up. 56 /// \param LO - \c LangOptions specifying the OpenCL version. 57 /// \returns \c true if \c Ext is known and supported, \c false otherwise. isSupported(llvm::StringRef Ext,const LangOptions & LO)58 bool isSupported(llvm::StringRef Ext, const LangOptions &LO) const { 59 auto E = OptMap.find(Ext); 60 if (E == OptMap.end()) { 61 return false; 62 } 63 // In C++ mode all extensions should work at least as in v2.0. 64 auto CLVer = LO.OpenCLCPlusPlus ? 200 : LO.OpenCLVersion; 65 auto I = E->getValue(); 66 return I.Supported && I.Avail <= CLVer; 67 } 68 69 /// Check if \c Ext is supported as an (optional) OpenCL core features for 70 /// the given OpenCL version. 71 /// 72 /// \param Ext - Extension to look up. 73 /// \param LO - \c LangOptions specifying the OpenCL version. 74 /// \returns \c true if \c Ext is known and supported, \c false otherwise. isSupportedCore(llvm::StringRef Ext,const LangOptions & LO)75 bool isSupportedCore(llvm::StringRef Ext, const LangOptions &LO) const { 76 auto E = OptMap.find(Ext); 77 if (E == OptMap.end()) { 78 return false; 79 } 80 // In C++ mode all extensions should work at least as in v2.0. 81 auto CLVer = LO.OpenCLCPlusPlus ? 200 : LO.OpenCLVersion; 82 auto I = E->getValue(); 83 return I.Supported && I.Avail <= CLVer && I.Core != ~0U && CLVer >= I.Core; 84 } 85 86 /// Check if \c Ext is a supported OpenCL extension for the given OpenCL 87 /// version. 88 /// 89 /// \param Ext - Extension to look up. 90 /// \param LO - \c LangOptions specifying the OpenCL version. 91 /// \returns \c true if \c Ext is known and supported, \c false otherwise. isSupportedExtension(llvm::StringRef Ext,const LangOptions & LO)92 bool isSupportedExtension(llvm::StringRef Ext, const LangOptions &LO) const { 93 auto E = OptMap.find(Ext); 94 if (E == OptMap.end()) { 95 return false; 96 } 97 // In C++ mode all extensions should work at least as in v2.0. 98 auto CLVer = LO.OpenCLCPlusPlus ? 200 : LO.OpenCLVersion; 99 auto I = E->getValue(); 100 return I.Supported && I.Avail <= CLVer && (I.Core == ~0U || CLVer < I.Core); 101 } 102 103 void enable(llvm::StringRef Ext, bool V = true) { 104 OptMap[Ext].Enabled = V; 105 } 106 107 /// Enable or disable support for OpenCL extensions 108 /// \param Ext name of the extension optionally prefixed with 109 /// '+' or '-' 110 /// \param V used when \p Ext is not prefixed by '+' or '-' 111 void support(llvm::StringRef Ext, bool V = true) { 112 assert(!Ext.empty() && "Extension is empty."); 113 114 switch (Ext[0]) { 115 case '+': 116 V = true; 117 Ext = Ext.drop_front(); 118 break; 119 case '-': 120 V = false; 121 Ext = Ext.drop_front(); 122 break; 123 } 124 125 if (Ext.equals("all")) { 126 supportAll(V); 127 return; 128 } 129 OptMap[Ext].Supported = V; 130 } 131 OpenCLOptions()132 OpenCLOptions(){ 133 #define OPENCLEXT_INTERNAL(Ext, AvailVer, CoreVer) \ 134 OptMap[#Ext].Avail = AvailVer; \ 135 OptMap[#Ext].Core = CoreVer; 136 #include "clang/Basic/OpenCLExtensions.def" 137 } 138 addSupport(const OpenCLOptions & Opts)139 void addSupport(const OpenCLOptions &Opts) { 140 for (auto &I:Opts.OptMap) 141 if (I.second.Supported) 142 OptMap[I.getKey()].Supported = true; 143 } 144 copy(const OpenCLOptions & Opts)145 void copy(const OpenCLOptions &Opts) { 146 OptMap = Opts.OptMap; 147 } 148 149 // Turn on or off support of all options. 150 void supportAll(bool On = true) { 151 for (llvm::StringMap<Info>::iterator I = OptMap.begin(), 152 E = OptMap.end(); I != E; ++I) 153 I->second.Supported = On; 154 } 155 disableAll()156 void disableAll() { 157 for (llvm::StringMap<Info>::iterator I = OptMap.begin(), 158 E = OptMap.end(); I != E; ++I) 159 I->second.Enabled = false; 160 } 161 enableSupportedCore(LangOptions LO)162 void enableSupportedCore(LangOptions LO) { 163 for (llvm::StringMap<Info>::iterator I = OptMap.begin(), E = OptMap.end(); 164 I != E; ++I) 165 if (isSupportedCore(I->getKey(), LO)) 166 I->second.Enabled = true; 167 } 168 169 friend class ASTWriter; 170 friend class ASTReader; 171 }; 172 173 } // end namespace clang 174 175 #endif 176