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

Last change on this file since 4695 was 4692, checked in by nmedfort, 4 years ago

Temporary check in.

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