JIT:Manage addition and display
[scilab.git] / scilab / modules / jit / includes / JITvisitor.hxx
1 /*
2  *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  *  Copyright (C) 2013 - Harris Bakiras <harris.bakiras@lip6.fr>,
4  *  Peter Senna Tschudin <peter.senna@lip6.fr>
5  *
6  *  This file must be used under the terms of the CeCILL.
7  *  This source file is licensed as described in the file COPYING, which
8  *  you should have received as part of this distribution.  The terms
9  *  are also available at
10  *  http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
11  *
12  */
13
14 #ifndef AST_JITVISITOR_HXX
15 #define AST_JITVISITOR_HXX
16
17 #include <time.h>
18 #include <string>
19 #include <iostream>
20 #include <sstream>
21 #include <cstdio>
22 #include <iostream>
23
24 #include "visitor_common.hxx"
25 #include "shortcutvisitor.hxx"
26 #include "printvisitor.hxx"
27 #include "mutevisitor.hxx"
28
29 // Needed by visitprivate(const OpExp &)
30 // Needed by visitprivate(const LogicalOpExp &)
31 #include "generic_operations.hxx"
32 #include "types_or_and.hxx"
33 #include "configvariable.hxx"
34 #include "overload.hxx"
35 #include "scilabexception.hxx"
36
37 //#include "matrix_transpose_int.hxx"
38
39 extern "C" {
40 #include "doublecomplex.h"
41 #include "matrix_transpose.h"
42 #include "os_swprintf.h"
43 #include "more.h"
44 #include "sciprint.h"
45     //#include "HandleManagement.h"
46 }
47
48 #include "timer.hxx"
49 #include "localization.h"
50
51 #include "scilabWrite.hxx"
52 #include "context.hxx"
53
54 #include "all.hxx"
55 #include "types.hxx"
56 #include "alltypes.hxx"
57
58 #undef ID
59 #undef LT
60 #undef GT
61
62 #include "llvm/IR/Constants.h"
63 #include "llvm/IR/DerivedTypes.h"
64 #include "llvm/IR/IRBuilder.h"
65 #include "llvm/IR/LLVMContext.h"
66 #include "llvm/IR/Module.h"
67 #include "llvm/IR/Type.h"
68
69 #include "llvm/Analysis/Verifier.h"
70 #include "llvm/Support/TargetSelect.h"
71 #include "llvm/ExecutionEngine/ExecutionEngine.h"
72 #include "llvm/ExecutionEngine/JIT.h"
73 #include "llvm/PassManager.h"
74 #include "llvm/IR/DataLayout.h"
75 #include "vmkit_core.h"
76
77 #undef WHITE
78 #undef Max
79
80 #include <sys/types.h>
81
82 #include "llvm/IR/Attributes.h"
83 #include "llvm/IR/Function.h"
84 #include "llvm/IR/Instructions.h"
85 #include "llvm/CodeGen/GCStrategy.h"
86 #include "llvm/CodeGen/JITCodeEmitter.h"
87 #include "llvm/CodeGen/MachineFunction.h"
88 #include "llvm/ExecutionEngine/ExecutionEngine.h"
89 #include "llvm/Support/CommandLine.h"
90 #include "llvm/Support/ManagedStatic.h"
91 //#include "llvm/Support/Debug.h"
92 //#include "llvm/Support/raw_ostream.h"
93 #include <llvm/LinkAllPasses.h>
94
95 namespace llvm
96 {
97 #include "../src/cpp/llvm-wrapper-generated.cpp"
98 }
99
100 namespace ast
101 {
102 typedef double (*jitptr_t) ();
103
104 class JITVisitor : public ConstVisitor
105 {
106 private:
107     /*
108      * Attributes
109      */
110     llvm::Value* _result;
111     bool m_bSingleResult;
112     llvm::LLVMContext *context;
113     llvm::Module *TheModule;
114     llvm::IRBuilder<> *Builder;
115     llvm::ExecutionEngine* ee;
116     llvm::FunctionPassManager* pm;
117     llvm::Type* uintptrType;
118     symbol::Context * scilabContext;
119
120
121     void visit (const SeqExp  &e)
122     {
123         visitprivate(e);
124     }
125
126     void visit (const IntExp &e)
127     {
128         visitprivate(e);
129     }
130
131     void visit (const FloatExp &e)
132     {
133         visitprivate(e);
134     }
135
136     void visit (const DoubleExp &e)
137     {
138         visitprivate(e);
139     }
140
141     void visit (const OpExp &e)
142     {
143         visitprivate(e);
144     }
145
146     void visit (const SimpleVar &e)
147     {
148         visitprivate(e);
149     }
150
151
152 public:
153     JITVisitor() : ConstVisitor()
154     {
155         llvm::InitializeNativeTarget();
156         context = &llvm::getGlobalContext();
157         Builder = new llvm::IRBuilder<> (*context);
158         _result = NULL;
159         m_bSingleResult = false;
160         TheModule = new llvm::Module("scilab jit", *context);
161
162         std::string err;
163         llvm::EngineBuilder engine (TheModule);
164         llvm::TargetOptions options;
165         options.NoFramePointerElim = true;
166         engine.setTargetOptions(options);
167         engine.setEngineKind(llvm::EngineKind::JIT);
168         engine.setErrorStr(&err);
169
170         ee = engine.create();
171         if (!ee)
172         {
173             fprintf(stderr, "Could not create ExecutionEngine: %s\n", err.c_str());
174             exit(1);
175         }
176         ee->DisableLazyCompilation(0);
177         ee->addModule(TheModule);
178         TheModule->setDataLayout(ee->getDataLayout()->getStringRepresentation());
179         pm = NULL; /* TODO : init */
180
181         uintptrType = TheModule->getPointerSize() == llvm::Module::Pointer32 ?
182                       llvm::Type::getInt32Ty(*context) : llvm::Type::getInt64Ty(*context);
183
184         TheModule = llvm::makeLLVMModuleContents(TheModule);
185         //TheModule->dump();
186
187         for (llvm::Module::iterator cur = TheModule->begin(), end = TheModule->end(); cur != end; cur++)
188         {
189             void* ptr = dlsym(RTLD_DEFAULT, cur->getName().data());
190             //printf("%s ---> %p\n", cur->getName().data(), ptr);
191             if (ptr)
192             {
193                 ee->updateGlobalMapping(cur, ptr);
194             }
195         }
196
197         scilabContext = symbol::Context::getInstance();
198     }
199
200     void result_set(llvm::Value* const gtVal)
201     {
202         m_bSingleResult = true;
203         _result = gtVal;
204     }
205
206     llvm::Value* result_get()
207     {
208         return  _result;
209     }
210
211     void visitprivate(const DoubleExp &e)
212     {
213         if (e.getBigDouble() == NULL)
214         {
215             Double *pdbl = new Double(e.value_get());
216             (const_cast<DoubleExp *>(&e))->setBigDouble(pdbl);
217         }
218
219         //              llvm::Value* res = llvm::ConstantFP::get(llvm::getGlobalContext(), llvm::APFloat(e.getBigDouble()));
220         llvm::Value* res = llvm::ConstantInt::get(uintptrType, (uintptr_t)e.getBigDouble());
221         res = Builder->CreateIntToPtr(res, llvm::PointerType::getUnqual(TheModule->getTypeByName("class.types::Double")));
222         res->dump();
223         result_set(res);
224         _result->dump();
225     }
226
227     void visitprivate(const FloatExp &e)
228     {
229     }
230
231     void visitprivate(const IntExp &e)
232     {
233     }
234
235     void visitprivate(const SeqExp &e)
236     {
237
238         //T execMe;
239         std::list<Exp *>::const_iterator    itExp;
240
241         for (itExp = e.exps_get().begin (); itExp != e.exps_get().end (); ++itExp)
242         {
243             //reset default values
244             result_set(NULL);
245             llvm::FunctionType *FT = llvm::FunctionType::get(llvm::Type::getDoubleTy(*context), false);
246             llvm::Function *TheFunction = llvm::Function::Create(FT, llvm::Function::ExternalLinkage, "TheFunction", TheModule);
247             llvm::BasicBlock *BB = llvm::BasicBlock::Create(llvm::getGlobalContext(), "entry", TheFunction);
248             Builder->SetInsertPoint(BB);
249
250             (*itExp)->accept(*this);
251
252             if (1 || result_get() != NULL)
253             {
254                 Builder->CreateRet(result_get());
255                 TheFunction->dump();
256                 void* res = ee->getPointerToFunction(TheFunction);
257                 jitptr_t myJit = (jitptr_t) res;
258                 double result = myJit();
259                 std::cout << "coucou result : " << result << std::endl;
260             }
261         }
262     }
263
264     llvm::Value* const llvm_value_one = llvm::ConstantFP::get(llvm::getGlobalContext(), llvm::APFloat(1.0));
265     llvm::Value* llvm_rec_power (llvm::Value* x, llvm::Value* n)
266     {
267         llvm::ConstantFP* ncfp = llvm::dyn_cast<llvm::ConstantFP>(n);
268
269         if (ncfp->isZero())
270         {
271             // return 1
272             return llvm_value_one;
273         }
274         if (ncfp->isNegative())
275         {
276             llvm::Value* moduloN = Builder->CreateFMul(llvm::ConstantFP::get(llvm::getGlobalContext(), llvm::APFloat(-1.0)), n);
277             // return 1 / (x * llvm_rec_power(x, (-1 * n)-1))
278             return Builder->CreateFDiv(llvm_value_one, Builder->CreateFMul(x, llvm_rec_power(x, Builder->CreateFSub(moduloN, llvm_value_one, "OpExp::minus")), "OpExp::times"), "OpExp::rdivide");
279         }
280         else
281         {
282             // return x * llvm_rec_power(x, n-1)
283             return Builder->CreateFMul(x, llvm_rec_power(x, Builder->CreateFSub(n, llvm_value_one, "OpExp::minus")), "OpExp::times");
284         }
285     }
286     void visitprivate(const OpExp &e)
287     {
288         /*
289           switch (e.kind_get())
290           {
291           case OpExp::invalid_kind :
292           {
293           std::cout << "OpExp::invalid_kind" << std::endl;
294           break;
295           }
296           case OpExp::bool_kind :
297           {
298           std::cout << "OpExp::bool_kind" << std::endl;
299           break;
300           }
301           case OpExp::string_kind :
302           {
303           std::cout << "OpExp::string_kind" << std::endl;
304           break;
305           }
306           case OpExp::integer_kind :
307           {
308           std::cout << "OpExp::integer_kind" << std::endl;
309           break;
310           }
311           case OpExp::float_kind :
312           {
313           std::cout << "OpExp::float_kind" << std::endl;
314           break;
315           }
316           case OpExp::double_kind :
317           {
318           std::cout << "OpExp::double_kind" << std::endl;
319           break;
320           }
321           case OpExp::float_complex_kind :
322           {
323           break;
324           }
325           case OpExp::double_complex_kind :
326           {
327           break;
328           }
329           case OpExp::bool_matrix_kind :
330           {
331           break;
332           }
333           case OpExp::string_matrix_kind :
334           {
335           break;
336           }
337           case OpExp::integer_matrix_kind :
338           {
339           break;
340           }
341           case OpExp::float_matrix_kind :
342           {
343           break;
344           }
345           case OpExp::double_matrix_kind :
346           {
347           break;
348           }
349           case OpExp::float_complex_matrix_kind :
350           {
351           break;
352           }
353           case OpExp::double_complex_matrix_kind :
354           {
355           break;
356           }
357           case OpExp::matrix_kind :
358           {
359           break;
360           }
361           }
362         */
363
364         /*getting what to assign*/
365         e.left_get().accept(*this);
366         llvm::Value *pITL = result_get();
367
368         /*getting what to assign*/
369         e.right_get().accept(*this);
370         llvm::Value *pITR = result_get();
371
372         llvm::Value *pResult = NULL;
373         switch (e.oper_get())
374         {
375             case OpExp::plus :
376             {
377                 //%5 = call i32 @_Z17AddDoubleToDoublePN5types6DoubleES1_PS1_(%"class.types::Double"* %3, %"class.types::Double"* %4, %"class.types::Double"** %pdbl1)
378                 //                      pResult = Builder->CreateFAdd(pITL, pITR, "OpExp::plus");
379
380                 llvm::Value * tmp = Builder->CreateAlloca(llvm::PointerType::getUnqual(TheModule->getTypeByName("class.types::Double")));
381
382                 //printf("%p \n",TheModule->getFunction("_Z17AddDoubleToDoublePN5types6DoubleES1_PS1_"));
383
384                 Builder->CreateCall3(TheModule->getFunction("_Z17AddDoubleToDoublePN5types6DoubleES1_PS1_"), pITR, pITL, tmp);
385
386                 pResult = Builder->CreateLoad(tmp);
387                 break;
388             }
389             case OpExp::minus :
390             {
391                 pResult = Builder->CreateFSub(pITL, pITR, "OpExp::minus");
392                 break;
393             }
394             case OpExp::times :
395             {
396                 pResult = Builder->CreateFMul(pITL, pITR, "OpExp::times");
397                 break;
398             }
399             case OpExp::rdivide :
400             {
401                 pResult = Builder->CreateFDiv(pITL, pITR, "OpExp::rdivide");
402                 break;
403             }
404             case OpExp::ldivide :
405             {
406                 pResult = Builder->CreateFDiv(pITR, pITL, "OpExp::ldivide");
407                 break;
408             }
409             case OpExp::power :
410             {
411                 pResult = llvm_rec_power(pITL, pITR);
412                 break;
413             }
414             case OpExp::unaryMinus :
415             {
416                 pResult = Builder->CreateFSub(pITL, pITR, "OpExp::unaryMinus");
417                 break;
418             }
419             case OpExp::eq :
420             {
421                 pResult = Builder->CreateUIToFP(Builder->CreateFCmpUEQ(pITL, pITR, "OpExp::eq"), llvm::Type::getDoubleTy(llvm::getGlobalContext()), "booltodouble");
422                 break;
423             }
424             case OpExp::ne :
425             {
426                 pResult = Builder->CreateUIToFP(Builder->CreateNot(Builder->CreateFCmpUEQ(pITL, pITR, "OpExp::eq"), "not"), llvm::Type::getDoubleTy(llvm::getGlobalContext()), "booltodouble");
427                 break;
428             }
429             case OpExp::lt :
430             {
431                 pResult = Builder->CreateUIToFP(Builder->CreateFCmpULT(pITL, pITR, "OpExp::lt"), llvm::Type::getDoubleTy(llvm::getGlobalContext()), "booltodouble");
432                 break;
433             }
434             case OpExp::le :
435             {
436                 pResult = Builder->CreateUIToFP(Builder->CreateFCmpULE(pITL, pITR, "OpExp::le"), llvm::Type::getDoubleTy(llvm::getGlobalContext()), "booltodouble");
437                 break;
438             }
439             case OpExp::gt :
440             {
441                 pResult = Builder->CreateUIToFP(Builder->CreateFCmpUGT(pITL, pITR, "OpExp::gt"), llvm::Type::getDoubleTy(llvm::getGlobalContext()), "booltodouble");
442                 break;
443             }
444             case OpExp::ge :
445             {
446                 pResult = Builder->CreateUIToFP(Builder->CreateFCmpUGE(pITL, pITR, "OpExp::ge"), llvm::Type::getDoubleTy(llvm::getGlobalContext()), "booltodouble");
447                 break;
448             }
449             default:
450             {
451                 std::cout << "Operation not supported, returning 42..." << std::endl;
452                 pResult = llvm::ConstantFP::get(llvm::getGlobalContext(), llvm::APFloat(42.0));
453                 break;
454             }
455         }
456
457         if (pResult == NULL)
458         {
459             result_set(llvm::ConstantFP::get(llvm::getGlobalContext(), llvm::APFloat(42.0)));
460         }
461         result_set(pResult);
462     }
463
464     void visitprivate (const AssignExp &e)
465     {
466         /*getting what to assign*/
467
468         const SimpleVar *pVar = dynamic_cast<const SimpleVar*>(&e.left_exp_get());
469         if (pVar)
470         {
471             // x = ?
472             /*getting what to assign*/
473             e.right_exp_get().accept(*this);
474
475             llvm::Value *pITR = result_get();
476             //reset result
477             result_set(NULL);
478
479             //mod->getFunction("_ZN6symbol7Context3putERKNS_6SymbolERN5types12InternalTypeE");
480             llvm::Value * llvmScilabContext = llvm::ConstantInt::get(uintptrType, (uintptr_t)scilabContext);
481             llvmScilabContext = Builder->CreateIntToPtr(llvmScilabContext, llvm::PointerType::getUnqual(TheModule->getTypeByName("class.symbol::Context")));
482
483             llvm::Value * llvmSym = llvm::ConstantInt::get(uintptrType, (uintptr_t)&pVar->name_get());
484             llvmSym = Builder->CreateIntToPtr(llvmSym, llvm::PointerType::getUnqual(TheModule->getTypeByName("class.symbol::Symbol")));
485             llvmSym->dump();
486
487             Builder->CreateCall3(TheModule->getFunction("_ZN6symbol7Context3putERKNS_6SymbolERN5types12InternalTypeE"), llvmScilabContext, llvmSym, pITR);
488
489             //symbol::Context::getInstance()->put(pVar->name_get(), *pIT);
490             return;
491         }
492
493         llvm::Value *pResult = NULL;
494     }
495
496     void visitprivate (const SimpleVar &e)
497     {
498         if (e.is_verbose())
499         {
500             InternalType * pI = symbol::Context::getInstance()->get(e.name_get());
501             if (pI != NULL && pI->isCallable() == false && ConfigVariable::isPromptShow())
502             {
503                 std::wostringstream ostr;
504                 ostr << e.name_get().name_get() << L"  = " << L"(" << pI->getRef() << L")" << std::endl;
505                 ostr << std::endl;
506                 scilabWriteW(ostr.str().c_str());
507                 //std::cout <<
508                 //VariableToString(pI);
509             }
510             else
511             {
512                 wchar_t szError[bsiz];
513                 os_swprintf(szError, bsiz, _W("Undefined variable: %ls\n"), e.name_get().name_get().c_str());
514                 throw ScilabError(szError, 999, e.location_get());
515                 //Err, SimpleVar doesn't exist in Scilab scopes.
516             }
517         }
518         else // JIT
519         {
520             //mod->getFunction("_ZNK6symbol7Context3getERKNS_6SymbolE")
521             llvm::Value * llvmScilabContext = llvm::ConstantInt::get(uintptrType, (uintptr_t)scilabContext);
522             llvmScilabContext = Builder->CreateIntToPtr(llvmScilabContext, llvm::PointerType::getUnqual(TheModule->getTypeByName("class.symbol::Context")));
523
524             llvm::Value * llvmSym = llvm::ConstantInt::get(uintptrType, (uintptr_t)&e.name_get());
525             llvmSym = Builder->CreateIntToPtr(llvmSym, llvm::PointerType::getUnqual(TheModule->getTypeByName("class.symbol::Symbol")));
526
527             llvm::Value * result = Builder->CreateCall2(TheModule->getFunction("_ZNK6symbol7Context3getERKNS_6SymbolE"), llvmScilabContext, llvmSym);
528             result_set(result);
529         }
530     }
531
532     void visit (const BoolExp &e)
533     {
534         //            visitprivate(e);
535     }
536
537     void visit (const NilExp &e)
538     {
539         //            visitprivate(e);
540     }
541
542     void visit (const ColonVar &e)
543     {
544         //            visitprivate(e);
545     }
546
547     void visit (const DollarVar &e)
548     {
549         //            visitprivate(e);
550     }
551
552     void visit (const ArrayListVar &e)
553     {
554         //            visitprivate(e);
555     }
556
557     void visit (const FieldExp &e)
558     {
559         //            visitprivate(e);
560     }
561
562
563     void visit (const LogicalOpExp &e)
564     {
565         //            visitprivate(e);
566     }
567
568     void visit (const AssignExp &e)
569     {
570         visitprivate(e);
571     }
572
573     void visit (const CellCallExp &e)
574     {
575         //            visitprivate(e);
576     }
577
578     void visit (const CallExp &e)
579     {
580         //            visitprivate(e);
581     }
582
583     void visit (const IfExp &e)
584     {
585         //            visitprivate(e);
586     }
587
588     void visit (const TryCatchExp &e)
589     {
590         //            visitprivate(e);
591     }
592
593     void visit (const WhileExp &e)
594     {
595         //            visitprivate(e);
596     }
597
598     void visit (const ForExp &e)
599     {
600         //            visitprivate(e);
601     }
602
603     void visit (const BreakExp &e)
604     {
605         //            visitprivate(e);
606     }
607
608     void visit (const ContinueExp &e)
609     {
610         //            visitprivate(e);
611     }
612
613     void visit (const ReturnExp &e)
614     {
615         //            visitprivate(e);
616     }
617
618     void visit (const SelectExp &e)
619     {
620         //            visitprivate(e);
621     }
622
623     void visit (const CaseExp &e)
624     {
625         //            visitprivate(e);
626     }
627
628     void visit (const ArrayListExp &e)
629     {
630         //            visitprivate(e);
631     }
632
633     void visit (const AssignListExp &e)
634     {
635         //            visitprivate(e);
636     }
637
638     void visit (const NotExp &e)
639     {
640         //            visitprivate(e);
641     }
642
643     void visit (const TransposeExp &e)
644     {
645         //            visitprivate(e);
646     }
647
648     void visit (const VarDec &e)
649     {
650         //            visitprivate(e);
651     }
652
653     void visit (const FunctionDec &e)
654     {
655         //            visitprivate(e);
656     }
657
658     void visit(const ListExp &e)
659     {
660         //            visitprivate(e);
661     }
662     void visit (const MatrixExp &e)
663     {
664         //            visitprivate(e);
665     }
666
667     void visit (const MatrixLineExp &e)
668     {
669         //            visitprivate(e);
670     }
671
672     void visit (const CellExp &e)
673     {
674         //            visitprivate(e);
675     }
676
677     void visit (const StringExp &e)
678     {
679         //            visitprivate(e);
680     }
681
682     void visit (const CommentExp &e)
683     {
684         //            visitprivate(e);
685     }
686 };
687 }
688 #endif // !AST_JITVISITOR_HXX
689
690