xref: /freebsd-src/contrib/llvm-project/clang/lib/Basic/OpenCLOptions.cpp (revision fe6060f10f634930ff71b7c50291ddc610da2475)
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"
10*fe6060f1SDimitry Andric #include "clang/Basic/Diagnostic.h"
11*fe6060f1SDimitry Andric #include "clang/Basic/TargetInfo.h"
12e8d8bef9SDimitry Andric 
13e8d8bef9SDimitry Andric namespace clang {
14e8d8bef9SDimitry Andric 
15e8d8bef9SDimitry Andric bool OpenCLOptions::isKnown(llvm::StringRef Ext) const {
16e8d8bef9SDimitry Andric   return OptMap.find(Ext) != OptMap.end();
17e8d8bef9SDimitry Andric }
18e8d8bef9SDimitry Andric 
19*fe6060f1SDimitry Andric bool OpenCLOptions::isAvailableOption(llvm::StringRef Ext,
20*fe6060f1SDimitry Andric                                       const LangOptions &LO) const {
21*fe6060f1SDimitry Andric   if (!isKnown(Ext))
22*fe6060f1SDimitry Andric     return false;
23*fe6060f1SDimitry Andric 
24*fe6060f1SDimitry Andric   auto &OptInfo = OptMap.find(Ext)->getValue();
25*fe6060f1SDimitry Andric   if (OptInfo.isCoreIn(LO) || OptInfo.isOptionalCoreIn(LO))
26*fe6060f1SDimitry Andric     return isSupported(Ext, LO);
27*fe6060f1SDimitry Andric 
28*fe6060f1SDimitry Andric   return isEnabled(Ext);
29*fe6060f1SDimitry Andric }
30*fe6060f1SDimitry Andric 
31e8d8bef9SDimitry Andric bool OpenCLOptions::isEnabled(llvm::StringRef Ext) const {
32*fe6060f1SDimitry Andric   auto I = OptMap.find(Ext);
33*fe6060f1SDimitry Andric   return I != OptMap.end() && I->getValue().Enabled;
34*fe6060f1SDimitry Andric }
35*fe6060f1SDimitry Andric 
36*fe6060f1SDimitry Andric bool OpenCLOptions::isWithPragma(llvm::StringRef Ext) const {
37e8d8bef9SDimitry Andric   auto E = OptMap.find(Ext);
38*fe6060f1SDimitry Andric   return E != OptMap.end() && E->second.WithPragma;
39e8d8bef9SDimitry Andric }
40e8d8bef9SDimitry Andric 
41e8d8bef9SDimitry Andric bool OpenCLOptions::isSupported(llvm::StringRef Ext,
42e8d8bef9SDimitry Andric                                 const LangOptions &LO) const {
43*fe6060f1SDimitry Andric   auto I = OptMap.find(Ext);
44*fe6060f1SDimitry Andric   return I != OptMap.end() && I->getValue().Supported &&
45*fe6060f1SDimitry Andric          I->getValue().isAvailableIn(LO);
46e8d8bef9SDimitry Andric }
47e8d8bef9SDimitry Andric 
48e8d8bef9SDimitry Andric bool OpenCLOptions::isSupportedCore(llvm::StringRef Ext,
49e8d8bef9SDimitry Andric                                     const LangOptions &LO) const {
50*fe6060f1SDimitry Andric   auto I = OptMap.find(Ext);
51*fe6060f1SDimitry Andric   return I != OptMap.end() && I->getValue().Supported &&
52*fe6060f1SDimitry Andric          I->getValue().isCoreIn(LO);
53e8d8bef9SDimitry Andric }
54e8d8bef9SDimitry Andric 
55e8d8bef9SDimitry Andric bool OpenCLOptions::isSupportedOptionalCore(llvm::StringRef Ext,
56e8d8bef9SDimitry Andric                                             const LangOptions &LO) const {
57*fe6060f1SDimitry Andric   auto I = OptMap.find(Ext);
58*fe6060f1SDimitry Andric   return I != OptMap.end() && I->getValue().Supported &&
59*fe6060f1SDimitry Andric          I->getValue().isOptionalCoreIn(LO);
60e8d8bef9SDimitry Andric }
61e8d8bef9SDimitry Andric 
62e8d8bef9SDimitry Andric bool OpenCLOptions::isSupportedCoreOrOptionalCore(llvm::StringRef Ext,
63e8d8bef9SDimitry Andric                                                   const LangOptions &LO) const {
64e8d8bef9SDimitry Andric   return isSupportedCore(Ext, LO) || isSupportedOptionalCore(Ext, LO);
65e8d8bef9SDimitry Andric }
66e8d8bef9SDimitry Andric 
67e8d8bef9SDimitry Andric bool OpenCLOptions::isSupportedExtension(llvm::StringRef Ext,
68e8d8bef9SDimitry Andric                                          const LangOptions &LO) const {
69*fe6060f1SDimitry Andric   auto I = OptMap.find(Ext);
70*fe6060f1SDimitry Andric   return I != OptMap.end() && I->getValue().Supported &&
71*fe6060f1SDimitry Andric          I->getValue().isAvailableIn(LO) &&
72e8d8bef9SDimitry Andric          !isSupportedCoreOrOptionalCore(Ext, LO);
73e8d8bef9SDimitry Andric }
74e8d8bef9SDimitry Andric 
75e8d8bef9SDimitry Andric void OpenCLOptions::enable(llvm::StringRef Ext, bool V) {
76e8d8bef9SDimitry Andric   OptMap[Ext].Enabled = V;
77e8d8bef9SDimitry Andric }
78e8d8bef9SDimitry Andric 
79*fe6060f1SDimitry Andric void OpenCLOptions::acceptsPragma(llvm::StringRef Ext, bool V) {
80*fe6060f1SDimitry Andric   OptMap[Ext].WithPragma = V;
81*fe6060f1SDimitry Andric }
82*fe6060f1SDimitry Andric 
83e8d8bef9SDimitry Andric void OpenCLOptions::support(llvm::StringRef Ext, bool V) {
84e8d8bef9SDimitry Andric   assert(!Ext.empty() && "Extension is empty.");
85e8d8bef9SDimitry Andric   assert(Ext[0] != '+' && Ext[0] != '-');
86e8d8bef9SDimitry Andric   OptMap[Ext].Supported = V;
87e8d8bef9SDimitry Andric }
88e8d8bef9SDimitry Andric 
89e8d8bef9SDimitry Andric OpenCLOptions::OpenCLOptions() {
90*fe6060f1SDimitry Andric #define OPENCL_GENERIC_EXTENSION(Ext, ...)                                     \
91*fe6060f1SDimitry Andric   OptMap.insert_or_assign(#Ext, OpenCLOptionInfo{__VA_ARGS__});
92e8d8bef9SDimitry Andric #include "clang/Basic/OpenCLExtensions.def"
93e8d8bef9SDimitry Andric }
94e8d8bef9SDimitry Andric 
95e8d8bef9SDimitry Andric void OpenCLOptions::addSupport(const llvm::StringMap<bool> &FeaturesMap,
96e8d8bef9SDimitry Andric                                const LangOptions &Opts) {
97e8d8bef9SDimitry Andric   for (const auto &F : FeaturesMap) {
98e8d8bef9SDimitry Andric     const auto &Name = F.getKey();
99e8d8bef9SDimitry Andric     if (F.getValue() && isKnown(Name) && OptMap[Name].isAvailableIn(Opts))
100e8d8bef9SDimitry Andric       support(Name);
101e8d8bef9SDimitry Andric   }
102e8d8bef9SDimitry Andric }
103e8d8bef9SDimitry Andric 
104e8d8bef9SDimitry Andric void OpenCLOptions::disableAll() {
105e8d8bef9SDimitry Andric   for (auto &Opt : OptMap)
106e8d8bef9SDimitry Andric     Opt.getValue().Enabled = false;
107e8d8bef9SDimitry Andric }
108e8d8bef9SDimitry Andric 
109*fe6060f1SDimitry Andric bool OpenCLOptions::diagnoseUnsupportedFeatureDependencies(
110*fe6060f1SDimitry Andric     const TargetInfo &TI, DiagnosticsEngine &Diags) {
111*fe6060f1SDimitry Andric   // Feature pairs. First feature in a pair requires the second one to be
112*fe6060f1SDimitry Andric   // supported.
113*fe6060f1SDimitry Andric   static const llvm::StringMap<llvm::StringRef> DependentFeaturesMap = {
114*fe6060f1SDimitry Andric       {"__opencl_c_read_write_images", "__opencl_c_images"}};
115*fe6060f1SDimitry Andric 
116*fe6060f1SDimitry Andric   auto OpenCLFeaturesMap = TI.getSupportedOpenCLOpts();
117*fe6060f1SDimitry Andric 
118*fe6060f1SDimitry Andric   bool IsValid = true;
119*fe6060f1SDimitry Andric   for (auto &FeaturePair : DependentFeaturesMap)
120*fe6060f1SDimitry Andric     if (TI.hasFeatureEnabled(OpenCLFeaturesMap, FeaturePair.getKey()) &&
121*fe6060f1SDimitry Andric         !TI.hasFeatureEnabled(OpenCLFeaturesMap, FeaturePair.getValue())) {
122*fe6060f1SDimitry Andric       IsValid = false;
123*fe6060f1SDimitry Andric       Diags.Report(diag::err_opencl_feature_requires)
124*fe6060f1SDimitry Andric           << FeaturePair.getKey() << FeaturePair.getValue();
125*fe6060f1SDimitry Andric     }
126*fe6060f1SDimitry Andric   return IsValid;
127*fe6060f1SDimitry Andric }
128*fe6060f1SDimitry Andric 
129*fe6060f1SDimitry Andric bool OpenCLOptions::diagnoseFeatureExtensionDifferences(
130*fe6060f1SDimitry Andric     const TargetInfo &TI, DiagnosticsEngine &Diags) {
131*fe6060f1SDimitry Andric   // Extensions and equivalent feature pairs.
132*fe6060f1SDimitry Andric   static const llvm::StringMap<llvm::StringRef> FeatureExtensionMap = {
133*fe6060f1SDimitry Andric       {"cl_khr_fp64", "__opencl_c_fp64"}};
134*fe6060f1SDimitry Andric 
135*fe6060f1SDimitry Andric   auto OpenCLFeaturesMap = TI.getSupportedOpenCLOpts();
136*fe6060f1SDimitry Andric 
137*fe6060f1SDimitry Andric   bool IsValid = true;
138*fe6060f1SDimitry Andric   for (auto &ExtAndFeat : FeatureExtensionMap)
139*fe6060f1SDimitry Andric     if (TI.hasFeatureEnabled(OpenCLFeaturesMap, ExtAndFeat.getKey()) !=
140*fe6060f1SDimitry Andric         TI.hasFeatureEnabled(OpenCLFeaturesMap, ExtAndFeat.getValue())) {
141*fe6060f1SDimitry Andric       IsValid = false;
142*fe6060f1SDimitry Andric       Diags.Report(diag::err_opencl_extension_and_feature_differs)
143*fe6060f1SDimitry Andric           << ExtAndFeat.getKey() << ExtAndFeat.getValue();
144*fe6060f1SDimitry Andric     }
145*fe6060f1SDimitry Andric   return IsValid;
146e8d8bef9SDimitry Andric }
147e8d8bef9SDimitry Andric 
148e8d8bef9SDimitry Andric } // end namespace clang
149