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

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

Pablo support for byte comparisions; LineFeed? kernel processes byte streams directly. Some clean up of PabloBuilder? functionality.

File size: 14.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_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_pack.h>
20#include <pablo/pe_repeat.h>
21#include <pablo/pe_scanthru.h>
22#include <pablo/pe_string.h>
23#include <pablo/pe_var.h>
24#include <pablo/pe_zeroes.h>
25#include <pablo/ps_assign.h>
26#include <pablo/pablo_kernel.h>
27#include <IR_Gen/idisa_builder.h>
28#include <llvm/IR/Module.h>
29#include <llvm/Support/raw_os_ostream.h>
30
31using namespace llvm;
32
33namespace pablo {
34
35#ifndef NDEBUG
36inline void checkSameType(const Type * const A, const Type * const B) {
37    assert ("DIFFERING CONTEXTS" && (&(A->getContext()) == &(B->getContext())));
38    assert ("DIFFERING TYPES" && (A == B));
39}
40inline void checkSameType(const PabloAST * const A, const PabloAST * const B) {
41    checkSameType(A->getType(), B->getType());
42}
43#define CHECK_SAME_TYPE(A, B) checkSameType(A, B)
44#else
45#define CHECK_SAME_TYPE(A, B)
46#endif
47
48/// UNARY CREATE FUNCTIONS
49///
50
51Count * PabloBlock::createCount(PabloAST * expr) {
52    IntegerType * const type = getParent()->getSizeTy();
53    return insertAtInsertionPoint(new (mAllocator) Count(expr, makeName("count"), type, mAllocator));
54}
55
56Count * PabloBlock::createCount(PabloAST * const expr, const llvm::StringRef & prefix)  {
57    IntegerType * const type = getParent()->getSizeTy();
58    return insertAtInsertionPoint(new (mAllocator) Count(expr, makeName(prefix), type, mAllocator));
59}
60
61Not * PabloBlock::createNot(PabloAST * expr, String * name) {
62    assert (expr);
63    if (name == nullptr) {
64        name = makeName("not");
65    }
66    return insertAtInsertionPoint(new (mAllocator) Not(expr, name, mAllocator));
67}
68
69Var * PabloBlock::createVar(PabloAST * name, Type * type) {
70    if (type == nullptr) {
71        type = getParent()->getStreamTy();
72    }
73    if (LLVM_UNLIKELY(name == nullptr || !isa<String>(name))) {
74        throw std::runtime_error("Var objects must have a String name");
75    }
76    return mParent->makeVariable(cast<String>(name), type);
77}
78
79InFile * PabloBlock::createInFile(PabloAST * expr, String * name) {
80    assert (expr);
81    if (name == nullptr) {
82        name = makeName("inFile");
83    }
84    return insertAtInsertionPoint(new (mAllocator) InFile(expr, name, mAllocator));
85}
86
87AtEOF * PabloBlock::createAtEOF(PabloAST * expr, String * name) {
88    assert (expr);
89    if (name == nullptr) {
90        name = makeName("atEOF");
91    }
92    return insertAtInsertionPoint(new (mAllocator) AtEOF(expr, name, mAllocator));
93}
94
95/// BINARY CREATE FUNCTIONS
96
97Advance * PabloBlock::createAdvance(PabloAST * expr, Integer * shiftAmount, String * name) {
98    if (name == nullptr) {
99        name = makeName("advance");
100    }
101    return insertAtInsertionPoint(new (mAllocator) Advance(expr, shiftAmount, name, mAllocator));
102}
103
104Lookahead * PabloBlock::createLookahead(PabloAST * expr, Integer * shiftAmount, String * name) {
105    if (name == nullptr) {
106        name = makeName("lookahead");
107    }
108    return insertAtInsertionPoint(new (mAllocator) Lookahead(expr, shiftAmount, name, mAllocator));
109}
110
111Extract * PabloBlock::createExtract(Var * array, Integer * index) {
112    assert (array && index);
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 << ": ";
122        type->print(out);
123        out << " is not an array type";
124        throw std::runtime_error(out.str());
125    }
126    return new (mAllocator) Extract(array, index, type, mAllocator);
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 (mAllocator) And(expr1->getType(), expr1, expr2, name, mAllocator));
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 (mAllocator) And(type, reserved, name, mAllocator));
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 (mAllocator) Or(expr1->getType(), expr1, expr2, name, mAllocator));
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 (mAllocator) Or(type, reserved, name, mAllocator));
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 (mAllocator) Xor(expr1->getType(), expr1, expr2, name, mAllocator));
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 (mAllocator) Xor(type, reserved, name, mAllocator));
172}
173
174Add * PabloBlock::createAdd(PabloAST * expr1, PabloAST * expr2) {
175    CHECK_SAME_TYPE(expr1, expr2);
176    return new (mAllocator) Add(expr1->getType(), expr1, expr2, mAllocator);
177}
178
179Subtract * PabloBlock::createSubtract(PabloAST * expr1, PabloAST * expr2) {
180    CHECK_SAME_TYPE(expr1, expr2);
181    return new (mAllocator) Subtract(expr1->getType(), expr1, expr2, mAllocator);
182}
183
184LessThan * PabloBlock::createLessThan(PabloAST * expr1, PabloAST * expr2) {
185    const Type * const t1 = expr1->getType()->isArrayTy() ? expr1->getType()->getArrayElementType() : expr1->getType();
186    const Type * const t2 = expr2->getType()->isArrayTy() ? expr2->getType()->getArrayElementType() : expr2->getType();
187    CHECK_SAME_TYPE(t1, t2);
188    Type * ty = getParent()->getInt1Ty();
189    if (t1->isVectorTy() || t2->isVectorTy()) {
190        ty = VectorType::get(ty, 0);
191    }
192    return new (mAllocator) LessThan(ty, expr1, expr2, mAllocator);
193}
194
195Equals * PabloBlock::createEquals(PabloAST * expr1, PabloAST * expr2) {
196    const Type * const t1 = expr1->getType()->isArrayTy() ? expr1->getType()->getArrayElementType() : expr1->getType();
197    const Type * const t2 = expr2->getType()->isArrayTy() ? expr2->getType()->getArrayElementType() : expr2->getType();
198    CHECK_SAME_TYPE(t1, t2);
199    Type * ty = getParent()->getInt1Ty();
200    if (t1->isVectorTy() || t2->isVectorTy()) {
201        ty = VectorType::get(ty, 0);
202    }
203    return new (mAllocator) Equals(ty, expr1, expr2, mAllocator);
204}
205
206Assign * PabloBlock::createAssign(PabloAST * const var, PabloAST * const value) {
207    CHECK_SAME_TYPE(var, value);
208    Var * test = nullptr;
209    if (isa<Extract>(var)) {
210        test = cast<Extract>(var)->getArray();
211    } else if (isa<Var>(var)) {
212        test = cast<Var>(var);
213    }
214    if (LLVM_UNLIKELY(test == nullptr || test->isReadOnly())) {
215        std::string tmp;
216        raw_string_ostream out(tmp);
217        out << "cannot assign ";
218        value->print(out);
219        out << " to ";
220        var->print(out);
221        out << ": ";
222        var->print(out);
223        if (test == nullptr) {
224            out << " must be an Extract expression or Var declaration";
225        } else {
226            out << " is read only";
227        }
228        report_fatal_error(out.str());
229    }
230    return insertAtInsertionPoint(new (mAllocator) Assign(var, value, mAllocator));
231}
232
233MatchStar * PabloBlock::createMatchStar(PabloAST * marker, PabloAST * charclass, String * name) {
234    CHECK_SAME_TYPE(marker, charclass);
235    if (name == nullptr) {
236        name = makeName("matchstar");
237    }
238    return insertAtInsertionPoint(new (mAllocator) MatchStar(marker, charclass, name, mAllocator));
239}
240
241ScanThru * PabloBlock::createScanThru(PabloAST * from, PabloAST * thru, String * name) {
242    CHECK_SAME_TYPE(from, thru);
243    if (name == nullptr) {
244        name = makeName("scanthru");
245    }
246    return insertAtInsertionPoint(new (mAllocator) ScanThru(from, thru, name, mAllocator));
247}
248
249ScanTo * PabloBlock::createScanTo(PabloAST * from, PabloAST * to, String * name) {
250    CHECK_SAME_TYPE(from, to);
251    if (name == nullptr) {
252        name = makeName("scanto");
253    }
254    return insertAtInsertionPoint(new (mAllocator) ScanTo(from, to, name, mAllocator));
255}
256
257AdvanceThenScanThru * PabloBlock::createAdvanceThenScanThru(PabloAST * from, PabloAST * thru, String * name) {
258    CHECK_SAME_TYPE(from, thru);
259    if (name == nullptr) {
260        name = makeName("advscanthru");
261    }
262    return insertAtInsertionPoint(new (mAllocator) AdvanceThenScanThru(from, thru, name, mAllocator));
263}
264
265AdvanceThenScanTo * PabloBlock::createAdvanceThenScanTo(PabloAST * from, PabloAST * to, String * name) {
266    CHECK_SAME_TYPE(from, to);
267    if (name == nullptr) {
268        name = makeName("advscanto");
269    }
270    return insertAtInsertionPoint(new (mAllocator) AdvanceThenScanTo(from, to, name, mAllocator));
271}
272
273If * PabloBlock::createIf(PabloAST * condition, PabloBlock * body) {
274    assert (condition && body);
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 && body);
282    While * const node = insertAtInsertionPoint(new (mAllocator) While(condition, body, mAllocator));
283    body->setBranch(node);
284    return node;
285}
286
287Repeat * PabloBlock::createRepeat(Integer * fieldWidth, PabloAST * value, String * name) {
288    assert (fieldWidth && value);
289    if (name == nullptr) {
290        name = makeName("fill");
291    }
292    Type * const type = VectorType::get(IntegerType::get(value->getType()->getContext(), fieldWidth->value()), 0);
293    return insertAtInsertionPoint(new (mAllocator) Repeat(fieldWidth, value, type, name, mAllocator));
294}
295
296PackH * PabloBlock::createPackH(Integer * fieldWidth, PabloAST * value, String * name) {
297    assert (fieldWidth && value);
298    if (name == nullptr) {
299        name = makeName("packh");
300    }
301    Type * const type = VectorType::get(IntegerType::get(value->getType()->getContext(), fieldWidth->value()), 0);
302    return insertAtInsertionPoint(new (mAllocator) PackH(fieldWidth, value, name, type, mAllocator));
303}
304
305PackL * PabloBlock::createPackL(Integer * fieldWidth, PabloAST * value, String * name) {
306    assert (fieldWidth && value);
307    if (name == nullptr) {
308        name = makeName("packl");
309    }
310    Type * const type = VectorType::get(IntegerType::get(value->getType()->getContext(), fieldWidth->value()), 0);
311    return insertAtInsertionPoint(new (mAllocator) PackL(fieldWidth, value, name, type, mAllocator));
312}
313
314/// TERNARY CREATE FUNCTIONS
315
316Sel * PabloBlock::createSel(PabloAST * condition, PabloAST * trueExpr, PabloAST * falseExpr, String * name) {
317    CHECK_SAME_TYPE(trueExpr, falseExpr);
318    if (name == nullptr) {
319        name = makeName("sel");
320    }
321    return insertAtInsertionPoint(new (mAllocator) Sel(condition, trueExpr, falseExpr, name, mAllocator));
322}
323
324IndexedAdvance * PabloBlock::createIndexedAdvance(PabloAST * expr, PabloAST * indexStream, Integer * shiftAmount, String * name) {
325    if (name == nullptr) {
326        name = makeName("indexed_advance");
327    }
328    return insertAtInsertionPoint(new (mAllocator) IndexedAdvance(expr, indexStream, shiftAmount, name, mAllocator));
329}
330   
331
332/** ------------------------------------------------------------------------------------------------------------- *
333 * @brief Create
334 ** ------------------------------------------------------------------------------------------------------------- */
335PabloBlock * PabloBlock::Create(PabloKernel * const parent) noexcept {
336    Allocator & allocator = parent->mAllocator;
337    return new (allocator) PabloBlock(parent, allocator);
338}
339
340/** ------------------------------------------------------------------------------------------------------------- *
341 * @brief insert
342 ** ------------------------------------------------------------------------------------------------------------- */
343void PabloBlock::insert(Statement * const statement) {
344    assert (statement);
345    if (LLVM_UNLIKELY(mInsertionPoint == nullptr)) {
346        if (mFirst) {
347            statement->insertBefore(mFirst);
348        } else {
349            statement->removeFromParent();
350            statement->mParent = this;
351            mFirst = mLast = statement;
352        }
353    } else if (LLVM_LIKELY(statement != mInsertionPoint)) {
354        statement->insertAfter(mInsertionPoint);
355        mLast = (mLast == mInsertionPoint) ? statement : mLast;
356        assert (statement->mPrev == mInsertionPoint);
357    }
358    mInsertionPoint = statement;
359}
360
361/** ------------------------------------------------------------------------------------------------------------- *
362 * @brief eraseFromParent
363 ** ------------------------------------------------------------------------------------------------------------- */
364void PabloBlock::eraseFromParent(const bool recursively) {
365    Statement * stmt = front();
366    while (stmt) {
367        stmt = stmt->eraseFromParent(recursively);
368    }
369}
370
371/** ------------------------------------------------------------------------------------------------------------- *
372 * @brief getPredecessor
373 ** ------------------------------------------------------------------------------------------------------------- */
374PabloBlock * PabloBlock::getPredecessor() const {
375    return getBranch() ? getBranch()->getParent() : nullptr;
376}
377
378/** ------------------------------------------------------------------------------------------------------------- *
379 * @brief print
380 ** ------------------------------------------------------------------------------------------------------------- */
381void PabloBlock::print(raw_ostream & O, const bool expandNested) const {
382    PabloPrinter::print(this, O, expandNested);
383}
384
385}
Note: See TracBrowser for help on using the repository browser.