| //===--- OpenCLOptions.cpp---------------------------------------*- C++ -*-===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "clang/Basic/OpenCLOptions.h" |
| #include "clang/Basic/Diagnostic.h" |
| #include "clang/Basic/TargetInfo.h" |
| |
| namespace clang { |
| |
| bool OpenCLOptions::isKnown(llvm::StringRef Ext) const { |
| return OptMap.find(Ext) != OptMap.end(); |
| } |
| |
| bool OpenCLOptions::isAvailableOption(llvm::StringRef Ext, |
| const LangOptions &LO) const { |
| if (!isKnown(Ext)) |
| return false; |
| |
| auto &OptInfo = OptMap.find(Ext)->getValue(); |
| if (OptInfo.isCoreIn(LO) || OptInfo.isOptionalCoreIn(LO)) |
| return isSupported(Ext, LO); |
| |
| return isEnabled(Ext); |
| } |
| |
| bool OpenCLOptions::isEnabled(llvm::StringRef Ext) const { |
| auto I = OptMap.find(Ext); |
| return I != OptMap.end() && I->getValue().Enabled; |
| } |
| |
| bool OpenCLOptions::isWithPragma(llvm::StringRef Ext) const { |
| auto E = OptMap.find(Ext); |
| return E != OptMap.end() && E->second.WithPragma; |
| } |
| |
| bool OpenCLOptions::isSupported(llvm::StringRef Ext, |
| const LangOptions &LO) const { |
| auto I = OptMap.find(Ext); |
| return I != OptMap.end() && I->getValue().Supported && |
| I->getValue().isAvailableIn(LO); |
| } |
| |
| bool OpenCLOptions::isSupportedCore(llvm::StringRef Ext, |
| const LangOptions &LO) const { |
| auto I = OptMap.find(Ext); |
| return I != OptMap.end() && I->getValue().Supported && |
| I->getValue().isCoreIn(LO); |
| } |
| |
| bool OpenCLOptions::isSupportedOptionalCore(llvm::StringRef Ext, |
| const LangOptions &LO) const { |
| auto I = OptMap.find(Ext); |
| return I != OptMap.end() && I->getValue().Supported && |
| I->getValue().isOptionalCoreIn(LO); |
| } |
| |
| bool OpenCLOptions::isSupportedCoreOrOptionalCore(llvm::StringRef Ext, |
| const LangOptions &LO) const { |
| return isSupportedCore(Ext, LO) || isSupportedOptionalCore(Ext, LO); |
| } |
| |
| bool OpenCLOptions::isSupportedExtension(llvm::StringRef Ext, |
| const LangOptions &LO) const { |
| auto I = OptMap.find(Ext); |
| return I != OptMap.end() && I->getValue().Supported && |
| I->getValue().isAvailableIn(LO) && |
| !isSupportedCoreOrOptionalCore(Ext, LO); |
| } |
| |
| void OpenCLOptions::enable(llvm::StringRef Ext, bool V) { |
| OptMap[Ext].Enabled = V; |
| } |
| |
| void OpenCLOptions::acceptsPragma(llvm::StringRef Ext, bool V) { |
| OptMap[Ext].WithPragma = V; |
| } |
| |
| void OpenCLOptions::support(llvm::StringRef Ext, bool V) { |
| assert(!Ext.empty() && "Extension is empty."); |
| assert(Ext[0] != '+' && Ext[0] != '-'); |
| OptMap[Ext].Supported = V; |
| } |
| |
| OpenCLOptions::OpenCLOptions() { |
| #define OPENCL_GENERIC_EXTENSION(Ext, ...) \ |
| OptMap.insert_or_assign(#Ext, OpenCLOptionInfo{__VA_ARGS__}); |
| #include "clang/Basic/OpenCLExtensions.def" |
| } |
| |
| void OpenCLOptions::addSupport(const llvm::StringMap<bool> &FeaturesMap, |
| const LangOptions &Opts) { |
| for (const auto &F : FeaturesMap) { |
| const auto &Name = F.getKey(); |
| if (F.getValue() && isKnown(Name) && OptMap[Name].isAvailableIn(Opts)) |
| support(Name); |
| } |
| } |
| |
| void OpenCLOptions::disableAll() { |
| for (auto &Opt : OptMap) |
| Opt.getValue().Enabled = false; |
| } |
| |
| bool OpenCLOptions::diagnoseUnsupportedFeatureDependencies( |
| const TargetInfo &TI, DiagnosticsEngine &Diags) { |
| // Feature pairs. First feature in a pair requires the second one to be |
| // supported. |
| static const llvm::StringMap<llvm::StringRef> DependentFeaturesMap = { |
| {"__opencl_c_read_write_images", "__opencl_c_images"}, |
| {"__opencl_c_3d_image_writes", "__opencl_c_images"}, |
| {"__opencl_c_pipes", "__opencl_c_generic_address_space"}}; |
| |
| auto OpenCLFeaturesMap = TI.getSupportedOpenCLOpts(); |
| |
| bool IsValid = true; |
| for (auto &FeaturePair : DependentFeaturesMap) |
| if (TI.hasFeatureEnabled(OpenCLFeaturesMap, FeaturePair.getKey()) && |
| !TI.hasFeatureEnabled(OpenCLFeaturesMap, FeaturePair.getValue())) { |
| IsValid = false; |
| Diags.Report(diag::err_opencl_feature_requires) |
| << FeaturePair.getKey() << FeaturePair.getValue(); |
| } |
| return IsValid; |
| } |
| |
| bool OpenCLOptions::diagnoseFeatureExtensionDifferences( |
| const TargetInfo &TI, DiagnosticsEngine &Diags) { |
| // Extensions and equivalent feature pairs. |
| static const llvm::StringMap<llvm::StringRef> FeatureExtensionMap = { |
| {"cl_khr_fp64", "__opencl_c_fp64"}, |
| {"cl_khr_3d_image_writes", "__opencl_c_3d_image_writes"}}; |
| |
| auto OpenCLFeaturesMap = TI.getSupportedOpenCLOpts(); |
| |
| bool IsValid = true; |
| for (auto &ExtAndFeat : FeatureExtensionMap) |
| if (TI.hasFeatureEnabled(OpenCLFeaturesMap, ExtAndFeat.getKey()) != |
| TI.hasFeatureEnabled(OpenCLFeaturesMap, ExtAndFeat.getValue())) { |
| IsValid = false; |
| Diags.Report(diag::err_opencl_extension_and_feature_differs) |
| << ExtAndFeat.getKey() << ExtAndFeat.getValue(); |
| } |
| return IsValid; |
| } |
| |
| } // end namespace clang |