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