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>
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
14 #ifndef AST_JITVISITOR_HXX
15 #define AST_JITVISITOR_HXX
24 #include "visitor_common.hxx"
25 #include "shortcutvisitor.hxx"
26 #include "printvisitor.hxx"
27 #include "mutevisitor.hxx"
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"
37 //#include "matrix_transpose_int.hxx"
40 #include "doublecomplex.h"
41 #include "matrix_transpose.h"
42 #include "os_swprintf.h"
45 //#include "HandleManagement.h"
49 #include "localization.h"
51 #include "scilabWrite.hxx"
52 #include "context.hxx"
56 #include "alltypes.hxx"
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"
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"
80 #include <sys/types.h>
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>
97 #include "../src/cpp/llvm-wrapper-generated.cpp"
102 typedef double (*jitptr_t) ();
104 class JITVisitor : public ConstVisitor
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 llvm::Function * TheFunction;
121 // utilisees par step, end ds la visit de ListExp
122 llvm::Value * _result2;
123 llvm::Value * _result3;
125 void visit (const SeqExp &e)
130 void visit (const IntExp &e)
135 void visit (const FloatExp &e)
140 void visit (const DoubleExp &e)
145 void visit (const OpExp &e)
150 void visit (const SimpleVar &e)
157 JITVisitor() : ConstVisitor()
159 llvm::InitializeNativeTarget();
160 context = &llvm::getGlobalContext();
161 Builder = new llvm::IRBuilder<> (*context);
163 m_bSingleResult = false;
164 TheModule = new llvm::Module("scilab jit", *context);
167 llvm::EngineBuilder engine (TheModule);
168 llvm::TargetOptions options;
169 options.NoFramePointerElim = true;
170 engine.setTargetOptions(options);
171 engine.setEngineKind(llvm::EngineKind::JIT);
172 engine.setErrorStr(&err);
174 ee = engine.create();
177 fprintf(stderr, "Could not create ExecutionEngine: %s\n", err.c_str());
180 ee->DisableLazyCompilation(0);
181 ee->addModule(TheModule);
182 TheModule->setDataLayout(ee->getDataLayout()->getStringRepresentation());
183 pm = NULL; /* TODO : init */
185 uintptrType = TheModule->getPointerSize() == llvm::Module::Pointer32 ?
186 llvm::Type::getInt32Ty(*context) : llvm::Type::getInt64Ty(*context);
188 TheModule = llvm::makeLLVMModuleContents(TheModule);
191 for (llvm::Module::iterator cur = TheModule->begin(), end = TheModule->end(); cur != end; cur++)
193 void* ptr = dlsym(RTLD_DEFAULT, cur->getName().data());
194 //printf("%s ---> %p\n", cur->getName().data(), ptr);
197 ee->updateGlobalMapping(cur, ptr);
201 scilabContext = symbol::Context::getInstance();
204 void result_set(llvm::Value* const gtVal)
206 m_bSingleResult = true;
210 llvm::Value* result_get()
215 void visitprivate(const DoubleExp &e)
217 if (e.getBigDouble() == NULL)
219 Double *pdbl = new Double(e.value_get());
220 (const_cast<DoubleExp *>(&e))->setBigDouble(pdbl);
223 // llvm::Value* res = llvm::ConstantFP::get(llvm::getGlobalContext(), llvm::APFloat(e.getBigDouble()));
224 llvm::Value* res = llvm::ConstantInt::get(uintptrType, (uintptr_t)e.getBigDouble());
225 res = Builder->CreateIntToPtr(res, llvm::PointerType::getUnqual(TheModule->getTypeByName("class.types::Double")));
230 void visitprivate(const FloatExp &e)
234 void visitprivate(const IntExp &e)
238 void visitprivate(const SeqExp &e)
242 std::list<Exp *>::const_iterator itExp;
244 for (itExp = e.exps_get().begin (); itExp != e.exps_get().end (); ++itExp)
246 //reset default values
249 (*itExp)->accept(*this);
250 std::cout << "coucou" << std::endl;
251 result_get()->dump();
255 llvm::Value* const llvm_value_one = llvm::ConstantFP::get(llvm::getGlobalContext(), llvm::APFloat(1.0));
256 llvm::Value* llvm_rec_power (llvm::Value* x, llvm::Value* n)
258 llvm::ConstantFP* ncfp = llvm::dyn_cast<llvm::ConstantFP>(n);
263 return llvm_value_one;
265 if (ncfp->isNegative())
267 llvm::Value* moduloN = Builder->CreateFMul(llvm::ConstantFP::get(llvm::getGlobalContext(), llvm::APFloat(-1.0)), n);
268 // return 1 / (x * llvm_rec_power(x, (-1 * n)-1))
269 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");
273 // return x * llvm_rec_power(x, n-1)
274 return Builder->CreateFMul(x, llvm_rec_power(x, Builder->CreateFSub(n, llvm_value_one, "OpExp::minus")), "OpExp::times");
277 void visitprivate(const OpExp &e)
280 switch (e.kind_get())
282 case OpExp::invalid_kind :
284 std::cout << "OpExp::invalid_kind" << std::endl;
287 case OpExp::bool_kind :
289 std::cout << "OpExp::bool_kind" << std::endl;
292 case OpExp::string_kind :
294 std::cout << "OpExp::string_kind" << std::endl;
297 case OpExp::integer_kind :
299 std::cout << "OpExp::integer_kind" << std::endl;
302 case OpExp::float_kind :
304 std::cout << "OpExp::float_kind" << std::endl;
307 case OpExp::double_kind :
309 std::cout << "OpExp::double_kind" << std::endl;
312 case OpExp::float_complex_kind :
316 case OpExp::double_complex_kind :
320 case OpExp::bool_matrix_kind :
324 case OpExp::string_matrix_kind :
328 case OpExp::integer_matrix_kind :
332 case OpExp::float_matrix_kind :
336 case OpExp::double_matrix_kind :
340 case OpExp::float_complex_matrix_kind :
344 case OpExp::double_complex_matrix_kind :
348 case OpExp::matrix_kind :
355 /*getting what to assign*/
356 e.left_get().accept(*this);
357 llvm::Value *pITL = result_get();
359 /*getting what to assign*/
360 e.right_get().accept(*this);
361 llvm::Value *pITR = result_get();
363 llvm::Value *pResult = NULL;
365 llvm::Value * tmp = Builder->CreateAlloca(llvm::PointerType::getUnqual(TheModule->getTypeByName("class.types::Double")));
367 switch (e.oper_get())
372 Builder->CreateCall3(TheModule->getFunction("_Z17AddDoubleToDoublePN5types6DoubleES1_PS1_"), pITR, pITL, tmp);
379 Builder->CreateCall3(TheModule->getFunction("_Z23SubstractDoubleToDoublePN5types6DoubleES1_PS1_"), pITR, pITL, tmp);
386 Builder->CreateCall3(TheModule->getFunction("_Z22MultiplyDoubleByDoublePN5types6DoubleES1_PS1_"), pITR, pITL, tmp);
390 case OpExp::rdivide :
392 pResult = Builder->CreateFDiv(pITL, pITR, "OpExp::rdivide");
395 case OpExp::ldivide :
397 pResult = Builder->CreateFDiv(pITR, pITL, "OpExp::ldivide");
402 pResult = llvm_rec_power(pITL, pITR);
405 case OpExp::unaryMinus :
407 pResult = Builder->CreateFSub(pITL, pITR, "OpExp::unaryMinus");
412 pResult = Builder->CreateUIToFP(Builder->CreateFCmpUEQ(pITL, pITR, "OpExp::eq"), llvm::Type::getDoubleTy(llvm::getGlobalContext()), "booltodouble");
417 pResult = Builder->CreateUIToFP(Builder->CreateNot(Builder->CreateFCmpUEQ(pITL, pITR, "OpExp::eq"), "not"), llvm::Type::getDoubleTy(llvm::getGlobalContext()), "booltodouble");
422 pResult = Builder->CreateUIToFP(Builder->CreateFCmpULT(pITL, pITR, "OpExp::lt"), llvm::Type::getDoubleTy(llvm::getGlobalContext()), "booltodouble");
427 pResult = Builder->CreateUIToFP(Builder->CreateFCmpULE(pITL, pITR, "OpExp::le"), llvm::Type::getDoubleTy(llvm::getGlobalContext()), "booltodouble");
432 pResult = Builder->CreateUIToFP(Builder->CreateFCmpUGT(pITL, pITR, "OpExp::gt"), llvm::Type::getDoubleTy(llvm::getGlobalContext()), "booltodouble");
437 pResult = Builder->CreateUIToFP(Builder->CreateFCmpUGE(pITL, pITR, "OpExp::ge"), llvm::Type::getDoubleTy(llvm::getGlobalContext()), "booltodouble");
442 std::cout << "Operation not supported, returning 42..." << std::endl;
443 pResult = llvm::ConstantFP::get(llvm::getGlobalContext(), llvm::APFloat(42.0));
447 pResult = Builder->CreateLoad(tmp);
451 result_set(llvm::ConstantFP::get(llvm::getGlobalContext(), llvm::APFloat(42.0)));
456 void visitprivate (const AssignExp &e)
458 /*getting what to assign*/
460 const SimpleVar *pVar = dynamic_cast<const SimpleVar*>(&e.left_exp_get());
464 /*getting what to assign*/
465 e.right_exp_get().accept(*this);
467 llvm::Value *pITR = result_get();
471 genLLVMPutSymbol(&pVar->name_get(), pITR);
473 //symbol::Context::getInstance()->put(pVar->name_get(), *pIT);
477 llvm::Value *pResult = NULL;
480 void visitprivate (const SimpleVar &e)
484 InternalType * pI = symbol::Context::getInstance()->get(e.name_get());
485 if (pI != NULL && pI->isCallable() == false && ConfigVariable::isPromptShow())
487 std::wostringstream ostr;
488 ostr << e.name_get().name_get() << L" = " << L"(" << pI->getRef() << L")" << std::endl;
490 scilabWriteW(ostr.str().c_str());
495 wchar_t szError[bsiz];
496 os_swprintf(szError, bsiz, _W("Undefined variable: %ls\n"), e.name_get().name_get().c_str());
497 throw ScilabError(szError, 999, e.location_get());
498 //Err, SimpleVar doesn't exist in Scilab scopes.
503 //mod->getFunction("_ZNK6symbol7Context3getERKNS_6SymbolE")
504 llvm::Value * llvmScilabContext = llvm::ConstantInt::get(uintptrType, (uintptr_t)scilabContext);
505 llvmScilabContext = Builder->CreateIntToPtr(llvmScilabContext, llvm::PointerType::getUnqual(TheModule->getTypeByName("class.symbol::Context")));
507 llvm::Value * llvmSym = llvm::ConstantInt::get(uintptrType, (uintptr_t)&e.name_get());
508 llvmSym = Builder->CreateIntToPtr(llvmSym, llvm::PointerType::getUnqual(TheModule->getTypeByName("class.symbol::Symbol")));
510 llvm::Value * result = Builder->CreateCall2(TheModule->getFunction("_ZNK6symbol7Context3getERKNS_6SymbolE"), llvmScilabContext, llvmSym);
515 void visitprivate(const ForExp &e)
517 e.vardec_get().accept(*this);
518 symbol::Symbol& varName = e.vardec_get().name_get();
520 llvm::BasicBlock * BBTest = llvm::BasicBlock::Create(llvm::getGlobalContext(), "for_test", TheFunction);
521 llvm::BasicBlock * BBBody = llvm::BasicBlock::Create(llvm::getGlobalContext(), "for_body", TheFunction);
522 llvm::BasicBlock * BBAfter = llvm::BasicBlock::Create(llvm::getGlobalContext(), "for_after", TheFunction);
524 llvm::Value* cur = Builder->CreateAlloca(llvm::PointerType::getUnqual(TheModule->getTypeByName("class.types::Double")));
525 llvm::Value* tmp = Builder->CreateAlloca(llvm::PointerType::getUnqual(TheModule->getTypeByName("class.types::Bool")));
526 llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::getInt32Ty(*context), 0);
528 llvm::Value* start = _result;
529 llvm::Value* step = _result2;
530 llvm::Value* end = _result3;
532 Builder->CreateStore(start, cur);
533 Builder->CreateBr(BBTest);
535 Builder->SetInsertPoint(BBTest);
536 Builder->CreateCall3(TheModule->getFunction("_Z16DoubleLessDoublePN5types6DoubleES1_PPNS_4BoolE"), end, Builder->CreateLoad(cur), tmp);
537 tmp = Builder->CreateLoad(tmp);
538 tmp = Builder->CreateCall2(TheModule->getFunction("_ZN5types7ArrayOfIiE3getEi"), tmp, zero);
539 Builder->CreateCondBr(tmp, BBAfter, BBBody);
542 Builder->SetInsertPoint(BBBody);
543 genLLVMPutSymbol(&varName, Builder->CreateLoad(cur));
544 e.body_get().accept(*this);
545 Builder->CreateCall3(TheModule->getFunction("_Z17AddDoubleToDoublePN5types6DoubleES1_PS1_"), Builder->CreateLoad(cur), step, cur);
546 Builder->CreateBr(BBTest);
548 Builder->SetInsertPoint(BBAfter);
551 void visitprivate(const ListExp &e)
553 e.start_get().accept(*this);
554 llvm::Value * start = result_get();
556 e.step_get().accept(*this);
557 llvm::Value * step = result_get();
559 e.end_get().accept(*this);
560 llvm::Value * end = result_get();
567 void visitprivate(const VarDec &e)
569 e.init_get().accept(*this);
572 void visit (const BoolExp &e)
577 void visit (const NilExp &e)
582 void visit (const ColonVar &e)
587 void visit (const DollarVar &e)
592 void visit (const ArrayListVar &e)
597 void visit (const FieldExp &e)
603 void visit (const LogicalOpExp &e)
608 void visit (const AssignExp &e)
613 void visit (const CellCallExp &e)
618 void visit (const CallExp &e)
623 void visit (const IfExp &e)
628 void visit (const TryCatchExp &e)
633 void visit (const WhileExp &e)
638 void visit (const ForExp &e)
643 void visit (const BreakExp &e)
648 void visit (const ContinueExp &e)
653 void visit (const ReturnExp &e)
658 void visit (const SelectExp &e)
663 void visit (const CaseExp &e)
668 void visit (const ArrayListExp &e)
673 void visit (const AssignListExp &e)
678 void visit (const NotExp &e)
683 void visit (const TransposeExp &e)
688 void visit (const VarDec &e)
693 void visit (const FunctionDec &e)
698 void visit(const ListExp &e)
702 void visit (const MatrixExp &e)
707 void visit (const MatrixLineExp &e)
712 void visit (const CellExp &e)
717 void visit (const StringExp &e)
722 void visit (const CommentExp &e)
727 void genLLVMInitialize()
729 llvm::FunctionType *FT = llvm::FunctionType::get(llvm::Type::getVoidTy(*context), false);
730 TheFunction = llvm::Function::Create(FT, llvm::Function::ExternalLinkage, "TheFunction", TheModule);
731 llvm::BasicBlock *BB = llvm::BasicBlock::Create(llvm::getGlobalContext(), "entry", TheFunction);
732 Builder->SetInsertPoint(BB);
735 void genLLVMFinalize()
737 Builder->CreateRetVoid();
741 void compileAndExec()
743 void* res = ee->getPointerToFunction(TheFunction);
744 jitptr_t myJit = (jitptr_t) res;
748 void genLLVMPutSymbol(const symbol::Symbol * s, llvm::Value * v)
750 llvm::Value * llvmScilabContext = llvm::ConstantInt::get(uintptrType, (uintptr_t)scilabContext);
751 llvmScilabContext = Builder->CreateIntToPtr(llvmScilabContext, llvm::PointerType::getUnqual(TheModule->getTypeByName("class.symbol::Context")));
753 llvm::Value * llvmSym = llvm::ConstantInt::get(uintptrType, (uintptr_t)s);
754 llvmSym = Builder->CreateIntToPtr(llvmSym, llvm::PointerType::getUnqual(TheModule->getTypeByName("class.symbol::Symbol")));
757 Builder->CreateCall3(TheModule->getFunction("_ZN6symbol7Context3putERKNS_6SymbolERN5types12InternalTypeE"), llvmScilabContext, llvmSym, v);
760 static void printScilabVar(types::InternalType * pIT)
762 std::wostringstream ostr;
764 //to manage lines information
765 int iLines = ConfigVariable::getConsoleLines();
767 bool bFinish = false;
771 bFinish = pIT->toString(ostr);
772 scilabWriteW(ostr.str().c_str());
773 if (bFinish == false && iLines != 0)
775 //show message on prompt
776 bFinish = linesmore() == 1;
780 while (bFinish == false);
782 pIT->clearPrintState();
787 #endif // !AST_JITVISITOR_HXX