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