31 const std::string& ext_func_name,
35 CHECK(elem_type->isPointerTy());
36 llvm::StructType* generated_struct_type =
37 llvm::StructType::get(cgen_state->
context_,
39 llvm::Type::getInt64Ty(cgen_state->
context_),
40 llvm::Type::getInt8Ty(cgen_state->
context_)},
42 llvm::Function* udf_func = cgen_state->module_->getFunction(ext_func_name);
47 llvm::FunctionType* udf_func_type = udf_func->getFunctionType();
48 CHECK_LE(param_num, udf_func_type->getNumParams());
49 llvm::Type* param_pointer_type = udf_func_type->getParamType(param_num);
50 CHECK(param_pointer_type->isPointerTy());
51 llvm::Type* param_type = param_pointer_type->getPointerElementType();
52 CHECK(param_type->isStructTy());
53 llvm::StructType* struct_type = llvm::cast<llvm::StructType>(param_type);
54 CHECK_GE(struct_type->getStructNumElements(),
55 generated_struct_type->getStructNumElements())
58 const auto expected_elems = generated_struct_type->elements();
59 const auto current_elems = struct_type->elements();
60 for (
size_t i = 0; i < expected_elems.size(); i++) {
61 CHECK_EQ(expected_elems[i], current_elems[i])
66 if (struct_type->isLiteral()) {
70 llvm::StringRef struct_name = struct_type->getStructName();
71 #if LLVM_VERSION_MAJOR >= 12
72 return struct_type->getTypeByName(cgen_state->context_, struct_name);
74 return cgen_state->module_->getTypeByName(struct_name);
77 return generated_struct_type;
81 llvm::LLVMContext& ctx) {
82 switch (ext_arg_type) {
93 return llvm::Type::getFloatTy(ctx);
95 return llvm::Type::getDoubleTy(ctx);
122 return llvm::Type::getVoidTy(ctx);
132 const auto bits = ll_type->getPrimitiveSizeInBits();
134 if (ll_type->isFloatingPointTy()) {
141 LOG(
FATAL) <<
"Unsupported llvm floating point type: " << bits
142 <<
", only 32 and 64 bit floating point is supported.";
157 LOG(
FATAL) <<
"Unrecognized llvm type for SQL type: "
166 llvm::LLVMContext& ctx) {
169 return llvm::Type::getInt8PtrTy(ctx);
173 if (elem_ti.is_fp()) {
174 switch (elem_ti.get_size()) {
176 return llvm::Type::getFloatPtrTy(ctx);
178 return llvm::Type::getDoublePtrTy(ctx);
182 if (elem_ti.is_text_encoding_dict()) {
183 return llvm::Type::getInt32PtrTy(ctx);
186 if (elem_ti.is_boolean()) {
187 return llvm::Type::getInt8PtrTy(ctx);
190 CHECK(elem_ti.is_integer());
191 switch (elem_ti.get_size()) {
193 return llvm::Type::getInt8PtrTy(ctx);
195 return llvm::Type::getInt16PtrTy(ctx);
197 return llvm::Type::getInt32PtrTy(ctx);
199 return llvm::Type::getInt64PtrTy(ctx);
208 for (
size_t i = 0; i < function_oper->
getArity(); ++i) {
209 const auto arg = function_oper->
getArg(i);
211 if ((func_ti.is_array() && arg_ti.is_array()) ||
212 (func_ti.is_text_encoding_none() && arg_ti.is_text_encoding_none()) ||
213 (func_ti.is_text_encoding_dict() && arg_ti.is_text_encoding_dict()) ||
214 (func_ti.is_text_encoding_dict_array() && arg_ti.is_text_encoding_dict())) {
220 }
else if (!arg_ti.get_notnull() && !arg_ti.is_buffer()) {
234 Executor* exec_ptr =
reinterpret_cast<Executor*
>(exec);
235 if (buffer !=
nullptr) {
236 exec_ptr->getRowSetMemoryOwner()->addVarlenBuffer(buffer);
249 LOG(
WARNING) <<
"codegenFunctionOper[GPU]: " << e.what() <<
" Redirecting "
250 << function_oper->
getName() <<
" to run on CPU.";
257 LOG(
WARNING) <<
"codegenFunctionOper[CPU]: " << e.what();
264 CHECK(ret_ti.is_integer() || ret_ti.is_fp() || ret_ti.is_boolean() ||
265 ret_ti.is_buffer() || ret_ti.is_text_encoding_dict());
277 if (*it.foper == *function_oper) {
278 auto inst = llvm::dyn_cast<llvm::Instruction>(it.lv);
279 if (inst && inst->getParent() == current_bb) {
284 std::vector<llvm::Value*> orig_arg_lvs;
285 std::vector<size_t> orig_arg_lvs_index;
286 std::unordered_map<llvm::Value*, llvm::Value*> const_arr_size;
288 for (
size_t i = 0; i < function_oper->
getArity(); ++i) {
289 orig_arg_lvs_index.push_back(orig_arg_lvs.size());
290 const auto arg = function_oper->
getArg(i);
293 (arg_cast && arg_cast->get_optype() ==
kCAST) ? arg_cast->
get_operand() : arg;
295 auto is_local_alloc = array_expr_arg && array_expr_arg->
isLocalAlloc();
296 const auto& arg_ti = arg->get_type_info();
297 const auto arg_lvs =
codegen(arg,
true, co);
302 if ((geo_uoper_arg || geo_binoper_arg) && arg_ti.is_geometry()) {
304 CHECK_EQ(2 * static_cast<size_t>(arg_ti.get_physical_coord_cols()), arg_lvs.size());
305 for (
size_t i = 0; i < arg_lvs.size(); i++) {
306 auto arr = arg_lvs[i++];
307 auto size = arg_lvs[i];
308 orig_arg_lvs.push_back(arr);
309 const_arr_size[arr] = size;
311 }
else if (geo_expr_arg && geo_expr_arg->get_type_info().is_geometry()) {
312 CHECK(geo_expr_arg->get_type_info().get_type() ==
kPOINT);
313 CHECK_EQ(arg_lvs.size(), size_t(2));
314 for (
size_t j = 0; j < arg_lvs.size(); j++) {
315 orig_arg_lvs.push_back(arg_lvs[j]);
317 }
else if (arg_ti.is_geometry()) {
318 CHECK_EQ(static_cast<size_t>(arg_ti.get_physical_coord_cols()), arg_lvs.size());
319 for (
size_t j = 0; j < arg_lvs.size(); j++) {
320 orig_arg_lvs.push_back(arg_lvs[j]);
322 }
else if (arg_ti.is_text_encoding_none()) {
323 if (arg_lvs.size() == 3) {
329 std::begin(arg_lvs), std::end(arg_lvs), std::back_inserter(orig_arg_lvs));
330 }
else if (arg_lvs.size() == 1) {
336 CHECK(arg_lvs[0]->getType()->isPointerTy());
338 arg_lvs[0]->getType()->getPointerElementType(), arg_lvs[0]);
339 orig_arg_lvs.push_back(none_enc_string);
340 orig_arg_lvs.push_back(
346 }
else if (arg_ti.is_text_encoding_dict()) {
347 CHECK_EQ(
size_t(1), arg_lvs.size());
348 orig_arg_lvs.push_back(arg_lvs[0]);
350 if (arg_lvs.size() > 1) {
351 CHECK(arg_ti.is_array());
352 CHECK_EQ(
size_t(2), arg_lvs.size());
353 const_arr_size[arg_lvs.front()] = arg_lvs.back();
355 CHECK_EQ(
size_t(1), arg_lvs.size());
359 if (is_local_alloc && arg_ti.get_size() > 0) {
363 orig_arg_lvs.push_back(arg_lvs.front());
374 function_oper, &ext_func_sig, orig_arg_lvs, orig_arg_lvs_index, const_arr_size, co);
381 args.insert(args.begin(), row_func_mgr);
384 llvm::Value* buffer_ret{
nullptr};
385 if (ret_ti.is_buffer()) {
387 CHECK(ret_ti.is_array() || ret_ti.is_text_encoding_none());
395 args.insert(args.begin(), buffer_ret);
399 ext_func_sig.
getName(), ret_ty,
args, {}, ret_ti.is_buffer());
401 bbs, ret_ti.is_buffer() ? buffer_ret : ext_call, null_buffer_ptr, function_oper);
404 if (!(ret_ti.is_buffer() || ret_ti.is_text_encoding_dict())) {
406 if (bbs.args_null_bb &&
413 function_oper->
getName().substr(0, 3) != std::string(
"ST_")) {
414 ext_call_nullcheck =
codegenCast(ext_call_nullcheck,
423 return ext_call_nullcheck;
427 std::tuple<CodeGenerator::ArgNullcheckBBs, llvm::Value*>
429 const std::vector<llvm::Value*>& orig_arg_lvs) {
431 llvm::BasicBlock* args_null_bb{
nullptr};
432 llvm::BasicBlock* args_notnull_bb{
nullptr};
434 llvm::Value* null_array_alloca{
nullptr};
438 if (func_ti.is_buffer()) {
448 args_notnull_bb = llvm::BasicBlock::Create(
450 args_null_bb = llvm::BasicBlock::Create(
455 return std::make_tuple(
463 llvm::Value* fn_ret_lv,
464 llvm::Value* null_array_ptr,
472 llvm::PHINode* ext_call_phi{
nullptr};
473 llvm::Value* null_lv{
nullptr};
475 if (!func_ti.is_buffer()) {
480 extension_ret_ti.is_fp()
486 extension_ret_ti.is_fp()
498 CHECK(null_array_ptr);
499 const auto arr_null_bool =
505 const auto arr_null_size =
512 ext_call_phi->addIncoming(func_ti.is_buffer() ? null_array_ptr : null_lv,
524 if (!ret_ti.is_integer() && !ret_ti.is_fp()) {
527 for (
size_t i = 0; i < function_oper->
getArity(); ++i) {
528 const auto arg = function_oper->
getArg(i);
530 if (!arg_ti.is_integer() && !arg_ti.is_fp()) {
545 if (function_oper->
getName() ==
"FLOOR" || function_oper->
getName() ==
"CEIL") {
547 const auto arg = function_oper->
getArg(0);
549 CHECK(arg_ti.is_decimal());
550 const auto arg_lvs =
codegen(arg,
true, co);
551 CHECK_EQ(
size_t(1), arg_lvs.size());
552 const auto arg_lv = arg_lvs.front();
553 CHECK(arg_lv->getType()->isIntegerTy(64));
556 const std::string func_name =
557 (function_oper->
getName() ==
"FLOOR") ?
"decimal_floor" :
"decimal_ceil";
561 CHECK(ret_ti.is_decimal());
566 }
else if (function_oper->
getName() ==
"ROUND" &&
570 const auto arg0 = function_oper->
getArg(0);
572 const auto arg0_lvs =
codegen(arg0,
true, co);
573 CHECK_EQ(
size_t(1), arg0_lvs.size());
574 const auto arg0_lv = arg0_lvs.front();
575 CHECK(arg0_lv->getType()->isIntegerTy(64));
577 const auto arg1 = function_oper->
getArg(1);
579 CHECK(arg1_ti.is_integer());
580 const auto arg1_lvs =
codegen(arg1,
true, co);
581 auto arg1_lv = arg1_lvs.front();
582 if (arg1_ti.get_type() !=
kINT) {
587 std::tie(bbs0, std::ignore) =
590 const std::string func_name =
"Round__4";
592 CHECK(ret_ti.is_decimal());
600 throw std::runtime_error(
"Type combination not supported for function " +
609 const std::vector<llvm::Value*>& orig_arg_lvs) {
611 llvm::Value* one_arg_null =
613 size_t physical_coord_cols = 0;
614 for (
size_t i = 0, j = 0; i < function_oper->
getArity();
615 ++i, j += std::max(
size_t(1), physical_coord_cols)) {
616 const auto arg = function_oper->
getArg(i);
619 if (arg_ti.get_notnull()) {
623 if (geo_expr_arg && arg_ti.is_geometry()) {
626 llvm::CmpInst::ICMP_EQ,
628 llvm::ConstantPointerNull::get(
633 physical_coord_cols = 2;
638 if (arg_ti.is_geometry()) {
639 auto* coords_load = llvm::dyn_cast<llvm::LoadInst>(orig_arg_lvs[i]);
645 if (arg_ti.is_geometry()) {
646 auto* coords_alloca = llvm::dyn_cast<llvm::AllocaInst>(orig_arg_lvs[j]);
647 auto* coords_phi = llvm::dyn_cast<llvm::PHINode>(orig_arg_lvs[j]);
648 if (coords_alloca || coords_phi) {
653 if (arg_ti.is_text_encoding_dict()) {
658 if (arg_ti.is_buffer() || arg_ti.is_geometry()) {
662 (arg_ti.get_type() ==
kPOINT) ?
"point_coord_array_is_null" :
"array_is_null";
668 CHECK(arg_ti.is_number() or arg_ti.is_boolean());
687 llvm::Value* row_pos,
689 bool cast_and_extend) {
699 auto len = cgen_state_->emitExternalCall(
702 {chunk, row_pos, cgen_state_->llInt(
log2_bytes(elem_ti.get_logical_size()))});
704 if (cast_and_extend) {
705 buff = castArrayPointer(buff, elem_ti);
707 cgen_state_->ir_builder_.CreateZExt(len,
get_int_type(64, cgen_state_->context_));
710 return std::make_pair(buff, len);
715 llvm::Value* buffer_buf,
716 llvm::Value* buffer_size,
717 llvm::Value* buffer_null,
718 std::vector<llvm::Value*>& output_args) {
724 cgen_state_, ext_func_name, param_num, buffer_buf->getType());
727 auto buffer_buf_ptr =
731 auto buffer_size_ptr =
736 auto buffer_null_extended =
738 auto buffer_is_null_ptr =
741 output_args.push_back(alloc_mem);
747 llvm::Function* udf_func = module_for_lookup->getFunction(udf_func_name);
749 llvm::StructType* generated_struct_type =
759 llvm::FunctionType* udf_func_type = udf_func->getFunctionType();
760 CHECK(param_num < udf_func_type->getNumParams());
761 llvm::Type* param_pointer_type = udf_func_type->getParamType(param_num);
762 CHECK(param_pointer_type->isPointerTy());
763 llvm::Type* param_type = param_pointer_type->getPointerElementType();
764 CHECK(param_type->isStructTy());
765 llvm::StructType* struct_type = llvm::cast<llvm::StructType>(param_type);
766 CHECK_EQ(struct_type->getStructNumElements(), 5u)
768 const auto expected_elems = generated_struct_type->elements();
769 const auto current_elems = struct_type->elements();
770 for (
size_t i = 0; i < expected_elems.size(); i++) {
771 CHECK_EQ(expected_elems[i], current_elems[i]);
773 if (struct_type->isLiteral()) {
777 llvm::StringRef struct_name = struct_type->getStructName();
778 #if LLVM_VERSION_MAJOR >= 12
779 llvm::StructType* point_type =
780 struct_type->getTypeByName(cgen_state_->context_, struct_name);
782 llvm::StructType* point_type = module_for_lookup->getTypeByName(struct_name);
788 return generated_struct_type;
793 llvm::Value* point_buf,
794 llvm::Value* point_size,
795 llvm::Value* compression,
796 llvm::Value* input_srid,
797 llvm::Value* output_srid,
798 std::vector<llvm::Value*>& output_args) {
813 auto point_size_ptr =
817 auto point_compression_ptr =
821 auto input_srid_ptr =
825 auto output_srid_ptr =
829 output_args.push_back(alloc_mem);
833 const std::string& udf_func_name,
836 llvm::Function* udf_func = module_for_lookup->getFunction(udf_func_name);
838 llvm::StructType* generated_struct_type =
848 llvm::FunctionType* udf_func_type = udf_func->getFunctionType();
849 CHECK(param_num < udf_func_type->getNumParams());
850 llvm::Type* param_pointer_type = udf_func_type->getParamType(param_num);
851 CHECK(param_pointer_type->isPointerTy());
852 llvm::Type* param_type = param_pointer_type->getPointerElementType();
853 CHECK(param_type->isStructTy());
854 llvm::StructType* struct_type = llvm::cast<llvm::StructType>(param_type);
855 CHECK(struct_type->isStructTy());
856 CHECK_EQ(struct_type->getStructNumElements(), 5u);
858 const auto expected_elems = generated_struct_type->elements();
859 const auto current_elems = struct_type->elements();
860 for (
size_t i = 0; i < expected_elems.size(); i++) {
861 CHECK_EQ(expected_elems[i], current_elems[i]);
863 if (struct_type->isLiteral()) {
867 llvm::StringRef struct_name = struct_type->getStructName();
868 #if LLVM_VERSION_MAJOR >= 12
869 llvm::StructType* multi_point_type =
870 struct_type->getTypeByName(cgen_state_->context_, struct_name);
872 llvm::StructType* multi_point_type = module_for_lookup->getTypeByName(struct_name);
874 CHECK(multi_point_type);
876 return multi_point_type;
878 return generated_struct_type;
883 llvm::Value* multi_point_buf,
884 llvm::Value* multi_point_size,
885 llvm::Value* compression,
886 llvm::Value* input_srid,
887 llvm::Value* output_srid,
888 std::vector<llvm::Value*>& output_args) {
890 CHECK(multi_point_buf);
891 CHECK(multi_point_size);
900 auto multi_point_buf_ptr =
904 auto multi_point_size_ptr =
908 auto compression_ptr =
912 auto input_srid_ptr =
916 auto output_srid_ptr =
920 output_args.push_back(alloc_mem);
924 const std::string& udf_func_name,
927 llvm::Function* udf_func = module_for_lookup->getFunction(udf_func_name);
929 llvm::StructType* generated_struct_type =
939 llvm::FunctionType* udf_func_type = udf_func->getFunctionType();
940 CHECK(param_num < udf_func_type->getNumParams());
941 llvm::Type* param_pointer_type = udf_func_type->getParamType(param_num);
942 CHECK(param_pointer_type->isPointerTy());
943 llvm::Type* param_type = param_pointer_type->getPointerElementType();
944 CHECK(param_type->isStructTy());
945 llvm::StructType* struct_type = llvm::cast<llvm::StructType>(param_type);
946 CHECK(struct_type->isStructTy());
947 CHECK_EQ(struct_type->getStructNumElements(), 5u);
949 const auto expected_elems = generated_struct_type->elements();
950 const auto current_elems = struct_type->elements();
951 for (
size_t i = 0; i < expected_elems.size(); i++) {
952 CHECK_EQ(expected_elems[i], current_elems[i]);
954 if (struct_type->isLiteral()) {
958 llvm::StringRef struct_name = struct_type->getStructName();
959 #if LLVM_VERSION_MAJOR >= 12
960 llvm::StructType* line_string_type =
961 struct_type->getTypeByName(cgen_state_->context_, struct_name);
963 llvm::StructType* line_string_type = module_for_lookup->getTypeByName(struct_name);
965 CHECK(line_string_type);
967 return line_string_type;
969 return generated_struct_type;
974 llvm::Value* line_string_buf,
975 llvm::Value* line_string_size,
976 llvm::Value* compression,
977 llvm::Value* input_srid,
978 llvm::Value* output_srid,
979 std::vector<llvm::Value*>& output_args) {
981 CHECK(line_string_buf);
982 CHECK(line_string_size);
991 auto line_string_buf_ptr =
995 auto line_string_size_ptr =
999 auto line_string_compression_ptr =
1003 auto input_srid_ptr =
1007 auto output_srid_ptr =
1011 output_args.push_back(alloc_mem);
1015 const std::string& udf_func_name,
1018 llvm::Function* udf_func = module_for_lookup->getFunction(udf_func_name);
1020 llvm::StructType* generated_struct_type =
1032 llvm::FunctionType* udf_func_type = udf_func->getFunctionType();
1033 CHECK(param_num < udf_func_type->getNumParams());
1034 llvm::Type* param_pointer_type = udf_func_type->getParamType(param_num);
1035 CHECK(param_pointer_type->isPointerTy());
1036 llvm::Type* param_type = param_pointer_type->getPointerElementType();
1037 CHECK(param_type->isStructTy());
1038 llvm::StructType* struct_type = llvm::cast<llvm::StructType>(param_type);
1039 CHECK(struct_type->isStructTy());
1040 CHECK_EQ(struct_type->getStructNumElements(), 7u);
1042 const auto expected_elems = generated_struct_type->elements();
1043 const auto current_elems = struct_type->elements();
1044 for (
size_t i = 0; i < expected_elems.size(); i++) {
1045 CHECK_EQ(expected_elems[i], current_elems[i]);
1047 if (struct_type->isLiteral()) {
1051 llvm::StringRef struct_name = struct_type->getStructName();
1052 #if LLVM_VERSION_MAJOR >= 12
1053 llvm::StructType* multi_linestring_type =
1054 struct_type->getTypeByName(cgen_state_->context_, struct_name);
1056 llvm::StructType* multi_linestring_type =
1057 module_for_lookup->getTypeByName(struct_name);
1059 CHECK(multi_linestring_type);
1061 return multi_linestring_type;
1063 return generated_struct_type;
1067 const std::string& udf_func_name,
1069 llvm::Value* multi_linestring_coords,
1070 llvm::Value* multi_linestring_coords_size,
1071 llvm::Value* linestring_sizes,
1072 llvm::Value* linestring_sizes_size,
1073 llvm::Value* compression,
1074 llvm::Value* input_srid,
1075 llvm::Value* output_srid,
1076 std::vector<llvm::Value*>& output_args) {
1078 CHECK(multi_linestring_coords);
1079 CHECK(multi_linestring_coords_size);
1080 CHECK(linestring_sizes);
1081 CHECK(linestring_sizes_size);
1086 auto multi_linestring_abstraction =
1092 multi_linestring_abstraction, alloc_mem, 0);
1094 multi_linestring_coords_ptr);
1097 multi_linestring_abstraction, alloc_mem, 1);
1099 multi_linestring_coords_size_ptr);
1102 multi_linestring_abstraction, alloc_mem, 2);
1103 const auto linestring_sizes_ptr_ty =
1104 llvm::dyn_cast<llvm::PointerType>(linestring_sizes_ptr->getType());
1105 CHECK(linestring_sizes_ptr_ty);
1108 linestring_sizes, linestring_sizes_ptr_ty->getPointerElementType()),
1109 linestring_sizes_ptr);
1112 multi_linestring_abstraction, alloc_mem, 3);
1116 multi_linestring_abstraction, alloc_mem, 4);
1120 multi_linestring_abstraction, alloc_mem, 5);
1124 multi_linestring_abstraction, alloc_mem, 6);
1127 output_args.push_back(alloc_mem);
1133 llvm::Function* udf_func = module_for_lookup->getFunction(udf_func_name);
1135 llvm::StructType* generated_struct_type =
1147 llvm::FunctionType* udf_func_type = udf_func->getFunctionType();
1148 CHECK(param_num < udf_func_type->getNumParams());
1149 llvm::Type* param_pointer_type = udf_func_type->getParamType(param_num);
1150 CHECK(param_pointer_type->isPointerTy());
1151 llvm::Type* param_type = param_pointer_type->getPointerElementType();
1152 CHECK(param_type->isStructTy());
1153 llvm::StructType* struct_type = llvm::cast<llvm::StructType>(param_type);
1155 CHECK(struct_type->isStructTy());
1156 CHECK_EQ(struct_type->getStructNumElements(), 7u);
1158 const auto expected_elems = generated_struct_type->elements();
1159 const auto current_elems = struct_type->elements();
1160 for (
size_t i = 0; i < expected_elems.size(); i++) {
1161 CHECK_EQ(expected_elems[i], current_elems[i]);
1163 if (struct_type->isLiteral()) {
1167 llvm::StringRef struct_name = struct_type->getStructName();
1169 #if LLVM_VERSION_MAJOR >= 12
1170 llvm::StructType* polygon_type =
1171 struct_type->getTypeByName(cgen_state_->context_, struct_name);
1173 llvm::StructType* polygon_type = module_for_lookup->getTypeByName(struct_name);
1175 CHECK(polygon_type);
1177 return polygon_type;
1179 return generated_struct_type;
1184 llvm::Value* polygon_buf,
1185 llvm::Value* polygon_size,
1186 llvm::Value* ring_sizes_buf,
1187 llvm::Value* num_rings,
1188 llvm::Value* compression,
1189 llvm::Value* input_srid,
1190 llvm::Value* output_srid,
1191 std::vector<llvm::Value*>& output_args) {
1194 CHECK(polygon_size);
1195 CHECK(ring_sizes_buf);
1204 auto alloc_mem = builder.CreateAlloca(polygon_abstraction,
nullptr);
1206 const auto polygon_buf_ptr = builder.CreateStructGEP(polygon_abstraction, alloc_mem, 0);
1207 builder.CreateStore(polygon_buf, polygon_buf_ptr);
1209 const auto polygon_size_ptr =
1210 builder.CreateStructGEP(polygon_abstraction, alloc_mem, 1);
1211 builder.CreateStore(polygon_size, polygon_size_ptr);
1213 const auto ring_sizes_buf_ptr =
1214 builder.CreateStructGEP(polygon_abstraction, alloc_mem, 2);
1215 const auto ring_sizes_ptr_ty =
1216 llvm::dyn_cast<llvm::PointerType>(ring_sizes_buf_ptr->getType());
1217 CHECK(ring_sizes_ptr_ty);
1218 builder.CreateStore(
1219 builder.CreateBitCast(ring_sizes_buf, ring_sizes_ptr_ty->getPointerElementType()),
1220 ring_sizes_buf_ptr);
1222 const auto ring_size_ptr = builder.CreateStructGEP(polygon_abstraction, alloc_mem, 3);
1223 builder.CreateStore(num_rings, ring_size_ptr);
1225 const auto polygon_compression_ptr =
1226 builder.CreateStructGEP(polygon_abstraction, alloc_mem, 4);
1227 builder.CreateStore(compression, polygon_compression_ptr);
1229 const auto input_srid_ptr = builder.CreateStructGEP(polygon_abstraction, alloc_mem, 5);
1230 builder.CreateStore(input_srid, input_srid_ptr);
1232 const auto output_srid_ptr = builder.CreateStructGEP(polygon_abstraction, alloc_mem, 6);
1233 builder.CreateStore(output_srid, output_srid_ptr);
1235 output_args.push_back(alloc_mem);
1239 const std::string& udf_func_name,
1243 llvm::StructType* generated_struct_type =
1257 llvm::FunctionType* udf_func_type = udf_func->getFunctionType();
1258 CHECK(param_num < udf_func_type->getNumParams());
1259 llvm::Type* param_pointer_type = udf_func_type->getParamType(param_num);
1260 CHECK(param_pointer_type->isPointerTy());
1261 llvm::Type* param_type = param_pointer_type->getPointerElementType();
1262 CHECK(param_type->isStructTy());
1263 llvm::StructType* struct_type = llvm::cast<llvm::StructType>(param_type);
1264 CHECK(struct_type->isStructTy());
1265 CHECK_EQ(struct_type->getStructNumElements(), 9u);
1266 const auto expected_elems = generated_struct_type->elements();
1267 const auto current_elems = struct_type->elements();
1268 for (
size_t i = 0; i < expected_elems.size(); i++) {
1269 CHECK_EQ(expected_elems[i], current_elems[i]);
1271 if (struct_type->isLiteral()) {
1274 llvm::StringRef struct_name = struct_type->getStructName();
1276 #if LLVM_VERSION_MAJOR >= 12
1277 llvm::StructType* polygon_type =
1278 struct_type->getTypeByName(cgen_state_->context_, struct_name);
1280 llvm::StructType* polygon_type = cgen_state_->module_->getTypeByName(struct_name);
1282 CHECK(polygon_type);
1284 return polygon_type;
1286 return generated_struct_type;
1291 llvm::Value* polygon_coords,
1292 llvm::Value* polygon_coords_size,
1293 llvm::Value* ring_sizes_buf,
1294 llvm::Value* ring_sizes,
1295 llvm::Value* polygon_bounds,
1296 llvm::Value* polygon_bounds_sizes,
1297 llvm::Value* compression,
1298 llvm::Value* input_srid,
1299 llvm::Value* output_srid,
1300 std::vector<llvm::Value*>& output_args) {
1302 CHECK(polygon_coords);
1303 CHECK(polygon_coords_size);
1304 CHECK(ring_sizes_buf);
1306 CHECK(polygon_bounds);
1307 CHECK(polygon_bounds_sizes);
1315 auto alloc_mem = builder.CreateAlloca(multi_polygon_abstraction,
nullptr);
1317 const auto polygon_coords_ptr =
1318 builder.CreateStructGEP(multi_polygon_abstraction, alloc_mem, 0);
1319 builder.CreateStore(polygon_coords, polygon_coords_ptr);
1321 const auto polygon_coords_size_ptr =
1322 builder.CreateStructGEP(multi_polygon_abstraction, alloc_mem, 1);
1323 builder.CreateStore(polygon_coords_size, polygon_coords_size_ptr);
1325 const auto ring_sizes_buf_ptr =
1326 builder.CreateStructGEP(multi_polygon_abstraction, alloc_mem, 2);
1327 const auto ring_sizes_ptr_ty =
1328 llvm::dyn_cast<llvm::PointerType>(ring_sizes_buf_ptr->getType());
1329 CHECK(ring_sizes_ptr_ty);
1330 builder.CreateStore(
1331 builder.CreateBitCast(ring_sizes_buf, ring_sizes_ptr_ty->getPointerElementType()),
1332 ring_sizes_buf_ptr);
1334 const auto ring_sizes_ptr =
1335 builder.CreateStructGEP(multi_polygon_abstraction, alloc_mem, 3);
1336 builder.CreateStore(ring_sizes, ring_sizes_ptr);
1338 const auto polygon_bounds_buf_ptr =
1339 builder.CreateStructGEP(multi_polygon_abstraction, alloc_mem, 4);
1340 const auto bounds_ptr_ty =
1341 llvm::dyn_cast<llvm::PointerType>(polygon_bounds_buf_ptr->getType());
1342 CHECK(bounds_ptr_ty);
1343 builder.CreateStore(
1344 builder.CreateBitCast(polygon_bounds, bounds_ptr_ty->getPointerElementType()),
1345 polygon_bounds_buf_ptr);
1347 const auto polygon_bounds_sizes_ptr =
1348 builder.CreateStructGEP(multi_polygon_abstraction, alloc_mem, 5);
1349 builder.CreateStore(polygon_bounds_sizes, polygon_bounds_sizes_ptr);
1351 const auto polygon_compression_ptr =
1352 builder.CreateStructGEP(multi_polygon_abstraction, alloc_mem, 6);
1353 builder.CreateStore(compression, polygon_compression_ptr);
1355 const auto input_srid_ptr =
1356 builder.CreateStructGEP(multi_polygon_abstraction, alloc_mem, 7);
1357 builder.CreateStore(input_srid, input_srid_ptr);
1359 const auto output_srid_ptr =
1360 builder.CreateStructGEP(multi_polygon_abstraction, alloc_mem, 8);
1361 builder.CreateStore(output_srid, output_srid_ptr);
1363 output_args.push_back(alloc_mem);
1371 const std::vector<llvm::Value*>& orig_arg_lvs,
1372 const std::vector<size_t>& orig_arg_lvs_index,
1373 const std::unordered_map<llvm::Value*, llvm::Value*>& const_arr_size,
1376 CHECK(ext_func_sig);
1377 const auto& ext_func_args = ext_func_sig->
getInputArgs();
1380 std::vector<llvm::Value*>
args;
1388 for (
size_t i = 0, j = 0, dj = (func_ti.is_buffer() ? 1 : 0);
1391 size_t k = orig_arg_lvs_index[i];
1393 const auto arg = function_oper->
getArg(i);
1394 const auto ext_func_arg = ext_func_args[ij];
1396 llvm::Value* arg_lv{
nullptr};
1397 if (arg_ti.is_text_encoding_none()) {
1400 const auto ptr_lv = orig_arg_lvs[k + 1];
1401 const auto len_lv = orig_arg_lvs[k + 2];
1403 auto string_buf_arg = builder.CreatePointerCast(
1405 auto string_size_arg =
1414 }
else if (arg_ti.is_text_encoding_dict()) {
1417 arg_lv = orig_arg_lvs[k];
1418 args.push_back(arg_lv);
1419 }
else if (arg_ti.is_array()) {
1420 bool const_arr = (const_arr_size.count(orig_arg_lvs[k]) > 0);
1421 const auto elem_ti = arg_ti.get_elem_type();
1423 const auto ptr_lv = (const_arr)
1428 {orig_arg_lvs[k],
posArg(arg)});
1430 (const_arr) ? const_arr_size.at(orig_arg_lvs[k])
1446 auto array_size_arg =
1448 llvm::Value* array_null_arg =
nullptr;
1449 if (
auto gep = llvm::dyn_cast<llvm::GetElementPtrInst>(ptr_lv)) {
1450 CHECK(gep->getSourceElementType()->isArrayTy());
1460 {orig_arg_lvs[k],
posArg(arg)});
1472 }
else if (arg_ti.is_geometry()) {
1477 args.push_back(ptr_lv);
1481 args.push_back(size_lv);
1486 bool const_arr = (const_arr_size.count(orig_arg_lvs[k]) > 0);
1497 llvm::Value* ptr_lv;
1498 llvm::Value* len_lv;
1499 int32_t fixlen = -1;
1500 if (arg_ti.get_type() ==
kPOINT) {
1503 const auto coords_cd =
executor()->getPhysicalColumnDescriptor(col_var, 1);
1504 if (coords_cd && coords_cd->columnType.get_type() ==
kARRAY) {
1505 fixlen = coords_cd->columnType.get_size();
1513 {orig_arg_lvs[k],
posArg(arg)});
1517 ptr_lv = (const_arr) ? orig_arg_lvs[k]
1521 {orig_arg_lvs[k],
posArg(arg)});
1522 len_lv = (const_arr)
1523 ? const_arr_size.at(orig_arg_lvs[k])
1540 if (arg_ti.get_type() ==
kPOINT) {
1580 switch (arg_ti.get_type()) {
1592 auto [linestring_sizes, linestring_sizes_size] =
1600 multi_linestring_coords,
1603 linestring_sizes_size,
1611 auto const_arr = const_arr_size.count(orig_arg_lvs[k + 1]) > 0;
1612 auto [linestring_sizes, linestring_sizes_size] =
1613 (const_arr) ? std::make_pair(orig_arg_lvs[k + 1],
1614 const_arr_size.at(orig_arg_lvs[k + 1]))
1619 args.push_back(linestring_sizes);
1620 args.push_back(linestring_sizes_size);
1632 auto [ring_size_buff, ring_size] =
1651 auto const_arr = const_arr_size.count(orig_arg_lvs[k + 1]) > 0;
1652 auto [ring_size_buff, ring_size] =
1653 (const_arr) ? std::make_pair(orig_arg_lvs[k + 1],
1654 const_arr_size.at(orig_arg_lvs[k + 1]))
1659 args.push_back(ring_size_buff);
1660 args.push_back(ring_size);
1672 auto [ring_size_buff, ring_size] =
1678 auto [poly_bounds_buff, poly_bounds_size] =
1700 auto const_arr = const_arr_size.count(orig_arg_lvs[k + 1]) > 0;
1701 auto [ring_size_buff, ring_size] =
1702 (const_arr) ? std::make_pair(orig_arg_lvs[k + 1],
1703 const_arr_size.at(orig_arg_lvs[k + 1]))
1709 args.push_back(ring_size_buff);
1710 args.push_back(ring_size);
1714 auto const_arr = const_arr_size.count(orig_arg_lvs[k + 2]) > 0;
1715 auto [poly_bounds_buff, poly_bounds_size] =
1717 ? std::make_pair(orig_arg_lvs[k + 2],
1718 const_arr_size.at(orig_arg_lvs[k + 2]))
1722 args.push_back(poly_bounds_buff);
1723 args.push_back(poly_bounds_size);
1735 if (arg_ti.get_type() != arg_target_ti.get_type()) {
1736 arg_lv = codegenCast(orig_arg_lvs[k], arg_ti, arg_target_ti,
false, co);
1738 arg_lv = orig_arg_lvs[k];
1742 args.push_back(arg_lv);
1782 auto*
const string_view_type =
1786 string_view_type->setName(
"StringView");
1787 return string_view_type;
llvm::StructType * createLineStringStructType(const std::string &udf_func_name, size_t param_num)
void codegenGeoMultiPolygonArgs(const std::string &udf_func_name, size_t param_num, llvm::Value *polygon_coords, llvm::Value *polygon_coords_size, llvm::Value *ring_sizes_buf, llvm::Value *ring_sizes, llvm::Value *polygon_bounds, llvm::Value *polygon_bounds_sizes, llvm::Value *compression, llvm::Value *input_srid, llvm::Value *output_srid, std::vector< llvm::Value * > &output_args)
llvm::BasicBlock * orig_bb
HOST DEVICE int get_size() const
bool is_ext_arg_type_scalar(const ExtArgumentType ext_arg_type)
llvm::BasicBlock * args_notnull_bb
std::unique_ptr< llvm::Module > udf_gpu_module
const ExtArgumentType getRet() const
void codegenGeoPolygonArgs(const std::string &udf_func_name, size_t param_num, llvm::Value *polygon_buf, llvm::Value *polygon_size, llvm::Value *ring_sizes_buf, llvm::Value *num_rings, llvm::Value *compression, llvm::Value *input_srid, llvm::Value *output_srid, std::vector< llvm::Value * > &output_args)
llvm::StructType * createMultiPointStructType(const std::string &udf_func_name, size_t param_num)
std::vector< llvm::Value * > codegenFunctionOperCastArgs(const Analyzer::FunctionOper *, const ExtensionFunction *, const std::vector< llvm::Value * > &, const std::vector< size_t > &, const std::unordered_map< llvm::Value *, llvm::Value * > &, const CompilationOptions &)
llvm::StructType * createMultiLineStringStructType(const std::string &udf_func_name, size_t param_num)
llvm::Value * codegenFunctionOperNullArg(const Analyzer::FunctionOper *, const std::vector< llvm::Value * > &)
llvm::IRBuilder ir_builder_
llvm::Value * posArg(const Analyzer::Expr *) const
llvm::Value * castArrayPointer(llvm::Value *ptr, const SQLTypeInfo &elem_ti)
llvm::Type * get_fp_type(const int width, llvm::LLVMContext &context)
llvm::StructType * createPointStructType(const std::string &udf_func_name, size_t param_num)
bool call_requires_custom_type_handling(const Analyzer::FunctionOper *function_oper)
const std::string getName(bool keep_suffix=true) const
HOST DEVICE SQLTypes get_type() const
llvm::Type * get_int_type(const int width, llvm::LLVMContext &context)
bool ext_func_call_requires_nullcheck(const Analyzer::FunctionOper *function_oper)
SQLTypeInfo get_sql_type_from_llvm_type(const llvm::Type *ll_type)
llvm::StructType * get_buffer_struct_type(CgenState *cgen_state, const std::string &ext_func_name, size_t param_num, llvm::Type *elem_type)
std::vector< FunctionOperValue > ext_call_cache_
void codegenBufferArgs(const std::string &udf_func_name, size_t param_num, llvm::Value *buffer_buf, llvm::Value *buffer_size, llvm::Value *buffer_is_null, std::vector< llvm::Value * > &output_args)
llvm::Function * row_func_
RUNTIME_EXPORT void register_buffer_with_executor_rsm(int64_t exec, int8_t *buffer)
std::pair< llvm::Value *, llvm::Value * > codegenArrayBuff(llvm::Value *chunk, llvm::Value *row_pos, SQLTypes array_type, bool cast_and_extend)
Supported runtime functions management and retrieval.
llvm::LLVMContext & context_
llvm::Function * current_func_
std::tuple< ArgNullcheckBBs, llvm::Value * > beginArgsNullcheck(const Analyzer::FunctionOper *function_oper, const std::vector< llvm::Value * > &orig_arg_lvs)
llvm::Value * emitExternalCall(const std::string &fname, llvm::Type *ret_type, const std::vector< llvm::Value * > args, const std::vector< llvm::Attribute::AttrKind > &fnattrs={}, const bool has_struct_return=false)
llvm::Value * get_arg_by_name(llvm::Function *func, const std::string &name)
DEVICE auto copy(ARGS &&...args)
llvm::ConstantInt * inlineIntNull(const SQLTypeInfo &)
bool is_ext_arg_type_geo(const ExtArgumentType ext_arg_type)
void codegenGeoMultiPointArgs(const std::string &udf_func_name, size_t param_num, llvm::Value *multi_point_buf, llvm::Value *multi_point_size, llvm::Value *compression, llvm::Value *input_srid, llvm::Value *output_srid, std::vector< llvm::Value * > &output_args)
bool is_ext_arg_type_array(const ExtArgumentType ext_arg_type)
llvm::Value * codegenFunctionOper(const Analyzer::FunctionOper *, const CompilationOptions &)
llvm::Type * get_llvm_type_from_sql_array_type(const SQLTypeInfo ti, llvm::LLVMContext &ctx)
llvm::BasicBlock * args_null_bb
llvm::Type * ext_arg_type_to_llvm_type(const ExtArgumentType ext_arg_type, llvm::LLVMContext &ctx)
void codegenGeoMultiLineStringArgs(const std::string &udf_func_name, size_t param_num, llvm::Value *multi_linestring_coords, llvm::Value *multi_linestring_size, llvm::Value *linestring_sizes, llvm::Value *linestring_sizes_size, llvm::Value *compression, llvm::Value *input_srid, llvm::Value *output_srid, std::vector< llvm::Value * > &output_args)
std::string toString(const Executor::ExtModuleKinds &kind)
std::tuple< T, std::vector< SQLTypeInfo > > bind_function(std::string name, Analyzer::ExpressionPtrVector func_args, const std::vector< T > &ext_funcs, const std::string processor)
Argument type based extension function binding.
const SQLTypeInfo & get_type_info() const
llvm::Value * emitCall(const std::string &fname, const std::vector< llvm::Value * > &args)
ExecutorDeviceType device_type
void codegenGeoPointArgs(const std::string &udf_func_name, size_t param_num, llvm::Value *point_buf, llvm::Value *point_size, llvm::Value *compression, llvm::Value *input_srid, llvm::Value *output_srid, std::vector< llvm::Value * > &output_args)
std::vector< llvm::Value * > codegen(const Analyzer::Expr *, const bool fetch_columns, const CompilationOptions &)
HOST DEVICE EncodingType get_compression() const
std::string serialize_llvm_object(const T *llvm_obj)
bool isLocalAlloc() const
llvm::StructType * createPolygonStructType(const std::string &udf_func_name, size_t param_num)
const Analyzer::Expr * getArg(const size_t i) const
const Expr * get_operand() const
llvm::Value * endArgsNullcheck(const ArgNullcheckBBs &, llvm::Value *, llvm::Value *, const Analyzer::FunctionOper *)
const std::vector< ExtArgumentType > & getInputArgs() const
llvm::StructType * createStringViewStructType()
std::unique_ptr< llvm::Module > udf_cpu_module
HOST DEVICE int get_comp_param() const
llvm::Value * codegenFunctionOperWithCustomTypeHandling(const Analyzer::FunctionOperWithCustomTypeHandling *, const CompilationOptions &)
llvm::ConstantInt * llInt(const T v) const
llvm::Value * codegenIsNullNumber(llvm::Value *, const SQLTypeInfo &)
uint64_t exp_to_scale(const unsigned exp)
llvm::ConstantInt * ll_bool(const bool v, llvm::LLVMContext &context)
llvm::Value * codegenCompression(const SQLTypeInfo &type_info)
llvm::Value * codegenCast(const Analyzer::UOper *, const CompilationOptions &)
uint32_t log2_bytes(const uint32_t bytes)
std::string getName() const
void codegenGeoLineStringArgs(const std::string &udf_func_name, size_t param_num, llvm::Value *line_string_buf, llvm::Value *line_string_size, llvm::Value *compression, llvm::Value *input_srid, llvm::Value *output_srid, std::vector< llvm::Value * > &output_args)
bool is_text_encoding_none() const
bool is_ext_arg_type_pointer(const ExtArgumentType ext_arg_type)
SQLTypeInfo get_elem_type() const
int get_physical_coord_cols() const
SQLTypeInfo ext_arg_type_to_type_info(const ExtArgumentType ext_arg_type)
llvm::ConstantFP * inlineFpNull(const SQLTypeInfo &)
Executor * executor() const
llvm::StructType * createMultiPolygonStructType(const std::string &udf_func_name, size_t param_num)