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

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

Large refactoring step. Removed IR generation code from Kernel (formally KernelBuilder?) and moved it into the new KernelBuilder? class.

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