31 const std::string& ext_func_name,
36 CHECK(elem_type->isPointerTy());
37 llvm::StructType* generated_struct_type =
38 (has_is_null ? llvm::StructType::get(cgen_state->
context_,
40 llvm::Type::getInt64Ty(cgen_state->
context_),
41 llvm::Type::getInt8Ty(cgen_state->
context_)},
43 : llvm::StructType::get(
45 {elem_type, llvm::Type::getInt64Ty(cgen_state->context_)},
47 llvm::Function* udf_func = cgen_state->module_->getFunction(ext_func_name);
52 llvm::FunctionType* udf_func_type = udf_func->getFunctionType();
53 CHECK_LE(param_num, udf_func_type->getNumParams());
54 llvm::Type* param_pointer_type = udf_func_type->getParamType(param_num);
55 CHECK(param_pointer_type->isPointerTy());
56 llvm::Type* param_type = param_pointer_type->getPointerElementType();
57 CHECK(param_type->isStructTy());
58 llvm::StructType* struct_type = llvm::cast<llvm::StructType>(param_type);
59 CHECK_GE(struct_type->getStructNumElements(),
60 generated_struct_type->getStructNumElements())
63 const auto expected_elems = generated_struct_type->elements();
64 const auto current_elems = struct_type->elements();
65 for (
size_t i = 0; i < expected_elems.size(); i++) {
66 CHECK_EQ(expected_elems[i], current_elems[i])
71 if (struct_type->isLiteral()) {
75 llvm::StringRef struct_name = struct_type->getStructName();
76 #if LLVM_VERSION_MAJOR >= 12
77 return struct_type->getTypeByName(cgen_state->context_, struct_name);
79 return cgen_state->module_->getTypeByName(struct_name);
82 return generated_struct_type;
86 llvm::LLVMContext& ctx) {
87 switch (ext_arg_type) {
98 return llvm::Type::getFloatTy(ctx);
100 return llvm::Type::getDoubleTy(ctx);
124 return llvm::Type::getVoidTy(ctx);
134 const auto bits = ll_type->getPrimitiveSizeInBits();
136 if (ll_type->isFloatingPointTy()) {
143 LOG(
FATAL) <<
"Unsupported llvm floating point type: " << bits
144 <<
", only 32 and 64 bit floating point is supported.";
159 LOG(
FATAL) <<
"Unrecognized llvm type for SQL type: "
168 llvm::LLVMContext& ctx) {
171 return llvm::Type::getInt8PtrTy(ctx);
175 if (elem_ti.is_fp()) {
176 switch (elem_ti.get_size()) {
178 return llvm::Type::getFloatPtrTy(ctx);
180 return llvm::Type::getDoublePtrTy(ctx);
184 if (elem_ti.is_boolean()) {
185 return llvm::Type::getInt8PtrTy(ctx);
188 CHECK(elem_ti.is_integer());
189 switch (elem_ti.get_size()) {
191 return llvm::Type::getInt8PtrTy(ctx);
193 return llvm::Type::getInt16PtrTy(ctx);
195 return llvm::Type::getInt32PtrTy(ctx);
197 return llvm::Type::getInt64PtrTy(ctx);
206 for (
size_t i = 0; i < function_oper->
getArity(); ++i) {
207 const auto arg = function_oper->
getArg(i);
209 if ((func_ti.is_array() && arg_ti.is_array()) ||
210 (func_ti.is_bytes() && arg_ti.is_bytes())) {
216 }
else if (!arg_ti.get_notnull() && !arg_ti.is_buffer()) {
230 Executor* exec_ptr =
reinterpret_cast<Executor*
>(exec);
231 if (buffer !=
nullptr) {
232 exec_ptr->getRowSetMemoryOwner()->addVarlenBuffer(buffer);
245 LOG(
WARNING) <<
"codegenFunctionOper[GPU]: " << e.what() <<
" Redirecting "
246 << function_oper->
getName() <<
" to run on CPU.";
253 LOG(
WARNING) <<
"codegenFunctionOper[CPU]: " << e.what();
260 CHECK(ret_ti.is_integer() || ret_ti.is_fp() || ret_ti.is_boolean() ||
273 if (*it.foper == *function_oper) {
274 auto inst = llvm::dyn_cast<llvm::Instruction>(it.lv);
275 if (inst && inst->getParent() == current_bb) {
280 std::vector<llvm::Value*> orig_arg_lvs;
281 std::vector<size_t> orig_arg_lvs_index;
282 std::unordered_map<llvm::Value*, llvm::Value*> const_arr_size;
284 for (
size_t i = 0; i < function_oper->
getArity(); ++i) {
285 orig_arg_lvs_index.push_back(orig_arg_lvs.size());
286 const auto arg = function_oper->
getArg(i);
289 (arg_cast && arg_cast->get_optype() ==
kCAST) ? arg_cast->
get_operand() : arg;
291 auto is_local_alloc = array_expr_arg && array_expr_arg->
isLocalAlloc();
292 const auto& arg_ti = arg->get_type_info();
293 const auto arg_lvs =
codegen(arg,
true, co);
298 if ((geo_uoper_arg || geo_binoper_arg) && arg_ti.is_geometry()) {
300 CHECK_EQ(2 * static_cast<size_t>(arg_ti.get_physical_coord_cols()), arg_lvs.size());
301 for (
size_t i = 0; i < arg_lvs.size(); i++) {
302 auto arr = arg_lvs[i++];
303 auto size = arg_lvs[i];
304 orig_arg_lvs.push_back(arr);
305 const_arr_size[arr] = size;
307 }
else if (geo_expr_arg && geo_expr_arg->get_type_info().is_geometry()) {
308 CHECK(geo_expr_arg->get_type_info().get_type() ==
kPOINT);
309 CHECK_EQ(arg_lvs.size(), size_t(2));
310 for (
size_t j = 0; j < arg_lvs.size(); j++) {
311 orig_arg_lvs.push_back(arg_lvs[j]);
313 }
else if (arg_ti.is_geometry()) {
314 CHECK_EQ(static_cast<size_t>(arg_ti.get_physical_coord_cols()), arg_lvs.size());
315 for (
size_t j = 0; j < arg_lvs.size(); j++) {
316 orig_arg_lvs.push_back(arg_lvs[j]);
318 }
else if (arg_ti.is_bytes()) {
319 CHECK_EQ(
size_t(3), arg_lvs.size());
325 for (
size_t j = 0; j < arg_lvs.size(); j++) {
326 orig_arg_lvs.push_back(arg_lvs[j]);
329 if (arg_lvs.size() > 1) {
330 CHECK(arg_ti.is_array());
331 CHECK_EQ(
size_t(2), arg_lvs.size());
332 const_arr_size[arg_lvs.front()] = arg_lvs.back();
334 CHECK_EQ(
size_t(1), arg_lvs.size());
338 if (is_local_alloc && arg_ti.get_size() > 0) {
342 orig_arg_lvs.push_back(arg_lvs.front());
353 function_oper, &ext_func_sig, orig_arg_lvs, orig_arg_lvs_index, const_arr_size, co);
355 llvm::Value* buffer_ret{
nullptr};
356 if (ret_ti.is_buffer()) {
358 CHECK(ret_ti.is_array() || ret_ti.is_bytes());
365 ret_ti.is_array() || ret_ti.is_bytes());
367 args.insert(args.begin(), buffer_ret);
371 ext_func_sig.
getName(), ret_ty,
args, {}, ret_ti.is_buffer());
373 bbs, ret_ti.is_buffer() ? buffer_ret : ext_call, null_buffer_ptr, function_oper);
376 if (!(ret_ti.is_buffer())) {
378 if (bbs.args_null_bb &&
385 function_oper->
getName().substr(0, 3) != std::string(
"ST_")) {
386 ext_call_nullcheck =
codegenCast(ext_call_nullcheck,
395 return ext_call_nullcheck;
399 std::tuple<CodeGenerator::ArgNullcheckBBs, llvm::Value*>
401 const std::vector<llvm::Value*>& orig_arg_lvs) {
403 llvm::BasicBlock* args_null_bb{
nullptr};
404 llvm::BasicBlock* args_notnull_bb{
nullptr};
406 llvm::Value* null_array_alloca{
nullptr};
410 if (func_ti.is_buffer()) {
416 func_ti.is_array() || func_ti.is_bytes());
421 args_notnull_bb = llvm::BasicBlock::Create(
423 args_null_bb = llvm::BasicBlock::Create(
428 return std::make_tuple(
436 llvm::Value* fn_ret_lv,
437 llvm::Value* null_array_ptr,
445 llvm::PHINode* ext_call_phi{
nullptr};
446 llvm::Value* null_lv{
nullptr};
448 if (!func_ti.is_buffer()) {
453 extension_ret_ti.is_fp()
459 extension_ret_ti.is_fp()
472 CHECK(null_array_ptr);
473 const auto arr_null_bool =
479 const auto arr_null_size =
486 ext_call_phi->addIncoming(func_ti.is_buffer() ? null_array_ptr : null_lv,
498 if (!ret_ti.is_integer() && !ret_ti.is_fp()) {
501 for (
size_t i = 0; i < function_oper->
getArity(); ++i) {
502 const auto arg = function_oper->
getArg(i);
504 if (!arg_ti.is_integer() && !arg_ti.is_fp()) {
519 if (function_oper->
getName() ==
"FLOOR" || function_oper->
getName() ==
"CEIL") {
521 const auto arg = function_oper->
getArg(0);
523 CHECK(arg_ti.is_decimal());
524 const auto arg_lvs =
codegen(arg,
true, co);
525 CHECK_EQ(
size_t(1), arg_lvs.size());
526 const auto arg_lv = arg_lvs.front();
527 CHECK(arg_lv->getType()->isIntegerTy(64));
530 const std::string func_name =
531 (function_oper->
getName() ==
"FLOOR") ?
"decimal_floor" :
"decimal_ceil";
535 CHECK(ret_ti.is_decimal());
540 }
else if (function_oper->
getName() ==
"ROUND" &&
544 const auto arg0 = function_oper->
getArg(0);
546 const auto arg0_lvs =
codegen(arg0,
true, co);
547 CHECK_EQ(
size_t(1), arg0_lvs.size());
548 const auto arg0_lv = arg0_lvs.front();
549 CHECK(arg0_lv->getType()->isIntegerTy(64));
551 const auto arg1 = function_oper->
getArg(1);
553 CHECK(arg1_ti.is_integer());
554 const auto arg1_lvs =
codegen(arg1,
true, co);
555 auto arg1_lv = arg1_lvs.front();
556 if (arg1_ti.get_type() !=
kINT) {
561 std::tie(bbs0, std::ignore) =
564 const std::string func_name =
"Round__4";
566 CHECK(ret_ti.is_decimal());
574 throw std::runtime_error(
"Type combination not supported for function " +
583 const std::vector<llvm::Value*>& orig_arg_lvs) {
585 llvm::Value* one_arg_null =
587 size_t physical_coord_cols = 0;
588 for (
size_t i = 0, j = 0; i < function_oper->
getArity();
589 ++i, j += std::max(
size_t(1), physical_coord_cols)) {
590 const auto arg = function_oper->
getArg(i);
593 if (arg_ti.get_notnull()) {
597 if (geo_expr_arg && arg_ti.is_geometry()) {
600 llvm::CmpInst::ICMP_EQ,
602 llvm::ConstantPointerNull::get(
607 physical_coord_cols = 2;
612 if (arg_ti.is_geometry()) {
613 auto* coords_load = llvm::dyn_cast<llvm::LoadInst>(orig_arg_lvs[i]);
619 if (arg_ti.is_geometry()) {
620 auto* coords_alloca = llvm::dyn_cast<llvm::AllocaInst>(orig_arg_lvs[j]);
621 auto* coords_phi = llvm::dyn_cast<llvm::PHINode>(orig_arg_lvs[j]);
622 if (coords_alloca || coords_phi) {
627 if (arg_ti.is_buffer() || arg_ti.is_geometry()) {
631 (arg_ti.get_type() ==
kPOINT) ?
"point_coord_array_is_null" :
"array_is_null";
637 CHECK(arg_ti.is_number() or arg_ti.is_boolean());
656 llvm::Value* row_pos,
658 bool cast_and_extend) {
668 auto len = cgen_state_->emitExternalCall(
671 {chunk, row_pos, cgen_state_->llInt(
log2_bytes(elem_ti.get_logical_size()))});
673 if (cast_and_extend) {
674 buff = castArrayPointer(buff, elem_ti);
676 cgen_state_->ir_builder_.CreateZExt(len,
get_int_type(64, cgen_state_->context_));
679 return std::make_pair(buff, len);
684 llvm::Value* buffer_buf,
685 llvm::Value* buffer_size,
686 llvm::Value* buffer_null,
687 std::vector<llvm::Value*>& output_args) {
693 cgen_state_, ext_func_name, param_num, buffer_buf->getType(), !!(buffer_null));
696 auto buffer_buf_ptr =
700 auto buffer_size_ptr =
706 auto buffer_null_extended =
708 auto buffer_is_null_ptr =
712 output_args.push_back(alloc_mem);
718 llvm::Function* udf_func = module_for_lookup->getFunction(udf_func_name);
720 llvm::StructType* generated_struct_type =
730 llvm::FunctionType* udf_func_type = udf_func->getFunctionType();
731 CHECK(param_num < udf_func_type->getNumParams());
732 llvm::Type* param_pointer_type = udf_func_type->getParamType(param_num);
733 CHECK(param_pointer_type->isPointerTy());
734 llvm::Type* param_type = param_pointer_type->getPointerElementType();
735 CHECK(param_type->isStructTy());
736 llvm::StructType* struct_type = llvm::cast<llvm::StructType>(param_type);
737 CHECK_EQ(struct_type->getStructNumElements(), 5u)
739 const auto expected_elems = generated_struct_type->elements();
740 const auto current_elems = struct_type->elements();
741 for (
size_t i = 0; i < expected_elems.size(); i++) {
742 CHECK_EQ(expected_elems[i], current_elems[i]);
744 if (struct_type->isLiteral()) {
748 llvm::StringRef struct_name = struct_type->getStructName();
749 #if LLVM_VERSION_MAJOR >= 12
750 llvm::StructType* point_type =
751 struct_type->getTypeByName(cgen_state_->context_, struct_name);
753 llvm::StructType* point_type = module_for_lookup->getTypeByName(struct_name);
759 return generated_struct_type;
764 llvm::Value* point_buf,
765 llvm::Value* point_size,
766 llvm::Value* compression,
767 llvm::Value* input_srid,
768 llvm::Value* output_srid,
769 std::vector<llvm::Value*>& output_args) {
784 auto point_size_ptr =
788 auto point_compression_ptr =
792 auto input_srid_ptr =
796 auto output_srid_ptr =
800 output_args.push_back(alloc_mem);
804 const std::string& udf_func_name,
807 llvm::Function* udf_func = module_for_lookup->getFunction(udf_func_name);
809 llvm::StructType* generated_struct_type =
819 llvm::FunctionType* udf_func_type = udf_func->getFunctionType();
820 CHECK(param_num < udf_func_type->getNumParams());
821 llvm::Type* param_pointer_type = udf_func_type->getParamType(param_num);
822 CHECK(param_pointer_type->isPointerTy());
823 llvm::Type* param_type = param_pointer_type->getPointerElementType();
824 CHECK(param_type->isStructTy());
825 llvm::StructType* struct_type = llvm::cast<llvm::StructType>(param_type);
826 CHECK(struct_type->isStructTy());
827 CHECK_EQ(struct_type->getStructNumElements(), 5u);
829 const auto expected_elems = generated_struct_type->elements();
830 const auto current_elems = struct_type->elements();
831 for (
size_t i = 0; i < expected_elems.size(); i++) {
832 CHECK_EQ(expected_elems[i], current_elems[i]);
834 if (struct_type->isLiteral()) {
838 llvm::StringRef struct_name = struct_type->getStructName();
839 #if LLVM_VERSION_MAJOR >= 12
840 llvm::StructType* multi_point_type =
841 struct_type->getTypeByName(cgen_state_->context_, struct_name);
843 llvm::StructType* multi_point_type = module_for_lookup->getTypeByName(struct_name);
845 CHECK(multi_point_type);
847 return multi_point_type;
849 return generated_struct_type;
854 llvm::Value* multi_point_buf,
855 llvm::Value* multi_point_size,
856 llvm::Value* compression,
857 llvm::Value* input_srid,
858 llvm::Value* output_srid,
859 std::vector<llvm::Value*>& output_args) {
861 CHECK(multi_point_buf);
862 CHECK(multi_point_size);
871 auto multi_point_buf_ptr =
875 auto multi_point_size_ptr =
879 auto compression_ptr =
883 auto input_srid_ptr =
887 auto output_srid_ptr =
891 output_args.push_back(alloc_mem);
895 const std::string& udf_func_name,
898 llvm::Function* udf_func = module_for_lookup->getFunction(udf_func_name);
900 llvm::StructType* generated_struct_type =
910 llvm::FunctionType* udf_func_type = udf_func->getFunctionType();
911 CHECK(param_num < udf_func_type->getNumParams());
912 llvm::Type* param_pointer_type = udf_func_type->getParamType(param_num);
913 CHECK(param_pointer_type->isPointerTy());
914 llvm::Type* param_type = param_pointer_type->getPointerElementType();
915 CHECK(param_type->isStructTy());
916 llvm::StructType* struct_type = llvm::cast<llvm::StructType>(param_type);
917 CHECK(struct_type->isStructTy());
918 CHECK_EQ(struct_type->getStructNumElements(), 5u);
920 const auto expected_elems = generated_struct_type->elements();
921 const auto current_elems = struct_type->elements();
922 for (
size_t i = 0; i < expected_elems.size(); i++) {
923 CHECK_EQ(expected_elems[i], current_elems[i]);
925 if (struct_type->isLiteral()) {
929 llvm::StringRef struct_name = struct_type->getStructName();
930 #if LLVM_VERSION_MAJOR >= 12
931 llvm::StructType* line_string_type =
932 struct_type->getTypeByName(cgen_state_->context_, struct_name);
934 llvm::StructType* line_string_type = module_for_lookup->getTypeByName(struct_name);
936 CHECK(line_string_type);
938 return line_string_type;
940 return generated_struct_type;
945 llvm::Value* line_string_buf,
946 llvm::Value* line_string_size,
947 llvm::Value* compression,
948 llvm::Value* input_srid,
949 llvm::Value* output_srid,
950 std::vector<llvm::Value*>& output_args) {
952 CHECK(line_string_buf);
953 CHECK(line_string_size);
962 auto line_string_buf_ptr =
966 auto line_string_size_ptr =
970 auto line_string_compression_ptr =
974 auto input_srid_ptr =
978 auto output_srid_ptr =
982 output_args.push_back(alloc_mem);
986 const std::string& udf_func_name,
989 llvm::Function* udf_func = module_for_lookup->getFunction(udf_func_name);
991 llvm::StructType* generated_struct_type =
1003 llvm::FunctionType* udf_func_type = udf_func->getFunctionType();
1004 CHECK(param_num < udf_func_type->getNumParams());
1005 llvm::Type* param_pointer_type = udf_func_type->getParamType(param_num);
1006 CHECK(param_pointer_type->isPointerTy());
1007 llvm::Type* param_type = param_pointer_type->getPointerElementType();
1008 CHECK(param_type->isStructTy());
1009 llvm::StructType* struct_type = llvm::cast<llvm::StructType>(param_type);
1010 CHECK(struct_type->isStructTy());
1011 CHECK_EQ(struct_type->getStructNumElements(), 7u);
1013 const auto expected_elems = generated_struct_type->elements();
1014 const auto current_elems = struct_type->elements();
1015 for (
size_t i = 0; i < expected_elems.size(); i++) {
1016 CHECK_EQ(expected_elems[i], current_elems[i]);
1018 if (struct_type->isLiteral()) {
1022 llvm::StringRef struct_name = struct_type->getStructName();
1023 #if LLVM_VERSION_MAJOR >= 12
1024 llvm::StructType* multi_linestring_type =
1025 struct_type->getTypeByName(cgen_state_->context_, struct_name);
1027 llvm::StructType* multi_linestring_type =
1028 module_for_lookup->getTypeByName(struct_name);
1030 CHECK(multi_linestring_type);
1032 return multi_linestring_type;
1034 return generated_struct_type;
1038 const std::string& udf_func_name,
1040 llvm::Value* multi_linestring_coords,
1041 llvm::Value* multi_linestring_coords_size,
1042 llvm::Value* linestring_sizes,
1043 llvm::Value* linestring_sizes_size,
1044 llvm::Value* compression,
1045 llvm::Value* input_srid,
1046 llvm::Value* output_srid,
1047 std::vector<llvm::Value*>& output_args) {
1049 CHECK(multi_linestring_coords);
1050 CHECK(multi_linestring_coords_size);
1051 CHECK(linestring_sizes);
1052 CHECK(linestring_sizes_size);
1057 auto multi_linestring_abstraction =
1063 multi_linestring_abstraction, alloc_mem, 0);
1065 multi_linestring_coords_ptr);
1068 multi_linestring_abstraction, alloc_mem, 1);
1070 multi_linestring_coords_size_ptr);
1073 multi_linestring_abstraction, alloc_mem, 2);
1074 const auto linestring_sizes_ptr_ty =
1075 llvm::dyn_cast<llvm::PointerType>(linestring_sizes_ptr->getType());
1076 CHECK(linestring_sizes_ptr_ty);
1079 linestring_sizes, linestring_sizes_ptr_ty->getPointerElementType()),
1080 linestring_sizes_ptr);
1083 multi_linestring_abstraction, alloc_mem, 3);
1087 multi_linestring_abstraction, alloc_mem, 4);
1091 multi_linestring_abstraction, alloc_mem, 5);
1095 multi_linestring_abstraction, alloc_mem, 6);
1098 output_args.push_back(alloc_mem);
1104 llvm::Function* udf_func = module_for_lookup->getFunction(udf_func_name);
1106 llvm::StructType* generated_struct_type =
1118 llvm::FunctionType* udf_func_type = udf_func->getFunctionType();
1119 CHECK(param_num < udf_func_type->getNumParams());
1120 llvm::Type* param_pointer_type = udf_func_type->getParamType(param_num);
1121 CHECK(param_pointer_type->isPointerTy());
1122 llvm::Type* param_type = param_pointer_type->getPointerElementType();
1123 CHECK(param_type->isStructTy());
1124 llvm::StructType* struct_type = llvm::cast<llvm::StructType>(param_type);
1126 CHECK(struct_type->isStructTy());
1127 CHECK_EQ(struct_type->getStructNumElements(), 7u);
1129 const auto expected_elems = generated_struct_type->elements();
1130 const auto current_elems = struct_type->elements();
1131 for (
size_t i = 0; i < expected_elems.size(); i++) {
1132 CHECK_EQ(expected_elems[i], current_elems[i]);
1134 if (struct_type->isLiteral()) {
1138 llvm::StringRef struct_name = struct_type->getStructName();
1140 #if LLVM_VERSION_MAJOR >= 12
1141 llvm::StructType* polygon_type =
1142 struct_type->getTypeByName(cgen_state_->context_, struct_name);
1144 llvm::StructType* polygon_type = module_for_lookup->getTypeByName(struct_name);
1146 CHECK(polygon_type);
1148 return polygon_type;
1150 return generated_struct_type;
1155 llvm::Value* polygon_buf,
1156 llvm::Value* polygon_size,
1157 llvm::Value* ring_sizes_buf,
1158 llvm::Value* num_rings,
1159 llvm::Value* compression,
1160 llvm::Value* input_srid,
1161 llvm::Value* output_srid,
1162 std::vector<llvm::Value*>& output_args) {
1165 CHECK(polygon_size);
1166 CHECK(ring_sizes_buf);
1175 auto alloc_mem = builder.CreateAlloca(polygon_abstraction,
nullptr);
1177 const auto polygon_buf_ptr = builder.CreateStructGEP(polygon_abstraction, alloc_mem, 0);
1178 builder.CreateStore(polygon_buf, polygon_buf_ptr);
1180 const auto polygon_size_ptr =
1181 builder.CreateStructGEP(polygon_abstraction, alloc_mem, 1);
1182 builder.CreateStore(polygon_size, polygon_size_ptr);
1184 const auto ring_sizes_buf_ptr =
1185 builder.CreateStructGEP(polygon_abstraction, alloc_mem, 2);
1186 const auto ring_sizes_ptr_ty =
1187 llvm::dyn_cast<llvm::PointerType>(ring_sizes_buf_ptr->getType());
1188 CHECK(ring_sizes_ptr_ty);
1189 builder.CreateStore(
1190 builder.CreateBitCast(ring_sizes_buf, ring_sizes_ptr_ty->getPointerElementType()),
1191 ring_sizes_buf_ptr);
1193 const auto ring_size_ptr = builder.CreateStructGEP(polygon_abstraction, alloc_mem, 3);
1194 builder.CreateStore(num_rings, ring_size_ptr);
1196 const auto polygon_compression_ptr =
1197 builder.CreateStructGEP(polygon_abstraction, alloc_mem, 4);
1198 builder.CreateStore(compression, polygon_compression_ptr);
1200 const auto input_srid_ptr = builder.CreateStructGEP(polygon_abstraction, alloc_mem, 5);
1201 builder.CreateStore(input_srid, input_srid_ptr);
1203 const auto output_srid_ptr = builder.CreateStructGEP(polygon_abstraction, alloc_mem, 6);
1204 builder.CreateStore(output_srid, output_srid_ptr);
1206 output_args.push_back(alloc_mem);
1210 const std::string& udf_func_name,
1214 llvm::StructType* generated_struct_type =
1228 llvm::FunctionType* udf_func_type = udf_func->getFunctionType();
1229 CHECK(param_num < udf_func_type->getNumParams());
1230 llvm::Type* param_pointer_type = udf_func_type->getParamType(param_num);
1231 CHECK(param_pointer_type->isPointerTy());
1232 llvm::Type* param_type = param_pointer_type->getPointerElementType();
1233 CHECK(param_type->isStructTy());
1234 llvm::StructType* struct_type = llvm::cast<llvm::StructType>(param_type);
1235 CHECK(struct_type->isStructTy());
1236 CHECK_EQ(struct_type->getStructNumElements(), 9u);
1237 const auto expected_elems = generated_struct_type->elements();
1238 const auto current_elems = struct_type->elements();
1239 for (
size_t i = 0; i < expected_elems.size(); i++) {
1240 CHECK_EQ(expected_elems[i], current_elems[i]);
1242 if (struct_type->isLiteral()) {
1245 llvm::StringRef struct_name = struct_type->getStructName();
1247 #if LLVM_VERSION_MAJOR >= 12
1248 llvm::StructType* polygon_type =
1249 struct_type->getTypeByName(cgen_state_->context_, struct_name);
1251 llvm::StructType* polygon_type = cgen_state_->module_->getTypeByName(struct_name);
1253 CHECK(polygon_type);
1255 return polygon_type;
1257 return generated_struct_type;
1262 llvm::Value* polygon_coords,
1263 llvm::Value* polygon_coords_size,
1264 llvm::Value* ring_sizes_buf,
1265 llvm::Value* ring_sizes,
1266 llvm::Value* polygon_bounds,
1267 llvm::Value* polygon_bounds_sizes,
1268 llvm::Value* compression,
1269 llvm::Value* input_srid,
1270 llvm::Value* output_srid,
1271 std::vector<llvm::Value*>& output_args) {
1273 CHECK(polygon_coords);
1274 CHECK(polygon_coords_size);
1275 CHECK(ring_sizes_buf);
1277 CHECK(polygon_bounds);
1278 CHECK(polygon_bounds_sizes);
1286 auto alloc_mem = builder.CreateAlloca(multi_polygon_abstraction,
nullptr);
1288 const auto polygon_coords_ptr =
1289 builder.CreateStructGEP(multi_polygon_abstraction, alloc_mem, 0);
1290 builder.CreateStore(polygon_coords, polygon_coords_ptr);
1292 const auto polygon_coords_size_ptr =
1293 builder.CreateStructGEP(multi_polygon_abstraction, alloc_mem, 1);
1294 builder.CreateStore(polygon_coords_size, polygon_coords_size_ptr);
1296 const auto ring_sizes_buf_ptr =
1297 builder.CreateStructGEP(multi_polygon_abstraction, alloc_mem, 2);
1298 const auto ring_sizes_ptr_ty =
1299 llvm::dyn_cast<llvm::PointerType>(ring_sizes_buf_ptr->getType());
1300 CHECK(ring_sizes_ptr_ty);
1301 builder.CreateStore(
1302 builder.CreateBitCast(ring_sizes_buf, ring_sizes_ptr_ty->getPointerElementType()),
1303 ring_sizes_buf_ptr);
1305 const auto ring_sizes_ptr =
1306 builder.CreateStructGEP(multi_polygon_abstraction, alloc_mem, 3);
1307 builder.CreateStore(ring_sizes, ring_sizes_ptr);
1309 const auto polygon_bounds_buf_ptr =
1310 builder.CreateStructGEP(multi_polygon_abstraction, alloc_mem, 4);
1311 const auto bounds_ptr_ty =
1312 llvm::dyn_cast<llvm::PointerType>(polygon_bounds_buf_ptr->getType());
1313 CHECK(bounds_ptr_ty);
1314 builder.CreateStore(
1315 builder.CreateBitCast(polygon_bounds, bounds_ptr_ty->getPointerElementType()),
1316 polygon_bounds_buf_ptr);
1318 const auto polygon_bounds_sizes_ptr =
1319 builder.CreateStructGEP(multi_polygon_abstraction, alloc_mem, 5);
1320 builder.CreateStore(polygon_bounds_sizes, polygon_bounds_sizes_ptr);
1322 const auto polygon_compression_ptr =
1323 builder.CreateStructGEP(multi_polygon_abstraction, alloc_mem, 6);
1324 builder.CreateStore(compression, polygon_compression_ptr);
1326 const auto input_srid_ptr =
1327 builder.CreateStructGEP(multi_polygon_abstraction, alloc_mem, 7);
1328 builder.CreateStore(input_srid, input_srid_ptr);
1330 const auto output_srid_ptr =
1331 builder.CreateStructGEP(multi_polygon_abstraction, alloc_mem, 8);
1332 builder.CreateStore(output_srid, output_srid_ptr);
1334 output_args.push_back(alloc_mem);
1342 const std::vector<llvm::Value*>& orig_arg_lvs,
1343 const std::vector<size_t>& orig_arg_lvs_index,
1344 const std::unordered_map<llvm::Value*, llvm::Value*>& const_arr_size,
1347 CHECK(ext_func_sig);
1348 const auto& ext_func_args = ext_func_sig->
getInputArgs();
1351 std::vector<llvm::Value*>
args;
1359 for (
size_t i = 0, j = 0, dj = (func_ti.is_buffer() ? 1 : 0);
1362 size_t k = orig_arg_lvs_index[i];
1364 const auto arg = function_oper->
getArg(i);
1365 const auto ext_func_arg = ext_func_args[ij];
1367 llvm::Value* arg_lv{
nullptr};
1368 if (arg_ti.is_bytes()) {
1371 const auto ptr_lv = orig_arg_lvs[k + 1];
1372 const auto len_lv = orig_arg_lvs[k + 2];
1374 auto string_buf_arg = builder.CreatePointerCast(
1376 auto string_size_arg =
1384 }
else if (arg_ti.is_array()) {
1385 bool const_arr = (const_arr_size.count(orig_arg_lvs[k]) > 0);
1386 const auto elem_ti = arg_ti.get_elem_type();
1388 const auto ptr_lv = (const_arr)
1393 {orig_arg_lvs[k],
posArg(arg)});
1395 (const_arr) ? const_arr_size.at(orig_arg_lvs[k])
1411 auto array_size_arg =
1413 auto array_null_arg =
1416 {orig_arg_lvs[k],
posArg(arg)});
1427 }
else if (arg_ti.is_geometry()) {
1432 args.push_back(ptr_lv);
1436 args.push_back(size_lv);
1441 bool const_arr = (const_arr_size.count(orig_arg_lvs[k]) > 0);
1452 llvm::Value* ptr_lv;
1453 llvm::Value* len_lv;
1454 int32_t fixlen = -1;
1455 if (arg_ti.get_type() ==
kPOINT) {
1458 const auto coords_cd =
executor()->getPhysicalColumnDescriptor(col_var, 1);
1459 if (coords_cd && coords_cd->columnType.get_type() ==
kARRAY) {
1460 fixlen = coords_cd->columnType.get_size();
1468 {orig_arg_lvs[k],
posArg(arg)});
1472 ptr_lv = (const_arr) ? orig_arg_lvs[k]
1476 {orig_arg_lvs[k],
posArg(arg)});
1477 len_lv = (const_arr)
1478 ? const_arr_size.at(orig_arg_lvs[k])
1495 if (arg_ti.get_type() ==
kPOINT) {
1535 switch (arg_ti.get_type()) {
1547 auto [linestring_sizes, linestring_sizes_size] =
1555 multi_linestring_coords,
1558 linestring_sizes_size,
1566 auto const_arr = const_arr_size.count(orig_arg_lvs[k + 1]) > 0;
1567 auto [linestring_sizes, linestring_sizes_size] =
1568 (const_arr) ? std::make_pair(orig_arg_lvs[k + 1],
1569 const_arr_size.at(orig_arg_lvs[k + 1]))
1574 args.push_back(linestring_sizes);
1575 args.push_back(linestring_sizes_size);
1587 auto [ring_size_buff, ring_size] =
1606 auto const_arr = const_arr_size.count(orig_arg_lvs[k + 1]) > 0;
1607 auto [ring_size_buff, ring_size] =
1608 (const_arr) ? std::make_pair(orig_arg_lvs[k + 1],
1609 const_arr_size.at(orig_arg_lvs[k + 1]))
1614 args.push_back(ring_size_buff);
1615 args.push_back(ring_size);
1627 auto [ring_size_buff, ring_size] =
1633 auto [poly_bounds_buff, poly_bounds_size] =
1655 auto const_arr = const_arr_size.count(orig_arg_lvs[k + 1]) > 0;
1656 auto [ring_size_buff, ring_size] =
1657 (const_arr) ? std::make_pair(orig_arg_lvs[k + 1],
1658 const_arr_size.at(orig_arg_lvs[k + 1]))
1664 args.push_back(ring_size_buff);
1665 args.push_back(ring_size);
1669 auto const_arr = const_arr_size.count(orig_arg_lvs[k + 2]) > 0;
1670 auto [poly_bounds_buff, poly_bounds_size] =
1672 ? std::make_pair(orig_arg_lvs[k + 2],
1673 const_arr_size.at(orig_arg_lvs[k + 2]))
1677 args.push_back(poly_bounds_buff);
1678 args.push_back(poly_bounds_size);
1690 if (arg_ti.get_type() != arg_target_ti.get_type()) {
1691 arg_lv = codegenCast(orig_arg_lvs[k], arg_ti, arg_target_ti,
false, co);
1693 arg_lv = orig_arg_lvs[k];
1697 args.push_back(arg_lv);
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
llvm::StructType * get_buffer_struct_type(CgenState *cgen_state, const std::string &ext_func_name, size_t param_num, llvm::Type *elem_type, bool has_is_null)
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 * 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 * 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)
std::string toString(const QueryDescriptionType &type)
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)
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)
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::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::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
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::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_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)