Clang Project

clang_source_code/include/clang/Basic/SyncScope.h
1//===--- SyncScope.h - Atomic synchronization scopes ------------*- 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/// \file
10/// Provides definitions for the atomic synchronization scopes.
11///
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_CLANG_BASIC_SYNCSCOPE_H
15#define LLVM_CLANG_BASIC_SYNCSCOPE_H
16
17#include "clang/Basic/LangOptions.h"
18#include "llvm/ADT/ArrayRef.h"
19#include "llvm/ADT/StringRef.h"
20#include <memory>
21
22namespace clang {
23
24/// Defines synch scope values used internally by clang.
25///
26/// The enum values start from 0 and are contiguous. They are mainly used for
27/// enumerating all supported synch scope values and mapping them to LLVM
28/// synch scopes. Their numerical values may be different from the corresponding
29/// synch scope enums used in source languages.
30///
31/// In atomic builtin and expressions, language-specific synch scope enums are
32/// used. Currently only OpenCL memory scope enums are supported and assumed
33/// to be used by all languages. However, in the future, other languages may
34/// define their own set of synch scope enums. The language-specific synch scope
35/// values are represented by class AtomicScopeModel and its derived classes.
36///
37/// To add a new enum value:
38///   Add the enum value to enum class SyncScope.
39///   Update enum value Last if necessary.
40///   Update getAsString.
41///
42enum class SyncScope {
43  OpenCLWorkGroup,
44  OpenCLDevice,
45  OpenCLAllSVMDevices,
46  OpenCLSubGroup,
47  Last = OpenCLSubGroup
48};
49
50inline llvm::StringRef getAsString(SyncScope S) {
51  switch (S) {
52  case SyncScope::OpenCLWorkGroup:
53    return "opencl_workgroup";
54  case SyncScope::OpenCLDevice:
55    return "opencl_device";
56  case SyncScope::OpenCLAllSVMDevices:
57    return "opencl_allsvmdevices";
58  case SyncScope::OpenCLSubGroup:
59    return "opencl_subgroup";
60  }
61  llvm_unreachable("Invalid synch scope");
62}
63
64/// Defines the kind of atomic scope models.
65enum class AtomicScopeModelKind { NoneOpenCL };
66
67/// Defines the interface for synch scope model.
68class AtomicScopeModel {
69public:
70  virtual ~AtomicScopeModel() {}
71  /// Maps language specific synch scope values to internal
72  /// SyncScope enum.
73  virtual SyncScope map(unsigned Sconst = 0;
74
75  /// Check if the compile-time constant synch scope value
76  /// is valid.
77  virtual bool isValid(unsigned Sconst = 0;
78
79  /// Get all possible synch scope values that might be
80  /// encountered at runtime for the current language.
81  virtual ArrayRef<unsignedgetRuntimeValues() const = 0;
82
83  /// If atomic builtin function is called with invalid
84  /// synch scope value at runtime, it will fall back to a valid
85  /// synch scope value returned by this function.
86  virtual unsigned getFallBackValue() const = 0;
87
88  /// Create an atomic scope model by AtomicScopeModelKind.
89  /// \return an empty std::unique_ptr for AtomicScopeModelKind::None.
90  static std::unique_ptr<AtomicScopeModelcreate(AtomicScopeModelKind K);
91};
92
93/// Defines the synch scope model for OpenCL.
94class AtomicScopeOpenCLModel : public AtomicScopeModel {
95public:
96  /// The enum values match the pre-defined macros
97  /// __OPENCL_MEMORY_SCOPE_*, which are used to define memory_scope_*
98  /// enums in opencl-c.h.
99  enum ID {
100    WorkGroup = 1,
101    Device = 2,
102    AllSVMDevices = 3,
103    SubGroup = 4,
104    Last = SubGroup
105  };
106
107  AtomicScopeOpenCLModel() {}
108
109  SyncScope map(unsigned Sconst override {
110    switch (static_cast<ID>(S)) {
111    case WorkGroup:
112      return SyncScope::OpenCLWorkGroup;
113    case Device:
114      return SyncScope::OpenCLDevice;
115    case AllSVMDevices:
116      return SyncScope::OpenCLAllSVMDevices;
117    case SubGroup:
118      return SyncScope::OpenCLSubGroup;
119    }
120    llvm_unreachable("Invalid language synch scope value");
121  }
122
123  bool isValid(unsigned Sconst override {
124    return S >= static_cast<unsigned>(WorkGroup) &&
125           S <= static_cast<unsigned>(Last);
126  }
127
128  ArrayRef<unsignedgetRuntimeValues() const override {
129    static_assert(Last == SubGroup"Does not include all synch scopes");
130    static const unsigned Scopes[] = {
131        static_cast<unsigned>(WorkGroup), static_cast<unsigned>(Device),
132        static_cast<unsigned>(AllSVMDevices), static_cast<unsigned>(SubGroup)};
133    return llvm::makeArrayRef(Scopes);
134  }
135
136  unsigned getFallBackValue() const override {
137    return static_cast<unsigned>(AllSVMDevices);
138  }
139};
140
141inline std::unique_ptr<AtomicScopeModel>
142AtomicScopeModel::create(AtomicScopeModelKind K) {
143  switch (K) {
144  case AtomicScopeModelKind::None:
145    return std::unique_ptr<AtomicScopeModel>{};
146  case AtomicScopeModelKind::OpenCL:
147    return llvm::make_unique<AtomicScopeOpenCLModel>();
148  }
149  llvm_unreachable("Invalid atomic scope model kind");
150}
151}
152
153#endif
154
clang::AtomicScopeModel::map
clang::AtomicScopeModel::isValid
clang::AtomicScopeModel::getRuntimeValues
clang::AtomicScopeModel::getFallBackValue
clang::AtomicScopeModel::create
clang::AtomicScopeOpenCLModel::ID
clang::AtomicScopeOpenCLModel::map
clang::AtomicScopeOpenCLModel::isValid
clang::AtomicScopeOpenCLModel::getRuntimeValues
clang::AtomicScopeOpenCLModel::getFallBackValue
clang::AtomicScopeModel::create