source: icGREP/icgrep-devel/icgrep/pablo/pablo_compiler.cpp @ 5310

Last change on this file since 5310 was 5310, checked in by nmedfort, 2 years ago

Adjusted pablo compiler to use getInputStream and getOutputStream when accessing packed stream fields.

File size: 24.9 KB
Line 
1/*
2 *  Copyright (c) 2014-16 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_compiler.h"
8#include <pablo/pablo_kernel.h>
9#include <pablo/pablo_toolchain.h>
10#include <pablo/codegenstate.h>
11#include <pablo/boolean.h>
12#include <pablo/arithmetic.h>
13#include <pablo/branch.h>
14#include <pablo/pe_advance.h>
15#include <pablo/pe_lookahead.h>
16#include <pablo/pe_matchstar.h>
17#include <pablo/pe_scanthru.h>
18#include <pablo/pe_infile.h>
19#include <pablo/pe_count.h>
20#include <pablo/pe_integer.h>
21#include <pablo/pe_string.h>
22#include <pablo/pe_zeroes.h>
23#include <pablo/pe_ones.h>
24#include <pablo/pe_var.h>
25#include <pablo/ps_assign.h>
26#include <pablo/carry_manager.h>
27#include <IR_Gen/idisa_builder.h>
28#include <kernels/streamset.h>
29#include <llvm/IR/Module.h>
30#include <llvm/Support/raw_os_ostream.h>
31
32using namespace llvm;
33
34namespace pablo {
35
36using TypeId = PabloAST::ClassTypeId;
37
38inline static unsigned getAlignment(const Value * const ptr) {
39    return ptr->getType()->getPrimitiveSizeInBits() / 8;
40}
41
42inline static unsigned getPointerElementAlignment(const Value * const ptr) {
43    return ptr->getType()->getPointerElementType()->getPrimitiveSizeInBits() / 8;
44}
45
46void PabloCompiler::initializeKernelData() {
47    Examine();
48    mCarryManager->initializeCarryData(mKernel);
49}
50   
51void PabloCompiler::compile() {
52
53    mCarryManager->initializeCodeGen();
54     
55    PabloBlock * const entryBlock = mKernel->getEntryBlock(); assert (entryBlock);
56    mMarker.emplace(entryBlock->createZeroes(), iBuilder->allZeroes());
57    mMarker.emplace(entryBlock->createOnes(), iBuilder->allOnes());
58
59    for (unsigned i = 0; i < mKernel->getNumOfInputs(); ++i) {
60        Var * var = mKernel->getInput(i);
61        if (LLVM_UNLIKELY(var->isScalar())) {
62            mMarker.emplace(var, mKernel->getScalarFieldPtr(var->getName()));
63        }
64    }
65
66    for (unsigned i = 0; i < mKernel->getNumOfOutputs(); ++i) {
67        Var * var = mKernel->getOutput(i);
68        if (LLVM_UNLIKELY(var->isScalar())) {
69            mMarker.emplace(var, mKernel->getScalarFieldPtr(var->getName()));
70        }
71    }
72
73    compileBlock(entryBlock);
74
75    mCarryManager->finalizeCodeGen();
76
77}
78
79inline void PabloCompiler::Examine() {
80    Examine(mKernel->getEntryBlock());
81}
82
83void PabloCompiler::Examine(const PabloBlock * const block) {
84    for (const Statement * stmt : *block) {
85        if (LLVM_UNLIKELY(isa<Lookahead>(stmt))) {
86            const Lookahead * const la = cast<Lookahead>(stmt);
87            assert (isa<Var>(la->getExpr()));
88            if (LLVM_LIKELY(la->getAmount() > mKernel->getLookAhead())) {
89                mKernel->setLookAhead(la->getAmount());
90            }
91        } else if (LLVM_UNLIKELY(isa<Branch>(stmt))) {
92            Examine(cast<Branch>(stmt)->getBody());
93        } else if (LLVM_UNLIKELY(isa<Count>(stmt))) {
94            mAccumulator.insert(std::make_pair(stmt, iBuilder->getInt32(mKernel->addUnnamedScalar(stmt->getType()))));
95        }
96    }   
97}
98
99inline void PabloCompiler::compileBlock(const PabloBlock * const block) {
100    for (const Statement * statement : *block) {
101        compileStatement(statement);
102    }
103}
104
105void PabloCompiler::compileIf(const If * const ifStatement) {
106    //
107    //  The If-ElseZero stmt:
108    //  if <predicate:expr> then <body:stmt>* elsezero <defined:var>* endif
109    //  If the value of the predicate is nonzero, then determine the values of variables
110    //  <var>* by executing the given statements.  Otherwise, the value of the
111    //  variables are all zero.  Requirements: (a) no variable that is defined within
112    //  the body of the if may be accessed outside unless it is explicitly
113    //  listed in the variable list, (b) every variable in the defined list receives
114    //  a value within the body, and (c) the logical consequence of executing
115    //  the statements in the event that the predicate is zero is that the
116    //  values of all defined variables indeed work out to be 0.
117    //
118    //  Simple Implementation with Phi nodes:  a phi node in the if exit block
119    //  is inserted for each variable in the defined variable list.  It receives
120    //  a zero value from the ifentry block and the defined value from the if
121    //  body.
122    //
123
124    BasicBlock * const ifEntryBlock = iBuilder->GetInsertBlock();
125    BasicBlock * const ifBodyBlock = mKernel->CreateBasicBlock("if.body");
126    BasicBlock * const ifEndBlock = mKernel->CreateBasicBlock("if.end");
127   
128    std::vector<std::pair<const Var *, Value *>> incoming;
129
130    for (const Var * var : ifStatement->getEscaped()) {
131        auto f = mMarker.find(var);
132        if (LLVM_UNLIKELY(f == mMarker.end())) {
133            std::string tmp;
134            raw_string_ostream out(tmp);
135            var->print(out);
136            out << " is uninitialized prior to entering ";
137            ifStatement->print(out);
138            report_fatal_error(out.str());
139        }
140        incoming.emplace_back(var, f->second);
141    }
142
143    const PabloBlock * ifBody = ifStatement->getBody();
144   
145    mCarryManager->enterIfScope(ifBody);
146
147    Value * condition = compileExpression(ifStatement->getCondition());
148    if (condition->getType() == iBuilder->getBitBlockType()) {
149        condition = iBuilder->bitblock_any(mCarryManager->generateSummaryTest(condition));
150    }
151   
152    iBuilder->CreateCondBr(condition, ifBodyBlock, ifEndBlock);
153   
154    // Entry processing is complete, now handle the body of the if.
155    iBuilder->SetInsertPoint(ifBodyBlock);
156
157    mCarryManager->enterIfBody(ifEntryBlock);
158
159    compileBlock(ifBody);
160
161    BasicBlock * ifExitBlock = iBuilder->GetInsertBlock();   
162
163    mCarryManager->leaveIfBody(ifExitBlock);
164
165    iBuilder->CreateBr(ifEndBlock);
166    //End Block
167    iBuilder->SetInsertPoint(ifEndBlock);
168
169    mCarryManager->leaveIfScope(ifEntryBlock, ifExitBlock);
170
171    for (const auto i : incoming) {
172        const Var * var; Value * incoming;
173        std::tie(var, incoming) = i;
174
175        auto f = mMarker.find(var);
176        if (LLVM_UNLIKELY(f == mMarker.end())) {
177            std::string tmp;
178            raw_string_ostream out(tmp);
179            out << "PHINode creation error: ";
180            var->print(out);
181            out << " was not assigned an outgoing value.";
182            report_fatal_error(out.str());
183        }
184
185        Value * const outgoing = f->second;
186        if (LLVM_UNLIKELY(incoming == outgoing)) {
187            continue;
188        }
189
190        if (LLVM_UNLIKELY(incoming->getType() != outgoing->getType())) {
191            std::string tmp;
192            raw_string_ostream out(tmp);
193            out << "PHINode creation error: incoming type of ";
194            var->print(out);
195            out << " (";
196            incoming->getType()->print(out);
197            out << ") differs from the outgoing type (";
198            outgoing->getType()->print(out);
199            out << ") within ";
200            ifStatement->print(out);
201            report_fatal_error(out.str());
202        }
203
204        PHINode * phi = iBuilder->CreatePHI(incoming->getType(), 2, var->getName());
205        phi->addIncoming(incoming, ifEntryBlock);
206        phi->addIncoming(outgoing, ifExitBlock);
207        f->second = phi;
208    }   
209}
210
211void PabloCompiler::compileWhile(const While * const whileStatement) {
212
213    const PabloBlock * const whileBody = whileStatement->getBody();
214
215    BasicBlock * whileEntryBlock = iBuilder->GetInsertBlock();
216    BasicBlock * whileBodyBlock = mKernel->CreateBasicBlock("while.body");
217    BasicBlock * whileEndBlock = mKernel->CreateBasicBlock("while.end");
218
219    const auto escaped = whileStatement->getEscaped();
220
221#ifdef ENABLE_BOUNDED_WHILE
222    PHINode * bound_phi = nullptr;  // Needed for bounded while loops.
223#endif
224    // On entry to the while structure, proceed to execute the first iteration
225    // of the loop body unconditionally.   The while condition is tested at the end of
226    // the loop.
227
228    mCarryManager->enterLoopScope(whileBody);
229
230    iBuilder->CreateBr(whileBodyBlock);
231
232    iBuilder->SetInsertPoint(whileBodyBlock);
233
234    //
235    // There are 3 sets of Phi nodes for the while loop.
236    // (1) Carry-ins: (a) incoming carry data first iterations, (b) zero thereafter
237    // (2) Carry-out accumulators: (a) zero first iteration, (b) |= carry-out of each iteration
238    // (3) Next nodes: (a) values set up before loop, (b) modified values calculated in loop.
239#ifdef ENABLE_BOUNDED_WHILE
240    // (4) The loop bound, if any.
241#endif
242
243    std::vector<std::pair<const Var *, PHINode *>> variants;
244
245    // for any Next nodes in the loop body, initialize to (a) pre-loop value.
246    for (const auto var : escaped) {
247        auto f = mMarker.find(var);
248        if (LLVM_UNLIKELY(f == mMarker.end())) {
249            std::string tmp;
250            raw_string_ostream out(tmp);
251            out << "PHINode creation error: ";
252            var->print(out);
253            out << " is uninitialized prior to entering ";
254            whileStatement->print(out);
255            report_fatal_error(out.str());
256        }
257        Value * entryValue = f->second;
258        PHINode * phi = iBuilder->CreatePHI(entryValue->getType(), 2, var->getName());
259        phi->addIncoming(entryValue, whileEntryBlock);
260        f->second = phi;
261        assert(mMarker[var] == phi);
262        variants.emplace_back(var, phi);
263    }
264#ifdef ENABLE_BOUNDED_WHILE
265    if (whileStatement->getBound()) {
266        bound_phi = iBuilder->CreatePHI(iBuilder->getSizeTy(), 2, "while_bound");
267        bound_phi->addIncoming(iBuilder->getSize(whileStatement->getBound()), whileEntryBlock);
268    }
269#endif
270
271    mCarryManager->enterLoopBody(whileEntryBlock);
272
273    //
274    // Now compile the loop body proper.  Carry-out accumulated values
275    // and iterated values of Next nodes will be computed.
276    compileBlock(whileBody);
277
278    // After the whileBody has been compiled, we may be in a different basic block.
279    BasicBlock * whileExitBlock = iBuilder->GetInsertBlock();
280
281    mCarryManager->leaveLoopBody(whileExitBlock);
282
283    // Terminate the while loop body with a conditional branch back.
284    Value * condition = compileExpression(whileStatement->getCondition());
285    if (condition->getType() == iBuilder->getBitBlockType()) {
286        condition = iBuilder->bitblock_any(condition);
287    }
288#ifdef ENABLE_BOUNDED_WHILE
289    if (whileStatement->getBound()) {
290        Value * new_bound = iBuilder->CreateSub(bound_phi, iBuilder->getSize(1));
291        bound_phi->addIncoming(new_bound, whileExitBlock);
292        condition = iBuilder->CreateAnd(condition, iBuilder->CreateICmpUGT(new_bound, ConstantInt::getNullValue(iBuilder->getSizeTy())));
293    }
294#endif
295
296    // and for any variant nodes in the loop body
297    for (const auto variant : variants) {
298        const Var * var; PHINode * incomingPhi;
299        std::tie(var, incomingPhi) = variant;
300        const auto f = mMarker.find(var);
301        if (LLVM_UNLIKELY(f == mMarker.end())) {
302            std::string tmp;
303            raw_string_ostream out(tmp);
304            out << "PHINode creation error: ";
305            var->print(out);
306            out << " is no longer assigned a value.";
307            report_fatal_error(out.str());
308        }
309
310        Value * const outgoingValue = f->second;
311
312        if (LLVM_UNLIKELY(incomingPhi->getType() != outgoingValue->getType())) {
313            std::string tmp;
314            raw_string_ostream out(tmp);
315            out << "PHINode creation error: incoming type of ";
316            var->print(out);
317            out << " (";
318            incomingPhi->getType()->print(out);
319            out << ") differs from the outgoing type (";
320            outgoingValue->getType()->print(out);
321            out << ") within ";
322            whileStatement->print(out);
323            report_fatal_error(out.str());
324        }
325
326        incomingPhi->addIncoming(outgoingValue, whileExitBlock);
327        f->second = incomingPhi;
328    }
329
330    iBuilder->CreateCondBr(condition, whileBodyBlock, whileEndBlock);
331
332    iBuilder->SetInsertPoint(whileEndBlock);
333
334    mCarryManager->leaveLoopScope(whileEntryBlock, whileExitBlock);
335
336}
337
338void PabloCompiler::compileStatement(const Statement * const stmt) {
339
340    if (LLVM_UNLIKELY(isa<If>(stmt))) {
341        compileIf(cast<If>(stmt));
342    } else if (LLVM_UNLIKELY(isa<While>(stmt))) {
343        compileWhile(cast<While>(stmt));
344    } else {
345        const PabloAST * expr = stmt;
346        Value * value = nullptr;
347        if (LLVM_UNLIKELY(isa<Assign>(stmt))) {
348
349            value = compileExpression(cast<Assign>(stmt)->getValue());
350
351            expr = cast<Assign>(stmt)->getVariable();
352
353            bool storeRequired = false;
354
355            if (LLVM_LIKELY(isa<Var>(expr))) {
356                const Var * var = cast<Var>(expr);
357                if (LLVM_UNLIKELY(var->isReadOnly())) {
358                    std::string tmp;
359                    raw_string_ostream out(tmp);
360                    out << "cannot assign value to ";
361                    var->print(out);
362                    out << ": ";
363                    var->print(out);
364                    out << " is read only";
365                    report_fatal_error(out.str());
366                }
367                storeRequired = var->isKernelParameter();
368            }
369
370            if (storeRequired || isa<Extract>(expr)) {
371                const auto f = mMarker.find(expr);
372                if (LLVM_UNLIKELY(f == mMarker.end())) {
373                    std::string tmp;
374                    raw_string_ostream out(tmp);
375                    out << "cannot assign value to ";
376                    expr->print(out);
377                    out << ": ";
378                    expr->print(out);
379                    out << " does not dominate ";
380                    stmt->print(out);
381                    report_fatal_error(out.str());
382                }
383                Value * const ptr = f->second;
384                iBuilder->CreateAlignedStore(value, ptr, getAlignment(value));
385                value = ptr;
386            }
387
388        } else if (const Extract * extract = dyn_cast<Extract>(stmt)) {
389            Value * index = compileExpression(extract->getIndex());
390            Var * const array = dyn_cast<Var>(extract->getArray());
391            if (LLVM_LIKELY(array && array->isKernelParameter())) {
392                if (array->isReadOnly()) {
393                    value = mKernel->getInputStream(array->getName(), index);
394                } else if (array->isReadNone()) {
395                    value = mKernel->getOutputStream(array->getName(), index);
396                } else {
397                    std::string tmp;
398                    raw_string_ostream out(tmp);
399                    out << "stream ";
400                    expr->print(out);
401                    out << " cannot be read or written to";
402                    report_fatal_error(out.str());
403                }
404            } else {
405                Value * ptr = compileExpression(extract->getArray(), false);
406                value = iBuilder->CreateGEP(ptr, {ConstantInt::getNullValue(index->getType()), index}, "extract");
407            }
408        } else if (isa<And>(stmt)) {
409            value = compileExpression(stmt->getOperand(0));
410            for (unsigned i = 1; i < stmt->getNumOperands(); ++i) {
411                value = iBuilder->simd_and(value, compileExpression(stmt->getOperand(1)));
412            }
413        } else if (isa<Or>(stmt)) {
414            value = compileExpression(stmt->getOperand(0));
415            for (unsigned i = 1; i < stmt->getNumOperands(); ++i) {
416                value = iBuilder->simd_or(value, compileExpression(stmt->getOperand(1)));
417            }
418        } else if (isa<Xor>(stmt)) {
419            value = compileExpression(stmt->getOperand(0));
420            for (unsigned i = 1; i < stmt->getNumOperands(); ++i) {
421                value = iBuilder->simd_xor(value, compileExpression(stmt->getOperand(1)));
422            }
423        } else if (const Sel * sel = dyn_cast<Sel>(stmt)) {
424            Value* ifMask = compileExpression(sel->getCondition());
425            Value* ifTrue = iBuilder->simd_and(ifMask, compileExpression(sel->getTrueExpr()));
426            Value* ifFalse = iBuilder->simd_and(iBuilder->simd_not(ifMask), compileExpression(sel->getFalseExpr()));
427            value = iBuilder->simd_or(ifTrue, ifFalse);
428        } else if (isa<Not>(stmt)) {
429            value = iBuilder->simd_not(compileExpression(stmt->getOperand(0)));
430        } else if (isa<Advance>(stmt)) {
431            const Advance * const adv = cast<Advance>(stmt);
432            // If our expr is an Extract op on a mutable Var then we need to pass the index value to the carry
433            // manager so that it properly selects the correct carry bit.
434            value = mCarryManager->advanceCarryInCarryOut(adv, compileExpression(adv->getExpression()));
435        } else if (const MatchStar * mstar = dyn_cast<MatchStar>(stmt)) {
436            Value * const marker = compileExpression(mstar->getMarker());
437            Value * const cc = compileExpression(mstar->getCharClass());
438            Value * const marker_and_cc = iBuilder->simd_and(marker, cc);
439            Value * const sum = mCarryManager->addCarryInCarryOut(mstar, marker_and_cc, cc);
440            value = iBuilder->simd_or(iBuilder->simd_xor(sum, cc), marker);
441        } else if (const ScanThru * sthru = dyn_cast<ScanThru>(stmt)) {
442            Value * const marker_expr = compileExpression(sthru->getScanFrom());
443            Value * const cc_expr = compileExpression(sthru->getScanThru());
444            Value * const sum = mCarryManager->addCarryInCarryOut(sthru, marker_expr, cc_expr);
445            value = iBuilder->simd_and(sum, iBuilder->simd_not(cc_expr));
446        } else if (const InFile * e = dyn_cast<InFile>(stmt)) {
447            Value * EOFmask = mKernel->getScalarField("EOFmask");
448            value = iBuilder->simd_xor(compileExpression(e->getExpr()), EOFmask);
449        } else if (const AtEOF * e = dyn_cast<AtEOF>(stmt)) {
450            Value * EOFbit = mKernel->getScalarField("EOFbit");
451            value = iBuilder->simd_and(compileExpression(e->getExpr()), EOFbit);
452        } else if (const Count * c = dyn_cast<Count>(stmt)) {
453            Value * const to_count = compileExpression(c->getExpr());
454            const unsigned counterSize = iBuilder->getSizeTy()->getBitWidth();
455            const auto f = mAccumulator.find(c);
456            if (LLVM_UNLIKELY(f == mAccumulator.end())) {
457                report_fatal_error("Unknown accumulator: " + c->getName().str());
458            }
459            Value * ptr = mKernel->getScalarFieldPtr(f->second);
460            Value * count = iBuilder->CreateAlignedLoad(ptr, getPointerElementAlignment(ptr));
461            Value * const partial = iBuilder->simd_popcount(counterSize, to_count);
462            if (LLVM_UNLIKELY(counterSize <= 1)) {
463                value = partial;
464            } else {
465                value = iBuilder->mvmd_extract(counterSize, partial, 0);
466                const auto fields = (iBuilder->getBitBlockWidth() / counterSize);
467                for (unsigned i = 1; i < fields; ++i) {
468                    Value * temp = iBuilder->mvmd_extract(counterSize, partial, i);
469                    value = iBuilder->CreateAdd(value, temp);
470                }
471            }
472            value = iBuilder->CreateAdd(value, count);
473            iBuilder->CreateStore(value, ptr);
474
475        } else if (const Lookahead * l = dyn_cast<Lookahead>(stmt)) {
476            PabloAST * const var = l->getExpr();
477            if (LLVM_UNLIKELY(!isa<Var>(var))) {
478                throw std::runtime_error("Lookahead operations may only be applied to input streams");
479            }
480            unsigned index = 0;
481            for (; index < mKernel->getNumOfInputs(); ++index) {
482                if (mKernel->getInput(index) == var) {
483                    break;
484                }
485            }
486            if (LLVM_UNLIKELY(index >= mKernel->getNumOfInputs())) {
487                throw std::runtime_error("Lookahead has an illegal Var operand");
488            }
489            const unsigned bit_shift = (l->getAmount() % iBuilder->getBitBlockWidth());
490            const unsigned block_shift = (l->getAmount() / iBuilder->getBitBlockWidth());
491            std::string inputName = cast<Var>(var)->getName().str();
492            Value * blockNo = mKernel->getBlockNo();
493            Value * lookAhead_blockPtr  = mKernel->getInputStreamSetPtr(inputName, iBuilder->CreateAdd(blockNo, iBuilder->getSize(block_shift)));
494            Value * lookAhead_inputPtr = iBuilder->CreateGEP(lookAhead_blockPtr, {iBuilder->getInt32(0), iBuilder->getInt32(index)});
495            Value * lookAhead = iBuilder->CreateBlockAlignedLoad(lookAhead_inputPtr);
496            if (bit_shift == 0) {  // Simple case with no intra-block shifting.
497                value = lookAhead;
498            } else { // Need to form shift result from two adjacent blocks.
499                Value * lookAhead_blockPtr1  = mKernel->getInputStreamSetPtr(inputName, iBuilder->CreateAdd(blockNo, iBuilder->getSize(block_shift + 1)));
500                Value * lookAhead_inputPtr1 = iBuilder->CreateGEP(lookAhead_blockPtr1, {iBuilder->getInt32(0), iBuilder->getInt32(index)});
501                Value * lookAhead1 = iBuilder->CreateBlockAlignedLoad(lookAhead_inputPtr1);
502                if (LLVM_UNLIKELY((bit_shift % 8) == 0)) { // Use a single whole-byte shift, if possible.
503                    value = iBuilder->mvmd_dslli(8, lookAhead1, lookAhead, (bit_shift / 8));
504                } else {
505                    Type  * const streamType = iBuilder->getIntNTy(iBuilder->getBitBlockWidth());
506                    Value * b1 = iBuilder->CreateBitCast(lookAhead1, streamType);
507                    Value * b0 = iBuilder->CreateBitCast(lookAhead, streamType);
508                    Value * result = iBuilder->CreateOr(iBuilder->CreateShl(b1, iBuilder->getBitBlockWidth() - bit_shift), iBuilder->CreateLShr(b0, bit_shift));
509                    value = iBuilder->CreateBitCast(result, iBuilder->getBitBlockType());
510                }
511            }
512
513        } else {
514            std::string tmp;
515            raw_string_ostream out(tmp);
516            out << "Internal error: ";
517            stmt->print(out);
518            out << " is not a recognized statement in the Pablo compiler.";
519            throw std::runtime_error(out.str());
520        }
521
522        mMarker[expr] = value;
523        if (DebugOptionIsSet(DumpTrace)) {
524            const String & name = isa<Var>(expr) ? cast<Var>(expr)->getName() : cast<Statement>(expr)->getName();
525            if (value->getType()->isVectorTy()) {
526                iBuilder->CallPrintRegister(name.str(), value);
527            } else if (value->getType()->isIntegerTy()) {
528                iBuilder->CallPrintInt(name.str(), value);
529            }
530        }
531    }
532}
533
534Value * PabloCompiler::compileExpression(const PabloAST * expr, const bool ensureLoaded) const {
535    if (LLVM_UNLIKELY(isa<Ones>(expr))) {
536        return iBuilder->allOnes();
537    } else if (LLVM_UNLIKELY(isa<Zeroes>(expr))) {
538        return iBuilder->allZeroes();
539    } else if (LLVM_UNLIKELY(isa<Integer>(expr))) {
540        return ConstantInt::get(cast<Integer>(expr)->getType(), cast<Integer>(expr)->value());
541    } else if (LLVM_UNLIKELY(isa<Operator>(expr))) {
542        const Operator * op = cast<Operator>(expr);
543        Value * lh = compileExpression(op->getLH());
544        Value * rh = compileExpression(op->getRH());
545        if (LLVM_UNLIKELY(lh->getType() != rh->getType())) {
546            std::string tmp;
547            raw_string_ostream out(tmp);
548            out << "Operator creation error: left hand type of ";
549            expr->print(out);
550            out << " (";
551            lh->getType()->print(out);
552            out << ") differs from right hand type (";
553            rh->getType()->print(out);
554            out << ")";
555            report_fatal_error(out.str());
556        }
557        switch (op->getClassTypeId()) {
558            case TypeId::Add:
559                return iBuilder->CreateAdd(lh, rh);
560            case TypeId::Subtract:
561                return iBuilder->CreateSub(lh, rh);
562            case TypeId::LessThan:
563                return iBuilder->CreateICmpSLT(lh, rh);
564            case TypeId::LessThanEquals:
565                return iBuilder->CreateICmpSLE(lh, rh);
566            case TypeId::Equals:
567                return iBuilder->CreateICmpEQ(lh, rh);
568            case TypeId::GreaterThanEquals:
569                return iBuilder->CreateICmpSGE(lh, rh);
570            case TypeId::GreaterThan:
571                return iBuilder->CreateICmpSGT(lh, rh);
572            case TypeId::NotEquals:
573                return iBuilder->CreateICmpNE(lh, rh);
574            default: break;
575        }
576        std::string tmp;
577        raw_string_ostream out(tmp);
578        expr->print(out);
579        out << " is not a valid Operator";
580        report_fatal_error(out.str());
581    }
582    const auto f = mMarker.find(expr);
583    if (LLVM_UNLIKELY(f == mMarker.end())) {
584        std::string tmp;
585        raw_string_ostream out(tmp);
586        out << "Compilation error: ";
587        expr->print(out);
588        out << " was used before definition!";
589        report_fatal_error(out.str());
590    }
591    Value * value = f->second;
592    if (LLVM_UNLIKELY(isa<GetElementPtrInst>(value) && ensureLoaded)) {
593        value = iBuilder->CreateAlignedLoad(value, getPointerElementAlignment(value));
594    }
595    return value;
596}
597
598PabloCompiler::PabloCompiler(PabloKernel * kernel)
599: iBuilder(kernel->getBuilder())
600, mKernel(kernel)
601, mCarryManager(new CarryManager(iBuilder)) {
602
603}
604
605PabloCompiler::~PabloCompiler() {
606    delete mCarryManager;
607}
608
609}
Note: See TracBrowser for help on using the repository browser.