1b60736ecSDimitry Andric //===--- OpenCLOptions.cpp---------------------------------------*- C++ -*-===//
2b60736ecSDimitry Andric //
3b60736ecSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4b60736ecSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5b60736ecSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6b60736ecSDimitry Andric //
7b60736ecSDimitry Andric //===----------------------------------------------------------------------===//
8b60736ecSDimitry Andric
9b60736ecSDimitry Andric #include "clang/Basic/OpenCLOptions.h"
10344a3780SDimitry Andric #include "clang/Basic/Diagnostic.h"
11344a3780SDimitry Andric #include "clang/Basic/TargetInfo.h"
12b60736ecSDimitry Andric
13b60736ecSDimitry Andric namespace clang {
14b60736ecSDimitry Andric
15145449b1SDimitry Andric // First feature in a pair requires the second one to be supported.
16145449b1SDimitry Andric static const std::pair<StringRef, StringRef> DependentFeaturesList[] = {
176f8fc217SDimitry Andric {"__opencl_c_read_write_images", "__opencl_c_images"},
186f8fc217SDimitry Andric {"__opencl_c_3d_image_writes", "__opencl_c_images"},
196f8fc217SDimitry Andric {"__opencl_c_pipes", "__opencl_c_generic_address_space"},
206f8fc217SDimitry Andric {"__opencl_c_device_enqueue", "__opencl_c_generic_address_space"},
216f8fc217SDimitry Andric {"__opencl_c_device_enqueue", "__opencl_c_program_scope_global_variables"}};
226f8fc217SDimitry Andric
23145449b1SDimitry Andric // Extensions and equivalent feature pairs.
24145449b1SDimitry Andric static const std::pair<StringRef, StringRef> FeatureExtensionMap[] = {
256f8fc217SDimitry Andric {"cl_khr_fp64", "__opencl_c_fp64"},
266f8fc217SDimitry Andric {"cl_khr_3d_image_writes", "__opencl_c_3d_image_writes"}};
276f8fc217SDimitry Andric
isKnown(llvm::StringRef Ext) const28b60736ecSDimitry Andric bool OpenCLOptions::isKnown(llvm::StringRef Ext) const {
297fa27ce4SDimitry Andric return OptMap.contains(Ext);
30b60736ecSDimitry Andric }
31b60736ecSDimitry Andric
isAvailableOption(llvm::StringRef Ext,const LangOptions & LO) const32344a3780SDimitry Andric bool OpenCLOptions::isAvailableOption(llvm::StringRef Ext,
33344a3780SDimitry Andric const LangOptions &LO) const {
34344a3780SDimitry Andric if (!isKnown(Ext))
35344a3780SDimitry Andric return false;
36344a3780SDimitry Andric
37344a3780SDimitry Andric auto &OptInfo = OptMap.find(Ext)->getValue();
38344a3780SDimitry Andric if (OptInfo.isCoreIn(LO) || OptInfo.isOptionalCoreIn(LO))
39344a3780SDimitry Andric return isSupported(Ext, LO);
40344a3780SDimitry Andric
41344a3780SDimitry Andric return isEnabled(Ext);
42344a3780SDimitry Andric }
43344a3780SDimitry Andric
isEnabled(llvm::StringRef Ext) const44b60736ecSDimitry Andric bool OpenCLOptions::isEnabled(llvm::StringRef Ext) const {
45344a3780SDimitry Andric auto I = OptMap.find(Ext);
46344a3780SDimitry Andric return I != OptMap.end() && I->getValue().Enabled;
47344a3780SDimitry Andric }
48344a3780SDimitry Andric
isWithPragma(llvm::StringRef Ext) const49344a3780SDimitry Andric bool OpenCLOptions::isWithPragma(llvm::StringRef Ext) const {
50b60736ecSDimitry Andric auto E = OptMap.find(Ext);
51344a3780SDimitry Andric return E != OptMap.end() && E->second.WithPragma;
52b60736ecSDimitry Andric }
53b60736ecSDimitry Andric
isSupported(llvm::StringRef Ext,const LangOptions & LO) const54b60736ecSDimitry Andric bool OpenCLOptions::isSupported(llvm::StringRef Ext,
55b60736ecSDimitry Andric const LangOptions &LO) const {
56344a3780SDimitry Andric auto I = OptMap.find(Ext);
57344a3780SDimitry Andric return I != OptMap.end() && I->getValue().Supported &&
58344a3780SDimitry Andric I->getValue().isAvailableIn(LO);
59b60736ecSDimitry Andric }
60b60736ecSDimitry Andric
isSupportedCore(llvm::StringRef Ext,const LangOptions & LO) const61b60736ecSDimitry Andric bool OpenCLOptions::isSupportedCore(llvm::StringRef Ext,
62b60736ecSDimitry Andric const LangOptions &LO) const {
63344a3780SDimitry Andric auto I = OptMap.find(Ext);
64344a3780SDimitry Andric return I != OptMap.end() && I->getValue().Supported &&
65344a3780SDimitry Andric I->getValue().isCoreIn(LO);
66b60736ecSDimitry Andric }
67b60736ecSDimitry Andric
isSupportedOptionalCore(llvm::StringRef Ext,const LangOptions & LO) const68b60736ecSDimitry Andric bool OpenCLOptions::isSupportedOptionalCore(llvm::StringRef Ext,
69b60736ecSDimitry Andric const LangOptions &LO) const {
70344a3780SDimitry Andric auto I = OptMap.find(Ext);
71344a3780SDimitry Andric return I != OptMap.end() && I->getValue().Supported &&
72344a3780SDimitry Andric I->getValue().isOptionalCoreIn(LO);
73b60736ecSDimitry Andric }
74b60736ecSDimitry Andric
isSupportedCoreOrOptionalCore(llvm::StringRef Ext,const LangOptions & LO) const75b60736ecSDimitry Andric bool OpenCLOptions::isSupportedCoreOrOptionalCore(llvm::StringRef Ext,
76b60736ecSDimitry Andric const LangOptions &LO) const {
77b60736ecSDimitry Andric return isSupportedCore(Ext, LO) || isSupportedOptionalCore(Ext, LO);
78b60736ecSDimitry Andric }
79b60736ecSDimitry Andric
isSupportedExtension(llvm::StringRef Ext,const LangOptions & LO) const80b60736ecSDimitry Andric bool OpenCLOptions::isSupportedExtension(llvm::StringRef Ext,
81b60736ecSDimitry Andric const LangOptions &LO) const {
82344a3780SDimitry Andric auto I = OptMap.find(Ext);
83344a3780SDimitry Andric return I != OptMap.end() && I->getValue().Supported &&
84344a3780SDimitry Andric I->getValue().isAvailableIn(LO) &&
85b60736ecSDimitry Andric !isSupportedCoreOrOptionalCore(Ext, LO);
86b60736ecSDimitry Andric }
87b60736ecSDimitry Andric
enable(llvm::StringRef Ext,bool V)88b60736ecSDimitry Andric void OpenCLOptions::enable(llvm::StringRef Ext, bool V) {
89b60736ecSDimitry Andric OptMap[Ext].Enabled = V;
90b60736ecSDimitry Andric }
91b60736ecSDimitry Andric
acceptsPragma(llvm::StringRef Ext,bool V)92344a3780SDimitry Andric void OpenCLOptions::acceptsPragma(llvm::StringRef Ext, bool V) {
93344a3780SDimitry Andric OptMap[Ext].WithPragma = V;
94344a3780SDimitry Andric }
95344a3780SDimitry Andric
support(llvm::StringRef Ext,bool V)96b60736ecSDimitry Andric void OpenCLOptions::support(llvm::StringRef Ext, bool V) {
97b60736ecSDimitry Andric assert(!Ext.empty() && "Extension is empty.");
98b60736ecSDimitry Andric assert(Ext[0] != '+' && Ext[0] != '-');
99b60736ecSDimitry Andric OptMap[Ext].Supported = V;
100b60736ecSDimitry Andric }
101b60736ecSDimitry Andric
OpenCLOptions()102b60736ecSDimitry Andric OpenCLOptions::OpenCLOptions() {
103344a3780SDimitry Andric #define OPENCL_GENERIC_EXTENSION(Ext, ...) \
104344a3780SDimitry Andric OptMap.insert_or_assign(#Ext, OpenCLOptionInfo{__VA_ARGS__});
105b60736ecSDimitry Andric #include "clang/Basic/OpenCLExtensions.def"
106b60736ecSDimitry Andric }
107b60736ecSDimitry Andric
addSupport(const llvm::StringMap<bool> & FeaturesMap,const LangOptions & Opts)108b60736ecSDimitry Andric void OpenCLOptions::addSupport(const llvm::StringMap<bool> &FeaturesMap,
109b60736ecSDimitry Andric const LangOptions &Opts) {
110b60736ecSDimitry Andric for (const auto &F : FeaturesMap) {
111b60736ecSDimitry Andric const auto &Name = F.getKey();
112b60736ecSDimitry Andric if (F.getValue() && isKnown(Name) && OptMap[Name].isAvailableIn(Opts))
113b60736ecSDimitry Andric support(Name);
114b60736ecSDimitry Andric }
115b60736ecSDimitry Andric }
116b60736ecSDimitry Andric
disableAll()117b60736ecSDimitry Andric void OpenCLOptions::disableAll() {
118b60736ecSDimitry Andric for (auto &Opt : OptMap)
119b60736ecSDimitry Andric Opt.getValue().Enabled = false;
120b60736ecSDimitry Andric }
121b60736ecSDimitry Andric
diagnoseUnsupportedFeatureDependencies(const TargetInfo & TI,DiagnosticsEngine & Diags)122344a3780SDimitry Andric bool OpenCLOptions::diagnoseUnsupportedFeatureDependencies(
123344a3780SDimitry Andric const TargetInfo &TI, DiagnosticsEngine &Diags) {
124344a3780SDimitry Andric auto OpenCLFeaturesMap = TI.getSupportedOpenCLOpts();
125344a3780SDimitry Andric
126344a3780SDimitry Andric bool IsValid = true;
1276f8fc217SDimitry Andric for (auto &FeaturePair : DependentFeaturesList) {
1286f8fc217SDimitry Andric auto Feature = FeaturePair.first;
1296f8fc217SDimitry Andric auto Dep = FeaturePair.second;
1306f8fc217SDimitry Andric if (TI.hasFeatureEnabled(OpenCLFeaturesMap, Feature) &&
1316f8fc217SDimitry Andric !TI.hasFeatureEnabled(OpenCLFeaturesMap, Dep)) {
132344a3780SDimitry Andric IsValid = false;
1336f8fc217SDimitry Andric Diags.Report(diag::err_opencl_feature_requires) << Feature << Dep;
1346f8fc217SDimitry Andric }
135344a3780SDimitry Andric }
136344a3780SDimitry Andric return IsValid;
137344a3780SDimitry Andric }
138344a3780SDimitry Andric
diagnoseFeatureExtensionDifferences(const TargetInfo & TI,DiagnosticsEngine & Diags)139344a3780SDimitry Andric bool OpenCLOptions::diagnoseFeatureExtensionDifferences(
140344a3780SDimitry Andric const TargetInfo &TI, DiagnosticsEngine &Diags) {
141344a3780SDimitry Andric auto OpenCLFeaturesMap = TI.getSupportedOpenCLOpts();
142344a3780SDimitry Andric
143344a3780SDimitry Andric bool IsValid = true;
144344a3780SDimitry Andric for (auto &ExtAndFeat : FeatureExtensionMap)
145145449b1SDimitry Andric if (TI.hasFeatureEnabled(OpenCLFeaturesMap, ExtAndFeat.first) !=
146145449b1SDimitry Andric TI.hasFeatureEnabled(OpenCLFeaturesMap, ExtAndFeat.second)) {
147344a3780SDimitry Andric IsValid = false;
148344a3780SDimitry Andric Diags.Report(diag::err_opencl_extension_and_feature_differs)
149145449b1SDimitry Andric << ExtAndFeat.first << ExtAndFeat.second;
150344a3780SDimitry Andric }
151344a3780SDimitry Andric return IsValid;
152b60736ecSDimitry Andric }
153b60736ecSDimitry Andric
154b60736ecSDimitry Andric } // end namespace clang
155