xref: /src/contrib/llvm-project/clang/lib/Basic/OpenCLOptions.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
1b60736ecSDimitry Andric //===--- OpenCLOptions.cpp---------------------------------------*- C++ -*-===//
2b60736ecSDimitry Andric //
3b60736ecSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4b60736ecSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5b60736ecSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6b60736ecSDimitry Andric //
7b60736ecSDimitry Andric //===----------------------------------------------------------------------===//
8b60736ecSDimitry Andric 
9b60736ecSDimitry Andric #include "clang/Basic/OpenCLOptions.h"
10344a3780SDimitry Andric #include "clang/Basic/Diagnostic.h"
11344a3780SDimitry Andric #include "clang/Basic/TargetInfo.h"
12b60736ecSDimitry Andric 
13b60736ecSDimitry Andric namespace clang {
14b60736ecSDimitry Andric 
15145449b1SDimitry Andric // First feature in a pair requires the second one to be supported.
16145449b1SDimitry Andric static const std::pair<StringRef, StringRef> DependentFeaturesList[] = {
176f8fc217SDimitry Andric     {"__opencl_c_read_write_images", "__opencl_c_images"},
186f8fc217SDimitry Andric     {"__opencl_c_3d_image_writes", "__opencl_c_images"},
196f8fc217SDimitry Andric     {"__opencl_c_pipes", "__opencl_c_generic_address_space"},
206f8fc217SDimitry Andric     {"__opencl_c_device_enqueue", "__opencl_c_generic_address_space"},
216f8fc217SDimitry Andric     {"__opencl_c_device_enqueue", "__opencl_c_program_scope_global_variables"}};
226f8fc217SDimitry Andric 
23145449b1SDimitry Andric // Extensions and equivalent feature pairs.
24145449b1SDimitry Andric static const std::pair<StringRef, StringRef> FeatureExtensionMap[] = {
256f8fc217SDimitry Andric     {"cl_khr_fp64", "__opencl_c_fp64"},
266f8fc217SDimitry Andric     {"cl_khr_3d_image_writes", "__opencl_c_3d_image_writes"}};
276f8fc217SDimitry Andric 
isKnown(llvm::StringRef Ext) const28b60736ecSDimitry Andric bool OpenCLOptions::isKnown(llvm::StringRef Ext) const {
297fa27ce4SDimitry Andric   return OptMap.contains(Ext);
30b60736ecSDimitry Andric }
31b60736ecSDimitry Andric 
isAvailableOption(llvm::StringRef Ext,const LangOptions & LO) const32344a3780SDimitry Andric bool OpenCLOptions::isAvailableOption(llvm::StringRef Ext,
33344a3780SDimitry Andric                                       const LangOptions &LO) const {
34344a3780SDimitry Andric   if (!isKnown(Ext))
35344a3780SDimitry Andric     return false;
36344a3780SDimitry Andric 
37344a3780SDimitry Andric   auto &OptInfo = OptMap.find(Ext)->getValue();
38344a3780SDimitry Andric   if (OptInfo.isCoreIn(LO) || OptInfo.isOptionalCoreIn(LO))
39344a3780SDimitry Andric     return isSupported(Ext, LO);
40344a3780SDimitry Andric 
41344a3780SDimitry Andric   return isEnabled(Ext);
42344a3780SDimitry Andric }
43344a3780SDimitry Andric 
isEnabled(llvm::StringRef Ext) const44b60736ecSDimitry Andric bool OpenCLOptions::isEnabled(llvm::StringRef Ext) const {
45344a3780SDimitry Andric   auto I = OptMap.find(Ext);
46344a3780SDimitry Andric   return I != OptMap.end() && I->getValue().Enabled;
47344a3780SDimitry Andric }
48344a3780SDimitry Andric 
isWithPragma(llvm::StringRef Ext) const49344a3780SDimitry Andric bool OpenCLOptions::isWithPragma(llvm::StringRef Ext) const {
50b60736ecSDimitry Andric   auto E = OptMap.find(Ext);
51344a3780SDimitry Andric   return E != OptMap.end() && E->second.WithPragma;
52b60736ecSDimitry Andric }
53b60736ecSDimitry Andric 
isSupported(llvm::StringRef Ext,const LangOptions & LO) const54b60736ecSDimitry Andric bool OpenCLOptions::isSupported(llvm::StringRef Ext,
55b60736ecSDimitry Andric                                 const LangOptions &LO) const {
56344a3780SDimitry Andric   auto I = OptMap.find(Ext);
57344a3780SDimitry Andric   return I != OptMap.end() && I->getValue().Supported &&
58344a3780SDimitry Andric          I->getValue().isAvailableIn(LO);
59b60736ecSDimitry Andric }
60b60736ecSDimitry Andric 
isSupportedCore(llvm::StringRef Ext,const LangOptions & LO) const61b60736ecSDimitry Andric bool OpenCLOptions::isSupportedCore(llvm::StringRef Ext,
62b60736ecSDimitry Andric                                     const LangOptions &LO) const {
63344a3780SDimitry Andric   auto I = OptMap.find(Ext);
64344a3780SDimitry Andric   return I != OptMap.end() && I->getValue().Supported &&
65344a3780SDimitry Andric          I->getValue().isCoreIn(LO);
66b60736ecSDimitry Andric }
67b60736ecSDimitry Andric 
isSupportedOptionalCore(llvm::StringRef Ext,const LangOptions & LO) const68b60736ecSDimitry Andric bool OpenCLOptions::isSupportedOptionalCore(llvm::StringRef Ext,
69b60736ecSDimitry Andric                                             const LangOptions &LO) const {
70344a3780SDimitry Andric   auto I = OptMap.find(Ext);
71344a3780SDimitry Andric   return I != OptMap.end() && I->getValue().Supported &&
72344a3780SDimitry Andric          I->getValue().isOptionalCoreIn(LO);
73b60736ecSDimitry Andric }
74b60736ecSDimitry Andric 
isSupportedCoreOrOptionalCore(llvm::StringRef Ext,const LangOptions & LO) const75b60736ecSDimitry Andric bool OpenCLOptions::isSupportedCoreOrOptionalCore(llvm::StringRef Ext,
76b60736ecSDimitry Andric                                                   const LangOptions &LO) const {
77b60736ecSDimitry Andric   return isSupportedCore(Ext, LO) || isSupportedOptionalCore(Ext, LO);
78b60736ecSDimitry Andric }
79b60736ecSDimitry Andric 
isSupportedExtension(llvm::StringRef Ext,const LangOptions & LO) const80b60736ecSDimitry Andric bool OpenCLOptions::isSupportedExtension(llvm::StringRef Ext,
81b60736ecSDimitry Andric                                          const LangOptions &LO) const {
82344a3780SDimitry Andric   auto I = OptMap.find(Ext);
83344a3780SDimitry Andric   return I != OptMap.end() && I->getValue().Supported &&
84344a3780SDimitry Andric          I->getValue().isAvailableIn(LO) &&
85b60736ecSDimitry Andric          !isSupportedCoreOrOptionalCore(Ext, LO);
86b60736ecSDimitry Andric }
87b60736ecSDimitry Andric 
enable(llvm::StringRef Ext,bool V)88b60736ecSDimitry Andric void OpenCLOptions::enable(llvm::StringRef Ext, bool V) {
89b60736ecSDimitry Andric   OptMap[Ext].Enabled = V;
90b60736ecSDimitry Andric }
91b60736ecSDimitry Andric 
acceptsPragma(llvm::StringRef Ext,bool V)92344a3780SDimitry Andric void OpenCLOptions::acceptsPragma(llvm::StringRef Ext, bool V) {
93344a3780SDimitry Andric   OptMap[Ext].WithPragma = V;
94344a3780SDimitry Andric }
95344a3780SDimitry Andric 
support(llvm::StringRef Ext,bool V)96b60736ecSDimitry Andric void OpenCLOptions::support(llvm::StringRef Ext, bool V) {
97b60736ecSDimitry Andric   assert(!Ext.empty() && "Extension is empty.");
98b60736ecSDimitry Andric   assert(Ext[0] != '+' && Ext[0] != '-');
99b60736ecSDimitry Andric   OptMap[Ext].Supported = V;
100b60736ecSDimitry Andric }
101b60736ecSDimitry Andric 
OpenCLOptions()102b60736ecSDimitry Andric OpenCLOptions::OpenCLOptions() {
103344a3780SDimitry Andric #define OPENCL_GENERIC_EXTENSION(Ext, ...)                                     \
104344a3780SDimitry Andric   OptMap.insert_or_assign(#Ext, OpenCLOptionInfo{__VA_ARGS__});
105b60736ecSDimitry Andric #include "clang/Basic/OpenCLExtensions.def"
106b60736ecSDimitry Andric }
107b60736ecSDimitry Andric 
addSupport(const llvm::StringMap<bool> & FeaturesMap,const LangOptions & Opts)108b60736ecSDimitry Andric void OpenCLOptions::addSupport(const llvm::StringMap<bool> &FeaturesMap,
109b60736ecSDimitry Andric                                const LangOptions &Opts) {
110b60736ecSDimitry Andric   for (const auto &F : FeaturesMap) {
111b60736ecSDimitry Andric     const auto &Name = F.getKey();
112b60736ecSDimitry Andric     if (F.getValue() && isKnown(Name) && OptMap[Name].isAvailableIn(Opts))
113b60736ecSDimitry Andric       support(Name);
114b60736ecSDimitry Andric   }
115b60736ecSDimitry Andric }
116b60736ecSDimitry Andric 
disableAll()117b60736ecSDimitry Andric void OpenCLOptions::disableAll() {
118b60736ecSDimitry Andric   for (auto &Opt : OptMap)
119b60736ecSDimitry Andric     Opt.getValue().Enabled = false;
120b60736ecSDimitry Andric }
121b60736ecSDimitry Andric 
diagnoseUnsupportedFeatureDependencies(const TargetInfo & TI,DiagnosticsEngine & Diags)122344a3780SDimitry Andric bool OpenCLOptions::diagnoseUnsupportedFeatureDependencies(
123344a3780SDimitry Andric     const TargetInfo &TI, DiagnosticsEngine &Diags) {
124344a3780SDimitry Andric   auto OpenCLFeaturesMap = TI.getSupportedOpenCLOpts();
125344a3780SDimitry Andric 
126344a3780SDimitry Andric   bool IsValid = true;
1276f8fc217SDimitry Andric   for (auto &FeaturePair : DependentFeaturesList) {
1286f8fc217SDimitry Andric     auto Feature = FeaturePair.first;
1296f8fc217SDimitry Andric     auto Dep = FeaturePair.second;
1306f8fc217SDimitry Andric     if (TI.hasFeatureEnabled(OpenCLFeaturesMap, Feature) &&
1316f8fc217SDimitry Andric         !TI.hasFeatureEnabled(OpenCLFeaturesMap, Dep)) {
132344a3780SDimitry Andric       IsValid = false;
1336f8fc217SDimitry Andric       Diags.Report(diag::err_opencl_feature_requires) << Feature << Dep;
1346f8fc217SDimitry Andric     }
135344a3780SDimitry Andric   }
136344a3780SDimitry Andric   return IsValid;
137344a3780SDimitry Andric }
138344a3780SDimitry Andric 
diagnoseFeatureExtensionDifferences(const TargetInfo & TI,DiagnosticsEngine & Diags)139344a3780SDimitry Andric bool OpenCLOptions::diagnoseFeatureExtensionDifferences(
140344a3780SDimitry Andric     const TargetInfo &TI, DiagnosticsEngine &Diags) {
141344a3780SDimitry Andric   auto OpenCLFeaturesMap = TI.getSupportedOpenCLOpts();
142344a3780SDimitry Andric 
143344a3780SDimitry Andric   bool IsValid = true;
144344a3780SDimitry Andric   for (auto &ExtAndFeat : FeatureExtensionMap)
145145449b1SDimitry Andric     if (TI.hasFeatureEnabled(OpenCLFeaturesMap, ExtAndFeat.first) !=
146145449b1SDimitry Andric         TI.hasFeatureEnabled(OpenCLFeaturesMap, ExtAndFeat.second)) {
147344a3780SDimitry Andric       IsValid = false;
148344a3780SDimitry Andric       Diags.Report(diag::err_opencl_extension_and_feature_differs)
149145449b1SDimitry Andric           << ExtAndFeat.first << ExtAndFeat.second;
150344a3780SDimitry Andric     }
151344a3780SDimitry Andric   return IsValid;
152b60736ecSDimitry Andric }
153b60736ecSDimitry Andric 
154b60736ecSDimitry Andric } // end namespace clang
155