JIT visitor moved in the jit module
[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 #include "llvm/IR/DerivedTypes.h"
61 #include "llvm/IR/IRBuilder.h"
62 #include "llvm/IR/LLVMContext.h"
63 #include "llvm/IR/Module.h"
64
65 #include "llvm/Analysis/Verifier.h"
66 #include "llvm/Support/TargetSelect.h"
67 #include "llvm/ExecutionEngine/ExecutionEngine.h"
68 #include "llvm/ExecutionEngine/JIT.h"
69 #include "llvm/PassManager.h"
70 #include "llvm/IR/DataLayout.h"
71 #include "vmkit_core.h"
72
73 namespace ast
74 {
75         typedef double (*jitptr_t) ();
76
77         class JITVisitor : public ConstVisitor
78         {
79         private:
80                 /*
81                  * Attributes
82                  */
83                 llvm::Value* _result;
84                 bool m_bSingleResult;
85                 llvm::LLVMContext *context;
86                 llvm::Module *TheModule;
87                 llvm::IRBuilder<> *Builder;
88                 llvm::ExecutionEngine* ee;
89                 llvm::FunctionPassManager* pm;
90
91
92         void visit (const SeqExp  &e)
93         {
94             visitprivate(e);
95         }
96
97         void visit (const IntExp &e)
98         {
99             visitprivate(e);
100         }
101
102         void visit (const FloatExp &e)
103         {
104             visitprivate(e);
105         }
106
107         void visit (const DoubleExp &e)
108         {
109             visitprivate(e);
110         }
111
112         void visit (const OpExp &e)
113         {
114             visitprivate(e);
115         }
116
117         void visit (const SimpleVar &e)
118         {
119             visitprivate(e);
120         }
121
122
123         public:
124         JITVisitor() : ConstVisitor() {
125                 llvm::InitializeNativeTarget();
126                 context = &llvm::getGlobalContext();
127                 Builder = new llvm::IRBuilder<> (*context);
128                 _result = NULL;
129                 m_bSingleResult = false;
130                 TheModule = new llvm::Module("scilab jit", *context);
131
132                 std::string err;
133                 llvm::EngineBuilder engine (TheModule);
134                 llvm::TargetOptions options;
135                 options.NoFramePointerElim = true;
136                 engine.setTargetOptions(options);
137                 engine.setEngineKind(llvm::EngineKind::JIT);
138                 engine.setErrorStr(&err);
139
140                 ee = engine.create();
141                 if (!ee) {
142                         fprintf(stderr, "Could not create ExecutionEngine: %s\n", err.c_str());
143                         exit(1);
144                 }
145                 ee->DisableLazyCompilation(0);
146                 ee->addModule(TheModule);
147                 TheModule->setDataLayout(ee->getDataLayout()->getStringRepresentation());
148                 pm = NULL; /* TODO : init */
149         }
150
151         void result_set(llvm::Value* const gtVal)
152         {
153             m_bSingleResult = true;
154             _result = gtVal;
155         }
156
157         llvm::Value* result_get()
158         {
159                 return  _result;
160         }
161
162         void visitprivate(const DoubleExp &e) {
163                 if (e.getBigDouble() == NULL)
164                 {
165                         Double *pdbl = new Double(e.value_get());
166                         (const_cast<DoubleExp *>(&e))->setBigDouble(pdbl);
167                 }
168                 llvm::Value* res = llvm::ConstantFP::get(llvm::getGlobalContext(), llvm::APFloat(e.getBigDouble()->get(0)));
169                 result_set(res);
170                 _result->dump();
171         }
172
173         void visitprivate(const FloatExp &e) {
174         }
175
176         void visitprivate(const IntExp &e) {
177         }
178
179         void visitprivate(const SeqExp &e) {
180
181             //T execMe;
182             std::list<Exp *>::const_iterator    itExp;
183
184             for (itExp = e.exps_get().begin (); itExp != e.exps_get().end (); ++itExp)
185             {
186                 //reset default values
187                 result_set(NULL);
188                 llvm::FunctionType *FT = llvm::FunctionType::get(llvm::Type::getDoubleTy(*context), false);
189                 llvm::Function *TheFunction = llvm::Function::Create(FT, llvm::Function::ExternalLinkage, "TheFunction", TheModule);
190                 llvm::BasicBlock *BB = llvm::BasicBlock::Create(llvm::getGlobalContext(), "entry", TheFunction);
191                 Builder->SetInsertPoint(BB);
192
193                 (*itExp)->accept(*this);
194
195
196                 if (result_get() != NULL)
197                 {
198                         Builder->CreateRet(result_get());
199                         TheFunction->dump();
200                         void* res = ee->getPointerToFunction(TheFunction);
201                         jitptr_t myJit = (jitptr_t) res;
202                         double result = myJit();
203                         std::cout << "result : " << result << std::endl;
204                 }
205             }
206         }
207
208                 llvm::Value* const llvm_value_one = llvm::ConstantFP::get(llvm::getGlobalContext(),llvm::APFloat(1.0));
209                 llvm::Value* llvm_rec_power (llvm::Value* x, llvm::Value* n)
210                 {
211                         llvm::ConstantFP* ncfp = llvm::dyn_cast<llvm::ConstantFP>(n);
212
213                         if (ncfp->isZero())
214                         {
215                                 // return 1
216                                 return llvm_value_one;
217                         }
218                         if (ncfp->isNegative()){
219                                 llvm::Value* moduloN = Builder->CreateFMul(llvm::ConstantFP::get(llvm::getGlobalContext(),llvm::APFloat(-1.0)), n);
220                                 // return 1 / (x * llvm_rec_power(x, (-1 * n)-1))
221                                 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");
222                         } else {
223                                 // return x * llvm_rec_power(x, n-1)
224                                 return Builder->CreateFMul(x, llvm_rec_power(x,Builder->CreateFSub(n, llvm_value_one, "OpExp::minus")), "OpExp::times");
225                         }
226                 }
227         void visitprivate(const OpExp &e) {
228                 /*
229             switch (e.kind_get())
230             {
231                 case OpExp::invalid_kind :
232                 {
233                         std::cout << "OpExp::invalid_kind" << std::endl;
234                         break;
235                 }
236                 case OpExp::bool_kind :
237                 {
238                         std::cout << "OpExp::bool_kind" << std::endl;
239                         break;
240                 }
241                 case OpExp::string_kind :
242                 {
243                         std::cout << "OpExp::string_kind" << std::endl;
244                         break;
245                 }
246                 case OpExp::integer_kind :
247                 {
248                         std::cout << "OpExp::integer_kind" << std::endl;
249                         break;
250                 }
251                 case OpExp::float_kind :
252                 {
253                         std::cout << "OpExp::float_kind" << std::endl;
254                         break;
255                 }
256                 case OpExp::double_kind :
257                 {
258                         std::cout << "OpExp::double_kind" << std::endl;
259                         break;
260                 }
261                 case OpExp::float_complex_kind :
262                 {
263                         break;
264                 }
265                 case OpExp::double_complex_kind :
266                 {
267                         break;
268                 }
269                 case OpExp::bool_matrix_kind :
270                 {
271                         break;
272                 }
273                 case OpExp::string_matrix_kind :
274                 {
275                         break;
276                 }
277                 case OpExp::integer_matrix_kind :
278                 {
279                         break;
280                 }
281                 case OpExp::float_matrix_kind :
282                 {
283                         break;
284                 }
285                 case OpExp::double_matrix_kind :
286                 {
287                         break;
288                 }
289                 case OpExp::float_complex_matrix_kind :
290                 {
291                         break;
292                 }
293                 case OpExp::double_complex_matrix_kind :
294                 {
295                         break;
296                 }
297                 case OpExp::matrix_kind :
298                 {
299                         break;
300                 }
301             }
302                  */
303
304                 /*getting what to assign*/
305                 e.left_get().accept(*this);
306                 llvm::Value *pITL = result_get();
307
308             /*getting what to assign*/
309             e.right_get().accept(*this);
310             llvm::Value *pITR = result_get();
311
312             llvm::Value *pResult = NULL;
313             switch (e.oper_get())
314             {
315                 case OpExp::plus :
316                 {
317                         pResult = Builder->CreateFAdd(pITL, pITR, "OpExp::plus");
318                         break;
319                 }
320                 case OpExp::minus :
321                 {
322                         pResult = Builder->CreateFSub(pITL, pITR, "OpExp::minus");
323                         break;
324                 }
325                 case OpExp::times :
326                 {
327                         pResult = Builder->CreateFMul(pITL, pITR, "OpExp::times");
328                         break;
329                 }
330                 case OpExp::rdivide :
331                 {
332                         pResult = Builder->CreateFDiv(pITL, pITR, "OpExp::rdivide");
333                         break;
334                 }
335                 case OpExp::ldivide :
336                 {
337                         pResult = Builder->CreateFDiv(pITR, pITL, "OpExp::ldivide");
338                         break;
339                 }
340                 case OpExp::power :
341                 {
342                         pResult = llvm_rec_power(pITL, pITR);
343                         break;
344                 }
345                 case OpExp::unaryMinus :
346                 {
347                         pResult = Builder->CreateFSub(pITL, pITR, "OpExp::unaryMinus");
348                         break;
349                 }
350                 case OpExp::eq :
351                 {
352                         pResult = Builder->CreateUIToFP(Builder->CreateFCmpUEQ(pITL, pITR, "OpExp::eq"), llvm::Type::getDoubleTy(llvm::getGlobalContext()), "booltodouble");
353                         break;
354                 }
355                 case OpExp::ne :
356                 {
357                         pResult = Builder->CreateUIToFP(Builder->CreateNot(Builder->CreateFCmpUEQ(pITL, pITR, "OpExp::eq"),"not"), llvm::Type::getDoubleTy(llvm::getGlobalContext()), "booltodouble");
358                         break;
359                 }
360                 case OpExp::lt :
361                 {
362                         pResult = Builder->CreateUIToFP(Builder->CreateFCmpULT(pITL, pITR, "OpExp::lt"), llvm::Type::getDoubleTy(llvm::getGlobalContext()), "booltodouble");
363                         break;
364                 }
365                 case OpExp::le :
366                 {
367                         pResult = Builder->CreateUIToFP(Builder->CreateFCmpULE(pITL, pITR, "OpExp::le"), llvm::Type::getDoubleTy(llvm::getGlobalContext()), "booltodouble");
368                         break;
369                 }
370                 case OpExp::gt :
371                 {
372                         pResult = Builder->CreateUIToFP(Builder->CreateFCmpUGT(pITL, pITR, "OpExp::gt"), llvm::Type::getDoubleTy(llvm::getGlobalContext()), "booltodouble");
373                         break;
374                 }
375                 case OpExp::ge :
376                 {
377                         pResult = Builder->CreateUIToFP(Builder->CreateFCmpUGE(pITL, pITR, "OpExp::ge"), llvm::Type::getDoubleTy(llvm::getGlobalContext()), "booltodouble");
378                         break;
379                 }
380                 default:
381                 {
382                         std::cout << "Operation not supported, returning 42..." << std::endl;
383                         pResult = llvm::ConstantFP::get(llvm::getGlobalContext(),llvm::APFloat(42.0));
384                         break;
385                 }
386             }
387
388             if(pResult == NULL) {
389                 result_set(llvm::ConstantFP::get(llvm::getGlobalContext(), llvm::APFloat(42.0)));
390             }
391             result_set(pResult);
392         }
393
394         void visitprivate (const SimpleVar &e)
395         {
396               /* Not implemented. It only exits Scilab... */
397               std::cout << "VISIT SIMPLEVAR, EXITING NOW..." << std::endl;
398               ConfigVariable::setExitStatus(0);
399               ConfigVariable::setForceQuit(true);
400         }
401
402         void visit (const BoolExp &e)
403         {
404 //            visitprivate(e);
405         }
406
407         void visit (const NilExp &e)
408         {
409 //            visitprivate(e);
410         }
411
412         void visit (const ColonVar &e)
413         {
414 //            visitprivate(e);
415         }
416
417         void visit (const DollarVar &e)
418         {
419 //            visitprivate(e);
420         }
421
422         void visit (const ArrayListVar &e)
423         {
424 //            visitprivate(e);
425         }
426
427         void visit (const FieldExp &e)
428         {
429 //            visitprivate(e);
430         }
431
432
433         void visit (const LogicalOpExp &e)
434         {
435 //            visitprivate(e);
436         }
437
438         void visit (const AssignExp &e)
439         {
440 //            visitprivate(e);
441         }
442
443         void visit (const CellCallExp &e)
444         {
445 //            visitprivate(e);
446         }
447
448         void visit (const CallExp &e)
449         {
450 //            visitprivate(e);
451         }
452
453         void visit (const IfExp &e)
454         {
455 //            visitprivate(e);
456         }
457
458         void visit (const TryCatchExp &e)
459         {
460 //            visitprivate(e);
461         }
462
463         void visit (const WhileExp &e)
464         {
465 //            visitprivate(e);
466         }
467
468         void visit (const ForExp &e)
469         {
470 //            visitprivate(e);
471         }
472
473         void visit (const BreakExp &e)
474         {
475 //            visitprivate(e);
476         }
477
478         void visit (const ContinueExp &e)
479         {
480 //            visitprivate(e);
481         }
482
483         void visit (const ReturnExp &e)
484         {
485 //            visitprivate(e);
486         }
487
488         void visit (const SelectExp &e)
489         {
490 //            visitprivate(e);
491         }
492
493         void visit (const CaseExp &e)
494         {
495 //            visitprivate(e);
496         }
497
498         void visit (const ArrayListExp &e)
499         {
500 //            visitprivate(e);
501         }
502
503         void visit (const AssignListExp &e)
504         {
505 //            visitprivate(e);
506         }
507
508         void visit (const NotExp &e)
509         {
510 //            visitprivate(e);
511         }
512
513         void visit (const TransposeExp &e)
514         {
515 //            visitprivate(e);
516         }
517
518         void visit (const VarDec &e)
519         {
520 //            visitprivate(e);
521         }
522
523         void visit (const FunctionDec &e)
524         {
525 //            visitprivate(e);
526         }
527
528         void visit(const ListExp &e)
529         {
530 //            visitprivate(e);
531         }
532         void visit (const MatrixExp &e)
533         {
534 //            visitprivate(e);
535         }
536
537         void visit (const MatrixLineExp &e)
538         {
539 //            visitprivate(e);
540         }
541
542         void visit (const CellExp &e)
543         {
544 //            visitprivate(e);
545         }
546
547         void visit (const StringExp &e)
548         {
549 //            visitprivate(e);
550         }
551
552         void visit (const CommentExp &e)
553         {
554 //            visitprivate(e);
555         }
556         };
557 }
558 #endif // !AST_JITVISITOR_HXX
559