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