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

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

Possible fix for segfault issue. CC seems to be generating the same charclass multiple times.

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