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