OpenVDB 12.0.0
 
Loading...
Searching...
No Matches
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
24namespace openvdb {
26namespace OPENVDB_VERSION_NAME {
27
28namespace ax {
29namespace 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
98private:
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()}}) {}
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
221private:
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
#define OPENVDB_ASSERT(X)
Definition Assert.h:41
Definition Exceptions.h:13
SymbolTable * get(const size_t index)
Get a SymbolTable with a unique index. If it doesn't exist, nullptr is returned.
Definition SymbolTable.h:155
SymbolTable & globals()
Access to the list of global variables which are always accessible.
Definition SymbolTable.h:122
SymbolTableBlocks()
Definition SymbolTable.h:117
std::map< size_t, SymbolTable > MapType
Definition SymbolTable.h:115
llvm::Value * find(const std::string &name) const
Find a variable within the program starting at the lowest level SymbolTable.
Definition SymbolTable.h:198
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
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
SymbolTable * getOrInsert(const size_t index)
Get or insert and get a SymbolTable with a unique index.
Definition SymbolTable.h:146
const SymbolTable & globals() const
Definition SymbolTable.h:123
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:209
A symbol table which can be used to represent a single scoped set of a programs variables....
Definition SymbolTable.h:37
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:70
const MapType & map() const
Access to the underlying map.
Definition SymbolTable.h:96
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
std::unordered_map< std::string, llvm::Value * > MapType
Definition SymbolTable.h:38
SymbolTable()
Definition SymbolTable.h:40
void clear()
Clear all symbols in this table.
Definition SymbolTable.h:92
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:47
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
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition version.h.in:121
#define OPENVDB_USE_VERSION_NAMESPACE
Definition version.h.in:218