19 namespace spatial_type {
26 :
Codegen(geo_operator, catalog)
28 dynamic_cast<const Analyzer::GeoTransformOperator*>(geo_operator)) {
32 if (ti.get_notnull()) {
39 size_t size()
const override {
return 1; }
43 inline static bool isUtm(
unsigned const srid) {
44 return (32601 <= srid && srid <= 32660) || (32701 <= srid && srid <= 32760);
48 const std::vector<llvm::Value*>& arg_lvs,
49 const std::vector<llvm::Value*>& pos_lvs,
53 const auto& operand_ti = geo_operand->get_type_info();
54 CHECK(operand_ti.is_geometry() && operand_ti.get_type() ==
kPOINT);
56 if (dynamic_cast<const Analyzer::ColumnVar*>(geo_operand)) {
59 arg_lvs.front(), pos_lvs.front(), operand_ti, cgen_state);
60 return std::make_tuple(std::vector<llvm::Value*>{arr_load_lvs.buffer},
61 arr_load_lvs.is_null);
62 }
else if (dynamic_cast<const Analyzer::GeoConstant*>(geo_operand)) {
68 return std::make_tuple(std::vector<llvm::Value*>{arg_lvs.front()},
nullptr);
70 CHECK(arg_lvs.size() == size_t(1) ||
71 arg_lvs.size() == size_t(2));
76 const auto is_null = builder.CreateICmp(
77 llvm::CmpInst::ICMP_EQ,
79 llvm::ConstantPointerNull::get(
81 ? llvm::Type::getInt32PtrTy(cgen_state->
context_)
82 : llvm::Type::getDoublePtrTy(cgen_state->
context_)));
83 return std::make_tuple(std::vector<llvm::Value*>{arg_lvs.front()},
is_null);
86 return std::make_tuple(std::vector<llvm::Value*>{},
nullptr);
89 std::vector<llvm::Value*>
codegen(
const std::vector<llvm::Value*>&
args,
96 const auto& operand_ti = geo_operand->get_type_info();
99 llvm::Value* arr_buff_ptr = args.front();
103 builder.CreateAlloca(llvm::Type::getDoubleTy(cgen_state->
context_),
104 cgen_state->
llInt(int32_t(2)),
106 auto compressed_arr_ptr = builder.CreateBitCast(
107 arr_buff_ptr, llvm::Type::getInt32PtrTy(cgen_state->
context_));
109 auto* gep = builder.CreateGEP(
110 compressed_arr_ptr->getType()->getScalarType()->getPointerElementType(),
112 cgen_state->
llInt(0));
114 "decompress_x_coord_geoint",
115 llvm::Type::getDoubleTy(cgen_state->
context_),
117 gep->getType()->getPointerElementType(), gep,
"compressed_x_coord")});
121 new_arr_ptr->getType()->getScalarType()->getPointerElementType(),
123 cgen_state->
llInt(0)));
124 gep = builder.CreateGEP(
125 compressed_arr_ptr->getType()->getScalarType()->getPointerElementType(),
127 cgen_state->
llInt(1));
129 "decompress_y_coord_geoint",
130 llvm::Type::getDoubleTy(cgen_state->
context_),
132 gep->getType()->getPointerElementType(), gep,
"compressed_y_coord")});
136 new_arr_ptr->getType()->getScalarType()->getPointerElementType(),
138 cgen_state->
llInt(1)));
139 arr_buff_ptr = new_arr_ptr;
142 builder.CreateAlloca(llvm::Type::getDoubleTy(cgen_state->
context_),
143 cgen_state->
llInt(int32_t(2)),
145 const auto arr_buff_ptr_cast = builder.CreateBitCast(
146 arr_buff_ptr, llvm::Type::getDoublePtrTy(cgen_state->
context_));
148 auto* gep = builder.CreateGEP(
149 arr_buff_ptr_cast->getType()->getScalarType()->getPointerElementType(),
151 cgen_state->
llInt(0));
153 builder.CreateLoad(gep->getType()->getPointerElementType(), gep),
155 new_arr_ptr->getType()->getScalarType()->getPointerElementType(),
157 cgen_state->
llInt(0)));
158 gep = builder.CreateGEP(
159 arr_buff_ptr_cast->getType()->getScalarType()->getPointerElementType(),
161 cgen_state->
llInt(1));
163 builder.CreateLoad(gep->getType()->getPointerElementType(), gep),
165 new_arr_ptr->getType()->getScalarType()->getPointerElementType(),
167 cgen_state->
llInt(1)));
168 arr_buff_ptr = new_arr_ptr;
170 CHECK(arr_buff_ptr->getType() == llvm::Type::getDoublePtrTy(cgen_state->
context_));
174 if (srid_in == srid_out) {
176 return {args.front()};
180 std::string transform_function_prefix{
""};
181 std::vector<llvm::Value*> transform_args;
183 if (srid_out == 900913) {
184 if (srid_in == 4326) {
185 transform_function_prefix =
"transform_4326_900913_";
186 }
else if (
isUtm(srid_in)) {
187 transform_function_prefix =
"transform_utm_900913_";
188 transform_args.push_back(cgen_state->
llInt(srid_in));
190 throw std::runtime_error(
"Unsupported input SRID " +
std::to_string(srid_in) +
193 }
else if (srid_out == 4326) {
194 if (srid_in == 900913) {
195 transform_function_prefix =
"transform_900913_4326_";
196 }
else if (
isUtm(srid_in)) {
197 transform_function_prefix =
"transform_utm_4326_";
198 transform_args.push_back(cgen_state->
llInt(srid_in));
200 throw std::runtime_error(
"Unsupported input SRID " +
std::to_string(srid_in) +
203 }
else if (
isUtm(srid_out)) {
204 if (srid_in == 4326) {
205 transform_function_prefix =
"transform_4326_utm_";
206 }
else if (srid_in == 900913) {
207 transform_function_prefix =
"transform_900913_utm_";
209 throw std::runtime_error(
"Unsupported input SRID " +
std::to_string(srid_in) +
212 transform_args.push_back(cgen_state->
llInt(srid_out));
214 throw std::runtime_error(
"Unsupported output SRID for ST_Transform: " +
217 CHECK(!transform_function_prefix.empty());
219 auto x_coord_ptr_lv = builder.CreateGEP(
220 arr_buff_ptr->getType()->getScalarType()->getPointerElementType(),
222 cgen_state->
llInt(0),
224 transform_args.push_back(builder.CreateLoad(
225 x_coord_ptr_lv->getType()->getPointerElementType(), x_coord_ptr_lv,
"x_coord"));
226 auto y_coord_ptr_lv = builder.CreateGEP(
227 arr_buff_ptr->getType()->getScalarType()->getPointerElementType(),
229 cgen_state->
llInt(1),
231 transform_args.push_back(builder.CreateLoad(
232 y_coord_ptr_lv->getType()->getPointerElementType(), y_coord_ptr_lv,
"y_coord"));
234 auto fn_x = cgen_state->
module_->getFunction(transform_function_prefix +
'x');
237 CHECK(!fn_x->isDeclaration());
240 for (
const auto& fcn_name : gpu_functions_to_replace) {
244 auto transform_call = builder.CreateCall(fn_x, transform_args);
245 builder.CreateStore(transform_call, x_coord_ptr_lv);
247 auto fn_y = cgen_state->
module_->getFunction(transform_function_prefix +
'y');
250 CHECK(!fn_y->isDeclaration());
253 for (
const auto& fcn_name : gpu_functions_to_replace) {
257 transform_call = builder.CreateCall(fn_y, transform_args);
258 builder.CreateStore(transform_call, y_coord_ptr_lv);
261 cgen_state->
emitCall(transform_function_prefix +
'x', transform_args),
264 cgen_state->
emitCall(transform_function_prefix +
'y', transform_args),
267 auto ret = arr_buff_ptr;
271 CHECK(nullcheck_codegen);
273 llvm::ConstantPointerNull::get(
275 ? llvm::PointerType::get(llvm::Type::getInt32Ty(cgen_state->
context_),
277 : llvm::PointerType::get(llvm::Type::getDoubleTy(cgen_state->
context_),
282 cgen_state->
llInt(static_cast<int32_t>(
class for a per-database catalog. also includes metadata for the current database and the current use...
void maybeCloneFunctionRecursive(llvm::Function *fn)
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::IRBuilder ir_builder_
void verify_function_ir(const llvm::Function *func)
llvm::LLVMContext & context_
CONSTEXPR DEVICE bool is_null(const T &value)
void replaceFunctionForGpu(const std::string &fcn_to_replace, llvm::Function *fn)
std::vector< std::string > gpuFunctionsToReplace(llvm::Function *fn)
const SQLTypeInfo & get_type_info() const
llvm::Value * emitCall(const std::string &fname, const std::vector< llvm::Value * > &args)
ExecutorDeviceType device_type
static ArrayLoadCodegen codegenGeoArrayLoadAndNullcheck(llvm::Value *byte_stream, llvm::Value *pos, const SQLTypeInfo &ti, CgenState *cgen_state)
const Analyzer::GeoOperator * operator_
llvm::ConstantInt * llInt(const T v) const
llvm::Value * finalize(llvm::Value *null_lv, llvm::Value *notnull_lv)
virtual const Analyzer::Expr * getOperand(const size_t index)
std::string getName() const