comparison libinterp/corefcn/jit-typeinfo.cc @ 20654:b65888ec820e draft default tip gccjit

dmalcom gcc jit import
author Stefan Mahr <dac922@gmx.de>
date Fri, 27 Feb 2015 16:59:36 +0100
parents d35201e5ce5d
children
comparison
equal deleted inserted replaced
20653:9cef0a1207e4 20654:b65888ec820e
502 << mat.slice_len << ", " << mat.dimensions << ", " 502 << mat.slice_len << ", " << mat.dimensions << ", "
503 << mat.array << "]"; 503 << mat.array << "]";
504 } 504 }
505 505
506 // -------------------- jit_type -------------------- 506 // -------------------- jit_type --------------------
507 jit_type::jit_type (const std::string& aname, jit_type *aparent, 507 jit_type::jit_type (const std::string& aname, jit_type *aparent
508 llvm::Type *allvm_type, bool askip_paren, int aid) : 508 #ifdef HAVE_LLVM
509 mname (aname), mparent (aparent), llvm_type (allvm_type), mid (aid), 509 , llvm::Type *allvm_type
510 #endif
511 #ifdef HAVE_GCCJIT
512 , gccjit::type agcc_type
513 #endif
514 , bool askip_paren, int aid) :
515 mname (aname), mparent (aparent)
516 #ifdef HAVE_LLVM
517 , llvm_type (allvm_type)
518 #endif
519 #ifdef HAVE_GCCJIT
520 , gccjit_type (agcc_type)
521 #endif
522 , mid (aid),
510 mdepth (aparent ? aparent->mdepth + 1 : 0), mskip_paren (askip_paren) 523 mdepth (aparent ? aparent->mdepth + 1 : 0), mskip_paren (askip_paren)
511 { 524 {
512 std::memset (msret, 0, sizeof (msret)); 525 std::memset (msret, 0, sizeof (msret));
513 std::memset (mpointer_arg, 0, sizeof (mpointer_arg)); 526 std::memset (mpointer_arg, 0, sizeof (mpointer_arg));
514 std::memset (mpack, 0, sizeof (mpack)); 527 std::memset (mpack, 0, sizeof (mpack));
523 { 536 {
524 return llvm_type ? llvm_type->getPointerTo () : 0; 537 return llvm_type ? llvm_type->getPointerTo () : 0;
525 } 538 }
526 539
527 // -------------------- jit_function -------------------- 540 // -------------------- jit_function --------------------
528 jit_function::jit_function () : module (0), llvm_function (0), mresult (0), 541 jit_function::jit_function () : module (0), llvm_function (0),
542 #ifdef HAVE_GCCJIT
543 gccjit_function (),
544 #endif
545 mresult (0),
529 call_conv (jit_convention::length), 546 call_conv (jit_convention::length),
530 mcan_error (false) 547 mcan_error (false)
531 {} 548 {}
532 549
533 jit_function::jit_function (llvm::Module *amodule, 550 jit_function::jit_function (llvm::Module *amodule,
551 #ifdef HAVE_GCCJIT
552 gccjit::context gccjit_ctxt,
553 #endif
534 jit_convention::type acall_conv, 554 jit_convention::type acall_conv,
535 const llvm::Twine& aname, jit_type *aresult, 555 std::string aname, jit_type *aresult,
536 const std::vector<jit_type *>& aargs) 556 const std::vector<jit_type *>& aargs)
537 : module (amodule), mresult (aresult), args (aargs), call_conv (acall_conv), 557 : module (amodule), mresult (aresult), args (aargs), call_conv (acall_conv),
538 mcan_error (false) 558 mcan_error (false)
539 { 559 {
540 llvm::SmallVector<llvm::Type *, 15> llvm_args; 560 llvm::SmallVector<llvm::Type *, 15> llvm_args;
584 #ifdef FUNCTION_ADDFNATTR_ARG_IS_ATTRIBUTES 604 #ifdef FUNCTION_ADDFNATTR_ARG_IS_ATTRIBUTES
585 llvm_function->addFnAttr (llvm::Attributes::AlwaysInline); 605 llvm_function->addFnAttr (llvm::Attributes::AlwaysInline);
586 #else 606 #else
587 llvm_function->addFnAttr (llvm::Attribute::AlwaysInline); 607 llvm_function->addFnAttr (llvm::Attribute::AlwaysInline);
588 #endif 608 #endif
609
610 #ifdef HAVE_GCCJIT
611 if (gccjit_ctxt.get_inner_context ())
612 {
613 std::vector<gccjit::param> gccjit_params;
614 for (int i = 0; i < args.size (); i++)
615 {
616 jit_type *ty = args[i];
617 assert (ty);
618
619 gccjit::type argty = ty->to_gccjit ();
620 if (ty->pointer_arg (call_conv))
621 argty = argty.get_pointer ();
622
623 std::stringstream paramname;
624 paramname << "arg" << i;
625
626 gccjit::param param = gccjit_ctxt.new_param (argty,
627 paramname.str ());
628 gccjit_params.push_back (param);
629 }
630 gccjit::type gccjit_return_type;
631 if (aresult)
632 gccjit_return_type = aresult->to_gccjit ();
633 else
634 gccjit_return_type = gccjit_ctxt.get_type (GCC_JIT_TYPE_VOID);
635
636 enum gcc_jit_function_kind kind;
637 if (acall_conv == jit_convention::external)
638 kind = GCC_JIT_FUNCTION_IMPORTED;
639 else
640 {
641 if (0)
642 /* Doing this is correct, but makes the dump a little harder
643 to read.
644 Also, not fully implemented yet in libgccjit. */
645 kind = GCC_JIT_FUNCTION_ALWAYS_INLINE;
646 else
647 kind = GCC_JIT_FUNCTION_EXPORTED;
648 }
649 gccjit_function =
650 gccjit_ctxt.new_function (kind,
651 gccjit_return_type,
652 aname,
653 gccjit_params,
654 0);
655 }
656 #endif
589 } 657 }
590 658
591 jit_function::jit_function (const jit_function& fn, jit_type *aresult, 659 jit_function::jit_function (const jit_function& fn, jit_type *aresult,
592 const std::vector<jit_type *>& aargs) 660 const std::vector<jit_type *>& aargs)
593 : module (fn.module), llvm_function (fn.llvm_function), mresult (aresult), 661 : module (fn.module),
662 llvm_function (fn.llvm_function),
663 #ifdef HAVE_GCCJIT
664 gccjit_function (fn.gccjit_function),
665 #endif
666 mresult (aresult),
594 args (aargs), call_conv (fn.call_conv), mcan_error (fn.mcan_error) 667 args (aargs), call_conv (fn.call_conv), mcan_error (fn.mcan_error)
595 { 668 {
596 } 669 }
597 670
598 jit_function::jit_function (const jit_function& fn) 671 jit_function::jit_function (const jit_function& fn)
599 : module (fn.module), llvm_function (fn.llvm_function), mresult (fn.mresult), 672 : module (fn.module),
673 llvm_function (fn.llvm_function),
674 #ifdef HAVE_GCCJIT
675 gccjit_function (fn.gccjit_function),
676 #endif
677 mresult (fn.mresult),
600 args (fn.args), call_conv (fn.call_conv), mcan_error (fn.mcan_error) 678 args (fn.args), call_conv (fn.call_conv), mcan_error (fn.mcan_error)
601 {} 679 {}
602 680
603 void 681 void
604 jit_function::erase (void) 682 jit_function::erase (void)
752 else 830 else
753 builder.CreateRetVoid (); 831 builder.CreateRetVoid ();
754 832
755 if (verify) 833 if (verify)
756 llvm::verifyFunction (*llvm_function); 834 llvm::verifyFunction (*llvm_function);
757 } 835
836 if (0)
837 {
838 std::cout << "-------------------- llvm ir (at do_return) --------------------";
839 std::cout << *llvm_function << std::endl;
840 }
841 }
842
843 #ifdef HAVE_GCCJIT
844 #if 1
845 gccjit::rvalue
846 jit_function::call (gccjit::context ctxt,
847 gccjit::block block,
848 const std::vector<jit_value *>& in_args) const
849 {
850 assert (in_args.size () == args.size ());
851 std::vector<gccjit::rvalue> gccjit_args (args.size ());
852 for (size_t i = 0; i < in_args.size (); ++i)
853 gccjit_args[i] = in_args[i]->as_rvalue ();
854 return call (ctxt, block, gccjit_args);
855 }
856
857 gccjit::rvalue
858 jit_function::call (gccjit::context ctxt,
859 gccjit::block block,
860 std::vector<gccjit::rvalue>& in_args) const
861 {
862 assert (in_args.size () == args.size ());
863
864 #if 1
865 std::vector<gccjit::rvalue> packed_args (in_args.size ());
866
867 for (size_t i = 0; i < in_args.size (); ++i)
868 {
869 gccjit::rvalue arg = in_args[i];
870 #if 0
871 jit_type::convert_fn convert = args[i]->pack (call_conv);
872 if (convert)
873 arg = convert (builder, arg);
874 #endif
875
876 if (args[i]->pointer_arg (call_conv))
877 {
878 // The LLVM implementation takes a copy using alloca, passing
879 // a ptr to the copy to the fn. Emulate this behavior.
880 gccjit::lvalue tmp =
881 block.get_function ().new_local (arg.get_type (), "tmp");
882 block.add_assignment (tmp, arg);
883 arg = tmp.get_address ();
884 }
885
886 packed_args[i] = arg;
887 }
888
889 return ctxt.new_call (gccjit_function,
890 packed_args);
891 #else
892 return ctxt.new_call (gccjit_function,
893 in_args);
894 #endif
895 }
896 #endif
897
898 gccjit::lvalue
899 jit_function::argument (size_t idx) const
900 {
901 return gccjit_function.get_param (idx);
902 }
903 #endif
758 904
759 void 905 void
760 jit_function::do_add_mapping (llvm::ExecutionEngine *engine, void *fn) 906 jit_function::do_add_mapping (llvm::ExecutionEngine *engine, void *fn)
761 { 907 {
762 assert (valid ()); 908 assert (valid ());
926 } 1072 }
927 1073
928 return 0; 1074 return 0;
929 } 1075 }
930 1076
1077 #ifdef HAVE_LLVM
931 llvm::Value * 1078 llvm::Value *
932 jit_index_operation::create_arg_array (llvm::IRBuilderD& builder, 1079 jit_index_operation::create_arg_array (llvm::IRBuilderD& builder,
933 const jit_function &fn, size_t start_idx, 1080 const jit_function &fn, size_t start_idx,
934 size_t end_idx) const 1081 size_t end_idx) const
935 { 1082 {
945 1092
946 llvm::Value *array_mem = builder.CreateAlloca (array_t); 1093 llvm::Value *array_mem = builder.CreateAlloca (array_t);
947 builder.CreateStore (array, array_mem); 1094 builder.CreateStore (array, array_mem);
948 return builder.CreateBitCast (array_mem, scalar_t->getPointerTo ()); 1095 return builder.CreateBitCast (array_mem, scalar_t->getPointerTo ());
949 } 1096 }
1097 #endif // #ifdef HAVE_LLVM
1098
1099 #ifdef HAVE_GCCJIT
1100 gccjit::rvalue
1101 jit_index_operation::create_arg_array (const jit_function &fn,
1102 gccjit::block block,
1103 size_t start_idx,
1104 size_t end_idx) const
1105 {
1106 size_t n = end_idx - start_idx;
1107 gccjit::type scalar_t = jit_typeinfo::get_scalar_gccjit ();
1108 gccjit::type array_t = block.get_context ().new_array_type (scalar_t, n);
1109 gccjit::lvalue array =
1110 block.get_function ().new_local (array_t, "tmp_array");
1111 for (size_t i = start_idx; i < end_idx; ++i)
1112 {
1113 gccjit::rvalue idx = fn.argument (i);
1114 block.add_assignment (array[i - start_idx], idx);
1115 }
1116 return array.get_address ().cast_to (scalar_t.get_pointer ());
1117 }
1118 #endif // #ifdef HAVE_GCCJIT
950 1119
951 // -------------------- jit_paren_subsref -------------------- 1120 // -------------------- jit_paren_subsref --------------------
952 jit_function * 1121 jit_function *
953 jit_paren_subsref::generate_matrix (const signature_vec& types) const 1122 jit_paren_subsref::generate_matrix (const signature_vec& types) const
954 { 1123 {
955 std::stringstream ss; 1124 std::stringstream ss;
956 ss << "jit_paren_subsref_matrix_scalar" << (types.size () - 1); 1125 ss << "jit_paren_subsref_matrix_scalar" << (types.size () - 1);
957 1126
958 jit_type *scalar = jit_typeinfo::get_scalar (); 1127 jit_type *scalar = jit_typeinfo::get_scalar ();
959 jit_function *fn = new jit_function (module, jit_convention::internal, 1128 jit_function *fn = new jit_function (module,
1129 #ifdef HAVE_GCCJIT
1130 gccjit_ctxt,
1131 #endif
1132 jit_convention::internal,
960 ss.str (), scalar, types); 1133 ss.str (), scalar, types);
961 fn->mark_can_error (); 1134 fn->mark_can_error ();
962 llvm::BasicBlock *body = fn->new_block (); 1135 llvm::BasicBlock *body = fn->new_block ();
963 llvm::IRBuilder<> builder (body); 1136 llvm::IRBuilder<> builder (body);
964 1137
967 llvm::Value *nelem = llvm::ConstantInt::get (index->to_llvm (), 1140 llvm::Value *nelem = llvm::ConstantInt::get (index->to_llvm (),
968 types.size () - 1); 1141 types.size () - 1);
969 llvm::Value *mat = fn->argument (builder, 0); 1142 llvm::Value *mat = fn->argument (builder, 0);
970 llvm::Value *ret = paren_scalar.call (builder, mat, array, nelem); 1143 llvm::Value *ret = paren_scalar.call (builder, mat, array, nelem);
971 fn->do_return (builder, ret); 1144 fn->do_return (builder, ret);
1145
1146 #ifdef HAVE_GCCJIT
1147 // gcc implementation
1148 {
1149 gccjit::function gf = fn->gccjit_function;
1150 gccjit::block body = gf.new_block ();
1151 gccjit::rvalue array = create_arg_array (*fn, body, 1, types.size ());
1152 jit_type *index = jit_typeinfo::get_index ();
1153 gccjit::rvalue nelem = gccjit_ctxt.new_rvalue (index->to_gccjit (),
1154 (int)types.size () - 1);
1155 gccjit::rvalue mat = gf.get_param (0);
1156 std::vector<gccjit::rvalue> args (3);
1157 args[0] = mat;
1158 args[1] = array;
1159 args[2] = nelem;
1160 gccjit::rvalue ret = paren_scalar.call (gccjit_ctxt, body, args);
1161 body.end_with_return (ret);
1162 }
1163 #endif
1164
972 return fn; 1165 return fn;
973 } 1166 }
974 1167
975 void 1168 void
976 jit_paren_subsref::do_initialize (void) 1169 jit_paren_subsref::do_initialize (void)
979 types[0] = jit_typeinfo::get_matrix (); 1172 types[0] = jit_typeinfo::get_matrix ();
980 types[1] = jit_typeinfo::get_scalar_ptr (); 1173 types[1] = jit_typeinfo::get_scalar_ptr ();
981 types[2] = jit_typeinfo::get_index (); 1174 types[2] = jit_typeinfo::get_index ();
982 1175
983 jit_type *scalar = jit_typeinfo::get_scalar (); 1176 jit_type *scalar = jit_typeinfo::get_scalar ();
984 paren_scalar = jit_function (module, jit_convention::external, 1177 paren_scalar = jit_function (module,
1178 #ifdef HAVE_GCCJIT
1179 gccjit_ctxt,
1180 #endif
1181 jit_convention::external,
985 "octave_jit_paren_scalar", scalar, types); 1182 "octave_jit_paren_scalar", scalar, types);
986 paren_scalar.add_mapping (engine, &octave_jit_paren_scalar); 1183 paren_scalar.add_mapping (engine, &octave_jit_paren_scalar);
987 paren_scalar.mark_can_error (); 1184 paren_scalar.mark_can_error ();
988 } 1185 }
989 1186
993 { 1190 {
994 std::stringstream ss; 1191 std::stringstream ss;
995 ss << "jit_paren_subsasgn_matrix_scalar" << (types.size () - 2); 1192 ss << "jit_paren_subsasgn_matrix_scalar" << (types.size () - 2);
996 1193
997 jit_type *matrix = jit_typeinfo::get_matrix (); 1194 jit_type *matrix = jit_typeinfo::get_matrix ();
998 jit_function *fn = new jit_function (module, jit_convention::internal, 1195 jit_function *fn = new jit_function (module,
1196 #ifdef HAVE_GCCJIT
1197 gccjit_ctxt,
1198 #endif
1199 jit_convention::internal,
999 ss.str (), matrix, types); 1200 ss.str (), matrix, types);
1000 fn->mark_can_error (); 1201 fn->mark_can_error ();
1001 llvm::BasicBlock *body = fn->new_block (); 1202 llvm::BasicBlock *body = fn->new_block ();
1002 llvm::IRBuilder<> builder (body); 1203 llvm::IRBuilder<> builder (body);
1003 1204
1008 1209
1009 llvm::Value *mat = fn->argument (builder, 0); 1210 llvm::Value *mat = fn->argument (builder, 0);
1010 llvm::Value *value = fn->argument (builder, types.size () - 1); 1211 llvm::Value *value = fn->argument (builder, types.size () - 1);
1011 llvm::Value *ret = paren_scalar.call (builder, mat, array, nelem, value); 1212 llvm::Value *ret = paren_scalar.call (builder, mat, array, nelem, value);
1012 fn->do_return (builder, ret); 1213 fn->do_return (builder, ret);
1214
1215 #ifdef HAVE_GCCJIT
1216 {
1217 // FIXME: TODO
1218 gccjit::function gf = fn->gccjit_function;
1219 gccjit::block body = gf.new_block ();
1220 gccjit::rvalue array = create_arg_array (*fn, body, 1, types.size () - 1);
1221 jit_type *index = jit_typeinfo::get_index ();
1222 gccjit::rvalue nelem = gccjit_ctxt.new_rvalue (index->to_gccjit (),
1223 (int)types.size () - 2);
1224 gccjit::rvalue mat = gf.get_param (0);
1225 gccjit::rvalue value = gf.get_param (types.size () - 1);
1226 std::vector<gccjit::rvalue> args(4);
1227 args[0] = mat;
1228 args[1] = array;
1229 args[2] = nelem;
1230 args[3] = value;
1231 gccjit::rvalue ret = paren_scalar.call (gccjit_ctxt, body, args);
1232 body.end_with_return (ret);
1233 }
1234 #endif
1235
1013 return fn; 1236 return fn;
1014 } 1237 }
1015 1238
1016 void 1239 void
1017 jit_paren_subsasgn::do_initialize (void) 1240 jit_paren_subsasgn::do_initialize (void)
1024 types[0] = matrix; 1247 types[0] = matrix;
1025 types[1] = jit_typeinfo::get_scalar_ptr (); 1248 types[1] = jit_typeinfo::get_scalar_ptr ();
1026 types[2] = jit_typeinfo::get_index (); 1249 types[2] = jit_typeinfo::get_index ();
1027 types[3] = jit_typeinfo::get_scalar (); 1250 types[3] = jit_typeinfo::get_scalar ();
1028 1251
1029 paren_scalar = jit_function (module, jit_convention::external, 1252 paren_scalar = jit_function (module,
1253 #ifdef HAVE_GCCJIT
1254 gccjit_ctxt,
1255 #endif
1256 jit_convention::external,
1030 "octave_jit_paren_scalar", matrix, types); 1257 "octave_jit_paren_scalar", matrix, types);
1031 paren_scalar.add_mapping (engine, &octave_jit_paren_scalar_subsasgn); 1258 paren_scalar.add_mapping (engine, &octave_jit_paren_scalar_subsasgn);
1032 paren_scalar.mark_can_error (); 1259 paren_scalar.mark_can_error ();
1033 } 1260 }
1034 1261
1046 : module (m), engine (e), next_id (0), 1273 : module (m), engine (e), next_id (0),
1047 builder (*new llvm::IRBuilderD (context)) 1274 builder (*new llvm::IRBuilderD (context))
1048 { 1275 {
1049 instance = this; 1276 instance = this;
1050 1277
1278 #ifdef HAVE_GCCJIT
1279 gccjit_ctxt = gccjit::context::acquire ();
1280 #endif
1281
1051 // FIXME: We should be registering types like in octave_value_typeinfo 1282 // FIXME: We should be registering types like in octave_value_typeinfo
1283 #ifdef HAVE_LLVM
1052 llvm::Type *any_t = llvm::StructType::create (context, "octave_base_value"); 1284 llvm::Type *any_t = llvm::StructType::create (context, "octave_base_value");
1053 any_t = any_t->getPointerTo (); 1285 any_t = any_t->getPointerTo ();
1054 1286
1055 llvm::Type *scalar_t = llvm::Type::getDoubleTy (context); 1287 llvm::Type *scalar_t = llvm::Type::getDoubleTy (context);
1056 llvm::Type *bool_t = llvm::Type::getInt1Ty (context); 1288 llvm::Type *bool_t = llvm::Type::getInt1Ty (context);
1057 llvm::Type *string_t = llvm::Type::getInt8Ty (context); 1289 llvm::Type *string_t = llvm::Type::getInt8Ty (context);
1058 string_t = string_t->getPointerTo (); 1290 string_t = string_t->getPointerTo ();
1059 llvm::Type *index_t = llvm::Type::getIntNTy (context, 1291 llvm::Type *index_t = llvm::Type::getIntNTy (context,
1060 sizeof(octave_idx_type) * 8); 1292 sizeof(octave_idx_type) * 8);
1061 1293 #endif
1294
1295 #ifdef HAVE_GCCJIT
1296 gccjit::type any_t_gcc =
1297 gccjit_ctxt.new_opaque_struct_type ("octave_base_value");
1298 any_t_gcc = any_t_gcc.get_pointer ();
1299 gccjit::type scalar_t_gcc = gccjit_ctxt.get_type (GCC_JIT_TYPE_DOUBLE);
1300 gccjit::type bool_t_gcc = gccjit_ctxt.get_type (GCC_JIT_TYPE_BOOL);
1301 gccjit::type string_t_gcc =
1302 gccjit_ctxt.get_type (GCC_JIT_TYPE_CHAR).get_pointer ();
1303 gccjit::type index_t_gcc = gccjit_ctxt.get_int_type <octave_idx_type> ();
1304 gccjit::type int_t_gcc = gccjit_ctxt.get_type (GCC_JIT_TYPE_INT);
1305 #endif
1306
1307 #ifdef HAVE_LLVM
1062 llvm::StructType *range_t = llvm::StructType::create (context, "range"); 1308 llvm::StructType *range_t = llvm::StructType::create (context, "range");
1063 std::vector<llvm::Type *> range_contents (4, scalar_t); 1309 std::vector<llvm::Type *> range_contents (4, scalar_t);
1064 range_contents[3] = index_t; 1310 range_contents[3] = index_t;
1065 range_t->setBody (range_contents); 1311 range_t->setBody (range_contents);
1066 1312 #endif
1313 #ifdef HAVE_GCCJIT
1314 field_rng_base = gccjit_ctxt.new_field (scalar_t_gcc, "rng_base");
1315 field_rng_limit = gccjit_ctxt.new_field (scalar_t_gcc, "rng_limit");
1316 field_rng_inc = gccjit_ctxt.new_field (scalar_t_gcc, "rng_inc");
1317 field_rng_nelem = gccjit_ctxt.new_field (index_t_gcc, "rng_nelem");
1318 /* FIXME: what about the "mutable Matrix cache;" */
1319
1320 std::vector<gccjit::field> range_fields (4);
1321 range_fields [0] = field_rng_base;
1322 range_fields [1] = field_rng_limit;
1323 range_fields [2] = field_rng_inc;
1324 range_fields [3] = field_rng_nelem;
1325
1326 gccjit::type range_t_gcc =
1327 gccjit_ctxt.new_struct_type (
1328 "range",
1329 range_fields,
1330 gccjit_ctxt.new_location ("liboctave/array/Range.h", 33, 0));
1331 #endif
1332
1333 #ifdef HAVE_LLVM
1067 llvm::Type *refcount_t = llvm::Type::getIntNTy (context, sizeof(int) * 8); 1334 llvm::Type *refcount_t = llvm::Type::getIntNTy (context, sizeof(int) * 8);
1068 1335 #endif
1336 #ifdef HAVE_GCCJIT
1337 gccjit::type refcount_t_gcc = gccjit_ctxt.get_type (GCC_JIT_TYPE_INT);
1338 #endif
1339
1340 #ifdef HAVE_LLVM
1069 llvm::StructType *matrix_t = llvm::StructType::create (context, "matrix"); 1341 llvm::StructType *matrix_t = llvm::StructType::create (context, "matrix");
1070 llvm::Type *matrix_contents[5]; 1342 llvm::Type *matrix_contents[5];
1071 matrix_contents[0] = refcount_t->getPointerTo (); 1343 matrix_contents[0] = refcount_t->getPointerTo ();
1072 matrix_contents[1] = scalar_t->getPointerTo (); 1344 matrix_contents[1] = scalar_t->getPointerTo ();
1073 matrix_contents[2] = index_t; 1345 matrix_contents[2] = index_t;
1074 matrix_contents[3] = index_t->getPointerTo (); 1346 matrix_contents[3] = index_t->getPointerTo ();
1075 matrix_contents[4] = string_t; 1347 matrix_contents[4] = string_t;
1076 matrix_t->setBody (llvm::makeArrayRef (matrix_contents, 5)); 1348 matrix_t->setBody (llvm::makeArrayRef (matrix_contents, 5));
1077 1349 #endif
1350 #ifdef HAVE_GCCJIT
1351 /*
1352 jit-typeinfo.h has, somewhat ominously:
1353 // jit_array is compatable with the llvm array/matrix structures
1354 typedef jit_array<NDArray, double> jit_matrix;
1355 */
1356 gccjit::type matrix_t_gcc;
1357 {
1358 /* typedef jit_array<NDArray, double> jit_matrix; */
1359 /* template <typename T, typename U> struct jit_array {...}; */
1360 gccjit::type T = string_t_gcc; /* NDArray */
1361 gccjit::type U = scalar_t_gcc; /* double */
1362
1363 /* int *ref_count; */
1364 field_ref_count =
1365 gccjit_ctxt.new_field (refcount_t_gcc.get_pointer (), "ref_count");
1366
1367 /* U *slice_data; */
1368 field_slice_data =
1369 gccjit_ctxt.new_field (U.get_pointer (), "slice_data");
1370
1371 /* octave_idx_type slice_len; */
1372 field_slice_len = gccjit_ctxt.new_field (index_t_gcc, "slice_len");
1373
1374 /* octave_idx_type *dimensions; */
1375 field_dimensions =
1376 gccjit_ctxt.new_field (index_t_gcc.get_pointer (), "dimensions");
1377
1378 /* T *array; */
1379 field_array = gccjit_ctxt.new_field (T.get_pointer (), "array");
1380
1381 std::vector<gccjit::field> matrix_fields (5);
1382 matrix_fields[0] = field_ref_count;
1383 matrix_fields[1] = field_slice_data;
1384 matrix_fields[2] = field_slice_len;
1385 matrix_fields[3] = field_dimensions;
1386 matrix_fields[4] = field_array;
1387
1388 matrix_t_gcc = gccjit_ctxt.new_struct_type (
1389 "jit_matrix",
1390 matrix_fields,
1391 gccjit_ctxt.new_location ("jit-typeinfo.h", 106, 0));
1392 }
1393 #endif
1394
1395 #ifdef HAVE_LLVM
1078 llvm::Type *complex_t = llvm::ArrayType::get (scalar_t, 2); 1396 llvm::Type *complex_t = llvm::ArrayType::get (scalar_t, 2);
1397 #endif
1398 #ifdef HAVE_GCCJIT
1399 gccjit::type complex_t_gcc = gccjit_ctxt.new_array_type (scalar_t_gcc, 2);
1400 #endif
1079 1401
1080 // complex_ret is what is passed to C functions in order to get calling 1402 // complex_ret is what is passed to C functions in order to get calling
1081 // convention right 1403 // convention right
1082 llvm::Type *cmplx_inner_cont[] = {scalar_t, scalar_t}; 1404 llvm::Type *cmplx_inner_cont[] = {scalar_t, scalar_t};
1083 llvm::StructType *cmplx_inner = llvm::StructType::create (cmplx_inner_cont); 1405 llvm::StructType *cmplx_inner = llvm::StructType::create (cmplx_inner_cont);
1087 llvm::Type *contents[] = {cmplx_inner}; 1409 llvm::Type *contents[] = {cmplx_inner};
1088 complex_ret->setBody (contents); 1410 complex_ret->setBody (contents);
1089 } 1411 }
1090 1412
1091 // create types 1413 // create types
1414 #ifdef HAVE_GCCJIT
1415 any = new_type ("any", 0, any_t, any_t_gcc);
1416 matrix = new_type ("matrix", any, matrix_t, matrix_t_gcc);
1417 complex = new_type ("complex", any, complex_t, complex_t_gcc);
1418 scalar = new_type ("scalar", complex, scalar_t, scalar_t_gcc);
1419 scalar_ptr = new_type ("scalar_ptr", 0, scalar_t->getPointerTo (),
1420 scalar_t_gcc.get_pointer ());
1421 any_ptr = new_type ("any_ptr", 0, any_t->getPointerTo (),
1422 any_t_gcc.get_pointer());
1423 range = new_type ("range", any, range_t, range_t_gcc);
1424 string = new_type ("string", any, string_t, string_t_gcc);
1425 boolean = new_type ("bool", any, bool_t, bool_t_gcc);
1426 index = new_type ("index", any, index_t, index_t_gcc);
1427 #else
1092 any = new_type ("any", 0, any_t); 1428 any = new_type ("any", 0, any_t);
1093 matrix = new_type ("matrix", any, matrix_t); 1429 matrix = new_type ("matrix", any, matrix_t);
1094 complex = new_type ("complex", any, complex_t); 1430 complex = new_type ("complex", any, complex_t);
1095 scalar = new_type ("scalar", complex, scalar_t); 1431 scalar = new_type ("scalar", complex, scalar_t);
1096 scalar_ptr = new_type ("scalar_ptr", 0, scalar_t->getPointerTo ()); 1432 scalar_ptr = new_type ("scalar_ptr", 0, scalar_t->getPointerTo ());
1097 any_ptr = new_type ("any_ptr", 0, any_t->getPointerTo ()); 1433 any_ptr = new_type ("any_ptr", 0, any_t->getPointerTo ());
1098 range = new_type ("range", any, range_t); 1434 range = new_type ("range", any, range_t);
1099 string = new_type ("string", any, string_t); 1435 string = new_type ("string", any, string_t);
1100 boolean = new_type ("bool", any, bool_t); 1436 boolean = new_type ("bool", any, bool_t);
1101 index = new_type ("index", any, index_t); 1437 index = new_type ("index", any, index_t);
1438 #endif
1102 1439
1103 create_int (8); 1440 create_int (8);
1104 create_int (16); 1441 create_int (16);
1105 create_int (32); 1442 create_int (32);
1106 create_int (64); 1443 create_int (64);
1122 complex->set_packed_type (jit_convention::external, complex_ret); 1459 complex->set_packed_type (jit_convention::external, complex_ret);
1123 1460
1124 if (sizeof (void *) == 4) 1461 if (sizeof (void *) == 4)
1125 complex->mark_sret (jit_convention::external); 1462 complex->mark_sret (jit_convention::external);
1126 1463
1464 #ifdef HAVE_GCCJIT
1465 paren_subsref_fn.initialize (module, engine, gccjit_ctxt);
1466 paren_subsasgn_fn.initialize (module, engine, gccjit_ctxt);
1467 #else
1127 paren_subsref_fn.initialize (module, engine); 1468 paren_subsref_fn.initialize (module, engine);
1128 paren_subsasgn_fn.initialize (module, engine); 1469 paren_subsasgn_fn.initialize (module, engine);
1470 #endif
1129 1471
1130 // bind global variables 1472 // bind global variables
1473 #ifdef HAVE_LLVM
1131 lerror_state = new llvm::GlobalVariable (*module, bool_t, false, 1474 lerror_state = new llvm::GlobalVariable (*module, bool_t, false,
1132 llvm::GlobalValue::ExternalLinkage, 1475 llvm::GlobalValue::ExternalLinkage,
1133 0, "error_state"); 1476 0, "error_state");
1134 engine->addGlobalMapping (lerror_state, 1477 engine->addGlobalMapping (lerror_state,
1135 reinterpret_cast<void *> (&error_state)); 1478 reinterpret_cast<void *> (&error_state));
1140 = new llvm::GlobalVariable (*module, sig_atomic_type, false, 1483 = new llvm::GlobalVariable (*module, sig_atomic_type, false,
1141 llvm::GlobalValue::ExternalLinkage, 0, 1484 llvm::GlobalValue::ExternalLinkage, 0,
1142 "octave_interrupt_state"); 1485 "octave_interrupt_state");
1143 engine->addGlobalMapping (loctave_interrupt_state, 1486 engine->addGlobalMapping (loctave_interrupt_state,
1144 reinterpret_cast<void *> (&octave_interrupt_state)); 1487 reinterpret_cast<void *> (&octave_interrupt_state));
1488 #endif
1489
1490 #ifdef HAVE_GCCJIT
1491 // Access "error_state" (actually declared as an "int"), by
1492 // taking its address and dereferencing:
1493 error_state_gccjit =
1494 *gccjit_ctxt.new_rvalue (int_t_gcc.get_pointer (),
1495 &error_state);
1496 sig_atomic_type_gccjit = gccjit_ctxt.get_int_type <sig_atomic_t> ();
1497 octave_interrupt_state_gccjit =
1498 *gccjit_ctxt.new_rvalue (
1499 sig_atomic_type_gccjit.get_volatile ().get_pointer (),
1500 &octave_interrupt_state);
1501 #endif
1145 1502
1146 // generic call function 1503 // generic call function
1147 { 1504 {
1148 jit_type *int_t = intN (sizeof (octave_builtin::fcn) * 8); 1505 jit_type *int_t = intN (sizeof (octave_builtin::fcn) * 8);
1149 any_call = create_external (JIT_FN (octave_jit_call), any, int_t, int_t, 1506 any_call = create_external (JIT_FN (octave_jit_call), any, int_t, int_t,
1173 unary_ops[i].stash_name ("unary" + op_name); 1530 unary_ops[i].stash_name ("unary" + op_name);
1174 } 1531 }
1175 1532
1176 for (int op = 0; op < octave_value::num_binary_ops; ++op) 1533 for (int op = 0; op < octave_value::num_binary_ops; ++op)
1177 { 1534 {
1178 llvm::Twine fn_name ("octave_jit_binary_any_any_"); 1535 std::string fn_name ("octave_jit_binary_any_any_");
1179 fn_name = fn_name + llvm::Twine (op); 1536 char buf[64];
1537 snprintf (buf, sizeof(buf), "%i", op);
1538 fn_name = fn_name + std::string (buf);
1180 1539
1181 fn = create_internal (fn_name, any, any, any); 1540 fn = create_internal (fn_name, any, any, any);
1182 fn.mark_can_error (); 1541 fn.mark_can_error ();
1183 llvm::BasicBlock *block = fn.new_block (); 1542 llvm::BasicBlock *block = fn.new_block ();
1184 builder.SetInsertPoint (block); 1543 builder.SetInsertPoint (block);
1187 llvm::Value *op_as_llvm = llvm::ConstantInt::get (llvm_bo_type, op_int); 1546 llvm::Value *op_as_llvm = llvm::ConstantInt::get (llvm_bo_type, op_int);
1188 llvm::Value *ret = any_binary.call (builder, op_as_llvm, 1547 llvm::Value *ret = any_binary.call (builder, op_as_llvm,
1189 fn.argument (builder, 0), 1548 fn.argument (builder, 0),
1190 fn.argument (builder, 1)); 1549 fn.argument (builder, 1));
1191 fn.do_return (builder, ret); 1550 fn.do_return (builder, ret);
1551
1552 #ifdef HAVE_GCCJIT
1553 // gccjit implementation of octave_jit_binary_any_any_*:
1554 gccjit::function gf = fn.gccjit_function;
1555 gccjit::block gccjit_block = gf.new_block ();
1556 gccjit_block.end_with_return (
1557 gccjit_block.add_call (
1558 any_binary.gccjit_function,
1559 gccjit_ctxt.new_rvalue (binary_op_type->to_gccjit (),
1560 op),
1561 gf.get_param (0),
1562 gf.get_param (1)));
1563 #endif
1564
1192 binary_ops[op].add_overload (fn); 1565 binary_ops[op].add_overload (fn);
1193 } 1566 }
1194 1567
1195 // grab matrix 1568 // grab matrix
1196 fn = create_external (JIT_FN (octave_jit_grab_matrix), matrix, matrix); 1569 fn = create_external (JIT_FN (octave_jit_grab_matrix), matrix, matrix);
1218 destroy_fn.add_overload (create_identity(scalar)); 1591 destroy_fn.add_overload (create_identity(scalar));
1219 destroy_fn.add_overload (create_identity(boolean)); 1592 destroy_fn.add_overload (create_identity(boolean));
1220 destroy_fn.add_overload (create_identity(index)); 1593 destroy_fn.add_overload (create_identity(index));
1221 destroy_fn.add_overload (create_identity(complex)); 1594 destroy_fn.add_overload (create_identity(complex));
1222 1595
1223 // -------------------- scalar related operations --------------------
1224
1225 // now for binary scalar operations 1596 // now for binary scalar operations
1597 #ifdef HAVE_GCCJIT
1598 add_binary_op (scalar, octave_value::op_add,
1599 llvm::Instruction::FAdd,
1600 GCC_JIT_BINARY_OP_PLUS);
1601 add_binary_op (scalar, octave_value::op_sub,
1602 llvm::Instruction::FSub,
1603 GCC_JIT_BINARY_OP_MINUS);
1604 add_binary_op (scalar, octave_value::op_mul,
1605 llvm::Instruction::FMul,
1606 GCC_JIT_BINARY_OP_MULT);
1607 add_binary_op (scalar, octave_value::op_el_mul,
1608 llvm::Instruction::FMul,
1609 GCC_JIT_BINARY_OP_MULT);
1610
1611 add_binary_fcmp (scalar, octave_value::op_lt,
1612 llvm::CmpInst::FCMP_ULT,
1613 GCC_JIT_COMPARISON_LT);
1614 add_binary_fcmp (scalar, octave_value::op_le,
1615 llvm::CmpInst::FCMP_ULE,
1616 GCC_JIT_COMPARISON_LE);
1617 add_binary_fcmp (scalar, octave_value::op_eq,
1618 llvm::CmpInst::FCMP_UEQ,
1619 GCC_JIT_COMPARISON_EQ);
1620 add_binary_fcmp (scalar, octave_value::op_ge,
1621 llvm::CmpInst::FCMP_UGE,
1622 GCC_JIT_COMPARISON_GE);
1623 add_binary_fcmp (scalar, octave_value::op_gt,
1624 llvm::CmpInst::FCMP_UGT,
1625 GCC_JIT_COMPARISON_GT);
1626 add_binary_fcmp (scalar, octave_value::op_ne,
1627 llvm::CmpInst::FCMP_UNE,
1628 GCC_JIT_COMPARISON_NE);
1629 #else
1226 add_binary_op (scalar, octave_value::op_add, llvm::Instruction::FAdd); 1630 add_binary_op (scalar, octave_value::op_add, llvm::Instruction::FAdd);
1227 add_binary_op (scalar, octave_value::op_sub, llvm::Instruction::FSub); 1631 add_binary_op (scalar, octave_value::op_sub, llvm::Instruction::FSub);
1228 add_binary_op (scalar, octave_value::op_mul, llvm::Instruction::FMul); 1632 add_binary_op (scalar, octave_value::op_mul, llvm::Instruction::FMul);
1229 add_binary_op (scalar, octave_value::op_el_mul, llvm::Instruction::FMul); 1633 add_binary_op (scalar, octave_value::op_el_mul, llvm::Instruction::FMul);
1230 1634
1232 add_binary_fcmp (scalar, octave_value::op_le, llvm::CmpInst::FCMP_ULE); 1636 add_binary_fcmp (scalar, octave_value::op_le, llvm::CmpInst::FCMP_ULE);
1233 add_binary_fcmp (scalar, octave_value::op_eq, llvm::CmpInst::FCMP_UEQ); 1637 add_binary_fcmp (scalar, octave_value::op_eq, llvm::CmpInst::FCMP_UEQ);
1234 add_binary_fcmp (scalar, octave_value::op_ge, llvm::CmpInst::FCMP_UGE); 1638 add_binary_fcmp (scalar, octave_value::op_ge, llvm::CmpInst::FCMP_UGE);
1235 add_binary_fcmp (scalar, octave_value::op_gt, llvm::CmpInst::FCMP_UGT); 1639 add_binary_fcmp (scalar, octave_value::op_gt, llvm::CmpInst::FCMP_UGT);
1236 add_binary_fcmp (scalar, octave_value::op_ne, llvm::CmpInst::FCMP_UNE); 1640 add_binary_fcmp (scalar, octave_value::op_ne, llvm::CmpInst::FCMP_UNE);
1641 #endif
1237 1642
1238 jit_function gripe_div0 = create_external (JIT_FN (gripe_divide_by_zero), 0); 1643 jit_function gripe_div0 = create_external (JIT_FN (gripe_divide_by_zero), 0);
1239 gripe_div0.mark_can_error (); 1644 gripe_div0.mark_can_error ();
1240 1645
1241 // divide is annoying because it might error 1646 // divide is annoying because it might error
1259 builder.SetInsertPoint (normal_block); 1664 builder.SetInsertPoint (normal_block);
1260 llvm::Value *ret = builder.CreateFDiv (fn.argument (builder, 0), 1665 llvm::Value *ret = builder.CreateFDiv (fn.argument (builder, 0),
1261 fn.argument (builder, 1)); 1666 fn.argument (builder, 1));
1262 fn.do_return (builder, ret); 1667 fn.do_return (builder, ret);
1263 } 1668 }
1669
1670 // gccjit implementation of octave_jit_div_scalar_scalar:
1671 #ifdef HAVE_GCCJIT
1672 {
1673 gccjit::function gf = fn.gccjit_function;
1674 gccjit::block initial_block = gf.new_block ("initial");
1675 gccjit::block warn_block = gf.new_block ("warn");
1676 gccjit::block normal_block = gf.new_block ("normal");
1677 initial_block.end_with_conditional (
1678 gf.get_param (1) != scalar_t_gcc.zero (),
1679 normal_block, // on_true
1680 warn_block); // on_false
1681
1682 warn_block.add_call (gripe_div0.gccjit_function);
1683 warn_block.end_with_jump (normal_block);
1684
1685 normal_block.end_with_return (gf.get_param (0) / gf.get_param (1));
1686 }
1687 #endif
1264 binary_ops[octave_value::op_div].add_overload (fn); 1688 binary_ops[octave_value::op_div].add_overload (fn);
1265 binary_ops[octave_value::op_el_div].add_overload (fn); 1689 binary_ops[octave_value::op_el_div].add_overload (fn);
1266 1690
1267 // ldiv is the same as div with the operators reversed 1691 // ldiv is the same as div with the operators reversed
1268 fn = mirror_binary (fn); 1692 fn = mirror_binary (fn);
1277 binary_ops[octave_value::op_pow].add_overload (fn); 1701 binary_ops[octave_value::op_pow].add_overload (fn);
1278 binary_ops[octave_value::op_el_pow].add_overload (fn); 1702 binary_ops[octave_value::op_el_pow].add_overload (fn);
1279 1703
1280 // now for unary scalar operations 1704 // now for unary scalar operations
1281 // FIXME: Impelment not 1705 // FIXME: Impelment not
1282 fn = create_internal ("octave_jit_++", scalar, scalar); 1706 fn = create_internal ("octave_jit_plusplus", scalar, scalar);
1283 body = fn.new_block (); 1707 body = fn.new_block ();
1284 builder.SetInsertPoint (body); 1708 builder.SetInsertPoint (body);
1285 { 1709 {
1286 llvm::Value *one = llvm::ConstantFP::get (scalar_t, 1); 1710 llvm::Value *one = llvm::ConstantFP::get (scalar_t, 1);
1287 llvm::Value *val = fn.argument (builder, 0); 1711 llvm::Value *val = fn.argument (builder, 0);
1288 val = builder.CreateFAdd (val, one); 1712 val = builder.CreateFAdd (val, one);
1289 fn.do_return (builder, val); 1713 fn.do_return (builder, val);
1290 } 1714 }
1715 // gccjit implementation of octave_jit_plusplus:
1716 #ifdef HAVE_GCCJIT
1717 {
1718 gccjit::function gf = fn.gccjit_function;
1719 gccjit::block b = gf.new_block ();
1720 b.end_with_return (gf.get_param (0) + scalar_t_gcc.one ());
1721 }
1722 #endif
1291 unary_ops[octave_value::op_incr].add_overload (fn); 1723 unary_ops[octave_value::op_incr].add_overload (fn);
1292 1724
1293 fn = create_internal ("octave_jit_--", scalar, scalar); 1725 fn = create_internal ("octave_jit_minusminus", scalar, scalar);
1294 body = fn.new_block (); 1726 body = fn.new_block ();
1295 builder.SetInsertPoint (body); 1727 builder.SetInsertPoint (body);
1296 { 1728 {
1297 llvm::Value *one = llvm::ConstantFP::get (scalar_t, 1); 1729 llvm::Value *one = llvm::ConstantFP::get (scalar_t, 1);
1298 llvm::Value *val = fn.argument (builder, 0); 1730 llvm::Value *val = fn.argument (builder, 0);
1299 val = builder.CreateFSub (val, one); 1731 val = builder.CreateFSub (val, one);
1300 fn.do_return (builder, val); 1732 fn.do_return (builder, val);
1301 } 1733
1734 // gccjit implementation of octave_jit_minusminus:
1735 #ifdef HAVE_GCCJIT
1736 gccjit::function gf = fn.gccjit_function;
1737 gccjit::block b = gf.new_block ();
1738 b.end_with_return (gf.get_param (0) - scalar_t_gcc.one ());
1739 #endif
1740 }
1741
1302 unary_ops[octave_value::op_decr].add_overload (fn); 1742 unary_ops[octave_value::op_decr].add_overload (fn);
1303 1743
1304 fn = create_internal ("octave_jit_uminus", scalar, scalar); 1744 fn = create_internal ("octave_jit_uminus", scalar, scalar);
1305 body = fn.new_block (); 1745 body = fn.new_block ();
1306 builder.SetInsertPoint (body); 1746 builder.SetInsertPoint (body);
1308 llvm::Value *mone = llvm::ConstantFP::get (scalar_t, -1); 1748 llvm::Value *mone = llvm::ConstantFP::get (scalar_t, -1);
1309 llvm::Value *val = fn.argument (builder, 0); 1749 llvm::Value *val = fn.argument (builder, 0);
1310 val = builder.CreateFMul (val, mone); 1750 val = builder.CreateFMul (val, mone);
1311 fn.do_return (builder, val); 1751 fn.do_return (builder, val);
1312 } 1752 }
1313 unary_ops[octave_value::op_uminus].add_overload (fn); 1753 // gccjit implementation of octave_jit_uminus:
1754 #ifdef HAVE_GCCJIT
1755 {
1756 gccjit::function gf = fn.gccjit_function;
1757 gccjit::block b = gf.new_block ();
1758 b.end_with_return (-gf.get_param (0));
1759 }
1760 #endif
1314 1761
1315 fn = create_identity (scalar); 1762 fn = create_identity (scalar);
1316 unary_ops[octave_value::op_uplus].add_overload (fn); 1763 unary_ops[octave_value::op_uplus].add_overload (fn);
1317 unary_ops[octave_value::op_transpose].add_overload (fn); 1764 unary_ops[octave_value::op_transpose].add_overload (fn);
1318 unary_ops[octave_value::op_hermitian].add_overload (fn); 1765 unary_ops[octave_value::op_hermitian].add_overload (fn);
1319 1766
1320 // now for binary complex operations 1767 // now for binary complex operations
1321 fn = create_internal ("octave_jit_+_complex_complex", complex, complex, 1768 fn = create_internal ("octave_jit_plus_complex_complex", complex, complex,
1322 complex); 1769 complex);
1323 body = fn.new_block (); 1770 body = fn.new_block ();
1324 builder.SetInsertPoint (body); 1771 builder.SetInsertPoint (body);
1325 { 1772 {
1326 llvm::Value *lhs = fn.argument (builder, 0); 1773 llvm::Value *lhs = fn.argument (builder, 0);
1329 complex_real (rhs)); 1776 complex_real (rhs));
1330 llvm::Value *imag = builder.CreateFAdd (complex_imag (lhs), 1777 llvm::Value *imag = builder.CreateFAdd (complex_imag (lhs),
1331 complex_imag (rhs)); 1778 complex_imag (rhs));
1332 fn.do_return (builder, complex_new (real, imag)); 1779 fn.do_return (builder, complex_new (real, imag));
1333 } 1780 }
1781 // gccjit implementation of octave_jit_plus_complex_complex:
1782 #ifdef HAVE_GCCJIT
1783 {
1784 gccjit::function gf = fn.gccjit_function;
1785 gccjit::block b = gf.new_block ();
1786 gccjit::rvalue lhs = gf.get_param (0);
1787 gccjit::rvalue rhs = gf.get_param (1);
1788 gccjit::rvalue real = complex_real (lhs) + complex_real (rhs);
1789 gccjit::rvalue imag = complex_imag (lhs) + complex_imag (rhs);
1790 b.end_with_return (complex_new (b, real, imag));
1791 }
1792 #endif
1334 binary_ops[octave_value::op_add].add_overload (fn); 1793 binary_ops[octave_value::op_add].add_overload (fn);
1335 1794
1336 fn = create_internal ("octave_jit_-_complex_complex", complex, complex, 1795 fn = create_internal ("octave_jit_minus_complex_complex", complex, complex,
1337 complex); 1796 complex);
1338 body = fn.new_block (); 1797 body = fn.new_block ();
1339 builder.SetInsertPoint (body); 1798 builder.SetInsertPoint (body);
1340 { 1799 {
1341 llvm::Value *lhs = fn.argument (builder, 0); 1800 llvm::Value *lhs = fn.argument (builder, 0);
1344 complex_real (rhs)); 1803 complex_real (rhs));
1345 llvm::Value *imag = builder.CreateFSub (complex_imag (lhs), 1804 llvm::Value *imag = builder.CreateFSub (complex_imag (lhs),
1346 complex_imag (rhs)); 1805 complex_imag (rhs));
1347 fn.do_return (builder, complex_new (real, imag)); 1806 fn.do_return (builder, complex_new (real, imag));
1348 } 1807 }
1808 // gccjit implementation of octave_jit_minus_complex_complex:
1809 #ifdef HAVE_GCCJIT
1810 {
1811 gccjit::function gf = fn.gccjit_function;
1812 gccjit::block b = gf.new_block ();
1813 gccjit::rvalue lhs = gf.get_param (0);
1814 gccjit::rvalue rhs = gf.get_param (1);
1815 gccjit::rvalue real = complex_real (lhs) - complex_real (rhs);
1816 gccjit::rvalue imag = complex_imag (lhs) - complex_imag (rhs);
1817 b.end_with_return (complex_new (b, real, imag));
1818 }
1819 #endif
1349 binary_ops[octave_value::op_sub].add_overload (fn); 1820 binary_ops[octave_value::op_sub].add_overload (fn);
1350 1821
1351 fn = create_external (JIT_FN (octave_jit_complex_mul), 1822 fn = create_external (JIT_FN (octave_jit_complex_mul),
1352 complex, complex, complex); 1823 complex, complex, complex);
1353 binary_ops[octave_value::op_mul].add_overload (fn); 1824 binary_ops[octave_value::op_mul].add_overload (fn);
1362 fn = create_external (JIT_FN (octave_jit_pow_complex_complex), complex, 1833 fn = create_external (JIT_FN (octave_jit_pow_complex_complex), complex,
1363 complex, complex); 1834 complex, complex);
1364 binary_ops[octave_value::op_pow].add_overload (fn); 1835 binary_ops[octave_value::op_pow].add_overload (fn);
1365 binary_ops[octave_value::op_el_pow].add_overload (fn); 1836 binary_ops[octave_value::op_el_pow].add_overload (fn);
1366 1837
1367 fn = create_internal ("octave_jit_*_scalar_complex", complex, scalar, 1838 fn = create_internal ("octave_jit_mult_scalar_complex", complex, scalar,
1368 complex); 1839 complex);
1369 jit_function mul_scalar_complex = fn; 1840 jit_function mul_scalar_complex = fn;
1370 body = fn.new_block (); 1841 body = fn.new_block ();
1371 builder.SetInsertPoint (body); 1842 builder.SetInsertPoint (body);
1372 { 1843 {
1389 builder.SetInsertPoint (complex_mul); 1860 builder.SetInsertPoint (complex_mul);
1390 temp = complex_new (builder.CreateFMul (lhs, complex_real (rhs)), 1861 temp = complex_new (builder.CreateFMul (lhs, complex_real (rhs)),
1391 builder.CreateFMul (lhs, complex_imag (rhs))); 1862 builder.CreateFMul (lhs, complex_imag (rhs)));
1392 fn.do_return (builder, temp); 1863 fn.do_return (builder, temp);
1393 } 1864 }
1865 // gccjit implementation of octave_jit_mult_scalar_complex:
1866 #ifdef HAVE_GCCJIT
1867 {
1868 gccjit::function gf = fn.gccjit_function;
1869
1870 gccjit::rvalue fzero = scalar_t_gcc.zero ();
1871 gccjit::rvalue lhs = gf.get_param (0);
1872 gccjit::rvalue rhs = gf.get_param (1);
1873
1874 gccjit::block initial = gf.new_block ("initial");
1875 gccjit::block complex_mul = gf.new_block ("complex_mul");
1876 gccjit::block scalar_mul = gf.new_block ("scalar_mul");
1877
1878 initial.end_with_conditional (complex_imag (rhs) == fzero,
1879 scalar_mul,
1880 complex_mul);
1881
1882 scalar_mul.end_with_return (complex_new (scalar_mul,
1883 lhs * complex_real (rhs),
1884 fzero));
1885 complex_mul.end_with_return (complex_new (complex_mul,
1886 lhs * complex_real (rhs),
1887 lhs * complex_imag (rhs)));
1888 }
1889 #endif
1394 binary_ops[octave_value::op_mul].add_overload (fn); 1890 binary_ops[octave_value::op_mul].add_overload (fn);
1395 binary_ops[octave_value::op_el_mul].add_overload (fn); 1891 binary_ops[octave_value::op_el_mul].add_overload (fn);
1396 1892
1397 1893
1398 fn = mirror_binary (mul_scalar_complex); 1894 fn = mirror_binary (mul_scalar_complex);
1399 binary_ops[octave_value::op_mul].add_overload (fn); 1895 binary_ops[octave_value::op_mul].add_overload (fn);
1400 binary_ops[octave_value::op_el_mul].add_overload (fn); 1896 binary_ops[octave_value::op_el_mul].add_overload (fn);
1401 1897
1402 fn = create_internal ("octave_jit_+_scalar_complex", complex, scalar, 1898 fn = create_internal ("octave_jit_plus_scalar_complex", complex, scalar,
1403 complex); 1899 complex);
1404 body = fn.new_block (); 1900 body = fn.new_block ();
1405 builder.SetInsertPoint (body); 1901 builder.SetInsertPoint (body);
1406 { 1902 {
1407 llvm::Value *lhs = fn.argument (builder, 0); 1903 llvm::Value *lhs = fn.argument (builder, 0);
1408 llvm::Value *rhs = fn.argument (builder, 1); 1904 llvm::Value *rhs = fn.argument (builder, 1);
1409 llvm::Value *real = builder.CreateFAdd (lhs, complex_real (rhs)); 1905 llvm::Value *real = builder.CreateFAdd (lhs, complex_real (rhs));
1410 fn.do_return (builder, complex_real (rhs, real)); 1906 fn.do_return (builder, complex_real (rhs, real));
1411 } 1907 }
1908 // gccjit implementation of octave_jit_plus_scalar_complex:
1909 #ifdef HAVE_GCCJIT
1910 {
1911 gccjit::function gf = fn.gccjit_function;
1912 gccjit::block b = gf.new_block ();
1913 gccjit::rvalue lhs = gf.get_param (0);
1914 gccjit::lvalue rhs = gf.get_param (1);
1915 gccjit::rvalue real = lhs + complex_real (rhs);
1916 b.end_with_return (complex_real (b, rhs, real));
1917 }
1918 #endif
1412 binary_ops[octave_value::op_add].add_overload (fn); 1919 binary_ops[octave_value::op_add].add_overload (fn);
1413 1920
1414 fn = mirror_binary (fn); 1921 fn = mirror_binary (fn);
1415 binary_ops[octave_value::op_add].add_overload (fn); 1922 binary_ops[octave_value::op_add].add_overload (fn);
1416 1923
1417 fn = create_internal ("octave_jit_-_complex_scalar", complex, complex, 1924 fn = create_internal ("octave_jit_minus_complex_scalar", complex, complex,
1418 scalar); 1925 scalar);
1419 body = fn.new_block (); 1926 body = fn.new_block ();
1420 builder.SetInsertPoint (body); 1927 builder.SetInsertPoint (body);
1421 { 1928 {
1422 llvm::Value *lhs = fn.argument (builder, 0); 1929 llvm::Value *lhs = fn.argument (builder, 0);
1423 llvm::Value *rhs = fn.argument (builder, 1); 1930 llvm::Value *rhs = fn.argument (builder, 1);
1424 llvm::Value *real = builder.CreateFSub (complex_real (lhs), rhs); 1931 llvm::Value *real = builder.CreateFSub (complex_real (lhs), rhs);
1425 fn.do_return (builder, complex_real (lhs, real)); 1932 fn.do_return (builder, complex_real (lhs, real));
1426 } 1933 }
1934 // gccjit implementation of octave_jit_minus_complex_scalar:
1935 #ifdef HAVE_GCCJIT
1936 {
1937 gccjit::function gf = fn.gccjit_function;
1938 gccjit::block b = gf.new_block ();
1939 gccjit::lvalue lhs = gf.get_param (0);
1940 gccjit::rvalue rhs = gf.get_param (1);
1941 gccjit::rvalue real = complex_real (lhs) - rhs;
1942 b.end_with_return (complex_real (b, lhs, real));
1943 }
1944 #endif
1427 binary_ops[octave_value::op_sub].add_overload (fn); 1945 binary_ops[octave_value::op_sub].add_overload (fn);
1428 1946
1429 fn = create_internal ("octave_jit_-_scalar_complex", complex, scalar, 1947 fn = create_internal ("octave_jit_minus_scalar_complex", complex, scalar,
1430 complex); 1948 complex);
1431 body = fn.new_block (); 1949 body = fn.new_block ();
1432 builder.SetInsertPoint (body); 1950 builder.SetInsertPoint (body);
1433 { 1951 {
1434 llvm::Value *lhs = fn.argument (builder, 0); 1952 llvm::Value *lhs = fn.argument (builder, 0);
1435 llvm::Value *rhs = fn.argument (builder, 1); 1953 llvm::Value *rhs = fn.argument (builder, 1);
1436 llvm::Value *real = builder.CreateFSub (lhs, complex_real (rhs)); 1954 llvm::Value *real = builder.CreateFSub (lhs, complex_real (rhs));
1437 fn.do_return (builder, complex_real (rhs, real)); 1955 fn.do_return (builder, complex_real (rhs, real));
1438 } 1956 }
1957 // gccjit implementation of octave_jit_minus_scalar_complex:
1958 #ifdef HAVE_GCCJIT
1959 {
1960 gccjit::function gf = fn.gccjit_function;
1961 gccjit::block b = gf.new_block ();
1962 gccjit::rvalue lhs = gf.get_param (0);
1963 gccjit::lvalue rhs = gf.get_param (1);
1964 gccjit::rvalue real = lhs - complex_real (rhs);
1965 b.end_with_return (complex_real (b, rhs, real));
1966 }
1967 #endif
1439 binary_ops[octave_value::op_sub].add_overload (fn); 1968 binary_ops[octave_value::op_sub].add_overload (fn);
1440 1969
1441 fn = create_external (JIT_FN (octave_jit_pow_scalar_complex), complex, scalar, 1970 fn = create_external (JIT_FN (octave_jit_pow_scalar_complex), complex, scalar,
1442 complex); 1971 complex);
1443 binary_ops[octave_value::op_pow].add_overload (fn); 1972 binary_ops[octave_value::op_pow].add_overload (fn);
1447 complex, scalar); 1976 complex, scalar);
1448 binary_ops[octave_value::op_pow].add_overload (fn); 1977 binary_ops[octave_value::op_pow].add_overload (fn);
1449 binary_ops[octave_value::op_el_pow].add_overload (fn); 1978 binary_ops[octave_value::op_el_pow].add_overload (fn);
1450 1979
1451 // now for binary index operators 1980 // now for binary index operators
1981 #ifdef HAVE_GCCJIT
1982 add_binary_op (index, octave_value::op_add,
1983 llvm::Instruction::Add,
1984 GCC_JIT_BINARY_OP_PLUS);
1985
1986 // and binary bool operators
1987 add_binary_op (boolean, octave_value::op_el_or,
1988 llvm::Instruction::Or,
1989 GCC_JIT_BINARY_OP_LOGICAL_OR);
1990 add_binary_op (boolean, octave_value::op_el_and,
1991 llvm::Instruction::And,
1992 GCC_JIT_BINARY_OP_LOGICAL_AND);
1993 #else
1452 add_binary_op (index, octave_value::op_add, llvm::Instruction::Add); 1994 add_binary_op (index, octave_value::op_add, llvm::Instruction::Add);
1453 1995
1454 // and binary bool operators 1996 // and binary bool operators
1455 add_binary_op (boolean, octave_value::op_el_or, llvm::Instruction::Or); 1997 add_binary_op (boolean, octave_value::op_el_or, llvm::Instruction::Or);
1456 add_binary_op (boolean, octave_value::op_el_and, llvm::Instruction::And); 1998 add_binary_op (boolean, octave_value::op_el_and, llvm::Instruction::And);
1999 #endif
1457 2000
1458 // now for printing functions 2001 // now for printing functions
1459 print_fn.stash_name ("print"); 2002 print_fn.stash_name ("print");
1460 add_print (any, reinterpret_cast<void *> (&octave_jit_print_any)); 2003 add_print (any, reinterpret_cast<void *> (&octave_jit_print_any));
1461 add_print (scalar, reinterpret_cast<void *> (&octave_jit_print_scalar)); 2004 add_print (scalar, reinterpret_cast<void *> (&octave_jit_print_scalar));
1468 builder.SetInsertPoint (body); 2011 builder.SetInsertPoint (body);
1469 { 2012 {
1470 llvm::Value *zero = llvm::ConstantInt::get (index_t, 0); 2013 llvm::Value *zero = llvm::ConstantInt::get (index_t, 0);
1471 fn.do_return (builder, zero); 2014 fn.do_return (builder, zero);
1472 } 2015 }
2016 #ifdef HAVE_GCCJIT
2017 {
2018 gccjit::function gf = fn.gccjit_function;
2019 gccjit::block b = gf.new_block ();
2020 b.end_with_return (gccjit_ctxt.zero (index_t_gcc));
2021 }
2022 #endif
1473 for_init_fn.add_overload (fn); 2023 for_init_fn.add_overload (fn);
1474 2024
1475 // bounds check for for loop 2025 // bounds check for for loop
1476 for_check_fn.stash_name ("for_check"); 2026 for_check_fn.stash_name ("for_check");
1477 2027
1482 llvm::Value *nelem 2032 llvm::Value *nelem
1483 = builder.CreateExtractValue (fn.argument (builder, 0), 3); 2033 = builder.CreateExtractValue (fn.argument (builder, 0), 3);
1484 llvm::Value *idx = fn.argument (builder, 1); 2034 llvm::Value *idx = fn.argument (builder, 1);
1485 llvm::Value *ret = builder.CreateICmpULT (idx, nelem); 2035 llvm::Value *ret = builder.CreateICmpULT (idx, nelem);
1486 fn.do_return (builder, ret); 2036 fn.do_return (builder, ret);
1487 } 2037
2038 }
2039 #ifdef HAVE_GCCJIT
2040 {
2041 gccjit::function gf = fn.gccjit_function;
2042 // FIXME: is "range" a (struct range) or a (struct range *) ?
2043 gccjit::rvalue nelem
2044 = gf.get_param (0).access_field (field_rng_nelem);
2045 gccjit::rvalue idx = gf.get_param (1);
2046 gccjit::rvalue ret = idx < nelem;
2047 gccjit::block b = gf.new_block ();
2048 b.end_with_return (ret);
2049 }
2050 #endif
1488 for_check_fn.add_overload (fn); 2051 for_check_fn.add_overload (fn);
1489 2052
1490 // index variabe for for loop 2053 // index variabe for for loop
1491 for_index_fn.stash_name ("for_index"); 2054 for_index_fn.stash_name ("for_index");
1492 2055
1502 2065
1503 llvm::Value *ret = builder.CreateFMul (didx, inc); 2066 llvm::Value *ret = builder.CreateFMul (didx, inc);
1504 ret = builder.CreateFAdd (base, ret); 2067 ret = builder.CreateFAdd (base, ret);
1505 fn.do_return (builder, ret); 2068 fn.do_return (builder, ret);
1506 } 2069 }
2070 #ifdef HAVE_GCCJIT
2071 {
2072 gccjit::function gf = fn.gccjit_function;
2073 gccjit::block b = gf.new_block ();
2074 gccjit::rvalue idx = gf.get_param (1);
2075 gccjit::rvalue didx = idx.cast_to (scalar_t_gcc);
2076 gccjit::rvalue rng = gf.get_param (0);
2077 gccjit::rvalue base = rng.access_field (field_rng_base);
2078 gccjit::rvalue inc = rng.access_field (field_rng_inc);
2079 gccjit::rvalue ret = didx * inc;
2080 ret = base + ret;
2081 b.end_with_return (ret);
2082 }
2083 #endif
1507 for_index_fn.add_overload (fn); 2084 for_index_fn.add_overload (fn);
1508 2085
1509 // logically true 2086 // logically true
1510 logically_true_fn.stash_name ("logically_true"); 2087 logically_true_fn.stash_name ("logically_true");
1511 2088
1533 2110
1534 llvm::Value *zero = llvm::ConstantFP::get (scalar_t, 0); 2111 llvm::Value *zero = llvm::ConstantFP::get (scalar_t, 0);
1535 llvm::Value *ret = builder.CreateFCmpONE (fn.argument (builder, 0), zero); 2112 llvm::Value *ret = builder.CreateFCmpONE (fn.argument (builder, 0), zero);
1536 fn.do_return (builder, ret); 2113 fn.do_return (builder, ret);
1537 } 2114 }
2115 #ifdef HAVE_GCCJIT
2116 {
2117 gccjit::function gf = fn.gccjit_function;
2118 gccjit::block initial = gf.new_block ("initial");
2119 gccjit::block error = gf.new_block ("error");
2120 gccjit::block normal = gf.new_block ("normal");
2121 initial.add_comment ("check for NaN");
2122 initial.end_with_conditional (gf.get_param (0) != gf.get_param (0),
2123 error, normal);
2124
2125 error.add_call (gripe_nantl.gccjit_function);
2126 error.end_with_jump (normal);
2127
2128 normal.end_with_return ( gf.get_param (0) != scalar_t_gcc.zero ());
2129 }
2130 #endif
1538 logically_true_fn.add_overload (fn); 2131 logically_true_fn.add_overload (fn);
1539 2132
1540 // logically_true boolean 2133 // logically_true boolean
1541 fn = create_identity (boolean); 2134 fn = create_identity (boolean);
1542 logically_true_fn.add_overload (fn); 2135 logically_true_fn.add_overload (fn);
1566 rng = builder.CreateInsertValue (rng, limit, 1); 2159 rng = builder.CreateInsertValue (rng, limit, 1);
1567 rng = builder.CreateInsertValue (rng, inc, 2); 2160 rng = builder.CreateInsertValue (rng, inc, 2);
1568 rng = builder.CreateInsertValue (rng, nelem, 3); 2161 rng = builder.CreateInsertValue (rng, nelem, 3);
1569 fn.do_return (builder, rng); 2162 fn.do_return (builder, rng);
1570 } 2163 }
2164 #ifdef HAVE_GCCJIT
2165 {
2166 gccjit::function gf = fn.gccjit_function;
2167 gccjit::rvalue base = gf.get_param (0);
2168 gccjit::rvalue limit = gf.get_param (1);
2169 gccjit::rvalue inc = gf.get_param (2);
2170 gccjit::block b = gf.new_block ();
2171 gccjit::rvalue nelem = compute_nelem.gccjit_function (base, limit, inc);
2172 gccjit::lvalue rng = gf.new_local (range_t_gcc, "rng");
2173 b.add_assignment (rng.access_field (field_rng_base), base);
2174 b.add_assignment (rng.access_field (field_rng_limit), limit);
2175 b.add_assignment (rng.access_field (field_rng_inc), inc);
2176 b.add_assignment (rng.access_field (field_rng_nelem), nelem);
2177 b.end_with_return (rng);
2178 }
2179 #endif
1571 make_range_fn.add_overload (fn); 2180 make_range_fn.add_overload (fn);
1572 2181
1573 // paren_subsref 2182 // paren_subsref
1574 jit_type *jit_int = intN (sizeof (int) * 8); 2183 jit_type *jit_int = intN (sizeof (int) * 8);
1575 llvm::Type *int_t = jit_int->to_llvm (); 2184 llvm::Type *int_t = jit_int->to_llvm ();
1577 = create_external (JIT_FN (octave_jit_ginvalid_index), 0); 2186 = create_external (JIT_FN (octave_jit_ginvalid_index), 0);
1578 jit_function gindex_range = create_external (JIT_FN (octave_jit_gindex_range), 2187 jit_function gindex_range = create_external (JIT_FN (octave_jit_gindex_range),
1579 0, jit_int, jit_int, index, 2188 0, jit_int, jit_int, index,
1580 index); 2189 index);
1581 2190
1582 fn = create_internal ("()subsref", scalar, matrix, scalar); 2191 fn = create_internal ("subsref", scalar, matrix, scalar);
1583 fn.mark_can_error (); 2192 fn.mark_can_error ();
1584 2193
1585 body = fn.new_block (); 2194 body = fn.new_block ();
1586 builder.SetInsertPoint (body); 2195 builder.SetInsertPoint (body);
1587 { 2196 {
1636 merge->addIncoming (undef, conv_error); 2245 merge->addIncoming (undef, conv_error);
1637 merge->addIncoming (undef, bounds_error); 2246 merge->addIncoming (undef, bounds_error);
1638 merge->addIncoming (ret, success); 2247 merge->addIncoming (ret, success);
1639 fn.do_return (builder, merge); 2248 fn.do_return (builder, merge);
1640 } 2249 }
2250 // gccjit implementation of subsref:
2251 #ifdef HAVE_GCCJIT
2252 {
2253 gccjit::function gf = fn.gccjit_function;
2254 gccjit::block initial = gf.new_block ("initial");
2255
2256 gccjit::rvalue one_idx = index_t_gcc.one ();
2257 gccjit::rvalue one_int = jit_int->to_gccjit ().one ();
2258
2259 gccjit::rvalue mat = gf.get_param (0);
2260 gccjit::rvalue idx = gf.get_param (1); // scalar
2261
2262 // convert index to scalar to integer, and check index >= 1
2263 gccjit::rvalue int_idx = idx.cast_to (index_t_gcc);
2264 gccjit::rvalue check_idx = int_idx.cast_to (scalar_t_gcc);
2265 gccjit::rvalue cond0 = (idx != check_idx);
2266 gccjit::rvalue cond1 = (int_idx < one_idx);
2267
2268 gccjit::block conv_error = gf.new_block ("conv_error");
2269 gccjit::block normal = gf.new_block ("normal");
2270 initial.end_with_conditional (cond0 || cond1, conv_error, normal);
2271
2272 // "conv_error" block:
2273 conv_error.add_call (ginvalid_index.gccjit_function);
2274 conv_error.end_with_return (scalar_t_gcc.zero ()); // dummy value
2275
2276 // "normal" block:
2277 gccjit::rvalue len = mat.access_field (field_slice_len);
2278 gccjit::rvalue cond = (int_idx > len);
2279 gccjit::block bounds_error = gf.new_block ("bounds_error");
2280 gccjit::block success = gf.new_block ("success");
2281 normal.end_with_conditional (cond, bounds_error, success);
2282
2283 // "bounds_error" block:
2284 bounds_error.add_call (gindex_range.gccjit_function,
2285 one_int, one_int, int_idx, len);
2286 bounds_error.end_with_return (scalar_t_gcc.zero ()); // dummy value
2287
2288 // "success" block:
2289 gccjit::rvalue data = mat.access_field (field_slice_data);
2290 gccjit::rvalue gep = data[int_idx];
2291 gccjit::rvalue ret = gep;
2292 success.end_with_return (ret);
2293 }
2294 #endif
1641 paren_subsref_fn.add_overload (fn); 2295 paren_subsref_fn.add_overload (fn);
1642 2296
1643 // paren subsasgn 2297 // paren subsasgn
1644 paren_subsasgn_fn.stash_name ("()subsasgn"); 2298 paren_subsasgn_fn.stash_name ("subsasgn");
1645 2299
1646 jit_function resize_paren_subsasgn 2300 jit_function resize_paren_subsasgn
1647 = create_external (JIT_FN (octave_jit_paren_subsasgn_impl), matrix, matrix, 2301 = create_external (JIT_FN (octave_jit_paren_subsasgn_impl), matrix, matrix,
1648 index, scalar); 2302 index, scalar);
1649 2303
1708 merge->addIncoming (mat, conv_error); 2362 merge->addIncoming (mat, conv_error);
1709 merge->addIncoming (resize_result, bounds_error); 2363 merge->addIncoming (resize_result, bounds_error);
1710 merge->addIncoming (mat, success); 2364 merge->addIncoming (mat, success);
1711 fn.do_return (builder, merge); 2365 fn.do_return (builder, merge);
1712 } 2366 }
2367 // gccjit implementation of octave_jit_paren_subsasgn:
2368 #ifdef HAVE_GCCJIT
2369 {
2370 gccjit::function gf = fn.gccjit_function;
2371 gccjit::block initial = gf.new_block ("initial");
2372 gccjit::rvalue one_idx = index_t_gcc.one ();
2373 gccjit::rvalue one_int = jit_int->to_gccjit ().one ();
2374
2375 gccjit::lvalue mat = gf.get_param (0);
2376 gccjit::rvalue idx = gf.get_param (1);
2377 gccjit::rvalue value = gf.get_param (2);
2378 gccjit::rvalue int_idx = idx.cast_to (index_t_gcc);
2379 gccjit::rvalue check_idx = int_idx.cast_to (scalar_t_gcc);
2380 gccjit::rvalue cond0 = (idx != check_idx);
2381 gccjit::rvalue cond1 = (int_idx < one_idx);
2382 gccjit::rvalue cond = (cond0 || cond1);
2383
2384 gccjit::block conv_error = gf.new_block ("conv_error");
2385 gccjit::block normal = gf.new_block ("normal");
2386 initial.end_with_conditional (cond, conv_error, normal);
2387
2388 // block: conv_error
2389 conv_error.add_call (ginvalid_index.gccjit_function);
2390 conv_error.end_with_return (mat);
2391
2392 // block: normal
2393 gccjit::rvalue len = mat.access_field (field_slice_len);
2394 cond0 = (int_idx > len);
2395
2396 gccjit::rvalue rcount = mat.access_field (field_ref_count);
2397 rcount = rcount.dereference ();
2398 cond1 = rcount > one_int;
2399 cond = (cond0 || cond1);
2400
2401 gccjit::block bounds_error = gf.new_block ("bounds_error");
2402 gccjit::block success = gf.new_block ("success");
2403 normal.end_with_conditional (cond, bounds_error, success);
2404
2405 // block: bounds_error
2406 // resize on out of bounds access
2407 std::vector<gccjit::rvalue> args (3);
2408 args[0] = mat;
2409 args[1] = int_idx;
2410 args[2] = value;
2411 gccjit::rvalue resize_result =
2412 resize_paren_subsasgn.call (gccjit_ctxt, bounds_error, args);
2413 bounds_error.end_with_return (resize_result);
2414
2415 // block: success
2416 gccjit::rvalue data = mat.access_field (field_slice_data);
2417 gccjit::lvalue gep = data[int_idx];
2418 success.add_assignment (gep, value);
2419 success.end_with_return (mat);
2420 }
2421 #endif
1713 paren_subsasgn_fn.add_overload (fn); 2422 paren_subsasgn_fn.add_overload (fn);
1714 2423
1715 fn = create_external (JIT_FN (octave_jit_paren_subsasgn_matrix_range), matrix, 2424 fn = create_external (JIT_FN (octave_jit_paren_subsasgn_matrix_range), matrix,
1716 matrix, range, scalar); 2425 matrix, range, scalar);
1717 fn.mark_can_error (); 2426 fn.mark_can_error ();
1724 { 2433 {
1725 llvm::Value *mat = fn.argument (builder, 0); 2434 llvm::Value *mat = fn.argument (builder, 0);
1726 llvm::Value *ret = builder.CreateExtractValue (mat, 2); 2435 llvm::Value *ret = builder.CreateExtractValue (mat, 2);
1727 fn.do_return (builder, builder.CreateSIToFP (ret, scalar_t)); 2436 fn.do_return (builder, builder.CreateSIToFP (ret, scalar_t));
1728 } 2437 }
2438 #ifdef HAVE_GCCJIT
2439 {
2440 gccjit::function gf = fn.gccjit_function;
2441 gccjit::rvalue mat = gf.get_param (0);
2442 // FIXME: is this the right behavior?
2443 gccjit::rvalue ret = mat.access_field (field_slice_len);
2444 gccjit::block b = gf.new_block ();
2445 b.end_with_return (ret.cast_to (scalar_t_gcc));
2446 }
2447 #endif
1729 end1_fn.add_overload (fn); 2448 end1_fn.add_overload (fn);
1730 2449
1731 end_fn.stash_name ("end"); 2450 end_fn.stash_name ("end");
1732 fn = create_external (JIT_FN (octave_jit_end_matrix),scalar, matrix, index, 2451 fn = create_external (JIT_FN (octave_jit_end_matrix),scalar, matrix, index,
1733 index); 2452 index);
1782 builder.SetInsertPoint (body); 2501 builder.SetInsertPoint (body);
1783 { 2502 {
1784 llvm::Value *zero = llvm::ConstantFP::get (scalar_t, 0); 2503 llvm::Value *zero = llvm::ConstantFP::get (scalar_t, 0);
1785 fn.do_return (builder, complex_new (fn.argument (builder, 0), zero)); 2504 fn.do_return (builder, complex_new (fn.argument (builder, 0), zero));
1786 } 2505 }
2506 // gccjit implementation of octave_jit_cast_complex_scalar:
2507 #ifdef HAVE_GCCJIT
2508 {
2509 gccjit::function gf = fn.gccjit_function;
2510 gccjit::block b = gf.new_block ();
2511 gccjit::rvalue zero = scalar_t_gcc.zero ();
2512 b.end_with_return (complex_new (b, gf.get_param (0), zero));
2513 }
2514 #endif
1787 casts[complex->type_id ()].add_overload (fn); 2515 casts[complex->type_id ()].add_overload (fn);
1788 2516
1789 // cast scalar <- complex 2517 // cast scalar <- complex
1790 fn = create_internal ("octave_jit_cast_scalar_complex", scalar, complex); 2518 fn = create_internal ("octave_jit_cast_scalar_complex", scalar, complex);
1791 body = fn.new_block (); 2519 body = fn.new_block ();
1792 builder.SetInsertPoint (body); 2520 builder.SetInsertPoint (body);
1793 fn.do_return (builder, complex_real (fn.argument (builder, 0))); 2521 fn.do_return (builder, complex_real (fn.argument (builder, 0)));
2522 #ifdef HAVE_GCCJIT
2523 {
2524 gccjit::function gf = fn.gccjit_function;
2525 gccjit::block b = gf.new_block ();
2526 b.end_with_return (complex_real (gf.get_param (0)));
2527 }
2528 #endif
1794 casts[scalar->type_id ()].add_overload (fn); 2529 casts[scalar->type_id ()].add_overload (fn);
1795 2530
1796 // cast any <- any 2531 // cast any <- any
1797 fn = create_identity (any); 2532 fn = create_identity (any);
1798 casts[any->type_id ()].add_overload (fn); 2533 casts[any->type_id ()].add_overload (fn);
1816 add_builtin ("cos"); 2551 add_builtin ("cos");
1817 register_intrinsic ("cos", llvm::Intrinsic::cos, scalar, scalar); 2552 register_intrinsic ("cos", llvm::Intrinsic::cos, scalar, scalar);
1818 register_generic ("cos", matrix, matrix); 2553 register_generic ("cos", matrix, matrix);
1819 2554
1820 add_builtin ("exp"); 2555 add_builtin ("exp");
1821 register_intrinsic ("exp", llvm::Intrinsic::exp, scalar, scalar); 2556 // FIXME: looks like a typo: "cos" here should be "exp":
2557 // filed as http://savannah.gnu.org/bugs/index.php?41560
2558 register_intrinsic ("exp", llvm::Intrinsic::cos, scalar, scalar);
1822 register_generic ("exp", matrix, matrix); 2559 register_generic ("exp", matrix, matrix);
1823 2560
1824 add_builtin ("balance"); 2561 add_builtin ("balance");
1825 register_generic ("balance", matrix, matrix); 2562 register_generic ("balance", matrix, matrix);
1826 2563
1831 register_generic ("det", scalar, matrix); 2568 register_generic ("det", scalar, matrix);
1832 2569
1833 add_builtin ("norm"); 2570 add_builtin ("norm");
1834 register_generic ("norm", scalar, matrix); 2571 register_generic ("norm", scalar, matrix);
1835 2572
2573 //FIXME: gccjit can't yet cope with duplicate names
2574 #if !defined (HAVE_GCCJIT)
1836 add_builtin ("rand"); 2575 add_builtin ("rand");
1837 register_generic ("rand", matrix, scalar); 2576 register_generic ("rand", matrix, scalar);
1838 register_generic ("rand", matrix, std::vector<jit_type *> (2, scalar)); 2577 register_generic ("rand", matrix, std::vector<jit_type *> (2, scalar));
1839 2578
2579
1840 add_builtin ("magic"); 2580 add_builtin ("magic");
1841 register_generic ("magic", matrix, scalar); 2581 register_generic ("magic", matrix, scalar);
1842 register_generic ("magic", matrix, std::vector<jit_type *> (2, scalar)); 2582 register_generic ("magic", matrix, std::vector<jit_type *> (2, scalar));
1843 2583
1844 add_builtin ("eye"); 2584 add_builtin ("eye");
1845 register_generic ("eye", matrix, scalar); 2585 register_generic ("eye", matrix, scalar);
1846 register_generic ("eye", matrix, std::vector<jit_type *> (2, scalar)); 2586 register_generic ("eye", matrix, std::vector<jit_type *> (2, scalar));
2587 #endif
1847 2588
1848 add_builtin ("mod"); 2589 add_builtin ("mod");
1849 register_generic ("mod", scalar, std::vector<jit_type *> (2, scalar)); 2590 register_generic ("mod", scalar, std::vector<jit_type *> (2, scalar));
1850 2591
1851 casts.resize (next_id + 1); 2592 casts.resize (next_id + 1);
1868 2609
1869 args[0] = any; 2610 args[0] = any;
1870 casts[btype->type_id ()].add_overload (jit_function (any_id, btype, 2611 casts[btype->type_id ()].add_overload (jit_function (any_id, btype,
1871 args)); 2612 args));
1872 } 2613 }
2614 #ifdef HAVE_GCCJIT
2615 gccjit_ctxt.dump_to_file ("/tmp/jit-typeinfo-dump.c", true);
2616 #endif
1873 } 2617 }
1874 2618
1875 const jit_function& 2619 const jit_function&
1876 jit_typeinfo::do_end (jit_value *value, jit_value *idx, jit_value *count) 2620 jit_typeinfo::do_end (jit_value *value, jit_value *idx, jit_value *count)
1877 { 2621 {
1881 2625
1882 return end_fn.overload (value->type (), idx->type (), count->type ()); 2626 return end_fn.overload (value->type (), idx->type (), count->type ());
1883 } 2627 }
1884 2628
1885 jit_type* 2629 jit_type*
1886 jit_typeinfo::new_type (const std::string& name, jit_type *parent, 2630 jit_typeinfo::new_type (const std::string& name, jit_type *parent
1887 llvm::Type *llvm_type, bool skip_paren) 2631 #ifdef HAVE_LLVM
1888 { 2632 , llvm::Type *llvm_type
1889 jit_type *ret = new jit_type (name, parent, llvm_type, skip_paren, next_id++); 2633 #endif
2634 #ifdef HAVE_GCCJIT
2635 , gccjit::type gccjit_type
2636 #endif
2637 , bool skip_paren)
2638 {
2639 jit_type *ret = new jit_type (name, parent
2640 #ifdef HAVE_LLVM
2641 , llvm_type
2642 #endif
2643 #ifdef HAVE_GCCJIT
2644 , gccjit_type
2645 #endif
2646 , skip_paren, next_id++);
1890 id_to_type.push_back (ret); 2647 id_to_type.push_back (ret);
1891 return ret; 2648 return ret;
1892 } 2649 }
1893 2650
1894 void 2651 void
1901 print_fn.add_overload (fn); 2658 print_fn.add_overload (fn);
1902 } 2659 }
1903 2660
1904 // FIXME: cp between add_binary_op, add_binary_icmp, and add_binary_fcmp 2661 // FIXME: cp between add_binary_op, add_binary_icmp, and add_binary_fcmp
1905 void 2662 void
1906 jit_typeinfo::add_binary_op (jit_type *ty, int op, int llvm_op) 2663 jit_typeinfo::add_binary_op (jit_type *ty, int op
2664 , int llvm_op
2665 #ifdef HAVE_GCCJIT
2666 , enum gcc_jit_binary_op gccjit_op
2667 #endif
2668 )
1907 { 2669 {
1908 std::stringstream fname; 2670 std::stringstream fname;
1909 octave_value::binary_op ov_op = static_cast<octave_value::binary_op>(op); 2671 octave_value::binary_op ov_op = static_cast<octave_value::binary_op>(op);
1910 fname << "octave_jit_" << octave_value::binary_op_as_string (ov_op) 2672 fname << "octave_jit_" << octave_value::binary_op_fcn_name (ov_op)
1911 << "_" << ty->name (); 2673 << "_" << ty->name ();
1912 2674
1913 jit_function fn = create_internal (fname.str (), ty, ty, ty); 2675 jit_function fn = create_internal (fname.str (), ty, ty, ty);
2676
2677 // LLVM implementation:
1914 llvm::BasicBlock *block = fn.new_block (); 2678 llvm::BasicBlock *block = fn.new_block ();
1915 builder.SetInsertPoint (block); 2679 builder.SetInsertPoint (block);
1916 llvm::Instruction::BinaryOps temp 2680 llvm::Instruction::BinaryOps temp
1917 = static_cast<llvm::Instruction::BinaryOps>(llvm_op); 2681 = static_cast<llvm::Instruction::BinaryOps>(llvm_op);
1918 2682
1919 llvm::Value *ret = builder.CreateBinOp (temp, fn.argument (builder, 0), 2683 llvm::Value *ret = builder.CreateBinOp (temp, fn.argument (builder, 0),
1920 fn.argument (builder, 1)); 2684 fn.argument (builder, 1));
1921 fn.do_return (builder, ret); 2685 fn.do_return (builder, ret);
2686
2687 // gccjit implementation:
2688 #ifdef HAVE_GCCJIT
2689 gccjit::function gf = fn.gccjit_function;
2690 gccjit::block b = gf.new_block ();
2691 b.end_with_return (
2692 gf.get_context ().new_binary_op (
2693 gccjit_op,
2694 ty->to_gccjit (),
2695 gf.get_param (0),
2696 gf.get_param (1)));
2697 #endif
1922 binary_ops[op].add_overload (fn); 2698 binary_ops[op].add_overload (fn);
1923 } 2699 }
1924 2700
1925 void 2701 void
1926 jit_typeinfo::add_binary_icmp (jit_type *ty, int op, int llvm_op) 2702 jit_typeinfo::add_binary_icmp (jit_type *ty, int op
2703 , int llvm_op
2704 #ifdef HAVE_GCCJIT
2705 , enum gcc_jit_comparison gccjit_op
2706 #endif
2707 )
1927 { 2708 {
1928 std::stringstream fname; 2709 std::stringstream fname;
1929 octave_value::binary_op ov_op = static_cast<octave_value::binary_op>(op); 2710 octave_value::binary_op ov_op = static_cast<octave_value::binary_op>(op);
1930 fname << "octave_jit" << octave_value::binary_op_as_string (ov_op) 2711 fname << "octave_jit_" << octave_value::binary_op_fcn_name (ov_op)
1931 << "_" << ty->name (); 2712 << "_" << ty->name ();
1932 2713
1933 jit_function fn = create_internal (fname.str (), boolean, ty, ty); 2714 jit_function fn = create_internal (fname.str (), boolean, ty, ty);
2715
2716 // LLVM implementation:
1934 llvm::BasicBlock *block = fn.new_block (); 2717 llvm::BasicBlock *block = fn.new_block ();
1935 builder.SetInsertPoint (block); 2718 builder.SetInsertPoint (block);
1936 llvm::CmpInst::Predicate temp 2719 llvm::CmpInst::Predicate temp
1937 = static_cast<llvm::CmpInst::Predicate>(llvm_op); 2720 = static_cast<llvm::CmpInst::Predicate>(llvm_op);
1938 llvm::Value *ret = builder.CreateICmp (temp, fn.argument (builder, 0), 2721 llvm::Value *ret = builder.CreateICmp (temp, fn.argument (builder, 0),
1939 fn.argument (builder, 1)); 2722 fn.argument (builder, 1));
1940 fn.do_return (builder, ret); 2723 fn.do_return (builder, ret);
2724
2725 // gccjit implementation:
2726 #ifdef HAVE_GCCJIT
2727 gccjit::function gf = fn.gccjit_function;
2728 gccjit::block b = gf.new_block ();
2729 b.end_with_return (
2730 gf.get_context ().new_comparison (
2731 gccjit_op,
2732 gf.get_param (0),
2733 gf.get_param (1)));
2734 #endif
1941 binary_ops[op].add_overload (fn); 2735 binary_ops[op].add_overload (fn);
1942 } 2736 }
1943 2737
1944 void 2738 void
1945 jit_typeinfo::add_binary_fcmp (jit_type *ty, int op, int llvm_op) 2739 jit_typeinfo::add_binary_fcmp (jit_type *ty, int op
2740 , int llvm_op
2741 #ifdef HAVE_GCCJIT
2742 , enum gcc_jit_comparison gccjit_op
2743 #endif
2744 )
1946 { 2745 {
1947 std::stringstream fname; 2746 std::stringstream fname;
1948 octave_value::binary_op ov_op = static_cast<octave_value::binary_op>(op); 2747 octave_value::binary_op ov_op = static_cast<octave_value::binary_op>(op);
1949 fname << "octave_jit" << octave_value::binary_op_as_string (ov_op) 2748 fname << "octave_jit_" << octave_value::binary_op_fcn_name (ov_op)
1950 << "_" << ty->name (); 2749 << "_" << ty->name ();
1951 2750
1952 jit_function fn = create_internal (fname.str (), boolean, ty, ty); 2751 jit_function fn = create_internal (fname.str (), boolean, ty, ty);
2752
2753 // LLVM implementation:
1953 llvm::BasicBlock *block = fn.new_block (); 2754 llvm::BasicBlock *block = fn.new_block ();
1954 builder.SetInsertPoint (block); 2755 builder.SetInsertPoint (block);
1955 llvm::CmpInst::Predicate temp 2756 llvm::CmpInst::Predicate temp
1956 = static_cast<llvm::CmpInst::Predicate>(llvm_op); 2757 = static_cast<llvm::CmpInst::Predicate>(llvm_op);
1957 llvm::Value *ret = builder.CreateFCmp (temp, fn.argument (builder, 0), 2758 llvm::Value *ret = builder.CreateFCmp (temp, fn.argument (builder, 0),
1958 fn.argument (builder, 1)); 2759 fn.argument (builder, 1));
1959 fn.do_return (builder, ret); 2760 fn.do_return (builder, ret);
2761
2762 // gccjit implementation:
2763 #ifdef HAVE_GCCJIT
2764 gccjit::function gf = fn.gccjit_function;
2765 gccjit::block b = gf.new_block ();
2766 b.end_with_return (
2767 gf.get_context ().new_comparison (
2768 gccjit_op,
2769 gf.get_param (0),
2770 gf.get_param (1)));
2771 #endif
1960 binary_ops[op].add_overload (fn); 2772 binary_ops[op].add_overload (fn);
1961 } 2773 }
1962 2774
1963 jit_function 2775 jit_function
1964 jit_typeinfo::create_function (jit_convention::type cc, const llvm::Twine& name, 2776 jit_typeinfo::create_function (jit_convention::type cc, std::string name,
1965 jit_type *ret, 2777 jit_type *ret,
1966 const std::vector<jit_type *>& args) 2778 const std::vector<jit_type *>& args)
1967 { 2779 {
1968 jit_function result (module, cc, name, ret, args); 2780 jit_function result (module,
2781 #ifdef HAVE_GCCJIT
2782 gccjit_ctxt,
2783 #endif
2784 cc, name, ret, args);
1969 return result; 2785 return result;
1970 } 2786 }
1971 2787
1972 jit_function 2788 jit_function
1973 jit_typeinfo::create_identity (jit_type *type) 2789 jit_typeinfo::create_identity (jit_type *type)
1980 { 2796 {
1981 std::stringstream name; 2797 std::stringstream name;
1982 name << "id_" << type->name (); 2798 name << "id_" << type->name ();
1983 2799
1984 jit_function fn = create_internal (name.str (), type, type); 2800 jit_function fn = create_internal (name.str (), type, type);
2801
2802 // LLVM implementation:
1985 llvm::BasicBlock *body = fn.new_block (); 2803 llvm::BasicBlock *body = fn.new_block ();
1986 builder.SetInsertPoint (body); 2804 builder.SetInsertPoint (body);
1987 fn.do_return (builder, fn.argument (builder, 0)); 2805 fn.do_return (builder, fn.argument (builder, 0));
2806
2807 // gccjit implementation:
2808 #ifdef HAVE_GCCJIT
2809 gccjit::function gf = fn.gccjit_function;
2810 gccjit::block b = gf.new_block ();
2811 b.end_with_return (gf.get_param (0));
2812 #endif
2813
1988 return identities[id] = fn; 2814 return identities[id] = fn;
1989 } 2815 }
1990 2816
1991 return identities[id]; 2817 return identities[id];
1992 } 2818 }
1993 2819
2820 #ifdef HAVE_LLVM
1994 llvm::Value * 2821 llvm::Value *
1995 jit_typeinfo::do_insert_error_check (llvm::IRBuilderD& abuilder) 2822 jit_typeinfo::do_insert_error_check (llvm::IRBuilderD& abuilder)
1996 { 2823 {
1997 return abuilder.CreateLoad (lerror_state); 2824 return abuilder.CreateLoad (lerror_state);
1998 } 2825 }
2002 { 2829 {
2003 llvm::LoadInst *val = abuilder.CreateLoad (loctave_interrupt_state); 2830 llvm::LoadInst *val = abuilder.CreateLoad (loctave_interrupt_state);
2004 val->setVolatile (true); 2831 val->setVolatile (true);
2005 return abuilder.CreateICmpSGT (val, abuilder.getInt32 (0)); 2832 return abuilder.CreateICmpSGT (val, abuilder.getInt32 (0));
2006 } 2833 }
2834 #endif /* #ifdef HAVE_LLVM */
2835
2836 #ifdef HAVE_GCCJIT
2837 gccjit::rvalue
2838 jit_typeinfo::do_insert_error_check (gccjit::function func)
2839 {
2840 return error_state_gccjit.cast_to (gccjit_ctxt.get_type (GCC_JIT_TYPE_BOOL));
2841 }
2842
2843 gccjit::rvalue
2844 jit_typeinfo::do_insert_interrupt_check (gccjit::function func)
2845 {
2846 return octave_interrupt_state_gccjit > sig_atomic_type_gccjit.zero ();
2847 }
2848 #endif /* #ifdef HAVE_GCCJIT */
2849
2007 2850
2008 void 2851 void
2009 jit_typeinfo::add_builtin (const std::string& name) 2852 jit_typeinfo::add_builtin (const std::string& name)
2010 { 2853 {
2011 jit_type *btype = new_type (name, any, any->to_llvm (), true); 2854 jit_type *btype = new_type (name, any, any->to_llvm (),
2855 #ifdef HAVE_GCCJIT
2856 any->to_gccjit (),
2857 #endif
2858 true);
2012 builtins[name] = btype; 2859 builtins[name] = btype;
2013 2860
2014 octave_builtin *ov_builtin = find_builtin (name); 2861 octave_builtin *ov_builtin = find_builtin (name);
2015 if (ov_builtin) 2862 if (ov_builtin)
2016 ov_builtin->stash_jit (*btype); 2863 ov_builtin->stash_jit (*btype);
2048 for (size_t i = 0; i < nargs; ++i) 2895 for (size_t i = 0; i < nargs; ++i)
2049 fargs[i] = fn.argument (builder, i + 1); 2896 fargs[i] = fn.argument (builder, i + 1);
2050 2897
2051 llvm::Value *ret = builder.CreateCall (ifun, fargs); 2898 llvm::Value *ret = builder.CreateCall (ifun, fargs);
2052 fn.do_return (builder, ret); 2899 fn.do_return (builder, ret);
2900
2901 // gcc implementation
2902 #ifdef HAVE_GCCJIT
2903 {
2904 gccjit::function gf = fn.gccjit_function;
2905 gccjit::function builtin = gccjit_ctxt.get_builtin_function (name);
2906 std::vector<gccjit::rvalue> gccjit_args (nargs);
2907 for (size_t i = 0; i < nargs; ++i)
2908 gccjit_args[i] = gf.get_param (i + 1);
2909 gccjit::rvalue ret = gccjit_ctxt.new_call (builtin, gccjit_args);
2910 gccjit::block b = gf.new_block ();
2911 b.end_with_return (ret);
2912 }
2913 #endif
2914
2053 paren_subsref_fn.add_overload (fn); 2915 paren_subsref_fn.add_overload (fn);
2054 } 2916 }
2055 2917
2056 octave_builtin * 2918 octave_builtin *
2057 jit_typeinfo::find_builtin (const std::string& name) 2919 jit_typeinfo::find_builtin (const std::string& name)
2073 std::vector<jit_type *> fn_args (args.size () + 1); 2935 std::vector<jit_type *> fn_args (args.size () + 1);
2074 fn_args[0] = builtins[name]; 2936 fn_args[0] = builtins[name];
2075 std::copy (args.begin (), args.end (), fn_args.begin () + 1); 2937 std::copy (args.begin (), args.end (), fn_args.begin () + 1);
2076 jit_function fn = create_internal (name, result, fn_args); 2938 jit_function fn = create_internal (name, result, fn_args);
2077 fn.mark_can_error (); 2939 fn.mark_can_error ();
2940
2941 // LLVM implementation:
2078 llvm::BasicBlock *block = fn.new_block (); 2942 llvm::BasicBlock *block = fn.new_block ();
2079 builder.SetInsertPoint (block); 2943 builder.SetInsertPoint (block);
2080 llvm::Type *any_t = any->to_llvm (); 2944 llvm::Type *any_t = any->to_llvm ();
2081 llvm::ArrayType *array_t = llvm::ArrayType::get (any_t, args.size ()); 2945 llvm::ArrayType *array_t = llvm::ArrayType::get (any_t, args.size ());
2082 llvm::Value *array = llvm::UndefValue::get (array_t); 2946 llvm::Value *array = llvm::UndefValue::get (array_t);
2103 llvm::Value *res_llvm = llvm::ConstantInt::get (intTy, result_int); 2967 llvm::Value *res_llvm = llvm::ConstantInt::get (intTy, result_int);
2104 llvm::Value *ret = any_call.call (builder, fcn, nargin, array, res_llvm); 2968 llvm::Value *ret = any_call.call (builder, fcn, nargin, array, res_llvm);
2105 2969
2106 jit_function cast_result = cast (result, any); 2970 jit_function cast_result = cast (result, any);
2107 fn.do_return (builder, cast_result.call (builder, ret)); 2971 fn.do_return (builder, cast_result.call (builder, ret));
2972
2973 // gccjit implementation:
2974 #ifdef HAVE_GCCJIT
2975 {
2976 gccjit::function gf = fn.gccjit_function;
2977 gccjit::block b = gf.new_block ("body of register_generic");
2978 b.add_comment ("TODO: register_generic");
2979
2980 gccjit::type array_t = gccjit_ctxt.new_array_type (any->to_gccjit (),
2981 args.size ());
2982 #if 1
2983 gccjit::lvalue array = gf.new_local (array_t, "tmp_array");
2984 for (size_t i = 0; i < args.size (); ++i)
2985 {
2986 gccjit::lvalue arg = gf.get_param (i + 1);
2987 jit_function agrab = get_grab (args[i]);
2988 if (agrab.valid ())
2989 {
2990 std::vector<gccjit::rvalue> grab_args (1, arg);
2991 b.add_assignment (arg, agrab.call (gccjit_ctxt, b, grab_args));
2992 }
2993 jit_function acast = cast (any, args[i]);
2994 std::vector<gccjit::rvalue> cast_args (1, arg);
2995 b.add_assignment (array[i],
2996 acast.call (gccjit_ctxt, b, cast_args));
2997 }
2998 #endif
2999
3000 gccjit::type int_t = intN (sizeof (octave_builtin::fcn) * 8)->to_gccjit ();
3001 size_t fcn_int = reinterpret_cast<size_t> (builtin->function ());
3002 gccjit::rvalue fcn = gccjit_ctxt.new_rvalue (int_t, (int)fcn_int);
3003 gccjit::rvalue nargin = gccjit_ctxt.new_rvalue (int_t, (int)args.size ());
3004 size_t result_int = reinterpret_cast<size_t> (result);
3005 gccjit::rvalue res_gcc = gccjit_ctxt.new_rvalue (int_t, (int)result_int);
3006 std::vector<gccjit::rvalue> call_args (4);
3007 call_args[0] = fcn;
3008 call_args[1] = nargin;
3009 call_args[2] = array;
3010 call_args[3] = res_gcc;
3011 gccjit::rvalue ret = any_call.call (gccjit_ctxt, b, call_args);
3012
3013 jit_function cast_result = cast (result, any);
3014 std::vector<gccjit::rvalue> final_cast_args (1);
3015 final_cast_args[0] = ret;
3016 gccjit::rvalue final_result = cast_result.call (gccjit_ctxt, b, final_cast_args);
3017 b.end_with_return (final_result);
3018 }
3019 #endif
3020
2108 paren_subsref_fn.add_overload (fn); 3021 paren_subsref_fn.add_overload (fn);
2109 } 3022 }
2110 3023
2111 jit_function 3024 jit_function
2112 jit_typeinfo::mirror_binary (const jit_function& fn) 3025 jit_typeinfo::mirror_binary (const jit_function& fn)
2115 fn.result (), fn.argument_type (1), 3028 fn.result (), fn.argument_type (1),
2116 fn.argument_type (0)); 3029 fn.argument_type (0));
2117 if (fn.can_error ()) 3030 if (fn.can_error ())
2118 ret.mark_can_error (); 3031 ret.mark_can_error ();
2119 3032
3033 // LLVM implementation:
2120 llvm::BasicBlock *body = ret.new_block (); 3034 llvm::BasicBlock *body = ret.new_block ();
2121 builder.SetInsertPoint (body); 3035 builder.SetInsertPoint (body);
2122 llvm::Value *result = fn.call (builder, ret.argument (builder, 1), 3036 llvm::Value *result = fn.call (builder, ret.argument (builder, 1),
2123 ret.argument (builder, 0)); 3037 ret.argument (builder, 0));
2124 if (ret.result ()) 3038 if (ret.result ())
2125 ret.do_return (builder, result); 3039 ret.do_return (builder, result);
2126 else 3040 else
2127 ret.do_return (builder); 3041 ret.do_return (builder);
2128 3042
3043 // gccjit implementation:
3044 #ifdef HAVE_GCCJIT
3045 gccjit::function gf = ret.gccjit_function;
3046 gccjit::block b = gf.new_block ();
3047 b.add_comment ("built by mirror_binary");
3048 //std::vector<gccjit::rvalue> gccjit_args (2);
3049 //gccjit_args[0] = gf.get_param (1);
3050 //gccjit_args[1] = gf.get_param (0);
3051 if (ret.result ())
3052 b.end_with_return (
3053 gccjit_ctxt.new_call (fn.gccjit_function,
3054 gf.get_param (1),
3055 gf.get_param (0)));
3056 else
3057 b.end_with_return ();
3058 #endif
3059
2129 return ret; 3060 return ret;
2130 } 3061 }
2131 3062
3063 #ifdef HAVE_LLVM
2132 llvm::Value * 3064 llvm::Value *
2133 jit_typeinfo::pack_complex (llvm::IRBuilderD& bld, llvm::Value *cplx) 3065 jit_typeinfo::pack_complex (llvm::IRBuilderD& bld, llvm::Value *cplx)
2134 { 3066 {
2135 llvm::Type *complex_ret = instance->complex_ret; 3067 llvm::Type *complex_ret = instance->complex_ret;
2136 llvm::Value *real = bld.CreateExtractValue (cplx, 0); 3068 llvm::Value *real = bld.CreateExtractValue (cplx, 0);
2187 { 3119 {
2188 llvm::Value *ret = llvm::UndefValue::get (complex->to_llvm ()); 3120 llvm::Value *ret = llvm::UndefValue::get (complex->to_llvm ());
2189 ret = complex_real (ret, real); 3121 ret = complex_real (ret, real);
2190 return complex_imag (ret, imag); 3122 return complex_imag (ret, imag);
2191 } 3123 }
3124 #endif // #ifdef HAVE_LLVM
3125
3126 #ifdef HAVE_GCCJIT
3127 gccjit::rvalue
3128 jit_typeinfo::complex_real (gccjit::rvalue cx)
3129 {
3130 return cx[0];
3131 }
3132
3133 gccjit::rvalue
3134 jit_typeinfo::complex_real (gccjit::block block,
3135 gccjit::lvalue cx,
3136 gccjit::rvalue real)
3137 {
3138 block.add_assignment (cx[0], real);
3139 return cx;
3140 }
3141
3142 gccjit::rvalue
3143 jit_typeinfo::complex_imag (gccjit::rvalue cx)
3144 {
3145 return cx[1];
3146 }
3147
3148 gccjit::rvalue
3149 jit_typeinfo::complex_imag (gccjit::block block,
3150 gccjit::lvalue cx,
3151 gccjit::rvalue imag)
3152 {
3153 block.add_assignment (cx[1], imag);
3154 return cx;
3155 }
3156
3157 gccjit::rvalue
3158 jit_typeinfo::complex_new (gccjit::block block,
3159 gccjit::rvalue real,
3160 gccjit::rvalue imag)
3161 {
3162 gccjit::rvalue tmp =
3163 block.get_function ().new_local (complex->to_gccjit (),
3164 "complex_new");
3165 block.add_assignment (tmp[0], real);
3166 block.add_assignment (tmp[1], imag);
3167 return tmp;
3168 }
3169 #endif // #ifdef HAVE_GCCJIT
2192 3170
2193 void 3171 void
2194 jit_typeinfo::create_int (size_t nbits) 3172 jit_typeinfo::create_int (size_t nbits)
2195 { 3173 {
2196 std::stringstream tname; 3174 std::stringstream tname;
2197 tname << "int" << nbits; 3175 tname << "int" << nbits;
2198 ints[nbits] = new_type (tname.str (), any, llvm::Type::getIntNTy (context, 3176 ints[nbits] = new_type (tname.str (), any
2199 nbits)); 3177 , llvm::Type::getIntNTy (context,
3178 nbits)
3179 #ifdef HAVE_GCCJIT
3180 , gccjit_ctxt.get_int_type (nbits / 8, 1)
3181 #endif
3182 );
2200 } 3183 }
2201 3184
2202 jit_type * 3185 jit_type *
2203 jit_typeinfo::intN (size_t nbits) const 3186 jit_typeinfo::intN (size_t nbits) const
2204 { 3187 {