source: icGREP/icgrep-devel/icgrep/llvm_gen.cpp @ 3982

Last change on this file since 3982 was 3982, checked in by daled, 5 years ago

icGREP now support Unicode categories.

File size: 37.5 KB
Line 
1/*
2 *  Copyright (c) 2014 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 "llvm_gen.h"
8#include "printer_pablos.h"
9
10Ps* ps = NULL; Nl* nl = NULL; No* no = NULL; Lo* lo = NULL; Ll* ll = NULL; Lm* lm = NULL; Nd* nd = NULL;
11Pc* pc = NULL; Lt* lt = NULL; Lu* lu = NULL; Pf* pf = NULL; Pd* pd = NULL; Pe* pe = NULL; Pi* pi = NULL;
12Po* po = NULL; Me* me = NULL; Mc* mc = NULL; Mn* mn = NULL; Sk* sk = NULL; So* so = NULL; Sm* sm = NULL;
13Sc* sc = NULL; Zl* zl = NULL; Co* co = NULL; Cn* cn = NULL; Cc* cc = NULL; Cf* cf = NULL; Cs* cs = NULL;
14Zp* zp = NULL; Zs* zs = NULL;
15
16extern "C" {
17  void wrapped_print_register(BitBlock bit_block) {
18      print_register<BitBlock>("", bit_block);
19  }
20}
21
22extern "C" {
23    BitBlock wrapped_get_category_Ps(Basis_bits &basis_bits){
24        if (ps == NULL) ps = new Ps();
25        Struct_Ps ps_output;
26        ps->do_block(basis_bits, ps_output);
27
28        return ps_output.cc;
29    }
30}
31
32extern "C" {
33    BitBlock wrapped_get_category_Nl(Basis_bits &basis_bits){
34        if (nl == NULL) nl = new Nl();
35        Struct_Nl nl_output;
36        nl->do_block(basis_bits, nl_output);
37
38        return nl_output.cc;
39    }
40}
41
42extern "C" {
43    BitBlock wrapped_get_category_No(Basis_bits &basis_bits){
44        if (no == NULL) no = new No();
45        Struct_No no_output;
46        no->do_block(basis_bits, no_output);
47
48        return no_output.cc;
49    }
50}
51
52extern "C" {
53    BitBlock wrapped_get_category_Lo(Basis_bits &basis_bits){
54        if (lo == NULL) lo = new Lo();
55        Struct_Lo lo_output;
56        lo->do_block(basis_bits, lo_output);
57
58        return lo_output.cc;
59    }
60}
61
62extern "C" {
63    BitBlock wrapped_get_category_Ll(Basis_bits &basis_bits){
64        if (ll == NULL) ll = new Ll();
65        Struct_Ll ll_output;
66        ll->do_block(basis_bits, ll_output);
67
68        return ll_output.cc;
69    }
70}
71
72extern "C" {
73    BitBlock wrapped_get_category_Lm(Basis_bits &basis_bits){
74        if (lm == NULL) lm = new Lm();
75        Struct_Lm lm_output;
76        lm->do_block(basis_bits, lm_output);
77
78        return lm_output.cc;
79    }
80}
81
82extern "C" {
83    BitBlock wrapped_get_category_Nd(Basis_bits &basis_bits){
84        if (nd == NULL) nd = new Nd();
85        Struct_Nd nd_output;
86        nd->do_block(basis_bits, nd_output);
87
88        return nd_output.cc;
89    }
90}
91
92extern "C" {
93    BitBlock wrapped_get_category_Pc(Basis_bits &basis_bits){
94        if (pc == NULL) pc = new Pc();
95        Struct_Pc pc_output;
96        pc->do_block(basis_bits, pc_output);
97
98        return pc_output.cc;
99    }
100}
101
102extern "C" {
103    BitBlock wrapped_get_category_Lt(Basis_bits &basis_bits){
104        if (lt == NULL) lt = new Lt();
105        Struct_Lt lt_output;
106        lt->do_block(basis_bits, lt_output);
107
108        return lt_output.cc;
109    }
110}
111
112extern "C" {
113    BitBlock wrapped_get_category_Lu(Basis_bits &basis_bits){
114        if (lu == NULL) lu = new Lu();
115        Struct_Lu lu_output;
116        lu->do_block(basis_bits, lu_output);
117
118        return lu_output.cc;
119    }
120}
121
122extern "C" {
123    BitBlock wrapped_get_category_Pf(Basis_bits &basis_bits){
124        if (pf == NULL) pf = new Pf();
125        Struct_Pf pf_output;
126        pf->do_block(basis_bits, pf_output);
127
128        return pf_output.cc;
129    }
130}
131
132extern "C" {
133    BitBlock wrapped_get_category_Pd(Basis_bits &basis_bits){
134        if (pd == NULL) pd = new Pd();
135        Struct_Pd pd_output;
136        pd->do_block(basis_bits, pd_output);
137
138        return pd_output.cc;
139    }
140}
141
142extern "C" {
143    BitBlock wrapped_get_category_Pe(Basis_bits &basis_bits){
144        if (pe == NULL) pe = new Pe();
145        Struct_Pe pe_output;
146        pe->do_block(basis_bits, pe_output);
147
148        return pe_output.cc;
149    }
150}
151
152extern "C" {
153    BitBlock wrapped_get_category_Pi(Basis_bits &basis_bits){
154        if (pi == NULL) pi = new Pi();
155        Struct_Pi pi_output;
156        pi->do_block(basis_bits, pi_output);
157
158        return pi_output.cc;
159    }
160}
161
162extern "C" {
163    BitBlock wrapped_get_category_Po(Basis_bits &basis_bits){
164        if (po == NULL) po = new Po();
165        Struct_Po po_output;
166        po->do_block(basis_bits, po_output);
167
168        return po_output.cc;
169    }
170}
171
172extern "C" {
173    BitBlock wrapped_get_category_Me(Basis_bits &basis_bits){
174        if (me == NULL) me = new Me();
175        Struct_Me me_output;
176        me->do_block(basis_bits, me_output);
177
178        return me_output.cc;
179    }
180}
181
182extern "C" {
183    BitBlock wrapped_get_category_Mc(Basis_bits &basis_bits){
184        if (mc == NULL) mc = new Mc();
185        Struct_Mc mc_output;
186        mc->do_block(basis_bits, mc_output);
187
188        return mc_output.cc;
189    }
190}
191
192extern "C" {
193    BitBlock wrapped_get_category_Mn(Basis_bits &basis_bits){
194        if (mn == NULL) mn = new Mn();
195        Struct_Mn mn_output;
196        mn->do_block(basis_bits, mn_output);
197
198        return mn_output.cc;
199    }
200}
201
202extern "C" {
203    BitBlock wrapped_get_category_Sk(Basis_bits &basis_bits){
204        if (sk == NULL) sk = new Sk();
205        Struct_Sk sk_output;
206        sk->do_block(basis_bits, sk_output);
207
208        return sk_output.cc;
209    }
210}
211
212extern "C" {
213    BitBlock wrapped_get_category_So(Basis_bits &basis_bits){
214        if (so == NULL) so = new So();
215        Struct_So so_output;
216        so->do_block(basis_bits, so_output);
217
218        return so_output.cc;
219    }
220}
221
222extern "C" {
223    BitBlock wrapped_get_category_Sm(Basis_bits &basis_bits){
224        if (sm == NULL) sm = new Sm();
225        Struct_Sm sm_output;
226        sm->do_block(basis_bits, sm_output);
227
228        return sm_output.cc;
229    }
230}
231
232extern "C" {
233    BitBlock wrapped_get_category_Sc(Basis_bits &basis_bits){
234        if (sc == NULL) sc = new Sc();
235        Struct_Sc sc_output;
236        sc->do_block(basis_bits, sc_output);
237
238        return sc_output.cc;
239    }
240}
241
242extern "C" {
243    BitBlock wrapped_get_category_Zl(Basis_bits &basis_bits){
244        if (zl == NULL) zl = new Zl();
245        Struct_Zl zl_output;
246        zl->do_block(basis_bits, zl_output);
247
248        return zl_output.cc;
249    }
250}
251
252extern "C" {
253    BitBlock wrapped_get_category_Co(Basis_bits &basis_bits){
254        if (co == NULL) co = new Co();
255        Struct_Co co_output;
256        co->do_block(basis_bits, co_output);
257
258        return co_output.cc;
259    }
260}
261
262extern "C" {
263    BitBlock wrapped_get_category_Cn(Basis_bits &basis_bits){
264        if (cn == NULL) cn = new Cn();
265        Struct_Cn cn_output;
266        cn->do_block(basis_bits, cn_output);
267
268        return cn_output.cc;
269    }
270}
271
272extern "C" {
273    BitBlock wrapped_get_category_Cc(Basis_bits &basis_bits){
274        if (cc == NULL) cc = new Cc();
275        Struct_Cc cc_output;
276        cc->do_block(basis_bits, cc_output);
277
278        return cc_output.cc;
279    }
280}
281
282extern "C" {
283    BitBlock wrapped_get_category_Cf(Basis_bits &basis_bits){
284        if (cf == NULL) cf = new Cf();
285        Struct_Cf cf_output;
286        cf->do_block(basis_bits, cf_output);
287
288        return cf_output.cc;
289    }
290}
291
292extern "C" {
293    BitBlock wrapped_get_category_Cs(Basis_bits &basis_bits){
294        if (cs == NULL) cs = new Cs();
295        Struct_Cs cs_output;
296        cs->do_block(basis_bits, cs_output);
297
298        return cs_output.cc;
299    }
300}
301
302extern "C" {
303    BitBlock wrapped_get_category_Zp(Basis_bits &basis_bits){
304        if (zp == NULL) zp = new Zp();
305        Struct_Zp zp_output;
306        zp->do_block(basis_bits, zp_output);
307
308        return zp_output.cc;
309    }
310}
311
312extern "C" {
313    BitBlock wrapped_get_category_Zs(Basis_bits &basis_bits){
314        if (zs == NULL) zs = new Zs();
315        Struct_Zs zs_output;
316        zs->do_block(basis_bits, zs_output);
317
318        return zs_output.cc;
319    }
320}
321
322LLVM_Generator::LLVM_Generator(std::map<std::string, std::string> name_map, std::string basis_pattern, int bits)
323{
324    m_name_map = name_map;
325    mBasis_Pattern = basis_pattern;
326    mBits = bits;
327}
328
329LLVM_Generator::~LLVM_Generator()
330{
331    delete mMod;
332
333    if (ps != NULL) delete ps;
334    if (nl != NULL) delete nl;
335    if (no != NULL) delete no;
336    if (lo != NULL) delete lo;
337    if (ll != NULL) delete ll;
338    if (lm != NULL) delete lm;
339    if (nd != NULL) delete nd;
340    if (pc != NULL) delete pc;
341    if (lt != NULL) delete lt;
342    if (lu != NULL) delete lu;
343    if (pf != NULL) delete pf;
344    if (pd != NULL) delete pd;
345    if (pe != NULL) delete pe;
346    if (pi != NULL) delete pi;
347    if (po != NULL) delete po;
348    if (me != NULL) delete me;
349    if (mc != NULL) delete mc;
350    if (mn != NULL) delete mn;
351    if (sk != NULL) delete sk;
352    if (so != NULL) delete so;
353    if (sm != NULL) delete sm;
354    if (sc != NULL) delete sc;
355    if (zl != NULL) delete zl;
356    if (co != NULL) delete co;
357    if (cn != NULL) delete cn;
358    if (cc != NULL) delete cc;
359    if (cf != NULL) delete cf;
360    if (cs != NULL) delete cs;
361    if (zp != NULL) delete zp;
362    if (zs != NULL) delete zs;
363
364}
365
366LLVM_Gen_RetVal LLVM_Generator::Generate_LLVMIR(CodeGenState cg_state, CodeGenState subexpression_cg_state, std::list<PabloS*> cc_cgo_stmtsl)
367{
368    //Create the module.
369    MakeLLVMModule();
370
371    //Create the jit execution engine.up
372    InitializeNativeTarget();
373    std::string ErrStr;
374
375    mExecutionEngine = EngineBuilder(mMod).setUseMCJIT(true).setErrorStr(&ErrStr).setOptLevel(CodeGenOpt::Level::Less).create();
376    if (!mExecutionEngine)
377    {
378        std::cout << "\nCould not create ExecutionEngine: " + ErrStr << std::endl;
379        exit(1);
380    }
381
382    InitializeNativeTargetAsmPrinter();
383    InitializeNativeTargetAsmParser();
384
385    DefineTypes();
386    DeclareFunctions();
387    DeclareCallFunctions(cg_state.stmtsl);
388
389    Function::arg_iterator args = mFunc_process_block->arg_begin();
390    Value* ptr_basis_bits = args++;
391    ptr_basis_bits->setName("basis_bits");
392    mptr_carry_q = args++;
393    mptr_carry_q->setName("carry_q");
394    Value* ptr_output = args++;
395    ptr_output->setName("output");
396
397    //Create the carry queue.
398    mCarryQueueIdx = 0;
399    mCarryQueueSize = LLVM_Generator_Helper::CarryCount_PabloStatements(subexpression_cg_state.stmtsl);
400    mCarryQueueSize += LLVM_Generator_Helper::CarryCount_PabloStatements(cg_state.stmtsl);
401
402    mBasicBlock = BasicBlock::Create(mMod->getContext(), "parabix_entry", mFunc_process_block,0);
403
404    //The basis bits structure
405    mPtr_basis_bits_addr = new AllocaInst(mStruct_Basis_Bits_Ptr1, "basis_bits.addr", mBasicBlock);
406    StoreInst* void_14 = new StoreInst(ptr_basis_bits, mPtr_basis_bits_addr, false, mBasicBlock);
407
408    for (int i = 0; i < mBits; i++)
409    {
410        StoreBitBlockMarkerPtr(mBasis_Pattern + INT2STRING(i), i);
411    }
412
413    //The output structure.
414    mPtr_output_addr = new AllocaInst(mStruct_Output_Ptr1, "output.addr", mBasicBlock);
415    StoreInst* void_16 = new StoreInst(ptr_output, mPtr_output_addr, false, mBasicBlock);
416
417    //Generate the IR instructions for the function.
418
419    Generate_PabloStatements(cc_cgo_stmtsl);
420    Generate_PabloStatements(subexpression_cg_state.stmtsl);
421    Generate_PabloStatements(cg_state.stmtsl);
422    SetReturnMarker(cg_state.newsym, 0);
423    SetReturnMarker(m_name_map.find("LineFeed")->second, 1);
424
425    //Terminate the block
426    ReturnInst::Create(mMod->getContext(), mBasicBlock);
427
428    //Create a verifier.  The verifier will print an error message if our module is malformed in any way.
429    verifyModule(*mMod, PrintMessageAction);
430
431    //Un-comment this line in order to display the IR that has been generated by this module.
432    //mMod->dump();
433
434    //Use the pass manager to run optimizations on the function.
435    FunctionPassManager fpm(mMod);
436
437    // Set up the optimizer pipeline.  Start with registering info about how the target lays out data structures.
438    fpm.add(new DataLayout(*mExecutionEngine->getDataLayout()));
439
440    fpm.add(createPromoteMemoryToRegisterPass()); //Transform to SSA form.
441
442    fpm.add(createBasicAliasAnalysisPass());      //Provide basic AliasAnalysis support for GVN. (Global Value Numbering)
443    fpm.add(createInstructionCombiningPass());    //Simple peephole optimizations and bit-twiddling.
444    fpm.add(createCFGSimplificationPass());       //Simplify the control flow graph (deleting unreachable blocks, etc).
445    fpm.add(createReassociatePass());             //Reassociate expressions.
446    fpm.add(createGVNPass());                     //Eliminate common subexpressions.
447
448    fpm.doInitialization();
449
450    fpm.run(*mFunc_process_block);
451
452    //mMod->dump();
453
454    mExecutionEngine->finalizeObject();
455
456    LLVM_Gen_RetVal retVal;
457    //Return the required size of the carry queue and a pointer to the process_block function.
458    retVal.carry_q_size = mCarryQueueSize;
459    retVal.process_block_fptr = mExecutionEngine->getPointerToFunction(mFunc_process_block);
460
461    return retVal;
462}
463
464void LLVM_Generator::DefineTypes()
465{
466    //The BitBlock vector.
467    m64x2Vect = VectorType::get(IntegerType::get(mMod->getContext(), 64), 2);
468    m128x1Vect = VectorType::get(IntegerType::get(mMod->getContext(), 128), 1);
469    //A pointer to the BitBlock vector.
470    m64x2Vect_Ptr1 = PointerType::get(m64x2Vect, 0);
471
472    //Constant definitions.
473    mConst_int64_neg1 = ConstantInt::get(mMod->getContext(), APInt(64, StringRef("-1"), 10));
474
475    mConst_Aggregate_64x2_0 = ConstantAggregateZero::get(m64x2Vect);
476    std::vector<Constant*> const_packed_27_elems;
477    const_packed_27_elems.push_back(mConst_int64_neg1);
478    const_packed_27_elems.push_back(mConst_int64_neg1);
479    mConst_Aggregate_64x2_neg1 = ConstantVector::get(const_packed_27_elems);
480
481
482    StructType *StructTy_struct_Basis_bits = mMod->getTypeByName("struct.Basis_bits");
483    if (!StructTy_struct_Basis_bits) {
484        StructTy_struct_Basis_bits = StructType::create(mMod->getContext(), "struct.Basis_bits");
485    }
486    std::vector<Type*>StructTy_struct_Basis_bits_fields;
487    for (int i = 0; i < mBits; i++)
488    {
489        StructTy_struct_Basis_bits_fields.push_back(m64x2Vect);
490    }
491    if (StructTy_struct_Basis_bits->isOpaque()) {
492        StructTy_struct_Basis_bits->setBody(StructTy_struct_Basis_bits_fields, /*isPacked=*/false);
493    }
494
495    mStruct_Basis_Bits_Ptr1 = PointerType::get(StructTy_struct_Basis_bits, 0);
496
497    std::vector<Type*>FuncTy_0_args;
498    FuncTy_0_args.push_back(mStruct_Basis_Bits_Ptr1);
499
500    //The carry q array.
501    FuncTy_0_args.push_back(m64x2Vect_Ptr1);
502
503    //The output structure.
504    StructType *StructTy_struct_Output = mMod->getTypeByName("struct.Output");
505    if (!StructTy_struct_Output) {
506        StructTy_struct_Output = StructType::create(mMod->getContext(), "struct.Output");
507    }
508    std::vector<Type*>StructTy_struct_Output_fields;
509    StructTy_struct_Output_fields.push_back(m64x2Vect);
510    StructTy_struct_Output_fields.push_back(m64x2Vect);
511    if (StructTy_struct_Output->isOpaque()) {
512        StructTy_struct_Output->setBody(StructTy_struct_Output_fields, /*isPacked=*/false);
513    }
514    mStruct_Output_Ptr1 = PointerType::get(StructTy_struct_Output, 0);
515
516    //The &output parameter.
517    FuncTy_0_args.push_back(mStruct_Output_Ptr1);
518
519    mFuncTy_0 = FunctionType::get(
520     /*Result=*/Type::getVoidTy(mMod->getContext()),
521     /*Params=*/FuncTy_0_args,
522     /*isVarArg=*/false);
523}
524
525void LLVM_Generator::DeclareFunctions()
526{
527    //mFunc_get_unicode_category = mMod->getOrInsertFunction("wrapped_get_unicode_category", m64x2Vect, mStruct_Basis_Bits_Ptr1, Type::getInt8PtrTy(mMod->getContext()), NULL);
528    //mExecutionEngine->addGlobalMapping(cast<GlobalValue>(mFunc_get_unicode_category), (void *)&wrapped_get_unicode_category);
529
530    //This function can be used for testing to print the contents of a register from JIT'd code to the terminal window.
531    mFunc_print_register = mMod->getOrInsertFunction("wrapped_print_register", Type::getVoidTy(getGlobalContext()), m64x2Vect, NULL);
532
533    mExecutionEngine->addGlobalMapping(cast<GlobalValue>(mFunc_print_register), (void *)&wrapped_print_register);
534    // to call->  b.CreateCall(mFunc_print_register, unicode_category);
535
536    SmallVector<AttributeSet, 4> Attrs;
537    AttributeSet PAS;
538    {
539        AttrBuilder B;
540        B.addAttribute(Attribute::ReadOnly);
541        B.addAttribute(Attribute::NoCapture);
542        PAS = AttributeSet::get(mMod->getContext(), 1U, B);
543    }
544    Attrs.push_back(PAS);
545    {
546        AttrBuilder B;
547        B.addAttribute(Attribute::NoCapture);
548        PAS = AttributeSet::get(mMod->getContext(), 2U, B);
549    }
550    Attrs.push_back(PAS);
551    {
552        AttrBuilder B;
553        B.addAttribute(Attribute::NoCapture);
554        PAS = AttributeSet::get(mMod->getContext(), 3U, B);
555    }
556    Attrs.push_back(PAS);
557    {
558        AttrBuilder B;
559        B.addAttribute(Attribute::NoUnwind);
560        B.addAttribute(Attribute::UWTable);
561        PAS = AttributeSet::get(mMod->getContext(), ~0U, B);
562    }
563    AttributeSet AttrSet = AttributeSet::get(mMod->getContext(), Attrs);
564
565    //Create the function that will be generated.
566    mFunc_process_block = mMod->getFunction("process_block");
567    if (!mFunc_process_block) {
568        mFunc_process_block = Function::Create(
569            /*Type=*/mFuncTy_0,
570            /*Linkage=*/GlobalValue::ExternalLinkage,
571            /*Name=*/"process_block", mMod);
572        mFunc_process_block->setCallingConv(CallingConv::C);
573    }
574    mFunc_process_block->setAttributes(AttrSet);
575}
576
577void LLVM_Generator::DeclareCallFunctions(std::list<PabloS*> stmts)
578{
579    std::list<PabloS*>::iterator it;
580    for (it = stmts.begin(); it != stmts.end(); ++it)
581    {
582        DeclareCallFunctions_PabloS(*it);
583    }
584}
585
586void LLVM_Generator::DeclareCallFunctions_PabloS(PabloS* stmt)
587{
588    if (Assign* an = dynamic_cast<Assign*>(stmt))
589    {
590        DeclareCallFunctions_PabloE(an->getExpr());
591    }
592    if (While* whl = dynamic_cast<While*>(stmt))
593    {
594        DeclareCallFunctions_PabloE(whl->getExpr());
595        DeclareCallFunctions(whl->getPSList());
596    }
597}
598
599void LLVM_Generator::DeclareCallFunctions_PabloE(PabloE* expr)
600{
601    if (Call* pablo_call = dynamic_cast<Call*>(expr))
602    {
603        std::string callee = "wrapped_get_category_" + pablo_call->getCallee();
604        if (mMarkerMap.find(callee) == mMarkerMap.end())
605        {
606            Value* func_get_unicode_category = mMod->getOrInsertFunction(callee, m64x2Vect, mStruct_Basis_Bits_Ptr1, NULL);
607            void* addr;
608            if (pablo_call->getCallee() == "Ps")
609            {
610                addr = (void *)&wrapped_get_category_Ps;
611            }
612            else if (pablo_call->getCallee() == "Nl")
613            {
614                addr = (void *)&wrapped_get_category_Nl;
615            }
616            else if (pablo_call->getCallee() == "No")
617            {
618                addr = (void *)&wrapped_get_category_No;
619            }
620            else if (pablo_call->getCallee() == "Lo")
621            {
622                addr = (void *)&wrapped_get_category_Lo;
623            }
624            else if (pablo_call->getCallee() == "Ll")
625            {
626                addr = (void *)&wrapped_get_category_Ll;
627            }
628            else if (pablo_call->getCallee() == "Lm")
629            {
630                addr = (void *)&wrapped_get_category_Lm;
631            }
632            else if (pablo_call->getCallee() == "Nd")
633            {
634                addr = (void *)&wrapped_get_category_Nd;
635            }
636            else if (pablo_call->getCallee() == "Pc")
637            {
638                addr = (void *)&wrapped_get_category_Pc;
639            }
640            else if (pablo_call->getCallee() == "Lt")
641            {
642                addr = (void *)&wrapped_get_category_Lt;
643            }
644            else if (pablo_call->getCallee() == "Lu")
645            {
646                addr = (void *)&wrapped_get_category_Lu;
647            }
648            else if (pablo_call->getCallee() == "Pf")
649            {
650                addr = (void *)&wrapped_get_category_Pf;
651            }
652            else if (pablo_call->getCallee() == "Pd")
653            {
654                addr = (void *)&wrapped_get_category_Pd;
655            }
656            else if (pablo_call->getCallee() == "Pe")
657            {
658                addr = (void *)&wrapped_get_category_Pe;
659            }
660            else if (pablo_call->getCallee() == "Pi")
661            {
662                addr = (void *)&wrapped_get_category_Pi;
663            }
664            else if (pablo_call->getCallee() == "Po")
665            {
666                addr = (void *)&wrapped_get_category_Po;
667            }
668            else if (pablo_call->getCallee() == "Me")
669            {
670                addr = (void *)&wrapped_get_category_Me;
671            }
672            else if (pablo_call->getCallee() == "Mc")
673            {
674                addr = (void *)&wrapped_get_category_Mc;
675            }
676            else if (pablo_call->getCallee() == "Mn")
677            {
678                addr = (void *)&wrapped_get_category_Mn;
679            }
680            else if (pablo_call->getCallee() == "Sk")
681            {
682                addr = (void *)&wrapped_get_category_Sk;
683            }
684            else if (pablo_call->getCallee() == "So")
685            {
686                addr = (void *)&wrapped_get_category_So;
687            }
688            else if (pablo_call->getCallee() == "Sm")
689            {
690                addr = (void *)&wrapped_get_category_Sm;
691            }
692            else if (pablo_call->getCallee() == "Sc")
693            {
694                addr = (void *)&wrapped_get_category_Sc;
695            }
696            else if (pablo_call->getCallee() == "Zl")
697            {
698                addr = (void *)&wrapped_get_category_Zl;
699            }
700            else if (pablo_call->getCallee() == "Co")
701            {
702                addr = (void *)&wrapped_get_category_Co;
703            }
704            else if (pablo_call->getCallee() == "Cn")
705            {
706                addr = (void *)&wrapped_get_category_Cn;
707            }
708            else if (pablo_call->getCallee() == "Cc")
709            {
710                addr = (void *)&wrapped_get_category_Cc;
711            }
712            else if (pablo_call->getCallee() == "Cf")
713            {
714                addr = (void *)&wrapped_get_category_Cf;
715            }
716            else if (pablo_call->getCallee() == "Cs")
717            {
718                addr = (void *)&wrapped_get_category_Cs;
719            }
720            else if (pablo_call->getCallee() == "Zp")
721            {
722                addr = (void *)&wrapped_get_category_Zp;
723            }
724            else if (pablo_call->getCallee() == "Zs")
725            {
726                addr = (void *)&wrapped_get_category_Zs;
727            }
728
729            mExecutionEngine->addGlobalMapping(cast<GlobalValue>(func_get_unicode_category), addr);
730            mMarkerMap.insert(make_pair(callee, func_get_unicode_category));
731        }
732    }
733    else if (And* pablo_and = dynamic_cast<And*>(expr))
734    {
735        DeclareCallFunctions_PabloE(pablo_and->getExpr1());
736        DeclareCallFunctions_PabloE(pablo_and->getExpr2());
737    }
738    else if (Or* pablo_or = dynamic_cast<Or*>(expr))
739    {
740        DeclareCallFunctions_PabloE(pablo_or->getExpr1());
741        DeclareCallFunctions_PabloE(pablo_or->getExpr2());
742    }
743    else if (Sel* pablo_sel = dynamic_cast<Sel*>(expr))
744    {
745        DeclareCallFunctions_PabloE(pablo_sel->getIf_expr());
746        DeclareCallFunctions_PabloE(pablo_sel->getT_expr());
747        DeclareCallFunctions_PabloE(pablo_sel->getF_expr());
748    }
749    else if (Not* pablo_not = dynamic_cast<Not*>(expr))
750    {
751        DeclareCallFunctions_PabloE(pablo_not->getExpr());
752    }
753    else if (Advance* adv = dynamic_cast<Advance*>(expr))
754    {
755        DeclareCallFunctions_PabloE(adv->getExpr());
756    }
757    else if (MatchStar* mstar = dynamic_cast<MatchStar*>(expr))
758    {
759        DeclareCallFunctions_PabloE(mstar->getExpr1());
760        DeclareCallFunctions_PabloE(mstar->getExpr2());
761    }
762    else if (ScanThru* sthru = dynamic_cast<ScanThru*>(expr))
763    {
764        DeclareCallFunctions_PabloE(sthru->getScanFrom());
765        DeclareCallFunctions_PabloE(sthru->getScanThru());
766    }
767}
768
769void LLVM_Generator::MakeLLVMModule()
770{
771    mMod = new Module("icgrep", getGlobalContext());
772    mMod->setDataLayout("e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128");
773    mMod->setTargetTriple("x86_64-unknown-linux-gnu");
774}
775
776void LLVM_Generator::StoreBitBlockMarkerPtr(std::string name, int index)
777{
778    IRBuilder<> b(mBasicBlock);
779
780    Value* basis_bits_struct = b.CreateLoad(mPtr_basis_bits_addr);
781    Value* struct_indices[] = {b.getInt64(0), b.getInt32(index)};
782    Value* basis_bits_struct_GEP = b.CreateGEP(basis_bits_struct, struct_indices, name);
783    mMarkerMap.insert(make_pair(name, basis_bits_struct_GEP));
784}
785
786Value* LLVM_Generator::GetMarker(std::string name)
787{
788    IRBuilder<> b(mBasicBlock);
789
790    if (mMarkerMap.find(name) == mMarkerMap.end())
791    {       
792        Value* ptr = b.CreateAlloca(m64x2Vect);
793        Value* void_1 = b.CreateStore(mConst_Aggregate_64x2_0, ptr);
794        mMarkerMap.insert(make_pair(name, ptr));
795    }
796    std::map<std::string, Value*>::iterator itGet = mMarkerMap.find(name);
797
798    return itGet->second;
799}
800
801void LLVM_Generator::SetReturnMarker(std::string marker, int output_idx)
802{
803    IRBuilder<> b(mBasicBlock);
804
805    Value* marker_bitblock = b.CreateLoad(GetMarker(marker));
806    Value* output_struct = b.CreateLoad(mPtr_output_addr);
807    Value* output_indices[] = {b.getInt64(0), b.getInt32(output_idx)};
808    Value* output_struct_GEP = b.CreateGEP(output_struct, output_indices, "return" + marker);
809    Value* store_marker = b.CreateStore(marker_bitblock, output_struct_GEP);
810}
811
812std::string LLVM_Generator::Generate_PabloStatements(std::list<PabloS*> stmts)
813{
814    std::string retVal = "";
815
816    std::list<PabloS*>::iterator it;
817    for (it = stmts.begin(); it != stmts.end(); ++it)
818    {
819        retVal = Generate_PabloS(*it);
820    }
821
822    return retVal;
823}
824
825std::string LLVM_Generator::Generate_PabloS(PabloS *stmt)
826{
827    std::string retVal = "";
828
829    if (Assign* assign = dynamic_cast<Assign*>(stmt))
830    {
831        IRBuilder<> b(mBasicBlock);
832
833        b.CreateStore(Generate_PabloE(assign->getExpr()), GetMarker(assign->getM()));
834
835        retVal = assign->getM();
836    }
837    else if (While* whl = dynamic_cast<While*>(stmt))
838    {
839        int idx = mCarryQueueIdx;
840
841        //With this call to the while body we will account for all of the carry in values.
842        std::string returnMarker = Generate_PabloStatements(whl->getPSList());
843
844        BasicBlock*  whileCondBlock = BasicBlock::Create(mMod->getContext(), "while.cond", mFunc_process_block, 0);
845        BasicBlock*  whileBodyBlock = BasicBlock::Create(mMod->getContext(), "while.body",mFunc_process_block, 0);
846        BasicBlock*  whileEndBlock = BasicBlock::Create(mMod->getContext(), "while.end",mFunc_process_block, 0);
847
848        IRBuilder<> b(mBasicBlock);
849        b.CreateBr(whileCondBlock);
850        mBasicBlock = whileCondBlock;
851        IRBuilder<> b_cond(whileCondBlock);
852
853        Value* expression_marker_value = Generate_PabloE(whl->getExpr());
854        // Use an i128 compare for simplicity and speed.
855        Value* cast_marker_value_1 = b_cond.CreateBitCast(expression_marker_value, IntegerType::get(mMod->getContext(), 128));
856        Value* int_tobool1 = b_cond.CreateICmpEQ(cast_marker_value_1, ConstantInt::get(IntegerType::get(mMod->getContext(), 128), 0));
857        b_cond.CreateCondBr(int_tobool1, whileEndBlock, whileBodyBlock);
858
859        mBasicBlock = whileBodyBlock;
860        mCarryQueueIdx = 0;
861        //Store the current carry queue.
862        Value* ptr_last_carry_q = mptr_carry_q;
863
864        IRBuilder<> b_wb1(mBasicBlock);
865        //Create and initialize a new carry queue.
866        Value* ptr_while_carry_q = b_wb1.CreateAlloca(m64x2Vect, b_wb1.getInt64(mCarryQueueSize - idx));
867        for (int i=0; i<(mCarryQueueSize-idx); i++)
868        {
869            Value* carryq_idx1 = b_wb1.getInt64(i);
870            Value* carryq_GEP1 = b_wb1.CreateGEP(ptr_while_carry_q, carryq_idx1);
871            Value* void_1 = b_wb1.CreateStore(mConst_Aggregate_64x2_0, carryq_GEP1);
872        }
873
874        //Point mptr_carry_q to the new local carry queue.
875        mptr_carry_q = ptr_while_carry_q;
876
877        returnMarker = Generate_PabloStatements(whl->getPSList());
878
879        IRBuilder<> b_wb2(mBasicBlock);
880        //Copy back to the last carry queue the carries from the execution of the while statement list.
881        for (int c=0; c<(mCarryQueueSize-idx); c++)
882        {
883            Value* carryq_idx = b_wb2.getInt64(c);
884            Value* carryq_GEP = b_wb2.CreateGEP(mptr_carry_q, carryq_idx);
885            Value* carryq_value = b_wb2.CreateLoad(carryq_GEP);
886
887            Value* last_carryq_idx = b_wb2.getInt64(idx + c);
888            Value* last_carryq_GEP = b_wb2.CreateGEP(ptr_last_carry_q, last_carryq_idx);
889            Value* last_carryq_value = b_wb2.CreateLoad(last_carryq_GEP);
890
891            Value* new_carryq_value = b_wb2.CreateOr(carryq_value, last_carryq_value);
892            Value* void_1 = b_wb2.CreateStore(new_carryq_value, last_carryq_GEP);
893        }
894
895        b_wb2.CreateBr(whileCondBlock);
896
897        mBasicBlock = whileEndBlock;
898        mptr_carry_q = ptr_last_carry_q;
899        mCarryQueueIdx += idx;
900
901        retVal = returnMarker;
902    }
903
904    return retVal;
905}
906
907Value* LLVM_Generator::Generate_PabloE(PabloE *expr)
908{
909    Value* retVal = 0;
910
911    if (All* all = dynamic_cast<All*>(expr))
912    {
913        IRBuilder<> b(mBasicBlock);
914
915        if ((all->getNum() != 0) && (all->getNum() != 1))
916            std::cout << "\nErr: 'All' can only be set to 1 or 0.\n" << std::endl;
917        Value* ptr_all = b.CreateAlloca(m64x2Vect);
918        Value* void_1 = b.CreateStore((all->getNum() == 0 ? mConst_Aggregate_64x2_0 : mConst_Aggregate_64x2_neg1), ptr_all);
919        Value* all_value = b.CreateLoad(ptr_all);
920
921        retVal = all_value;
922    }
923    else if (Call* call = dynamic_cast<Call*>(expr))
924    {
925        IRBuilder<> b(mBasicBlock);
926
927        //Call the callee once and store the result in the marker map.
928        if (mMarkerMap.find(call->getCallee()) == mMarkerMap.end())
929        {
930            std::map<std::string, Value*>::iterator itFuncGet = mMarkerMap.find("wrapped_get_category_" + call->getCallee());
931            Value* basis_bits_struct = b.CreateLoad(mPtr_basis_bits_addr);
932            Value* unicode_category = b.CreateCall(itFuncGet->second, basis_bits_struct);
933            Value* ptr = b.CreateAlloca(m64x2Vect);
934            Value* void_1 = b.CreateStore(unicode_category, ptr);
935
936            mMarkerMap.insert(make_pair(call->getCallee(), ptr));
937        }
938        std::map<std::string, Value*>::iterator itGet = mMarkerMap.find(call->getCallee());
939        Value * var_value = b.CreateLoad(itGet->second);
940
941
942        retVal = var_value;
943    }
944    else if (Var* var = dynamic_cast<Var*>(expr))
945    {
946        IRBuilder<> b(mBasicBlock);
947
948        Value* var_value = b.CreateLoad(GetMarker(var->getVar()), false, var->getVar());
949
950        retVal = var_value;
951    }
952    else if (And* pablo_and = dynamic_cast<And*>(expr))
953    {
954        IRBuilder<> b(mBasicBlock);
955
956        Value* and_result = b.CreateAnd(Generate_PabloE(pablo_and->getExpr1()), Generate_PabloE(pablo_and->getExpr2()), "and_inst");
957
958        retVal = and_result;
959    }
960    else if (Or* pablo_or = dynamic_cast<Or*>(expr))
961    {
962        IRBuilder<> b(mBasicBlock);
963
964        Value* or_result = b.CreateOr(Generate_PabloE(pablo_or->getExpr1()), Generate_PabloE(pablo_or->getExpr2()), "or_inst");
965
966        retVal = or_result;
967    }
968    else if (Sel* pablo_sel = dynamic_cast<Sel*>(expr))
969    {
970        IRBuilder<>b(mBasicBlock);
971
972        Value* and_if_true_result = b.CreateAnd(Generate_PabloE(pablo_sel->getIf_expr()), Generate_PabloE(pablo_sel->getT_expr()));
973        Constant* const_packed_elems [] = {b.getInt64(-1), b.getInt64(-1)};
974        Constant* const_packed = ConstantVector::get(const_packed_elems);
975        Value* not_if_result = b.CreateXor(Generate_PabloE(pablo_sel->getIf_expr()), const_packed);
976        Value* and_if_false_result = b.CreateAnd(not_if_result, Generate_PabloE(pablo_sel->getF_expr()));
977        Value* or_result = b.CreateOr(and_if_true_result, and_if_false_result);
978
979        retVal = or_result;
980    }
981    else if (Not* pablo_not = dynamic_cast<Not*>(expr))
982    {
983        IRBuilder<> b(mBasicBlock);
984
985        Constant* const_packed_elems [] = {b.getInt64(-1), b.getInt64(-1)};
986        Constant* const_packed = ConstantVector::get(const_packed_elems);
987        Value* expr_value = Generate_PabloE(pablo_not->getExpr());
988        Value* xor_rslt = b.CreateXor(expr_value, const_packed, "xor_inst");
989
990        retVal = xor_rslt;
991    }
992    else if (CharClass* cc = dynamic_cast<CharClass*>(expr))
993    {
994        IRBuilder<> b(mBasicBlock);
995
996        Value* character_class = b.CreateLoad(GetMarker(cc->getCharClass()));
997
998        retVal = character_class;
999    }
1000    else if (Advance* adv = dynamic_cast<Advance*>(expr))
1001    {
1002        IRBuilder<> b(mBasicBlock);
1003
1004        //CarryQ - carry in.
1005        Value* carryq_idx = b.getInt64(mCarryQueueIdx);
1006        Value* carryq_GEP = b.CreateGEP(mptr_carry_q, carryq_idx);
1007        Value* carryq_value = b.CreateLoad(carryq_GEP);
1008
1009        Value* strm_value = Generate_PabloE(adv->getExpr());
1010        Value* srli_1_value = b.CreateLShr(strm_value, 63);
1011
1012        Value* packed_shuffle;
1013        Constant* const_packed_1_elems [] = {b.getInt32(0), b.getInt32(2)};
1014        Constant* const_packed_1 = ConstantVector::get(const_packed_1_elems);
1015        packed_shuffle = b.CreateShuffleVector(carryq_value, srli_1_value, const_packed_1, "packed_shuffle nw");
1016
1017        Constant* const_packed_2_elems[] = {b.getInt64(1), b.getInt64(1)};
1018        Constant* const_packed_2 = ConstantVector::get(const_packed_2_elems);
1019
1020        Value* shl_value = b.CreateShl(strm_value, const_packed_2, "shl_value");
1021        Value* result_value = b.CreateOr(shl_value, packed_shuffle, "or.result_value");
1022
1023        //CarryQ - carry out.
1024        Value* cast_marker_value_1 = b.CreateBitCast(strm_value, IntegerType::get(mMod->getContext(), 128));
1025        Value* srli_2_value = b.CreateLShr(cast_marker_value_1, 127);
1026        Value* carryout_2_carry = b.CreateBitCast(srli_2_value, m64x2Vect);
1027        Value* void_1 = b.CreateStore(carryout_2_carry, carryq_GEP);
1028
1029        //Increment the idx for the next advance or scan through.
1030        mCarryQueueIdx++;
1031
1032        retVal = result_value;
1033    }
1034    else if (MatchStar* mstar = dynamic_cast<MatchStar*>(expr))
1035    {
1036        IRBuilder<> b(mBasicBlock);
1037
1038        //CarryQ - carry in.
1039        Value* carryq_idx = b.getInt64(mCarryQueueIdx);
1040        Value* carryq_GEP = b.CreateGEP(mptr_carry_q, carryq_idx);
1041        Value* carryq_value = b.CreateLoad(carryq_GEP);
1042        //Get the input stream.
1043        Value* strm_value = Generate_PabloE(mstar->getExpr1());
1044        //Get the character that is to be matched.
1045        Value* cc_value = Generate_PabloE(mstar->getExpr2());
1046
1047        Value* and_value_1 = b.CreateAnd(cc_value, strm_value, "match_star_and_value_1");
1048        Value* add_value_1 = b.CreateAdd(and_value_1, cc_value, "match_star_add_value_1");
1049        Value* add_value_2 = b.CreateAdd(add_value_1, carryq_value, "match_star_add_value_2");
1050        Value* xor_value_1 = b.CreateXor(add_value_2, mConst_Aggregate_64x2_neg1, "match_star_xor_value_1");
1051        Value* and_value_2 = b.CreateAnd(cc_value, xor_value_1, "match_star_and_value_2");
1052        Value* or_value_1 = b.CreateOr(and_value_1, and_value_2, "match_star_or_value_1");
1053
1054        Value* srli_instr_1 = b.CreateLShr(or_value_1, 63);
1055
1056        Value* cast_marker_value_1 = b.CreateBitCast(srli_instr_1, IntegerType::get(mMod->getContext(), 128));
1057        Value* sll_1_value = b.CreateShl(cast_marker_value_1, 64);
1058        Value* cast_marker_value_2 = b.CreateBitCast(sll_1_value, m64x2Vect);
1059
1060
1061        Value* add_value_3 = b.CreateAdd(cast_marker_value_2, add_value_2, "match_star_add_value_3");
1062        Value* xor_value_2 = b.CreateXor(add_value_3, mConst_Aggregate_64x2_neg1, "match_star_xor_value_2");
1063        Value* and_value_3 = b.CreateAnd(cc_value, xor_value_2, "match_star_and_value_3");
1064        Value* or_value_2  = b.CreateOr(and_value_1, and_value_3, "match_star_or_value_2 ");
1065        Value* xor_value_3 = b.CreateXor(add_value_3, cc_value, "match_star_xor_value_3");
1066        Value* result_value = b.CreateOr(xor_value_3, strm_value, "match_star_result_value");
1067
1068        //CarryQ - carry out:
1069        Value* cast_marker_value_3 = b.CreateBitCast(or_value_2, IntegerType::get(mMod->getContext(), 128));
1070        Value* srli_2_value = b.CreateLShr(cast_marker_value_3, 127);
1071        Value* carryout_2_carry = b.CreateBitCast(srli_2_value, m64x2Vect);
1072
1073        Value* void_1 = b.CreateStore(carryout_2_carry, carryq_GEP);
1074
1075        mCarryQueueIdx++;
1076
1077        retVal = result_value;
1078    }
1079    else if (ScanThru* sthru = dynamic_cast<ScanThru*>(expr))
1080    {
1081        IRBuilder<> b(mBasicBlock);
1082
1083        //CarryQ - carry in.
1084        Value* carryq_idx = b.getInt64(mCarryQueueIdx);
1085        Value* carryq_GEP = b.CreateGEP(mptr_carry_q, carryq_idx);
1086        Value* carryq_value = b.CreateLoad(carryq_GEP);
1087        //Get the input stream.
1088        Value* strm_value = Generate_PabloE(sthru->getScanFrom());
1089        //Get the scanthru bit stream.
1090        Value* scanthru_value = Generate_PabloE(sthru->getScanThru());
1091
1092        Value* and_value_1 = b.CreateAnd(scanthru_value, strm_value, "scanthru_and_value_1");
1093        Value* add_value_1 = b.CreateAdd(and_value_1, carryq_value, "scanthru_add_value_1");
1094        Value* add_value_2 = b.CreateAdd(add_value_1, scanthru_value, "scanthru_add_value_2");
1095
1096        Value* srli_instr_1 = b.CreateLShr(and_value_1, 63);
1097
1098        Value* cast_marker_value_1 = b.CreateBitCast(srli_instr_1, IntegerType::get(mMod->getContext(), 128));
1099        Value* sll_1_value = b.CreateShl(cast_marker_value_1, 64);
1100        Value* cast_marker_value_2 = b.CreateBitCast(sll_1_value, m64x2Vect);
1101
1102        Value* add_value_3 = b.CreateAdd(cast_marker_value_2, add_value_2, "scanthru_add_value_3");
1103        Value* xor_value_1  = b.CreateXor(scanthru_value, mConst_Aggregate_64x2_neg1, "scanthru_xor_value_1");
1104        Value* result_value = b.CreateAnd(add_value_3, xor_value_1, "scanthru_result_value");
1105
1106        //CarryQ - carry out:
1107        Value* cast_marker_value_3 = b.CreateBitCast(add_value_3, IntegerType::get(mMod->getContext(), 128));
1108        Value* srli_2_value = b.CreateLShr(cast_marker_value_3, 127);
1109        Value* carryout_2_carry = b.CreateBitCast(srli_2_value, m64x2Vect);
1110
1111        Value* void_1 = b.CreateStore(carryout_2_carry, carryq_GEP);
1112
1113        mCarryQueueIdx++;
1114
1115        retVal = result_value;
1116    }
1117
1118    return retVal;
1119}
1120
Note: See TracBrowser for help on using the repository browser.