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

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

Work on non carry collapsing mode. Beginning work on pablo-level phi nodes.

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