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

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

Work on bracket matching problem

File size: 11.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#include <pablo/codegenstate.h>
8#include <pablo/printer_pablos.h>
9
10#define CHECK_SAME_TYPE(A, B) \
11    assert ("DIFFERING CONTEXTS" && (&((A)->getType()->getContext()) == &((B)->getType()->getContext()))); \
12    assert ("DIFFERING TYPES" && ((A)->getType() == (B)->getType()))
13
14using StreamType = IDISA::StreamType;
15
16inline void printType(const Type * type, raw_string_ostream & out) {
17    if (auto st = dyn_cast<StreamType>(type)) {
18        out << "s" << st->getFieldWidth();
19        return;
20    }
21    if (auto ty = dyn_cast<ArrayType>(type)) {
22        unsigned numElems = ty->getNumElements();
23        auto elemTy = ty->getElementType();
24        if (auto st = dyn_cast<StreamType>(elemTy)) {
25            out << "<" << numElems << " x s" << st->getFieldWidth() << ">";
26            return;
27        }
28    }
29    type->print(out);
30}
31
32namespace pablo {
33
34/// UNARY CREATE FUNCTIONS
35///
36
37Call * PabloBlock::createCall(PabloAST * prototype, const std::vector<PabloAST *> &) {
38    assert (prototype);
39    return insertAtInsertionPoint(new (mAllocator) Call(prototype, mAllocator));
40}
41
42Count * PabloBlock::createCount(PabloAST * expr) {
43    Type * type = getParent()->getBuilder()->getSizeTy();
44    return insertAtInsertionPoint(new (mAllocator) Count(expr, makeName("count"), type, mAllocator));
45}
46
47Count * PabloBlock::createCount(PabloAST * const expr, const std::string & prefix)  {
48    Type * type = getParent()->getBuilder()->getSizeTy();
49    return insertAtInsertionPoint(new (mAllocator) Count(expr, makeName(prefix), type, mAllocator));
50}
51
52Not * PabloBlock::createNot(PabloAST * expr, String * name) {
53    assert (expr);
54    if (name == nullptr) {
55        name = makeName("not");
56    }
57    return insertAtInsertionPoint(new (mAllocator) Not(expr, name, mAllocator));
58}
59
60Var * PabloBlock::createVar(PabloAST * name, Type * type) {
61    if (type == nullptr) {
62        type = getParent()->getBuilder()->getStreamTy();
63    }
64    if (LLVM_UNLIKELY(name == nullptr || !isa<String>(name))) {
65        throw std::runtime_error("Var objects must have a String name");
66    }
67    return mParent->makeVariable(name, type);
68}
69
70InFile * PabloBlock::createInFile(PabloAST * expr, String * name) {
71    assert (expr);
72    if (name == nullptr) {
73        name = makeName("inFile");
74    }
75    return insertAtInsertionPoint(new (mAllocator) InFile(expr, name, mAllocator));
76}
77
78AtEOF * PabloBlock::createAtEOF(PabloAST * expr, String * name) {
79    assert (expr);
80    if (name == nullptr) {
81        name = makeName("atEOF");
82    }
83    return insertAtInsertionPoint(new (mAllocator) AtEOF(expr, name, mAllocator));
84}
85   
86   
87/// BINARY CREATE FUNCTIONS
88
89Advance * PabloBlock::createAdvance(PabloAST * expr, PabloAST * shiftAmount, String * name) {
90    if (name == nullptr) {
91        name = makeName("advance");
92    }
93    return insertAtInsertionPoint(new (mAllocator) Advance(expr, shiftAmount, name, mAllocator));
94}
95
96Lookahead * PabloBlock::createLookahead(PabloAST * expr, PabloAST * shiftAmount, String * name) {
97    if (name == nullptr) {
98        name = makeName("lookahead");
99    }
100    return insertAtInsertionPoint(new (mAllocator) Lookahead(expr, shiftAmount, name, mAllocator));
101}
102
103Extract * PabloBlock::createExtract(PabloAST * array, PabloAST * index, String * name) {
104    assert (array && index);
105    if (name == nullptr) {
106        std::string tmp;
107        raw_string_ostream out(tmp);
108        array->print(out);
109        out << '[';
110        index->print(out);
111        out << ']';
112        name = makeName(out.str());
113    }
114    Type * type = array->getType();
115    if (LLVM_LIKELY(isa<ArrayType>(type))) {
116        type = cast<ArrayType>(type)->getArrayElementType();
117    } else {
118        std::string tmp;
119        raw_string_ostream out(tmp);
120        out << "cannot extract element from ";
121        array->print(out);
122        out << " : not a StreamType or ArrayType";
123        throw std::runtime_error(out.str());
124    }
125    return insertAtInsertionPoint(new (mAllocator) Extract(array, index, name, type, mAllocator));
126}
127
128And * PabloBlock::createAnd(PabloAST * expr1, PabloAST * expr2, String * name) {
129    CHECK_SAME_TYPE(expr1, expr2);
130    if (name == nullptr) {
131        name = makeName("and");
132    }
133    return insertAtInsertionPoint(new (mAllocator) And(expr1->getType(), expr1, expr2, name, mAllocator));
134}
135
136And * PabloBlock::createAnd(Type * const type, const unsigned reserved, String * name) {
137    if (name == nullptr) {
138        name = makeName("and");
139    }
140    return insertAtInsertionPoint(new (mAllocator) And(type, reserved, name, mAllocator));
141}
142
143Or * PabloBlock::createOr(PabloAST * expr1, PabloAST * expr2, String * name) {
144    CHECK_SAME_TYPE(expr1, expr2);
145    if (name == nullptr) {
146        name = makeName("or");
147    }
148    return insertAtInsertionPoint(new (mAllocator) Or(expr1->getType(), expr1, expr2, name, mAllocator));
149}
150
151Or * PabloBlock::createOr(Type * const type, const unsigned reserved, String * name) {
152    if (name == nullptr) {
153        name = makeName("or");
154    }
155    return insertAtInsertionPoint(new (mAllocator) Or(type, reserved, name, mAllocator));
156}
157
158Xor * PabloBlock::createXor(PabloAST * expr1, PabloAST * expr2, String * name) {
159    CHECK_SAME_TYPE(expr1, expr2);
160    if (name == nullptr) {
161        name = makeName("xor");
162    }
163    return insertAtInsertionPoint(new (mAllocator) Xor(expr1->getType(), expr1, expr2, name, mAllocator));
164}
165
166Xor * PabloBlock::createXor(Type * const type, const unsigned reserved, String * name) {
167    if (name == nullptr) {
168        name = makeName("xor");
169    }
170    return insertAtInsertionPoint(new (mAllocator) Xor(type, reserved, name, mAllocator));
171}
172
173Add * PabloBlock::createAdd(PabloAST * expr1, PabloAST * expr2) {
174    CHECK_SAME_TYPE(expr1, expr2);
175    return new (mAllocator) Add(expr1->getType(), expr1, expr2, mAllocator);
176}
177
178Subtract * PabloBlock::createSubtract(PabloAST * expr1, PabloAST * expr2) {
179    CHECK_SAME_TYPE(expr1, expr2);
180    return new (mAllocator) Subtract(expr1->getType(), expr1, expr2, mAllocator);
181}
182
183LessThan * PabloBlock::createLessThan(PabloAST * expr1, PabloAST * expr2) {
184    CHECK_SAME_TYPE(expr1, expr2);
185    return new (mAllocator) LessThan(getParent()->getBuilder()->getInt1Ty(), expr1, expr2, mAllocator);
186}
187
188enum class AssignErrorType {
189    TypeMismatch
190    , ReadOnlyVar
191    , NotAVariable
192};
193
194static void reportAssignError(PabloAST * const var, PabloAST * const value, const AssignErrorType type) {
195    std::string tmp;
196    raw_string_ostream out(tmp);
197    out << "Cannot assign ";
198    value->print(out);
199    out << " to ";
200    var->print(out);
201    out << ": ";
202    switch (type) {
203        case AssignErrorType::TypeMismatch:
204            out << "type mismatch ";
205            printType(value->getType(), out);
206            out << " vs. ";
207            printType(var->getType(), out);
208            break;
209        case AssignErrorType::ReadOnlyVar:
210            var->print(out);
211            out << " is read only";
212            break;
213        case AssignErrorType::NotAVariable:
214            var->print(out);
215            out << " is not a variable";
216            break;
217    }
218    llvm::report_fatal_error(out.str());
219}
220
221Assign * PabloBlock::createAssign(PabloAST * const var, PabloAST * const value) {
222    CHECK_SAME_TYPE(var, value);
223
224    if (LLVM_UNLIKELY(var->getType() != value->getType())) {
225        reportAssignError(var, value, AssignErrorType::TypeMismatch);
226    }
227
228    PabloAST * test = var;
229    for (;;) {
230        if (LLVM_LIKELY(isa<Var>(test))) {
231            if (LLVM_UNLIKELY(cast<Var>(test)->isReadOnly())) {
232                reportAssignError(var, value, AssignErrorType::ReadOnlyVar);
233            }
234            break;
235        } else if (isa<Extract>(test)) {
236            test = cast<Extract>(test)->getArray();
237        } else {
238            reportAssignError(var, value, AssignErrorType::NotAVariable);
239        }
240    }
241
242    return insertAtInsertionPoint(new (mAllocator) Assign(var, value, mAllocator));
243}
244
245MatchStar * PabloBlock::createMatchStar(PabloAST * marker, PabloAST * charclass, String * name) {
246    CHECK_SAME_TYPE(marker, charclass);
247    if (name == nullptr) {
248        name = makeName("matchstar");
249    }
250    return insertAtInsertionPoint(new (mAllocator) MatchStar(marker, charclass, name, mAllocator));
251}
252
253ScanThru * PabloBlock::createScanThru(PabloAST * from, PabloAST * thru, String * name) {
254    CHECK_SAME_TYPE(from, thru);
255    if (name == nullptr) {
256        name = makeName("scanthru");
257    }
258    return insertAtInsertionPoint(new (mAllocator) ScanThru(from, thru, name, mAllocator));
259}
260
261If * PabloBlock::createIf(PabloAST * condition, PabloBlock * body) {
262    assert (condition);
263    If * const node = insertAtInsertionPoint(new (mAllocator) If(condition, body, mAllocator));
264    body->setBranch(node);
265    return node;
266}
267
268While * PabloBlock::createWhile(PabloAST * condition, PabloBlock * body) {
269    assert (condition);
270    While * const node = insertAtInsertionPoint(new (mAllocator) While(condition, body, mAllocator));
271    body->setBranch(node);
272    return node;
273}
274
275/// TERNARY CREATE FUNCTION
276
277Sel * PabloBlock::createSel(PabloAST * condition, PabloAST * trueExpr, PabloAST * falseExpr, String * name) {
278    CHECK_SAME_TYPE(trueExpr, falseExpr);
279    if (name == nullptr) {
280        name = makeName("sel");
281    }
282    return insertAtInsertionPoint(new (mAllocator) Sel(condition, trueExpr, falseExpr, name, mAllocator));
283}
284
285/** ------------------------------------------------------------------------------------------------------------- *
286 * @brief insert
287 ** ------------------------------------------------------------------------------------------------------------- */
288void PabloBlock::insert(Statement * const statement) {
289    assert (statement);
290    if (LLVM_UNLIKELY(mInsertionPoint == nullptr)) {
291        if (mFirst) {
292            statement->insertBefore(mFirst);
293        } else {
294            statement->removeFromParent();
295            statement->mParent = this;
296            mFirst = mLast = statement;
297        }
298    } else if (LLVM_LIKELY(statement != mInsertionPoint)) {
299        statement->insertAfter(mInsertionPoint);
300        mLast = (mLast == mInsertionPoint) ? statement : mLast;
301        assert (statement->mPrev == mInsertionPoint);
302    }
303    mInsertionPoint = statement;
304}
305
306/** ------------------------------------------------------------------------------------------------------------- *
307 * @brief eraseFromParent
308 ** ------------------------------------------------------------------------------------------------------------- */
309void PabloBlock::eraseFromParent(const bool recursively) {
310    Statement * stmt = front();
311    while (stmt) {
312        stmt = stmt->eraseFromParent(recursively);
313    }
314}
315
316/** ------------------------------------------------------------------------------------------------------------- *
317 * @brief print
318 ** ------------------------------------------------------------------------------------------------------------- */
319void PabloBlock::print(raw_ostream & O, const bool expandNested) const {
320    PabloPrinter::print(this, O, expandNested);
321}
322
323}
Note: See TracBrowser for help on using the repository browser.