reference, declarationdefinition
definition → references, declarations, derived classes, virtual overrides
reference to multiple definitions → definitions
unreferenced
    1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
  134
  135
  136
  137
  138
  139
  140
  141
  142
//===--- OpenCLOptions.h ----------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
///
/// \file
/// Defines the clang::OpenCLOptions class.
///
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_BASIC_OPENCLOPTIONS_H
#define LLVM_CLANG_BASIC_OPENCLOPTIONS_H

#include "clang/Basic/LangOptions.h"
#include "llvm/ADT/StringMap.h"

namespace clang {

/// OpenCL supported extensions and optional core features
class OpenCLOptions {
  struct Info {
    bool Supported; // Is this option supported
    bool Enabled;   // Is this option enabled
    unsigned Avail; // Option starts to be available in this OpenCL version
    unsigned Core;  // Option becomes (optional) core feature in this OpenCL
                    // version
    Info(bool S = false, bool E = false, unsigned A = 100, unsigned C = ~0U)
      :Supported(S), Enabled(E), Avail(A), Core(C){}
  };
  llvm::StringMap<Info> OptMap;
public:
  bool isKnown(llvm::StringRef Ext) const {
    return OptMap.find(Ext) != OptMap.end();
  }

  bool isEnabled(llvm::StringRef Ext) const {
    return OptMap.find(Ext)->second.Enabled;
  }

  // Is supported as either an extension or an (optional) core feature for
  // OpenCL version \p CLVer.
  bool isSupported(llvm::StringRef Ext, const LangOptions &LO) const {
    // In C++ mode all extensions should work at least as in v2.0.
    auto CLVer = LO.OpenCLCPlusPlus ? 200 : LO.OpenCLVersion;
    auto I = OptMap.find(Ext)->getValue();
    return I.Supported && I.Avail <= CLVer;
  }

  // Is supported (optional) OpenCL core features for OpenCL version \p CLVer.
  // For supported extension, return false.
  bool isSupportedCore(llvm::StringRef Ext, const LangOptions &LO) const {
    // In C++ mode all extensions should work at least as in v2.0.
    auto CLVer = LO.OpenCLCPlusPlus ? 200 : LO.OpenCLVersion;
    auto I = OptMap.find(Ext)->getValue();
    return I.Supported && I.Avail <= CLVer && I.Core != ~0U && CLVer >= I.Core;
  }

  // Is supported OpenCL extension for OpenCL version \p CLVer.
  // For supported (optional) core feature, return false.
  bool isSupportedExtension(llvm::StringRef Ext, const LangOptions &LO) const {
    // In C++ mode all extensions should work at least as in v2.0.
    auto CLVer = LO.OpenCLCPlusPlus ? 200 : LO.OpenCLVersion;
    auto I = OptMap.find(Ext)->getValue();
    return I.Supported && I.Avail <= CLVer && (I.Core == ~0U || CLVer < I.Core);
  }

  void enable(llvm::StringRef Ext, bool V = true) {
    OptMap[Ext].Enabled = V;
  }

  /// Enable or disable support for OpenCL extensions
  /// \param Ext name of the extension optionally prefixed with
  ///        '+' or '-'
  /// \param V used when \p Ext is not prefixed by '+' or '-'
  void support(llvm::StringRef Ext, bool V = true) {
    assert(!Ext.empty() && "Extension is empty.");

    switch (Ext[0]) {
    case '+':
      V = true;
      Ext = Ext.drop_front();
      break;
    case '-':
      V = false;
      Ext = Ext.drop_front();
      break;
    }

    if (Ext.equals("all")) {
      supportAll(V);
      return;
    }
    OptMap[Ext].Supported = V;
  }

  OpenCLOptions(){
#define OPENCLEXT_INTERNAL(Ext, AvailVer, CoreVer) \
    OptMap[#Ext].Avail = AvailVer; \
    OptMap[#Ext].Core = CoreVer;
#include "clang/Basic/OpenCLExtensions.def"
  }

  void addSupport(const OpenCLOptions &Opts) {
    for (auto &I:Opts.OptMap)
      if (I.second.Supported)
        OptMap[I.getKey()].Supported = true;
  }

  void copy(const OpenCLOptions &Opts) {
    OptMap = Opts.OptMap;
  }

  // Turn on or off support of all options.
  void supportAll(bool On = true) {
    for (llvm::StringMap<Info>::iterator I = OptMap.begin(),
         E = OptMap.end(); I != E; ++I)
      I->second.Supported = On;
  }

  void disableAll() {
    for (llvm::StringMap<Info>::iterator I = OptMap.begin(),
         E = OptMap.end(); I != E; ++I)
      I->second.Enabled = false;
  }

  void enableSupportedCore(LangOptions LO) {
    for (llvm::StringMap<Info>::iterator I = OptMap.begin(), E = OptMap.end();
         I != E; ++I)
      if (isSupportedCore(I->getKey(), LO))
        I->second.Enabled = true;
  }

  friend class ASTWriter;
  friend class ASTReader;
};

} // end namespace clang

#endif