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

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

Code clean-up. Removed Pablo Call, SetIthBit? and Prototype.

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