OpenVDB  9.0.1
SymbolTable.h
Go to the documentation of this file.
1 // Copyright Contributors to the OpenVDB Project
2 // SPDX-License-Identifier: MPL-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 
17 #include <llvm/IR/Value.h>
18 
19 #include <string>
20 #include <map>
21 #include <unordered_map>
22 
23 namespace openvdb {
25 namespace OPENVDB_VERSION_NAME {
26 
27 namespace ax {
28 namespace codegen {
29 
30 /// @brief A symbol table which can be used to represent a single scoped set of
31 /// a programs variables. This is simply an unordered map of strings to
32 /// llvm::Values
33 /// @note Consider using llvm's ValueSymbolTable
34 ///
36 {
37  using MapType = std::unordered_map<std::string, llvm::Value*>;
38 
39  SymbolTable() : mMap() {}
40  ~SymbolTable() = default;
41 
42  /// @brief Get a llvm::Value from this symbol table with the given name
43  /// mapping. It it does not exist, a nullptr is returned.
44  /// @param name The name of the variable
45  ///
46  inline llvm::Value* get(const std::string& name) const
47  {
48  const auto iter = mMap.find(name);
49  if (iter == mMap.end()) return nullptr;
50  return iter->second;
51  }
52 
53  /// @brief Returns true if a variable exists in this symbol table with the
54  /// given name.
55  /// @param name The name of the variable
56  ///
57  inline bool exists(const std::string& name) const
58  {
59  const auto iter = mMap.find(name);
60  return (iter != mMap.end());
61  }
62 
63  /// @brief Insert a variable to this symbol table if it does not exist. Returns
64  /// true if successfully, false if a variable already exists with the
65  /// given name.
66  /// @param name The name of the variable
67  /// @param value The llvm::Value corresponding to this variable
68  ///
69  inline bool insert(const std::string& name, llvm::Value* value)
70  {
71  if (exists(name)) return false;
72  mMap[name] = value;
73  return true;
74  }
75 
76  /// @brief Replace a variable in this symbol table. Returns true if the variable
77  /// previously existed and false if not. In both cases, the variable is
78  /// inserted.
79  /// @param name The name of the variable
80  /// @param value The llvm::Value corresponding to this variable
81  ///
82  inline bool replace(const std::string& name, llvm::Value* value)
83  {
84  const bool existed = exists(name);
85  mMap[name] = value;
86  return existed;
87  }
88 
89  /// @brief Clear all symbols in this table
90  ///
91  inline void clear() { mMap.clear(); }
92 
93  /// @brief Access to the underlying map
94  ///
95  inline const MapType& map() const { return mMap; }
96 
97 private:
98  MapType mMap;
99 };
100 
101 
102 /// @brief A map of unique ids to symbol tables which can be used to represent local
103 /// variables within a program. New scopes can be added and erased where necessary
104 /// and iterated through using find(). Find assumes that tables are added through
105 /// parented ascending ids.
106 ///
107 /// @note The zero id is used to represent global variables
108 /// @note The block symbol table is fairly simple and currently only supports insertion
109 /// by integer ids. Scopes that exist at the same level are expected to be built
110 /// in isolation and erase and re-create the desired ids where necessary.
111 ///
113 {
114  using MapType = std::map<size_t, SymbolTable>;
115 
116  SymbolTableBlocks() : mTables({{0, SymbolTable()}}) {}
117  ~SymbolTableBlocks() = default;
118 
119  /// @brief Access to the list of global variables which are always accessible
120  ///
121  inline SymbolTable& globals() { return mTables.at(0); }
122  inline const SymbolTable& globals() const { return mTables.at(0); }
123 
124  /// @brief Erase a given scoped indexed SymbolTable from the list of held
125  /// SymbolTables. Returns true if the table previously existed.
126  /// @note If the zero index is supplied, this function throws a runtime error
127  ///
128  /// @param index The SymbolTable index to erase
129  ///
130  inline bool erase(const size_t index)
131  {
132  if (index == 0) {
133  throw std::runtime_error("Attempted to erase global variables which is disallowed.");
134  }
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* 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* 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 llvm::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 global 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  assert(it != mTables.end());
182  MapType::const_reverse_iterator iter(++it);
183 
184  for (; iter != mTables.crend(); ++iter) {
185  llvm::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 llvm::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, llvm::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 
217  return false;
218  }
219 
220 private:
221  MapType mTables;
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 
SymbolTable & globals()
Access to the list of global variables which are always accessible.
Definition: SymbolTable.h:121
std::unordered_map< std::string, llvm::Value * > MapType
Definition: SymbolTable.h:37
SymbolTable()
Definition: SymbolTable.h:39
void clear()
Clear all symbols in this table.
Definition: SymbolTable.h:91
const MapType & map() const
Access to the underlying map.
Definition: SymbolTable.h:95
Definition: Exceptions.h:13
bool replace(const std::string &name, llvm::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 replace(const std::string &name, llvm::Value *value)
Replace a variable in this symbol table. Returns true if the variable previously existed and false if...
Definition: SymbolTable.h:82
ValueT value
Definition: GridBuilder.h:1287
llvm::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
llvm::Value * find(const std::string &name) const
Find a variable within the program starting at the lowest level SymbolTable.
Definition: SymbolTable.h:197
const SymbolTable & globals() const
Definition: SymbolTable.h:122
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:35
bool exists(const std::string &name) const
Returns true if a variable exists in this symbol table with the given name.
Definition: SymbolTable.h:57
SymbolTable * getOrInsert(const size_t index)
Get or insert and get a SymbolTable with a unique index.
Definition: SymbolTable.h:145
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:130
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h.in:116
bool insert(const std::string &name, llvm::Value *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:69
std::map< size_t, SymbolTable > MapType
Definition: SymbolTable.h:114
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h.in:202
SymbolTableBlocks()
Definition: SymbolTable.h:116
A map of unique ids to symbol tables which can be used to represent local variables within a program...
Definition: SymbolTable.h:112