1 //===--- OpenCLOptions.cpp---------------------------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 #include "clang/Basic/OpenCLOptions.h"
10 #include "clang/Basic/Diagnostic.h"
11 #include "clang/Basic/TargetInfo.h"
15 // First feature in a pair requires the second one to be supported.
16 static const std::pair
<StringRef
, StringRef
> DependentFeaturesList
[] = {
17 {"__opencl_c_read_write_images", "__opencl_c_images"},
18 {"__opencl_c_3d_image_writes", "__opencl_c_images"},
19 {"__opencl_c_pipes", "__opencl_c_generic_address_space"},
20 {"__opencl_c_device_enqueue", "__opencl_c_generic_address_space"},
21 {"__opencl_c_device_enqueue", "__opencl_c_program_scope_global_variables"}};
23 // Extensions and equivalent feature pairs.
24 static const std::pair
<StringRef
, StringRef
> FeatureExtensionMap
[] = {
25 {"cl_khr_fp64", "__opencl_c_fp64"},
26 {"cl_khr_3d_image_writes", "__opencl_c_3d_image_writes"}};
28 bool OpenCLOptions::isKnown(llvm::StringRef Ext
) const {
29 return OptMap
.contains(Ext
);
32 bool OpenCLOptions::isAvailableOption(llvm::StringRef Ext
,
33 const LangOptions
&LO
) const {
37 auto &OptInfo
= OptMap
.find(Ext
)->getValue();
38 if (OptInfo
.isCoreIn(LO
) || OptInfo
.isOptionalCoreIn(LO
))
39 return isSupported(Ext
, LO
);
41 return isEnabled(Ext
);
44 bool OpenCLOptions::isEnabled(llvm::StringRef Ext
) const {
45 auto I
= OptMap
.find(Ext
);
46 return I
!= OptMap
.end() && I
->getValue().Enabled
;
49 bool OpenCLOptions::isWithPragma(llvm::StringRef Ext
) const {
50 auto E
= OptMap
.find(Ext
);
51 return E
!= OptMap
.end() && E
->second
.WithPragma
;
54 bool OpenCLOptions::isSupported(llvm::StringRef Ext
,
55 const LangOptions
&LO
) const {
56 auto I
= OptMap
.find(Ext
);
57 return I
!= OptMap
.end() && I
->getValue().Supported
&&
58 I
->getValue().isAvailableIn(LO
);
61 bool OpenCLOptions::isSupportedCore(llvm::StringRef Ext
,
62 const LangOptions
&LO
) const {
63 auto I
= OptMap
.find(Ext
);
64 return I
!= OptMap
.end() && I
->getValue().Supported
&&
65 I
->getValue().isCoreIn(LO
);
68 bool OpenCLOptions::isSupportedOptionalCore(llvm::StringRef Ext
,
69 const LangOptions
&LO
) const {
70 auto I
= OptMap
.find(Ext
);
71 return I
!= OptMap
.end() && I
->getValue().Supported
&&
72 I
->getValue().isOptionalCoreIn(LO
);
75 bool OpenCLOptions::isSupportedCoreOrOptionalCore(llvm::StringRef Ext
,
76 const LangOptions
&LO
) const {
77 return isSupportedCore(Ext
, LO
) || isSupportedOptionalCore(Ext
, LO
);
80 bool OpenCLOptions::isSupportedExtension(llvm::StringRef Ext
,
81 const LangOptions
&LO
) const {
82 auto I
= OptMap
.find(Ext
);
83 return I
!= OptMap
.end() && I
->getValue().Supported
&&
84 I
->getValue().isAvailableIn(LO
) &&
85 !isSupportedCoreOrOptionalCore(Ext
, LO
);
88 void OpenCLOptions::enable(llvm::StringRef Ext
, bool V
) {
89 OptMap
[Ext
].Enabled
= V
;
92 void OpenCLOptions::acceptsPragma(llvm::StringRef Ext
, bool V
) {
93 OptMap
[Ext
].WithPragma
= V
;
96 void OpenCLOptions::support(llvm::StringRef Ext
, bool V
) {
97 assert(!Ext
.empty() && "Extension is empty.");
98 assert(Ext
[0] != '+' && Ext
[0] != '-');
99 OptMap
[Ext
].Supported
= V
;
102 OpenCLOptions::OpenCLOptions() {
103 #define OPENCL_GENERIC_EXTENSION(Ext, ...) \
104 OptMap.insert_or_assign(#Ext, OpenCLOptionInfo{__VA_ARGS__});
105 #include "clang/Basic/OpenCLExtensions.def"
108 void OpenCLOptions::addSupport(const llvm::StringMap
<bool> &FeaturesMap
,
109 const LangOptions
&Opts
) {
110 for (const auto &F
: FeaturesMap
) {
111 const auto &Name
= F
.getKey();
112 if (F
.getValue() && isKnown(Name
) && OptMap
[Name
].isAvailableIn(Opts
))
117 void OpenCLOptions::disableAll() {
118 for (auto &Opt
: OptMap
)
119 Opt
.getValue().Enabled
= false;
122 bool OpenCLOptions::diagnoseUnsupportedFeatureDependencies(
123 const TargetInfo
&TI
, DiagnosticsEngine
&Diags
) {
124 auto OpenCLFeaturesMap
= TI
.getSupportedOpenCLOpts();
127 for (auto &FeaturePair
: DependentFeaturesList
) {
128 auto Feature
= FeaturePair
.first
;
129 auto Dep
= FeaturePair
.second
;
130 if (TI
.hasFeatureEnabled(OpenCLFeaturesMap
, Feature
) &&
131 !TI
.hasFeatureEnabled(OpenCLFeaturesMap
, Dep
)) {
133 Diags
.Report(diag::err_opencl_feature_requires
) << Feature
<< Dep
;
139 bool OpenCLOptions::diagnoseFeatureExtensionDifferences(
140 const TargetInfo
&TI
, DiagnosticsEngine
&Diags
) {
141 auto OpenCLFeaturesMap
= TI
.getSupportedOpenCLOpts();
144 for (auto &ExtAndFeat
: FeatureExtensionMap
)
145 if (TI
.hasFeatureEnabled(OpenCLFeaturesMap
, ExtAndFeat
.first
) !=
146 TI
.hasFeatureEnabled(OpenCLFeaturesMap
, ExtAndFeat
.second
)) {
148 Diags
.Report(diag::err_opencl_extension_and_feature_differs
)
149 << ExtAndFeat
.first
<< ExtAndFeat
.second
;
154 } // end namespace clang