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
encodeOpenCLVersion(unsigned OpenCLVersion)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 // Check if OpenCL C version is contained in a given encoded OpenCL C version
55 // mask.
isOpenCLVersionContainedInMask(const LangOptions & LO,unsigned Mask)56 static inline bool isOpenCLVersionContainedInMask(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
63 } // end anonymous namespace
64
65 /// OpenCL supported extensions and optional core features
66 class OpenCLOptions {
67 public:
68 struct OpenCLOptionInfo {
69 // Does this option have pragma.
70 bool WithPragma = false;
71
72 // Option starts to be available in this OpenCL version
73 unsigned Avail = 100U;
74
75 // Option becomes core feature in this OpenCL versions
76 unsigned Core = 0U;
77
78 // Option becomes optional core feature in this OpenCL versions
79 unsigned Opt = 0U;
80
81 // Is this option supported
82 bool Supported = false;
83
84 // Is this option enabled
85 bool Enabled = false;
86
87 OpenCLOptionInfo() = default;
OpenCLOptionInfoOpenCLOptionInfo88 OpenCLOptionInfo(bool Pragma, unsigned AvailV, unsigned CoreV,
89 unsigned OptV)
90 : WithPragma(Pragma), Avail(AvailV), Core(CoreV), Opt(OptV) {}
91
isCoreOpenCLOptionInfo92 bool isCore() const { return Core != 0U; }
93
isOptionalCoreOpenCLOptionInfo94 bool isOptionalCore() const { return Opt != 0U; }
95
96 // Is option available in OpenCL version \p LO.
isAvailableInOpenCLOptionInfo97 bool isAvailableIn(const LangOptions &LO) const {
98 // In C++ mode all extensions should work at least as in v2.0.
99 auto CLVer = LO.OpenCLCPlusPlus ? 200 : LO.OpenCLVersion;
100 return CLVer >= Avail;
101 }
102
103 // Is core option in OpenCL version \p LO.
isCoreInOpenCLOptionInfo104 bool isCoreIn(const LangOptions &LO) const {
105 return isAvailableIn(LO) && isOpenCLVersionContainedInMask(LO, Core);
106 }
107
108 // Is optional core option in OpenCL version \p LO.
isOptionalCoreInOpenCLOptionInfo109 bool isOptionalCoreIn(const LangOptions &LO) const {
110 return isAvailableIn(LO) && isOpenCLVersionContainedInMask(LO, Opt);
111 }
112 };
113
114 bool isKnown(llvm::StringRef Ext) const;
115
116 // For core or optional core feature check that it is supported
117 // by a target, for any other option (extension) check that it is
118 // enabled via pragma
119 bool isAvailableOption(llvm::StringRef Ext, const LangOptions &LO) const;
120
121 bool isWithPragma(llvm::StringRef Ext) const;
122
123 // Is supported as either an extension or an (optional) core feature for
124 // OpenCL version \p LO.
125 bool isSupported(llvm::StringRef Ext, const LangOptions &LO) const;
126
127 // Is supported OpenCL core feature for OpenCL version \p LO.
128 // For supported extension, return false.
129 bool isSupportedCore(llvm::StringRef Ext, const LangOptions &LO) const;
130
131 // Is supported optional core OpenCL feature for OpenCL version \p LO.
132 // For supported extension, return false.
133 bool isSupportedOptionalCore(llvm::StringRef Ext,
134 const LangOptions &LO) const;
135
136 // Is supported optional core or core OpenCL feature for OpenCL version \p
137 // LO. For supported extension, return false.
138 bool isSupportedCoreOrOptionalCore(llvm::StringRef Ext,
139 const LangOptions &LO) const;
140
141 // Is supported OpenCL extension for OpenCL version \p LO.
142 // For supported core or optional core feature, return false.
143 bool isSupportedExtension(llvm::StringRef Ext, const LangOptions &LO) const;
144
145 // FIXME: Whether extension should accept pragma should not
146 // be reset dynamically. But it currently required when
147 // registering new extensions via pragmas.
148 void acceptsPragma(llvm::StringRef Ext, bool V = true);
149
150 void enable(llvm::StringRef Ext, bool V = true);
151
152 /// Enable or disable support for OpenCL extensions
153 /// \param Ext name of the extension (not prefixed with '+' or '-')
154 /// \param V value to set for a extension
155 void support(llvm::StringRef Ext, bool V = true);
156
157 OpenCLOptions();
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 template <typename... Args>
isOpenCLOptionCoreIn(const LangOptions & LO,Args &&...args)172 static bool isOpenCLOptionCoreIn(const LangOptions &LO, Args &&... args) {
173 return OpenCLOptionInfo(std::forward<Args>(args)...).isCoreIn(LO);
174 }
175
176 template <typename... Args>
isOpenCLOptionAvailableIn(const LangOptions & LO,Args &&...args)177 static bool isOpenCLOptionAvailableIn(const LangOptions &LO,
178 Args &&... args) {
179 return OpenCLOptionInfo(std::forward<Args>(args)...).isAvailableIn(LO);
180 }
181
182 private:
183 // Option is enabled via pragma
184 bool isEnabled(llvm::StringRef Ext) const;
185
186 OpenCLOptionInfoMap OptMap;
187 };
188
189 } // end namespace clang
190
191 #endif
192