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

Last change on this file since 4541 was 4541, checked in by cameron, 4 years ago

New carry data system -- first stage

File size: 42.6 KB
Line 
1/*
2 *  Copyright (c) 2014-15 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/pablo_compiler.h>
8#include <pablo/codegenstate.h>
9#include <pablo/printer_pablos.h>
10#include <cc/cc_namemap.hpp>
11#include <re/re_name.h>
12#include <stdexcept>
13#include <include/simd-lib/bitblock.hpp>
14#include <sstream>
15#include <llvm/IR/Verifier.h>
16#include <llvm/Pass.h>
17#include <llvm/PassManager.h>
18#include <llvm/ADT/SmallVector.h>
19#include <llvm/Analysis/Passes.h>
20#include <llvm/IR/BasicBlock.h>
21#include <llvm/IR/CallingConv.h>
22#include <llvm/IR/Constants.h>
23#include <llvm/IR/DataLayout.h>
24#include <llvm/IR/DerivedTypes.h>
25#include <llvm/IR/Function.h>
26#include <llvm/IR/GlobalVariable.h>
27#include <llvm/IR/InlineAsm.h>
28#include <llvm/IR/Instructions.h>
29#include <llvm/IR/LLVMContext.h>
30#include <llvm/IR/Module.h>
31#include <llvm/Support/FormattedStream.h>
32#include <llvm/Support/MathExtras.h>
33#include <llvm/Support/Casting.h>
34#include <llvm/Support/Compiler.h>
35#include <llvm/Support/Debug.h>
36#include <llvm/Support/TargetSelect.h>
37#include <llvm/Support/Host.h>
38#include <llvm/Transforms/Scalar.h>
39#include <llvm/ExecutionEngine/ExecutionEngine.h>
40#include <llvm/ExecutionEngine/MCJIT.h>
41#include <llvm/IRReader/IRReader.h>
42#include <llvm/Bitcode/ReaderWriter.h>
43#include <llvm/Support/MemoryBuffer.h>
44#include <llvm/IR/IRBuilder.h>
45#include <llvm/Support/CommandLine.h>
46#include <llvm/ADT/Twine.h>
47#include <iostream>
48
49cl::OptionCategory eIRDumpOptions("LLVM IR Dump Options", "These options control dumping of LLVM IR.");
50static cl::opt<bool> DumpGeneratedIR("dump-generated-IR", cl::init(false), cl::desc("print LLVM IR generated by RE compilation"), cl::cat(eIRDumpOptions));
51
52extern "C" {
53  void wrapped_print_register(BitBlock bit_block) {
54      print_register<BitBlock>("", bit_block);
55  }
56}
57
58namespace pablo {
59
60PabloCompiler::PabloCompiler(const std::vector<Var*> & basisBits)
61: mBasisBits(basisBits)
62, mMod(new Module("icgrep", getGlobalContext()))
63, mBasicBlock(nullptr)
64, mExecutionEngine(nullptr)
65, mBitBlockType(VectorType::get(IntegerType::get(mMod->getContext(), 64), BLOCK_SIZE / 64))
66, mBasisBitsInputPtr(nullptr)
67, mCarryDataPtr(nullptr)
68, mNestingDepth(0)
69, mZeroInitializer(ConstantAggregateZero::get(mBitBlockType))
70, mOneInitializer(ConstantVector::getAllOnesValue(mBitBlockType))
71, mFunctionType(nullptr)
72, mFunction(nullptr)
73, mBasisBitsAddr(nullptr)
74, mOutputAddrPtr(nullptr)
75, mMaxNestingDepth(0)
76, mPrintRegisterFunction(nullptr)
77{
78    //Create the jit execution engine.up
79    InitializeNativeTarget();
80    InitializeNativeTargetAsmPrinter();
81    InitializeNativeTargetAsmParser();
82    DefineTypes();
83}
84
85PabloCompiler::~PabloCompiler()
86{
87
88}
89   
90void PabloCompiler::InstallExternalFunction(std::string C_fn_name, void * fn_ptr) {
91    mExternalMap.insert(std::make_pair(C_fn_name, fn_ptr));
92}
93
94
95CompiledPabloFunction PabloCompiler::compile(PabloBlock & pb)
96{
97    mNestingDepth = 0;
98    mMaxNestingDepth = 0;
99    unsigned totalCarryDataSize = Examine(pb, 0); 
100    mCarryDataVector.resize(totalCarryDataSize);
101    mCarryDataSummaryIdx.resize(totalCarryDataSize);
102    std::string errMessage;
103    EngineBuilder builder(mMod);
104    builder.setErrorStr(&errMessage);
105    builder.setMCPU(sys::getHostCPUName());
106    builder.setUseMCJIT(true);
107    builder.setOptLevel(mMaxNestingDepth ? CodeGenOpt::Level::Less : CodeGenOpt::Level::None);
108    mExecutionEngine = builder.create();
109    if (mExecutionEngine == nullptr) {
110        throw std::runtime_error("Could not create ExecutionEngine: " + errMessage);
111    }
112    DeclareFunctions();
113
114    DeclareCallFunctions();
115
116    Function::arg_iterator args = mFunction->arg_begin();
117    mBasisBitsAddr = args++;
118    mBasisBitsAddr->setName("basis_bits");
119    mCarryDataPtr = args++;
120    mCarryDataPtr->setName("carry_data");
121    mOutputAddrPtr = args++;
122    mOutputAddrPtr->setName("output");
123
124    mNestingDepth = 0;
125    mMaxNestingDepth = 0;
126    mBasicBlock = BasicBlock::Create(mMod->getContext(), "parabix_entry", mFunction,0);
127
128    //The basis bits structure
129    for (unsigned i = 0; i != mBasisBits.size(); ++i) {
130        IRBuilder<> b(mBasicBlock);
131        Value* indices[] = {b.getInt64(0), b.getInt32(i)};
132        Value * gep = b.CreateGEP(mBasisBitsAddr, indices);
133        LoadInst * basisBit = b.CreateAlignedLoad(gep, BLOCK_SIZE/8, false, mBasisBits[i]->getName()->to_string());
134        mMarkerMap.insert(std::make_pair(mBasisBits[i], basisBit));
135    }
136
137    //Generate the IR instructions for the function.
138    compileBlock(pb);
139
140    if (LLVM_UNLIKELY(mNestingDepth != 0)) {
141        throw std::runtime_error("Non-zero nesting depth error (" + std::to_string(mNestingDepth) + ")");
142    }
143
144    //Terminate the block
145    ReturnInst::Create(mMod->getContext(), mBasicBlock);
146
147    //Display the IR that has been generated by this module.
148    if (LLVM_UNLIKELY(DumpGeneratedIR)) {
149        mMod->dump();
150    }
151    //Create a verifier.  The verifier will print an error message if our module is malformed in any way.
152    verifyModule(*mMod, &dbgs());
153
154    mExecutionEngine->finalizeObject();
155
156    //Return the required size of the carry data area to the process_block function.
157    // Reserve 1 element in the carry data area for current block number (future). TODO
158    return CompiledPabloFunction((totalCarryDataSize + 1) * sizeof(BitBlock), mFunction, mExecutionEngine);
159}
160
161void PabloCompiler::DefineTypes()
162{
163    StructType * structBasisBits = mMod->getTypeByName("struct.Basis_bits");
164    if (structBasisBits == nullptr) {
165        structBasisBits = StructType::create(mMod->getContext(), "struct.Basis_bits");
166    }
167    std::vector<Type*>StructTy_struct_Basis_bits_fields;
168    for (int i = 0; i != mBasisBits.size(); i++)
169    {
170        StructTy_struct_Basis_bits_fields.push_back(mBitBlockType);
171    }
172    if (structBasisBits->isOpaque()) {
173        structBasisBits->setBody(StructTy_struct_Basis_bits_fields, /*isPacked=*/false);
174    }
175    mBasisBitsInputPtr = PointerType::get(structBasisBits, 0);
176
177    std::vector<Type*>functionTypeArgs;
178    functionTypeArgs.push_back(mBasisBitsInputPtr);
179
180    //The carry data array.
181    //A pointer to the BitBlock vector.
182    functionTypeArgs.push_back(PointerType::get(mBitBlockType, 0));
183
184    //The output structure.
185    StructType * outputStruct = mMod->getTypeByName("struct.Output");
186    if (!outputStruct) {
187        outputStruct = StructType::create(mMod->getContext(), "struct.Output");
188    }
189    if (outputStruct->isOpaque()) {
190        std::vector<Type*>fields;
191        fields.push_back(mBitBlockType);
192        fields.push_back(mBitBlockType);
193        outputStruct->setBody(fields, /*isPacked=*/false);
194    }
195    PointerType* outputStructPtr = PointerType::get(outputStruct, 0);
196
197    //The &output parameter.
198    functionTypeArgs.push_back(outputStructPtr);
199
200    mFunctionType = FunctionType::get(
201     /*Result=*/Type::getVoidTy(mMod->getContext()),
202     /*Params=*/functionTypeArgs,
203     /*isVarArg=*/false);
204}
205
206void PabloCompiler::DeclareFunctions()
207{
208    //This function can be used for testing to print the contents of a register from JIT'd code to the terminal window.
209    mPrintRegisterFunction = mMod->getOrInsertFunction("wrapped_print_register", Type::getVoidTy(getGlobalContext()), mBitBlockType, NULL);
210    mExecutionEngine->addGlobalMapping(cast<GlobalValue>(mPrintRegisterFunction), (void *)&wrapped_print_register);
211    // to call->  b.CreateCall(mFunc_print_register, unicode_category);
212
213#ifdef USE_UADD_OVERFLOW
214#ifdef USE_TWO_UADD_OVERFLOW
215    // Type Definitions for llvm.uadd.with.overflow.carryin.i128 or .i256
216    std::vector<Type*>StructTy_0_fields;
217    StructTy_0_fields.push_back(IntegerType::get(mMod->getContext(), BLOCK_SIZE));
218    StructTy_0_fields.push_back(IntegerType::get(mMod->getContext(), 1));
219    StructType *StructTy_0 = StructType::get(mMod->getContext(), StructTy_0_fields, /*isPacked=*/false);
220
221    std::vector<Type*>FuncTy_1_args;
222    FuncTy_1_args.push_back(IntegerType::get(mMod->getContext(), BLOCK_SIZE));
223    FuncTy_1_args.push_back(IntegerType::get(mMod->getContext(), BLOCK_SIZE));
224    FunctionType* FuncTy_1 = FunctionType::get(
225                                              /*Result=*/StructTy_0,
226                                              /*Params=*/FuncTy_1_args,
227                                              /*isVarArg=*/false);
228
229    mFunctionUaddOverflow = mMod->getFunction("llvm.uadd.with.overflow.i" +
230                                              std::to_string(BLOCK_SIZE));
231    if (!mFunctionUaddOverflow) {
232        mFunctionUaddOverflow= Function::Create(
233          /*Type=*/ FuncTy_1,
234          /*Linkage=*/ GlobalValue::ExternalLinkage,
235          /*Name=*/ "llvm.uadd.with.overflow.i" + std::to_string(BLOCK_SIZE), mMod); // (external, no body)
236        mFunctionUaddOverflow->setCallingConv(CallingConv::C);
237    }
238    AttributeSet mFunctionUaddOverflowPAL;
239    {
240        SmallVector<AttributeSet, 4> Attrs;
241        AttributeSet PAS;
242        {
243          AttrBuilder B;
244          B.addAttribute(Attribute::NoUnwind);
245          B.addAttribute(Attribute::ReadNone);
246          PAS = AttributeSet::get(mMod->getContext(), ~0U, B);
247        }
248
249        Attrs.push_back(PAS);
250        mFunctionUaddOverflowPAL = AttributeSet::get(mMod->getContext(), Attrs);
251    }
252    mFunctionUaddOverflow->setAttributes(mFunctionUaddOverflowPAL);
253#else
254    // Type Definitions for llvm.uadd.with.overflow.carryin.i128 or .i256
255    std::vector<Type*>StructTy_0_fields;
256    StructTy_0_fields.push_back(IntegerType::get(mMod->getContext(), BLOCK_SIZE));
257    StructTy_0_fields.push_back(IntegerType::get(mMod->getContext(), 1));
258    StructType *StructTy_0 = StructType::get(mMod->getContext(), StructTy_0_fields, /*isPacked=*/false);
259
260    std::vector<Type*>FuncTy_1_args;
261    FuncTy_1_args.push_back(IntegerType::get(mMod->getContext(), BLOCK_SIZE));
262    FuncTy_1_args.push_back(IntegerType::get(mMod->getContext(), BLOCK_SIZE));
263    FuncTy_1_args.push_back(IntegerType::get(mMod->getContext(), 1));
264    FunctionType* FuncTy_1 = FunctionType::get(
265                                              /*Result=*/StructTy_0,
266                                              /*Params=*/FuncTy_1_args,
267                                              /*isVarArg=*/false);
268
269    mFunctionUaddOverflowCarryin = mMod->getFunction("llvm.uadd.with.overflow.carryin.i" +
270                                              std::to_string(BLOCK_SIZE));
271    if (!mFunctionUaddOverflowCarryin) {
272        mFunctionUaddOverflowCarryin = Function::Create(
273          /*Type=*/ FuncTy_1,
274          /*Linkage=*/ GlobalValue::ExternalLinkage,
275          /*Name=*/ "llvm.uadd.with.overflow.carryin.i" + std::to_string(BLOCK_SIZE), mMod); // (external, no body)
276        mFunctionUaddOverflowCarryin->setCallingConv(CallingConv::C);
277    }
278    AttributeSet mFunctionUaddOverflowCarryinPAL;
279    {
280        SmallVector<AttributeSet, 4> Attrs;
281        AttributeSet PAS;
282        {
283          AttrBuilder B;
284          B.addAttribute(Attribute::NoUnwind);
285          B.addAttribute(Attribute::ReadNone);
286          PAS = AttributeSet::get(mMod->getContext(), ~0U, B);
287        }
288
289        Attrs.push_back(PAS);
290        mFunctionUaddOverflowCarryinPAL = AttributeSet::get(mMod->getContext(), Attrs);
291    }
292    mFunctionUaddOverflowCarryin->setAttributes(mFunctionUaddOverflowCarryinPAL);
293#endif
294#endif
295
296    //Starts on process_block
297    SmallVector<AttributeSet, 4> Attrs;
298    AttributeSet PAS;
299    {
300        AttrBuilder B;
301        B.addAttribute(Attribute::ReadOnly);
302        B.addAttribute(Attribute::NoCapture);
303        PAS = AttributeSet::get(mMod->getContext(), 1U, B);
304    }
305    Attrs.push_back(PAS);
306    {
307        AttrBuilder B;
308        B.addAttribute(Attribute::NoCapture);
309        PAS = AttributeSet::get(mMod->getContext(), 2U, B);
310    }
311    Attrs.push_back(PAS);
312    {
313        AttrBuilder B;
314        B.addAttribute(Attribute::NoCapture);
315        PAS = AttributeSet::get(mMod->getContext(), 3U, B);
316    }
317    Attrs.push_back(PAS);
318    {
319        AttrBuilder B;
320        B.addAttribute(Attribute::NoUnwind);
321        B.addAttribute(Attribute::UWTable);
322        PAS = AttributeSet::get(mMod->getContext(), ~0U, B);
323    }
324    AttributeSet AttrSet = AttributeSet::get(mMod->getContext(), Attrs);
325
326    //Create the function that will be generated.
327    mFunction = mMod->getFunction("process_block");
328    if (!mFunction) {
329        mFunction = Function::Create(
330            /*Type=*/mFunctionType,
331            /*Linkage=*/GlobalValue::ExternalLinkage,
332            /*Name=*/"process_block", mMod);
333        mFunction->setCallingConv(CallingConv::C);
334    }
335    mFunction->setAttributes(AttrSet);
336}
337   
338// CarryDataNumbering
339//
340// For each PabloBlock, a contiguous CarryData area holds carry,
341// and advance values that are generated in one block for use in the
342// next.  For a given block, the carry data area contains the
343// carries, the advances and the nested data for contained blocks,
344// if any.
345// Notes:
346//   (a) an additional data entry is created for each if-statement
347//       having more than one carry or advance opreation within it.  This
348//       additional entry is a summary entry which must be nonzero to
349//       indicate that there are carry or advance bits associated with
350//       any operation within the if-structure (at any nesting level).
351//   (b) advancing by a large amount may require multiple advance entries.
352//       the number of advance entries for an operation Adv(x, n) is
353//       (n + BLOCK_SIZE - 1) / BLOCK_SIZE
354//
355// Examine precomputes some CarryNumbering and AdvanceNumbering, as
356// well as mMaxNestingDepth of while loops.
357//
358unsigned PabloCompiler::Examine(PabloBlock & blk, unsigned carryDataIndexIn) {
359    // Count local carries and advances at this level.
360    unsigned carryDataIndex = carryDataIndexIn;
361    unsigned localCarries = 0;
362    unsigned localAdvances = 0;
363    unsigned nestedCarryDataSize = 0;
364    for (Statement * stmt : blk) {
365        if (Advance * adv = dyn_cast<Advance>(stmt)) {
366            adv->setLocalAdvanceIndex(localAdvances);
367            localAdvances += (adv->getAdvanceAmount() + BLOCK_SIZE - 1) / BLOCK_SIZE;
368        }
369        else if (MatchStar * m = dyn_cast<MatchStar>(stmt)) {
370            m->setLocalCarryIndex(localCarries);
371            ++localCarries;
372        }
373        else if (ScanThru * s = dyn_cast<ScanThru>(stmt)) {
374            s->setLocalCarryIndex(localCarries);
375            ++localCarries;
376        }
377    }
378    carryDataIndex += localCarries + localAdvances;
379    for (Statement * stmt : blk) {
380        if (Call * call = dyn_cast<Call>(stmt)) {
381            mCalleeMap.insert(std::make_pair(call->getCallee(), nullptr));
382        }
383        else if (If * ifStatement = dyn_cast<If>(stmt)) {
384            const auto ifCarryDataSize = Examine(ifStatement->getBody(), carryDataIndex);
385            nestedCarryDataSize += ifCarryDataSize;
386            carryDataIndex += ifCarryDataSize;
387        }
388        else if (While * whileStatement = dyn_cast<While>(stmt)) {
389            mMaxNestingDepth = std::max(mMaxNestingDepth, ++mNestingDepth);
390            const auto whileCarryDataSize = Examine(whileStatement->getBody(), carryDataIndex);
391            --mNestingDepth;
392            nestedCarryDataSize += whileCarryDataSize;
393            carryDataIndex += whileCarryDataSize;
394        }
395    }
396    blk.setCarryIndexBase(carryDataIndexIn);
397    blk.setLocalCarryCount(localCarries);
398    blk.setLocalAdvanceCount(localAdvances);
399    unsigned totalCarryDataSize = localCarries + localAdvances + nestedCarryDataSize;
400    if (totalCarryDataSize > 1) {
401        // Need extra space for the summary variable, always the last
402        // entry within the block.
403        totalCarryDataSize += 1;
404    }
405    blk.setTotalCarryDataSize(totalCarryDataSize);
406    return totalCarryDataSize;
407}
408
409void PabloCompiler::DeclareCallFunctions() {
410    for (auto mapping : mCalleeMap) {
411        const String * callee = mapping.first;
412        //std::cerr << callee->str() << " to be declared\n";
413        auto ei = mExternalMap.find(callee->value());
414        if (ei != mExternalMap.end()) {
415            void * fn_ptr = ei->second;
416            //std::cerr << "Ptr found:" <<  std::hex << ((intptr_t) fn_ptr) << std::endl;
417            Value * externalValue = mMod->getOrInsertFunction(callee->value(), mBitBlockType, mBasisBitsInputPtr, NULL);
418            if (LLVM_UNLIKELY(externalValue == nullptr)) {
419                throw std::runtime_error("Could not create static method call for external function \"" + callee->to_string() + "\"");
420            }
421            mExecutionEngine->addGlobalMapping(cast<GlobalValue>(externalValue), fn_ptr);
422            mCalleeMap[callee] = externalValue;
423        }
424        else {
425            throw std::runtime_error("External function \"" + callee->to_string() + "\" not installed");
426        }
427    }
428}
429
430void PabloCompiler::compileBlock(const PabloBlock & blk) {
431    for (const Statement * statement : blk) {
432        compileStatement(statement);
433    }
434}
435
436
437
438
439void PabloCompiler::compileIf(const If * ifStatement) {       
440        //
441        //  The If-ElseZero stmt:
442        //  if <predicate:expr> then <body:stmt>* elsezero <defined:var>* endif
443        //  If the value of the predicate is nonzero, then determine the values of variables
444        //  <var>* by executing the given statements.  Otherwise, the value of the
445        //  variables are all zero.  Requirements: (a) no variable that is defined within
446        //  the body of the if may be accessed outside unless it is explicitly
447        //  listed in the variable list, (b) every variable in the defined list receives
448        //  a value within the body, and (c) the logical consequence of executing
449        //  the statements in the event that the predicate is zero is that the
450        //  values of all defined variables indeed work out to be 0.
451        //
452        //  Simple Implementation with Phi nodes:  a phi node in the if exit block
453        //  is inserted for each variable in the defined variable list.  It receives
454        //  a zero value from the ifentry block and the defined value from the if
455        //  body.
456        //
457        BasicBlock * ifEntryBlock = mBasicBlock;  // The block we are in.
458        BasicBlock * ifBodyBlock = BasicBlock::Create(mMod->getContext(), "if.body", mFunction, 0);
459        BasicBlock * ifEndBlock = BasicBlock::Create(mMod->getContext(), "if.end", mFunction, 0);
460       
461        IRBuilder<> b_entry(ifEntryBlock);
462        mBasicBlock = ifEntryBlock;
463   
464        const unsigned baseCarryDataIdx = ifStatement->getBody().getCarryIndexBase();
465        const unsigned carryDataSize = ifStatement->getBody().getTotalCarryDataSize();
466        const unsigned carrySummaryIndex = baseCarryDataIdx + carryDataSize - 1;
467       
468        Value* if_test_value = compileExpression(ifStatement->getCondition());
469        if (carryDataSize > 0) {
470            // load the summary variable
471            Value* last_if_pending_data = genCarryDataLoad(carrySummaryIndex);
472            if_test_value = b_entry.CreateOr(if_test_value, last_if_pending_data);
473        }
474        b_entry.CreateCondBr(genBitBlockAny(if_test_value), ifEndBlock, ifBodyBlock);
475
476        // Entry processing is complete, now handle the body of the if.
477        mBasicBlock = ifBodyBlock;
478        compileBlock(ifStatement -> getBody());
479
480        // If we compiled an If or a While statement, we won't be in the same basic block as before.
481        // Create the branch from the current basic block to the end block.
482        IRBuilder<> bIfBody(mBasicBlock);
483        // After the recursive compile, now insert the code to compute the summary
484        // carry over variable.
485       
486        if (carryDataSize > 1) {
487            // If there was only one carry entry, then it also serves as the summary variable.
488            // Otherwise, we need to combine entries to compute the summary.
489            Value * carry_summary = mZeroInitializer;
490            for (int c = baseCarryDataIdx; c < carrySummaryIndex; c++) {
491                int s = mCarryDataSummaryIdx[c];
492                if (s == -1) {
493                    Value* carryq_value = mCarryDataVector[c];
494                    if (carry_summary == mZeroInitializer) {
495                        carry_summary = carryq_value;
496                    }
497                    else {
498                        carry_summary = bIfBody.CreateOr(carry_summary, carryq_value);
499                    }
500                    mCarryDataSummaryIdx[c] = carrySummaryIndex;
501                }
502            }
503            genCarryDataStore(carry_summary, carrySummaryIndex);
504        }
505        bIfBody.CreateBr(ifEndBlock);
506        //End Block
507        IRBuilder<> bEnd(ifEndBlock);
508        for (const PabloAST * node : ifStatement->getDefined()) {
509            const Assign * assign = cast<Assign>(node);
510            PHINode * phi = bEnd.CreatePHI(mBitBlockType, 2, assign->getName()->value());
511            auto f = mMarkerMap.find(assign);
512            assert (f != mMarkerMap.end());
513            phi->addIncoming(mZeroInitializer, ifEntryBlock);
514            phi->addIncoming(f->second, mBasicBlock);
515            mMarkerMap[assign] = phi;
516        }
517        // Create the phi Node for the summary variable.
518        if (carryDataSize > 0) {
519            PHINode * summary_phi = bEnd.CreatePHI(mBitBlockType, 2, "summary");
520            summary_phi->addIncoming(mZeroInitializer, ifEntryBlock);
521            summary_phi->addIncoming(mCarryDataVector[carrySummaryIndex], mBasicBlock);
522            mCarryDataVector[carrySummaryIndex] = summary_phi;
523        }
524       
525        // Set the basic block to the new end block
526        mBasicBlock = ifEndBlock;
527}
528
529void PabloCompiler::compileWhile(const While * whileStatement) {
530        const unsigned baseCarryDataIdx = whileStatement->getBody().getCarryIndexBase();
531        const unsigned carryDataSize = whileStatement->getBody().getTotalCarryDataSize();
532   
533        if (mNestingDepth == 0) {
534            for (auto i = 0; i < carryDataSize; ++i) {
535                genCarryDataLoad(baseCarryDataIdx + i);
536            }
537        }
538
539        SmallVector<const Next*, 4> nextNodes;
540        for (const PabloAST * node : whileStatement->getBody()) {
541            if (isa<Next>(node)) {
542                nextNodes.push_back(cast<Next>(node));
543            }
544        }
545
546        // Compile the initial iteration statements; the calls to genCarryDataStore will update the
547        // mCarryDataVector with the appropriate values. Although we're not actually entering a new basic
548        // block yet, increment the nesting depth so that any calls to genCarryDataLoad or genCarryDataStore
549        // will refer to the previous value.
550
551        ++mNestingDepth;
552
553        compileBlock(whileStatement->getBody());
554
555        // Reset the carry queue index. Note: this ought to be changed in the future. Currently this assumes
556        // that compiling the while body twice will generate the equivalent IR. This is not necessarily true
557        // but works for now.
558
559        BasicBlock* whileCondBlock = BasicBlock::Create(mMod->getContext(), "while.cond", mFunction, 0);
560        BasicBlock* whileBodyBlock = BasicBlock::Create(mMod->getContext(), "while.body", mFunction, 0);
561        BasicBlock* whileEndBlock = BasicBlock::Create(mMod->getContext(), "while.end", mFunction, 0);
562
563        // Note: compileBlock may update the mBasicBlock pointer if the body contains nested loops. It
564        // may not be same one that we entered the function with.
565        IRBuilder<> bEntry(mBasicBlock);
566        bEntry.CreateBr(whileCondBlock);
567
568        // CONDITION BLOCK
569        IRBuilder<> bCond(whileCondBlock);
570        // generate phi nodes for any carry propogating instruction
571        std::vector<PHINode*> phiNodes(carryDataSize + nextNodes.size());
572        unsigned index = 0;
573        for (index = 0; index < carryDataSize; ++index) {
574            PHINode * phi = bCond.CreatePHI(mBitBlockType, 2);
575            phi->addIncoming(mCarryDataVector[baseCarryDataIdx + index], mBasicBlock);
576            mCarryDataVector[baseCarryDataIdx + index] = mZeroInitializer; // (use phi for multi-carry mode.)
577            phiNodes[index] = phi;
578        }
579        // and for any Next nodes in the loop body
580        for (const Next * n : nextNodes) {
581            PHINode * phi = bCond.CreatePHI(mBitBlockType, 2, n->getName()->value());
582            auto f = mMarkerMap.find(n->getInitial());
583            assert (f != mMarkerMap.end());
584            phi->addIncoming(f->second, mBasicBlock);
585            mMarkerMap[n->getInitial()] = phi;
586            phiNodes[index++] = phi;
587        }
588
589        mBasicBlock = whileCondBlock;
590        bCond.CreateCondBr(genBitBlockAny(compileExpression(whileStatement->getCondition())), whileEndBlock, whileBodyBlock);
591
592        // BODY BLOCK
593        mBasicBlock = whileBodyBlock;
594        compileBlock(whileStatement->getBody());
595        // update phi nodes for any carry propogating instruction
596        IRBuilder<> bWhileBody(mBasicBlock);
597        for (index = 0; index < carryDataSize; ++index) {
598            Value * carryOut = bWhileBody.CreateOr(phiNodes[index], mCarryDataVector[baseCarryDataIdx + index]);
599            PHINode * phi = phiNodes[index];
600            phi->addIncoming(carryOut, mBasicBlock);
601            mCarryDataVector[baseCarryDataIdx + index] = phi;
602        }
603        // and for any Next nodes in the loop body
604        for (const Next * n : nextNodes) {
605            auto f = mMarkerMap.find(n->getInitial());
606            assert (f != mMarkerMap.end());
607            PHINode * phi = phiNodes[index++];
608            phi->addIncoming(f->second, mBasicBlock);
609            mMarkerMap[n->getInitial()] = phi;
610        }
611
612        bWhileBody.CreateBr(whileCondBlock);
613
614        // EXIT BLOCK
615        mBasicBlock = whileEndBlock;
616        if (--mNestingDepth == 0) {
617            for (index = 0; index < carryDataSize; ++index) {
618                genCarryDataStore(phiNodes[index], baseCarryDataIdx + index);
619            }
620        }
621 
622}
623
624void PabloCompiler::compileStatement(const Statement * stmt)
625{
626    IRBuilder<> b(mBasicBlock);
627    if (const Assign * assign = dyn_cast<const Assign>(stmt)) {
628        Value * expr = compileExpression(assign->getExpr());
629        mMarkerMap[assign] = expr;
630        if (LLVM_UNLIKELY(assign->isOutputAssignment())) {
631            SetOutputValue(expr, assign->getOutputIndex());
632        }
633    }
634    else if (const Next * next = dyn_cast<const Next>(stmt)) {
635        Value * expr = compileExpression(next->getExpr());
636        mMarkerMap[next->getInitial()] = expr;
637    }
638    else if (const If * ifStatement = dyn_cast<const If>(stmt))
639    {
640        compileIf(ifStatement);
641    }
642    else if (const While * whileStatement = dyn_cast<const While>(stmt))
643    {
644        compileWhile(whileStatement);
645    }
646    else if (const Call* call = dyn_cast<Call>(stmt)) {
647        //Call the callee once and store the result in the marker map.
648        auto mi = mMarkerMap.find(call);
649        if (mi == mMarkerMap.end()) {
650            auto ci = mCalleeMap.find(call->getCallee());
651            if (LLVM_UNLIKELY(ci == mCalleeMap.end())) {
652                throw std::runtime_error("Unexpected error locating static function for \"" + call->getCallee()->to_string() + "\"");
653            }
654            mi = mMarkerMap.insert(std::make_pair(call, b.CreateCall(ci->second, mBasisBitsAddr))).first;
655        }
656        // return mi->second;
657    }
658    else if (const And * pablo_and = dyn_cast<And>(stmt)) {
659        Value * expr = b.CreateAnd(compileExpression(pablo_and->getExpr1()), compileExpression(pablo_and->getExpr2()), "and");
660        mMarkerMap[pablo_and] = expr;
661        // return expr;
662    }
663    else if (const Or * pablo_or = dyn_cast<Or>(stmt)) {
664        Value * expr = b.CreateOr(compileExpression(pablo_or->getExpr1()), compileExpression(pablo_or->getExpr2()), "or");
665        mMarkerMap[pablo_or] = expr;
666        // return expr;
667    }
668    else if (const Xor * pablo_xor = dyn_cast<Xor>(stmt)) {
669        Value * expr = b.CreateXor(compileExpression(pablo_xor->getExpr1()), compileExpression(pablo_xor->getExpr2()), "xor");
670        mMarkerMap[pablo_xor] = expr;
671        // return expr;
672    }
673    else if (const Sel * sel = dyn_cast<Sel>(stmt)) {
674        Value* ifMask = compileExpression(sel->getCondition());
675        Value* ifTrue = b.CreateAnd(ifMask, compileExpression(sel->getTrueExpr()));
676        Value* ifFalse = b.CreateAnd(genNot(ifMask), compileExpression(sel->getFalseExpr()));
677        Value * expr = b.CreateOr(ifTrue, ifFalse);
678        mMarkerMap[sel] = expr;
679        // return expr;
680    }
681    else if (const Not * pablo_not = dyn_cast<Not>(stmt)) {
682        Value * expr = genNot(compileExpression(pablo_not->getExpr()));
683        mMarkerMap[pablo_not] = expr;
684        // return expr;
685    }
686    else if (const Advance * adv = dyn_cast<Advance>(stmt)) {
687        Value* strm_value = compileExpression(adv->getExpr());
688        int shift = adv->getAdvanceAmount();
689        unsigned advance_index = adv->getLocalAdvanceIndex();
690        Value * expr = genAdvanceWithCarry(strm_value, shift, advance_index, stmt->getParent());
691        mMarkerMap[adv] = expr;
692        // return expr;
693    }
694    else if (const MatchStar * mstar = dyn_cast<MatchStar>(stmt))
695    {
696        Value * marker = compileExpression(mstar->getMarker());
697        Value * cc = compileExpression(mstar->getCharClass());
698        Value * marker_and_cc = b.CreateAnd(marker, cc);
699        unsigned carry_index = mstar->getLocalCarryIndex();
700        Value * expr = b.CreateOr(b.CreateXor(genAddWithCarry(marker_and_cc, cc, carry_index, stmt->getParent()), cc), marker, "matchstar");
701        mMarkerMap[mstar] = expr;
702        // return expr;
703    }
704    else if (const ScanThru * sthru = dyn_cast<ScanThru>(stmt))
705    {
706        Value * marker_expr = compileExpression(sthru->getScanFrom());
707        Value * cc_expr = compileExpression(sthru->getScanThru());
708        unsigned carry_index = sthru->getLocalCarryIndex();
709        Value * expr = b.CreateAnd(genAddWithCarry(marker_expr, cc_expr, carry_index, stmt->getParent()), genNot(cc_expr), "scanthru");
710        mMarkerMap[sthru] = expr;
711        // return expr;
712    }
713    else {
714        PabloPrinter::print(stmt, std::cerr);
715        throw std::runtime_error("Unrecognized Pablo Statement! can't compile.");
716    }
717}
718
719Value * PabloCompiler::compileExpression(const PabloAST * expr) {
720    if (isa<Ones>(expr)) {
721        return mOneInitializer;
722    }
723    else if (isa<Zeroes>(expr)) {
724        return mZeroInitializer;
725    }
726    else if (const Next * next = dyn_cast<Next>(expr)) {
727        expr = next->getInitial();
728    }
729    auto f = mMarkerMap.find(expr);
730    if (f == mMarkerMap.end()) {
731        std::stringstream str;
732        str << "\"";
733        PabloPrinter::print(expr, str);
734        str << "\" was used before definition!";
735        throw std::runtime_error(str.str());
736    }
737    return f->second;
738}
739
740
741#ifdef USE_UADD_OVERFLOW
742#ifdef USE_TWO_UADD_OVERFLOW
743PabloCompiler::SumWithOverflowPack PabloCompiler::callUaddOverflow(Value* int128_e1, Value* int128_e2) {
744    std::vector<Value*> struct_res_params;
745    struct_res_params.push_back(int128_e1);
746    struct_res_params.push_back(int128_e2);
747    CallInst* struct_res = CallInst::Create(mFunctionUaddOverflow, struct_res_params, "uadd_overflow_res", mBasicBlock);
748    struct_res->setCallingConv(CallingConv::C);
749    struct_res->setTailCall(false);
750    AttributeSet struct_res_PAL;
751    struct_res->setAttributes(struct_res_PAL);
752
753    SumWithOverflowPack ret;
754
755    std::vector<unsigned> int128_sum_indices;
756    int128_sum_indices.push_back(0);
757    ret.sum = ExtractValueInst::Create(struct_res, int128_sum_indices, "sum", mBasicBlock);
758
759    std::vector<unsigned> int1_obit_indices;
760    int1_obit_indices.push_back(1);
761    ret.obit = ExtractValueInst::Create(struct_res, int1_obit_indices, "obit", mBasicBlock);
762
763    return ret;
764}
765#else
766PabloCompiler::SumWithOverflowPack PabloCompiler::callUaddOverflow(Value* int128_e1, Value* int128_e2, Value* int1_cin) {
767    std::vector<Value*> struct_res_params;
768    struct_res_params.push_back(int128_e1);
769    struct_res_params.push_back(int128_e2);
770    struct_res_params.push_back(int1_cin);
771    CallInst* struct_res = CallInst::Create(mFunctionUaddOverflowCarryin, struct_res_params, "uadd_overflow_res", mBasicBlock);
772    struct_res->setCallingConv(CallingConv::C);
773    struct_res->setTailCall(false);
774    AttributeSet struct_res_PAL;
775    struct_res->setAttributes(struct_res_PAL);
776
777    SumWithOverflowPack ret;
778
779    std::vector<unsigned> int128_sum_indices;
780    int128_sum_indices.push_back(0);
781    ret.sum = ExtractValueInst::Create(struct_res, int128_sum_indices, "sum", mBasicBlock);
782
783    std::vector<unsigned> int1_obit_indices;
784    int1_obit_indices.push_back(1);
785    ret.obit = ExtractValueInst::Create(struct_res, int1_obit_indices, "obit", mBasicBlock);
786
787    return ret;
788}
789#endif
790#endif
791
792
793Value* PabloCompiler::genAddWithCarry(Value* e1, Value* e2, unsigned localIndex, const PabloBlock * blk) {
794    IRBuilder<> b(mBasicBlock);
795
796    //CarryQ - carry in.
797    const int carryIdx = blk->getCarryIndexBase() + localIndex;
798    Value* carryq_value = genCarryDataLoad(carryIdx);
799#ifdef USE_TWO_UADD_OVERFLOW
800    //This is the ideal implementation, which uses two uadd.with.overflow
801    //The back end should be able to recognize this pattern and combine it into uadd.with.overflow.carryin
802    CastInst* int128_e1 = new BitCastInst(e1, IntegerType::get(mMod->getContext(), BLOCK_SIZE), "e1_128", mBasicBlock);
803    CastInst* int128_e2 = new BitCastInst(e2, IntegerType::get(mMod->getContext(), BLOCK_SIZE), "e2_128", mBasicBlock);
804    CastInst* int128_carryq_value = new BitCastInst(carryq_value, IntegerType::get(mMod->getContext(), BLOCK_SIZE), "carryq_128", mBasicBlock);
805
806    SumWithOverflowPack sumpack0, sumpack1;
807
808    sumpack0 = callUaddOverflow(int128_e1, int128_e2);
809    sumpack1 = callUaddOverflow(sumpack0.sum, int128_carryq_value);
810
811    Value* obit = b.CreateOr(sumpack0.obit, sumpack1.obit, "carry_bit");
812    Value* sum = b.CreateBitCast(sumpack1.sum, mBitBlockType, "ret_sum");
813
814    /*obit is the i1 carryout, zero extend and insert it into a v2i64 or v4i64 vector.*/
815    ConstantAggregateZero* const_packed_5 = ConstantAggregateZero::get(mBitBlockType);
816    ConstantInt* const_int32_6 = ConstantInt::get(mMod->getContext(), APInt(32, StringRef("0"), 10));
817    CastInst* int64_o0 = new ZExtInst(obit, IntegerType::get(mMod->getContext(), 64), "o0", mBasicBlock);
818    InsertElementInst* carry_out = InsertElementInst::Create(const_packed_5, int64_o0, const_int32_6, "carry_out", mBasicBlock);
819
820#elif defined USE_UADD_OVERFLOW
821    //use llvm.uadd.with.overflow.i128 or i256
822    CastInst* int128_e1 = new BitCastInst(e1, IntegerType::get(mMod->getContext(), BLOCK_SIZE), "e1_128", mBasicBlock);
823    CastInst* int128_e2 = new BitCastInst(e2, IntegerType::get(mMod->getContext(), BLOCK_SIZE), "e2_128", mBasicBlock);
824
825    //get i1 carryin from iBLOCK_SIZE
826    ConstantInt* const_int32_6 = ConstantInt::get(mMod->getContext(), APInt(32, StringRef("0"), 10));
827    ExtractElementInst * int64_carryq_value = ExtractElementInst::Create(carryq_value, const_int32_6, "carryq_64", mBasicBlock);
828    CastInst* int1_carryq_value = new TruncInst(int64_carryq_value, IntegerType::get(mMod->getContext(), 1), "carryq_1", mBasicBlock);
829
830    SumWithOverflowPack sumpack0;
831    sumpack0 = callUaddOverflow(int128_e1, int128_e2, int1_carryq_value);
832    Value* obit = sumpack0.obit;
833    Value* sum = b.CreateBitCast(sumpack0.sum, mBitBlockType, "sum");
834
835    /*obit is the i1 carryout, zero extend and insert it into a v2i64 or v4i64 vector.*/
836    ConstantAggregateZero* const_packed_5 = ConstantAggregateZero::get(mBitBlockType);
837    CastInst* int64_o0 = new ZExtInst(obit, IntegerType::get(mMod->getContext(), 64), "o0", mBasicBlock);
838    InsertElementInst* carry_out = InsertElementInst::Create(const_packed_5, int64_o0, const_int32_6, "carry_out", mBasicBlock);
839#elif (BLOCK_SIZE == 128)
840    //calculate carry through logical ops
841    Value* carrygen = b.CreateAnd(e1, e2, "carrygen");
842    Value* carryprop = b.CreateOr(e1, e2, "carryprop");
843    Value* digitsum = b.CreateAdd(e1, e2, "digitsum");
844    Value* partial = b.CreateAdd(digitsum, carryq_value, "partial");
845    Value* digitcarry = b.CreateOr(carrygen, b.CreateAnd(carryprop, genNot(partial)));
846    Value* mid_carry_in = genShiftLeft64(b.CreateLShr(digitcarry, 63), "mid_carry_in");
847
848    Value* sum = b.CreateAdd(partial, mid_carry_in, "sum");
849    Value* carry_out = genShiftHighbitToLow(b.CreateOr(carrygen, b.CreateAnd(carryprop, genNot(sum))), "carry_out");
850#else
851    //BLOCK_SIZE == 256, there is no other implementation
852    static_assert(false, "Add with carry for 256-bit bitblock requires USE_UADD_OVERFLOW");
853#endif //USE_TWO_UADD_OVERFLOW
854
855    genCarryDataStore(carry_out, carryIdx);
856    return sum;
857}
858
859Value* PabloCompiler::genCarryDataLoad(const unsigned index) {
860    assert (index < mCarryDataVector.size());
861    if (mNestingDepth == 0) {
862        IRBuilder<> b(mBasicBlock);
863        mCarryDataVector[index] = b.CreateAlignedLoad(b.CreateGEP(mCarryDataPtr, b.getInt64(index)), BLOCK_SIZE/8, false);
864    }
865    return mCarryDataVector[index];
866}
867
868void PabloCompiler::genCarryDataStore(Value* carryOut, const unsigned index ) {
869    assert (carryOut);
870    assert (index < mCarryDataVector.size());
871    if (mNestingDepth == 0) {
872        IRBuilder<> b(mBasicBlock);
873        b.CreateAlignedStore(carryOut, b.CreateGEP(mCarryDataPtr, b.getInt64(index)), BLOCK_SIZE/8, false);
874    }
875    mCarryDataSummaryIdx[index] = -1;
876    mCarryDataVector[index] = carryOut;
877}
878
879inline Value* PabloCompiler::genBitBlockAny(Value* test) {
880    IRBuilder<> b(mBasicBlock);
881    Value* cast_marker_value_1 = b.CreateBitCast(test, IntegerType::get(mMod->getContext(), BLOCK_SIZE));
882    return b.CreateICmpEQ(cast_marker_value_1, ConstantInt::get(IntegerType::get(mMod->getContext(), BLOCK_SIZE), 0));
883}
884
885Value* PabloCompiler::genShiftHighbitToLow(Value* e, const Twine &namehint) {
886    IRBuilder<> b(mBasicBlock);
887    Value* i128_val = b.CreateBitCast(e, IntegerType::get(mMod->getContext(), BLOCK_SIZE));
888    return b.CreateBitCast(b.CreateLShr(i128_val, BLOCK_SIZE - 1, namehint), mBitBlockType);
889}
890
891Value* PabloCompiler::genShiftLeft64(Value* e, const Twine &namehint) {
892    IRBuilder<> b(mBasicBlock);
893    Value* i128_val = b.CreateBitCast(e, IntegerType::get(mMod->getContext(), BLOCK_SIZE));
894    return b.CreateBitCast(b.CreateShl(i128_val, 64, namehint), mBitBlockType);
895}
896
897inline Value* PabloCompiler::genNot(Value* expr) {
898    IRBuilder<> b(mBasicBlock);
899    return b.CreateXor(expr, mOneInitializer, "not");
900}
901Value* PabloCompiler::genAdvanceWithCarry(Value* strm_value, int shift_amount, unsigned localIndex, const PabloBlock * blk) {
902    IRBuilder<> b(mBasicBlock);
903    int advEntries = (shift_amount - 1) / BLOCK_SIZE + 1;
904    int block_shift = shift_amount % BLOCK_SIZE;
905    const auto advanceIndex = blk->getCarryIndexBase() + blk->getLocalCarryCount() + localIndex;
906    const auto storeIdx = advanceIndex;
907    const auto loadIdx = advanceIndex + advEntries - 1;
908    Value* result_value;
909   
910    if (advEntries == 1) {
911        if (block_shift == 0) { 
912            result_value = genCarryDataLoad(loadIdx);
913            //b.CreateCall(mFunc_print_register, result_value);
914        }
915#if (BLOCK_SIZE == 128) && !defined(USE_LONG_INTEGER_SHIFT)
916        if (block_shift == 1) {
917            Value* advanceq_value = genShiftHighbitToLow(genCarryDataLoad(loadIdx));
918            Value* srli_1_value = b.CreateLShr(strm_value, 63);
919            Value* packed_shuffle;
920            Constant* const_packed_1_elems [] = {b.getInt32(0), b.getInt32(2)};
921            Constant* const_packed_1 = ConstantVector::get(const_packed_1_elems);
922            packed_shuffle = b.CreateShuffleVector(advanceq_value, srli_1_value, const_packed_1);
923
924            Constant* const_packed_2_elems[] = {b.getInt64(1), b.getInt64(1)};
925            Constant* const_packed_2 = ConstantVector::get(const_packed_2_elems);
926
927            Value* shl_value = b.CreateShl(strm_value, const_packed_2);
928            result_value = b.CreateOr(shl_value, packed_shuffle, "advance");
929        }
930        else { //if (block_shift < BLOCK_SIZE) {
931            // This is the preferred logic, but is too slow for the general case.
932            // We need to speed up our custom LLVM for this code.
933            Value* advanceq_longint = b.CreateBitCast(genCarryDataLoad(loadIdx), IntegerType::get(mMod->getContext(), BLOCK_SIZE));
934            Value* strm_longint = b.CreateBitCast(strm_value, IntegerType::get(mMod->getContext(), BLOCK_SIZE));
935            Value* adv_longint = b.CreateOr(b.CreateShl(strm_longint, block_shift), b.CreateLShr(advanceq_longint, BLOCK_SIZE - block_shift), "advance");
936            result_value = b.CreateBitCast(adv_longint, mBitBlockType);
937        }
938#else
939        Value* advanceq_longint = b.CreateBitCast(genCarryDataLoad(loadIdx), IntegerType::get(mMod->getContext(), BLOCK_SIZE));
940        Value* strm_longint = b.CreateBitCast(strm_value, IntegerType::get(mMod->getContext(), BLOCK_SIZE));
941        Value* adv_longint = b.CreateOr(b.CreateShl(strm_longint, block_shift), b.CreateLShr(advanceq_longint, BLOCK_SIZE - block_shift), "advance");
942        result_value = b.CreateBitCast(adv_longint, mBitBlockType);
943
944#endif
945    }
946    else {
947        if (block_shift == 0) {
948            result_value = genCarryDataLoad(loadIdx);
949        }
950        else { 
951            // The advance is based on the two oldest bit blocks in the advance queue.
952            Value* advanceq_longint = b.CreateBitCast(genCarryDataLoad(loadIdx), IntegerType::get(mMod->getContext(), BLOCK_SIZE));
953            Value* strm_longint = b.CreateBitCast(genCarryDataLoad(loadIdx-1), IntegerType::get(mMod->getContext(), BLOCK_SIZE));
954            Value* adv_longint = b.CreateOr(b.CreateShl(strm_longint, block_shift), b.CreateLShr(advanceq_longint, BLOCK_SIZE - block_shift), "longadvance");
955            result_value = b.CreateBitCast(adv_longint, mBitBlockType);
956            //b.CreateCall(mFunc_print_register, genCarryDataLoad(loadIdx));
957            //b.CreateCall(mFunc_print_register, genCarryDataLoad(loadIdx-1));
958            //b.CreateCall(mFunc_print_register, result_value);
959        }
960        // copy entries from previous blocks forward
961        for (int i = loadIdx; i > storeIdx; i--) {
962            genCarryDataStore(genCarryDataLoad(i-1), i);
963        }
964    }
965    genCarryDataStore(strm_value, storeIdx);
966    return result_value;
967}
968
969void PabloCompiler::SetOutputValue(Value * marker, const unsigned index) {
970    IRBuilder<> b(mBasicBlock);
971    if (marker->getType()->isPointerTy()) {
972        marker = b.CreateAlignedLoad(marker, BLOCK_SIZE/8, false);
973    }
974    Value* indices[] = {b.getInt64(0), b.getInt32(index)};
975    Value* gep = b.CreateGEP(mOutputAddrPtr, indices);
976    b.CreateAlignedStore(marker, gep, BLOCK_SIZE/8, false);
977}
978
979CompiledPabloFunction::CompiledPabloFunction(size_t carryDataSize, Function * function, ExecutionEngine * executionEngine)
980: CarryDataSize(carryDataSize)
981, FunctionPointer(executionEngine->getPointerToFunction(function))
982, mFunction(function)
983, mExecutionEngine(executionEngine)
984{
985
986}
987
988// Clean up the memory for the compiled function once we're finished using it.
989CompiledPabloFunction::~CompiledPabloFunction() {
990    if (mExecutionEngine) {
991        assert (mFunction);
992        // mExecutionEngine->freeMachineCodeForFunction(mFunction); // This function only prints a "not supported" message. Reevaluate with LLVM 3.6.
993        delete mExecutionEngine;
994    }
995}
996
997}
Note: See TracBrowser for help on using the repository browser.