1e8d8bef9SDimitry Andric //===--- OpenCLOptions.cpp---------------------------------------*- C++ -*-===//
2e8d8bef9SDimitry Andric //
3e8d8bef9SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e8d8bef9SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e8d8bef9SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e8d8bef9SDimitry Andric //
7e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===//
8e8d8bef9SDimitry Andric 
9e8d8bef9SDimitry Andric #include "clang/Basic/OpenCLOptions.h"
10fe6060f1SDimitry Andric #include "clang/Basic/Diagnostic.h"
11fe6060f1SDimitry Andric #include "clang/Basic/TargetInfo.h"
12e8d8bef9SDimitry Andric 
13e8d8bef9SDimitry Andric namespace clang {
14e8d8bef9SDimitry Andric 
1581ad6265SDimitry Andric // First feature in a pair requires the second one to be supported.
1681ad6265SDimitry Andric static const std::pair<StringRef, StringRef> DependentFeaturesList[] = {
1704eeddc0SDimitry Andric     {"__opencl_c_read_write_images", "__opencl_c_images"},
1804eeddc0SDimitry Andric     {"__opencl_c_3d_image_writes", "__opencl_c_images"},
1904eeddc0SDimitry Andric     {"__opencl_c_pipes", "__opencl_c_generic_address_space"},
2004eeddc0SDimitry Andric     {"__opencl_c_device_enqueue", "__opencl_c_generic_address_space"},
2104eeddc0SDimitry Andric     {"__opencl_c_device_enqueue", "__opencl_c_program_scope_global_variables"}};
2204eeddc0SDimitry Andric 
2381ad6265SDimitry Andric // Extensions and equivalent feature pairs.
2481ad6265SDimitry Andric static const std::pair<StringRef, StringRef> FeatureExtensionMap[] = {
2504eeddc0SDimitry Andric     {"cl_khr_fp64", "__opencl_c_fp64"},
2604eeddc0SDimitry Andric     {"cl_khr_3d_image_writes", "__opencl_c_3d_image_writes"}};
2704eeddc0SDimitry Andric 
isKnown(llvm::StringRef Ext) const28e8d8bef9SDimitry Andric bool OpenCLOptions::isKnown(llvm::StringRef Ext) const {
29*06c3fb27SDimitry Andric   return OptMap.contains(Ext);
30e8d8bef9SDimitry Andric }
31e8d8bef9SDimitry Andric 
isAvailableOption(llvm::StringRef Ext,const LangOptions & LO) const32fe6060f1SDimitry Andric bool OpenCLOptions::isAvailableOption(llvm::StringRef Ext,
33fe6060f1SDimitry Andric                                       const LangOptions &LO) const {
34fe6060f1SDimitry Andric   if (!isKnown(Ext))
35fe6060f1SDimitry Andric     return false;
36fe6060f1SDimitry Andric 
37fe6060f1SDimitry Andric   auto &OptInfo = OptMap.find(Ext)->getValue();
38fe6060f1SDimitry Andric   if (OptInfo.isCoreIn(LO) || OptInfo.isOptionalCoreIn(LO))
39fe6060f1SDimitry Andric     return isSupported(Ext, LO);
40fe6060f1SDimitry Andric 
41fe6060f1SDimitry Andric   return isEnabled(Ext);
42fe6060f1SDimitry Andric }
43fe6060f1SDimitry Andric 
isEnabled(llvm::StringRef Ext) const44e8d8bef9SDimitry Andric bool OpenCLOptions::isEnabled(llvm::StringRef Ext) const {
45fe6060f1SDimitry Andric   auto I = OptMap.find(Ext);
46fe6060f1SDimitry Andric   return I != OptMap.end() && I->getValue().Enabled;
47fe6060f1SDimitry Andric }
48fe6060f1SDimitry Andric 
isWithPragma(llvm::StringRef Ext) const49fe6060f1SDimitry Andric bool OpenCLOptions::isWithPragma(llvm::StringRef Ext) const {
50e8d8bef9SDimitry Andric   auto E = OptMap.find(Ext);
51fe6060f1SDimitry Andric   return E != OptMap.end() && E->second.WithPragma;
52e8d8bef9SDimitry Andric }
53e8d8bef9SDimitry Andric 
isSupported(llvm::StringRef Ext,const LangOptions & LO) const54e8d8bef9SDimitry Andric bool OpenCLOptions::isSupported(llvm::StringRef Ext,
55e8d8bef9SDimitry Andric                                 const LangOptions &LO) const {
56fe6060f1SDimitry Andric   auto I = OptMap.find(Ext);
57fe6060f1SDimitry Andric   return I != OptMap.end() && I->getValue().Supported &&
58fe6060f1SDimitry Andric          I->getValue().isAvailableIn(LO);
59e8d8bef9SDimitry Andric }
60e8d8bef9SDimitry Andric 
isSupportedCore(llvm::StringRef Ext,const LangOptions & LO) const61e8d8bef9SDimitry Andric bool OpenCLOptions::isSupportedCore(llvm::StringRef Ext,
62e8d8bef9SDimitry Andric                                     const LangOptions &LO) const {
63fe6060f1SDimitry Andric   auto I = OptMap.find(Ext);
64fe6060f1SDimitry Andric   return I != OptMap.end() && I->getValue().Supported &&
65fe6060f1SDimitry Andric          I->getValue().isCoreIn(LO);
66e8d8bef9SDimitry Andric }
67e8d8bef9SDimitry Andric 
isSupportedOptionalCore(llvm::StringRef Ext,const LangOptions & LO) const68e8d8bef9SDimitry Andric bool OpenCLOptions::isSupportedOptionalCore(llvm::StringRef Ext,
69e8d8bef9SDimitry Andric                                             const LangOptions &LO) const {
70fe6060f1SDimitry Andric   auto I = OptMap.find(Ext);
71fe6060f1SDimitry Andric   return I != OptMap.end() && I->getValue().Supported &&
72fe6060f1SDimitry Andric          I->getValue().isOptionalCoreIn(LO);
73e8d8bef9SDimitry Andric }
74e8d8bef9SDimitry Andric 
isSupportedCoreOrOptionalCore(llvm::StringRef Ext,const LangOptions & LO) const75e8d8bef9SDimitry Andric bool OpenCLOptions::isSupportedCoreOrOptionalCore(llvm::StringRef Ext,
76e8d8bef9SDimitry Andric                                                   const LangOptions &LO) const {
77e8d8bef9SDimitry Andric   return isSupportedCore(Ext, LO) || isSupportedOptionalCore(Ext, LO);
78e8d8bef9SDimitry Andric }
79e8d8bef9SDimitry Andric 
isSupportedExtension(llvm::StringRef Ext,const LangOptions & LO) const80e8d8bef9SDimitry Andric bool OpenCLOptions::isSupportedExtension(llvm::StringRef Ext,
81e8d8bef9SDimitry Andric                                          const LangOptions &LO) const {
82fe6060f1SDimitry Andric   auto I = OptMap.find(Ext);
83fe6060f1SDimitry Andric   return I != OptMap.end() && I->getValue().Supported &&
84fe6060f1SDimitry Andric          I->getValue().isAvailableIn(LO) &&
85e8d8bef9SDimitry Andric          !isSupportedCoreOrOptionalCore(Ext, LO);
86e8d8bef9SDimitry Andric }
87e8d8bef9SDimitry Andric 
enable(llvm::StringRef Ext,bool V)88e8d8bef9SDimitry Andric void OpenCLOptions::enable(llvm::StringRef Ext, bool V) {
89e8d8bef9SDimitry Andric   OptMap[Ext].Enabled = V;
90e8d8bef9SDimitry Andric }
91e8d8bef9SDimitry Andric 
acceptsPragma(llvm::StringRef Ext,bool V)92fe6060f1SDimitry Andric void OpenCLOptions::acceptsPragma(llvm::StringRef Ext, bool V) {
93fe6060f1SDimitry Andric   OptMap[Ext].WithPragma = V;
94fe6060f1SDimitry Andric }
95fe6060f1SDimitry Andric 
support(llvm::StringRef Ext,bool V)96e8d8bef9SDimitry Andric void OpenCLOptions::support(llvm::StringRef Ext, bool V) {
97e8d8bef9SDimitry Andric   assert(!Ext.empty() && "Extension is empty.");
98e8d8bef9SDimitry Andric   assert(Ext[0] != '+' && Ext[0] != '-');
99e8d8bef9SDimitry Andric   OptMap[Ext].Supported = V;
100e8d8bef9SDimitry Andric }
101e8d8bef9SDimitry Andric 
OpenCLOptions()102e8d8bef9SDimitry Andric OpenCLOptions::OpenCLOptions() {
103fe6060f1SDimitry Andric #define OPENCL_GENERIC_EXTENSION(Ext, ...)                                     \
104fe6060f1SDimitry Andric   OptMap.insert_or_assign(#Ext, OpenCLOptionInfo{__VA_ARGS__});
105e8d8bef9SDimitry Andric #include "clang/Basic/OpenCLExtensions.def"
106e8d8bef9SDimitry Andric }
107e8d8bef9SDimitry Andric 
addSupport(const llvm::StringMap<bool> & FeaturesMap,const LangOptions & Opts)108e8d8bef9SDimitry Andric void OpenCLOptions::addSupport(const llvm::StringMap<bool> &FeaturesMap,
109e8d8bef9SDimitry Andric                                const LangOptions &Opts) {
110e8d8bef9SDimitry Andric   for (const auto &F : FeaturesMap) {
111e8d8bef9SDimitry Andric     const auto &Name = F.getKey();
112e8d8bef9SDimitry Andric     if (F.getValue() && isKnown(Name) && OptMap[Name].isAvailableIn(Opts))
113e8d8bef9SDimitry Andric       support(Name);
114e8d8bef9SDimitry Andric   }
115e8d8bef9SDimitry Andric }
116e8d8bef9SDimitry Andric 
disableAll()117e8d8bef9SDimitry Andric void OpenCLOptions::disableAll() {
118e8d8bef9SDimitry Andric   for (auto &Opt : OptMap)
119e8d8bef9SDimitry Andric     Opt.getValue().Enabled = false;
120e8d8bef9SDimitry Andric }
121e8d8bef9SDimitry Andric 
diagnoseUnsupportedFeatureDependencies(const TargetInfo & TI,DiagnosticsEngine & Diags)122fe6060f1SDimitry Andric bool OpenCLOptions::diagnoseUnsupportedFeatureDependencies(
123fe6060f1SDimitry Andric     const TargetInfo &TI, DiagnosticsEngine &Diags) {
124fe6060f1SDimitry Andric   auto OpenCLFeaturesMap = TI.getSupportedOpenCLOpts();
125fe6060f1SDimitry Andric 
126fe6060f1SDimitry Andric   bool IsValid = true;
12704eeddc0SDimitry Andric   for (auto &FeaturePair : DependentFeaturesList) {
12804eeddc0SDimitry Andric     auto Feature = FeaturePair.first;
12904eeddc0SDimitry Andric     auto Dep = FeaturePair.second;
13004eeddc0SDimitry Andric     if (TI.hasFeatureEnabled(OpenCLFeaturesMap, Feature) &&
13104eeddc0SDimitry Andric         !TI.hasFeatureEnabled(OpenCLFeaturesMap, Dep)) {
132fe6060f1SDimitry Andric       IsValid = false;
13304eeddc0SDimitry Andric       Diags.Report(diag::err_opencl_feature_requires) << Feature << Dep;
13404eeddc0SDimitry Andric     }
135fe6060f1SDimitry Andric   }
136fe6060f1SDimitry Andric   return IsValid;
137fe6060f1SDimitry Andric }
138fe6060f1SDimitry Andric 
diagnoseFeatureExtensionDifferences(const TargetInfo & TI,DiagnosticsEngine & Diags)139fe6060f1SDimitry Andric bool OpenCLOptions::diagnoseFeatureExtensionDifferences(
140fe6060f1SDimitry Andric     const TargetInfo &TI, DiagnosticsEngine &Diags) {
141fe6060f1SDimitry Andric   auto OpenCLFeaturesMap = TI.getSupportedOpenCLOpts();
142fe6060f1SDimitry Andric 
143fe6060f1SDimitry Andric   bool IsValid = true;
144fe6060f1SDimitry Andric   for (auto &ExtAndFeat : FeatureExtensionMap)
14581ad6265SDimitry Andric     if (TI.hasFeatureEnabled(OpenCLFeaturesMap, ExtAndFeat.first) !=
14681ad6265SDimitry Andric         TI.hasFeatureEnabled(OpenCLFeaturesMap, ExtAndFeat.second)) {
147fe6060f1SDimitry Andric       IsValid = false;
148fe6060f1SDimitry Andric       Diags.Report(diag::err_opencl_extension_and_feature_differs)
14981ad6265SDimitry Andric           << ExtAndFeat.first << ExtAndFeat.second;
150fe6060f1SDimitry Andric     }
151fe6060f1SDimitry Andric   return IsValid;
152e8d8bef9SDimitry Andric }
153e8d8bef9SDimitry Andric 
154e8d8bef9SDimitry Andric } // end namespace clang
155