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