source: icGREP/icgrep-devel/icgrep/pablo/codegenstate.h @ 4414

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

Minor changes towards maintaining UseDef? information.

File size: 8.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 PS_PABLOS_H
8#define PS_PABLOS_H
9
10#include <pablo/pabloAST.h>
11#include <pablo/pabloAST.h>
12#include <pablo/pe_advance.h>
13#include <pablo/pe_and.h>
14#include <pablo/pe_call.h>
15#include <pablo/pe_matchstar.h>
16#include <pablo/pe_next.h>
17#include <pablo/pe_not.h>
18#include <pablo/pe_ones.h>
19#include <pablo/pe_or.h>
20#include <pablo/pe_scanthru.h>
21#include <pablo/pe_sel.h>
22#include <pablo/pe_string.h>
23#include <pablo/pe_var.h>
24#include <pablo/pe_xor.h>
25#include <pablo/pe_zeroes.h>
26#include <pablo/ps_assign.h>
27#include <pablo/ps_if.h>
28#include <pablo/ps_while.h>
29#include <pablo/symbol_generator.h>
30#include <map>
31#include <vector>
32#include <string>
33#include <array>
34#include <tuple>
35#include <pablo/printer_pablos.h>
36
37namespace pablo {
38
39class PabloBlock : public StatementList {
40    friend class pablo::PabloAST;
41    friend struct OptimizeAnd;
42    friend struct OptimizeOr;
43    friend struct OptimizeSel;
44    friend struct OptimizeXor;
45    friend struct OptimizeNot;
46public:
47
48    inline static PabloBlock & Create() {
49        return *(new PabloBlock());
50    }
51
52    inline static PabloBlock & Create(PabloBlock & predecessor) {
53        return *(new PabloBlock(&predecessor));
54    }
55
56    PabloAST * createAdvance(PabloAST * expr, const int shiftAmount);
57
58    inline Zeroes * createZeroes() const {
59        return mZeroes;
60    }
61
62    inline Ones * createOnes() const {
63        return mOnes;
64    }
65
66    Call * createCall(const std::string name);
67
68    Assign * createAssign(const std::string prefix, PabloAST * expr, const int outputIndex = -1)  {
69        // Note: we cannot just use the findOrMake method to obtain this; an Assign node cannot be considered
70        // unique until we prove it has no Next node associated with it. But the Assign node must be created
71        // before the Next node. Should we create a "Constant" flag for this?
72        Assign * assign = new Assign(expr, outputIndex, mSymbolGenerator->make(prefix), this);
73        push_back(assign);
74        return assign;
75    }
76
77    Var * createVar(const std::string name);
78
79    PabloAST * createVar(const PabloAST * const) {
80        throw std::runtime_error("Var objects should only refer to external Vars (i.e., input basis bit streams). Use Assign objects directly.");
81    }
82
83    Next * createNext(Assign * assign, PabloAST * expr);
84
85    PabloAST * createAnd(PabloAST * expr1, PabloAST * expr2);
86
87    PabloAST * createNot(PabloAST * expr);
88
89    PabloAST * createOr(PabloAST * expr1, PabloAST * expr2);
90
91    PabloAST * createXor(PabloAST * expr1, PabloAST * expr2);
92
93    PabloAST * createMatchStar(PabloAST * marker, PabloAST * charclass);
94
95    PabloAST * createScanThru(PabloAST * from, PabloAST * thru);
96
97    PabloAST * createSel(PabloAST * condition, PabloAST * trueExpr, PabloAST * falseExpr);
98
99    And * createAndImm(PabloAST * expr1, PabloAST * expr2);
100
101    Not * createNotImm(PabloAST * expr);
102
103    Or * createOrImm(PabloAST * expr1, PabloAST * expr2);
104
105    Xor * createXorImm(PabloAST * expr1, PabloAST * expr2);
106
107    Sel * createSelImm(PabloAST * condition, PabloAST * trueExpr, PabloAST * falseExpr);
108
109    inline If * createIf(PabloAST * condition, std::vector<Assign *> && definedVars, PabloBlock & body) {
110        If * statement = new If(condition, std::move(definedVars), body, this);
111        push_back(statement);
112        return statement;
113    }
114
115    inline While * createWhile(PabloAST * cond, PabloBlock & body) {
116        While * statement = new While(cond, body, this);
117        push_back(statement);
118        return statement;
119    }
120
121    template<typename... Args>
122    struct ExpressionMap {
123        enum {N = sizeof...(Args)};
124        typedef ExpressionMap<Args...> MapType;
125        typedef std::tuple<PabloAST::ClassTypeId, Args...> Key;
126
127        inline ExpressionMap(MapType * predecessor)
128        : mPredecessor(predecessor)
129        {
130
131        }
132
133        template <class Type, typename... Params>
134        inline std::pair<Type *, bool> findOrMake(const PabloAST::ClassTypeId type, Args... args, Params... params) {
135            Key key = std::make_tuple(type, args...);
136            PabloAST * const f = find(key);
137            if (f) {
138                return std::make_pair(cast<Type>(f), false);
139            }
140            PabloAST * const expr = new Type(std::forward<Args>(args)..., std::forward<Params>(params)...);
141            mMap.insert(std::make_pair(std::move(key), expr));
142            return std::make_pair(cast<Type>(expr), isa<Statement>(expr));
143        }
144
145        template <class Functor, typename... Params>
146        inline PabloAST * findOrCall(const PabloAST::ClassTypeId type, Args... args, Params... params) {
147            Key key = std::make_tuple(type, args...);
148            PabloAST * const f = find(key);
149            if (f) {
150                return f;
151            }
152            Functor mf;
153            PabloAST * const expr = mf(std::forward<Args>(args)..., std::forward<Params>(params)...);
154            mMap.insert(std::make_pair(std::move(key), expr));
155            return expr;
156        }
157
158        inline bool erase(const PabloAST::ClassTypeId type, Args... args) {
159            Key key = std::make_tuple(type, args...);
160            auto itr = mMap.find(key);
161            if (itr == mMap.end()) {
162                return mPredecessor ? mPredecessor->erase(type, args...) : false;
163            }
164            mMap.erase(itr);
165            return true;
166        }
167
168        inline PabloAST * find(const Key & key) const {
169            // check this map to see if we have it
170            auto itr = mMap.find(key);
171            if (itr != mMap.end()) {
172                return itr->second;
173            }
174            // check any previous maps to see if it exists
175            auto * pred = mPredecessor;
176            while (pred) {
177                itr = pred->mMap.find(key);
178                if (itr == pred->mMap.end()) {
179                    pred = pred->mPredecessor;
180                    continue;
181                }
182                return itr->second;
183            }
184            return nullptr;
185        }
186
187    private:
188        MapType * const             mPredecessor;
189        std::map<Key, PabloAST *>   mMap;
190    };
191
192    inline StatementList & statements() {
193        return *this;
194    }
195
196    inline const StatementList & statements() const {
197        return *this;
198    }
199    inline String * getName(const std::string name) const {
200        return mSymbolGenerator->get(name);
201    }
202    inline String * makeName(const std::string prefix) const {
203        return mSymbolGenerator->make(prefix);
204    }
205protected:
206    PabloBlock()
207    : mZeroes(new Zeroes())
208    , mOnes(new Ones())
209    , mSymbolGenerator(new SymbolGenerator())
210    , mUnary(nullptr)
211    , mUnaryWithInt(nullptr)
212    , mBinary(nullptr)
213    , mTernary(nullptr)
214    {
215
216    }
217
218    PabloBlock(PabloBlock * predecessor)
219    : mZeroes(predecessor->mZeroes) // inherit the original "Zeroes" variable for simplicity
220    , mOnes(predecessor->mOnes) // inherit the original "Ones" variable for simplicity
221    , mSymbolGenerator(predecessor->mSymbolGenerator)
222    , mUnary(&(predecessor->mUnary))
223    , mUnaryWithInt(&(predecessor->mUnaryWithInt))
224    , mBinary(&(predecessor->mBinary))
225    , mTernary(&(predecessor->mTernary))
226    {
227
228    }
229
230    void* operator new (std::size_t size) noexcept {
231        return PabloAST::mAllocator.allocate(size);
232    }
233
234    template<typename Type>
235    inline Type appendIfNew(std::pair<Type, bool> retVal) {
236        if (std::get<1>(retVal)) {
237            push_back(cast<Statement>(std::get<0>(retVal)));
238        }
239        return std::get<0>(retVal);
240    }
241
242private:       
243    Zeroes * const                                      mZeroes;
244    Ones * const                                        mOnes;
245    SymbolGenerator * const                             mSymbolGenerator;
246    ExpressionMap<PabloAST *>                           mUnary;
247    ExpressionMap<PabloAST *, int>                      mUnaryWithInt;
248    ExpressionMap<PabloAST *, PabloAST *>               mBinary;
249    ExpressionMap<PabloAST *, PabloAST *, PabloAST *>   mTernary;
250};
251
252}
253
254#endif // PS_PABLOS_H
Note: See TracBrowser for help on using the repository browser.