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 | class DiagnosticsEngine; |
23 | class TargetInfo; |
24 | |
25 | namespace { |
26 | // This enum maps OpenCL version(s) into value. These values are used as |
27 | // a mask to indicate in which OpenCL version(s) extension is a core or |
28 | // optional core feature. |
29 | enum OpenCLVersionID : unsigned int { |
30 | OCL_C_10 = 0x1, |
31 | OCL_C_11 = 0x2, |
32 | OCL_C_12 = 0x4, |
33 | OCL_C_20 = 0x8, |
34 | OCL_C_30 = 0x10, |
35 | OCL_C_ALL = 0x1f, |
36 | OCL_C_11P = OCL_C_ALL ^ OCL_C_10, // OpenCL C 1.1+ |
37 | OCL_C_12P = OCL_C_ALL ^ (OCL_C_10 | OCL_C_11), // OpenCL C 1.2+ |
38 | }; |
39 | |
40 | static inline OpenCLVersionID encodeOpenCLVersion(unsigned OpenCLVersion) { |
41 | switch (OpenCLVersion) { |
42 | default: |
43 | llvm_unreachable("Unknown OpenCL version code" ); |
44 | case 100: |
45 | return OCL_C_10; |
46 | case 110: |
47 | return OCL_C_11; |
48 | case 120: |
49 | return OCL_C_12; |
50 | case 200: |
51 | return OCL_C_20; |
52 | case 300: |
53 | return OCL_C_30; |
54 | } |
55 | } |
56 | |
57 | // Check if OpenCL C version is contained in a given encoded OpenCL C version |
58 | // mask. |
59 | static inline bool isOpenCLVersionContainedInMask(const LangOptions &LO, |
60 | unsigned Mask) { |
61 | auto CLVer = LO.getOpenCLCompatibleVersion(); |
62 | OpenCLVersionID Code = encodeOpenCLVersion(OpenCLVersion: CLVer); |
63 | return Mask & Code; |
64 | } |
65 | |
66 | } // end anonymous namespace |
67 | |
68 | /// OpenCL supported extensions and optional core features |
69 | class OpenCLOptions { |
70 | |
71 | public: |
72 | // OpenCL C v1.2 s6.5 - All program scope variables must be declared in the |
73 | // __constant address space. |
74 | // OpenCL C v2.0 s6.5.1 - Variables defined at program scope and static |
75 | // variables inside a function can also be declared in the global |
76 | // address space. |
77 | // OpenCL C v3.0 s6.7.1 - Variables at program scope or static or extern |
78 | // variables inside functions can be declared in global address space if |
79 | // the __opencl_c_program_scope_global_variables feature is supported |
80 | // C++ for OpenCL inherits rule from OpenCL C v2.0. |
81 | bool areProgramScopeVariablesSupported(const LangOptions &Opts) const { |
82 | return Opts.getOpenCLCompatibleVersion() == 200 || |
83 | (Opts.getOpenCLCompatibleVersion() == 300 && |
84 | isSupported(Ext: "__opencl_c_program_scope_global_variables" , LO: Opts)); |
85 | } |
86 | |
87 | struct OpenCLOptionInfo { |
88 | // Does this option have pragma. |
89 | bool WithPragma = false; |
90 | |
91 | // Option starts to be available in this OpenCL version |
92 | unsigned Avail = 100U; |
93 | |
94 | // Option becomes core feature in this OpenCL versions |
95 | unsigned Core = 0U; |
96 | |
97 | // Option becomes optional core feature in this OpenCL versions |
98 | unsigned Opt = 0U; |
99 | |
100 | // Is this option supported |
101 | bool Supported = false; |
102 | |
103 | // Is this option enabled |
104 | bool Enabled = false; |
105 | |
106 | OpenCLOptionInfo() = default; |
107 | OpenCLOptionInfo(bool Pragma, unsigned AvailV, unsigned CoreV, |
108 | unsigned OptV) |
109 | : WithPragma(Pragma), Avail(AvailV), Core(CoreV), Opt(OptV) {} |
110 | |
111 | bool isCore() const { return Core != 0U; } |
112 | |
113 | bool isOptionalCore() const { return Opt != 0U; } |
114 | |
115 | // Is option available in OpenCL version \p LO. |
116 | bool isAvailableIn(const LangOptions &LO) const { |
117 | // In C++ mode all extensions should work at least as in v2.0. |
118 | return LO.getOpenCLCompatibleVersion() >= Avail; |
119 | } |
120 | |
121 | // Is core option in OpenCL version \p LO. |
122 | bool isCoreIn(const LangOptions &LO) const { |
123 | return isAvailableIn(LO) && isOpenCLVersionContainedInMask(LO, Mask: Core); |
124 | } |
125 | |
126 | // Is optional core option in OpenCL version \p LO. |
127 | bool isOptionalCoreIn(const LangOptions &LO) const { |
128 | return isAvailableIn(LO) && isOpenCLVersionContainedInMask(LO, Mask: Opt); |
129 | } |
130 | }; |
131 | |
132 | bool isKnown(llvm::StringRef Ext) const; |
133 | |
134 | // For core or optional core feature check that it is supported |
135 | // by a target, for any other option (extension) check that it is |
136 | // enabled via pragma |
137 | bool isAvailableOption(llvm::StringRef Ext, const LangOptions &LO) const; |
138 | |
139 | bool isWithPragma(llvm::StringRef Ext) const; |
140 | |
141 | // Is supported as either an extension or an (optional) core feature for |
142 | // OpenCL version \p LO. |
143 | bool isSupported(llvm::StringRef Ext, const LangOptions &LO) const; |
144 | |
145 | // Is supported OpenCL core feature for OpenCL version \p LO. |
146 | // For supported extension, return false. |
147 | bool isSupportedCore(llvm::StringRef Ext, const LangOptions &LO) const; |
148 | |
149 | // Is supported optional core OpenCL feature for OpenCL version \p LO. |
150 | // For supported extension, return false. |
151 | bool isSupportedOptionalCore(llvm::StringRef Ext, |
152 | const LangOptions &LO) const; |
153 | |
154 | // Is supported optional core or core OpenCL feature for OpenCL version \p |
155 | // LO. For supported extension, return false. |
156 | bool isSupportedCoreOrOptionalCore(llvm::StringRef Ext, |
157 | const LangOptions &LO) const; |
158 | |
159 | // Is supported OpenCL extension for OpenCL version \p LO. |
160 | // For supported core or optional core feature, return false. |
161 | bool isSupportedExtension(llvm::StringRef Ext, const LangOptions &LO) const; |
162 | |
163 | // FIXME: Whether extension should accept pragma should not |
164 | // be reset dynamically. But it currently required when |
165 | // registering new extensions via pragmas. |
166 | void acceptsPragma(llvm::StringRef Ext, bool V = true); |
167 | |
168 | void enable(llvm::StringRef Ext, bool V = true); |
169 | |
170 | /// Enable or disable support for OpenCL extensions |
171 | /// \param Ext name of the extension (not prefixed with '+' or '-') |
172 | /// \param V value to set for a extension |
173 | void support(llvm::StringRef Ext, bool V = true); |
174 | |
175 | OpenCLOptions(); |
176 | |
177 | // Set supported options based on target settings and language version |
178 | void addSupport(const llvm::StringMap<bool> &FeaturesMap, |
179 | const LangOptions &Opts); |
180 | |
181 | // Disable all extensions |
182 | void disableAll(); |
183 | |
184 | friend class ASTWriter; |
185 | friend class ASTReader; |
186 | |
187 | using OpenCLOptionInfoMap = llvm::StringMap<OpenCLOptionInfo>; |
188 | |
189 | template <typename... Args> |
190 | static bool isOpenCLOptionCoreIn(const LangOptions &LO, Args &&... args) { |
191 | return OpenCLOptionInfo(std::forward<Args>(args)...).isCoreIn(LO); |
192 | } |
193 | |
194 | template <typename... Args> |
195 | static bool isOpenCLOptionAvailableIn(const LangOptions &LO, |
196 | Args &&... args) { |
197 | return OpenCLOptionInfo(std::forward<Args>(args)...).isAvailableIn(LO); |
198 | } |
199 | |
200 | // Diagnose feature dependencies for OpenCL C 3.0. Return false if target |
201 | // doesn't follow these requirements. |
202 | static bool diagnoseUnsupportedFeatureDependencies(const TargetInfo &TI, |
203 | DiagnosticsEngine &Diags); |
204 | |
205 | // Diagnose that features and equivalent extension are set to same values. |
206 | // Return false if target doesn't follow these requirements. |
207 | static bool diagnoseFeatureExtensionDifferences(const TargetInfo &TI, |
208 | DiagnosticsEngine &Diags); |
209 | |
210 | private: |
211 | // Option is enabled via pragma |
212 | bool isEnabled(llvm::StringRef Ext) const; |
213 | |
214 | OpenCLOptionInfoMap OptMap; |
215 | }; |
216 | |
217 | } // end namespace clang |
218 | |
219 | #endif |
220 | |