Mercurial > octave-nkf
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 { |