OpenVDB  12.1.0
SymbolTable.h
Go to the documentation of this file.
1 // Copyright Contributors to the OpenVDB Project
2 // SPDX-License-Identifier: Apache-2.0
3 
4 /// @file codegen/SymbolTable.h
5 ///
6 /// @authors Nick Avramoussis
7 ///
8 /// @brief Contains the symbol table which holds mappings of variables names
9 /// to llvm::Values.
10 ///
11 
12 #ifndef OPENVDB_AX_CODEGEN_SYMBOL_TABLE_HAS_BEEN_INCLUDED
13 #define OPENVDB_AX_CODEGEN_SYMBOL_TABLE_HAS_BEEN_INCLUDED
14 
15 #include <openvdb/version.h>
16 #include <openvdb/util/Assert.h>
17 
18 #include "Value.h"
19 
20 #include <string>
21 #include <map>
22 #include <unordered_map>
23 
24 namespace openvdb {
26 namespace OPENVDB_VERSION_NAME {
27 
28 namespace ax {
29 namespace codegen {
30 
31 /// @brief A symbol table which can be used to represent a single scoped set of
32 /// a programs variables. This is simply an unordered map of strings to
33 /// llvm::Values
34 /// @note Consider using llvm's ValueSymbolTable
35 ///
36 template <typename T>
38 {
39  using MapType = std::unordered_map<std::string, T>;
40 
41  SymbolTable() : mMap() {}
42  ~SymbolTable() = default;
43 
44  /// @brief Get a Value from this symbol table with the given name
45  /// mapping. It it does not exist, a nullptr is returned.
46  /// @param name The name of the variable
47  ///
48  inline const T* get(const std::string& name) const
49  {
50  const auto iter = mMap.find(name);
51  if (iter == mMap.end()) return nullptr;
52  return &(iter->second);
53  }
54 
55  /// @brief Returns true if a variable exists in this symbol table with the
56  /// given name.
57  /// @param name The name of the variable
58  ///
59  inline bool exists(const std::string& name) const
60  {
61  const auto iter = mMap.find(name);
62  return (iter != mMap.end());
63  }
64 
65  /// @brief Insert a variable to this symbol table if it does not exist. Returns
66  /// true if successfully, false if a variable already exists with the
67  /// given name.
68  /// @param name The name of the variable
69  /// @param value The llvm::Value corresponding to this variable
70  ///
71  inline bool insert(const std::string& name, const T& value)
72  {
73  const auto iter = mMap.emplace(name, value);
74  return iter.second; // true if inserted, false otherwise
75  }
76 
77  /// @brief Replace a variable in this symbol table. Returns true if the variable
78  /// previously existed and false if not. In both cases, the variable is
79  /// inserted.
80  /// @param name The name of the variable
81  /// @param value The llvm::Value corresponding to this variable
82  ///
83  inline bool replace(const std::string& name, const T& value)
84  {
85  auto iter = mMap.emplace(name, value);
86  const bool inserted = iter.second;
87  if (!inserted) iter.first->second = value;
88  return !inserted;
89  }
90 
91  /// @brief Clear all symbols in this table
92  ///
93  inline void clear() { mMap.clear(); }
94 
95  /// @brief Access to the underlying map
96  ///
97  inline const MapType& map() const { return mMap; }
98 
99 private:
100  MapType mMap;
101 };
102 
103 
104 /// @brief A map of unique ids to symbol tables which can be used to represent local
105 /// variables within a program. New scopes can be added and erased where necessary
106 /// and iterated through using find(). Find assumes that tables are added through
107 /// parented ascending ids.
108 ///
109 /// @note The zero id is used to represent the top block scope, but globals are stored
110 /// separately.
111 /// @note The block symbol table is fairly simple and currently only supports insertion
112 /// by integer ids. Scopes that exist at the same level are expected to be built
113 /// in isolation and erase and re-create the desired ids where necessary.
114 ///
116 {
117  using MapType = std::map<size_t, SymbolTable<Value>>;
118 
120  : mTables({{0, SymbolTable<Value>()}})
121  , mGlobals() {}
122  ~SymbolTableBlocks() = default;
123 
124  /// @brief Access to the list of global variables which are always accessible
125  ///
126  inline SymbolTable<llvm::Value*>& globals() { return mGlobals; }
127  inline const SymbolTable<llvm::Value*>& globals() const { return mGlobals; }
128 
129  /// @brief Erase a given scoped indexed SymbolTable from the list of held
130  /// SymbolTables. Returns true if the table previously existed.
131  ///
132  /// @param index The SymbolTable index to erase
133  ///
134  inline bool erase(const size_t index)
135  {
136  const bool existed = (mTables.find(index) != mTables.end());
137  mTables.erase(index);
138  return existed;
139  }
140 
141  /// @brief Get or insert and get a SymbolTable with a unique index
142  ///
143  /// @param index The SymbolTable index
144  ///
145  inline SymbolTable<Value>* getOrInsert(const size_t index)
146  {
147  return &(mTables[index]);
148  }
149 
150  /// @brief Get a SymbolTable with a unique index. If it doesn't exist, nullptr is returned
151  ///
152  /// @param index The SymbolTable index
153  ///
154  inline SymbolTable<Value>* get(const size_t index)
155  {
156  auto iter = mTables.find(index);
157  if (iter == mTables.end()) return nullptr;
158  return &(iter->second);
159  }
160 
161  /// @brief Find a variable within the program starting at a given table index. If
162  /// the given index does not exist, the next descending index is used.
163  /// @note This function assumes that tables have been added in ascending order
164  /// dictating their nested structure.
165  ///
166  /// @param name The variable name to find
167  /// @param startIndex The start SymbolTable index
168  ///
169  inline const Value* find(const std::string& name, const size_t startIndex) const
170  {
171  // Find the lower bound start index and if necessary, decrement into
172  // the first block where the search will be started. Note that this
173  // is safe as the top scope block 0 will always exist
174 
175  auto it = mTables.lower_bound(startIndex);
176  if (it == mTables.end() || it->first != startIndex) --it;
177 
178  // reverse the iterator (which also make it point to the preceding
179  // value, hence the crement)
180 
181  OPENVDB_ASSERT(it != mTables.end());
182  MapType::const_reverse_iterator iter(++it);
183 
184  for (; iter != mTables.crend(); ++iter) {
185  const Value* value = iter->second.get(name);
186  if (value) return value;
187  }
188 
189  return nullptr;
190  }
191 
192  /// @brief Find a variable within the program starting at the lowest level
193  /// SymbolTable
194  ///
195  /// @param name The variable name to find
196  ///
197  inline const Value* find(const std::string& name) const
198  {
199  return this->find(name, mTables.crbegin()->first);
200  }
201 
202  /// @brief Replace the first occurrance of a variable with a given name with a
203  /// replacement value. Returns true if a replacement occurred.
204  ///
205  /// @param name The variable name to find and replace
206  /// @param value The llvm::Value to replace
207  ///
208  inline bool replace(const std::string& name, Value value)
209  {
210  for (auto it = mTables.rbegin(); it != mTables.rend(); ++it) {
211  if (it->second.get(name)) {
212  it->second.replace(name, value);
213  return true;
214  }
215  }
216  return false;
217  }
218 
219 private:
220  MapType mTables;
221  SymbolTable<llvm::Value*> mGlobals;
222 };
223 
224 } // namespace codegen
225 } // namespace ax
226 } // namespace OPENVDB_VERSION_NAME
227 } // namespace openvdb
228 
229 #endif // OPENVDB_AX_CODEGEN_SYMBOL_TABLE_HAS_BEEN_INCLUDED
230 
std::unordered_map< std::string, llvm::openvdb::v12_1::ax::codegen::Value * > MapType
Definition: SymbolTable.h:39
bool insert(const std::string &name, const T &value)
Insert a variable to this symbol table if it does not exist. Returns true if successfully, false if a variable already exists with the given name.
Definition: SymbolTable.h:71
void clear()
Clear all symbols in this table.
Definition: SymbolTable.h:93
SymbolTable< llvm::Value * > & globals()
Access to the list of global variables which are always accessible.
Definition: SymbolTable.h:126
const Value * find(const std::string &name, const size_t startIndex) const
Find a variable within the program starting at a given table index. If the given index does not exist...
Definition: SymbolTable.h:169
A map of unique ids to symbol tables which can be used to represent local variables within a program...
Definition: SymbolTable.h:115
bool replace(const std::string &name, Value value)
Replace the first occurrance of a variable with a given name with a replacement value. Returns true if a replacement occurred.
Definition: SymbolTable.h:208
bool exists(const std::string &name) const
Returns true if a variable exists in this symbol table with the given name.
Definition: SymbolTable.h:59
const MapType & map() const
Access to the underlying map.
Definition: SymbolTable.h:97
#define OPENVDB_ASSERT(X)
Definition: Assert.h:41
Definition: Exceptions.h:13
SymbolTableBlocks()
Definition: SymbolTable.h:119
bool erase(const size_t index)
Erase a given scoped indexed SymbolTable from the list of held SymbolTables. Returns true if the tabl...
Definition: SymbolTable.h:134
SymbolTable< Value > * getOrInsert(const size_t index)
Get or insert and get a SymbolTable with a unique index.
Definition: SymbolTable.h:145
bool replace(const std::string &name, const T &value)
Replace a variable in this symbol table. Returns true if the variable previously existed and false if...
Definition: SymbolTable.h:83
const Value * find(const std::string &name) const
Find a variable within the program starting at the lowest level SymbolTable.
Definition: SymbolTable.h:197
Intermediate representation of supported AX values.
Intermediate representation wrapper for supported value types in AX as immutable instances.
Definition: Value.h:62
SymbolTable()
Definition: SymbolTable.h:41
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h.in:121
const SymbolTable< llvm::Value * > & globals() const
Definition: SymbolTable.h:127
A symbol table which can be used to represent a single scoped set of a programs variables. This is simply an unordered map of strings to llvm::Values.
Definition: SymbolTable.h:37
std::map< size_t, SymbolTable< Value >> MapType
Definition: SymbolTable.h:117
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h.in:218