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 namespace {
23 // This enum maps OpenCL version(s) into value. These values are used as
24 // a mask to indicate in which OpenCL version(s) extension is a core or
25 // optional core feature.
26 enum OpenCLVersionID : unsigned int {
27   OCL_C_10 = 0x1,
28   OCL_C_11 = 0x2,
29   OCL_C_12 = 0x4,
30   OCL_C_20 = 0x8,
31   OCL_C_30 = 0x10,
32   OCL_C_ALL = 0x1f,
33   OCL_C_11P = OCL_C_ALL ^ OCL_C_10,              // OpenCL C 1.1+
34   OCL_C_12P = OCL_C_ALL ^ (OCL_C_10 | OCL_C_11), // OpenCL C 1.2+
35 };
36 
37 static inline OpenCLVersionID encodeOpenCLVersion(unsigned OpenCLVersion) {
38   switch (OpenCLVersion) {
39   default:
40     llvm_unreachable("Unknown OpenCL version code");
41   case 100:
42     return OCL_C_10;
43   case 110:
44     return OCL_C_11;
45   case 120:
46     return OCL_C_12;
47   case 200:
48     return OCL_C_20;
49   case 300:
50     return OCL_C_30;
51   }
52 }
53 
54 // Simple helper to check if OpenCL C version is contained in a given encoded
55 // OpenCL C version mask
56 static inline bool isOpenCLVersionIsContainedInMask(const LangOptions &LO,
57                                                     unsigned Mask) {
58   auto CLVer = LO.OpenCLCPlusPlus ? 200 : LO.OpenCLVersion;
59   OpenCLVersionID Code = encodeOpenCLVersion(CLVer);
60   return Mask & Code;
61 }
62 } // end anonymous namespace
63 
64 /// OpenCL supported extensions and optional core features
65 class OpenCLOptions {
66 public:
67   struct OpenCLOptionInfo {
68     // Does this option have pragma.
69     bool WithPragma = false;
70 
71     // Option starts to be available in this OpenCL version
72     unsigned Avail = 100U;
73 
74     // Option becomes core feature in this OpenCL versions
75     unsigned Core = 0U;
76 
77     // Option becomes optional core feature in this OpenCL versions
78     unsigned Opt = 0U;
79 
80     // Is this option supported
81     bool Supported = false;
82 
83     // Is this option enabled
84     bool Enabled = false;
85 
86     OpenCLOptionInfo() = default;
87     OpenCLOptionInfo(bool Pragma, unsigned AvailV, unsigned CoreV,
88                      unsigned OptV)
89         : WithPragma(Pragma), Avail(AvailV), Core(CoreV), Opt(OptV) {}
90 
91     bool isCore() const { return Core != 0U; }
92 
93     bool isOptionalCore() const { return Opt != 0U; }
94 
95     // Is option available in OpenCL version \p LO.
96     bool isAvailableIn(const LangOptions &LO) const {
97       // In C++ mode all extensions should work at least as in v2.0.
98       auto CLVer = LO.OpenCLCPlusPlus ? 200 : LO.OpenCLVersion;
99       return CLVer >= Avail;
100     }
101 
102     // Is core option in OpenCL version \p LO.
103     bool isCoreIn(const LangOptions &LO) const {
104       return isAvailableIn(LO) && isOpenCLVersionIsContainedInMask(LO, Core);
105     }
106 
107     // Is optional core option in OpenCL version \p LO.
108     bool isOptionalCoreIn(const LangOptions &LO) const {
109       return isAvailableIn(LO) && isOpenCLVersionIsContainedInMask(LO, Opt);
110     }
111   };
112 
113   bool isKnown(llvm::StringRef Ext) const;
114 
115   // For core or optional core feature check that it is supported
116   // by a target, for any other option (extension) check that it is
117   // enabled via pragma
118   bool isAvailableOption(llvm::StringRef Ext, const LangOptions &LO) const;
119 
120   bool isWithPragma(llvm::StringRef Ext) const;
121 
122   // Is supported as either an extension or an (optional) core feature for
123   // OpenCL version \p LO.
124   bool isSupported(llvm::StringRef Ext, const LangOptions &LO) const;
125 
126   // Is supported OpenCL core feature for OpenCL version \p LO.
127   // For supported extension, return false.
128   bool isSupportedCore(llvm::StringRef Ext, const LangOptions &LO) const;
129 
130   // Is supported optional core OpenCL feature for OpenCL version \p LO.
131   // For supported extension, return false.
132   bool isSupportedOptionalCore(llvm::StringRef Ext,
133                                const LangOptions &LO) const;
134 
135   // Is supported optional core or core OpenCL feature for OpenCL version \p
136   // LO. For supported extension, return false.
137   bool isSupportedCoreOrOptionalCore(llvm::StringRef Ext,
138                                      const LangOptions &LO) const;
139 
140   // Is supported OpenCL extension for OpenCL version \p LO.
141   // For supported core or optional core feature, return false.
142   bool isSupportedExtension(llvm::StringRef Ext, const LangOptions &LO) const;
143 
144   // FIXME: Whether extension should accept pragma should not
145   // be reset dynamically. But it currently required when
146   // registering new extensions via pragmas.
147   void acceptsPragma(llvm::StringRef Ext, bool V = true);
148 
149   void enable(llvm::StringRef Ext, bool V = true);
150 
151   /// Enable or disable support for OpenCL extensions
152   /// \param Ext name of the extension (not prefixed with '+' or '-')
153   /// \param V value to set for a extension
154   void support(llvm::StringRef Ext, bool V = true);
155 
156   OpenCLOptions();
157   OpenCLOptions(const OpenCLOptions &) = default;
158 
159   // Set supported options based on target settings and language version
160   void addSupport(const llvm::StringMap<bool> &FeaturesMap,
161                   const LangOptions &Opts);
162 
163   // Disable all extensions
164   void disableAll();
165 
166   friend class ASTWriter;
167   friend class ASTReader;
168 
169   using OpenCLOptionInfoMap = llvm::StringMap<OpenCLOptionInfo>;
170 
171 private:
172   // Option is enabled via pragma
173   bool isEnabled(llvm::StringRef Ext) const;
174 
175   OpenCLOptionInfoMap OptMap;
176 };
177 
178 } // end namespace clang
179 
180 #endif
181