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

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

Removed Variadic functionality; allowed for deferred creation of statement names

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_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 * const 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    return insertAtInsertionPoint(new (mAllocator) Not(expr, name, mAllocator));
64}
65
66Var * PabloBlock::createVar(String * name, Type * type) {
67    if (type == nullptr) {
68        type = getParent()->getStreamTy();
69    }
70    if (LLVM_UNLIKELY(name == nullptr)) {
71        throw std::runtime_error("Var objects must have a String name");
72    }
73    return mParent->makeVariable(cast<String>(name), type);
74}
75
76InFile * PabloBlock::createInFile(PabloAST * expr, String * name) {
77    assert (expr);
78    return insertAtInsertionPoint(new (mAllocator) InFile(expr, name, mAllocator));
79}
80
81AtEOF * PabloBlock::createAtEOF(PabloAST * expr, String * name) {
82    assert (expr);
83    return insertAtInsertionPoint(new (mAllocator) AtEOF(expr, name, mAllocator));
84}
85
86/// BINARY CREATE FUNCTIONS
87
88Advance * PabloBlock::createAdvance(PabloAST * expr, Integer * shiftAmount, String * name) {
89    return insertAtInsertionPoint(new (mAllocator) Advance(expr, shiftAmount, name, mAllocator));
90}
91
92Lookahead * PabloBlock::createLookahead(PabloAST * expr, Integer * shiftAmount, String * name) {
93    return insertAtInsertionPoint(new (mAllocator) Lookahead(expr, shiftAmount, name, mAllocator));
94}
95
96Extract * PabloBlock::createExtract(Var * array, Integer * index) {
97    assert (array && index);
98    Type * type = array->getType();
99    if (LLVM_LIKELY(isa<ArrayType>(type))) {
100        type = cast<ArrayType>(type)->getArrayElementType();
101    } else {
102        std::string tmp;
103        raw_string_ostream out(tmp);
104        out << "cannot extract element from ";
105        array->print(out);
106        out << ": ";
107        type->print(out);
108        out << " is not an array type";
109        throw std::runtime_error(out.str());
110    }
111    return new (mAllocator) Extract(array, index, type, mAllocator);
112}
113
114And * PabloBlock::createAnd(PabloAST * expr1, PabloAST * expr2, String * name) {
115    CHECK_SAME_TYPE(expr1, expr2);
116    return insertAtInsertionPoint(new (mAllocator) And(expr1->getType(), expr1, expr2, name, mAllocator));
117}
118
119Or * PabloBlock::createOr(PabloAST * expr1, PabloAST * expr2, String * name) {
120    CHECK_SAME_TYPE(expr1, expr2);
121    return insertAtInsertionPoint(new (mAllocator) Or(expr1->getType(), expr1, expr2, name, mAllocator));
122}
123
124Xor * PabloBlock::createXor(PabloAST * expr1, PabloAST * expr2, String * name) {
125    CHECK_SAME_TYPE(expr1, expr2);
126    return insertAtInsertionPoint(new (mAllocator) Xor(expr1->getType(), expr1, expr2, name, mAllocator));
127}
128
129Add * PabloBlock::createAdd(PabloAST * expr1, PabloAST * expr2) {
130    CHECK_SAME_TYPE(expr1, expr2);
131    return new (mAllocator) Add(expr1->getType(), expr1, expr2, mAllocator);
132}
133
134Subtract * PabloBlock::createSubtract(PabloAST * expr1, PabloAST * expr2) {
135    CHECK_SAME_TYPE(expr1, expr2);
136    return new (mAllocator) Subtract(expr1->getType(), expr1, expr2, mAllocator);
137}
138
139LessThan * PabloBlock::createLessThan(PabloAST * expr1, PabloAST * expr2) {
140    const Type * const t1 = expr1->getType()->isArrayTy() ? expr1->getType()->getArrayElementType() : expr1->getType();
141    const Type * const t2 = expr2->getType()->isArrayTy() ? expr2->getType()->getArrayElementType() : expr2->getType();
142    CHECK_SAME_TYPE(t1, t2);
143    Type * ty = getParent()->getInt1Ty();
144    if (t1->isVectorTy() || t2->isVectorTy()) {
145        ty = VectorType::get(ty, 0);
146    }
147    return new (mAllocator) LessThan(ty, expr1, expr2, mAllocator);
148}
149
150Equals * PabloBlock::createEquals(PabloAST * expr1, PabloAST * expr2) {
151    const Type * const t1 = expr1->getType()->isArrayTy() ? expr1->getType()->getArrayElementType() : expr1->getType();
152    const Type * const t2 = expr2->getType()->isArrayTy() ? expr2->getType()->getArrayElementType() : expr2->getType();
153    CHECK_SAME_TYPE(t1, t2);
154    Type * ty = getParent()->getInt1Ty();
155    if (t1->isVectorTy() || t2->isVectorTy()) {
156        ty = VectorType::get(ty, 0);
157    }
158    return new (mAllocator) Equals(ty, expr1, expr2, mAllocator);
159}
160
161Assign * PabloBlock::createAssign(PabloAST * const var, PabloAST * const value) {
162    CHECK_SAME_TYPE(var, value);
163    Var * test = nullptr;
164    if (isa<Extract>(var)) {
165        test = cast<Extract>(var)->getArray();
166    } else if (isa<Var>(var)) {
167        test = cast<Var>(var);
168    }
169    if (LLVM_UNLIKELY(test == nullptr || test->isReadOnly())) {
170        std::string tmp;
171        raw_string_ostream out(tmp);
172        out << "cannot assign ";
173        value->print(out);
174        out << " to ";
175        var->print(out);
176        out << ": ";
177        var->print(out);
178        if (test == nullptr) {
179            out << " must be an Extract expression or Var declaration";
180        } else {
181            out << " is read only";
182        }
183        report_fatal_error(out.str());
184    }
185    return insertAtInsertionPoint(new (mAllocator) Assign(var, value, mAllocator));
186}
187
188MatchStar * PabloBlock::createMatchStar(PabloAST * marker, PabloAST * charclass, String * name) {
189    CHECK_SAME_TYPE(marker, charclass);
190    return insertAtInsertionPoint(new (mAllocator) MatchStar(marker, charclass, name, mAllocator));
191}
192
193ScanThru * PabloBlock::createScanThru(PabloAST * from, PabloAST * thru, String * name) {
194    CHECK_SAME_TYPE(from, thru);
195    return insertAtInsertionPoint(new (mAllocator) ScanThru(from, thru, name, mAllocator));
196}
197
198ScanTo * PabloBlock::createScanTo(PabloAST * from, PabloAST * to, String * name) {
199    CHECK_SAME_TYPE(from, to);
200    return insertAtInsertionPoint(new (mAllocator) ScanTo(from, to, name, mAllocator));
201}
202
203AdvanceThenScanThru * PabloBlock::createAdvanceThenScanThru(PabloAST * from, PabloAST * thru, String * name) {
204    CHECK_SAME_TYPE(from, thru);
205    return insertAtInsertionPoint(new (mAllocator) AdvanceThenScanThru(from, thru, name, mAllocator));
206}
207
208AdvanceThenScanTo * PabloBlock::createAdvanceThenScanTo(PabloAST * from, PabloAST * to, String * name) {
209    CHECK_SAME_TYPE(from, to);
210    return insertAtInsertionPoint(new (mAllocator) AdvanceThenScanTo(from, to, name, mAllocator));
211}
212
213If * PabloBlock::createIf(PabloAST * condition, PabloBlock * body) {
214    assert (condition && body);
215    If * const node = insertAtInsertionPoint(new (mAllocator) If(condition, body, mAllocator));
216    body->setBranch(node);
217    return node;
218}
219
220While * PabloBlock::createWhile(PabloAST * condition, PabloBlock * body) {
221    assert (condition && body);
222    While * const node = insertAtInsertionPoint(new (mAllocator) While(condition, body, mAllocator));
223    body->setBranch(node);
224    return node;
225}
226
227Repeat * PabloBlock::createRepeat(Integer * fieldWidth, PabloAST * value, String * name) {
228    assert (fieldWidth && value);
229    Type * const type = VectorType::get(IntegerType::get(value->getType()->getContext(), fieldWidth->value()), 0);
230    return insertAtInsertionPoint(new (mAllocator) Repeat(fieldWidth, value, type, name, mAllocator));
231}
232
233PackH * PabloBlock::createPackH(Integer * fieldWidth, PabloAST * value, String * name) {
234    assert (fieldWidth && value);
235    Type * const type = VectorType::get(IntegerType::get(value->getType()->getContext(), fieldWidth->value()), 0);
236    return insertAtInsertionPoint(new (mAllocator) PackH(fieldWidth, value, name, type, mAllocator));
237}
238
239PackL * PabloBlock::createPackL(Integer * fieldWidth, PabloAST * value, String * name) {
240    assert (fieldWidth && value);
241    Type * const type = VectorType::get(IntegerType::get(value->getType()->getContext(), fieldWidth->value()), 0);
242    return insertAtInsertionPoint(new (mAllocator) PackL(fieldWidth, value, name, type, mAllocator));
243}
244
245/// TERNARY CREATE FUNCTIONS
246
247Sel * PabloBlock::createSel(PabloAST * condition, PabloAST * trueExpr, PabloAST * falseExpr, String * name) {
248    CHECK_SAME_TYPE(trueExpr, falseExpr);
249    return insertAtInsertionPoint(new (mAllocator) Sel(condition, trueExpr, falseExpr, name, mAllocator));
250}
251
252IndexedAdvance * PabloBlock::createIndexedAdvance(PabloAST * expr, PabloAST * indexStream, Integer * shiftAmount, String * name) {
253    return insertAtInsertionPoint(new (mAllocator) IndexedAdvance(expr, indexStream, shiftAmount, name, mAllocator));
254}
255   
256
257/** ------------------------------------------------------------------------------------------------------------- *
258 * @brief Create
259 ** ------------------------------------------------------------------------------------------------------------- */
260PabloBlock * PabloBlock::Create(PabloKernel * const parent) noexcept {
261    Allocator & allocator = parent->mAllocator;
262    return new (allocator) PabloBlock(parent, allocator);
263}
264
265/** ------------------------------------------------------------------------------------------------------------- *
266 * @brief insert
267 ** ------------------------------------------------------------------------------------------------------------- */
268void PabloBlock::insert(Statement * const statement) {
269    assert (statement);
270    if (LLVM_UNLIKELY(mInsertionPoint == nullptr)) {
271        if (mFirst) {
272            statement->insertBefore(mFirst);
273        } else {
274            statement->removeFromParent();
275            statement->mParent = this;
276            mFirst = mLast = statement;
277        }
278    } else if (LLVM_LIKELY(statement != mInsertionPoint)) {
279        statement->insertAfter(mInsertionPoint);
280        mLast = (mLast == mInsertionPoint) ? statement : mLast;
281        assert (statement->mPrev == mInsertionPoint);
282    }
283    mInsertionPoint = statement;
284}
285
286/** ------------------------------------------------------------------------------------------------------------- *
287 * @brief eraseFromParent
288 ** ------------------------------------------------------------------------------------------------------------- */
289void PabloBlock::eraseFromParent(const bool recursively) {
290    Statement * stmt = front();
291    while (stmt) {
292        stmt = stmt->eraseFromParent(recursively);
293    }
294}
295
296/** ------------------------------------------------------------------------------------------------------------- *
297 * @brief getPredecessor
298 ** ------------------------------------------------------------------------------------------------------------- */
299PabloBlock * PabloBlock::getPredecessor() const {
300    return getBranch() ? getBranch()->getParent() : nullptr;
301}
302
303/** ------------------------------------------------------------------------------------------------------------- *
304 * @brief print
305 ** ------------------------------------------------------------------------------------------------------------- */
306void PabloBlock::print(raw_ostream & O, const bool expandNested) const {
307    PabloPrinter::print(this, O, expandNested);
308}
309
310}
Note: See TracBrowser for help on using the repository browser.