26 #define __STDC_LIMIT_MACROS
27 #define __STDC_CONSTANT_MACROS
37 #ifdef HAVE_LLVM_IR_VERIFIER_H
38 #include <llvm/IR/Verifier.h>
40 #include <llvm/Analysis/Verifier.h>
43 #include <llvm/ExecutionEngine/ExecutionEngine.h>
45 #ifdef HAVE_LLVM_IR_FUNCTION_H
46 #include <llvm/IR/GlobalVariable.h>
47 #include <llvm/IR/LLVMContext.h>
48 #include <llvm/IR/Function.h>
49 #include <llvm/IR/Instructions.h>
50 #include <llvm/IR/Intrinsics.h>
52 #include <llvm/GlobalVariable.h>
53 #include <llvm/LLVMContext.h>
54 #include <llvm/Function.h>
55 #include <llvm/Instructions.h>
56 #include <llvm/Intrinsics.h>
59 #ifdef HAVE_LLVM_SUPPORT_IRBUILDER_H
60 #include <llvm/Support/IRBuilder.h>
61 #elif defined(HAVE_LLVM_IR_IRBUILDER_H)
62 #include <llvm/IR/IRBuilder.h>
64 #include <llvm/IRBuilder.h>
67 #include <llvm/Support/raw_os_ostream.h>
76 static llvm::LLVMContext&
context = llvm::getGlobalContext ();
84 return os << atype->
name ();
222 catch (
const octave_execution_exception&)
235 catch (
const octave_execution_exception&)
249 catch (
const octave_execution_exception&)
260 if (array->
nelem () < index)
264 data[index - 1] = value;
290 return ret.
xelem (0);
292 catch (
const octave_execution_exception&)
311 temp.
xelem(0) = value;
312 mat->
array->assign (idx, temp);
315 catch (
const octave_execution_exception&)
343 std::swap (
final, start);
346 if (start >= 0 && final < mat->slice_len)
352 std::fill (data + start, data + start + nelem, value);
365 avalue.
xelem (0) = value;
366 array->
assign (idx, avalue);
381 else if (ndim > count)
383 if (idx == count - 1)
410 if (lhs.imag () == 0 && rhs.imag() == 0)
411 return Complex (lhs.real () * rhs.real (), 0);
439 if (lhs < 0.0 && !
xisint (rhs))
447 if (lhs.imag () == 0 && rhs.imag () == 0)
455 if (lhs.imag () == 0)
463 if (rhs.imag () == 0)
471 std::cout << *m << std::endl;
477 error (
"incorrect type information given to the JIT compiler");
486 for (
size_t i = 0; i < nargin; ++i)
524 return os <<
"Range[" << rng.
base <<
", " << rng.
limit <<
", " << rng.
inc
525 <<
", " << rng.
nelem <<
"]";
540 llvm::Type *allvm_type,
bool askip_paren,
int aid) :
541 mname (aname),
mparent (aparent), llvm_type (allvm_type),
mid (aid),
542 mdepth (aparent ? aparent->mdepth + 1 : 0), mskip_paren (askip_paren)
567 const llvm::Twine& aname,
jit_type *aresult,
568 const std::vector<jit_type *>& aargs)
569 : module (amodule), mresult (aresult), args (aargs), call_conv (acall_conv),
572 llvm::SmallVector<llvm::Type *, 15> llvm_args;
574 llvm::Type *rtype = llvm::Type::getVoidTy (
context);
580 llvm_args.push_back (rtype->getPointerTo ());
581 rtype = llvm::Type::getVoidTy (
context);
585 for (std::vector<jit_type *>::const_iterator iter =
args.begin ();
586 iter !=
args.end (); ++iter)
592 argty = argty->getPointerTo ();
594 llvm_args.push_back (argty);
599 llvm::FunctionType *ft = llvm::FunctionType::get (rtype, llvm_args,
false);
600 llvm_function = llvm::Function::Create (ft, llvm::Function::ExternalLinkage,
605 #ifdef FUNCTION_ADDATTRIBUTE_ARG_IS_ATTRIBUTES
606 llvm::AttrBuilder attr_builder;
607 attr_builder.addAttribute (llvm::Attributes::StructRet);
608 llvm::Attributes attrs = llvm::Attributes::get(
context, attr_builder);
616 #ifdef FUNCTION_ADDFNATTR_ARG_IS_ATTRIBUTES
624 const std::vector<jit_type *>& aargs)
625 : module (fn.module), llvm_function (fn.llvm_function), mresult (aresult),
626 args (aargs), call_conv (fn.call_conv), mcan_error (fn.mcan_error)
631 : module (fn.module), llvm_function (fn.llvm_function), mresult (fn.mresult),
632 args (fn.args), call_conv (fn.call_conv), mcan_error (fn.mcan_error)
653 llvm::BasicBlock *insert_before)
661 const std::vector<jit_value *>& in_args)
const
666 assert (in_args.size () ==
args.size ());
667 std::vector<llvm::Value *> llvm_args (
args.size ());
668 for (
size_t i = 0; i < in_args.size (); ++i)
669 llvm_args[i] = in_args[i]->
to_llvm ();
671 return call (builder, llvm_args);
676 const std::vector<llvm::Value *>& in_args)
const
681 assert (in_args.size () ==
args.size ());
682 llvm::SmallVector<llvm::Value *, 10> llvm_args;
683 llvm_args.reserve (in_args.size () +
sret ());
685 llvm::BasicBlock *insert_block = builder.GetInsertBlock ();
686 llvm::Function *
parent = insert_block->getParent ();
690 llvm::BasicBlock& prelude = parent->getEntryBlock ();
693 llvm::AllocaInst *sret_mem = 0;
697 llvm_args.push_back (sret_mem);
700 for (
size_t i = 0; i < in_args.size (); ++i)
702 llvm::Value *
arg = in_args[i];
710 llvm::Value *alloca = pre_builder.CreateAlloca (ty);
711 builder.CreateStore (arg, alloca);
715 llvm_args.push_back (arg);
718 llvm::CallInst *callinst = builder.CreateCall (
llvm_function, llvm_args);
719 llvm::Value *ret = callinst;
723 #ifdef CALLINST_ADDATTRIBUTE_ARG_IS_ATTRIBUTES
724 llvm::AttrBuilder attr_builder;
725 attr_builder.addAttribute(llvm::Attributes::StructRet);
726 llvm::Attributes attrs = llvm::Attributes::get(
context, attr_builder);
727 callinst->addAttribute (1, attrs);
729 callinst->addAttribute (1, llvm::Attribute::StructRet);
731 ret = builder.CreateLoad (sret_mem);
738 ret = unpack (builder, ret);
747 assert (idx <
args.size ());
752 llvm::Function::arg_iterator iter =
llvm_function->arg_begin ();
756 for (
size_t i = 0; i < idx; ++i, ++iter);
759 return builder.CreateLoad (iter);
774 rval =
convert (builder, rval);
779 builder.CreateRetVoid ();
782 builder.CreateRet (rval);
785 builder.CreateRetVoid ();
801 llvm::Function *lfn = fn.
to_llvm ();
802 os <<
"jit_function: cc=" << fn.
call_conv;
803 llvm::raw_os_ostream llvm_out (os);
804 lfn->print (llvm_out);
812 for (generated_map::iterator iter =
generated.begin ();
822 const std::vector<jit_type*>& args)
830 bool must_resize =
false;
832 if (dv.length () != idx.numel ())
834 dv.resize (idx.numel ());
855 for (
size_t i =0; i < types.size (); ++i)
857 return null_overload;
880 numel =
std::max (numel, static_cast<octave_idx_type>(2));
883 for (
octave_idx_type i = 0; i < static_cast<octave_idx_type> (types.size ());
885 idx(i) = types[i]->type_id ();
887 if (types.size () == 0)
889 if (types.size () == 1)
902 generated_map::const_iterator
find =
generated.find (&types);
906 return *find->second;
908 return null_overload;
913 return ret ? *ret : null_overload;
929 if (l.size () < r.size ())
931 else if (l.size () > r.size ())
934 for (
size_t i = 0; i < l.size (); ++i)
936 if (l[i]->type_id () < r[i]->type_id ())
938 else if (l[i]->type_id () > r[i]->type_id ())
953 for (
size_t i = 1; i < types.size (); ++i)
954 if (types[i] != scalar)
966 size_t end_idx)
const
968 size_t n = end_idx - start_idx;
970 llvm::ArrayType *array_t = llvm::ArrayType::get (scalar_t, n);
971 llvm::Value *array = llvm::UndefValue::get (array_t);
972 for (
size_t i = start_idx; i < end_idx; ++i)
974 llvm::Value *idx = fn.
argument (builder, i);
975 array = builder.CreateInsertValue (array, idx, i - start_idx);
978 llvm::Value *array_mem = builder.CreateAlloca (array_t);
979 builder.CreateStore (array, array_mem);
980 return builder.CreateBitCast (array_mem, scalar_t->getPointerTo ());
987 std::stringstream ss;
988 ss <<
"jit_paren_subsref_matrix_scalar" << (types.size () - 1);
992 ss.str (),
scalar, types);
994 llvm::BasicBlock *body = fn->
new_block ();
999 llvm::Value *nelem = llvm::ConstantInt::get (index->to_llvm (),
1001 llvm::Value *mat = fn->
argument (builder, 0);
1010 std::vector<jit_type *> types (3);
1017 "octave_jit_paren_scalar", scalar, types);
1026 std::stringstream ss;
1027 ss <<
"jit_paren_subsasgn_matrix_scalar" << (types.size () - 2);
1031 ss.str (), matrix, types);
1033 llvm::BasicBlock *body = fn->
new_block ();
1036 llvm::Value *array =
create_arg_array (builder, *fn, 1, types.size () - 1);
1038 llvm::Value *nelem = llvm::ConstantInt::get (index->to_llvm (),
1041 llvm::Value *mat = fn->
argument (builder, 0);
1042 llvm::Value *value = fn->
argument (builder, types.size () - 1);
1055 std::vector<jit_type *> types (4);
1062 "octave_jit_paren_scalar", matrix, types);
1075 #define JIT_FN(fn) engine, &fn, #fn
1078 : module (m), engine (e),
next_id (0),
1084 llvm::Type *any_t = llvm::StructType::create (
context,
"octave_base_value");
1085 any_t = any_t->getPointerTo ();
1087 llvm::Type *scalar_t = llvm::Type::getDoubleTy (
context);
1088 llvm::Type *bool_t = llvm::Type::getInt1Ty (
context);
1089 llvm::Type *string_t = llvm::Type::getInt8Ty (
context);
1090 string_t = string_t->getPointerTo ();
1091 llvm::Type *index_t = llvm::Type::getIntNTy (
context,
1094 llvm::StructType *range_t = llvm::StructType::create (
context,
"range");
1095 std::vector<llvm::Type *> range_contents (4, scalar_t);
1096 range_contents[3] = index_t;
1097 range_t->setBody (range_contents);
1099 llvm::Type *refcount_t = llvm::Type::getIntNTy (
context,
sizeof(
int) * 8);
1101 llvm::StructType *matrix_t = llvm::StructType::create (
context,
"matrix");
1102 llvm::Type *matrix_contents[5];
1103 matrix_contents[0] = refcount_t->getPointerTo ();
1104 matrix_contents[1] = scalar_t->getPointerTo ();
1105 matrix_contents[2] = index_t;
1106 matrix_contents[3] = index_t->getPointerTo ();
1107 matrix_contents[4] = string_t;
1108 matrix_t->setBody (llvm::makeArrayRef (matrix_contents, 5));
1110 llvm::Type *complex_t = llvm::ArrayType::get (scalar_t, 2);
1114 llvm::Type *cmplx_inner_cont[] = {scalar_t, scalar_t};
1115 llvm::StructType *cmplx_inner = llvm::StructType::create (cmplx_inner_cont);
1119 llvm::Type *contents[] = {cmplx_inner};
1156 if (
sizeof (
void *) == 4)
1164 llvm::GlobalValue::ExternalLinkage,
1173 llvm::GlobalValue::ExternalLinkage, 0,
1174 "octave_interrupt_state");
1188 llvm::Type *llvm_bo_type = binary_op_type->
to_llvm ();
1197 binary_ops[i].stash_name (
"binary" + op_name);
1205 unary_ops[i].stash_name (
"unary" + op_name);
1210 llvm::Twine fn_name (
"octave_jit_binary_any_any_");
1211 fn_name = fn_name + llvm::Twine (op);
1215 llvm::BasicBlock *block = fn.
new_block ();
1216 builder.SetInsertPoint (block);
1218 std::numeric_limits<octave_value::binary_op>::is_signed);
1219 llvm::Value *op_as_llvm = llvm::ConstantInt::get (llvm_bo_type, op_int);
1220 llvm::Value *ret = any_binary.
call (
builder, op_as_llvm,
1277 llvm::BasicBlock *body = fn.
new_block ();
1278 builder.SetInsertPoint (body);
1280 llvm::BasicBlock *warn_block = fn.
new_block (
"warn");
1281 llvm::BasicBlock *normal_block = fn.
new_block (
"normal");
1283 llvm::Value *zero = llvm::ConstantFP::get (scalar_t, 0);
1285 builder.CreateCondBr (check, warn_block, normal_block);
1287 builder.SetInsertPoint (warn_block);
1289 builder.CreateBr (normal_block);
1291 builder.SetInsertPoint (normal_block);
1316 builder.SetInsertPoint (body);
1318 llvm::Value *one = llvm::ConstantFP::get (scalar_t, 1);
1320 val =
builder.CreateFAdd (val, one);
1327 builder.SetInsertPoint (body);
1329 llvm::Value *one = llvm::ConstantFP::get (scalar_t, 1);
1331 val =
builder.CreateFSub (val, one);
1338 builder.SetInsertPoint (body);
1340 llvm::Value *mone = llvm::ConstantFP::get (scalar_t, -1);
1342 val =
builder.CreateFMul (val, mone);
1356 builder.SetInsertPoint (body);
1371 builder.SetInsertPoint (body);
1403 builder.SetInsertPoint (body);
1405 llvm::BasicBlock *complex_mul = fn.
new_block (
"complex_mul");
1406 llvm::BasicBlock *scalar_mul = fn.
new_block (
"scalar_mul");
1408 llvm::Value *fzero = llvm::ConstantFP::get (scalar_t, 0);
1413 builder.CreateCondBr (cmp, scalar_mul, complex_mul);
1415 builder.SetInsertPoint (scalar_mul);
1417 temp =
builder.CreateFMul (lhs, temp);
1421 builder.SetInsertPoint (complex_mul);
1437 builder.SetInsertPoint (body);
1452 builder.SetInsertPoint (body);
1464 builder.SetInsertPoint (body);
1500 builder.SetInsertPoint (body);
1502 llvm::Value *zero = llvm::ConstantInt::get (index_t, 0);
1512 builder.SetInsertPoint (body);
1517 llvm::Value *ret =
builder.CreateICmpULT (idx, nelem);
1527 builder.SetInsertPoint (body);
1530 llvm::Value *didx =
builder.CreateSIToFP (idx, scalar_t);
1532 llvm::Value *base =
builder.CreateExtractValue (rng, 0);
1533 llvm::Value *inc =
builder.CreateExtractValue (rng, 2);
1535 llvm::Value *ret =
builder.CreateFMul (didx, inc);
1536 ret =
builder.CreateFAdd (base, ret);
1552 builder.SetInsertPoint (body);
1554 llvm::BasicBlock *error_block = fn.
new_block (
"error");
1555 llvm::BasicBlock *normal_block = fn.
new_block (
"normal");
1559 builder.CreateCondBr (check, error_block, normal_block);
1561 builder.SetInsertPoint (error_block);
1563 builder.CreateBr (normal_block);
1564 builder.SetInsertPoint (normal_block);
1566 llvm::Value *zero = llvm::ConstantFP::get (scalar_t, 0);
1586 builder.SetInsertPoint (body);
1591 llvm::Value *nelem = compute_nelem.
call (
builder, base, limit, inc);
1593 llvm::Value *dzero = llvm::ConstantFP::get (scalar_t, 0);
1594 llvm::Value *izero = llvm::ConstantInt::get (index_t, 0);
1595 llvm::Value *rng = llvm::ConstantStruct::get (range_t, dzero, dzero, dzero,
1597 rng =
builder.CreateInsertValue (rng, base, 0);
1598 rng =
builder.CreateInsertValue (rng, limit, 1);
1599 rng =
builder.CreateInsertValue (rng, inc, 2);
1600 rng =
builder.CreateInsertValue (rng, nelem, 3);
1607 llvm::Type *int_t = jit_int->
to_llvm ();
1611 0, jit_int, jit_int,
index,
1618 builder.SetInsertPoint (body);
1620 llvm::Value *one_idx = llvm::ConstantInt::get (index_t, 1);
1621 llvm::Value *one_int = llvm::ConstantInt::get (int_t, 1);
1623 llvm::Value *undef = llvm::UndefValue::get (scalar_t);
1628 llvm::Value *int_idx =
builder.CreateFPToSI (idx, index_t);
1629 llvm::Value *check_idx =
builder.CreateSIToFP (int_idx, scalar_t);
1630 llvm::Value *cond0 =
builder.CreateFCmpUNE (idx, check_idx);
1631 llvm::Value *cond1 =
builder.CreateICmpSLT (int_idx, one_idx);
1632 llvm::Value *cond =
builder.CreateOr (cond0, cond1);
1634 llvm::BasicBlock *done = fn.
new_block (
"done");
1635 llvm::BasicBlock *conv_error = fn.
new_block (
"conv_error", done);
1636 llvm::BasicBlock *normal = fn.
new_block (
"normal", done);
1637 builder.CreateCondBr (cond, conv_error, normal);
1639 builder.SetInsertPoint (conv_error);
1643 builder.SetInsertPoint (normal);
1645 =
builder.CreateExtractValue (mat, llvm::ArrayRef<unsigned> (2));
1646 cond =
builder.CreateICmpSGT (int_idx, len);
1649 llvm::BasicBlock *bounds_error = fn.
new_block (
"bounds_error", done);
1650 llvm::BasicBlock *success = fn.
new_block (
"success", done);
1651 builder.CreateCondBr (cond, bounds_error, success);
1653 builder.SetInsertPoint (bounds_error);
1654 gindex_range.
call (
builder, one_int, one_int, int_idx, len);
1657 builder.SetInsertPoint (success);
1658 llvm::Value *data =
builder.CreateExtractValue (mat,
1659 llvm::ArrayRef<unsigned> (1));
1660 llvm::Value *gep =
builder.CreateInBoundsGEP (data, int_idx);
1661 llvm::Value *ret =
builder.CreateLoad (gep);
1664 builder.SetInsertPoint (done);
1666 llvm::PHINode *merge = llvm::PHINode::Create (scalar_t, 3);
1668 merge->addIncoming (undef, conv_error);
1669 merge->addIncoming (undef, bounds_error);
1670 merge->addIncoming (ret, success);
1686 builder.SetInsertPoint (body);
1688 llvm::Value *one_idx = llvm::ConstantInt::get (index_t, 1);
1689 llvm::Value *one_int = llvm::ConstantInt::get (int_t, 1);
1695 llvm::Value *int_idx =
builder.CreateFPToSI (idx, index_t);
1696 llvm::Value *check_idx =
builder.CreateSIToFP (int_idx, scalar_t);
1697 llvm::Value *cond0 =
builder.CreateFCmpUNE (idx, check_idx);
1698 llvm::Value *cond1 =
builder.CreateICmpSLT (int_idx, one_idx);
1699 llvm::Value *cond =
builder.CreateOr (cond0, cond1);
1701 llvm::BasicBlock *done = fn.
new_block (
"done");
1703 llvm::BasicBlock *conv_error = fn.
new_block (
"conv_error", done);
1704 llvm::BasicBlock *normal = fn.
new_block (
"normal", done);
1705 builder.CreateCondBr (cond, conv_error, normal);
1706 builder.SetInsertPoint (conv_error);
1710 builder.SetInsertPoint (normal);
1711 llvm::Value *len =
builder.CreateExtractValue (mat, 2);
1712 cond0 =
builder.CreateICmpSGT (int_idx, len);
1714 llvm::Value *rcount =
builder.CreateExtractValue (mat, 0);
1715 rcount =
builder.CreateLoad (rcount);
1716 cond1 =
builder.CreateICmpSGT (rcount, one_int);
1717 cond =
builder.CreateOr (cond0, cond1);
1719 llvm::BasicBlock *bounds_error = fn.
new_block (
"bounds_error", done);
1720 llvm::BasicBlock *success = fn.
new_block (
"success", done);
1721 builder.CreateCondBr (cond, bounds_error, success);
1724 builder.SetInsertPoint (bounds_error);
1725 llvm::Value *resize_result = resize_paren_subsasgn.
call (
builder, mat,
1729 builder.SetInsertPoint (success);
1731 =
builder.CreateExtractValue (mat, llvm::ArrayRef<unsigned> (1));
1732 llvm::Value *gep =
builder.CreateInBoundsGEP (data, int_idx);
1733 builder.CreateStore (value, gep);
1736 builder.SetInsertPoint (done);
1738 llvm::PHINode *merge = llvm::PHINode::Create (matrix_t, 3);
1740 merge->addIncoming (mat, conv_error);
1741 merge->addIncoming (resize_result, bounds_error);
1742 merge->addIncoming (mat, success);
1755 builder.SetInsertPoint (body);
1758 llvm::Value *ret =
builder.CreateExtractValue (mat, 2);
1777 casts[range->type_id ()].stash_name (
"(range)");
1793 casts[range->type_id ()].add_overload (fn);
1814 builder.SetInsertPoint (body);
1816 llvm::Value *zero = llvm::ConstantFP::get (scalar_t, 0);
1824 builder.SetInsertPoint (body);
1888 std::vector<jit_type *> args;
1891 for (std::map<std::string, jit_type *>::iterator iter =
builtins.begin ();
1911 if (ccount && ccount->
value () == 1)
1919 llvm::Type *llvm_type,
bool skip_paren)
1929 std::stringstream name;
1930 name <<
"octave_jit_print_" << ty->
name ();
1940 std::stringstream fname;
1943 <<
"_" << ty->
name ();
1946 llvm::BasicBlock *block = fn.
new_block ();
1947 builder.SetInsertPoint (block);
1948 llvm::Instruction::BinaryOps temp
1949 =
static_cast<llvm::Instruction::BinaryOps
>(llvm_op);
1960 std::stringstream fname;
1963 <<
"_" << ty->
name ();
1966 llvm::BasicBlock *block = fn.
new_block ();
1967 builder.SetInsertPoint (block);
1968 llvm::CmpInst::Predicate temp
1969 =
static_cast<llvm::CmpInst::Predicate
>(llvm_op);
1979 std::stringstream fname;
1982 <<
"_" << ty->
name ();
1985 llvm::BasicBlock *block = fn.
new_block ();
1986 builder.SetInsertPoint (block);
1987 llvm::CmpInst::Predicate temp
1988 =
static_cast<llvm::CmpInst::Predicate
>(llvm_op);
1998 const std::vector<jit_type *>& args)
2013 std::stringstream name;
2014 name <<
"id_" << type->
name ();
2017 llvm::BasicBlock *body = fn.
new_block ();
2018 builder.SetInsertPoint (body);
2036 val->setVolatile (
true);
2037 return abuilder.CreateICmpSGT (val, abuilder.getInt32 (0));
2054 const std::vector<jit_type *>& args)
2057 size_t nargs = args.size ();
2058 llvm::SmallVector<llvm::Type *, 5> llvm_args (nargs);
2059 for (
size_t i = 0; i < nargs; ++i)
2060 llvm_args[i] = args[i]->
to_llvm ();
2062 llvm::Intrinsic::ID
id =
static_cast<llvm::Intrinsic::ID
> (iid);
2063 llvm::Function *ifun = llvm::Intrinsic::getDeclaration (
module,
id,
2065 std::stringstream fn_name;
2066 fn_name <<
"octave_jit_" << name;
2068 std::vector<jit_type *> args1 (nargs + 1);
2069 args1[0] = builtin_type;
2070 std::copy (args.begin (), args.end (), args1.begin () + 1);
2076 llvm::BasicBlock *body = fn.
new_block ();
2077 builder.SetInsertPoint (body);
2079 llvm::SmallVector<llvm::Value *, 5> fargs (nargs);
2080 for (
size_t i = 0; i < nargs; ++i)
2081 fargs[i] = fn.argument (
builder, i + 1);
2083 llvm::Value *ret =
builder.CreateCall (ifun, fargs);
2099 const std::vector<jit_type *>& args)
2105 std::vector<jit_type *> fn_args (args.size () + 1);
2107 std::copy (args.begin (), args.end (), fn_args.begin () + 1);
2109 fn.mark_can_error ();
2110 llvm::BasicBlock *block = fn.new_block ();
2111 builder.SetInsertPoint (block);
2113 llvm::ArrayType *array_t = llvm::ArrayType::get (any_t, args.size ());
2114 llvm::Value *array = llvm::UndefValue::get (array_t);
2115 for (
size_t i = 0; i < args.size (); ++i)
2117 llvm::Value *
arg = fn.argument (
builder, i + 1);
2125 llvm::Value *array_mem =
builder.CreateAlloca (array_t);
2126 builder.CreateStore (array, array_mem);
2127 array =
builder.CreateBitCast (array_mem, any_t->getPointerTo ());
2130 llvm::Type *intTy = jintTy->
to_llvm ();
2131 size_t fcn_int =
reinterpret_cast<size_t> (builtin->
function ());
2132 llvm::Value *fcn = llvm::ConstantInt::get (intTy, fcn_int);
2133 llvm::Value *nargin = llvm::ConstantInt::get (intTy, args.size ());
2134 size_t result_int =
reinterpret_cast<size_t> (result);
2135 llvm::Value *res_llvm = llvm::ConstantInt::get (intTy, result_int);
2152 llvm::BasicBlock *body = ret.
new_block ();
2153 builder.SetInsertPoint (body);
2168 llvm::Value *
real = bld.CreateExtractValue (cplx, 0);
2169 llvm::Value *
imag = bld.CreateExtractValue (cplx, 1);
2170 llvm::Value *ret = llvm::UndefValue::get (complex_ret);
2172 unsigned int re_idx[] = {0, 0};
2173 unsigned int im_idx[] = {0, 1};
2174 ret = bld.CreateInsertValue (ret, real, re_idx);
2175 return bld.CreateInsertValue (ret, imag, im_idx);
2181 unsigned int re_idx[] = {0, 0};
2182 unsigned int im_idx[] = {0, 1};
2185 llvm::Value *
real = bld.CreateExtractValue (result, re_idx);
2186 llvm::Value *
imag = bld.CreateExtractValue (result, im_idx);
2187 llvm::Value *ret = llvm::UndefValue::get (complex_t);
2189 ret = bld.CreateInsertValue (ret, real, 0);
2190 return bld.CreateInsertValue (ret, imag, 1);
2196 return builder.CreateExtractValue (cx, 0);
2202 return builder.CreateInsertValue (cx, real, 0);
2208 return builder.CreateExtractValue (cx, 1);
2214 return builder.CreateInsertValue (cx, imag, 1);
2228 std::stringstream tname;
2229 tname <<
"int" << nbits;
2237 std::map<size_t, jit_type *>::const_iterator iter =
ints.find (nbits);
2238 if (iter !=
ints.end ())
2239 return iter->second;
2253 return builtin && builtin->
to_jit () ? builtin->
to_jit ()
2275 if (cv.imag () != 0)
jit_type * result(void) const
void do_return(llvm::IRBuilderD &builder, llvm::Value *rval=0, bool verify=true)
octave_idx_type slice_len
Array< octave_idx_type > to_idx(const signature_vec &types) const
void stash_jit(jit_type &type)
static llvm::Value * unpack_complex(llvm::IRBuilderD &bld, llvm::Value *result)
void add_binary_fcmp(jit_type *ty, int op, int llvm_op)
bool is_range(void) const
jit_type * unknown_function
jit_function * generate_matrix(const signature_vec &types) const
static int xisint(double x)
Complex octave_jit_pow_scalar_scalar(double lhs, double rhs)
virtual void do_initialize(void)
static jit_type * get_matrix(void)
octave_base_value * octave_jit_grab_any(octave_base_value *obv)
octave_base_value * octave_jit_cast_any_complex(Complex c)
const std::string & name(void) const
llvm::Value * complex_imag(llvm::Value *cx)
llvm::Type * sig_atomic_type
double octave_jit_cast_scalar_any(octave_base_value *obv)
void octave_jit_gripe_nan_to_logical_conversion(void)
octave_value_list(* fcn)(const octave_value_list &, int)
jit_operation for_check_fn
octave_base_value * octave_jit_call(octave_builtin::fcn fn, size_t nargin, octave_base_value **argin, jit_type *result_type)
void add_binary_icmp(jit_type *ty, int op, int llvm_op)
octave_base_value * octave_jit_binary_any_any(octave_value::binary_op op, octave_base_value *lhs, octave_base_value *rhs)
llvm::Type * to_llvm(void) const
jit_paren_subsref paren_subsref_fn
static std::string binary_op_as_string(binary_op)
bool is_function(void) const
static void initialize(llvm::Module *m, llvm::ExecutionEngine *e)
virtual jit_function * generate(const signature_vec &types) const
jit_type * to_jit(void) const
octave_idx_type length(void) const
jit_block * parent(void) const
octave_idx_type nelem(void) const
bool mpointer_arg[jit_convention::length]
virtual Range range_value(void) const
octave_base_value * octave_jit_create_undef(void)
void register_generic(const std::string &name, jit_type *result, jit_type *arg0)
jit_matrix octave_jit_paren_subsasgn_matrix_range(jit_matrix *mat, jit_range *index, double value)
std::ostream & operator<<(std::ostream &os, const jit_range &rng)
bool is_complex_scalar(void) const
jit_type * new_type(const std::string &name, jit_type *parent, llvm::Type *llvm_type, bool skip_paren=false)
FloatComplex(* fptr)(const FloatComplex &, float, int, octave_idx_type &)
Complex octave_jit_complex_div(Complex lhs, Complex rhs)
bool msret[jit_convention::length]
static llvm::Value * pack_complex(llvm::IRBuilderD &bld, llvm::Value *cplx)
void error(const char *fmt,...)
void set_packed_type(jit_convention::type cc, llvm::Type *ty)
jit_type * type(void) const
void add_builtin(const std::string &name)
jit_type * intN(size_t nbits) const
void mark_sret(jit_convention::type cc)
llvm::Type * mpacked_type[jit_convention::length]
T * jit_slice_data(void) const
llvm::Value * complex_new(llvm::Value *real, llvm::Value *imag)
void add_overload(const jit_function &func)
void gripe_library_execution_error(void)
std::vector< jit_type * > signature_vec
jit_function mirror_binary(const jit_function &fn)
std::vector< jit_type * > id_to_type
convert_fn pack(jit_convention::type cc)
std::map< size_t, jit_type * > ints
static llvm::IRBuilder builder(llvm::getGlobalContext())
static llvm::Type * get_scalar_llvm(void)
void gripe_invalid_index(void)
llvm::TerminatorInst * to_llvm(void) const
void mark_pointer_arg(jit_convention::type cc)
jit_range octave_jit_cast_range_any(octave_base_value *obv)
llvm::ExecutionEngine * engine
static jit_type * get_range(void)
Complex octave_jit_cast_complex_any(octave_base_value *obv)
llvm::Function * llvm_function
llvm::GlobalVariable * lerror_state
llvm::Value * call(llvm::IRBuilderD &builder, const std::vector< jit_value * > &in_args) const
std::map< std::string, jit_type * > builtins
octave_idx_type nelem(void) const
Number of elements in the array.
jit_matrix octave_jit_grab_matrix(jit_matrix *m)
jit_function create_external(llvm::ExecutionEngine *ee, T fn, const llvm::Twine &name, jit_type *ret, const std::vector< jit_type * > &args=std::vector< jit_type * >())
jit_function paren_scalar
const dim_vector & dims(void) const
Return a const-reference so that dims ()(i) works efficiently.
std::ostream & jit_print(std::ostream &os, jit_type *atype)
static const jit_operation & cast(jit_type *result)
virtual Complex complex_value(bool=false) const
static jit_type * get_complex(void)
void octave_jit_gindex_range(int nd, int dim, octave_idx_type iext, octave_idx_type ext)
void add_mapping(llvm::ExecutionEngine *engine, T fn)
const jit_function & do_generate(const signature_vec &types) const
const jit_function & overload(const signature_vec &types) const
bool pointer_arg(jit_convention::type cc) const
int * jit_ref_count(void)
WARNING: Only call these functions from jit.
jit_matrix octave_jit_paren_scalar_subsasgn(jit_matrix *mat, double *indices, octave_idx_type idx_count, double value)
llvm::IRBuilderD & builder
void octave_jit_release_any(octave_base_value *obv)
virtual double double_value(bool=false) const
bool is_real_scalar(void) const
std::vector< jit_operation > binary_ops
static llvm::LLVMContext & context
static void gripe_index_out_of_range(void)
void octave_jit_print_matrix(jit_matrix *m)
static void gripe_bad_result(void)
bool is_matrix_type(void) const
void gripe_nan_to_logical_conversion(void)
void resize1(octave_idx_type n, const T &rfv)
jit_convention::type call_conv
llvm::StructType * complex_ret
bool is_double_type(void) const
jit_operation for_init_fn
std::vector< jit_operation > unary_ops
virtual jit_function * generate_matrix(const signature_vec &types) const
jit_type * do_type_of(const octave_value &ov) const
bool is_complex_type(void) const
const jit_function & do_end(jit_value *value, jit_value *index, jit_value *count)
void resize(const dim_vector &dv, const T &rfv)
octave_int< T > pow(const octave_int< T > &a, const octave_int< T > &b)
bool can_error(void) const
void create_int(size_t nbits)
llvm::Value * do_insert_error_check(llvm::IRBuilderD &bld)
jit_type * argument_type(size_t idx) const
static jit_type * get_scalar(void)
octave_builtin * find_builtin(const std::string &name)
sig_atomic_t octave_interrupt_state
void stash_name(const std::string &aname)
Complex octave_jit_pow_complex_scalar(Complex lhs, double rhs)
llvm::Value * complex_real(llvm::Value *cx)
octave_base_value * octave_jit_cast_any_matrix(jit_matrix *m)
OCTAVE_API double D_NINT(double x)
octave_idx_type * dimensions
bool operator()(const signature_vec *lhs, const signature_vec *rhs) const
jit_operation logically_true_fn
void add_binary_op(jit_type *ty, int op, int llvm_op)
jit_function create_identity(jit_type *type)
Complex octave_jit_pow_scalar_complex(double lhs, Complex rhs)
static octave_idx_type find(octave_idx_type i, octave_idx_type *pp)
T & xelem(octave_idx_type n)
jit_matrix octave_jit_paren_subsasgn_impl(jit_matrix *mat, octave_idx_type index, double value)
virtual ~jit_operation(void)
virtual jit_function * generate_matrix(const signature_vec &types) const =0
convert_fn unpack(jit_convention::type cc)
Handles the reference counting for all the derived classes.
charNDArray max(char d, const charNDArray &m)
void octave_jit_print_scalar(const char *name, double value)
static const jit_function & get_release(jit_type *type)
double octave_jit_end_matrix(jit_matrix *mat, octave_idx_type idx, octave_idx_type count)
jit_operation make_range_fn
jit_function create_internal(const llvm::Twine &name, jit_type *ret, const std::vector< jit_type * > &args=std::vector< jit_type * >())
jit_paren_subsasgn paren_subsasgn_fn
octave_value_list ovl(const octave_value &a0)
static void make_indices(double *indices, octave_idx_type idx_count, Array< idx_vector > &result)
static jit_type * get_scalar_ptr(void)
jit_type(const std::string &aname, jit_type *aparent, llvm::Type *allvm_type, bool askip_paren, int aid)
octave_base_value * octave_jit_cast_any_scalar(double value)
octave_base_value * octave_jit_cast_any_range(jit_range *rng)
jit_function create_function(jit_convention::type cc, const llvm::Twine &name, jit_type *ret, const std::vector< jit_type * > &args=std::vector< jit_type * >())
void initialize(llvm::Module *amodule, llvm::ExecutionEngine *aengine)
void register_intrinsic(const std::string &name, size_t id, jit_type *result, jit_type *arg0)
Complex complex_value(bool frc_str_conv=false) const
octave_idx_type octave_jit_compute_nelem(double base, double limit, double inc)
static size_t next_id(bool reset=false)
convert_fn munpack[jit_convention::length]
llvm::Value *(* convert_fn)(llvm::IRBuilderD &, llvm::Value *)
convert_fn mpack[jit_convention::length]
bool all_elements_are_ints(void) const
void print_with_name(std::ostream &os, const std::string &name) const
static int convert(int x, int ibase, int obase)
void add_print(jit_type *ty, void *fptr)
Complex octave_jit_pow_complex_complex(Complex lhs, Complex rhs)
void octave_jit_ginvalid_index(void)
jit_operation for_index_fn
bool is_undefined(void) const
llvm::BasicBlock * new_block(const std::string &aname="body", llvm::BasicBlock *insert_before=0)
static const jit_function & get_grab(jit_type *type)
void assign(const idx_vector &i, const Array< T > &rhs, const T &rfv)
Indexed assignment (always with resize & fill).
void set_pack(jit_convention::type cc, convert_fn fn)
ColumnVector imag(const ComplexColumnVector &a)
virtual void do_initialize(void)
static jit_typeinfo * instance
virtual jit_function * generate(const signature_vec &types) const
static jit_type * get_any(void)
llvm::Value * argument(llvm::IRBuilderD &builder, size_t idx) const
Complex octave_jit_complex_mul(Complex lhs, Complex rhs)
void do_add_mapping(llvm::ExecutionEngine *engine, void *fn)
std::complex< double > Complex
const T * fortran_vec(void) const
void octave_jit_print_any(const char *name, octave_base_value *obv)
static std::string unary_op_as_string(unary_op)
llvm::ExecutionEngine * engine
octave_base_value * internal_rep(void) const
ColumnVector real(const ComplexColumnVector &a)
llvm::Type * to_llvm_arg(void) const
virtual NDArray array_value(bool=false) const
llvm::Function * to_llvm(void) const
double octave_jit_paren_scalar(jit_matrix *mat, double *indicies, octave_idx_type idx_count)
void mark_can_error(void)
std::vector< jit_operation > casts
jit_matrix octave_jit_cast_matrix_any(octave_base_value *obv)
octave_value & xelem(octave_idx_type i)
llvm::Type * packed_type(jit_convention::type cc)
void set_unpack(jit_convention::type cc, convert_fn fn)
std::vector< jit_function > identities
llvm::Value * create_arg_array(llvm::IRBuilderD &builder, const jit_function &fn, size_t start_idx, size_t end_idx) const
virtual void print_with_name(std::ostream &output_buf, const std::string &name, bool print_padding=true)
jit_function paren_scalar
jit_typeinfo(llvm::Module *m, llvm::ExecutionEngine *e)
IRBuilder< true, ConstantFolder, IRBuilderDefaultInserter< true > > IRBuilderD
void gripe_divide_by_zero(void)
std::string name(void) const
void octave_jit_release_matrix(jit_matrix *m)
jit_operation create_undef_fn
return octave_value(v1.char_array_value().concat(v2.char_array_value(), ra_idx),((a1.is_sq_string()||a2.is_sq_string())? '\'': '"'))
F77_RET_T const double * x
llvm::GlobalVariable * loctave_interrupt_state
static bool scalar(const dim_vector &dims)
static jit_type * get_index(void)
charNDArray min(char d, const charNDArray &m)
octave_value do_binary_op(octave_value::binary_op op, const octave_value &v1, const octave_value &v2)
std::vector< Array< jit_function > > overloads
std::vector< jit_type * > args
llvm::Value * do_insert_interrupt_check(llvm::IRBuilderD &bld)
static octave_value find(const std::string &name, const octave_value_list &args=octave_value_list(), bool skip_variables=false, bool local_funcs=true)
bool all_elements_are_ints() const