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_bytes() && arg_ti.is_bytes()) ||
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_bytes()) {
323 CHECK_EQ(
size_t(3), arg_lvs.size());
328 for (
size_t j = 0; j < arg_lvs.size(); j++) {
329 orig_arg_lvs.push_back(arg_lvs[j]);
331 }
else if (arg_ti.is_text_encoding_dict()) {
332 CHECK_EQ(
size_t(1), arg_lvs.size());
333 orig_arg_lvs.push_back(arg_lvs[0]);
335 if (arg_lvs.size() > 1) {
336 CHECK(arg_ti.is_array());
337 CHECK_EQ(
size_t(2), arg_lvs.size());
338 const_arr_size[arg_lvs.front()] = arg_lvs.back();
340 CHECK_EQ(
size_t(1), arg_lvs.size());
344 if (is_local_alloc && arg_ti.get_size() > 0) {
348 orig_arg_lvs.push_back(arg_lvs.front());
359 function_oper, &ext_func_sig, orig_arg_lvs, orig_arg_lvs_index, const_arr_size, co);
366 args.insert(args.begin(), row_func_mgr);
369 llvm::Value* buffer_ret{
nullptr};
370 if (ret_ti.is_buffer()) {
372 CHECK(ret_ti.is_array() || ret_ti.is_bytes());
380 args.insert(args.begin(), buffer_ret);
384 ext_func_sig.
getName(), ret_ty,
args, {}, ret_ti.is_buffer());
386 bbs, ret_ti.is_buffer() ? buffer_ret : ext_call, null_buffer_ptr, function_oper);
389 if (!(ret_ti.is_buffer() || ret_ti.is_text_encoding_dict())) {
391 if (bbs.args_null_bb &&
398 function_oper->
getName().substr(0, 3) != std::string(
"ST_")) {
399 ext_call_nullcheck =
codegenCast(ext_call_nullcheck,
408 return ext_call_nullcheck;
412 std::tuple<CodeGenerator::ArgNullcheckBBs, llvm::Value*>
414 const std::vector<llvm::Value*>& orig_arg_lvs) {
416 llvm::BasicBlock* args_null_bb{
nullptr};
417 llvm::BasicBlock* args_notnull_bb{
nullptr};
419 llvm::Value* null_array_alloca{
nullptr};
423 if (func_ti.is_buffer()) {
433 args_notnull_bb = llvm::BasicBlock::Create(
435 args_null_bb = llvm::BasicBlock::Create(
440 return std::make_tuple(
448 llvm::Value* fn_ret_lv,
449 llvm::Value* null_array_ptr,
457 llvm::PHINode* ext_call_phi{
nullptr};
458 llvm::Value* null_lv{
nullptr};
460 if (!func_ti.is_buffer()) {
465 extension_ret_ti.is_fp()
471 extension_ret_ti.is_fp()
483 CHECK(null_array_ptr);
484 const auto arr_null_bool =
490 const auto arr_null_size =
497 ext_call_phi->addIncoming(func_ti.is_buffer() ? null_array_ptr : null_lv,
509 if (!ret_ti.is_integer() && !ret_ti.is_fp()) {
512 for (
size_t i = 0; i < function_oper->
getArity(); ++i) {
513 const auto arg = function_oper->
getArg(i);
515 if (!arg_ti.is_integer() && !arg_ti.is_fp()) {
530 if (function_oper->
getName() ==
"FLOOR" || function_oper->
getName() ==
"CEIL") {
532 const auto arg = function_oper->
getArg(0);
534 CHECK(arg_ti.is_decimal());
535 const auto arg_lvs =
codegen(arg,
true, co);
536 CHECK_EQ(
size_t(1), arg_lvs.size());
537 const auto arg_lv = arg_lvs.front();
538 CHECK(arg_lv->getType()->isIntegerTy(64));
541 const std::string func_name =
542 (function_oper->
getName() ==
"FLOOR") ?
"decimal_floor" :
"decimal_ceil";
546 CHECK(ret_ti.is_decimal());
551 }
else if (function_oper->
getName() ==
"ROUND" &&
555 const auto arg0 = function_oper->
getArg(0);
557 const auto arg0_lvs =
codegen(arg0,
true, co);
558 CHECK_EQ(
size_t(1), arg0_lvs.size());
559 const auto arg0_lv = arg0_lvs.front();
560 CHECK(arg0_lv->getType()->isIntegerTy(64));
562 const auto arg1 = function_oper->
getArg(1);
564 CHECK(arg1_ti.is_integer());
565 const auto arg1_lvs =
codegen(arg1,
true, co);
566 auto arg1_lv = arg1_lvs.front();
567 if (arg1_ti.get_type() !=
kINT) {
572 std::tie(bbs0, std::ignore) =
575 const std::string func_name =
"Round__4";
577 CHECK(ret_ti.is_decimal());
585 throw std::runtime_error(
"Type combination not supported for function " +
594 const std::vector<llvm::Value*>& orig_arg_lvs) {
596 llvm::Value* one_arg_null =
598 size_t physical_coord_cols = 0;
599 for (
size_t i = 0, j = 0; i < function_oper->
getArity();
600 ++i, j += std::max(
size_t(1), physical_coord_cols)) {
601 const auto arg = function_oper->
getArg(i);
604 if (arg_ti.get_notnull()) {
608 if (geo_expr_arg && arg_ti.is_geometry()) {
611 llvm::CmpInst::ICMP_EQ,
613 llvm::ConstantPointerNull::get(
618 physical_coord_cols = 2;
623 if (arg_ti.is_geometry()) {
624 auto* coords_load = llvm::dyn_cast<llvm::LoadInst>(orig_arg_lvs[i]);
630 if (arg_ti.is_geometry()) {
631 auto* coords_alloca = llvm::dyn_cast<llvm::AllocaInst>(orig_arg_lvs[j]);
632 auto* coords_phi = llvm::dyn_cast<llvm::PHINode>(orig_arg_lvs[j]);
633 if (coords_alloca || coords_phi) {
638 if (arg_ti.is_text_encoding_dict()) {
643 if (arg_ti.is_buffer() || arg_ti.is_geometry()) {
647 (arg_ti.get_type() ==
kPOINT) ?
"point_coord_array_is_null" :
"array_is_null";
653 CHECK(arg_ti.is_number() or arg_ti.is_boolean());
672 llvm::Value* row_pos,
674 bool cast_and_extend) {
684 auto len = cgen_state_->emitExternalCall(
687 {chunk, row_pos, cgen_state_->llInt(
log2_bytes(elem_ti.get_logical_size()))});
689 if (cast_and_extend) {
690 buff = castArrayPointer(buff, elem_ti);
692 cgen_state_->ir_builder_.CreateZExt(len,
get_int_type(64, cgen_state_->context_));
695 return std::make_pair(buff, len);
700 llvm::Value* buffer_buf,
701 llvm::Value* buffer_size,
702 llvm::Value* buffer_null,
703 std::vector<llvm::Value*>& output_args) {
709 cgen_state_, ext_func_name, param_num, buffer_buf->getType());
712 auto buffer_buf_ptr =
716 auto buffer_size_ptr =
721 auto buffer_null_extended =
723 auto buffer_is_null_ptr =
726 output_args.push_back(alloc_mem);
732 llvm::Function* udf_func = module_for_lookup->getFunction(udf_func_name);
734 llvm::StructType* generated_struct_type =
744 llvm::FunctionType* udf_func_type = udf_func->getFunctionType();
745 CHECK(param_num < udf_func_type->getNumParams());
746 llvm::Type* param_pointer_type = udf_func_type->getParamType(param_num);
747 CHECK(param_pointer_type->isPointerTy());
748 llvm::Type* param_type = param_pointer_type->getPointerElementType();
749 CHECK(param_type->isStructTy());
750 llvm::StructType* struct_type = llvm::cast<llvm::StructType>(param_type);
751 CHECK_EQ(struct_type->getStructNumElements(), 5u)
753 const auto expected_elems = generated_struct_type->elements();
754 const auto current_elems = struct_type->elements();
755 for (
size_t i = 0; i < expected_elems.size(); i++) {
756 CHECK_EQ(expected_elems[i], current_elems[i]);
758 if (struct_type->isLiteral()) {
762 llvm::StringRef struct_name = struct_type->getStructName();
763 #if LLVM_VERSION_MAJOR >= 12
764 llvm::StructType* point_type =
765 struct_type->getTypeByName(cgen_state_->context_, struct_name);
767 llvm::StructType* point_type = module_for_lookup->getTypeByName(struct_name);
773 return generated_struct_type;
778 llvm::Value* point_buf,
779 llvm::Value* point_size,
780 llvm::Value* compression,
781 llvm::Value* input_srid,
782 llvm::Value* output_srid,
783 std::vector<llvm::Value*>& output_args) {
798 auto point_size_ptr =
802 auto point_compression_ptr =
806 auto input_srid_ptr =
810 auto output_srid_ptr =
814 output_args.push_back(alloc_mem);
818 const std::string& udf_func_name,
821 llvm::Function* udf_func = module_for_lookup->getFunction(udf_func_name);
823 llvm::StructType* generated_struct_type =
833 llvm::FunctionType* udf_func_type = udf_func->getFunctionType();
834 CHECK(param_num < udf_func_type->getNumParams());
835 llvm::Type* param_pointer_type = udf_func_type->getParamType(param_num);
836 CHECK(param_pointer_type->isPointerTy());
837 llvm::Type* param_type = param_pointer_type->getPointerElementType();
838 CHECK(param_type->isStructTy());
839 llvm::StructType* struct_type = llvm::cast<llvm::StructType>(param_type);
840 CHECK(struct_type->isStructTy());
841 CHECK_EQ(struct_type->getStructNumElements(), 5u);
843 const auto expected_elems = generated_struct_type->elements();
844 const auto current_elems = struct_type->elements();
845 for (
size_t i = 0; i < expected_elems.size(); i++) {
846 CHECK_EQ(expected_elems[i], current_elems[i]);
848 if (struct_type->isLiteral()) {
852 llvm::StringRef struct_name = struct_type->getStructName();
853 #if LLVM_VERSION_MAJOR >= 12
854 llvm::StructType* multi_point_type =
855 struct_type->getTypeByName(cgen_state_->context_, struct_name);
857 llvm::StructType* multi_point_type = module_for_lookup->getTypeByName(struct_name);
859 CHECK(multi_point_type);
861 return multi_point_type;
863 return generated_struct_type;
868 llvm::Value* multi_point_buf,
869 llvm::Value* multi_point_size,
870 llvm::Value* compression,
871 llvm::Value* input_srid,
872 llvm::Value* output_srid,
873 std::vector<llvm::Value*>& output_args) {
875 CHECK(multi_point_buf);
876 CHECK(multi_point_size);
885 auto multi_point_buf_ptr =
889 auto multi_point_size_ptr =
893 auto compression_ptr =
897 auto input_srid_ptr =
901 auto output_srid_ptr =
905 output_args.push_back(alloc_mem);
909 const std::string& udf_func_name,
912 llvm::Function* udf_func = module_for_lookup->getFunction(udf_func_name);
914 llvm::StructType* generated_struct_type =
924 llvm::FunctionType* udf_func_type = udf_func->getFunctionType();
925 CHECK(param_num < udf_func_type->getNumParams());
926 llvm::Type* param_pointer_type = udf_func_type->getParamType(param_num);
927 CHECK(param_pointer_type->isPointerTy());
928 llvm::Type* param_type = param_pointer_type->getPointerElementType();
929 CHECK(param_type->isStructTy());
930 llvm::StructType* struct_type = llvm::cast<llvm::StructType>(param_type);
931 CHECK(struct_type->isStructTy());
932 CHECK_EQ(struct_type->getStructNumElements(), 5u);
934 const auto expected_elems = generated_struct_type->elements();
935 const auto current_elems = struct_type->elements();
936 for (
size_t i = 0; i < expected_elems.size(); i++) {
937 CHECK_EQ(expected_elems[i], current_elems[i]);
939 if (struct_type->isLiteral()) {
943 llvm::StringRef struct_name = struct_type->getStructName();
944 #if LLVM_VERSION_MAJOR >= 12
945 llvm::StructType* line_string_type =
946 struct_type->getTypeByName(cgen_state_->context_, struct_name);
948 llvm::StructType* line_string_type = module_for_lookup->getTypeByName(struct_name);
950 CHECK(line_string_type);
952 return line_string_type;
954 return generated_struct_type;
959 llvm::Value* line_string_buf,
960 llvm::Value* line_string_size,
961 llvm::Value* compression,
962 llvm::Value* input_srid,
963 llvm::Value* output_srid,
964 std::vector<llvm::Value*>& output_args) {
966 CHECK(line_string_buf);
967 CHECK(line_string_size);
976 auto line_string_buf_ptr =
980 auto line_string_size_ptr =
984 auto line_string_compression_ptr =
988 auto input_srid_ptr =
992 auto output_srid_ptr =
996 output_args.push_back(alloc_mem);
1000 const std::string& udf_func_name,
1003 llvm::Function* udf_func = module_for_lookup->getFunction(udf_func_name);
1005 llvm::StructType* generated_struct_type =
1017 llvm::FunctionType* udf_func_type = udf_func->getFunctionType();
1018 CHECK(param_num < udf_func_type->getNumParams());
1019 llvm::Type* param_pointer_type = udf_func_type->getParamType(param_num);
1020 CHECK(param_pointer_type->isPointerTy());
1021 llvm::Type* param_type = param_pointer_type->getPointerElementType();
1022 CHECK(param_type->isStructTy());
1023 llvm::StructType* struct_type = llvm::cast<llvm::StructType>(param_type);
1024 CHECK(struct_type->isStructTy());
1025 CHECK_EQ(struct_type->getStructNumElements(), 7u);
1027 const auto expected_elems = generated_struct_type->elements();
1028 const auto current_elems = struct_type->elements();
1029 for (
size_t i = 0; i < expected_elems.size(); i++) {
1030 CHECK_EQ(expected_elems[i], current_elems[i]);
1032 if (struct_type->isLiteral()) {
1036 llvm::StringRef struct_name = struct_type->getStructName();
1037 #if LLVM_VERSION_MAJOR >= 12
1038 llvm::StructType* multi_linestring_type =
1039 struct_type->getTypeByName(cgen_state_->context_, struct_name);
1041 llvm::StructType* multi_linestring_type =
1042 module_for_lookup->getTypeByName(struct_name);
1044 CHECK(multi_linestring_type);
1046 return multi_linestring_type;
1048 return generated_struct_type;
1052 const std::string& udf_func_name,
1054 llvm::Value* multi_linestring_coords,
1055 llvm::Value* multi_linestring_coords_size,
1056 llvm::Value* linestring_sizes,
1057 llvm::Value* linestring_sizes_size,
1058 llvm::Value* compression,
1059 llvm::Value* input_srid,
1060 llvm::Value* output_srid,
1061 std::vector<llvm::Value*>& output_args) {
1063 CHECK(multi_linestring_coords);
1064 CHECK(multi_linestring_coords_size);
1065 CHECK(linestring_sizes);
1066 CHECK(linestring_sizes_size);
1071 auto multi_linestring_abstraction =
1077 multi_linestring_abstraction, alloc_mem, 0);
1079 multi_linestring_coords_ptr);
1082 multi_linestring_abstraction, alloc_mem, 1);
1084 multi_linestring_coords_size_ptr);
1087 multi_linestring_abstraction, alloc_mem, 2);
1088 const auto linestring_sizes_ptr_ty =
1089 llvm::dyn_cast<llvm::PointerType>(linestring_sizes_ptr->getType());
1090 CHECK(linestring_sizes_ptr_ty);
1093 linestring_sizes, linestring_sizes_ptr_ty->getPointerElementType()),
1094 linestring_sizes_ptr);
1097 multi_linestring_abstraction, alloc_mem, 3);
1101 multi_linestring_abstraction, alloc_mem, 4);
1105 multi_linestring_abstraction, alloc_mem, 5);
1109 multi_linestring_abstraction, alloc_mem, 6);
1112 output_args.push_back(alloc_mem);
1118 llvm::Function* udf_func = module_for_lookup->getFunction(udf_func_name);
1120 llvm::StructType* generated_struct_type =
1132 llvm::FunctionType* udf_func_type = udf_func->getFunctionType();
1133 CHECK(param_num < udf_func_type->getNumParams());
1134 llvm::Type* param_pointer_type = udf_func_type->getParamType(param_num);
1135 CHECK(param_pointer_type->isPointerTy());
1136 llvm::Type* param_type = param_pointer_type->getPointerElementType();
1137 CHECK(param_type->isStructTy());
1138 llvm::StructType* struct_type = llvm::cast<llvm::StructType>(param_type);
1140 CHECK(struct_type->isStructTy());
1141 CHECK_EQ(struct_type->getStructNumElements(), 7u);
1143 const auto expected_elems = generated_struct_type->elements();
1144 const auto current_elems = struct_type->elements();
1145 for (
size_t i = 0; i < expected_elems.size(); i++) {
1146 CHECK_EQ(expected_elems[i], current_elems[i]);
1148 if (struct_type->isLiteral()) {
1152 llvm::StringRef struct_name = struct_type->getStructName();
1154 #if LLVM_VERSION_MAJOR >= 12
1155 llvm::StructType* polygon_type =
1156 struct_type->getTypeByName(cgen_state_->context_, struct_name);
1158 llvm::StructType* polygon_type = module_for_lookup->getTypeByName(struct_name);
1160 CHECK(polygon_type);
1162 return polygon_type;
1164 return generated_struct_type;
1169 llvm::Value* polygon_buf,
1170 llvm::Value* polygon_size,
1171 llvm::Value* ring_sizes_buf,
1172 llvm::Value* num_rings,
1173 llvm::Value* compression,
1174 llvm::Value* input_srid,
1175 llvm::Value* output_srid,
1176 std::vector<llvm::Value*>& output_args) {
1179 CHECK(polygon_size);
1180 CHECK(ring_sizes_buf);
1189 auto alloc_mem = builder.CreateAlloca(polygon_abstraction,
nullptr);
1191 const auto polygon_buf_ptr = builder.CreateStructGEP(polygon_abstraction, alloc_mem, 0);
1192 builder.CreateStore(polygon_buf, polygon_buf_ptr);
1194 const auto polygon_size_ptr =
1195 builder.CreateStructGEP(polygon_abstraction, alloc_mem, 1);
1196 builder.CreateStore(polygon_size, polygon_size_ptr);
1198 const auto ring_sizes_buf_ptr =
1199 builder.CreateStructGEP(polygon_abstraction, alloc_mem, 2);
1200 const auto ring_sizes_ptr_ty =
1201 llvm::dyn_cast<llvm::PointerType>(ring_sizes_buf_ptr->getType());
1202 CHECK(ring_sizes_ptr_ty);
1203 builder.CreateStore(
1204 builder.CreateBitCast(ring_sizes_buf, ring_sizes_ptr_ty->getPointerElementType()),
1205 ring_sizes_buf_ptr);
1207 const auto ring_size_ptr = builder.CreateStructGEP(polygon_abstraction, alloc_mem, 3);
1208 builder.CreateStore(num_rings, ring_size_ptr);
1210 const auto polygon_compression_ptr =
1211 builder.CreateStructGEP(polygon_abstraction, alloc_mem, 4);
1212 builder.CreateStore(compression, polygon_compression_ptr);
1214 const auto input_srid_ptr = builder.CreateStructGEP(polygon_abstraction, alloc_mem, 5);
1215 builder.CreateStore(input_srid, input_srid_ptr);
1217 const auto output_srid_ptr = builder.CreateStructGEP(polygon_abstraction, alloc_mem, 6);
1218 builder.CreateStore(output_srid, output_srid_ptr);
1220 output_args.push_back(alloc_mem);
1224 const std::string& udf_func_name,
1228 llvm::StructType* generated_struct_type =
1242 llvm::FunctionType* udf_func_type = udf_func->getFunctionType();
1243 CHECK(param_num < udf_func_type->getNumParams());
1244 llvm::Type* param_pointer_type = udf_func_type->getParamType(param_num);
1245 CHECK(param_pointer_type->isPointerTy());
1246 llvm::Type* param_type = param_pointer_type->getPointerElementType();
1247 CHECK(param_type->isStructTy());
1248 llvm::StructType* struct_type = llvm::cast<llvm::StructType>(param_type);
1249 CHECK(struct_type->isStructTy());
1250 CHECK_EQ(struct_type->getStructNumElements(), 9u);
1251 const auto expected_elems = generated_struct_type->elements();
1252 const auto current_elems = struct_type->elements();
1253 for (
size_t i = 0; i < expected_elems.size(); i++) {
1254 CHECK_EQ(expected_elems[i], current_elems[i]);
1256 if (struct_type->isLiteral()) {
1259 llvm::StringRef struct_name = struct_type->getStructName();
1261 #if LLVM_VERSION_MAJOR >= 12
1262 llvm::StructType* polygon_type =
1263 struct_type->getTypeByName(cgen_state_->context_, struct_name);
1265 llvm::StructType* polygon_type = cgen_state_->module_->getTypeByName(struct_name);
1267 CHECK(polygon_type);
1269 return polygon_type;
1271 return generated_struct_type;
1276 llvm::Value* polygon_coords,
1277 llvm::Value* polygon_coords_size,
1278 llvm::Value* ring_sizes_buf,
1279 llvm::Value* ring_sizes,
1280 llvm::Value* polygon_bounds,
1281 llvm::Value* polygon_bounds_sizes,
1282 llvm::Value* compression,
1283 llvm::Value* input_srid,
1284 llvm::Value* output_srid,
1285 std::vector<llvm::Value*>& output_args) {
1287 CHECK(polygon_coords);
1288 CHECK(polygon_coords_size);
1289 CHECK(ring_sizes_buf);
1291 CHECK(polygon_bounds);
1292 CHECK(polygon_bounds_sizes);
1300 auto alloc_mem = builder.CreateAlloca(multi_polygon_abstraction,
nullptr);
1302 const auto polygon_coords_ptr =
1303 builder.CreateStructGEP(multi_polygon_abstraction, alloc_mem, 0);
1304 builder.CreateStore(polygon_coords, polygon_coords_ptr);
1306 const auto polygon_coords_size_ptr =
1307 builder.CreateStructGEP(multi_polygon_abstraction, alloc_mem, 1);
1308 builder.CreateStore(polygon_coords_size, polygon_coords_size_ptr);
1310 const auto ring_sizes_buf_ptr =
1311 builder.CreateStructGEP(multi_polygon_abstraction, alloc_mem, 2);
1312 const auto ring_sizes_ptr_ty =
1313 llvm::dyn_cast<llvm::PointerType>(ring_sizes_buf_ptr->getType());
1314 CHECK(ring_sizes_ptr_ty);
1315 builder.CreateStore(
1316 builder.CreateBitCast(ring_sizes_buf, ring_sizes_ptr_ty->getPointerElementType()),
1317 ring_sizes_buf_ptr);
1319 const auto ring_sizes_ptr =
1320 builder.CreateStructGEP(multi_polygon_abstraction, alloc_mem, 3);
1321 builder.CreateStore(ring_sizes, ring_sizes_ptr);
1323 const auto polygon_bounds_buf_ptr =
1324 builder.CreateStructGEP(multi_polygon_abstraction, alloc_mem, 4);
1325 const auto bounds_ptr_ty =
1326 llvm::dyn_cast<llvm::PointerType>(polygon_bounds_buf_ptr->getType());
1327 CHECK(bounds_ptr_ty);
1328 builder.CreateStore(
1329 builder.CreateBitCast(polygon_bounds, bounds_ptr_ty->getPointerElementType()),
1330 polygon_bounds_buf_ptr);
1332 const auto polygon_bounds_sizes_ptr =
1333 builder.CreateStructGEP(multi_polygon_abstraction, alloc_mem, 5);
1334 builder.CreateStore(polygon_bounds_sizes, polygon_bounds_sizes_ptr);
1336 const auto polygon_compression_ptr =
1337 builder.CreateStructGEP(multi_polygon_abstraction, alloc_mem, 6);
1338 builder.CreateStore(compression, polygon_compression_ptr);
1340 const auto input_srid_ptr =
1341 builder.CreateStructGEP(multi_polygon_abstraction, alloc_mem, 7);
1342 builder.CreateStore(input_srid, input_srid_ptr);
1344 const auto output_srid_ptr =
1345 builder.CreateStructGEP(multi_polygon_abstraction, alloc_mem, 8);
1346 builder.CreateStore(output_srid, output_srid_ptr);
1348 output_args.push_back(alloc_mem);
1356 const std::vector<llvm::Value*>& orig_arg_lvs,
1357 const std::vector<size_t>& orig_arg_lvs_index,
1358 const std::unordered_map<llvm::Value*, llvm::Value*>& const_arr_size,
1361 CHECK(ext_func_sig);
1362 const auto& ext_func_args = ext_func_sig->
getInputArgs();
1365 std::vector<llvm::Value*>
args;
1373 for (
size_t i = 0, j = 0, dj = (func_ti.is_buffer() ? 1 : 0);
1376 size_t k = orig_arg_lvs_index[i];
1378 const auto arg = function_oper->
getArg(i);
1379 const auto ext_func_arg = ext_func_args[ij];
1381 llvm::Value* arg_lv{
nullptr};
1382 if (arg_ti.is_bytes()) {
1385 const auto ptr_lv = orig_arg_lvs[k + 1];
1386 const auto len_lv = orig_arg_lvs[k + 2];
1388 auto string_buf_arg = builder.CreatePointerCast(
1390 auto string_size_arg =
1399 }
else if (arg_ti.is_text_encoding_dict()) {
1402 arg_lv = orig_arg_lvs[k];
1403 args.push_back(arg_lv);
1404 }
else if (arg_ti.is_array()) {
1405 bool const_arr = (const_arr_size.count(orig_arg_lvs[k]) > 0);
1406 const auto elem_ti = arg_ti.get_elem_type();
1408 const auto ptr_lv = (const_arr)
1413 {orig_arg_lvs[k],
posArg(arg)});
1415 (const_arr) ? const_arr_size.at(orig_arg_lvs[k])
1431 auto array_size_arg =
1433 llvm::Value* array_null_arg =
nullptr;
1434 if (
auto gep = llvm::dyn_cast<llvm::GetElementPtrInst>(ptr_lv)) {
1435 CHECK(gep->getSourceElementType()->isArrayTy());
1445 {orig_arg_lvs[k],
posArg(arg)});
1457 }
else if (arg_ti.is_geometry()) {
1462 args.push_back(ptr_lv);
1466 args.push_back(size_lv);
1471 bool const_arr = (const_arr_size.count(orig_arg_lvs[k]) > 0);
1482 llvm::Value* ptr_lv;
1483 llvm::Value* len_lv;
1484 int32_t fixlen = -1;
1485 if (arg_ti.get_type() ==
kPOINT) {
1488 const auto coords_cd =
executor()->getPhysicalColumnDescriptor(col_var, 1);
1489 if (coords_cd && coords_cd->columnType.get_type() ==
kARRAY) {
1490 fixlen = coords_cd->columnType.get_size();
1498 {orig_arg_lvs[k],
posArg(arg)});
1502 ptr_lv = (const_arr) ? orig_arg_lvs[k]
1506 {orig_arg_lvs[k],
posArg(arg)});
1507 len_lv = (const_arr)
1508 ? const_arr_size.at(orig_arg_lvs[k])
1525 if (arg_ti.get_type() ==
kPOINT) {
1565 switch (arg_ti.get_type()) {
1577 auto [linestring_sizes, linestring_sizes_size] =
1585 multi_linestring_coords,
1588 linestring_sizes_size,
1596 auto const_arr = const_arr_size.count(orig_arg_lvs[k + 1]) > 0;
1597 auto [linestring_sizes, linestring_sizes_size] =
1598 (const_arr) ? std::make_pair(orig_arg_lvs[k + 1],
1599 const_arr_size.at(orig_arg_lvs[k + 1]))
1604 args.push_back(linestring_sizes);
1605 args.push_back(linestring_sizes_size);
1617 auto [ring_size_buff, ring_size] =
1636 auto const_arr = const_arr_size.count(orig_arg_lvs[k + 1]) > 0;
1637 auto [ring_size_buff, ring_size] =
1638 (const_arr) ? std::make_pair(orig_arg_lvs[k + 1],
1639 const_arr_size.at(orig_arg_lvs[k + 1]))
1644 args.push_back(ring_size_buff);
1645 args.push_back(ring_size);
1657 auto [ring_size_buff, ring_size] =
1663 auto [poly_bounds_buff, poly_bounds_size] =
1685 auto const_arr = const_arr_size.count(orig_arg_lvs[k + 1]) > 0;
1686 auto [ring_size_buff, ring_size] =
1687 (const_arr) ? std::make_pair(orig_arg_lvs[k + 1],
1688 const_arr_size.at(orig_arg_lvs[k + 1]))
1694 args.push_back(ring_size_buff);
1695 args.push_back(ring_size);
1699 auto const_arr = const_arr_size.count(orig_arg_lvs[k + 2]) > 0;
1700 auto [poly_bounds_buff, poly_bounds_size] =
1702 ? std::make_pair(orig_arg_lvs[k + 2],
1703 const_arr_size.at(orig_arg_lvs[k + 2]))
1707 args.push_back(poly_bounds_buff);
1708 args.push_back(poly_bounds_size);
1720 if (arg_ti.get_type() != arg_target_ti.get_type()) {
1721 arg_lv = codegenCast(orig_arg_lvs[k], arg_ti, arg_target_ti,
false, co);
1723 arg_lv = orig_arg_lvs[k];
1727 args.push_back(arg_lv);
1767 auto*
const string_view_type =
1771 string_view_type->setName(
"StringView");
1772 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)
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)
std::string toString(const ExecutorDeviceType &device_type)
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
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_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)