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

Last change on this file since 5230 was 5230, checked in by nmedfort, 20 months ago

Multi-threading support for PabloAST / PabloCompiler?. Requires unique LLVM Context / Module for each thread.

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