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     // Option starts to be available in this OpenCL version
69     unsigned Avail;
70 
71     // Option becomes core feature in this OpenCL versions
72     unsigned Core;
73 
74     // Option becomes optional core feature in this OpenCL versions
75     unsigned Opt;
76 
77     // Is this option supported
78     bool Supported = false;
79 
80     // Is this option enabled
81     bool Enabled = false;
82 
83     OpenCLOptionInfo(unsigned A = 100, unsigned C = 0U, unsigned O = 0U)
84         : Avail(A), Core(C), Opt(O) {}
85 
86     bool isCore() const { return Core != 0U; }
87 
88     bool isOptionalCore() const { return Opt != 0U; }
89 
90     // Is option available in OpenCL version \p LO.
91     bool isAvailableIn(const LangOptions &LO) const {
92       // In C++ mode all extensions should work at least as in v2.0.
93       auto CLVer = LO.OpenCLCPlusPlus ? 200 : LO.OpenCLVersion;
94       return CLVer >= Avail;
95     }
96 
97     // Is core option in OpenCL version \p LO.
98     bool isCoreIn(const LangOptions &LO) const {
99       return isAvailableIn(LO) && isOpenCLVersionIsContainedInMask(LO, Core);
100     }
101 
102     // Is optional core option in OpenCL version \p LO.
103     bool isOptionalCoreIn(const LangOptions &LO) const {
104       return isAvailableIn(LO) && isOpenCLVersionIsContainedInMask(LO, Opt);
105     }
106   };
107 
108   bool isKnown(llvm::StringRef Ext) const;
109 
110   bool isEnabled(llvm::StringRef Ext) const;
111 
112   // Is supported as either an extension or an (optional) core feature for
113   // OpenCL version \p LO.
114   bool isSupported(llvm::StringRef Ext, const LangOptions &LO) const;
115 
116   // Is supported OpenCL core feature for OpenCL version \p LO.
117   // For supported extension, return false.
118   bool isSupportedCore(llvm::StringRef Ext, const LangOptions &LO) const;
119 
120   // Is supported optional core OpenCL feature for OpenCL version \p LO.
121   // For supported extension, return false.
122   bool isSupportedOptionalCore(llvm::StringRef Ext,
123                                const LangOptions &LO) const;
124 
125   // Is supported optional core or core OpenCL feature for OpenCL version \p
126   // LO. For supported extension, return false.
127   bool isSupportedCoreOrOptionalCore(llvm::StringRef Ext,
128                                      const LangOptions &LO) const;
129 
130   // Is supported OpenCL extension for OpenCL version \p LO.
131   // For supported core or optional core feature, return false.
132   bool isSupportedExtension(llvm::StringRef Ext, const LangOptions &LO) const;
133 
134   void enable(llvm::StringRef Ext, bool V = true);
135 
136   /// Enable or disable support for OpenCL extensions
137   /// \param Ext name of the extension (not prefixed with '+' or '-')
138   /// \param V value to set for a extension
139   void support(llvm::StringRef Ext, bool V = true);
140 
141   OpenCLOptions();
142   OpenCLOptions(const OpenCLOptions &) = default;
143 
144   // Set supported options based on target settings and language version
145   void addSupport(const llvm::StringMap<bool> &FeaturesMap,
146                   const LangOptions &Opts);
147 
148   // Disable all extensions
149   void disableAll();
150 
151   // Enable supported core and optional core features
152   void enableSupportedCore(const LangOptions &LO);
153 
154   friend class ASTWriter;
155   friend class ASTReader;
156 
157   using OpenCLOptionInfoMap = llvm::StringMap<OpenCLOptionInfo>;
158 
159 private:
160   OpenCLOptionInfoMap OptMap;
161 };
162 
163 } // end namespace clang
164 
165 #endif
166