26 #define __STDC_LIMIT_MACROS
27 #define __STDC_CONSTANT_MACROS
29 #if defined (HAVE_CONFIG_H)
33 #if defined (HAVE_LLVM)
37 #if defined (HAVE_LLVM_IR_VERIFIER_H)
38 # include <llvm/IR/Verifier.h>
40 # include <llvm/Analysis/Verifier.h>
43 #include <llvm/ExecutionEngine/ExecutionEngine.h>
45 #if defined (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 #if defined (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 ();
241 if (array->
numel () < index)
245 data[index - 1] =
value;
270 return ret.
xelem (0);
285 mat->
array->assign (idx, temp);
314 if (start >= 0 && final < mat->slice_len)
320 std::fill (data + start, data + start + nelem, value);
334 array->
assign (idx, avalue);
349 else if (ndim > count)
351 if (idx == count - 1)
378 if (lhs.imag () == 0 && rhs.imag() == 0)
379 return Complex (lhs.real () * rhs.real (), 0);
407 if (lhs < 0.0 && !
xisint (rhs))
415 if (lhs.imag () == 0 && rhs.imag () == 0)
423 if (lhs.imag () == 0)
431 if (rhs.imag () == 0)
439 std::cout << *m << std::endl;
442 OCTAVE_NORETURN
static
446 error (
"incorrect type information given to the JIT compiler");
490 return os <<
"Range[" << rng.
base <<
", " << rng.
limit <<
", " << rng.
inc
491 <<
", " << rng.
nelem <<
"]";
506 llvm::Type *allvm_type,
bool askip_paren,
int aid) :
507 mname (aname),
mparent (aparent), llvm_type (allvm_type),
mid (aid),
508 mdepth (aparent ? aparent->mdepth + 1 : 0), mskip_paren (askip_paren)
533 const llvm::Twine& aname,
jit_type *aresult,
534 const std::vector<jit_type *>& aargs)
535 : module (amodule), mresult (aresult),
args (aargs), call_conv (acall_conv),
538 llvm::SmallVector<llvm::Type *, 15> llvm_args;
540 llvm::Type *rtype = llvm::Type::getVoidTy (
context);
546 llvm_args.push_back (rtype->getPointerTo ());
547 rtype = llvm::Type::getVoidTy (
context);
551 for (std::vector<jit_type *>::const_iterator iter =
args.begin ();
552 iter !=
args.end (); ++iter)
558 argty = argty->getPointerTo ();
560 llvm_args.push_back (argty);
565 llvm::FunctionType *ft = llvm::FunctionType::get (rtype, llvm_args,
false);
566 llvm_function = llvm::Function::Create (ft, llvm::Function::ExternalLinkage,
571 #if defined (FUNCTION_ADDATTRIBUTE_ARG_IS_ATTRIBUTES)
572 llvm::AttrBuilder attr_builder;
573 attr_builder.addAttribute (llvm::Attributes::StructRet);
574 llvm::Attributes attrs = llvm::Attributes::get(
context, attr_builder);
582 #if defined (FUNCTION_ADDFNATTR_ARG_IS_ATTRIBUTES)
590 const std::vector<jit_type *>& aargs)
591 : module (fn.module), llvm_function (fn.llvm_function), mresult (aresult),
592 args (aargs), call_conv (fn.call_conv), mcan_error (fn.mcan_error)
596 : module (fn.module), llvm_function (fn.llvm_function), mresult (fn.mresult),
597 args (fn.
args), call_conv (fn.call_conv), mcan_error (fn.mcan_error)
618 llvm::BasicBlock *insert_before)
626 const std::vector<jit_value *>& in_args)
const
631 assert (in_args.size () ==
args.size ());
632 std::vector<llvm::Value *> llvm_args (
args.size ());
633 for (
size_t i = 0;
i < in_args.size (); ++
i)
636 return call (builder, llvm_args);
641 const std::vector<llvm::Value *>& in_args)
const
646 assert (in_args.size () ==
args.size ());
647 llvm::SmallVector<llvm::Value *, 10> llvm_args;
648 llvm_args.reserve (in_args.size () +
sret ());
650 llvm::BasicBlock *insert_block = builder.GetInsertBlock ();
651 llvm::Function *
parent = insert_block->getParent ();
655 llvm::BasicBlock& prelude = parent->getEntryBlock ();
658 llvm::AllocaInst *sret_mem = 0;
662 llvm_args.push_back (sret_mem);
665 for (
size_t i = 0;
i < in_args.size (); ++
i)
667 llvm::Value *
arg = in_args[
i];
670 arg = convert (builder, arg);
675 llvm::Value *alloca = pre_builder.CreateAlloca (ty);
676 builder.CreateStore (arg, alloca);
680 llvm_args.push_back (arg);
683 llvm::CallInst *callinst = builder.CreateCall (
llvm_function, llvm_args);
684 llvm::Value *ret = callinst;
688 #if defined (CALLINST_ADDATTRIBUTE_ARG_IS_ATTRIBUTES)
689 llvm::AttrBuilder attr_builder;
690 attr_builder.addAttribute(llvm::Attributes::StructRet);
691 llvm::Attributes attrs = llvm::Attributes::get(
context, attr_builder);
692 callinst->addAttribute (1, attrs);
694 callinst->addAttribute (1, llvm::Attribute::StructRet);
696 ret = builder.CreateLoad (sret_mem);
703 ret = unpack (builder, ret);
712 assert (idx <
args.size ());
717 llvm::Function::arg_iterator iter =
llvm_function->arg_begin ();
721 for (
size_t i = 0;
i < idx; ++
i, ++iter);
724 return builder.CreateLoad (iter);
739 rval = convert (builder, rval);
744 builder.CreateRetVoid ();
747 builder.CreateRet (rval);
750 builder.CreateRetVoid ();
766 llvm::Function *lfn = fn.
to_llvm ();
767 os <<
"jit_function: cc=" << fn.
call_conv;
768 llvm::raw_os_ostream llvm_out (os);
769 lfn->print (llvm_out);
777 for (generated_map::iterator iter =
generated.begin ();
787 const std::vector<jit_type*>&
args)
795 bool must_resize =
false;
820 for (
size_t i = 0;
i < types.size (); ++
i)
822 return null_overload;
845 numel =
std::max (numel, static_cast<octave_idx_type>(2));
850 idx(
i) = types[
i]->type_id ();
852 if (types.size () == 0)
854 if (types.size () == 1)
867 generated_map::const_iterator
find =
generated.find (&types);
871 return *find->second;
873 return null_overload;
878 return ret ? *ret : null_overload;
894 if (l.size () < r.size ())
896 else if (l.size () > r.size ())
899 for (
size_t i = 0;
i < l.size (); ++
i)
901 if (l[
i]->type_id () < r[
i]->type_id ())
903 else if (l[
i]->type_id () > r[
i]->type_id ())
918 for (
size_t i = 1;
i < types.size (); ++
i)
919 if (types[
i] != scalar)
922 return generate_matrix (types);
931 size_t end_idx)
const
933 size_t n = end_idx - start_idx;
935 llvm::ArrayType *array_t = llvm::ArrayType::get (scalar_t, n);
936 llvm::Value *
array = llvm::UndefValue::get (array_t);
937 for (
size_t i = start_idx;
i < end_idx; ++
i)
939 llvm::Value *idx = fn.
argument (builder,
i);
940 array = builder.CreateInsertValue (array, idx,
i - start_idx);
943 llvm::Value *array_mem = builder.CreateAlloca (array_t);
944 builder.CreateStore (array, array_mem);
945 return builder.CreateBitCast (array_mem, scalar_t->getPointerTo ());
952 std::stringstream ss;
953 ss <<
"jit_paren_subsref_matrix_scalar" << (types.size () - 1);
957 ss.str (),
scalar, types);
959 llvm::BasicBlock *body = fn->
new_block ();
962 llvm::Value *
array = create_arg_array (builder, *fn, 1, types.size ());
964 llvm::Value *nelem = llvm::ConstantInt::get (index->to_llvm (),
966 llvm::Value *mat = fn->
argument (builder, 0);
967 llvm::Value *ret = paren_scalar.call (builder, mat, array, nelem);
975 std::vector<jit_type *> types (3);
982 "octave_jit_paren_scalar", scalar, types);
984 paren_scalar.mark_can_error ();
991 std::stringstream ss;
992 ss <<
"jit_paren_subsasgn_matrix_scalar" << (types.size () - 2);
996 ss.str (),
matrix, types);
998 llvm::BasicBlock *body = fn->
new_block ();
1001 llvm::Value *
array = create_arg_array (builder, *fn, 1, types.size () - 1);
1003 llvm::Value *nelem = llvm::ConstantInt::get (index->to_llvm (),
1006 llvm::Value *mat = fn->
argument (builder, 0);
1007 llvm::Value *
value = fn->
argument (builder, types.size () - 1);
1008 llvm::Value *ret = paren_scalar.call (builder, mat, array, nelem, value);
1016 if (paren_scalar.valid ())
1020 std::vector<jit_type *> types (4);
1027 "octave_jit_paren_scalar", matrix, types);
1029 paren_scalar.mark_can_error ();
1040 #define JIT_FN(fn) engine, &fn, #fn
1043 : module (m), engine (e),
next_id (0),
1049 llvm::Type *any_t = llvm::StructType::create (
context,
"octave_base_value");
1050 any_t = any_t->getPointerTo ();
1052 llvm::Type *scalar_t = llvm::Type::getDoubleTy (
context);
1053 llvm::Type *bool_t = llvm::Type::getInt1Ty (
context);
1054 llvm::Type *string_t = llvm::Type::getInt8Ty (
context);
1055 string_t = string_t->getPointerTo ();
1056 llvm::Type *index_t = llvm::Type::getIntNTy (
context,
1059 llvm::StructType *range_t = llvm::StructType::create (
context,
"range");
1060 std::vector<llvm::Type *> range_contents (4, scalar_t);
1061 range_contents[3] = index_t;
1062 range_t->setBody (range_contents);
1064 llvm::Type *refcount_t = llvm::Type::getIntNTy (
context,
sizeof(
int) * 8);
1066 llvm::StructType *matrix_t = llvm::StructType::create (
context,
"matrix");
1067 llvm::Type *matrix_contents[5];
1068 matrix_contents[0] = refcount_t->getPointerTo ();
1069 matrix_contents[1] = scalar_t->getPointerTo ();
1070 matrix_contents[2] = index_t;
1071 matrix_contents[3] = index_t->getPointerTo ();
1072 matrix_contents[4] = string_t;
1073 matrix_t->setBody (llvm::makeArrayRef (matrix_contents, 5));
1075 llvm::Type *complex_t = llvm::ArrayType::get (scalar_t, 2);
1079 llvm::Type *cmplx_inner_cont[] = {scalar_t, scalar_t};
1080 llvm::StructType *cmplx_inner = llvm::StructType::create (cmplx_inner_cont);
1084 llvm::Type *contents[] = {cmplx_inner};
1121 if (
sizeof (
void *) == 4)
1129 llvm::GlobalValue::ExternalLinkage,
1138 llvm::GlobalValue::ExternalLinkage, 0,
1139 "octave_interrupt_state");
1153 llvm::Type *llvm_bo_type = binary_op_type->
to_llvm ();
1175 llvm::Twine fn_name (
"octave_jit_binary_any_any_");
1176 fn_name = fn_name + llvm::Twine (op);
1180 llvm::BasicBlock *block = fn.
new_block ();
1181 builder.SetInsertPoint (block);
1183 std::numeric_limits<octave_value::binary_op>::is_signed);
1184 llvm::Value *op_as_llvm = llvm::ConstantInt::get (llvm_bo_type, op_int);
1185 llvm::Value *ret = any_binary.
call (
builder, op_as_llvm,
1242 llvm::BasicBlock *body = fn.
new_block ();
1243 builder.SetInsertPoint (body);
1245 llvm::BasicBlock *warn_block = fn.
new_block (
"warn");
1246 llvm::BasicBlock *normal_block = fn.
new_block (
"normal");
1248 llvm::Value *
zero = llvm::ConstantFP::get (scalar_t, 0);
1250 builder.CreateCondBr (check, warn_block, normal_block);
1252 builder.SetInsertPoint (warn_block);
1254 builder.CreateBr (normal_block);
1256 builder.SetInsertPoint (normal_block);
1281 builder.SetInsertPoint (body);
1283 llvm::Value *one = llvm::ConstantFP::get (scalar_t, 1);
1285 val =
builder.CreateFAdd (val, one);
1292 builder.SetInsertPoint (body);
1294 llvm::Value *one = llvm::ConstantFP::get (scalar_t, 1);
1296 val =
builder.CreateFSub (val, one);
1303 builder.SetInsertPoint (body);
1305 llvm::Value *mone = llvm::ConstantFP::get (scalar_t, -1);
1307 val =
builder.CreateFMul (val, mone);
1321 builder.SetInsertPoint (body);
1336 builder.SetInsertPoint (body);
1368 builder.SetInsertPoint (body);
1370 llvm::BasicBlock *complex_mul = fn.
new_block (
"complex_mul");
1371 llvm::BasicBlock *scalar_mul = fn.
new_block (
"scalar_mul");
1373 llvm::Value *fzero = llvm::ConstantFP::get (scalar_t, 0);
1378 builder.CreateCondBr (cmp, scalar_mul, complex_mul);
1380 builder.SetInsertPoint (scalar_mul);
1382 temp =
builder.CreateFMul (lhs, temp);
1385 builder.SetInsertPoint (complex_mul);
1400 builder.SetInsertPoint (body);
1415 builder.SetInsertPoint (body);
1427 builder.SetInsertPoint (body);
1463 builder.SetInsertPoint (body);
1465 llvm::Value *
zero = llvm::ConstantInt::get (index_t, 0);
1475 builder.SetInsertPoint (body);
1480 llvm::Value *ret =
builder.CreateICmpULT (idx, nelem);
1490 builder.SetInsertPoint (body);
1493 llvm::Value *didx =
builder.CreateSIToFP (idx, scalar_t);
1495 llvm::Value *base =
builder.CreateExtractValue (rng, 0);
1496 llvm::Value *inc =
builder.CreateExtractValue (rng, 2);
1498 llvm::Value *ret =
builder.CreateFMul (didx, inc);
1499 ret =
builder.CreateFAdd (base, ret);
1515 builder.SetInsertPoint (body);
1517 llvm::BasicBlock *error_block = fn.
new_block (
"error");
1518 llvm::BasicBlock *normal_block = fn.
new_block (
"normal");
1522 builder.CreateCondBr (check, error_block, normal_block);
1524 builder.SetInsertPoint (error_block);
1526 builder.CreateBr (normal_block);
1527 builder.SetInsertPoint (normal_block);
1529 llvm::Value *
zero = llvm::ConstantFP::get (scalar_t, 0);
1548 builder.SetInsertPoint (body);
1553 llvm::Value *nelem = compute_nelem.
call (
builder, base, limit, inc);
1555 llvm::Value *dzero = llvm::ConstantFP::get (scalar_t, 0);
1556 llvm::Value *izero = llvm::ConstantInt::get (index_t, 0);
1557 llvm::Value *rng = llvm::ConstantStruct::get (range_t, dzero, dzero, dzero,
1559 rng =
builder.CreateInsertValue (rng, base, 0);
1560 rng =
builder.CreateInsertValue (rng, limit, 1);
1561 rng =
builder.CreateInsertValue (rng, inc, 2);
1562 rng =
builder.CreateInsertValue (rng, nelem, 3);
1569 llvm::Type *int_t = jit_int->
to_llvm ();
1573 0, jit_int, jit_int,
index,
1580 builder.SetInsertPoint (body);
1582 llvm::Value *one_idx = llvm::ConstantInt::get (index_t, 1);
1583 llvm::Value *one_int = llvm::ConstantInt::get (int_t, 1);
1585 llvm::Value *undef = llvm::UndefValue::get (scalar_t);
1590 llvm::Value *int_idx =
builder.CreateFPToSI (idx, index_t);
1591 llvm::Value *check_idx =
builder.CreateSIToFP (int_idx, scalar_t);
1592 llvm::Value *cond0 =
builder.CreateFCmpUNE (idx, check_idx);
1593 llvm::Value *cond1 =
builder.CreateICmpSLT (int_idx, one_idx);
1594 llvm::Value *cond =
builder.CreateOr (cond0, cond1);
1597 llvm::BasicBlock *conv_error = fn.
new_block (
"conv_error", done);
1598 llvm::BasicBlock *normal = fn.
new_block (
"normal", done);
1599 builder.CreateCondBr (cond, conv_error, normal);
1601 builder.SetInsertPoint (conv_error);
1605 builder.SetInsertPoint (normal);
1607 =
builder.CreateExtractValue (mat, llvm::ArrayRef<unsigned> (2));
1608 cond =
builder.CreateICmpSGT (int_idx, len);
1610 llvm::BasicBlock *bounds_error = fn.
new_block (
"bounds_error", done);
1611 llvm::BasicBlock *success = fn.
new_block (
"success", done);
1612 builder.CreateCondBr (cond, bounds_error, success);
1614 builder.SetInsertPoint (bounds_error);
1615 gindex_range.
call (
builder, one_int, one_int, int_idx, len);
1618 builder.SetInsertPoint (success);
1619 llvm::Value *data =
builder.CreateExtractValue (mat,
1620 llvm::ArrayRef<unsigned> (1));
1621 llvm::Value *gep =
builder.CreateInBoundsGEP (data, int_idx);
1622 llvm::Value *ret =
builder.CreateLoad (gep);
1625 builder.SetInsertPoint (done);
1627 llvm::PHINode *merge = llvm::PHINode::Create (scalar_t, 3);
1629 merge->addIncoming (undef, conv_error);
1630 merge->addIncoming (undef, bounds_error);
1631 merge->addIncoming (ret, success);
1647 builder.SetInsertPoint (body);
1649 llvm::Value *one_idx = llvm::ConstantInt::get (index_t, 1);
1650 llvm::Value *one_int = llvm::ConstantInt::get (int_t, 1);
1656 llvm::Value *int_idx =
builder.CreateFPToSI (idx, index_t);
1657 llvm::Value *check_idx =
builder.CreateSIToFP (int_idx, scalar_t);
1658 llvm::Value *cond0 =
builder.CreateFCmpUNE (idx, check_idx);
1659 llvm::Value *cond1 =
builder.CreateICmpSLT (int_idx, one_idx);
1660 llvm::Value *cond =
builder.CreateOr (cond0, cond1);
1664 llvm::BasicBlock *conv_error = fn.
new_block (
"conv_error", done);
1665 llvm::BasicBlock *normal = fn.
new_block (
"normal", done);
1666 builder.CreateCondBr (cond, conv_error, normal);
1667 builder.SetInsertPoint (conv_error);
1671 builder.SetInsertPoint (normal);
1672 llvm::Value *len =
builder.CreateExtractValue (mat, 2);
1673 cond0 =
builder.CreateICmpSGT (int_idx, len);
1675 llvm::Value *rcount =
builder.CreateExtractValue (mat, 0);
1676 rcount =
builder.CreateLoad (rcount);
1677 cond1 =
builder.CreateICmpSGT (rcount, one_int);
1678 cond =
builder.CreateOr (cond0, cond1);
1680 llvm::BasicBlock *bounds_error = fn.
new_block (
"bounds_error", done);
1681 llvm::BasicBlock *success = fn.
new_block (
"success", done);
1682 builder.CreateCondBr (cond, bounds_error, success);
1685 builder.SetInsertPoint (bounds_error);
1686 llvm::Value *resize_result = resize_paren_subsasgn.
call (
builder, mat,
1690 builder.SetInsertPoint (success);
1692 =
builder.CreateExtractValue (mat, llvm::ArrayRef<unsigned> (1));
1693 llvm::Value *gep =
builder.CreateInBoundsGEP (data, int_idx);
1694 builder.CreateStore (value, gep);
1697 builder.SetInsertPoint (done);
1699 llvm::PHINode *merge = llvm::PHINode::Create (matrix_t, 3);
1701 merge->addIncoming (mat, conv_error);
1702 merge->addIncoming (resize_result, bounds_error);
1703 merge->addIncoming (mat, success);
1716 builder.SetInsertPoint (body);
1719 llvm::Value *ret =
builder.CreateExtractValue (mat, 2);
1738 casts[range->type_id ()].stash_name (
"(range)");
1754 casts[range->type_id ()].add_overload (fn);
1775 builder.SetInsertPoint (body);
1777 llvm::Value *
zero = llvm::ConstantFP::get (scalar_t, 0);
1785 builder.SetInsertPoint (body);
1849 std::vector<jit_type *>
args;
1852 for (std::map<std::string, jit_type *>::iterator iter =
builtins.begin ();
1872 if (ccount && ccount->
value () == 1)
1880 llvm::Type *llvm_type,
bool skip_paren)
1890 std::stringstream
name;
1891 name <<
"octave_jit_print_" << ty->
name ();
1901 std::stringstream
fname;
1904 <<
"_" << ty->
name ();
1907 llvm::BasicBlock *block = fn.
new_block ();
1908 builder.SetInsertPoint (block);
1909 llvm::Instruction::BinaryOps temp
1910 =
static_cast<llvm::Instruction::BinaryOps
>(llvm_op);
1921 std::stringstream
fname;
1924 <<
"_" << ty->
name ();
1927 llvm::BasicBlock *block = fn.
new_block ();
1928 builder.SetInsertPoint (block);
1929 llvm::CmpInst::Predicate temp
1930 =
static_cast<llvm::CmpInst::Predicate
>(llvm_op);
1940 std::stringstream
fname;
1943 <<
"_" << ty->
name ();
1946 llvm::BasicBlock *block = fn.
new_block ();
1947 builder.SetInsertPoint (block);
1948 llvm::CmpInst::Predicate temp
1949 =
static_cast<llvm::CmpInst::Predicate
>(llvm_op);
1959 const std::vector<jit_type *>&
args)
1974 std::stringstream
name;
1975 name <<
"id_" << type->
name ();
1978 llvm::BasicBlock *body = fn.
new_block ();
1979 builder.SetInsertPoint (body);
1997 val->setVolatile (
true);
1998 return abuilder.CreateICmpSGT (val, abuilder.getInt32 (0));
2015 const std::vector<jit_type *>&
args)
2018 size_t nargs = args.size ();
2019 llvm::SmallVector<llvm::Type *, 5> llvm_args (nargs);
2020 for (
size_t i = 0;
i < nargs; ++
i)
2023 llvm::Intrinsic::ID
id =
static_cast<llvm::Intrinsic::ID
> (iid);
2024 llvm::Function *ifun = llvm::Intrinsic::getDeclaration (
module,
id,
2026 std::stringstream fn_name;
2027 fn_name <<
"octave_jit_" <<
name;
2029 std::vector<jit_type *> args1 (nargs + 1);
2030 args1[0] = builtin_type;
2031 std::copy (args.begin (), args.end (), args1.begin () + 1);
2037 llvm::BasicBlock *body = fn.
new_block ();
2038 builder.SetInsertPoint (body);
2040 llvm::SmallVector<llvm::Value *, 5> fargs (nargs);
2041 for (
size_t i = 0;
i < nargs; ++
i)
2042 fargs[
i] = fn.argument (
builder,
i + 1);
2044 llvm::Value *ret =
builder.CreateCall (ifun, fargs);
2060 const std::vector<jit_type *>&
args)
2066 std::vector<jit_type *> fn_args (args.size () + 1);
2068 std::copy (args.begin (), args.end (), fn_args.begin () + 1);
2070 fn.mark_can_error ();
2071 llvm::BasicBlock *block = fn.new_block ();
2072 builder.SetInsertPoint (block);
2074 llvm::ArrayType *array_t = llvm::ArrayType::get (any_t, args.size ());
2075 llvm::Value *
array = llvm::UndefValue::get (array_t);
2076 for (
size_t i = 0;
i < args.size (); ++
i)
2086 llvm::Value *array_mem =
builder.CreateAlloca (array_t);
2087 builder.CreateStore (array, array_mem);
2088 array =
builder.CreateBitCast (array_mem, any_t->getPointerTo ());
2091 llvm::Type *intTy = jintTy->
to_llvm ();
2092 size_t fcn_int =
reinterpret_cast<size_t> (builtin->
function ());
2093 llvm::Value *
fcn = llvm::ConstantInt::get (intTy, fcn_int);
2094 llvm::Value *
nargin = llvm::ConstantInt::get (intTy, args.size ());
2095 size_t result_int =
reinterpret_cast<size_t> (
result);
2096 llvm::Value *res_llvm = llvm::ConstantInt::get (intTy, result_int);
2113 llvm::BasicBlock *body = ret.
new_block ();
2114 builder.SetInsertPoint (body);
2129 llvm::Value *
real = bld.CreateExtractValue (cplx, 0);
2130 llvm::Value *
imag = bld.CreateExtractValue (cplx, 1);
2131 llvm::Value *ret = llvm::UndefValue::get (complex_ret);
2133 unsigned int re_idx[] = {0, 0};
2134 unsigned int im_idx[] = {0, 1};
2135 ret = bld.CreateInsertValue (ret, real, re_idx);
2136 return bld.CreateInsertValue (ret, imag, im_idx);
2142 unsigned int re_idx[] = {0, 0};
2143 unsigned int im_idx[] = {0, 1};
2146 llvm::Value *
real = bld.CreateExtractValue (result, re_idx);
2147 llvm::Value *
imag = bld.CreateExtractValue (result, im_idx);
2148 llvm::Value *ret = llvm::UndefValue::get (complex_t);
2150 ret = bld.CreateInsertValue (ret, real, 0);
2151 return bld.CreateInsertValue (ret, imag, 1);
2157 return builder.CreateExtractValue (cx, 0);
2163 return builder.CreateInsertValue (cx, real, 0);
2169 return builder.CreateExtractValue (cx, 1);
2175 return builder.CreateInsertValue (cx, imag, 1);
2189 std::stringstream tname;
2190 tname <<
"int" << nbits;
2198 std::map<size_t, jit_type *>::const_iterator iter =
ints.find (nbits);
2199 if (iter !=
ints.end ())
2200 return iter->second;
2214 return builtin && builtin->
to_jit () ? builtin->
to_jit ()
2236 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)
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)
nd group nd example oindent but is performed more efficiently If only and it is a scalar
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
OCTAVE_EXPORT octave_value_list isa nd deftypefn *return ovl(args(0).is_integer_type())
jit_paren_subsref paren_subsref_fn
static std::string binary_op_as_string(binary_op)
bool is_function(void) const
octave_idx_type numel(void) const
Number of elements in the array.
static void initialize(llvm::Module *m, llvm::ExecutionEngine *e)
identity matrix If supplied two scalar respectively For allows like xample val
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
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)
the sparsity preserving column transformation such that that defines the pivoting threshold can be given in which case it defines the then the first element defines the pivoting tolerance for the unsymmetric the values defined such that for full matrix
bool is_complex_scalar(void) const
void resize(int n, int fill_value=0)
jit_type * new_type(const std::string &name, jit_type *parent, llvm::Type *llvm_type, bool skip_paren=false)
Complex octave_jit_complex_div(Complex lhs, Complex rhs)
void err_index_out_of_range(int nd, int dim, octave_idx_type idx, octave_idx_type ext)
bool msret[jit_convention::length]
static llvm::Value * pack_complex(llvm::IRBuilderD &bld, llvm::Value *cplx)
void err_invalid_index(const std::string &idx, octave_idx_type nd, octave_idx_type dim, const std::string &)
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)
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 err_nan_to_logical_conversion(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)
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
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 * >())
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)
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
nd deftypefn *octave_map m
void octave_jit_print_matrix(jit_matrix *m)
then the function must return scalars which will be concatenated into the return array(s).If code
bool is_matrix_type(void) const
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
octave_idx_type numel(void) const
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)
void warn_divide_by_zero(void)
the sparsity preserving column transformation such that that defines the pivoting threshold can be given in which case it defines the c
octave_idx_type * dimensions
bool operator()(const signature_vec *lhs, const signature_vec *rhs) const
With real return the complex result
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)
convert_fn unpack(jit_convention::type cc)
N Dimensional Array with copy-on-write semantics.
static OCTAVE_NORETURN void err_bad_result(void)
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 * >())
T::size_type numel(const T &str)
jit_paren_subsasgn paren_subsasgn_fn
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)
=val(i)}if ode{val(i)}occurs in table i
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 * >())
OCTAVE_EXPORT octave_value_list or N dimensional array whose elements are all equal to the IEEE symbol zero divided by nd tex zero divided by nd ifnottex and any operation involving another NaN value(5+NaN).Note that NaN always compares not equal to NaN(NaN!
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
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)
FloatComplex(* fptr)(const FloatComplex &, float, int, octave_idx_type &)
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)
Vector representing the dimensions (size) of an Array.
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)
If this string is the system will ring the terminal sometimes it is useful to be able to print the original representation of the string
int length(void) const
Number of dimensions.
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_typeinfo(llvm::Module *m, llvm::ExecutionEngine *e)
IRBuilder< true, ConstantFolder, IRBuilderDefaultInserter< true > > IRBuilderD
std::string name(void) const
void octave_jit_release_matrix(jit_matrix *m)
jit_operation create_undef_fn
F77_RET_T F77_REAL &F77_RET_T F77_DBLE &F77_RET_T F77_REAL &F77_RET_T F77_DBLE &F77_RET_T F77_REAL &F77_RET_T F77_DBLE &F77_RET_T const F77_REAL const F77_REAL F77_REAL &F77_RET_T const F77_DBLE const F77_DBLE F77_DBLE &F77_RET_T F77_REAL &F77_RET_T F77_DBLE &F77_RET_T F77_DBLE &F77_RET_T F77_REAL &F77_RET_T F77_REAL &F77_RET_T F77_DBLE &F77_RET_T const F77_DBLE F77_DBLE &F77_RET_T const F77_REAL F77_REAL &F77_RET_T F77_REAL F77_REAL &F77_RET_T F77_DBLE F77_DBLE &F77_RET_T const F77_DBLE * x
return octave_value(v1.char_array_value().concat(v2.char_array_value(), ra_idx),((a1.is_sq_string()||a2.is_sq_string())? '\'': '"'))
llvm::GlobalVariable * loctave_interrupt_state
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
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