OpenVDB 9.0.0
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
23namespace openvdb {
25namespace OPENVDB_VERSION_NAME {
26
27namespace ax {
28namespace 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
97private:
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()}}) {}
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
220private:
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
ValueT value
Definition: GridBuilder.h:1287
Definition: Exceptions.h:13
A map of unique ids to symbol tables which can be used to represent local variables within a program....
Definition: SymbolTable.h:113
SymbolTable * get(const size_t index)
Get a SymbolTable with a unique index. If it doesn't exist, nullptr is returned.
Definition: SymbolTable.h:154
SymbolTable & globals()
Access to the list of global variables which are always accessible.
Definition: SymbolTable.h:121
SymbolTableBlocks()
Definition: SymbolTable.h:116
std::map< size_t, SymbolTable > MapType
Definition: SymbolTable.h:114
llvm::Value * find(const std::string &name) const
Find a variable within the program starting at the lowest level SymbolTable.
Definition: SymbolTable.h:197
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
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
SymbolTable * getOrInsert(const size_t index)
Get or insert and get a SymbolTable with a unique index.
Definition: SymbolTable.h:145
const SymbolTable & globals() const
Definition: SymbolTable.h:122
bool replace(const std::string &name, llvm::Value *value)
Replace the first occurrance of a variable with a given name with a replacement value....
Definition: SymbolTable.h:208
A symbol table which can be used to represent a single scoped set of a programs variables....
Definition: SymbolTable.h:36
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,...
Definition: SymbolTable.h:69
const MapType & map() const
Access to the underlying map.
Definition: SymbolTable.h:95
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
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
llvm::Value * get(const std::string &name) const
Get a llvm::Value from this symbol table with the given name mapping. It it does not exist,...
Definition: SymbolTable.h:46
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
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h.in:116
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h.in:202