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

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

Start of work to simplify kernel writing. Removed generateDoBlockLogic method.

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