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 // First feature in a pair requires the second one to be supported. 16 static 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. 24 static 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 28 bool OpenCLOptions::isKnown(llvm::StringRef Ext) const { 29 return OptMap.find(Ext) != OptMap.end(); 30 } 31 32 bool 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 44 bool OpenCLOptions::isEnabled(llvm::StringRef Ext) const { 45 auto I = OptMap.find(Ext); 46 return I != OptMap.end() && I->getValue().Enabled; 47 } 48 49 bool OpenCLOptions::isWithPragma(llvm::StringRef Ext) const { 50 auto E = OptMap.find(Ext); 51 return E != OptMap.end() && E->second.WithPragma; 52 } 53 54 bool 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 61 bool 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 68 bool 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 75 bool OpenCLOptions::isSupportedCoreOrOptionalCore(llvm::StringRef Ext, 76 const LangOptions &LO) const { 77 return isSupportedCore(Ext, LO) || isSupportedOptionalCore(Ext, LO); 78 } 79 80 bool 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 88 void OpenCLOptions::enable(llvm::StringRef Ext, bool V) { 89 OptMap[Ext].Enabled = V; 90 } 91 92 void OpenCLOptions::acceptsPragma(llvm::StringRef Ext, bool V) { 93 OptMap[Ext].WithPragma = V; 94 } 95 96 void 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 102 OpenCLOptions::OpenCLOptions() { 103 #define OPENCL_GENERIC_EXTENSION(Ext, ...) \ 104 OptMap.insert_or_assign(#Ext, OpenCLOptionInfo{__VA_ARGS__}); 105 #include "clang/Basic/OpenCLExtensions.def" 106 } 107 108 void 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 117 void OpenCLOptions::disableAll() { 118 for (auto &Opt : OptMap) 119 Opt.getValue().Enabled = false; 120 } 121 122 bool 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 139 bool 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