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

Last change on this file since 4388 was 4344, checked in by cameron, 5 years ago

If statement support

File size: 6.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_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
36namespace pablo {
37
38class PabloBlock {
39public:
40
41    PabloBlock(SymbolGenerator & symgen)
42    : mZeroes(new Zeroes())
43    , mOnes(new Ones())
44    , mSymbolGenerator(symgen)
45    , mUnary(nullptr, this)
46    , mUnaryWithInt(nullptr, this)
47    , mBinary(nullptr, this)
48    , mTernary(nullptr, this)
49    {
50
51    }
52
53    PabloBlock(PabloBlock & cg)
54    : mZeroes(cg.mZeroes) // inherit the original "Zeroes" variable for simplicity
55    , mOnes(cg.mOnes) // inherit the original "Ones" variable for simplicity
56    , mSymbolGenerator(cg.mSymbolGenerator)
57    , mUnary(&(cg.mUnary), this)
58    , mUnaryWithInt(&(cg.mUnaryWithInt), this)
59    , mBinary(&(cg.mBinary), this)
60    , mTernary(&(cg.mTernary), this)
61    {
62
63    }
64
65    PabloAST * createAdvance(PabloAST * expr, const int shiftAmount);
66
67    inline Zeroes * createZeroes() const {
68        return mZeroes;
69    }
70
71    inline Ones * createOnes() const {
72        return mOnes;
73    }
74
75    Call * createCall(const std::string name);
76
77    inline Assign * createAssign(const std::string prefix, PabloAST * expr, const int outputIndex = -1) {
78        // TODO: should this test whether we've somehow created a var for this prior to
79        // making the assignment?
80        Assign * assign = new Assign(mSymbolGenerator.get_ssa(prefix), expr, outputIndex, &mStatements);
81        mStatements.push_back(assign);
82        return assign;
83    }
84
85    Var * createVar(const std::string name);
86
87    Var * createVar(Assign * assign);
88
89    Var * createVar(Next * next);
90
91    inline PabloAST * createVar(PabloAST * const input) {
92        switch (input->getClassTypeId()) {
93            case PabloAST::ClassTypeId::Assign:
94                return createVar(cast<Assign>(input));
95            case PabloAST::ClassTypeId::Next:
96                return createVar(cast<Next>(input));
97            default:
98                return input;
99        }
100    }
101
102    Next * createNext(Assign * assign, PabloAST * expr);
103
104    PabloAST * createAnd(PabloAST * expr1, PabloAST * expr2);
105
106    PabloAST * createNot(PabloAST * expr);
107
108    PabloAST * createOr(PabloAST * expr1, PabloAST * expr2);
109
110    PabloAST * createXor(PabloAST * expr1, PabloAST * expr2);
111
112    PabloAST * createMatchStar(PabloAST * marker, PabloAST * charclass);
113
114    PabloAST * createScanThru(PabloAST * from, PabloAST * thru);
115
116    PabloAST * createSel(PabloAST * condition, PabloAST * trueExpr, PabloAST * falseExpr);
117
118    inline If * createIf(PabloAST * condition, std::vector<Assign *> && definedVars, PabloBlock && body) {
119        If * statement = new If(condition, std::move(definedVars), std::move(body.statements()), &mStatements);
120        mStatements.push_back(statement);
121        return statement;
122    }
123
124    inline While * createWhile(PabloAST * cond, PabloBlock && body) {
125        While * statement = new While(cond, std::move(body.statements()), &mStatements);
126        mStatements.push_back(statement);
127        return statement;
128    }
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, PabloBlock * parent)
137        : mPredecessor(predecessor)
138        , mCurrentBlock(*parent)
139        {
140
141        }
142
143        template <class Type, typename... Params>
144        inline Type * findOrMake(const PabloAST::ClassTypeId type, Args... args, Params... params) {
145            Key key = std::make_tuple(type, args...);
146            PabloAST * const f = find(key);
147            if (f) {
148                return cast<Type>(f);
149            }
150            Type * const expr = new Type(std::forward<Args>(args)..., std::forward<Params>(params)...);
151            insert(std::move(key), expr);
152            return expr;
153        }
154
155
156        template <class Functor, typename... Params>
157        inline PabloAST * findOrCall(const PabloAST::ClassTypeId type, Args... args, Params... params) {
158            Key key = std::make_tuple(type, args...);
159            PabloAST * const f = find(key);
160            if (f) {
161                return f;
162            }
163            Functor mf(mCurrentBlock);
164            PabloAST * const expr = mf(std::forward<Args>(args)..., std::forward<Params>(params)...);
165            insert(std::move(key), expr);
166            return expr;
167        }
168
169        inline void insert(Key && key, PabloAST * expr) {
170            mMap.insert(std::make_pair(std::move(key), expr));
171        }
172
173        inline PabloAST * find(const Key & key) const {
174            // check this map to see if we have it
175            auto itr = mMap.find(key);
176            if (itr != mMap.end()) {
177                return itr->second;
178            }
179            // check any previous maps to see if it exists
180            auto * pred = mPredecessor;
181            while (pred) {
182                itr = pred->mMap.find(key);
183                if (itr == pred->mMap.end()) {
184                    pred = pred->mPredecessor;
185                    continue;
186                }
187                return itr->second;
188            }
189            return nullptr;
190        }
191
192    private:
193        MapType * const             mPredecessor;
194        PabloBlock &                mCurrentBlock;
195        std::map<Key, PabloAST *>   mMap;
196    };
197
198
199    inline StatementList & statements() {
200        return mStatements;
201    }
202
203    inline const StatementList & statements() const {
204        return mStatements;
205    }
206
207private:       
208    Zeroes * const                                      mZeroes;
209    Ones * const                                        mOnes;
210    SymbolGenerator &                                   mSymbolGenerator;
211    ExpressionMap<PabloAST *>                           mUnary;
212    ExpressionMap<PabloAST *, int>                      mUnaryWithInt;
213    ExpressionMap<PabloAST *, PabloAST *>               mBinary;
214    ExpressionMap<PabloAST *, PabloAST *, PabloAST *>   mTernary;
215    StatementList                                       mStatements;
216};
217
218}
219
220#endif // PS_PABLOS_H
Note: See TracBrowser for help on using the repository browser.