1e8d8bef9SDimitry Andric //===--- OpenCLOptions.cpp---------------------------------------*- C++ -*-===//
2e8d8bef9SDimitry Andric //
3e8d8bef9SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e8d8bef9SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e8d8bef9SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e8d8bef9SDimitry Andric //
7e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===//
8e8d8bef9SDimitry Andric
9e8d8bef9SDimitry Andric #include "clang/Basic/OpenCLOptions.h"
10fe6060f1SDimitry Andric #include "clang/Basic/Diagnostic.h"
11fe6060f1SDimitry Andric #include "clang/Basic/TargetInfo.h"
12e8d8bef9SDimitry Andric
13e8d8bef9SDimitry Andric namespace clang {
14e8d8bef9SDimitry Andric
1581ad6265SDimitry Andric // First feature in a pair requires the second one to be supported.
1681ad6265SDimitry Andric static const std::pair<StringRef, StringRef> DependentFeaturesList[] = {
1704eeddc0SDimitry Andric {"__opencl_c_read_write_images", "__opencl_c_images"},
1804eeddc0SDimitry Andric {"__opencl_c_3d_image_writes", "__opencl_c_images"},
1904eeddc0SDimitry Andric {"__opencl_c_pipes", "__opencl_c_generic_address_space"},
2004eeddc0SDimitry Andric {"__opencl_c_device_enqueue", "__opencl_c_generic_address_space"},
2104eeddc0SDimitry Andric {"__opencl_c_device_enqueue", "__opencl_c_program_scope_global_variables"}};
2204eeddc0SDimitry Andric
2381ad6265SDimitry Andric // Extensions and equivalent feature pairs.
2481ad6265SDimitry Andric static const std::pair<StringRef, StringRef> FeatureExtensionMap[] = {
2504eeddc0SDimitry Andric {"cl_khr_fp64", "__opencl_c_fp64"},
2604eeddc0SDimitry Andric {"cl_khr_3d_image_writes", "__opencl_c_3d_image_writes"}};
2704eeddc0SDimitry Andric
isKnown(llvm::StringRef Ext) const28e8d8bef9SDimitry Andric bool OpenCLOptions::isKnown(llvm::StringRef Ext) const {
29*06c3fb27SDimitry Andric return OptMap.contains(Ext);
30e8d8bef9SDimitry Andric }
31e8d8bef9SDimitry Andric
isAvailableOption(llvm::StringRef Ext,const LangOptions & LO) const32fe6060f1SDimitry Andric bool OpenCLOptions::isAvailableOption(llvm::StringRef Ext,
33fe6060f1SDimitry Andric const LangOptions &LO) const {
34fe6060f1SDimitry Andric if (!isKnown(Ext))
35fe6060f1SDimitry Andric return false;
36fe6060f1SDimitry Andric
37fe6060f1SDimitry Andric auto &OptInfo = OptMap.find(Ext)->getValue();
38fe6060f1SDimitry Andric if (OptInfo.isCoreIn(LO) || OptInfo.isOptionalCoreIn(LO))
39fe6060f1SDimitry Andric return isSupported(Ext, LO);
40fe6060f1SDimitry Andric
41fe6060f1SDimitry Andric return isEnabled(Ext);
42fe6060f1SDimitry Andric }
43fe6060f1SDimitry Andric
isEnabled(llvm::StringRef Ext) const44e8d8bef9SDimitry Andric bool OpenCLOptions::isEnabled(llvm::StringRef Ext) const {
45fe6060f1SDimitry Andric auto I = OptMap.find(Ext);
46fe6060f1SDimitry Andric return I != OptMap.end() && I->getValue().Enabled;
47fe6060f1SDimitry Andric }
48fe6060f1SDimitry Andric
isWithPragma(llvm::StringRef Ext) const49fe6060f1SDimitry Andric bool OpenCLOptions::isWithPragma(llvm::StringRef Ext) const {
50e8d8bef9SDimitry Andric auto E = OptMap.find(Ext);
51fe6060f1SDimitry Andric return E != OptMap.end() && E->second.WithPragma;
52e8d8bef9SDimitry Andric }
53e8d8bef9SDimitry Andric
isSupported(llvm::StringRef Ext,const LangOptions & LO) const54e8d8bef9SDimitry Andric bool OpenCLOptions::isSupported(llvm::StringRef Ext,
55e8d8bef9SDimitry Andric const LangOptions &LO) const {
56fe6060f1SDimitry Andric auto I = OptMap.find(Ext);
57fe6060f1SDimitry Andric return I != OptMap.end() && I->getValue().Supported &&
58fe6060f1SDimitry Andric I->getValue().isAvailableIn(LO);
59e8d8bef9SDimitry Andric }
60e8d8bef9SDimitry Andric
isSupportedCore(llvm::StringRef Ext,const LangOptions & LO) const61e8d8bef9SDimitry Andric bool OpenCLOptions::isSupportedCore(llvm::StringRef Ext,
62e8d8bef9SDimitry Andric const LangOptions &LO) const {
63fe6060f1SDimitry Andric auto I = OptMap.find(Ext);
64fe6060f1SDimitry Andric return I != OptMap.end() && I->getValue().Supported &&
65fe6060f1SDimitry Andric I->getValue().isCoreIn(LO);
66e8d8bef9SDimitry Andric }
67e8d8bef9SDimitry Andric
isSupportedOptionalCore(llvm::StringRef Ext,const LangOptions & LO) const68e8d8bef9SDimitry Andric bool OpenCLOptions::isSupportedOptionalCore(llvm::StringRef Ext,
69e8d8bef9SDimitry Andric const LangOptions &LO) const {
70fe6060f1SDimitry Andric auto I = OptMap.find(Ext);
71fe6060f1SDimitry Andric return I != OptMap.end() && I->getValue().Supported &&
72fe6060f1SDimitry Andric I->getValue().isOptionalCoreIn(LO);
73e8d8bef9SDimitry Andric }
74e8d8bef9SDimitry Andric
isSupportedCoreOrOptionalCore(llvm::StringRef Ext,const LangOptions & LO) const75e8d8bef9SDimitry Andric bool OpenCLOptions::isSupportedCoreOrOptionalCore(llvm::StringRef Ext,
76e8d8bef9SDimitry Andric const LangOptions &LO) const {
77e8d8bef9SDimitry Andric return isSupportedCore(Ext, LO) || isSupportedOptionalCore(Ext, LO);
78e8d8bef9SDimitry Andric }
79e8d8bef9SDimitry Andric
isSupportedExtension(llvm::StringRef Ext,const LangOptions & LO) const80e8d8bef9SDimitry Andric bool OpenCLOptions::isSupportedExtension(llvm::StringRef Ext,
81e8d8bef9SDimitry Andric const LangOptions &LO) const {
82fe6060f1SDimitry Andric auto I = OptMap.find(Ext);
83fe6060f1SDimitry Andric return I != OptMap.end() && I->getValue().Supported &&
84fe6060f1SDimitry Andric I->getValue().isAvailableIn(LO) &&
85e8d8bef9SDimitry Andric !isSupportedCoreOrOptionalCore(Ext, LO);
86e8d8bef9SDimitry Andric }
87e8d8bef9SDimitry Andric
enable(llvm::StringRef Ext,bool V)88e8d8bef9SDimitry Andric void OpenCLOptions::enable(llvm::StringRef Ext, bool V) {
89e8d8bef9SDimitry Andric OptMap[Ext].Enabled = V;
90e8d8bef9SDimitry Andric }
91e8d8bef9SDimitry Andric
acceptsPragma(llvm::StringRef Ext,bool V)92fe6060f1SDimitry Andric void OpenCLOptions::acceptsPragma(llvm::StringRef Ext, bool V) {
93fe6060f1SDimitry Andric OptMap[Ext].WithPragma = V;
94fe6060f1SDimitry Andric }
95fe6060f1SDimitry Andric
support(llvm::StringRef Ext,bool V)96e8d8bef9SDimitry Andric void OpenCLOptions::support(llvm::StringRef Ext, bool V) {
97e8d8bef9SDimitry Andric assert(!Ext.empty() && "Extension is empty.");
98e8d8bef9SDimitry Andric assert(Ext[0] != '+' && Ext[0] != '-');
99e8d8bef9SDimitry Andric OptMap[Ext].Supported = V;
100e8d8bef9SDimitry Andric }
101e8d8bef9SDimitry Andric
OpenCLOptions()102e8d8bef9SDimitry Andric OpenCLOptions::OpenCLOptions() {
103fe6060f1SDimitry Andric #define OPENCL_GENERIC_EXTENSION(Ext, ...) \
104fe6060f1SDimitry Andric OptMap.insert_or_assign(#Ext, OpenCLOptionInfo{__VA_ARGS__});
105e8d8bef9SDimitry Andric #include "clang/Basic/OpenCLExtensions.def"
106e8d8bef9SDimitry Andric }
107e8d8bef9SDimitry Andric
addSupport(const llvm::StringMap<bool> & FeaturesMap,const LangOptions & Opts)108e8d8bef9SDimitry Andric void OpenCLOptions::addSupport(const llvm::StringMap<bool> &FeaturesMap,
109e8d8bef9SDimitry Andric const LangOptions &Opts) {
110e8d8bef9SDimitry Andric for (const auto &F : FeaturesMap) {
111e8d8bef9SDimitry Andric const auto &Name = F.getKey();
112e8d8bef9SDimitry Andric if (F.getValue() && isKnown(Name) && OptMap[Name].isAvailableIn(Opts))
113e8d8bef9SDimitry Andric support(Name);
114e8d8bef9SDimitry Andric }
115e8d8bef9SDimitry Andric }
116e8d8bef9SDimitry Andric
disableAll()117e8d8bef9SDimitry Andric void OpenCLOptions::disableAll() {
118e8d8bef9SDimitry Andric for (auto &Opt : OptMap)
119e8d8bef9SDimitry Andric Opt.getValue().Enabled = false;
120e8d8bef9SDimitry Andric }
121e8d8bef9SDimitry Andric
diagnoseUnsupportedFeatureDependencies(const TargetInfo & TI,DiagnosticsEngine & Diags)122fe6060f1SDimitry Andric bool OpenCLOptions::diagnoseUnsupportedFeatureDependencies(
123fe6060f1SDimitry Andric const TargetInfo &TI, DiagnosticsEngine &Diags) {
124fe6060f1SDimitry Andric auto OpenCLFeaturesMap = TI.getSupportedOpenCLOpts();
125fe6060f1SDimitry Andric
126fe6060f1SDimitry Andric bool IsValid = true;
12704eeddc0SDimitry Andric for (auto &FeaturePair : DependentFeaturesList) {
12804eeddc0SDimitry Andric auto Feature = FeaturePair.first;
12904eeddc0SDimitry Andric auto Dep = FeaturePair.second;
13004eeddc0SDimitry Andric if (TI.hasFeatureEnabled(OpenCLFeaturesMap, Feature) &&
13104eeddc0SDimitry Andric !TI.hasFeatureEnabled(OpenCLFeaturesMap, Dep)) {
132fe6060f1SDimitry Andric IsValid = false;
13304eeddc0SDimitry Andric Diags.Report(diag::err_opencl_feature_requires) << Feature << Dep;
13404eeddc0SDimitry Andric }
135fe6060f1SDimitry Andric }
136fe6060f1SDimitry Andric return IsValid;
137fe6060f1SDimitry Andric }
138fe6060f1SDimitry Andric
diagnoseFeatureExtensionDifferences(const TargetInfo & TI,DiagnosticsEngine & Diags)139fe6060f1SDimitry Andric bool OpenCLOptions::diagnoseFeatureExtensionDifferences(
140fe6060f1SDimitry Andric const TargetInfo &TI, DiagnosticsEngine &Diags) {
141fe6060f1SDimitry Andric auto OpenCLFeaturesMap = TI.getSupportedOpenCLOpts();
142fe6060f1SDimitry Andric
143fe6060f1SDimitry Andric bool IsValid = true;
144fe6060f1SDimitry Andric for (auto &ExtAndFeat : FeatureExtensionMap)
14581ad6265SDimitry Andric if (TI.hasFeatureEnabled(OpenCLFeaturesMap, ExtAndFeat.first) !=
14681ad6265SDimitry Andric TI.hasFeatureEnabled(OpenCLFeaturesMap, ExtAndFeat.second)) {
147fe6060f1SDimitry Andric IsValid = false;
148fe6060f1SDimitry Andric Diags.Report(diag::err_opencl_extension_and_feature_differs)
14981ad6265SDimitry Andric << ExtAndFeat.first << ExtAndFeat.second;
150fe6060f1SDimitry Andric }
151fe6060f1SDimitry Andric return IsValid;
152e8d8bef9SDimitry Andric }
153e8d8bef9SDimitry Andric
154e8d8bef9SDimitry Andric } // end namespace clang
155