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

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

Preliminary steps for removal of superfluous Assigns.

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