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

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

Partial removal of BlockNo?

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