1 //===--- OpenCLOptions.h ----------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 ///
10 /// \file
11 /// Defines the clang::OpenCLOptions class.
12 ///
13 //===----------------------------------------------------------------------===//
14 
15 #ifndef LLVM_CLANG_BASIC_OPENCLOPTIONS_H
16 #define LLVM_CLANG_BASIC_OPENCLOPTIONS_H
17 
18 #include "clang/Basic/LangOptions.h"
19 #include "llvm/ADT/StringMap.h"
20 
21 namespace clang {
22 
23 /// OpenCL supported extensions and optional core features
24 class OpenCLOptions {
25   struct Info {
26     bool Supported; // Is this option supported
27     bool Enabled;   // Is this option enabled
28     unsigned Avail; // Option starts to be available in this OpenCL version
29     unsigned Core;  // Option becomes (optional) core feature in this OpenCL
30                     // version
31     Info(bool S = false, bool E = false, unsigned A = 100, unsigned C = ~0U)
SupportedInfo32       :Supported(S), Enabled(E), Avail(A), Core(C){}
33   };
34   llvm::StringMap<Info> OptMap;
35 public:
isKnown(llvm::StringRef Ext)36   bool isKnown(llvm::StringRef Ext) const {
37     return OptMap.find(Ext) != OptMap.end();
38   }
39 
isEnabled(llvm::StringRef Ext)40   bool isEnabled(llvm::StringRef Ext) const {
41     return OptMap.find(Ext)->second.Enabled;
42   }
43 
44   // Is supported as either an extension or an (optional) core feature for
45   // OpenCL version \p CLVer.
isSupported(llvm::StringRef Ext,LangOptions LO)46   bool isSupported(llvm::StringRef Ext, LangOptions LO) const {
47     // In C++ mode all extensions should work at least as in v2.0.
48     auto CLVer = LO.OpenCLCPlusPlus ? 200 : LO.OpenCLVersion;
49     auto I = OptMap.find(Ext)->getValue();
50     return I.Supported && I.Avail <= CLVer;
51   }
52 
53   // Is supported (optional) OpenCL core features for OpenCL version \p CLVer.
54   // For supported extension, return false.
isSupportedCore(llvm::StringRef Ext,LangOptions LO)55   bool isSupportedCore(llvm::StringRef Ext, LangOptions LO) const {
56     // In C++ mode all extensions should work at least as in v2.0.
57     auto CLVer = LO.OpenCLCPlusPlus ? 200 : LO.OpenCLVersion;
58     auto I = OptMap.find(Ext)->getValue();
59     return I.Supported && I.Avail <= CLVer && I.Core != ~0U && CLVer >= I.Core;
60   }
61 
62   // Is supported OpenCL extension for OpenCL version \p CLVer.
63   // For supported (optional) core feature, return false.
isSupportedExtension(llvm::StringRef Ext,LangOptions LO)64   bool isSupportedExtension(llvm::StringRef Ext, LangOptions LO) const {
65     // In C++ mode all extensions should work at least as in v2.0.
66     auto CLVer = LO.OpenCLCPlusPlus ? 200 : LO.OpenCLVersion;
67     auto I = OptMap.find(Ext)->getValue();
68     return I.Supported && I.Avail <= CLVer && (I.Core == ~0U || CLVer < I.Core);
69   }
70 
71   void enable(llvm::StringRef Ext, bool V = true) {
72     OptMap[Ext].Enabled = V;
73   }
74 
75   /// Enable or disable support for OpenCL extensions
76   /// \param Ext name of the extension optionally prefixed with
77   ///        '+' or '-'
78   /// \param V used when \p Ext is not prefixed by '+' or '-'
79   void support(llvm::StringRef Ext, bool V = true) {
80     assert(!Ext.empty() && "Extension is empty.");
81 
82     switch (Ext[0]) {
83     case '+':
84       V = true;
85       Ext = Ext.drop_front();
86       break;
87     case '-':
88       V = false;
89       Ext = Ext.drop_front();
90       break;
91     }
92 
93     if (Ext.equals("all")) {
94       supportAll(V);
95       return;
96     }
97     OptMap[Ext].Supported = V;
98   }
99 
OpenCLOptions()100   OpenCLOptions(){
101 #define OPENCLEXT_INTERNAL(Ext, AvailVer, CoreVer) \
102     OptMap[#Ext].Avail = AvailVer; \
103     OptMap[#Ext].Core = CoreVer;
104 #include "clang/Basic/OpenCLExtensions.def"
105   }
106 
addSupport(const OpenCLOptions & Opts)107   void addSupport(const OpenCLOptions &Opts) {
108     for (auto &I:Opts.OptMap)
109       if (I.second.Supported)
110         OptMap[I.getKey()].Supported = true;
111   }
112 
copy(const OpenCLOptions & Opts)113   void copy(const OpenCLOptions &Opts) {
114     OptMap = Opts.OptMap;
115   }
116 
117   // Turn on or off support of all options.
118   void supportAll(bool On = true) {
119     for (llvm::StringMap<Info>::iterator I = OptMap.begin(),
120          E = OptMap.end(); I != E; ++I)
121       I->second.Supported = On;
122   }
123 
disableAll()124   void disableAll() {
125     for (llvm::StringMap<Info>::iterator I = OptMap.begin(),
126          E = OptMap.end(); I != E; ++I)
127       I->second.Enabled = false;
128   }
129 
enableSupportedCore(LangOptions LO)130   void enableSupportedCore(LangOptions LO) {
131     for (llvm::StringMap<Info>::iterator I = OptMap.begin(), E = OptMap.end();
132          I != E; ++I)
133       if (isSupportedCore(I->getKey(), LO))
134         I->second.Enabled = true;
135   }
136 
137   friend class ASTWriter;
138   friend class ASTReader;
139 };
140 
141 } // end namespace clang
142 
143 #endif
144