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" 10*fe6060f1SDimitry Andric #include "clang/Basic/Diagnostic.h" 11*fe6060f1SDimitry Andric #include "clang/Basic/TargetInfo.h" 12e8d8bef9SDimitry Andric 13e8d8bef9SDimitry Andric namespace clang { 14e8d8bef9SDimitry Andric 15e8d8bef9SDimitry Andric bool OpenCLOptions::isKnown(llvm::StringRef Ext) const { 16e8d8bef9SDimitry Andric return OptMap.find(Ext) != OptMap.end(); 17e8d8bef9SDimitry Andric } 18e8d8bef9SDimitry Andric 19*fe6060f1SDimitry Andric bool OpenCLOptions::isAvailableOption(llvm::StringRef Ext, 20*fe6060f1SDimitry Andric const LangOptions &LO) const { 21*fe6060f1SDimitry Andric if (!isKnown(Ext)) 22*fe6060f1SDimitry Andric return false; 23*fe6060f1SDimitry Andric 24*fe6060f1SDimitry Andric auto &OptInfo = OptMap.find(Ext)->getValue(); 25*fe6060f1SDimitry Andric if (OptInfo.isCoreIn(LO) || OptInfo.isOptionalCoreIn(LO)) 26*fe6060f1SDimitry Andric return isSupported(Ext, LO); 27*fe6060f1SDimitry Andric 28*fe6060f1SDimitry Andric return isEnabled(Ext); 29*fe6060f1SDimitry Andric } 30*fe6060f1SDimitry Andric 31e8d8bef9SDimitry Andric bool OpenCLOptions::isEnabled(llvm::StringRef Ext) const { 32*fe6060f1SDimitry Andric auto I = OptMap.find(Ext); 33*fe6060f1SDimitry Andric return I != OptMap.end() && I->getValue().Enabled; 34*fe6060f1SDimitry Andric } 35*fe6060f1SDimitry Andric 36*fe6060f1SDimitry Andric bool OpenCLOptions::isWithPragma(llvm::StringRef Ext) const { 37e8d8bef9SDimitry Andric auto E = OptMap.find(Ext); 38*fe6060f1SDimitry Andric return E != OptMap.end() && E->second.WithPragma; 39e8d8bef9SDimitry Andric } 40e8d8bef9SDimitry Andric 41e8d8bef9SDimitry Andric bool OpenCLOptions::isSupported(llvm::StringRef Ext, 42e8d8bef9SDimitry Andric const LangOptions &LO) const { 43*fe6060f1SDimitry Andric auto I = OptMap.find(Ext); 44*fe6060f1SDimitry Andric return I != OptMap.end() && I->getValue().Supported && 45*fe6060f1SDimitry Andric I->getValue().isAvailableIn(LO); 46e8d8bef9SDimitry Andric } 47e8d8bef9SDimitry Andric 48e8d8bef9SDimitry Andric bool OpenCLOptions::isSupportedCore(llvm::StringRef Ext, 49e8d8bef9SDimitry Andric const LangOptions &LO) const { 50*fe6060f1SDimitry Andric auto I = OptMap.find(Ext); 51*fe6060f1SDimitry Andric return I != OptMap.end() && I->getValue().Supported && 52*fe6060f1SDimitry Andric I->getValue().isCoreIn(LO); 53e8d8bef9SDimitry Andric } 54e8d8bef9SDimitry Andric 55e8d8bef9SDimitry Andric bool OpenCLOptions::isSupportedOptionalCore(llvm::StringRef Ext, 56e8d8bef9SDimitry Andric const LangOptions &LO) const { 57*fe6060f1SDimitry Andric auto I = OptMap.find(Ext); 58*fe6060f1SDimitry Andric return I != OptMap.end() && I->getValue().Supported && 59*fe6060f1SDimitry Andric I->getValue().isOptionalCoreIn(LO); 60e8d8bef9SDimitry Andric } 61e8d8bef9SDimitry Andric 62e8d8bef9SDimitry Andric bool OpenCLOptions::isSupportedCoreOrOptionalCore(llvm::StringRef Ext, 63e8d8bef9SDimitry Andric const LangOptions &LO) const { 64e8d8bef9SDimitry Andric return isSupportedCore(Ext, LO) || isSupportedOptionalCore(Ext, LO); 65e8d8bef9SDimitry Andric } 66e8d8bef9SDimitry Andric 67e8d8bef9SDimitry Andric bool OpenCLOptions::isSupportedExtension(llvm::StringRef Ext, 68e8d8bef9SDimitry Andric const LangOptions &LO) const { 69*fe6060f1SDimitry Andric auto I = OptMap.find(Ext); 70*fe6060f1SDimitry Andric return I != OptMap.end() && I->getValue().Supported && 71*fe6060f1SDimitry Andric I->getValue().isAvailableIn(LO) && 72e8d8bef9SDimitry Andric !isSupportedCoreOrOptionalCore(Ext, LO); 73e8d8bef9SDimitry Andric } 74e8d8bef9SDimitry Andric 75e8d8bef9SDimitry Andric void OpenCLOptions::enable(llvm::StringRef Ext, bool V) { 76e8d8bef9SDimitry Andric OptMap[Ext].Enabled = V; 77e8d8bef9SDimitry Andric } 78e8d8bef9SDimitry Andric 79*fe6060f1SDimitry Andric void OpenCLOptions::acceptsPragma(llvm::StringRef Ext, bool V) { 80*fe6060f1SDimitry Andric OptMap[Ext].WithPragma = V; 81*fe6060f1SDimitry Andric } 82*fe6060f1SDimitry Andric 83e8d8bef9SDimitry Andric void OpenCLOptions::support(llvm::StringRef Ext, bool V) { 84e8d8bef9SDimitry Andric assert(!Ext.empty() && "Extension is empty."); 85e8d8bef9SDimitry Andric assert(Ext[0] != '+' && Ext[0] != '-'); 86e8d8bef9SDimitry Andric OptMap[Ext].Supported = V; 87e8d8bef9SDimitry Andric } 88e8d8bef9SDimitry Andric 89e8d8bef9SDimitry Andric OpenCLOptions::OpenCLOptions() { 90*fe6060f1SDimitry Andric #define OPENCL_GENERIC_EXTENSION(Ext, ...) \ 91*fe6060f1SDimitry Andric OptMap.insert_or_assign(#Ext, OpenCLOptionInfo{__VA_ARGS__}); 92e8d8bef9SDimitry Andric #include "clang/Basic/OpenCLExtensions.def" 93e8d8bef9SDimitry Andric } 94e8d8bef9SDimitry Andric 95e8d8bef9SDimitry Andric void OpenCLOptions::addSupport(const llvm::StringMap<bool> &FeaturesMap, 96e8d8bef9SDimitry Andric const LangOptions &Opts) { 97e8d8bef9SDimitry Andric for (const auto &F : FeaturesMap) { 98e8d8bef9SDimitry Andric const auto &Name = F.getKey(); 99e8d8bef9SDimitry Andric if (F.getValue() && isKnown(Name) && OptMap[Name].isAvailableIn(Opts)) 100e8d8bef9SDimitry Andric support(Name); 101e8d8bef9SDimitry Andric } 102e8d8bef9SDimitry Andric } 103e8d8bef9SDimitry Andric 104e8d8bef9SDimitry Andric void OpenCLOptions::disableAll() { 105e8d8bef9SDimitry Andric for (auto &Opt : OptMap) 106e8d8bef9SDimitry Andric Opt.getValue().Enabled = false; 107e8d8bef9SDimitry Andric } 108e8d8bef9SDimitry Andric 109*fe6060f1SDimitry Andric bool OpenCLOptions::diagnoseUnsupportedFeatureDependencies( 110*fe6060f1SDimitry Andric const TargetInfo &TI, DiagnosticsEngine &Diags) { 111*fe6060f1SDimitry Andric // Feature pairs. First feature in a pair requires the second one to be 112*fe6060f1SDimitry Andric // supported. 113*fe6060f1SDimitry Andric static const llvm::StringMap<llvm::StringRef> DependentFeaturesMap = { 114*fe6060f1SDimitry Andric {"__opencl_c_read_write_images", "__opencl_c_images"}}; 115*fe6060f1SDimitry Andric 116*fe6060f1SDimitry Andric auto OpenCLFeaturesMap = TI.getSupportedOpenCLOpts(); 117*fe6060f1SDimitry Andric 118*fe6060f1SDimitry Andric bool IsValid = true; 119*fe6060f1SDimitry Andric for (auto &FeaturePair : DependentFeaturesMap) 120*fe6060f1SDimitry Andric if (TI.hasFeatureEnabled(OpenCLFeaturesMap, FeaturePair.getKey()) && 121*fe6060f1SDimitry Andric !TI.hasFeatureEnabled(OpenCLFeaturesMap, FeaturePair.getValue())) { 122*fe6060f1SDimitry Andric IsValid = false; 123*fe6060f1SDimitry Andric Diags.Report(diag::err_opencl_feature_requires) 124*fe6060f1SDimitry Andric << FeaturePair.getKey() << FeaturePair.getValue(); 125*fe6060f1SDimitry Andric } 126*fe6060f1SDimitry Andric return IsValid; 127*fe6060f1SDimitry Andric } 128*fe6060f1SDimitry Andric 129*fe6060f1SDimitry Andric bool OpenCLOptions::diagnoseFeatureExtensionDifferences( 130*fe6060f1SDimitry Andric const TargetInfo &TI, DiagnosticsEngine &Diags) { 131*fe6060f1SDimitry Andric // Extensions and equivalent feature pairs. 132*fe6060f1SDimitry Andric static const llvm::StringMap<llvm::StringRef> FeatureExtensionMap = { 133*fe6060f1SDimitry Andric {"cl_khr_fp64", "__opencl_c_fp64"}}; 134*fe6060f1SDimitry Andric 135*fe6060f1SDimitry Andric auto OpenCLFeaturesMap = TI.getSupportedOpenCLOpts(); 136*fe6060f1SDimitry Andric 137*fe6060f1SDimitry Andric bool IsValid = true; 138*fe6060f1SDimitry Andric for (auto &ExtAndFeat : FeatureExtensionMap) 139*fe6060f1SDimitry Andric if (TI.hasFeatureEnabled(OpenCLFeaturesMap, ExtAndFeat.getKey()) != 140*fe6060f1SDimitry Andric TI.hasFeatureEnabled(OpenCLFeaturesMap, ExtAndFeat.getValue())) { 141*fe6060f1SDimitry Andric IsValid = false; 142*fe6060f1SDimitry Andric Diags.Report(diag::err_opencl_extension_and_feature_differs) 143*fe6060f1SDimitry Andric << ExtAndFeat.getKey() << ExtAndFeat.getValue(); 144*fe6060f1SDimitry Andric } 145*fe6060f1SDimitry Andric return IsValid; 146e8d8bef9SDimitry Andric } 147e8d8bef9SDimitry Andric 148e8d8bef9SDimitry Andric } // end namespace clang 149