source: icGREP/icgrep-devel/icgrep/pablo/pabloAST.h @ 4443

Last change on this file since 4443 was 4443, checked in by nmedfort, 5 years ago

Temporary check in.

File size: 12.0 KB
Line 
1/*
2 *  Copyright (c) 2014 International Characters.
3 *  This software is licensed to the public under the Open Software License 3.0.
4 *  icgrep is a trademark of International Characters.
5 */
6
7#ifndef PE_PabloAST_H
8#define PE_PabloAST_H
9
10#include <llvm/Support/Casting.h>
11#include <llvm/Support/Compiler.h>
12#include <boost/container/flat_set.hpp>
13#include <slab_allocator.h>
14#include <iterator>
15#include <unordered_map>
16
17using namespace llvm;
18
19namespace pablo {
20
21class PabloBlock;
22class String;
23
24class PabloAST {
25    friend class Statement;
26    friend class Var;
27    friend class If;
28    friend class While;
29    friend class PabloBlock;
30    friend class SymbolGenerator;
31public:
32
33    using Users = boost::container::flat_set<PabloAST *>;
34    using user_iterator = Users::iterator;
35    using const_user_iterator = Users::const_iterator;
36
37    typedef SlabAllocator<PabloAST *> Allocator;
38    enum class ClassTypeId : unsigned {
39        Advance
40        , And
41        , Assign
42        , Call
43        , If
44        , Integer
45        , MatchStar
46        , Next
47        , Not
48        , Ones
49        , Or
50        , ScanThru
51        , Sel
52        , String
53        , Var
54        , While
55        , Xor
56        , Zeroes
57        , Block
58    };
59    inline ClassTypeId getClassTypeId() const {
60        return mClassTypeId;
61    }
62
63    inline static void release_memory() {
64        mAllocator.release_memory();
65    }
66
67    inline user_iterator user_begin() {
68        return mUsers.begin();
69    }
70
71    inline user_iterator user_end() {
72        return mUsers.end();
73    }
74
75    inline const_user_iterator user_begin() const {
76        return mUsers.cbegin();
77    }
78
79    inline const_user_iterator user_end() const {
80        return mUsers.cend();
81    }
82
83    inline Users & users() {
84        return mUsers;
85    }
86
87    inline const Users & users() const {
88        return mUsers;
89    }
90
91    void replaceAllUsesWith(PabloAST * expr);
92
93    inline Users::size_type getNumUses() const {
94        return mUsers.size();
95    }
96
97    void* operator new (std::size_t size) noexcept {
98        return mAllocator.allocate(size);
99    }
100protected:
101    inline PabloAST(const ClassTypeId id)
102    : mClassTypeId(id)
103    {
104
105    }
106    inline void addUser(PabloAST * user) {
107        assert (user);
108        mUsers.insert(user);
109    }
110    inline void removeUser(PabloAST * user) {
111        assert (user);
112        auto pos = mUsers.find(user);
113        if (LLVM_UNLIKELY(pos == mUsers.end())) {
114            return;
115        }
116        mUsers.erase(pos);
117    }
118    virtual ~PabloAST() {
119        mUsers.clear();
120    }
121    static Allocator        mAllocator;
122private:
123    const ClassTypeId       mClassTypeId;
124    Users                   mUsers;
125};
126
127bool equals(const PabloAST * expr1, const PabloAST *expr2);
128
129class StatementList;
130
131class String;
132
133class Statement : public PabloAST {
134    friend class StatementList;
135    friend class If;
136    friend class While;
137    friend class Simplifier;
138    friend class PabloBlock;
139public:
140    static inline bool classof(const PabloAST * e) {
141        switch (e->getClassTypeId()) {
142            case PabloAST::ClassTypeId::String:
143            case PabloAST::ClassTypeId::Integer:
144            case PabloAST::ClassTypeId::Zeroes:
145            case PabloAST::ClassTypeId::Ones:
146            case PabloAST::ClassTypeId::Var:
147                return false;
148            default:
149                return true;
150        }
151    }
152    static inline bool classof(const Statement *) {
153        return true;
154    }
155    static inline bool classof(const void *) {
156        return false;
157    }
158
159    inline void replaceUsesOfWith(const PabloAST * const from, PabloAST * const to) {
160        for (unsigned i = 0; i != getNumOperands(); ++i) {
161            if (getOperand(i) == from) {
162                setOperand(i, to);
163            }
164        }
165    }
166
167    inline PabloAST * getOperand(const unsigned index) const {
168        assert (index < getNumOperands());
169        return mOperand[index];
170    }
171
172    void setOperand(const unsigned index, PabloAST * const value);
173
174    inline unsigned getNumOperands() const {
175        return mOperands;
176    }
177
178    void insertBefore(Statement * const statement);
179    void insertAfter(Statement * const statement);
180    Statement * removeFromParent();
181    Statement * eraseFromParent(const bool recursively = false);
182    Statement * replaceWith(PabloAST * const expr, const bool rename = true);
183
184    inline const String * getName() const {
185        return mName;
186    }
187    inline Statement * getNextNode() const {
188        return mNext;
189    }
190    inline Statement * getPrevNode() const {
191        return mPrev;
192    }
193    inline PabloBlock * getParent() const {
194        return mParent;
195    }
196    virtual ~Statement() {}
197protected:
198    Statement(const ClassTypeId id, std::initializer_list<PabloAST *> operands, const String * const name, PabloBlock * const parent)
199    : PabloAST(id)
200    , mName(name)
201    , mNext(nullptr)
202    , mPrev(nullptr)
203    , mParent(parent)
204    , mOperands(operands.size())
205    , mOperand(mAllocator.allocate(mOperands * sizeof(PabloAST *)))
206    {
207        unsigned i = 0;
208        for (PabloAST * const op : operands) {
209            mOperand[i++] = op;
210            op->addUser(this);
211        }
212    }
213    inline void setName(const String * const name) {
214        mName = name;
215    }
216protected:   
217    const String *              mName;
218    Statement *                 mNext;
219    Statement *                 mPrev;
220    PabloBlock *                mParent;
221    const unsigned              mOperands;
222    // If we knew prior to construction how many operands were needed, we could
223    // eliminate the mOperand pointer and simply use this[1] instead.
224    PabloAST **                 mOperand;
225};
226
227class StatementList {
228    friend class Statement;
229public:
230    class iterator: public std::iterator<std::forward_iterator_tag, Statement> {
231    public:
232        iterator(): mCurrent(nullptr) {}
233
234        iterator(Statement* base): mCurrent(base) {}
235
236        iterator(const iterator& other): mCurrent(other.mCurrent) {}
237
238        const iterator& operator=(const iterator& other) {
239            mCurrent = other.mCurrent; return other;
240        }
241
242        inline iterator& operator++() {
243            assert (mCurrent);
244            mCurrent = mCurrent->mNext;
245            return *this;
246        }
247
248        iterator  operator++(int) {
249            iterator tmp(*this);
250            ++(*this);
251            return tmp;
252        }
253
254        bool operator==(const iterator& other) const {
255            return  mCurrent == other.mCurrent;
256        }
257
258        bool operator!=(const iterator& other) const {
259            return  mCurrent != other.mCurrent;
260        }
261
262        Statement* operator*() {return mCurrent;}
263        Statement* operator->(){return mCurrent;}
264
265    private:
266        Statement * mCurrent;
267        friend class const_iterator;
268    };
269
270    class const_iterator: public std::iterator<std::forward_iterator_tag, Statement> {
271    public:
272        const_iterator(): mCurrent(nullptr) {}
273        const_iterator(const Statement* base): mCurrent(base) {}
274        const_iterator(const const_iterator& other): mCurrent(other.mCurrent) {}
275        const const_iterator& operator=(const const_iterator& other) {mCurrent = other.mCurrent; return other;}
276
277        inline const_iterator& operator++() {
278            assert (mCurrent);
279            mCurrent = mCurrent->mNext;
280            return *this;
281        }
282
283        const_iterator  operator++(int) {
284            const_iterator tmp(*this);
285            ++(*this);
286            return tmp;
287        }
288
289        bool operator==(const const_iterator & other) const {
290            return  mCurrent == other.mCurrent;
291        }
292        bool operator!=(const const_iterator & other) const {
293            return  mCurrent != other.mCurrent;
294        }
295
296        const Statement* operator*() {return mCurrent;}
297        const Statement* operator->(){return mCurrent;}
298
299    private:
300        const Statement * mCurrent;
301        friend struct iterator;
302    };
303
304    class reverse_iterator: public std::iterator<std::forward_iterator_tag, Statement> {
305    public:
306        reverse_iterator(): mCurrent(nullptr) {}
307
308        reverse_iterator(Statement* base): mCurrent(base) {}
309
310        reverse_iterator(const reverse_iterator& other): mCurrent(other.mCurrent) {}
311
312        const reverse_iterator& operator=(const reverse_iterator& other) {
313            mCurrent = other.mCurrent; return other;
314        }
315
316        inline reverse_iterator& operator++() {
317            assert (mCurrent);
318            mCurrent = mCurrent->mPrev;
319            return *this;
320        }
321
322        reverse_iterator operator++(int) {
323            reverse_iterator tmp(*this);
324            ++(*this);
325            return tmp;
326        }
327
328        bool operator==(const reverse_iterator& other) const {
329            return  mCurrent == other.mCurrent;
330        }
331
332        bool operator!=(const reverse_iterator& other) const {
333            return  mCurrent != other.mCurrent;
334        }
335
336        Statement* operator*() {return mCurrent;}
337        Statement* operator->(){return mCurrent;}
338
339    private:
340        Statement * mCurrent;
341        friend class const_reverse_iterator;
342    };
343
344    class const_reverse_iterator: public std::iterator<std::forward_iterator_tag, Statement> {
345    public:
346        const_reverse_iterator(): mCurrent(nullptr) {}
347        const_reverse_iterator(const Statement* base): mCurrent(base) {}
348        const_reverse_iterator(const const_reverse_iterator& other): mCurrent(other.mCurrent) {}
349        const const_reverse_iterator& operator=(const const_reverse_iterator& other) {mCurrent = other.mCurrent; return other;}
350
351        inline const_reverse_iterator& operator++() {
352            assert (mCurrent);
353            mCurrent = mCurrent->mPrev;
354            return *this;
355        }
356
357        const_reverse_iterator  operator++(int) {
358            const_reverse_iterator tmp(*this);
359            ++(*this);
360            return tmp;
361        }
362
363        bool operator==(const const_reverse_iterator & other) const {
364            return  mCurrent == other.mCurrent;
365        }
366        bool operator!=(const const_reverse_iterator & other) const {
367            return  mCurrent != other.mCurrent;
368        }
369
370        const Statement* operator*() {return mCurrent;}
371        const Statement* operator->(){return mCurrent;}
372
373    private:
374        const Statement * mCurrent;
375        friend struct iterator;
376    };
377
378public:
379
380    StatementList()
381    : mInsertionPoint(nullptr)
382    , mFirst(nullptr)
383    , mLast(nullptr)
384    {
385
386    }
387
388    StatementList(StatementList && other)
389    : mFirst(other.mFirst)
390    , mLast(other.mLast)
391    {
392        other.mFirst = nullptr;
393        other.mLast = nullptr;
394    }
395
396    iterator begin() {
397        return iterator(mFirst);
398    }
399
400    iterator end() {
401        return iterator(nullptr);
402    }
403
404    reverse_iterator rbegin() {
405        return reverse_iterator(mLast);
406    }
407
408    reverse_iterator rend() {
409        return reverse_iterator(nullptr);
410    }
411
412    const_iterator begin() const {
413        return const_iterator(mFirst);
414    }
415
416    const_iterator end() const {
417        return const_iterator(nullptr);
418    }
419
420    const_reverse_iterator rbegin() const {
421        return const_reverse_iterator(mLast);
422    }
423
424    const_reverse_iterator rend() const {
425        return const_reverse_iterator(nullptr);
426    }
427
428    const_iterator cbegin() const {
429        return const_iterator(mFirst);
430    }
431
432    const_iterator cend() const {
433        return const_iterator(nullptr);
434    }
435
436    const_reverse_iterator crbegin() const {
437        return const_reverse_iterator(mLast);
438    }
439
440    const_reverse_iterator crend() const {
441        return const_reverse_iterator(nullptr);
442    }
443
444    inline Statement * front() const {
445        return mFirst;
446    }
447
448    inline Statement * back() const {
449        return mLast;
450    }
451
452    inline void setInsertPoint(Statement * const statement) {
453        mInsertionPoint = statement;
454    }
455
456    inline void setInsertPoint(StatementList * const list) {
457        mInsertionPoint = list->back();
458    }
459
460    inline Statement * getInsertPoint() const {
461        return mInsertionPoint;
462    }
463
464    void insert(Statement * const statement);
465
466    ~StatementList();
467
468private:
469
470    Statement   * mInsertionPoint;
471    Statement   * mFirst;
472    Statement   * mLast;   
473};
474
475}
476
477#endif // PE_PabloAST_H
478
479
480
Note: See TracBrowser for help on using the repository browser.