OpenCLOptions.cpp 5.2 KB

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