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

Last change on this file since 5317 was 5317, checked in by cameron, 2 years ago

Simplify stream set access; better naming of access functions

File size: 24.7 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->getInputStreamBlockPtr(array->getName(), index);
394                } else if (array->isReadNone()) {
395                    value = mKernel->getOutputStreamBlockPtr(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            Var * var = nullptr;
477            PabloAST * stream = l->getExpr();
478            Value * index = iBuilder->getInt32(0);
479
480            if (LLVM_UNLIKELY(isa<Extract>(stream))) {
481                stream = cast<Extract>(stream)->getArray();
482                index = compileExpression(cast<Extract>(stream)->getIndex());
483            }
484            if (LLVM_LIKELY(isa<Var>(stream))) {
485                var = cast<Var>(stream);
486                if (!var->isKernelParameter() || var->isReadNone()) {
487                    std::string tmp;
488                    raw_string_ostream out(tmp);
489                    out << "Lookahead operation cannot be applied to ";
490                    stmt->print(out);
491                    out << ": ";
492                    var->print(out);
493                    out << " is not an input stream";
494                    report_fatal_error(out.str());
495                }
496            }
497
498            const auto bit_shift = (l->getAmount() % iBuilder->getBitBlockWidth());
499            const auto block_shift = (l->getAmount() / iBuilder->getBitBlockWidth());
500
501            Value * ptr = mKernel->getAdjustedInputStreamBlockPtr(iBuilder->getSize(block_shift), var->getName(), index);
502            Value * lookAhead = iBuilder->CreateBlockAlignedLoad(ptr);
503            if (bit_shift == 0) {  // Simple case with no intra-block shifting.
504                value = lookAhead;
505            } else { // Need to form shift result from two adjacent blocks.
506                Value * ptr = mKernel->getAdjustedInputStreamBlockPtr(iBuilder->getSize(block_shift + 1), var->getName(), index);
507                Value * lookAhead1 = iBuilder->CreateBlockAlignedLoad(ptr);
508                if (LLVM_UNLIKELY((bit_shift % 8) == 0)) { // Use a single whole-byte shift, if possible.
509                    value = iBuilder->mvmd_dslli(8, lookAhead1, lookAhead, (bit_shift / 8));
510                } else {
511                    Type  * const streamType = iBuilder->getIntNTy(iBuilder->getBitBlockWidth());
512                    Value * b1 = iBuilder->CreateBitCast(lookAhead1, streamType);
513                    Value * b0 = iBuilder->CreateBitCast(lookAhead, streamType);
514                    Value * result = iBuilder->CreateOr(iBuilder->CreateShl(b1, iBuilder->getBitBlockWidth() - bit_shift), iBuilder->CreateLShr(b0, bit_shift));
515                    value = iBuilder->CreateBitCast(result, iBuilder->getBitBlockType());
516                }
517            }
518
519        } else {
520            std::string tmp;
521            raw_string_ostream out(tmp);
522            out << "Internal error: ";
523            stmt->print(out);
524            out << " is not a recognized statement in the Pablo compiler.";
525            throw std::runtime_error(out.str());
526        }
527
528        mMarker[expr] = value;
529        if (DebugOptionIsSet(DumpTrace)) {
530            const String & name = isa<Var>(expr) ? cast<Var>(expr)->getName() : cast<Statement>(expr)->getName();
531            if (value->getType()->isVectorTy()) {
532                iBuilder->CallPrintRegister(name.str(), value);
533            } else if (value->getType()->isIntegerTy()) {
534                iBuilder->CallPrintInt(name.str(), value);
535            }
536        }
537    }
538}
539
540Value * PabloCompiler::compileExpression(const PabloAST * expr, const bool ensureLoaded) const {
541    if (LLVM_UNLIKELY(isa<Ones>(expr))) {
542        return iBuilder->allOnes();
543    } else if (LLVM_UNLIKELY(isa<Zeroes>(expr))) {
544        return iBuilder->allZeroes();
545    } else if (LLVM_UNLIKELY(isa<Integer>(expr))) {
546        return ConstantInt::get(cast<Integer>(expr)->getType(), cast<Integer>(expr)->value());
547    } else if (LLVM_UNLIKELY(isa<Operator>(expr))) {
548        const Operator * op = cast<Operator>(expr);
549        Value * lh = compileExpression(op->getLH());
550        Value * rh = compileExpression(op->getRH());
551        if (LLVM_UNLIKELY(lh->getType() != rh->getType())) {
552            std::string tmp;
553            raw_string_ostream out(tmp);
554            out << "Operator creation error: left hand type of ";
555            expr->print(out);
556            out << " (";
557            lh->getType()->print(out);
558            out << ") differs from right hand type (";
559            rh->getType()->print(out);
560            out << ")";
561            report_fatal_error(out.str());
562        }
563        switch (op->getClassTypeId()) {
564            case TypeId::Add:
565                return iBuilder->CreateAdd(lh, rh);
566            case TypeId::Subtract:
567                return iBuilder->CreateSub(lh, rh);
568            case TypeId::LessThan:
569                return iBuilder->CreateICmpSLT(lh, rh);
570            case TypeId::LessThanEquals:
571                return iBuilder->CreateICmpSLE(lh, rh);
572            case TypeId::Equals:
573                return iBuilder->CreateICmpEQ(lh, rh);
574            case TypeId::GreaterThanEquals:
575                return iBuilder->CreateICmpSGE(lh, rh);
576            case TypeId::GreaterThan:
577                return iBuilder->CreateICmpSGT(lh, rh);
578            case TypeId::NotEquals:
579                return iBuilder->CreateICmpNE(lh, rh);
580            default: break;
581        }
582        std::string tmp;
583        raw_string_ostream out(tmp);
584        expr->print(out);
585        out << " is not a valid Operator";
586        report_fatal_error(out.str());
587    }
588    const auto f = mMarker.find(expr);
589    if (LLVM_UNLIKELY(f == mMarker.end())) {
590        std::string tmp;
591        raw_string_ostream out(tmp);
592        out << "Compilation error: ";
593        expr->print(out);
594        out << " was used before definition!";
595        report_fatal_error(out.str());
596    }
597    Value * value = f->second;
598    if (LLVM_UNLIKELY(isa<GetElementPtrInst>(value) && ensureLoaded)) {
599        value = iBuilder->CreateAlignedLoad(value, getPointerElementAlignment(value));
600    }
601    return value;
602}
603
604PabloCompiler::PabloCompiler(PabloKernel * kernel)
605: iBuilder(kernel->getBuilder())
606, mKernel(kernel)
607, mCarryManager(new CarryManager(iBuilder)) {
608
609}
610
611PabloCompiler::~PabloCompiler() {
612    delete mCarryManager;
613}
614
615}
Note: See TracBrowser for help on using the repository browser.