OpenVDB  12.0.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 <llvm/IR/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 ///
37 {
38  using MapType = std::unordered_map<std::string, llvm::Value*>;
39 
40  SymbolTable() : mMap() {}
41  ~SymbolTable() = default;
42 
43  /// @brief Get a llvm::Value from this symbol table with the given name
44  /// mapping. It it does not exist, a nullptr is returned.
45  /// @param name The name of the variable
46  ///
47  inline llvm::Value* get(const std::string& name) const
48  {
49  const auto iter = mMap.find(name);
50  if (iter == mMap.end()) return nullptr;
51  return iter->second;
52  }
53 
54  /// @brief Returns true if a variable exists in this symbol table with the
55  /// given name.
56  /// @param name The name of the variable
57  ///
58  inline bool exists(const std::string& name) const
59  {
60  const auto iter = mMap.find(name);
61  return (iter != mMap.end());
62  }
63 
64  /// @brief Insert a variable to this symbol table if it does not exist. Returns
65  /// true if successfully, false if a variable already exists with the
66  /// given name.
67  /// @param name The name of the variable
68  /// @param value The llvm::Value corresponding to this variable
69  ///
70  inline bool insert(const std::string& name, llvm::Value* value)
71  {
72  if (exists(name)) return false;
73  mMap[name] = value;
74  return true;
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, llvm::Value* value)
84  {
85  const bool existed = exists(name);
86  mMap[name] = value;
87  return existed;
88  }
89 
90  /// @brief Clear all symbols in this table
91  ///
92  inline void clear() { mMap.clear(); }
93 
94  /// @brief Access to the underlying map
95  ///
96  inline const MapType& map() const { return mMap; }
97 
98 private:
99  MapType mMap;
100 };
101 
102 
103 /// @brief A map of unique ids to symbol tables which can be used to represent local
104 /// variables within a program. New scopes can be added and erased where necessary
105 /// and iterated through using find(). Find assumes that tables are added through
106 /// parented ascending ids.
107 ///
108 /// @note The zero id is used to represent global variables
109 /// @note The block symbol table is fairly simple and currently only supports insertion
110 /// by integer ids. Scopes that exist at the same level are expected to be built
111 /// in isolation and erase and re-create the desired ids where necessary.
112 ///
114 {
115  using MapType = std::map<size_t, SymbolTable>;
116 
117  SymbolTableBlocks() : mTables({{0, SymbolTable()}}) {}
118  ~SymbolTableBlocks() = default;
119 
120  /// @brief Access to the list of global variables which are always accessible
121  ///
122  inline SymbolTable& globals() { return mTables.at(0); }
123  inline const SymbolTable& globals() const { return mTables.at(0); }
124 
125  /// @brief Erase a given scoped indexed SymbolTable from the list of held
126  /// SymbolTables. Returns true if the table previously existed.
127  /// @note If the zero index is supplied, this function throws a runtime error
128  ///
129  /// @param index The SymbolTable index to erase
130  ///
131  inline bool erase(const size_t index)
132  {
133  if (index == 0) {
134  throw std::runtime_error("Attempted to erase global variables which is disallowed.");
135  }
136 
137  const bool existed = (mTables.find(index) != mTables.end());
138  mTables.erase(index);
139  return existed;
140  }
141 
142  /// @brief Get or insert and get a SymbolTable with a unique index
143  ///
144  /// @param index The SymbolTable index
145  ///
146  inline SymbolTable* getOrInsert(const size_t index)
147  {
148  return &(mTables[index]);
149  }
150 
151  /// @brief Get a SymbolTable with a unique index. If it doesn't exist, nullptr is returned
152  ///
153  /// @param index The SymbolTable index
154  ///
155  inline SymbolTable* get(const size_t index)
156  {
157  auto iter = mTables.find(index);
158  if (iter == mTables.end()) return nullptr;
159  return &(iter->second);
160  }
161 
162  /// @brief Find a variable within the program starting at a given table index. If
163  /// the given index does not exist, the next descending index is used.
164  /// @note This function assumes that tables have been added in ascending order
165  /// dictating their nested structure.
166  ///
167  /// @param name The variable name to find
168  /// @param startIndex The start SymbolTable index
169  ///
170  inline llvm::Value* find(const std::string& name, const size_t startIndex) const
171  {
172  // Find the lower bound start index and if necessary, decrement into
173  // the first block where the search will be started. Note that this
174  // is safe as the global block 0 will always exist
175 
176  auto it = mTables.lower_bound(startIndex);
177  if (it == mTables.end() || it->first != startIndex) --it;
178 
179  // reverse the iterator (which also make it point to the preceding
180  // value, hence the crement)
181 
182  OPENVDB_ASSERT(it != mTables.end());
183  MapType::const_reverse_iterator iter(++it);
184 
185  for (; iter != mTables.crend(); ++iter) {
186  llvm::Value* value = iter->second.get(name);
187  if (value) return value;
188  }
189 
190  return nullptr;
191  }
192 
193  /// @brief Find a variable within the program starting at the lowest level
194  /// SymbolTable
195  ///
196  /// @param name The variable name to find
197  ///
198  inline llvm::Value* find(const std::string& name) const
199  {
200  return this->find(name, mTables.crbegin()->first);
201  }
202 
203  /// @brief Replace the first occurrance of a variable with a given name with a
204  /// replacement value. Returns true if a replacement occurred.
205  ///
206  /// @param name The variable name to find and replace
207  /// @param value The llvm::Value to replace
208  ///
209  inline bool replace(const std::string& name, llvm::Value* value)
210  {
211  for (auto it = mTables.rbegin(); it != mTables.rend(); ++it) {
212  if (it->second.get(name)) {
213  it->second.replace(name, value);
214  return true;
215  }
216  }
217 
218  return false;
219  }
220 
221 private:
222  MapType mTables;
223 };
224 
225 } // namespace codegen
226 } // namespace ax
227 } // namespace OPENVDB_VERSION_NAME
228 } // namespace openvdb
229 
230 #endif // OPENVDB_AX_CODEGEN_SYMBOL_TABLE_HAS_BEEN_INCLUDED
231 
std::map< size_t, SymbolTable > MapType
Definition: SymbolTable.h:115
const MapType & map() const
Access to the underlying map.
Definition: SymbolTable.h:96
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:170
llvm::Value * find(const std::string &name) const
Find a variable within the program starting at the lowest level SymbolTable.
Definition: SymbolTable.h:198
A map of unique ids to symbol tables which can be used to represent local variables within a program...
Definition: SymbolTable.h:113
void clear()
Clear all symbols in this table.
Definition: SymbolTable.h:92
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:131
std::unordered_map< std::string, llvm::Value * > MapType
Definition: SymbolTable.h:38
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:70
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:209
#define OPENVDB_ASSERT(X)
Definition: Assert.h:41
SymbolTable()
Definition: SymbolTable.h:40
SymbolTable & globals()
Access to the list of global variables which are always accessible.
Definition: SymbolTable.h:122
Definition: Exceptions.h:13
const SymbolTable & globals() const
Definition: SymbolTable.h:123
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:83
SymbolTableBlocks()
Definition: SymbolTable.h:117
SymbolTable * getOrInsert(const size_t index)
Get or insert and get a SymbolTable with a unique index.
Definition: SymbolTable.h:146
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h.in:121
bool exists(const std::string &name) const
Returns true if a variable exists in this symbol table with the given name.
Definition: SymbolTable.h:58
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:36
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h.in:218