155 lines · cpp
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-exception6//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.contains(Ext);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 clang155