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

Last change on this file since 5400 was 5371, checked in by nmedfort, 2 years ago

Bug fix for long advance

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