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