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

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

Removed StreamType? in favour of 0-length VectorType?.

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