source: icGREP/icgrep-devel/icgrep/u8u16.cpp @ 5220

Last change on this file since 5220 was 5220, checked in by cameron, 3 years ago

Automate instance creation

File size: 19.8 KB
Line 
1/*
2 *  Copyright (c) 2016 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 <string>
8#include <iostream>
9#include <fstream>
10#include <sstream>
11#include <stdlib.h>
12
13#include <llvm/IR/Function.h>
14#include <llvm/IR/Module.h>
15#include <llvm/ExecutionEngine/ExecutionEngine.h>
16#include <llvm/ExecutionEngine/MCJIT.h>
17#include <llvm/IRReader/IRReader.h>
18#include <llvm/IR/Verifier.h>
19#include <llvm/Support/Debug.h>
20
21#include <llvm/Support/CommandLine.h>
22
23#include <toolchain.h>
24#include <re/re_cc.h>
25#include <cc/cc_compiler.h>
26#include <pablo/pablo_toolchain.h>
27#include <pablo/pablo_kernel.h>
28#include <pablo/prototype.h>
29#include <IDISA/idisa_builder.h>
30#include <IDISA/idisa_target.h>
31#include <kernels/pipeline.h>
32#include <kernels/interface.h>
33#include <kernels/kernel.h>
34#include <kernels/s2p_kernel.h>
35#include <kernels/p2s_kernel.h>
36#include <kernels/deletion.h>
37#include <kernels/stdout_kernel.h>
38#include <llvm/IR/TypeBuilder.h>
39
40
41// mmap system
42#include <boost/filesystem.hpp>
43#include <boost/iostreams/device/mapped_file.hpp>
44#include <boost/interprocess/anonymous_shared_memory.hpp>
45#include <boost/interprocess/mapped_region.hpp>
46#include <fcntl.h>
47static cl::OptionCategory u8u16Options("u8u16 Options",
48                                            "Transcoding control options.");
49
50static cl::list<std::string> inputFiles(cl::Positional, cl::desc("<input file ...>"), cl::OneOrMore, cl::cat(u8u16Options));
51
52static cl::opt<bool> segmentPipelineParallel("enable-segment-pipeline-parallel", cl::desc("Enable multithreading with segment pipeline parallelism."), cl::cat(u8u16Options));
53static cl::opt<bool> mMapBuffering("mmap-buffering", cl::desc("Enable mmap buffering."), cl::cat(u8u16Options));
54static cl::opt<bool> memAlignBuffering("memalign-buffering", cl::desc("Enable posix_memalign buffering."), cl::cat(u8u16Options));
55
56
57using namespace pablo;
58using namespace kernel;
59using namespace parabix;
60
61void u8u16_pablo(PabloKernel * kernel) {
62    //  input: 8 basis bit streams
63    //  output: 16 u8-indexed streams, + delmask stream + error stream
64
65    cc::CC_Compiler ccc(kernel);
66   
67    PabloBuilder & main = ccc.getBuilder();
68    const auto u8_bits = ccc.getBasisBits();
69
70    PabloAST * zeroes = main.createZeroes();
71
72    // Outputs
73    Var * u16_hi[8];
74    for (int i = 0; i < 8; ++i) {
75        u16_hi[i] = main.createVar("u16_hi" + std::to_string(i), zeroes);
76    }
77    Var * u16_lo[8];
78    for (int i = 0; i < 8; ++i) {
79        u16_lo[i] = main.createVar("u16_lo" + std::to_string(i), zeroes);
80    }
81    Var * delmask = main.createVar("delmask", zeroes);
82    Var * error_mask = main.createVar("error_mask", zeroes);
83
84    // The logic for processing non-ASCII bytes will be embedded within an if-hierarchy.
85    PabloAST * nonASCII = ccc.compileCC(re::makeCC(0x80, 0xFF));
86   
87    // Builder for the if statement handling all non-ASCII logic
88    PabloBuilder nAb = PabloBuilder::Create(main);
89    // Bits 3 through 7 of a 2-byte prefix are data bits, needed to
90    // produce the UTF-16 code unit data ...,
91    PabloAST * bit3a1 = nAb.createAdvance(u8_bits[3], 1);
92    PabloAST * bit4a1 = nAb.createAdvance(u8_bits[4], 1);
93    PabloAST * bit5a1 = nAb.createAdvance(u8_bits[5], 1);
94    PabloAST * bit6a1 = nAb.createAdvance(u8_bits[6], 1);
95    PabloAST * bit7a1 = nAb.createAdvance(u8_bits[7], 1);
96   
97    // Entry condition for 3 or 4 byte sequences: we have a prefix byte in the range 0xE0-0xFF.
98    PabloAST * pfx34 = ccc.compileCC(re::makeCC(0xE0, 0xFF), nAb);
99    // Builder for the if statement handling all logic for 3- and 4-byte sequences.
100    PabloBuilder p34b = PabloBuilder::Create(nAb);
101    // Bits 4 through 7 of a 3-byte prefix are data bits.  They must be moved
102    // to the final position of the 3-byte sequence.
103    PabloAST * bit2a1 = p34b.createAdvance(u8_bits[2], 1);
104    PabloAST * bit4a2 = p34b.createAdvance(bit4a1, 1);
105    PabloAST * bit5a2 = p34b.createAdvance(bit5a1, 1);
106    PabloAST * bit6a2 = p34b.createAdvance(bit6a1, 1);
107    PabloAST * bit7a2 = p34b.createAdvance(bit7a1, 1);
108
109
110    Var * const u8scope32 = nAb.createVar("u8scope32", zeroes);
111    Var * const u8scope33 = nAb.createVar("u8scope33", zeroes);
112    Var * const u8scope44 = nAb.createVar("u8scope44", zeroes);
113
114    //
115    // Logic for 4-byte UTF-8 sequences
116    //
117    // Entry condition  or 4 byte sequences: we have a prefix byte in the range 0xF0-0xFF.
118    PabloAST * pfx4 = ccc.compileCC(re::makeCC(0xF0, 0xFF), p34b);
119    // Builder for the if statement handling all logic for 4-byte sequences only.
120    PabloBuilder p4b = PabloBuilder::Create(p34b);
121    // Illegal 4-byte sequences
122    PabloAST * F0 = ccc.compileCC(re::makeCC(0xF0), p4b);
123    PabloAST * F4 = ccc.compileCC(re::makeCC(0xF4), p4b);
124    PabloAST * F0_err = p4b.createAnd(p4b.createAdvance(F0, 1), ccc.compileCC(re::makeCC(0x80, 0x8F), p4b));
125    PabloAST * F4_err = p4b.createAnd(p4b.createAdvance(F4, 1), ccc.compileCC(re::makeCC(0x90, 0xBF), p4b));
126    PabloAST * F5_FF = ccc.compileCC(re::makeCC(0xF5, 0xFF), p4b);
127
128    Var * FX_err = p34b.createVar("FX_err", zeroes);
129    p4b.createAssign(FX_err, p4b.createOr(F5_FF, p4b.createOr(F0_err, F4_err)));
130    //
131    // 4-byte prefixes have a scope that extends over the next 3 bytes.
132
133    Var * u8scope42 = p34b.createVar("u8scope42", zeroes);
134    Var * u8scope43 = p34b.createVar("u8scope43", zeroes);
135
136    p4b.createAssign(u8scope42, p4b.createAdvance(pfx4, 1));
137    p4b.createAssign(u8scope43, p4b.createAdvance(u8scope42, 1));
138    p4b.createAssign(u8scope44, p4b.createAdvance(u8scope43, 1));
139    //
140   
141    //  From the 4-byte sequence 11110abc 10defghi 10jklmno 10pqrstu,
142    //  we must calculate the value abcde - 1 to produce the bit values
143    //  for u16_hi6, hi7, lo0, lo1 at the scope43 position.
144    Var * s43_lo0 = nAb.createVar("scope43_lo0", zeroes);
145    Var * s43_lo1 = nAb.createVar("scope43_lo1", zeroes);
146    Var * s43_hi6 = nAb.createVar("scope43_hi6", zeroes);
147    Var * s43_hi7 = nAb.createVar("scope43_hi7", zeroes);
148
149    Var * s43_lo2 = main.createVar("scope43_lo2", zeroes);
150    Var * s43_lo3 = main.createVar("scope43_lo3", zeroes);
151    Var * s43_lo4 = main.createVar("scope43_lo4", zeroes);
152    Var * s43_lo5 = main.createVar("scope43_lo5", zeroes);
153    Var * s43_lo6 = main.createVar("scope43_lo6", zeroes);
154    Var * s43_lo7 = main.createVar("scope43_lo7", zeroes);
155
156    p4b.createAssign(s43_lo1, p4b.createAnd(u8scope43, p4b.createNot(bit3a1)));           // e - 1
157    p4b.createAssign(s43_lo0, p4b.createAnd(u8scope43, p4b.createXor(bit2a1, s43_lo1)));  // d - borrow
158    PabloAST * brw1 = p4b.createAnd(s43_lo1, p4b.createNot(bit2a1));
159    p4b.createAssign(s43_hi7, p4b.createAnd(u8scope43, p4b.createXor(bit7a2, brw1)));     // c - borrow
160    PabloAST * brw2 = p4b.createAnd(brw1, p4b.createNot(bit7a2));
161    p4b.createAssign(s43_hi6, p4b.createAnd(u8scope43, p4b.createXor(bit6a2, brw2)));     // b - borrow
162    //
163    p4b.createAssign(s43_lo2, p4b.createAnd(u8scope43, bit4a1));
164    p4b.createAssign(s43_lo3, p4b.createAnd(u8scope43, bit5a1));
165    p4b.createAssign(s43_lo4, p4b.createAnd(u8scope43, bit6a1));
166    p4b.createAssign(s43_lo5, p4b.createAnd(u8scope43, bit7a1));
167    p4b.createAssign(s43_lo6, p4b.createAnd(u8scope43, u8_bits[2]));
168    p4b.createAssign(s43_lo7, p4b.createAnd(u8scope43, u8_bits[3]));
169    //
170    //
171    p34b.createIf(pfx4, p4b);
172    //
173    // Combined logic for 3 and 4 byte sequences
174    //
175    PabloAST * pfx3 = ccc.compileCC(re::makeCC(0xE0, 0xEF), p34b);
176
177    p34b.createAssign(u8scope32, p34b.createAdvance(pfx3, 1));
178    p34b.createAssign(u8scope33, p34b.createAdvance(u8scope32, 1));
179
180    // Illegal 3-byte sequences
181    PabloAST * E0 = ccc.compileCC(re::makeCC(0xE0), p34b);
182    PabloAST * ED = ccc.compileCC(re::makeCC(0xED), p34b);
183    PabloAST * E0_err = p34b.createAnd(p34b.createAdvance(E0, 1), ccc.compileCC(re::makeCC(0x80, 0x9F), p34b));
184    PabloAST * ED_err = p34b.createAnd(p34b.createAdvance(ED, 1), ccc.compileCC(re::makeCC(0xA0, 0xBF), p34b));
185    Var * EX_FX_err = nAb.createVar("EX_FX_err", zeroes);
186
187    p34b.createAssign(EX_FX_err, p34b.createOr(p34b.createOr(E0_err, ED_err), FX_err));
188    // Two surrogate UTF-16 units are computed at the 3rd and 4th positions of 4-byte sequences.
189    PabloAST * surrogate = p34b.createOr(u8scope43, u8scope44);
190   
191    Var * p34del = nAb.createVar("p34del", zeroes);
192    p34b.createAssign(p34del, p34b.createOr(u8scope32, u8scope42));
193
194
195    // The high 5 bits of the UTF-16 code unit are only nonzero for 3 and 4-byte
196    // UTF-8 sequences.
197    p34b.createAssign(u16_hi[0], p34b.createOr(p34b.createAnd(u8scope33, bit4a2), surrogate));
198    p34b.createAssign(u16_hi[1], p34b.createOr(p34b.createAnd(u8scope33, bit5a2), surrogate));
199    p34b.createAssign(u16_hi[2], p34b.createAnd(u8scope33, bit6a2));
200    p34b.createAssign(u16_hi[3], p34b.createOr(p34b.createAnd(u8scope33, bit7a2), surrogate));
201    p34b.createAssign(u16_hi[4], p34b.createOr(p34b.createAnd(u8scope33, bit2a1), surrogate));
202   
203    //
204    nAb.createIf(pfx34, p34b);
205    //
206    // Combined logic for 2, 3 and 4 byte sequences
207    //
208
209    Var * u8lastscope = main.createVar("u8lastscope", zeroes);
210
211    PabloAST * pfx2 = ccc.compileCC(re::makeCC(0xC0, 0xDF), nAb);
212    PabloAST * u8scope22 = nAb.createAdvance(pfx2, 1);
213    nAb.createAssign(u8lastscope, nAb.createOr(u8scope22, nAb.createOr(u8scope33, u8scope44)));
214    PabloAST * u8anyscope = nAb.createOr(u8lastscope, p34del);
215
216    PabloAST * C0_C1_err = ccc.compileCC(re::makeCC(0xC0, 0xC1), nAb);
217    PabloAST * scope_suffix_mismatch = nAb.createXor(u8anyscope, ccc.compileCC(re::makeCC(0x80, 0xBF), nAb));
218    nAb.createAssign(error_mask, nAb.createOr(scope_suffix_mismatch, nAb.createOr(C0_C1_err, EX_FX_err)));
219    nAb.createAssign(delmask, nAb.createOr(p34del, ccc.compileCC(re::makeCC(0xC0, 0xFF), nAb)));
220   
221    // The low 3 bits of the high byte of the UTF-16 code unit as well as the high bit of the
222    // low byte are only nonzero for 2, 3 and 4 byte sequences.
223    nAb.createAssign(u16_hi[5], nAb.createOr(nAb.createAnd(u8lastscope, bit3a1), u8scope44));
224    nAb.createAssign(u16_hi[6], nAb.createOr(nAb.createAnd(u8lastscope, bit4a1), s43_hi6));
225    nAb.createAssign(u16_hi[7], nAb.createOr(nAb.createAnd(u8lastscope, bit5a1), s43_hi7));
226    nAb.createAssign(u16_lo[0], nAb.createOr(nAb.createAnd(u8lastscope, bit6a1), s43_lo0));
227
228    Var * p234_lo1 = main.createVar("p234_lo1", zeroes);
229
230    nAb.createAssign(p234_lo1, nAb.createOr(nAb.createAnd(u8lastscope, bit7a1), s43_lo1));
231
232    main.createIf(nonASCII, nAb);
233    //
234    //
235    PabloAST * ASCII = ccc.compileCC(re::makeCC(0x0, 0x7F));
236    PabloAST * last_byte = main.createOr(ASCII, u8lastscope);
237    main.createAssign(u16_lo[1], main.createOr(main.createAnd(ASCII, u8_bits[1]), p234_lo1));
238    main.createAssign(u16_lo[2], main.createOr(main.createAnd(last_byte, u8_bits[2]), s43_lo2));
239    main.createAssign(u16_lo[3], main.createOr(main.createAnd(last_byte, u8_bits[3]), s43_lo3));
240    main.createAssign(u16_lo[4], main.createOr(main.createAnd(last_byte, u8_bits[4]), s43_lo4));
241    main.createAssign(u16_lo[5], main.createOr(main.createAnd(last_byte, u8_bits[5]), s43_lo5));
242    main.createAssign(u16_lo[6], main.createOr(main.createAnd(last_byte, u8_bits[6]), s43_lo6));
243    main.createAssign(u16_lo[7], main.createOr(main.createAnd(last_byte, u8_bits[7]), s43_lo7));
244   
245    Var * output = kernel->addOutput("output", kernel->getStreamSetTy(16));
246    Var * delmask_out = kernel->addOutput("delmask_out", kernel->getStreamSetTy());
247    Var * error_mask_out = kernel->addOutput("error_mask_out", kernel->getStreamSetTy());
248    for (unsigned i = 0; i < 8; i++) {
249        main.createAssign(main.createExtract(output, i), u16_hi[i]);
250    }
251    for (unsigned i = 0; i < 8; i++) {
252        main.createAssign(main.createExtract(output, i + 8), u16_lo[i]);
253    }
254    main.createAssign(main.createExtract(delmask_out, main.getInteger(0)), delmask);
255    main.createAssign(main.createExtract(error_mask_out,  main.getInteger(0)), error_mask);
256
257    pablo_function_passes(kernel);
258}
259
260Function * u8u16Pipeline(Module * mod, IDISA::IDISA_Builder * iBuilder) {
261
262    const unsigned segmentSize = codegen::SegmentSize;
263    const unsigned bufferSegments = codegen::BufferSegments;
264   
265    assert (iBuilder);
266
267    ExternalFileBuffer ByteStream(iBuilder, iBuilder->getStreamSetTy(1, 8));
268
269    CircularBuffer BasisBits(iBuilder, iBuilder->getStreamSetTy(8), segmentSize * bufferSegments);
270
271    CircularBuffer U8u16Bits(iBuilder, iBuilder->getStreamSetTy(16), segmentSize * bufferSegments);
272    CircularBuffer DelMask(iBuilder, iBuilder->getStreamSetTy(), segmentSize * bufferSegments);
273    CircularBuffer ErrorMask(iBuilder, iBuilder->getStreamSetTy(), segmentSize * bufferSegments);
274
275    CircularBuffer U16Bits(iBuilder, iBuilder->getStreamSetTy(16), segmentSize * bufferSegments);
276   
277    CircularBuffer DeletionCounts(iBuilder, iBuilder->getStreamSetTy(), segmentSize * bufferSegments);
278
279    // Different choices for the output buffer depending on chosen option.
280    ExternalFileBuffer U16external(iBuilder, iBuilder->getStreamSetTy(1, 16));
281    LinearCopybackBuffer U16out(iBuilder, iBuilder->getStreamSetTy(16, 16), segmentSize * bufferSegments + 2);
282
283    s2pKernel s2pk(iBuilder);
284
285    s2pk.generateKernel({&ByteStream}, {&BasisBits});
286
287    pablo::PabloKernel u8u16k(iBuilder, "u8u16");
288
289    u8u16_pablo(&u8u16k);
290
291    u8u16k.generateKernel({&BasisBits}, {&U8u16Bits, &DelMask, &ErrorMask});
292
293    DeletionKernel delK(iBuilder, iBuilder->getBitBlockWidth()/16, 16);
294    delK.generateKernel({&U8u16Bits, &DelMask}, {&U16Bits, &DeletionCounts});
295
296    p2s_16Kernel_withCompressedOutput p2sk(iBuilder);
297
298    stdOutKernel stdoutK(iBuilder, 16);
299
300    if (mMapBuffering || memAlignBuffering) {
301        p2sk.generateKernel({&U16Bits, &DeletionCounts}, {&U16external});
302        stdoutK.generateKernel({&U16external}, {});
303    } else {
304        p2sk.generateKernel({&U16Bits, &DeletionCounts}, {&U16out});
305        stdoutK.generateKernel({&U16out}, {});
306    }
307
308    Type * const size_ty = iBuilder->getSizeTy();
309    Type * const voidTy = Type::getVoidTy(mod->getContext());
310    Type * const bitBlockType = iBuilder->getBitBlockType();
311    Type * const inputType = ArrayType::get(ArrayType::get(bitBlockType, 8), 1)->getPointerTo();
312    Type * const outputType = ArrayType::get(ArrayType::get(bitBlockType, 16), 1)->getPointerTo();
313    Type * const int32ty = iBuilder->getInt32Ty();
314    Type * const int8PtrTy = iBuilder->getInt8PtrTy();
315    Type * const voidPtrTy = Type::getVoidTy(mod->getContext())->getPointerTo();
316
317    Function * const main = cast<Function>(mod->getOrInsertFunction("Main", voidTy, inputType, outputType, size_ty, nullptr));
318    main->setCallingConv(CallingConv::C);
319    Function::arg_iterator args = main->arg_begin();
320
321    Value * const inputStream = &*(args++);
322    inputStream->setName("inputStream");
323    Value * const outputStream = &*(args++);
324    outputStream->setName("outputStream");
325    Value * const fileSize = &*(args++);
326    fileSize->setName("fileSize");
327
328    iBuilder->SetInsertPoint(BasicBlock::Create(mod->getContext(), "entry", main,0));
329
330    ByteStream.setStreamSetBuffer(inputStream, fileSize);
331    BasisBits.allocateBuffer();
332    U8u16Bits.allocateBuffer();
333    DelMask.allocateBuffer();
334    ErrorMask.allocateBuffer();
335    U16Bits.allocateBuffer();
336    DeletionCounts.allocateBuffer();
337    if (mMapBuffering || memAlignBuffering) {
338        U16external.setEmptyBuffer(outputStream);
339    } else {
340        U16out.allocateBuffer();
341    }
342
343    Type * pthreadTy = size_ty;
344    FunctionType * funVoidPtrVoidTy = FunctionType::get(voidTy, int8PtrTy, false);
345
346    Function * pthreadCreateFunc = cast<Function>(mod->getOrInsertFunction("pthread_create",
347                                                                         int32ty,
348                                                                         pthreadTy->getPointerTo(),
349                                                                         voidPtrTy,
350                                                                         static_cast<Type *>(funVoidPtrVoidTy)->getPointerTo(),
351                                                                         voidPtrTy, nullptr));
352    pthreadCreateFunc->setCallingConv(llvm::CallingConv::C);
353    Function * pthreadJoinFunc = cast<Function>(mod->getOrInsertFunction("pthread_join",
354                                                                       int32ty,
355                                                                       pthreadTy,
356                                                                       PointerType::get(int8PtrTy, 0), nullptr));
357    pthreadJoinFunc->setCallingConv(llvm::CallingConv::C);
358
359    Function * pthreadExitFunc = cast<Function>(mod->getOrInsertFunction("pthread_exit",
360                                                                       voidTy,
361                                                                       voidPtrTy, nullptr));
362    pthreadExitFunc->addFnAttr(llvm::Attribute::NoReturn);
363    pthreadExitFunc->setCallingConv(llvm::CallingConv::C);
364
365    if (segmentPipelineParallel){
366        generateSegmentParallelPipeline(iBuilder, {&s2pk, &u8u16k, &delK, &p2sk, &stdoutK}, fileSize);
367    } else {
368        generatePipelineLoop(iBuilder, {&s2pk, &u8u16k, &delK, &p2sk, &stdoutK}, fileSize);
369    }
370
371    iBuilder->CreateRetVoid();
372    return main;
373}
374
375
376
377
378
379typedef void (*u8u16FunctionType)(char * byte_data, char * output_data, size_t filesize);
380
381static ExecutionEngine * u8u16Engine = nullptr;
382
383u8u16FunctionType u8u16CodeGen(void) {
384    LLVMContext TheContext;                           
385    Module * M = new Module("u8u16", TheContext);
386    IDISA::IDISA_Builder * idb = IDISA::GetIDISA_Builder(M);
387
388    llvm::Function * main_IR = u8u16Pipeline(M, idb);
389   
390    verifyModule(*M, &dbgs());
391    //std::cerr << "ExecuteKernels(); done\n";
392    u8u16Engine = JIT_to_ExecutionEngine(M);
393   
394    u8u16Engine->finalizeObject();
395    //std::cerr << "finalizeObject(); done\n";
396
397    delete idb;
398    return reinterpret_cast<u8u16FunctionType>(u8u16Engine->getPointerToFunction(main_IR));
399}
400
401void u8u16(u8u16FunctionType fn_ptr, const std::string & fileName) {
402    std::string mFileName = fileName;
403    size_t mFileSize;
404    char * mFileBuffer;
405   
406    const boost::filesystem::path file(mFileName);
407    if (exists(file)) {
408        if (is_directory(file)) {
409            return;
410        }
411    } else {
412        std::cerr << "Error: cannot open " << mFileName << " for processing. Skipped.\n";
413        return;
414    }
415   
416    mFileSize = file_size(file);
417    boost::iostreams::mapped_file_source mFile;
418    if (mFileSize == 0) {
419        mFileBuffer = nullptr;
420    }
421    else {
422        try {
423            mFile.open(mFileName);
424        } catch (std::exception &e) {
425            std::cerr << "Error: Boost mmap of " << mFileName << ": " << e.what() << std::endl;
426            return;
427        }
428        mFileBuffer = const_cast<char *>(mFile.data());
429    }
430
431    if (mMapBuffering) {
432        boost::interprocess::mapped_region outputBuffer(boost::interprocess::anonymous_shared_memory(2*mFileSize));
433        outputBuffer.advise(boost::interprocess::mapped_region::advice_willneed);
434        outputBuffer.advise(boost::interprocess::mapped_region::advice_sequential);
435        fn_ptr(mFileBuffer, static_cast<char*>(outputBuffer.get_address()), mFileSize);
436    }
437    else if (memAlignBuffering) {
438        char * outputBuffer;
439        posix_memalign(reinterpret_cast<void **>(&outputBuffer), 32, 2*mFileSize);
440        fn_ptr(mFileBuffer, outputBuffer, mFileSize);
441        free(reinterpret_cast<void *>(outputBuffer));
442    }
443    else {
444        /* No external output buffer */
445        fn_ptr(mFileBuffer, nullptr, mFileSize);
446    }
447    mFile.close();
448   
449}
450
451
452int main(int argc, char *argv[]) {
453    cl::HideUnrelatedOptions(ArrayRef<const cl::OptionCategory *>{&u8u16Options, pablo::pablo_toolchain_flags(), codegen::codegen_flags()});
454    cl::ParseCommandLineOptions(argc, argv);
455
456    u8u16FunctionType fn_ptr = u8u16CodeGen();
457
458    for (unsigned i = 0; i != inputFiles.size(); ++i) {
459        u8u16(fn_ptr, inputFiles[i]);
460    }
461
462    return 0;
463}
464
465                       
Note: See TracBrowser for help on using the repository browser.