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:
isKnown(llvm::StringRef Ext)35   bool isKnown(llvm::StringRef Ext) const {
36     return OptMap.find(Ext) != OptMap.end();
37   }
38 
isEnabled(llvm::StringRef Ext)39   bool isEnabled(llvm::StringRef Ext) const {
40     return OptMap.find(Ext)->second.Enabled;
41   }
42 
43   // Is supported as either an extension or an (optional) core feature for
44   // OpenCL version \p CLVer.
isSupported(llvm::StringRef Ext,const LangOptions & LO)45   bool isSupported(llvm::StringRef Ext, const LangOptions &LO) const {
46     // In C++ mode all extensions should work at least as in v2.0.
47     auto CLVer = LO.OpenCLCPlusPlus ? 200 : LO.OpenCLVersion;
48     auto I = OptMap.find(Ext)->getValue();
49     return I.Supported && I.Avail <= CLVer;
50   }
51 
52   // Is supported (optional) OpenCL core features for OpenCL version \p CLVer.
53   // For supported extension, return false.
isSupportedCore(llvm::StringRef Ext,const LangOptions & LO)54   bool isSupportedCore(llvm::StringRef Ext, const LangOptions &LO) const {
55     // In C++ mode all extensions should work at least as in v2.0.
56     auto CLVer = LO.OpenCLCPlusPlus ? 200 : LO.OpenCLVersion;
57     auto I = OptMap.find(Ext)->getValue();
58     return I.Supported && I.Avail <= CLVer && I.Core != ~0U && CLVer >= I.Core;
59   }
60 
61   // Is supported OpenCL extension for OpenCL version \p CLVer.
62   // For supported (optional) core feature, return false.
isSupportedExtension(llvm::StringRef Ext,const LangOptions & LO)63   bool isSupportedExtension(llvm::StringRef Ext, const LangOptions &LO) const {
64     // In C++ mode all extensions should work at least as in v2.0.
65     auto CLVer = LO.OpenCLCPlusPlus ? 200 : LO.OpenCLVersion;
66     auto I = OptMap.find(Ext)->getValue();
67     return I.Supported && I.Avail <= CLVer && (I.Core == ~0U || CLVer < I.Core);
68   }
69 
70   void enable(llvm::StringRef Ext, bool V = true) {
71     OptMap[Ext].Enabled = V;
72   }
73 
74   /// Enable or disable support for OpenCL extensions
75   /// \param Ext name of the extension optionally prefixed with
76   ///        '+' or '-'
77   /// \param V used when \p Ext is not prefixed by '+' or '-'
78   void support(llvm::StringRef Ext, bool V = true) {
79     assert(!Ext.empty() && "Extension is empty.");
80 
81     switch (Ext[0]) {
82     case '+':
83       V = true;
84       Ext = Ext.drop_front();
85       break;
86     case '-':
87       V = false;
88       Ext = Ext.drop_front();
89       break;
90     }
91 
92     if (Ext.equals("all")) {
93       supportAll(V);
94       return;
95     }
96     OptMap[Ext].Supported = V;
97   }
98 
OpenCLOptions()99   OpenCLOptions(){
100 #define OPENCLEXT_INTERNAL(Ext, AvailVer, CoreVer) \
101     OptMap[#Ext].Avail = AvailVer; \
102     OptMap[#Ext].Core = CoreVer;
103 #include "clang/Basic/OpenCLExtensions.def"
104   }
105 
addSupport(const OpenCLOptions & Opts)106   void addSupport(const OpenCLOptions &Opts) {
107     for (auto &I:Opts.OptMap)
108       if (I.second.Supported)
109         OptMap[I.getKey()].Supported = true;
110   }
111 
copy(const OpenCLOptions & Opts)112   void copy(const OpenCLOptions &Opts) {
113     OptMap = Opts.OptMap;
114   }
115 
116   // Turn on or off support of all options.
117   void supportAll(bool On = true) {
118     for (llvm::StringMap<Info>::iterator I = OptMap.begin(),
119          E = OptMap.end(); I != E; ++I)
120       I->second.Supported = On;
121   }
122 
disableAll()123   void disableAll() {
124     for (llvm::StringMap<Info>::iterator I = OptMap.begin(),
125          E = OptMap.end(); I != E; ++I)
126       I->second.Enabled = false;
127   }
128 
enableSupportedCore(LangOptions LO)129   void enableSupportedCore(LangOptions LO) {
130     for (llvm::StringMap<Info>::iterator I = OptMap.begin(), E = OptMap.end();
131          I != E; ++I)
132       if (isSupportedCore(I->getKey(), LO))
133         I->second.Enabled = true;
134   }
135 
136   friend class ASTWriter;
137   friend class ASTReader;
138 };
139 
140 } // end namespace clang
141 
142 #endif
143