1e123cd67SAnton Zabaznov //===--- OpenCLOptions.cpp---------------------------------------*- C++ -*-===//
2e123cd67SAnton Zabaznov //
3e123cd67SAnton Zabaznov // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e123cd67SAnton Zabaznov // See https://llvm.org/LICENSE.txt for license information.
5e123cd67SAnton Zabaznov // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e123cd67SAnton Zabaznov //
7e123cd67SAnton Zabaznov //===----------------------------------------------------------------------===//
8e123cd67SAnton Zabaznov
9e123cd67SAnton Zabaznov #include "clang/Basic/OpenCLOptions.h"
10ab76101fSAnton Zabaznov #include "clang/Basic/Diagnostic.h"
11ab76101fSAnton Zabaznov #include "clang/Basic/TargetInfo.h"
12e123cd67SAnton Zabaznov
13e123cd67SAnton Zabaznov namespace clang {
14e123cd67SAnton Zabaznov
1514af99d3SBenjamin Kramer // First feature in a pair requires the second one to be supported.
1614af99d3SBenjamin Kramer static const std::pair<StringRef, StringRef> DependentFeaturesList[] = {
17a5de66c4SAnton Zabaznov {"__opencl_c_read_write_images", "__opencl_c_images"},
18a5de66c4SAnton Zabaznov {"__opencl_c_3d_image_writes", "__opencl_c_images"},
19a5de66c4SAnton Zabaznov {"__opencl_c_pipes", "__opencl_c_generic_address_space"},
20a5de66c4SAnton Zabaznov {"__opencl_c_device_enqueue", "__opencl_c_generic_address_space"},
21a5de66c4SAnton Zabaznov {"__opencl_c_device_enqueue", "__opencl_c_program_scope_global_variables"}};
22a5de66c4SAnton Zabaznov
2314af99d3SBenjamin Kramer // Extensions and equivalent feature pairs.
2414af99d3SBenjamin Kramer static const std::pair<StringRef, StringRef> FeatureExtensionMap[] = {
25a5de66c4SAnton Zabaznov {"cl_khr_fp64", "__opencl_c_fp64"},
26a5de66c4SAnton Zabaznov {"cl_khr_3d_image_writes", "__opencl_c_3d_image_writes"}};
27a5de66c4SAnton Zabaznov
isKnown(llvm::StringRef Ext) const28e123cd67SAnton Zabaznov bool OpenCLOptions::isKnown(llvm::StringRef Ext) const {
29*ea9d4040SKazu Hirata return OptMap.contains(Ext);
30e123cd67SAnton Zabaznov }
31e123cd67SAnton Zabaznov
isAvailableOption(llvm::StringRef Ext,const LangOptions & LO) const32840643bbSAnton Zabaznov bool OpenCLOptions::isAvailableOption(llvm::StringRef Ext,
33840643bbSAnton Zabaznov const LangOptions &LO) const {
34840643bbSAnton Zabaznov if (!isKnown(Ext))
35840643bbSAnton Zabaznov return false;
36840643bbSAnton Zabaznov
37840643bbSAnton Zabaznov auto &OptInfo = OptMap.find(Ext)->getValue();
38840643bbSAnton Zabaznov if (OptInfo.isCoreIn(LO) || OptInfo.isOptionalCoreIn(LO))
39840643bbSAnton Zabaznov return isSupported(Ext, LO);
40840643bbSAnton Zabaznov
41840643bbSAnton Zabaznov return isEnabled(Ext);
42840643bbSAnton Zabaznov }
43840643bbSAnton Zabaznov
isEnabled(llvm::StringRef Ext) const44e123cd67SAnton Zabaznov bool OpenCLOptions::isEnabled(llvm::StringRef Ext) const {
45840643bbSAnton Zabaznov auto I = OptMap.find(Ext);
46840643bbSAnton Zabaznov return I != OptMap.end() && I->getValue().Enabled;
47e123cd67SAnton Zabaznov }
48e123cd67SAnton Zabaznov
isWithPragma(llvm::StringRef Ext) const4925ad188bSAnastasia Stulova bool OpenCLOptions::isWithPragma(llvm::StringRef Ext) const {
5025ad188bSAnastasia Stulova auto E = OptMap.find(Ext);
5125ad188bSAnastasia Stulova return E != OptMap.end() && E->second.WithPragma;
5225ad188bSAnastasia Stulova }
5325ad188bSAnastasia Stulova
isSupported(llvm::StringRef Ext,const LangOptions & LO) const54e123cd67SAnton Zabaznov bool OpenCLOptions::isSupported(llvm::StringRef Ext,
55e123cd67SAnton Zabaznov const LangOptions &LO) const {
56840643bbSAnton Zabaznov auto I = OptMap.find(Ext);
57840643bbSAnton Zabaznov return I != OptMap.end() && I->getValue().Supported &&
58840643bbSAnton Zabaznov I->getValue().isAvailableIn(LO);
59e123cd67SAnton Zabaznov }
60e123cd67SAnton Zabaznov
isSupportedCore(llvm::StringRef Ext,const LangOptions & LO) const61e123cd67SAnton Zabaznov bool OpenCLOptions::isSupportedCore(llvm::StringRef Ext,
62e123cd67SAnton Zabaznov const LangOptions &LO) const {
63840643bbSAnton Zabaznov auto I = OptMap.find(Ext);
64840643bbSAnton Zabaznov return I != OptMap.end() && I->getValue().Supported &&
65840643bbSAnton Zabaznov I->getValue().isCoreIn(LO);
66e123cd67SAnton Zabaznov }
67e123cd67SAnton Zabaznov
isSupportedOptionalCore(llvm::StringRef Ext,const LangOptions & LO) const68e123cd67SAnton Zabaznov bool OpenCLOptions::isSupportedOptionalCore(llvm::StringRef Ext,
69e123cd67SAnton Zabaznov const LangOptions &LO) const {
70840643bbSAnton Zabaznov auto I = OptMap.find(Ext);
71840643bbSAnton Zabaznov return I != OptMap.end() && I->getValue().Supported &&
72840643bbSAnton Zabaznov I->getValue().isOptionalCoreIn(LO);
73e123cd67SAnton Zabaznov }
74e123cd67SAnton Zabaznov
isSupportedCoreOrOptionalCore(llvm::StringRef Ext,const LangOptions & LO) const75e123cd67SAnton Zabaznov bool OpenCLOptions::isSupportedCoreOrOptionalCore(llvm::StringRef Ext,
76e123cd67SAnton Zabaznov const LangOptions &LO) const {
77e123cd67SAnton Zabaznov return isSupportedCore(Ext, LO) || isSupportedOptionalCore(Ext, LO);
78e123cd67SAnton Zabaznov }
79e123cd67SAnton Zabaznov
isSupportedExtension(llvm::StringRef Ext,const LangOptions & LO) const80e123cd67SAnton Zabaznov bool OpenCLOptions::isSupportedExtension(llvm::StringRef Ext,
81e123cd67SAnton Zabaznov const LangOptions &LO) const {
82840643bbSAnton Zabaznov auto I = OptMap.find(Ext);
83840643bbSAnton Zabaznov return I != OptMap.end() && I->getValue().Supported &&
84840643bbSAnton Zabaznov I->getValue().isAvailableIn(LO) &&
85e123cd67SAnton Zabaznov !isSupportedCoreOrOptionalCore(Ext, LO);
86e123cd67SAnton Zabaznov }
87e123cd67SAnton Zabaznov
enable(llvm::StringRef Ext,bool V)88e123cd67SAnton Zabaznov void OpenCLOptions::enable(llvm::StringRef Ext, bool V) {
89e123cd67SAnton Zabaznov OptMap[Ext].Enabled = V;
90e123cd67SAnton Zabaznov }
91e123cd67SAnton Zabaznov
acceptsPragma(llvm::StringRef Ext,bool V)9225ad188bSAnastasia Stulova void OpenCLOptions::acceptsPragma(llvm::StringRef Ext, bool V) {
9325ad188bSAnastasia Stulova OptMap[Ext].WithPragma = V;
9425ad188bSAnastasia Stulova }
9525ad188bSAnastasia Stulova
support(llvm::StringRef Ext,bool V)96e123cd67SAnton Zabaznov void OpenCLOptions::support(llvm::StringRef Ext, bool V) {
97e123cd67SAnton Zabaznov assert(!Ext.empty() && "Extension is empty.");
98e123cd67SAnton Zabaznov assert(Ext[0] != '+' && Ext[0] != '-');
99e123cd67SAnton Zabaznov OptMap[Ext].Supported = V;
100e123cd67SAnton Zabaznov }
101e123cd67SAnton Zabaznov
OpenCLOptions()102e123cd67SAnton Zabaznov OpenCLOptions::OpenCLOptions() {
103f0efc007SAnton Zabaznov #define OPENCL_GENERIC_EXTENSION(Ext, ...) \
104f0efc007SAnton Zabaznov OptMap.insert_or_assign(#Ext, OpenCLOptionInfo{__VA_ARGS__});
105e123cd67SAnton Zabaznov #include "clang/Basic/OpenCLExtensions.def"
106e123cd67SAnton Zabaznov }
107e123cd67SAnton Zabaznov
addSupport(const llvm::StringMap<bool> & FeaturesMap,const LangOptions & Opts)108e123cd67SAnton Zabaznov void OpenCLOptions::addSupport(const llvm::StringMap<bool> &FeaturesMap,
109e123cd67SAnton Zabaznov const LangOptions &Opts) {
110e123cd67SAnton Zabaznov for (const auto &F : FeaturesMap) {
111e123cd67SAnton Zabaznov const auto &Name = F.getKey();
112e123cd67SAnton Zabaznov if (F.getValue() && isKnown(Name) && OptMap[Name].isAvailableIn(Opts))
113e123cd67SAnton Zabaznov support(Name);
114e123cd67SAnton Zabaznov }
115e123cd67SAnton Zabaznov }
116e123cd67SAnton Zabaznov
disableAll()117e123cd67SAnton Zabaznov void OpenCLOptions::disableAll() {
118e123cd67SAnton Zabaznov for (auto &Opt : OptMap)
119e123cd67SAnton Zabaznov Opt.getValue().Enabled = false;
120e123cd67SAnton Zabaznov }
121e123cd67SAnton Zabaznov
diagnoseUnsupportedFeatureDependencies(const TargetInfo & TI,DiagnosticsEngine & Diags)122ab76101fSAnton Zabaznov bool OpenCLOptions::diagnoseUnsupportedFeatureDependencies(
123ab76101fSAnton Zabaznov const TargetInfo &TI, DiagnosticsEngine &Diags) {
124ab76101fSAnton Zabaznov auto OpenCLFeaturesMap = TI.getSupportedOpenCLOpts();
125ab76101fSAnton Zabaznov
126ab76101fSAnton Zabaznov bool IsValid = true;
127a5de66c4SAnton Zabaznov for (auto &FeaturePair : DependentFeaturesList) {
128a5de66c4SAnton Zabaznov auto Feature = FeaturePair.first;
129a5de66c4SAnton Zabaznov auto Dep = FeaturePair.second;
130a5de66c4SAnton Zabaznov if (TI.hasFeatureEnabled(OpenCLFeaturesMap, Feature) &&
131a5de66c4SAnton Zabaznov !TI.hasFeatureEnabled(OpenCLFeaturesMap, Dep)) {
132ab76101fSAnton Zabaznov IsValid = false;
133a5de66c4SAnton Zabaznov Diags.Report(diag::err_opencl_feature_requires) << Feature << Dep;
134a5de66c4SAnton Zabaznov }
135ab76101fSAnton Zabaznov }
136ab76101fSAnton Zabaznov return IsValid;
137ab76101fSAnton Zabaznov }
138ab76101fSAnton Zabaznov
diagnoseFeatureExtensionDifferences(const TargetInfo & TI,DiagnosticsEngine & Diags)139ab76101fSAnton Zabaznov bool OpenCLOptions::diagnoseFeatureExtensionDifferences(
140ab76101fSAnton Zabaznov const TargetInfo &TI, DiagnosticsEngine &Diags) {
141ab76101fSAnton Zabaznov auto OpenCLFeaturesMap = TI.getSupportedOpenCLOpts();
142ab76101fSAnton Zabaznov
143ab76101fSAnton Zabaznov bool IsValid = true;
144ab76101fSAnton Zabaznov for (auto &ExtAndFeat : FeatureExtensionMap)
14514af99d3SBenjamin Kramer if (TI.hasFeatureEnabled(OpenCLFeaturesMap, ExtAndFeat.first) !=
14614af99d3SBenjamin Kramer TI.hasFeatureEnabled(OpenCLFeaturesMap, ExtAndFeat.second)) {
147ab76101fSAnton Zabaznov IsValid = false;
148ab76101fSAnton Zabaznov Diags.Report(diag::err_opencl_extension_and_feature_differs)
14914af99d3SBenjamin Kramer << ExtAndFeat.first << ExtAndFeat.second;
150ab76101fSAnton Zabaznov }
151ab76101fSAnton Zabaznov return IsValid;
152ab76101fSAnton Zabaznov }
153ab76101fSAnton Zabaznov
154e123cd67SAnton Zabaznov } // end namespace clang
155