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

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

Optimized Symbol Generation (and fixed potential bug that could allow duplicate names being constructed); made PabloKernel? extend PabloAST (temporarily removed PabloAST::getName() to avoid diamond problem); added an internal scalar to PabloKernel? struct for each Count to avoid InOut? output scalar variable problem; allowed CodeMotionPass? to move code within the same scope but across a branch statement. Began work on separating Kernels into either Block-Oriented or Segment-Oriented kernels.

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