2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2015 - Scilab Enterprises - Calixte DENIZET
5 * This file must be used under the terms of the CeCILL.
6 * This source file is licensed as described in the file COPYING, which
7 * you should have received as part of this distribution. The terms
8 * are also available at
9 * http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
15 #include "JITScalars.hxx"
16 #include "JITArrayofs.hxx"
17 #include "JITVisitor.hxx"
21 void JITVisitor::visit(const ast::VarDec & e)
26 void JITVisitor::visit(const ast::ForExp & e)
28 const ast::VarDec & vd = static_cast<const ast::VarDec &>(e.getVardec());
29 // TODO : handle for with an iterator
30 if (vd.getInit().isListExp())
32 const symbol::Symbol & symIterator = vd.getSymbol();
33 const ast::ListExp & le = static_cast<const ast::ListExp &>(vd.getInit());
35 if (le.getDecorator().getResult().getType().type != analysis::TIType::EMPTY)
37 llvm::Value * start = nullptr;
38 llvm::Value * step = nullptr;
39 llvm::Value * end = nullptr;
40 const ast::Exp & startE = le.getStart();
41 const ast::Exp & stepE = le.getStep();
42 const ast::Exp & endE = le.getEnd();
43 const analysis::TIType & startTy = startE.getDecorator().getResult().getType();
44 const analysis::TIType & stepTy = stepE.getDecorator().getResult().getType();
45 const analysis::TIType & endTy = endE.getDecorator().getResult().getType();
46 const bool startTyIsSigned = startTy.isintegral() && startTy.issigned();
47 const bool stepTyIsSigned = stepTy.isintegral() && stepTy.issigned();
48 const bool endTyIsSigned = endTy.isintegral() && endTy.issigned();
49 bool constantStart = false;
50 bool constantStep = false;
51 bool constantEnd = false;
53 bool integralStep = false;
54 bool integerIterator = false;
62 if (stepE.isDoubleExp())
66 const ast::DoubleExp & stepDE = static_cast<const ast::DoubleExp &>(stepE);
67 step_d = stepDE.getValue();
68 signStep = step_d > 0;
73 if (analysis::tools::asInteger(step_d, step_i))
80 // Step is not constant
81 // Check if step is zero or not
82 const analysis::TIType & ty = stepE.getDecorator().getResult().getType();
83 if (ty.isintegral() || ty.isreal())
86 step = getResult()->loadData(*this);
95 if (startE.isDoubleExp())
98 const ast::DoubleExp & startDE = static_cast<const ast::DoubleExp &>(startE);
99 start_d = startDE.getValue();
100 if (analysis::tools::asInteger(start_d, start_i))
102 integerIterator = integralStep;
105 start = getConstant(start_i);
106 step = getConstant(step_i);
111 start = getConstant(start_d);
114 step = getConstant(step_d);
120 startE.accept(*this);
121 start = getResult()->loadData(*this);
124 step = getConstant(step_d);
128 if (endE.isDoubleExp())
131 const ast::DoubleExp & endDE = static_cast<const ast::DoubleExp &>(endE);
132 end_d = endDE.getValue();
133 if (analysis::tools::asInteger(end_d, end_i))
135 end = getConstant(end_i);
139 end = getConstant(end_d);
145 end = getResult()->loadData(*this);
148 if (le.getDecorator().getResult().getRange().isValid())
150 integerIterator = true;
155 start = Cast::cast<int64_t>(start, startTyIsSigned, *this);
156 step = Cast::cast<int64_t>(step, stepTyIsSigned, *this);
157 end = Cast::cast<int64_t>(end, endTyIsSigned, *this);
158 llvm::Value * one = getConstant<int64_t>(1);
163 end = builder.CreateAdd(end, one);
167 end = builder.CreateSub(end, one);
173 start = Cast::cast<double>(start, startTyIsSigned, *this);
174 step = Cast::cast<double>(step, stepTyIsSigned, *this);
175 end = Cast::cast<double>(end, endTyIsSigned, *this);
178 // integers values: for i = start:step:end...
179 // is equivalent to for (int64_t i = start; i < end + 1; i += step)...
181 // flaoting values: for i = start:step:end...
182 // is equivalent to for (double i = start; i <= end; i += step)...
184 llvm::BasicBlock * cond = llvm::BasicBlock::Create(context, "for_cond", function);
185 llvm::BasicBlock * loop = llvm::BasicBlock::Create(context, "for_loop", function);
186 llvm::BasicBlock * after = llvm::BasicBlock::Create(context, "for_after", function);
188 // To know how to break or continue the loop
189 blocks.emplace(cond, after);
191 llvm::Value * sign_step = nullptr;
192 llvm::Value * zero_i64 = getConstant<int64_t>(0);
193 llvm::Value * zero_dbl = getConstant<double>(0);
194 llvm::Value * abs = llvm::Intrinsic::getDeclaration(&getModule(), llvm::Intrinsic::fabs, getTy<double>());
195 llvm::Value * abs_arg[1];
196 llvm::Value * cmp_i1 = nullptr;
200 llvm::Value * cmp_zero;
203 cmp_zero = builder.CreateICmpEQ(step, zero_i64);
207 cmp_zero = builder.CreateFCmpOEQ(step, zero_dbl);
209 llvm::BasicBlock * precond = llvm::BasicBlock::Create(context, "", function);
210 builder.CreateCondBr(cmp_zero, after, precond);
211 builder.SetInsertPoint(precond);
214 if (!integerIterator)
219 llvm::CallInst * abs_start = builder.CreateCall(abs, abs_arg);
220 abs_start->setTailCall(true);
221 cmp_i1 = builder.CreateFCmpUEQ(abs_start, getConstant<double>(std::numeric_limits<double>::infinity()));
222 llvm::BasicBlock * bb = llvm::BasicBlock::Create(context, "", function);
223 builder.CreateCondBr(cmp_i1, after, bb);
224 builder.SetInsertPoint(bb);
230 llvm::CallInst * abs_end = builder.CreateCall(abs, abs_arg);
231 abs_end->setTailCall(true);
232 cmp_i1 = builder.CreateFCmpUEQ(abs_end, getConstant<double>(std::numeric_limits<double>::infinity()));
233 llvm::BasicBlock * bb = llvm::BasicBlock::Create(context, "", function);
234 builder.CreateCondBr(cmp_i1, after, bb);
235 builder.SetInsertPoint(bb);
245 cmp_i1 = builder.CreateICmpSLT(start, end);
249 cmp_i1 = builder.CreateICmpSGT(start, end);
254 sign_step = builder.CreateICmpSGT(step, zero_i64);
255 llvm::Value * cmp1 = builder.CreateICmpSLT(start, end);
256 llvm::Value * cmp2 = builder.CreateICmpSGT(start, end);
257 cmp_i1 = builder.CreateSelect(sign_step, cmp1, cmp2);
266 cmp_i1 = builder.CreateFCmpOLE(start, end);
270 cmp_i1 = builder.CreateFCmpOGE(start, end);
276 llvm::CallInst * abs_step = builder.CreateCall(abs, abs_arg);
277 abs_step->setTailCall(true);
278 cmp_i1 = builder.CreateFCmpUEQ(abs_step, getConstant<double>(std::numeric_limits<double>::infinity()));
279 llvm::BasicBlock * bb = llvm::BasicBlock::Create(context, "", function);
280 builder.CreateCondBr(cmp_i1, after, bb);
281 builder.SetInsertPoint(bb);
282 sign_step = builder.CreateFCmpOGT(step, zero_dbl);
283 llvm::Value * cmp1 = builder.CreateFCmpOLE(start, end);
284 llvm::Value * cmp2 = builder.CreateFCmpOGE(start, end);
285 cmp_i1 = builder.CreateSelect(sign_step, cmp1, cmp2);
290 if (const analysis::LoopDecoration * ld = e.getDecorator().getLoopDecoration())
292 if (!ld->getClone().empty() || !ld->getPromotion().empty())
294 llvm::BasicBlock * pre = llvm::BasicBlock::Create(context, "for_pre", function);
295 builder.CreateCondBr(cmp_i1, pre, after);
296 builder.SetInsertPoint(pre);
297 if (!ld->getClone().empty())
305 builder.CreateBr(loop);
312 builder.CreateCondBr(cmp_i1, loop, after);
315 llvm::BasicBlock * cur_block = builder.GetInsertBlock();
317 builder.SetInsertPoint(loop);
321 i = builder.CreatePHI(getTy<int64_t>(), 2);
325 i = builder.CreatePHI(getTy<double>(), 2);
328 i->addIncoming(start, cur_block);
329 JITScilabPtr & it = variables.find(symIterator)->second;
330 it->storeData(*this, i);
332 // Visit the loop body
333 e.getBody().accept(*this);
335 builder.CreateBr(cond);
337 builder.SetInsertPoint(cond);
338 llvm::Value * i_step;
345 i_step = builder.CreateAdd(i, step);
346 cmp_i1 = builder.CreateICmpSLT(i_step, end);
350 i_step = builder.CreateSub(i, step);
351 cmp_i1 = builder.CreateICmpSGT(i_step, end);
356 i_step = builder.CreateAdd(i, step);
357 llvm::Value * cmp1 = builder.CreateICmpSLT(i_step, end);
358 llvm::Value * cmp2 = builder.CreateICmpSGT(i_step, end);
359 cmp_i1 = builder.CreateSelect(sign_step, cmp1, cmp2);
368 i_step = builder.CreateFAdd(i, step);
369 cmp_i1 = builder.CreateFCmpOLE(i_step, end);
373 i_step = builder.CreateFSub(i, step);
374 cmp_i1 = builder.CreateFCmpOGE(i_step, end);
379 i_step = builder.CreateFAdd(i, step);
380 llvm::Value * cmp1 = builder.CreateFCmpOLE(i_step, end);
381 llvm::Value * cmp2 = builder.CreateFCmpOGE(i_step, end);
382 cmp_i1 = builder.CreateSelect(sign_step, cmp1, cmp2);
386 i->addIncoming(i_step, cond);
388 builder.CreateCondBr(cmp_i1, loop, after);
390 builder.SetInsertPoint(after);
395 void JITVisitor::cloneSyms(const ast::Exp & e)
397 llvm::Type * types[] = { getTy<int8_t *>(), getTy<int8_t *>(), getTy<int64_t>(), getTy<int32_t>(), getTy<bool>() };
398 llvm::Value * __memcpy = llvm::Intrinsic::getDeclaration(module, llvm::Intrinsic::memcpy, types);
399 llvm::Function * __new = static_cast<llvm::Function *>(module->getOrInsertFunction("new", llvm::FunctionType::get(getTy<int8_t *>(), llvm::ArrayRef<llvm::Type *>(getTy<uint64_t>()), false)));
401 for (const auto & sym : e.getDecorator().getLoopDecoration()->getClone())
403 // TODO: bad stuff here: we must add the mangling to the name !!
404 JITScilabPtr & ptr = variables.find(sym)->second;
405 llvm::Value * x = ptr->loadData(*this);
406 llvm::Value * r = ptr->loadRows(*this);
407 llvm::Value * c = ptr->loadCols(*this);
408 llvm::Value * rc = builder.CreateMul(r, c);
409 llvm::Value * size = builder.CreateMul(rc, getConstant<int64_t>(getTySizeInBytes(x)));
410 llvm::CallInst * dest = builder.CreateCall(__new, size);
411 dest->addAttribute(0, llvm::Attribute::NoAlias);
412 llvm::Value * src = builder.CreateBitCast(x, getTy<int8_t *>());
413 llvm::Value * memcpy_args[] = { dest, src, size, getConstant<int64_t>(getTySizeInBytes(x)), getBool(false) };
414 builder.CreateCall(__memcpy, memcpy_args);
415 ptr->storeData(*this, dest);
418 /* if (const analysis::Clone * cl = e.getDecorator().getClone())
420 if (!cl->get().empty())
422 llvm::Type * types[] = { getTy<int8_t *>(), getTy<int8_t *>(), getTy<int64_t>(), getTy<int32_t>(), getTy<bool>() };
423 llvm::Value * __memcpy = llvm::Intrinsic::getDeclaration(module, llvm::Intrinsic::memcpy, types);
424 llvm::Function * __new = static_cast<llvm::Function *>(module->getOrInsertFunction("new", llvm::FunctionType::get(getTy<int8_t *>(), llvm::ArrayRef<llvm::Type *>(getTy<uint64_t>()), false)));
425 __new->addAttribute(0, llvm::Attribute::NoAlias);
427 for (const auto & sym : cl->get())
429 JITScilabPtr & ptr = variables.find(sym)->second;
430 llvm::Value * x = ptr->loadData(*this);
431 llvm::Value * r = ptr->loadRows(*this);
432 llvm::Value * c = ptr->loadCols(*this);
433 llvm::Value * rc = builder.CreateMul(r, c);
434 llvm::Value * size = builder.CreateMul(rc, getConstant<int64_t>(getTySizeInBytes(x)));
435 llvm::CallInst * dest = builder.CreateCall(__new, size);
436 dest->addAttribute(0, llvm::Attribute::NoAlias);
437 llvm::Value * src = builder.CreateBitCast(x, getTy<int8_t *>());
438 llvm::Value * memcpy_args[] = { dest, src, size, getConstant<int64_t>(getTySizeInBytes(x)), getBool(false) };
439 builder.CreateCall(__memcpy, memcpy_args);
440 ptr->storeData(*this, dest);