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

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

More work on usedef info.

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