summaryrefslogtreecommitdiffstats
path: root/include/clang/Basic/OpenCLOptions.h
blob: 47310da1d6d95dcf8ac4765d2efb84a788a743bc (plain)
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, 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, 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, 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