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

Last change on this file since 5709 was 5709, checked in by cameron, 21 months ago

createIndexedAdvance

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