OpenVDB 12.1.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 "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///
36template <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
99private:
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() {}
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
219private:
220 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
#define OPENVDB_ASSERT(X)
Definition Assert.h:41
Intermediate representation of supported AX values.
Intermediate representation wrapper for supported value types in AX as immutable instances.
Definition Value.h:63
Definition Exceptions.h:13
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
SymbolTableBlocks()
Definition SymbolTable.h:119
const Value * find(const std::string &name) const
Find a variable within the program starting at the lowest level SymbolTable.
Definition SymbolTable.h:197
std::map< size_t, SymbolTable< Value > > MapType
Definition SymbolTable.h:117
SymbolTable< llvm::Value * > & globals()
Access to the list of global variables which are always accessible.
Definition SymbolTable.h:126
SymbolTable< Value > * get(const size_t index)
Get a SymbolTable with a unique index. If it doesn't exist, nullptr is returned.
Definition SymbolTable.h:154
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
const SymbolTable< llvm::Value * > & globals() const
Definition SymbolTable.h:127
bool replace(const std::string &name, 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:38
const MapType & map() const
Access to the underlying map.
Definition SymbolTable.h:97
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
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,...
Definition SymbolTable.h:71
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
SymbolTable()
Definition SymbolTable.h:41
const T * get(const std::string &name) const
Get a Value from this symbol table with the given name mapping. It it does not exist,...
Definition SymbolTable.h:48
void clear()
Clear all symbols in this table.
Definition SymbolTable.h:93
std::unordered_map< std::string, T > MapType
Definition SymbolTable.h:39
#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