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

Last change on this file since 5229 was 5229, checked in by cameron, 3 years ago

Distinguishing between StreamType? and StreamSetType?; fixing StreamSetBlock? pointer calculations

File size: 10.2 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 Call(prototype));
39}
40
41Count * PabloBlock::createCount(PabloAST * expr) {
42    Type * type = getParent()->getBuilder()->getSizeTy();
43    return insertAtInsertionPoint(new Count(expr, makeName("count"), type));
44}
45
46Count * PabloBlock::createCount(PabloAST * const expr, const std::string & prefix)  {
47    Type * type = getParent()->getBuilder()->getSizeTy();
48    return insertAtInsertionPoint(new Count(expr, makeName(prefix), type));
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 Not(expr, name));
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 InFile(expr, name));
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 AtEOF(expr, name));
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 Advance(expr, shiftAmount, name));
93}
94
95Lookahead * PabloBlock::createLookahead(PabloAST * expr, PabloAST * shiftAmount, String * name) {
96    if (name == nullptr) {
97        name = makeName("lookahead");
98    }
99    return insertAtInsertionPoint(new Lookahead(expr, shiftAmount, name));
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<StreamType>(type))) {
115        type = cast<StreamType>(type)->getStreamElementType();
116    } else if (LLVM_LIKELY(isa<ArrayType>(type))) {
117        type = cast<ArrayType>(type)->getArrayElementType();
118    } else {
119        std::string tmp;
120        raw_string_ostream out(tmp);
121        out << "cannot extract element from ";
122        array->print(out);
123        out << " : not a StreamType or ArrayType";
124        throw std::runtime_error(out.str());
125    }
126    return insertAtInsertionPoint(new Extract(array, index, name, type));
127}
128
129And * PabloBlock::createAnd(PabloAST * expr1, PabloAST * expr2, String * name) {
130    CHECK_SAME_TYPE(expr1, expr2);
131    if (name == nullptr) {
132        name = makeName("and");
133    }
134    return insertAtInsertionPoint(new And(expr1->getType(), expr1, expr2, name));
135}
136
137And * PabloBlock::createAnd(Type * const type, const unsigned reserved, String * name) {
138    if (name == nullptr) {
139        name = makeName("and");
140    }
141    return insertAtInsertionPoint(new And(type, reserved, name));
142}
143
144Or * PabloBlock::createOr(PabloAST * expr1, PabloAST * expr2, String * name) {
145    CHECK_SAME_TYPE(expr1, expr2);
146    if (name == nullptr) {
147        name = makeName("or");
148    }
149    return insertAtInsertionPoint(new Or(expr1->getType(), expr1, expr2, name));
150}
151
152Or * PabloBlock::createOr(Type * const type, const unsigned reserved, String * name) {
153    if (name == nullptr) {
154        name = makeName("or");
155    }
156    return insertAtInsertionPoint(new Or(type, reserved, name));
157}
158
159Xor * PabloBlock::createXor(PabloAST * expr1, PabloAST * expr2, String * name) {
160    CHECK_SAME_TYPE(expr1, expr2);
161    if (name == nullptr) {
162        name = makeName("xor");
163    }
164    return insertAtInsertionPoint(new Xor(expr1->getType(), expr1, expr2, name));
165}
166
167Xor * PabloBlock::createXor(Type * const type, const unsigned reserved, String * name) {
168    if (name == nullptr) {
169        name = makeName("xor");
170    }
171    return insertAtInsertionPoint(new Xor(type, reserved, name));
172}
173
174Add * PabloBlock::createAdd(PabloAST * expr1, PabloAST * expr2) {
175    CHECK_SAME_TYPE(expr1, expr2);
176    return new Add(expr1->getType(), expr1, expr2);
177}
178
179Subtract * PabloBlock::createSubtract(PabloAST * expr1, PabloAST * expr2) {
180    CHECK_SAME_TYPE(expr1, expr2);
181    return new Subtract(expr1->getType(), expr1, expr2);
182}
183
184LessThan * PabloBlock::createLessThan(PabloAST * expr1, PabloAST * expr2) {
185    CHECK_SAME_TYPE(expr1, expr2);
186    return new LessThan(getParent()->getBuilder()->getInt1Ty(), expr1, expr2);
187}
188
189enum class AssignErrorType {
190    TypeMismatch
191    , ReadOnlyVar
192    , NotAVariable
193};
194
195static void reportAssignError(PabloAST * const var, PabloAST * const value, const AssignErrorType type) {
196    std::string tmp;
197    raw_string_ostream out(tmp);
198    out << "Cannot assign ";
199    value->print(out);
200    out << " to ";
201    var->print(out);
202    out << ": ";
203    switch (type) {
204        case AssignErrorType::TypeMismatch:
205            out << "type mismatch ";
206            printType(value->getType(), out);
207            out << " vs. ";
208            printType(var->getType(), out);
209            break;
210        case AssignErrorType::ReadOnlyVar:
211            var->print(out);
212            out << " is read only";
213            break;
214        case AssignErrorType::NotAVariable:
215            var->print(out);
216            out << " is not a variable";
217            break;
218    }
219    llvm::report_fatal_error(out.str());
220}
221
222Assign * PabloBlock::createAssign(PabloAST * const var, PabloAST * const value) {
223    CHECK_SAME_TYPE(var, value);
224
225    if (LLVM_UNLIKELY(var->getType() != value->getType())) {
226        reportAssignError(var, value, AssignErrorType::TypeMismatch);
227    }
228
229    PabloAST * test = var;
230    for (;;) {
231        if (LLVM_LIKELY(isa<Var>(test))) {
232            if (LLVM_UNLIKELY(cast<Var>(test)->isReadOnly())) {
233                reportAssignError(var, value, AssignErrorType::ReadOnlyVar);
234            }
235            break;
236        } else if (isa<Extract>(test)) {
237            test = cast<Extract>(test)->getArray();
238        } else {
239            reportAssignError(var, value, AssignErrorType::NotAVariable);
240        }
241    }
242
243    return insertAtInsertionPoint(new Assign(var, value));
244}
245
246MatchStar * PabloBlock::createMatchStar(PabloAST * marker, PabloAST * charclass, String * name) {
247    CHECK_SAME_TYPE(marker, charclass);
248    if (name == nullptr) {
249        name = makeName("matchstar");
250    }
251    return insertAtInsertionPoint(new MatchStar(marker, charclass, name));
252}
253
254ScanThru * PabloBlock::createScanThru(PabloAST * from, PabloAST * thru, String * name) {
255    CHECK_SAME_TYPE(from, thru);
256    if (name == nullptr) {
257        name = makeName("scanthru");
258    }
259    return insertAtInsertionPoint(new ScanThru(from, thru, name));
260}
261
262If * PabloBlock::createIf(PabloAST * condition, PabloBlock * body) {
263    assert (condition);
264    If * const node = insertAtInsertionPoint(new If(condition, body));
265    body->setBranch(node);
266    return node;
267}
268
269While * PabloBlock::createWhile(PabloAST * condition, PabloBlock * body) {
270    assert (condition);
271    While * const node = insertAtInsertionPoint(new While(condition, body));
272    body->setBranch(node);
273    return node;
274}
275
276/// TERNARY CREATE FUNCTION
277
278Sel * PabloBlock::createSel(PabloAST * condition, PabloAST * trueExpr, PabloAST * falseExpr, String * name) {
279    CHECK_SAME_TYPE(trueExpr, falseExpr);
280    if (name == nullptr) {
281        name = makeName("sel");
282    }
283    return insertAtInsertionPoint(new Sel(condition, trueExpr, falseExpr, name));
284}
285
286/** ------------------------------------------------------------------------------------------------------------- *
287 * @brief insert
288 ** ------------------------------------------------------------------------------------------------------------- */
289void PabloBlock::insert(Statement * const statement) {
290    assert (statement);
291    if (LLVM_UNLIKELY(mInsertionPoint == nullptr)) {
292        if (mFirst) {
293            statement->insertBefore(mFirst);
294        } else {
295            statement->removeFromParent();
296            statement->mParent = this;
297            mFirst = mLast = statement;
298        }
299    } else if (LLVM_LIKELY(statement != mInsertionPoint)) {
300        statement->insertAfter(mInsertionPoint);
301        mLast = (mLast == mInsertionPoint) ? statement : mLast;
302        assert (statement->mPrev == mInsertionPoint);
303    }
304    mInsertionPoint = statement;
305}
306
307/** ------------------------------------------------------------------------------------------------------------- *
308 * @brief eraseFromParent
309 ** ------------------------------------------------------------------------------------------------------------- */
310void PabloBlock::eraseFromParent(const bool recursively) {
311    Statement * stmt = front();
312    while (stmt) {
313        stmt = stmt->eraseFromParent(recursively);
314    }
315    mAllocator.deallocate(reinterpret_cast<Allocator::pointer>(this));
316}
317
318}
Note: See TracBrowser for help on using the repository browser.