source: icGREP/icgrep-devel/icgrep/pablo/codegenstate.cpp @ 5160

Last change on this file since 5160 was 5160, checked in by nmedfort, 3 years ago

Initial work for incorporating Types into Pablo AST.

File size: 23.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#include <pablo/codegenstate.h>
8#include <iostream>
9#include <pablo/printer_pablos.h>
10
11namespace pablo {
12
13inline PabloAST * PabloBlock::renameNonNamedNode(PabloAST * expr, const std::string && prefix) {
14    if (Statement * stmt = dyn_cast<Statement>(expr)) {
15        if (stmt->getName()->isGenerated()) {
16            stmt->setName(makeName(prefix, false));
17        }
18    }
19    return expr;
20}
21
22void PabloBlock::insert(Statement * const statement) {
23    assert (statement);
24    if (LLVM_UNLIKELY(mInsertionPoint == nullptr)) {
25        if (mFirst) {
26            statement->insertBefore(mFirst);
27        } else {
28            statement->removeFromParent();
29            statement->mParent = this;
30            mFirst = mLast = statement;
31        }
32    } else if (LLVM_LIKELY(statement != mInsertionPoint)) {
33        statement->insertAfter(mInsertionPoint);
34        mLast = (mLast == mInsertionPoint) ? statement : mLast;
35        assert (statement->mPrev == mInsertionPoint);
36    }
37    mInsertionPoint = statement;
38}
39
40/// UNARY CREATE FUNCTIONS
41
42Assign * PabloBlock::createAssign(const std::string && prefix, PabloAST * const expr)  {
43    assert ("Assign expression cannot be null!" && expr);
44    return insertAtInsertionPoint(new Assign(expr, makeName(prefix, false)));
45}
46
47PabloAST * PabloBlock::createAdvance(PabloAST * expr, PabloAST * shiftAmount) {
48    PabloAST::throwIfNonMatchingType(expr, PabloType::Stream);
49    if (isa<Zeroes>(expr) || cast<Integer>(shiftAmount)->value() == 0) {
50        return expr;
51    }
52    return insertAtInsertionPoint(new Advance(expr, shiftAmount, makeName("advance")));
53}
54
55PabloAST * PabloBlock::createAdvance(PabloAST * expr, PabloAST * shiftAmount, const std::string prefix) {
56    PabloAST::throwIfNonMatchingType(expr, PabloType::Stream);
57    if (isa<Zeroes>(expr) || cast<Integer>(shiftAmount)->value() == 0) {
58        return expr;
59    }
60    return insertAtInsertionPoint(new Advance(expr, shiftAmount, makeName(prefix, false)));
61}
62
63PabloAST * PabloBlock::createAdvance(PabloAST * expr, const Integer::Type shiftAmount) {
64    PabloAST::throwIfNonMatchingType(expr, PabloType::Stream);
65    if (isa<Zeroes>(expr) || shiftAmount == 0) {
66        return expr;
67    }
68    return insertAtInsertionPoint(new Advance(expr, getInteger(shiftAmount), makeName("advance")));
69}
70
71PabloAST * PabloBlock::createAdvance(PabloAST * expr, const Integer::Type shiftAmount, const std::string prefix) {
72    PabloAST::throwIfNonMatchingType(expr, PabloType::Stream);
73    if (isa<Zeroes>(expr) || shiftAmount == 0) {
74        return renameNonNamedNode(expr, std::move(prefix));
75    }
76    return insertAtInsertionPoint(new Advance(expr, getInteger(shiftAmount), makeName(prefix, false)));
77}
78
79Count * PabloBlock::createCount(const std::string counterName, PabloAST * const expr)  {
80    PabloAST::throwIfNonMatchingType(expr, PabloType::Stream);
81    return insertAtInsertionPoint(new Count(expr, makeName(counterName, false)));
82}
83   
84
85PabloAST * PabloBlock::createLookahead(PabloAST * expr, PabloAST * shiftAmount) {
86    if (isa<Zeroes>(expr) || cast<Integer>(shiftAmount)->value() == 0) {
87        return expr;
88    }
89    return insertAtInsertionPoint(new Lookahead(expr, shiftAmount, makeName("lookahead")));
90}
91
92PabloAST * PabloBlock::createLookahead(PabloAST * expr, PabloAST * shiftAmount, const std::string prefix) {
93    PabloAST::throwIfNonMatchingType(expr, PabloType::Stream);
94    if (isa<Zeroes>(expr) || cast<Integer>(shiftAmount)->value() == 0) {
95        return expr;
96    }
97    return insertAtInsertionPoint(new Lookahead(expr, shiftAmount, makeName(prefix, false)));
98}
99
100PabloAST * PabloBlock::createLookahead(PabloAST * expr, const Integer::Type shiftAmount) {
101    PabloAST::throwIfNonMatchingType(expr, PabloType::Stream);
102    if (isa<Zeroes>(expr) || shiftAmount == 0) {
103        return expr;
104    }
105    return insertAtInsertionPoint(new Lookahead(expr, getInteger(shiftAmount), makeName("lookahead")));
106}
107
108PabloAST * PabloBlock::createLookahead(PabloAST * expr, const Integer::Type shiftAmount, const std::string prefix) {
109    PabloAST::throwIfNonMatchingType(expr, PabloType::Stream);
110    if (isa<Zeroes>(expr) || shiftAmount == 0) {
111        return renameNonNamedNode(expr, std::move(prefix));
112    }
113    return insertAtInsertionPoint(new Lookahead(expr, getInteger(shiftAmount), makeName(prefix, false)));
114}
115
116Call * PabloBlock::createCall(PabloAST * prototype, const std::vector<PabloAST *> &) {
117    assert (prototype);
118    return insertAtInsertionPoint(new Call(prototype));
119}
120
121
122PabloAST * PabloBlock::createNot(PabloAST * expr) {
123    assert (expr);
124    PabloAST::throwIfNonMatchingType(expr, PabloType::Stream);
125    if (isa<Ones>(expr)) {
126        return createZeroes(expr->getType());
127    }
128    else if (isa<Zeroes>(expr)){
129        return createOnes(expr->getType());
130    }
131    else if (Not * not1 = dyn_cast<Not>(expr)) {
132        return not1->getOperand(0);
133    }
134    return insertAtInsertionPoint(new Not(expr, makeName("not_")));
135}
136
137PabloAST * PabloBlock::createNot(PabloAST * expr, const std::string prefix) {
138    assert (expr);
139    PabloAST::throwIfNonMatchingType(expr, PabloType::Stream);
140    if (isa<Ones>(expr)) {
141        return createZeroes(expr->getType());
142    }
143    else if (isa<Zeroes>(expr)){
144        return createOnes(expr->getType());
145    }
146    else if (Not * not1 = dyn_cast<Not>(expr)) {       
147        return renameNonNamedNode(not1->getOperand(0), std::move(prefix));
148    }
149    return insertAtInsertionPoint(new Not(expr, makeName(prefix, false)));
150}
151
152Var * PabloBlock::createVar(PabloAST * name, const PabloType * const type) {
153    assert (name);
154    return new Var(name, type);
155}
156
157PabloAST * PabloBlock::createInFile(PabloAST * expr) {
158    assert (expr);
159    return insertAtInsertionPoint(new InFile(expr, makeName("inFile_")));
160}
161
162PabloAST * PabloBlock::createInFile(PabloAST * expr, const std::string prefix) {
163    assert (expr);
164    return insertAtInsertionPoint(new InFile(expr, makeName(prefix, false)));
165}
166
167
168PabloAST * PabloBlock::createAtEOF(PabloAST * expr) {
169    assert (expr);
170    return insertAtInsertionPoint(new AtEOF(expr, makeName("atEOF_")));
171}
172
173PabloAST * PabloBlock::createAtEOF(PabloAST * expr, const std::string prefix) {
174    assert (expr);
175    return insertAtInsertionPoint(new AtEOF(expr, makeName(prefix, false)));
176}
177   
178   
179    /// BINARY CREATE FUNCTIONS
180
181Next * PabloBlock::createNext(Assign * assign, PabloAST * expr) {
182    assert (assign && expr);
183    return insertAtInsertionPoint(new Next(assign, expr));
184}
185
186PabloAST * PabloBlock::createMatchStar(PabloAST * marker, PabloAST * charclass) {
187    throwIfNonMatchingTypes(marker, charclass);
188    if (isa<Zeroes>(marker) || isa<Zeroes>(charclass)) {
189        return marker;
190    }
191    return insertAtInsertionPoint(new MatchStar(marker, charclass, makeName("matchstar")));
192}
193
194PabloAST * PabloBlock::createMatchStar(PabloAST * marker, PabloAST * charclass, const std::string prefix) {   
195    throwIfNonMatchingTypes(marker, charclass);
196    throwIfNonMatchingType(marker, PabloType::Stream);
197    if (isa<Zeroes>(marker) || isa<Zeroes>(charclass)) {
198        return renameNonNamedNode(marker, std::move(prefix));
199    }
200    return insertAtInsertionPoint(new MatchStar(marker, charclass, makeName(prefix, false)));
201}
202
203PabloAST * PabloBlock::createScanThru(PabloAST * from, PabloAST * thru) {   
204    throwIfNonMatchingTypes(from, thru);
205    throwIfNonMatchingType(from, PabloType::Stream);
206    if (isa<Zeroes>(from) || isa<Zeroes>(thru)) {
207        return from;
208    }
209    return insertAtInsertionPoint(new ScanThru(from, thru, makeName("scanthru")));
210}
211
212PabloAST * PabloBlock::createScanThru(PabloAST * from, PabloAST * thru, const std::string prefix) {
213    throwIfNonMatchingTypes(from, thru);
214    throwIfNonMatchingType(from, PabloType::Stream);
215    if (isa<Zeroes>(from) || isa<Zeroes>(thru)) {       
216        return renameNonNamedNode(from, std::move(prefix));
217    }
218    return insertAtInsertionPoint(new ScanThru(from, thru, makeName(prefix, false)));
219}
220
221template<typename Type>
222static inline Type * isBinary(PabloAST * expr) {
223    if (isa<Type>(expr) && cast<Type>(expr)->getNumOperands() == 2) {
224        return cast<Type>(expr);
225    }
226    return nullptr;
227}
228
229PabloAST * PabloBlock::createAnd(PabloAST * expr1, PabloAST * expr2) {
230    throwIfNonMatchingTypes(expr1, expr2);
231    if (isa<Zeroes>(expr2) || isa<Ones>(expr1)) {
232        return expr2;
233    } else if (isa<Zeroes>(expr1) || isa<Ones>(expr2) || equals(expr1, expr2)){
234        return expr1;
235    } else if (Not * not1 = dyn_cast<Not>(expr1)) {
236        if (Not * not2 = dyn_cast<Not>(expr2)) {
237            return createNot(createOr(not1->getOperand(0), not2->getOperand(0)));
238        } else if (equals(not1->getOperand(0), expr2)) {
239            return createZeroes(expr1->getType());
240        }
241    } else if (Not * not2 = dyn_cast<Not>(expr2)) {
242        if (equals(expr1, not2->getOperand(0))) {
243            return createZeroes(expr1->getType());
244        }
245    } else if (Or * or1 = isBinary<Or>(expr1)) {
246        if (equals(or1->getOperand(0), expr2) || equals(or1->getOperand(1), expr2)) {
247            return expr2;
248        }
249    } else if (Or * or2 = isBinary<Or>(expr2)) {
250        if (equals(or2->getOperand(0), expr1) || equals(or2->getOperand(1), expr1)) {
251            return expr1;
252        }
253    }
254    return insertAtInsertionPoint(new And(expr1->getType(), expr1, expr2, makeName("and_")));
255}
256
257PabloAST * PabloBlock::createAnd(PabloAST * expr1, PabloAST * expr2, const std::string prefix) {
258    throwIfNonMatchingTypes(expr1, expr2);
259    if (isa<Zeroes>(expr2) || isa<Ones>(expr1)) {
260        return renameNonNamedNode(expr2, std::move(prefix));
261    }
262    else if (isa<Zeroes>(expr1) || isa<Ones>(expr2) || equals(expr1, expr2)){
263        return renameNonNamedNode(expr1, std::move(prefix));
264    } else if (Not * not1 = dyn_cast<Not>(expr1)) {
265        if (Not * not2 = dyn_cast<Not>(expr2)) {
266            return createNot(createOr(not1->getOperand(0), not2->getOperand(0)), prefix);
267        }
268        else if (equals(not1->getOperand(0), expr2)) {
269            return createZeroes(expr1->getType());
270        }
271    } else if (Not * not2 = dyn_cast<Not>(expr2)) {
272        if (equals(expr1, not2->getOperand(0))) {
273            return createZeroes(expr1->getType());
274        }
275    } else if (Or * or1 = isBinary<Or>(expr1)) {
276        if (equals(or1->getOperand(0), expr2) || equals(or1->getOperand(1), expr2)) {
277            return expr2;
278        }
279    } else if (Or * or2 = isBinary<Or>(expr2)) {
280        if (equals(or2->getOperand(0), expr1) || equals(or2->getOperand(1), expr1)) {
281            return expr1;
282        }
283    }
284    return insertAtInsertionPoint(new And(expr1->getType(), expr1, expr2, makeName(prefix, false)));
285}
286
287And * PabloBlock::createAnd(const PabloType * const type, const unsigned reserved) {
288    return insertAtInsertionPoint(new And(type, reserved, makeName("and_")));
289}
290
291And * PabloBlock::createAnd(const PabloType * const type, const unsigned reserved, const std::string prefix) {
292    return insertAtInsertionPoint(new And(type, reserved, makeName(prefix, false)));
293}
294
295And * PabloBlock::createAnd(const PabloType * const type, std::vector<PabloAST *>::iterator begin, std::vector<PabloAST *>::iterator end) {
296    return insertAtInsertionPoint(new And(type, begin, end, makeName("and_")));
297}
298
299And * PabloBlock::createAnd(const PabloType * const type, Variadic::iterator begin, Variadic::iterator end) {
300    return insertAtInsertionPoint(new And(type, begin, end, makeName("and_")));
301}
302
303PabloAST * PabloBlock::createOr(PabloAST * expr1, PabloAST * expr2) {
304    throwIfNonMatchingTypes(expr1, expr2);
305    if (isa<Zeroes>(expr1) || isa<Ones>(expr2)){
306        return expr2;
307    }
308    if (isa<Zeroes>(expr2) || isa<Ones>(expr1) || equals(expr1, expr2)) {
309        return expr1;
310    } else if (Not * not1 = dyn_cast<Not>(expr1)) {
311        // ¬a√b = ¬¬(¬a √ b) = ¬(a ∧ ¬b)
312        return createNot(createAnd(not1->getOperand(0), createNot(expr2)));
313    } else if (Not * not2 = dyn_cast<Not>(expr2)) {
314        // a√¬b = ¬¬(¬b √ a) = ¬(b ∧ ¬a)
315        return createNot(createAnd(not2->getOperand(0), createNot(expr1)));
316    } else if (equals(expr1, expr2)) {
317        return expr1;
318    } else if (And * and1 = isBinary<And>(expr1)) {
319        if (And * and2 = isBinary<And>(expr2)) {
320            PabloAST * const expr1a = and1->getOperand(0);
321            PabloAST * const expr1b = and1->getOperand(1);
322            PabloAST * const expr2a = and2->getOperand(0);
323            PabloAST * const expr2b = and2->getOperand(1);
324            //These optimizations factor out common components that can occur when sets are formed by union
325            //(e.g., union of [a-z] and [A-Z].
326            if (equals(expr1a, expr2a)) {
327                return createAnd(expr1a, createOr(expr1b, expr2b));
328            } else if (equals(expr1b, expr2b)) {
329                return createAnd(expr1b, createOr(expr1a, expr2a));
330            } else if (equals(expr1a, expr2b)) {
331                return createAnd(expr1a, createOr(expr1b, expr2a));
332            } else if (equals(expr1b, expr2a)) {
333                return createAnd(expr1b, createOr(expr1a, expr2b));
334            }
335        } else if (equals(and1->getOperand(0), expr2) || equals(and1->getOperand(1), expr2)) {
336            // (a ∧ b) √ a = a
337            return expr2;
338        }
339    } else if (And * and2 = isBinary<And>(expr2)) {
340        if (equals(and2->getOperand(0), expr1) || equals(and2->getOperand(1), expr1)) {
341            return expr1;
342        }
343    }
344    return insertAtInsertionPoint(new Or(expr1->getType(), expr1, expr2, makeName("or_")));
345}
346
347PabloAST * PabloBlock::createOr(PabloAST * expr1, PabloAST * expr2, const std::string prefix) {
348    throwIfNonMatchingTypes(expr1, expr2);
349    if (isa<Zeroes>(expr1) || isa<Ones>(expr2)){
350        return renameNonNamedNode(expr2, std::move(prefix));
351    }
352    else if (isa<Zeroes>(expr2) || isa<Ones>(expr1) || equals(expr1, expr2)) {
353        return renameNonNamedNode(expr1, std::move(prefix));
354    } else if (Not * not1 = dyn_cast<Not>(expr1)) {
355        // ¬a√b = ¬¬(¬a√b) = ¬(a ∧ ¬b)
356        return createNot(createAnd(not1->getOperand(0), createNot(expr2)), prefix);
357    } else if (Not * not2 = dyn_cast<Not>(expr2)) {
358        // a√¬b = ¬¬(¬b√a) = ¬(b ∧ ¬a)
359        return createNot(createAnd(not2->getOperand(0), createNot(expr1)), prefix);
360    } else if (And * and1 = isBinary<And>(expr1)) {
361        if (And * and2 = isBinary<And>(expr2)) {
362            PabloAST * const expr1a = and1->getOperand(0);
363            PabloAST * const expr1b = and1->getOperand(1);
364            PabloAST * const expr2a = and2->getOperand(0);
365            PabloAST * const expr2b = and2->getOperand(1);
366            //These optimizations factor out common components that can occur when sets are formed by union
367            //(e.g., union of [a-z] and [A-Z].
368            if (equals(expr1a, expr2a)) {
369                return createAnd(expr1a, createOr(expr1b, expr2b), prefix);
370            } else if (equals(expr1b, expr2b)) {
371                return createAnd(expr1b, createOr(expr1a, expr2a), prefix);
372            } else if (equals(expr1a, expr2b)) {
373                return createAnd(expr1a, createOr(expr1b, expr2a), prefix);
374            } else if (equals(expr1b, expr2a)) {
375                return createAnd(expr1b, createOr(expr1a, expr2b), prefix);
376            }
377        } else if (equals(and1->getOperand(0), expr2) || equals(and1->getOperand(1), expr2)) {
378            // (a∧b) √ a = a
379            return expr2;
380        }
381    } else if (And * and2 = isBinary<And>(expr2)) {
382        if (equals(and2->getOperand(0), expr1) || equals(and2->getOperand(1), expr1)) {
383            return expr1;
384        }
385    }
386    return insertAtInsertionPoint(new Or(expr1->getType(), expr1, expr2, makeName(prefix, false)));
387}
388
389Or * PabloBlock::createOr(const PabloType * const type, const unsigned reserved) {
390    return insertAtInsertionPoint(new Or(type, reserved, makeName("or_")));
391}
392
393Or * PabloBlock::createOr(const PabloType * const type, const unsigned reserved, const std::string prefix) {
394    return insertAtInsertionPoint(new Or(type, reserved, makeName(prefix, false)));
395}
396
397Or * PabloBlock::createOr(const PabloType * const type, std::vector<PabloAST *>::iterator begin, std::vector<PabloAST *>::iterator end) {
398    return insertAtInsertionPoint(new Or(type, begin, end, makeName("or_")));
399}
400
401Or * PabloBlock::createOr(const PabloType * const type, Variadic::iterator begin, Variadic::iterator end) {
402    return insertAtInsertionPoint(new Or(type, begin, end, makeName("or_")));
403}
404
405PabloAST * PabloBlock::createXor(PabloAST * expr1, PabloAST * expr2) {
406    throwIfNonMatchingTypes(expr1, expr2);
407    if (expr1 == expr2) {
408        return PabloBlock::createZeroes(expr1->getType());
409    } else if (isa<Ones>(expr1)) {
410        return createNot(expr2);
411    } else if (isa<Zeroes>(expr1)){
412        return expr2;
413    } else if (isa<Ones>(expr2)) {
414        return createNot(expr1);
415    } else if (isa<Zeroes>(expr2)){
416        return expr1;
417    } else if (Not * not1 = dyn_cast<Not>(expr1)) {
418        if (Not * not2 = dyn_cast<Not>(expr2)) {
419            return createXor(not1->getOperand(0), not2->getOperand(0));
420        }
421    }
422    return insertAtInsertionPoint(new Xor(expr1->getType(), expr1, expr2, makeName("xor_")));
423}
424
425PabloAST * PabloBlock::createXor(PabloAST * expr1, PabloAST * expr2, const std::string prefix) {
426    throwIfNonMatchingTypes(expr1, expr2);
427    if (expr1 == expr2) {
428        return PabloBlock::createZeroes(expr1->getType());
429    } else if (isa<Ones>(expr1)) {
430        return createNot(expr2, prefix);
431    } else if (isa<Zeroes>(expr1)){
432        return expr2;
433    } else if (isa<Ones>(expr2)) {
434        return createNot(expr1, prefix);
435    } else if (isa<Zeroes>(expr2)){
436        return expr1;
437    } else if (Not * not1 = dyn_cast<Not>(expr1)) {
438        if (Not * not2 = dyn_cast<Not>(expr2)) {
439            return createXor(not1->getOperand(0), not2->getOperand(0), prefix);
440        }
441    }
442    return insertAtInsertionPoint(new Xor(expr1->getType(), expr1, expr2, makeName(prefix, false)));
443}
444
445Xor * PabloBlock::createXor(const PabloType * const type, const unsigned reserved) {
446    return insertAtInsertionPoint(new Xor(type, reserved, makeName("xor_")));
447}
448
449Xor * PabloBlock::createXor(const PabloType * const type, const unsigned reserved, const std::string prefix) {
450    return insertAtInsertionPoint(new Xor(type, reserved, makeName(prefix, false)));
451}
452
453Xor * PabloBlock::createXor(const PabloType * const type, std::vector<PabloAST *>::iterator begin, std::vector<PabloAST *>::iterator end) {
454    return insertAtInsertionPoint(new Xor(type, begin, end, makeName("xor_")));
455}
456
457Xor * PabloBlock::createXor(const PabloType * const type, Variadic::iterator begin, Variadic::iterator end) {
458    return insertAtInsertionPoint(new Xor(type, begin, end, makeName("xor_")));
459}
460
461/// TERNARY CREATE FUNCTION
462
463PabloAST * PabloBlock::createSel(PabloAST * condition, PabloAST * trueExpr, PabloAST * falseExpr) {
464    throwIfNonMatchingTypes(trueExpr, falseExpr);
465    if (isa<Ones>(condition)) {
466        return trueExpr;
467    } else if (isa<Zeroes>(condition)){
468        return falseExpr;
469    } else if (isa<Ones>(trueExpr)) {
470        return createOr(condition, falseExpr);
471    } else if (isa<Zeroes>(trueExpr)){
472        return createAnd(createNot(condition), falseExpr);
473    } else if (isa<Ones>(falseExpr)) {
474        return createOr(createNot(condition), trueExpr);
475    } else if (isa<Zeroes>(falseExpr)){
476        return createAnd(condition, trueExpr);
477    } else if (equals(trueExpr, falseExpr)) {
478        return trueExpr;
479    } else if (isa<Not>(trueExpr) && equals(cast<Not>(trueExpr)->getOperand(0), falseExpr)) {
480        return createXor(condition, falseExpr);
481    } else if (isa<Not>(falseExpr) && equals(trueExpr, cast<Not>(falseExpr)->getOperand(0))){
482        return createXor(condition, trueExpr);
483    }
484    return insertAtInsertionPoint(new Sel(condition, trueExpr, falseExpr, makeName("sel")));
485}
486
487PabloAST * PabloBlock::createSel(PabloAST * condition, PabloAST * trueExpr, PabloAST * falseExpr, const std::string prefix) {
488    throwIfNonMatchingTypes(trueExpr, falseExpr);
489    if (isa<Zeroes>(condition)){
490        return renameNonNamedNode(falseExpr, std::move(prefix));
491    } else if (isa<Ones>(condition) || equals(trueExpr, falseExpr)) {
492        return renameNonNamedNode(trueExpr, std::move(prefix));
493    } else if (isa<Ones>(trueExpr)) {
494        return createOr(condition, falseExpr, prefix);
495    } else if (isa<Zeroes>(trueExpr)){
496        return createAnd(createNot(condition), falseExpr, prefix);
497    } else if (isa<Ones>(falseExpr)) {
498        return createOr(createNot(condition), trueExpr, prefix);
499    } else if (isa<Zeroes>(falseExpr)){
500        return createAnd(condition, trueExpr, prefix);
501    } else if (isa<Not>(trueExpr) && equals(cast<Not>(trueExpr)->getOperand(0), falseExpr)) {
502        return createXor(condition, falseExpr, prefix);
503    } else if (isa<Not>(falseExpr) && equals(trueExpr, cast<Not>(falseExpr)->getOperand(0))){
504        return createXor(condition, trueExpr, prefix);
505    }
506    return insertAtInsertionPoint(new Sel(condition, trueExpr, falseExpr, makeName(prefix, false)));
507}
508
509If * PabloBlock::createIf(PabloAST * condition, const std::initializer_list<Assign *> definedVars, PabloBlock * body) {
510    assert (condition);
511    return insertAtInsertionPoint(new If(condition, definedVars, body));
512}
513
514If * PabloBlock::createIf(PabloAST * condition, const std::vector<Assign *> & definedVars, PabloBlock * body) {
515    assert (condition);
516    return insertAtInsertionPoint(new If(condition, definedVars, body));
517}
518
519If * PabloBlock::createIf(PabloAST * condition, std::vector<Assign *> && definedVars, PabloBlock * body) {
520    assert (condition);
521    return insertAtInsertionPoint(new If(condition, definedVars, body));
522}
523
524While * PabloBlock::createWhile(PabloAST * condition, const std::initializer_list<Next *> nextVars, PabloBlock * body) {
525    assert (condition);
526    return insertAtInsertionPoint(new While(condition, nextVars, body));
527}
528
529While * PabloBlock::createWhile(PabloAST * condition, const std::vector<Next *> & nextVars, PabloBlock * body) {
530    assert (condition);
531    return insertAtInsertionPoint(new While(condition, nextVars, body));
532}
533
534While * PabloBlock::createWhile(PabloAST * condition, std::vector<Next *> && nextVars, PabloBlock * body) {
535    assert (condition);
536    return insertAtInsertionPoint(new While(condition, nextVars, body));
537}
538
539/** ------------------------------------------------------------------------------------------------------------- *
540 * @brief eraseFromParent
541 ** ------------------------------------------------------------------------------------------------------------- */
542void PabloBlock::eraseFromParent(const bool recursively) {
543    Statement * stmt = front();
544    // Note: by erasing the scope block, any Assign/Next nodes will be replaced with Zero and removed from
545    // the If/While node
546    while (stmt) {
547        stmt = stmt->eraseFromParent(recursively);
548    }
549    mAllocator.deallocate(reinterpret_cast<Allocator::pointer>(this));
550}
551
552
553// Assign sequential scope indexes, returning the next unassigned index   
554
555unsigned PabloBlock::enumerateScopes(unsigned baseScopeIndex) {
556    mScopeIndex = baseScopeIndex;
557    unsigned nextScopeIndex = baseScopeIndex + 1;
558    for (Statement * stmt : *this) {
559        if (If * ifStatement = dyn_cast<If>(stmt)) {
560            nextScopeIndex = ifStatement->getBody()->enumerateScopes(nextScopeIndex);
561        }
562        else if (While * whileStatement = dyn_cast<While>(stmt)) {
563            nextScopeIndex = whileStatement->getBody()->enumerateScopes(nextScopeIndex);
564        }
565    }
566    return nextScopeIndex;
567}   
568   
569/// CONSTRUCTOR
570
571PabloBlock::PabloBlock(PabloFunction * parent, PabloBlock *predecessor) noexcept
572: PabloAST(PabloAST::ClassTypeId::Block, nullptr)
573, mParent(parent)
574, mPredecessor(predecessor)
575, mBranch(nullptr)
576, mScopeIndex(0)
577{
578
579}
580
581PabloBlock::~PabloBlock() {
582
583}
584
585}
Note: See TracBrowser for help on using the repository browser.