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