OmniSciDB  a5dc49c757
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
GeoIR.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2022 HEAVY.AI, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "Geospatial/Compression.h"
19 #include "QueryEngine/Execute.h"
22 
23 using heavyai::ErrorCode;
24 
26  llvm::Value* pos,
27  const SQLTypeInfo& ti,
28  CgenState* cgen_state) {
29  CHECK(byte_stream);
30 
31  const auto key = std::make_pair(byte_stream, pos);
32  auto cache_itr = cgen_state->array_load_cache_.find(key);
33  if (cache_itr != cgen_state->array_load_cache_.end()) {
34  return cache_itr->second;
35  }
36  const bool is_nullable = !ti.get_notnull();
37  CHECK(ti.get_type() == kPOINT); // TODO: lift this
38 
39  auto pt_arr_buf =
40  cgen_state->emitExternalCall("array_buff",
41  llvm::Type::getInt8PtrTy(cgen_state->context_),
42  {key.first, key.second});
43  llvm::Value* pt_is_null{nullptr};
44  if (is_nullable) {
45  pt_is_null = cgen_state->emitExternalCall("point_coord_array_is_null",
46  llvm::Type::getInt1Ty(cgen_state->context_),
47  {key.first, key.second});
48  }
49  ArrayLoadCodegen arr_load{pt_arr_buf, nullptr, pt_is_null};
50  cgen_state->array_load_cache_.insert(std::make_pair(key, arr_load));
51  return arr_load;
52 }
53 
54 std::vector<llvm::Value*> CodeGenerator::codegenGeoColumnVar(
55  const Analyzer::GeoColumnVar* geo_col_var,
56  const bool fetch_columns,
57  const CompilationOptions& co) {
58  auto generate_column_lvs = [this, geo_col_var, &co](const int column_id) {
59  auto column_key = geo_col_var->getColumnKey();
60  column_key.column_id = column_id;
61 
62  auto cd = get_column_descriptor(column_key);
63  CHECK(cd);
64 
65  const auto col_var =
66  Analyzer::ColumnVar(cd->columnType, column_key, geo_col_var->get_rte_idx());
67  const auto lv_vec = codegen(&col_var, /*fetch_columns=*/true, co);
68  CHECK_EQ(lv_vec.size(), size_t(1)); // ptr
69  return lv_vec;
70  };
71 
72  const auto& ti = geo_col_var->get_type_info();
73  switch (ti.get_type()) {
74  case kPOINT:
75  case kLINESTRING:
76  case kMULTILINESTRING:
77  case kPOLYGON:
78  case kMULTIPOLYGON: {
79  std::vector<llvm::Value*> geo_lvs;
80  // iterate over physical columns
81  for (int i = 0; i < ti.get_physical_coord_cols(); i++) {
82  const auto column_id = geo_col_var->getColumnKey().column_id + 1 + i;
83  const auto lvs = generate_column_lvs(column_id);
84  CHECK_EQ(lvs.size(), size_t(1)); // expecting ptr for each column
85  geo_lvs.insert(geo_lvs.end(), lvs.begin(), lvs.end());
86  }
87 
88  return geo_lvs;
89  }
90  default:
91  UNREACHABLE() << geo_col_var->toString();
92  }
93  UNREACHABLE();
94  return {};
95 }
96 
97 std::vector<llvm::Value*> CodeGenerator::codegenGeoExpr(const Analyzer::GeoExpr* expr,
98  const CompilationOptions& co) {
99  auto geo_constant = dynamic_cast<const Analyzer::GeoConstant*>(expr);
100  if (geo_constant) {
101  return codegenGeoConstant(geo_constant, co);
102  }
103  auto geo_operator = dynamic_cast<const Analyzer::GeoOperator*>(expr);
104  if (geo_operator) {
105  return codegenGeoOperator(geo_operator, co);
106  }
107  UNREACHABLE() << expr->toString();
108  return {};
109 }
110 
111 std::vector<llvm::Value*> CodeGenerator::codegenGeoConstant(
112  const Analyzer::GeoConstant* geo_constant,
113  const CompilationOptions& co) {
115 
116  std::vector<llvm::Value*> ret;
117  for (size_t i = 0; i < geo_constant->physicalCols(); i++) {
118  auto physical_constant = geo_constant->makePhysicalConstant(i);
119  auto operand_lvs = codegen(physical_constant.get(), /*fetch_columns=*/true, co);
120  CHECK_EQ(operand_lvs.size(), size_t(2));
121  auto array_buff_lv = operand_lvs[0];
122  if (i > 0) {
123  array_buff_lv = cgen_state_->ir_builder_.CreateBitCast(
124  operand_lvs[0], llvm::Type::getInt8PtrTy(cgen_state_->context_));
125  }
126  ret.push_back(array_buff_lv);
127  ret.push_back(operand_lvs[1]);
128  }
129  return ret;
130 }
131 
132 namespace {
134  PlanState* plan_state) {
135  auto comparator = Analyzer::ColumnVar::colvar_comp;
136  std::set<const Analyzer::ColumnVar*,
137  bool (*)(const Analyzer::ColumnVar*, const Analyzer::ColumnVar*)>
138  colvar_set(comparator);
139  geo_operator->collect_column_var(colvar_set, false);
140  std::for_each(colvar_set.begin(), colvar_set.end(), [&](const Analyzer::ColumnVar* cv) {
141  // we set `unmark_lazy_fetch` to be FALSE to restart the compilation step
142  // if we already generated a code for the expression used in this geo_oper as
143  // lazy-fetch
144  plan_state->addColumnToFetch(cv->getColumnKey(), false);
145  });
146 }
147 } // namespace
148 
149 std::vector<llvm::Value*> CodeGenerator::codegenGeoOperator(
150  const Analyzer::GeoOperator* geo_operator,
151  const CompilationOptions& co) {
153 
154  if (geo_operator->getName() == "ST_X" || geo_operator->getName() == "ST_Y") {
155  const auto key = geo_operator->toString();
156  auto geo_target_cache_it = cgen_state_->geo_target_cache_.find(key);
157  if (geo_target_cache_it != cgen_state_->geo_target_cache_.end()) {
158  return {geo_target_cache_it->second};
159  }
160  }
161 
162  auto op_codegen = spatial_type::Codegen::init(geo_operator);
163  CHECK(op_codegen);
164  // we fetch all physical columns, so we sync the logical geo column w/ it
166 
167  std::vector<llvm::Value*> load_lvs;
168  std::vector<llvm::Value*> pos_lvs;
169  for (size_t i = 0; i < op_codegen->size(); i++) {
170  auto intermediate_lvs =
171  codegen(op_codegen->getOperand(i), /*fetch_columns=*/true, co);
172  load_lvs.insert(load_lvs.end(), intermediate_lvs.begin(), intermediate_lvs.end());
173  pos_lvs.push_back(posArg(op_codegen->getOperand(i)));
174  }
175 
176  auto [arg_lvs, null_lv] = op_codegen->codegenLoads(load_lvs, pos_lvs, cgen_state_);
177 
178  std::unique_ptr<CodeGenerator::NullCheckCodegen> nullcheck_codegen =
179  op_codegen->getNullCheckCodegen(null_lv, cgen_state_, executor());
180  return op_codegen->codegen(arg_lvs, nullcheck_codegen.get(), cgen_state_, co);
181 }
182 
183 std::vector<llvm::Value*> CodeGenerator::codegenGeoUOper(
184  const Analyzer::GeoUOper* geo_expr,
185  const CompilationOptions& co) {
188  if (geo_expr->getOp() != Geospatial::GeoBase::GeoOp::kPROJECTION) {
189  throw QueryMustRunOnCpu();
190  }
191  }
192 
193  auto argument_list = codegenGeoArgs(geo_expr->getArgs0(), co);
194 
195  if (geo_expr->getOp() == Geospatial::GeoBase::GeoOp::kPROJECTION) {
196  return argument_list;
197  }
198 
199 #ifndef ENABLE_GEOS
200  throw std::runtime_error("Geo operation requires GEOS support.");
201 #endif
202 
203  // Basic set of arguments is currently common to all Geos_* func invocations:
204  // op kind, type of the first geo arg0, geo arg0 components
205  std::string func = "Geos_Wkb"s;
206 
207  if (geo_expr->getTypeInfo0().transforms() || geo_expr->get_type_info().transforms()) {
208  // If there is a transform on the argument and/or on the result of the operation,
209  // verify that the argument's output srid is equal to result's input srid
210  if (geo_expr->getTypeInfo0().get_output_srid() !=
211  geo_expr->get_type_info().get_input_srid()) {
212  throw std::runtime_error("GEOS runtime: input/output srids have to match.");
213  }
214  }
215  // Prepend arg0 geo SQLType
216  argument_list.insert(
217  argument_list.begin(),
218  cgen_state_->llInt(static_cast<int>(geo_expr->getTypeInfo0().get_type())));
219  // Prepend geo expr op
220  argument_list.insert(argument_list.begin(),
221  cgen_state_->llInt(static_cast<int>(geo_expr->getOp())));
222  for (auto i = 3; i > geo_expr->getTypeInfo0().get_physical_coord_cols(); i--) {
223  argument_list.insert(argument_list.end(),
224  llvm::ConstantPointerNull::get(
225  llvm::Type::getInt32PtrTy(cgen_state_->context_, 0)));
226  argument_list.insert(argument_list.end(), cgen_state_->llInt(int64_t(0)));
227  }
228  // Append geo expr compression
229  argument_list.insert(
230  argument_list.end(),
231  cgen_state_->llInt(static_cast<int>(
233  // Append geo expr input srid
234  argument_list.insert(
235  argument_list.end(),
236  cgen_state_->llInt(static_cast<int>(geo_expr->getTypeInfo0().get_input_srid())));
237  // Append geo expr output srid
238  argument_list.insert(
239  argument_list.end(),
240  cgen_state_->llInt(static_cast<int>(geo_expr->getTypeInfo0().get_output_srid())));
241 
242  // Deal with unary geo predicates
243  if (geo_expr->getOp() == Geospatial::GeoBase::GeoOp::kISEMPTY ||
245  return codegenGeosPredicateCall(func, argument_list, co);
246  }
247 
248  if (geo_expr->getOp() == Geospatial::GeoBase::GeoOp::kCONVEXHULL) {
249  func += "_double"s; // Use same interface as ST_ConcaveHull, with a dummy double
250 
251  // Insert that dummy double arg
252  argument_list.insert(argument_list.end(), cgen_state_->llFp(double(0)));
253 
254  auto result_srid = cgen_state_->llInt(geo_expr->get_type_info().get_output_srid());
255 
256  return codegenGeosConstructorCall(func, argument_list, result_srid, co);
257  }
258 
259  throw std::runtime_error("Unsupported unary geo operation.");
260  return {};
261 }
262 
263 std::vector<llvm::Value*> CodeGenerator::codegenGeoBinOper(
264  Analyzer::GeoBinOper const* geo_expr,
265  CompilationOptions const& co) {
268  throw QueryMustRunOnCpu();
269  }
270 #ifndef ENABLE_GEOS
271  throw std::runtime_error("Geo operation requires GEOS support.");
272 #endif
273 
274  auto argument_list = codegenGeoArgs(geo_expr->getArgs0(), co);
275 
276  // Basic set of arguments is currently common to all Geos_* func invocations:
277  // op kind, type of the first geo arg0, geo arg0 components
278  std::string func = "Geos_Wkb"s;
279  if (geo_expr->getTypeInfo0().transforms() || geo_expr->get_type_info().transforms()) {
280  // If there is a transform on the argument and/or on the result of the operation,
281  // verify that the argument's output srid is equal to result's input srid
282  if (geo_expr->getTypeInfo0().get_output_srid() !=
283  geo_expr->get_type_info().get_input_srid()) {
284  throw std::runtime_error("GEOS runtime: input/output srids have to match.");
285  }
286  }
287  // Prepend arg0 geo SQLType
288  argument_list.insert(
289  argument_list.begin(),
290  cgen_state_->llInt(static_cast<int>(geo_expr->getTypeInfo0().get_type())));
291  // Prepend geo expr op
292  argument_list.insert(argument_list.begin(),
293  cgen_state_->llInt(static_cast<int>(geo_expr->getOp())));
294  for (auto i = 3; i > geo_expr->getTypeInfo0().get_physical_coord_cols(); i--) {
295  argument_list.insert(argument_list.end(),
296  llvm::ConstantPointerNull::get(
297  llvm::Type::getInt32PtrTy(cgen_state_->context_, 0)));
298  argument_list.insert(argument_list.end(), cgen_state_->llInt(int64_t(0)));
299  }
300  // Append geo expr compression
301  argument_list.insert(
302  argument_list.end(),
303  cgen_state_->llInt(static_cast<int>(
305  // Append geo expr input srid
306  argument_list.insert(
307  argument_list.end(),
308  cgen_state_->llInt(static_cast<int>(geo_expr->getTypeInfo0().get_input_srid())));
309  // Append geo expr output srid
310  argument_list.insert(
311  argument_list.end(),
312  cgen_state_->llInt(static_cast<int>(geo_expr->getTypeInfo0().get_output_srid())));
313 
314  auto arg1_list = codegenGeoArgs(geo_expr->getArgs1(), co);
315 
316  if (geo_expr->getOp() == Geospatial::GeoBase::GeoOp::kDIFFERENCE ||
318  geo_expr->getOp() == Geospatial::GeoBase::GeoOp::kUNION ||
320  func += "_Wkb"s;
321  if (geo_expr->getOp() == Geospatial::GeoBase::GeoOp::kEQUALS) {
322  func += "_Predicate"s;
323  }
324  // Prepend arg1 geo SQLType
325  arg1_list.insert(
326  arg1_list.begin(),
327  cgen_state_->llInt(static_cast<int>(geo_expr->getTypeInfo1().get_type())));
328  for (auto i = 3; i > geo_expr->getTypeInfo1().get_physical_coord_cols(); i--) {
329  arg1_list.insert(arg1_list.end(),
330  llvm::ConstantPointerNull::get(
331  llvm::Type::getInt32PtrTy(cgen_state_->context_, 0)));
332  arg1_list.insert(arg1_list.end(), cgen_state_->llInt(int64_t(0)));
333  }
334  // Append geo expr compression
335  arg1_list.insert(arg1_list.end(),
336  cgen_state_->llInt(static_cast<int>(
338  // Append geo expr input srid
339  arg1_list.insert(arg1_list.end(),
340  cgen_state_->llInt(geo_expr->getTypeInfo1().get_input_srid()));
341  // Append geo expr output srid
342  arg1_list.insert(arg1_list.end(),
344  } else if (geo_expr->getOp() == Geospatial::GeoBase::GeoOp::kBUFFER) {
345  // Extra argument in this case is double
346  func += "_double"s;
347  } else if (geo_expr->getOp() == Geospatial::GeoBase::GeoOp::kCONCAVEHULL) {
348 #if (GEOS_VERSION_MAJOR > 3) || (GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR >= 11)
349  // Extra argument in this case is double
350  func += "_double"s;
351 #else
352  throw std::runtime_error("ST_ConcaveHull requires GEOS 3.11 or newer");
353 #endif
354  } else {
355  throw std::runtime_error("Unsupported binary geo operation.");
356  }
357 
358  // Append arg1 to the list
359  argument_list.insert(argument_list.end(), arg1_list.begin(), arg1_list.end());
360 
361  // Deal with binary geo predicates
362  if (geo_expr->getOp() == Geospatial::GeoBase::GeoOp::kEQUALS) {
363  return codegenGeosPredicateCall(func, argument_list, co);
364  }
365 
366  auto result_srid = cgen_state_->llInt(geo_expr->get_type_info().get_output_srid());
367 
368  return codegenGeosConstructorCall(func, argument_list, result_srid, co);
369 }
370 
371 std::vector<llvm::Value*> CodeGenerator::codegenGeoArgs(
372  const std::vector<std::shared_ptr<Analyzer::Expr>>& geo_args,
373  const CompilationOptions& co) {
375  std::vector<llvm::Value*> argument_list;
376  bool coord_col = true;
377  for (const auto& geo_arg : geo_args) {
378  const auto arg = geo_arg.get();
379  const auto& arg_ti = arg->get_type_info();
380  const auto elem_ti = arg_ti.get_elem_type();
381  const auto arg_lvs = codegen(arg, true, co);
382  if (arg_ti.is_number()) {
383  argument_list.emplace_back(arg_lvs.front());
384  continue;
385  }
386  if (arg_ti.is_geometry()) {
387  argument_list.insert(argument_list.end(), arg_lvs.begin(), arg_lvs.end());
388  continue;
389  }
390  CHECK(arg_ti.is_array());
391  if (arg_lvs.size() > 1) {
392  CHECK_EQ(size_t(2), arg_lvs.size());
393  auto ptr_lv = arg_lvs.front();
394  if (coord_col) {
395  coord_col = false;
396  } else {
397  ptr_lv = cgen_state_->ir_builder_.CreatePointerCast(
398  ptr_lv, llvm::Type::getInt32PtrTy(cgen_state_->context_));
399  }
400  argument_list.emplace_back(ptr_lv);
401  auto cast_len_lv = cgen_state_->ir_builder_.CreateZExt(
402  arg_lvs.back(), get_int_type(64, cgen_state_->context_));
403  argument_list.emplace_back(cast_len_lv);
404  } else {
405  CHECK_EQ(size_t(1), arg_lvs.size());
406  if (arg_ti.get_size() > 0) {
407  // Set up the pointer lv for a dynamically generated point
408  auto ptr_lv = arg_lvs.front();
409  auto col_var = dynamic_cast<const Analyzer::ColumnVar*>(arg);
410  // Override for point coord column access
411  if (col_var) {
412  ptr_lv = cgen_state_->emitExternalCall(
413  "fast_fixlen_array_buff",
414  llvm::Type::getInt8PtrTy(cgen_state_->context_),
415  {arg_lvs.front(), posArg(arg)});
416  }
417  if (coord_col) {
418  coord_col = false;
419  } else {
420  ptr_lv = cgen_state_->ir_builder_.CreatePointerCast(
421  ptr_lv, llvm::Type::getInt32PtrTy(cgen_state_->context_));
422  }
423  argument_list.emplace_back(ptr_lv);
424  argument_list.emplace_back(cgen_state_->llInt<int64_t>(arg_ti.get_size()));
425  } else {
426  auto ptr_lv =
427  cgen_state_->emitExternalCall("array_buff",
428  llvm::Type::getInt8PtrTy(cgen_state_->context_),
429  {arg_lvs.front(), posArg(arg)});
430  if (coord_col) {
431  coord_col = false;
432  } else {
433  ptr_lv = cgen_state_->ir_builder_.CreatePointerCast(
434  ptr_lv, llvm::Type::getInt32PtrTy(cgen_state_->context_));
435  }
436  argument_list.emplace_back(ptr_lv);
437  const auto len_lv = cgen_state_->emitExternalCall(
438  "array_size",
440  {arg_lvs.front(),
441  posArg(arg),
442  cgen_state_->llInt(log2_bytes(elem_ti.get_logical_size()))});
443  auto cast_len_lv = cgen_state_->ir_builder_.CreateZExt(
444  len_lv, get_int_type(64, cgen_state_->context_));
445  argument_list.emplace_back(cast_len_lv);
446  }
447  }
448  }
449  return argument_list;
450 }
451 
452 std::vector<llvm::Value*> CodeGenerator::codegenGeosPredicateCall(
453  const std::string& func,
454  std::vector<llvm::Value*> argument_list,
455  const CompilationOptions& co) {
457  auto i8_type = get_int_type(8, cgen_state_->context_);
458  auto result = cgen_state_->ir_builder_.CreateAlloca(i8_type, nullptr, "result");
459  argument_list.emplace_back(result);
460 
461  // Generate call to GEOS wrapper
462  cgen_state_->needs_geos_ = true;
463  auto status_lv = cgen_state_->emitExternalCall(
464  func, llvm::Type::getInt1Ty(cgen_state_->context_), argument_list);
465  // Need to check the status and throw an error if this call has failed.
466  llvm::BasicBlock* geos_pred_ok_bb{nullptr};
467  llvm::BasicBlock* geos_pred_fail_bb{nullptr};
468  geos_pred_ok_bb = llvm::BasicBlock::Create(
469  cgen_state_->context_, "geos_pred_ok_bb", cgen_state_->current_func_);
470  geos_pred_fail_bb = llvm::BasicBlock::Create(
471  cgen_state_->context_, "geos_pred_fail_bb", cgen_state_->current_func_);
472  if (!status_lv) {
473  status_lv = cgen_state_->llBool(false);
474  }
475  cgen_state_->ir_builder_.CreateCondBr(status_lv, geos_pred_ok_bb, geos_pred_fail_bb);
476  cgen_state_->ir_builder_.SetInsertPoint(geos_pred_fail_bb);
477  cgen_state_->ir_builder_.CreateRet(cgen_state_->llInt(int32_t(ErrorCode::GEOS)));
479  cgen_state_->ir_builder_.SetInsertPoint(geos_pred_ok_bb);
480  auto res = cgen_state_->ir_builder_.CreateLoad(
481  result->getType()->getPointerElementType(), result);
482  return {res};
483 }
484 
486  const std::string& func,
487  std::vector<llvm::Value*> argument_list,
488  llvm::Value* result_srid,
489  const CompilationOptions& co) {
491  // Create output buffer pointers, append pointers to output args to
492  auto i8_type = get_int_type(8, cgen_state_->context_);
493  auto i32_type = get_int_type(32, cgen_state_->context_);
494  auto i64_type = get_int_type(64, cgen_state_->context_);
495  auto pi8_type = llvm::PointerType::get(i8_type, 0);
496  auto pi32_type = llvm::PointerType::get(i32_type, 0);
497 
498  auto result_type =
499  cgen_state_->ir_builder_.CreateAlloca(i32_type, nullptr, "result_type");
500  auto result_coords =
501  cgen_state_->ir_builder_.CreateAlloca(pi8_type, nullptr, "result_coords");
502  auto result_coords_size =
503  cgen_state_->ir_builder_.CreateAlloca(i64_type, nullptr, "result_coords_size");
504  auto result_ring_sizes =
505  cgen_state_->ir_builder_.CreateAlloca(pi32_type, nullptr, "result_ring_sizes");
506  auto result_ring_sizes_size =
507  cgen_state_->ir_builder_.CreateAlloca(i64_type, nullptr, "result_ring_sizes_size");
508  auto result_poly_rings =
509  cgen_state_->ir_builder_.CreateAlloca(pi32_type, nullptr, "result_poly_rings");
510  auto result_poly_rings_size =
511  cgen_state_->ir_builder_.CreateAlloca(i64_type, nullptr, "result_poly_rings_size");
512 
513  argument_list.emplace_back(result_type);
514  argument_list.emplace_back(result_coords);
515  argument_list.emplace_back(result_coords_size);
516  argument_list.emplace_back(result_ring_sizes);
517  argument_list.emplace_back(result_ring_sizes_size);
518  argument_list.emplace_back(result_poly_rings);
519  argument_list.emplace_back(result_poly_rings_size);
520  argument_list.emplace_back(result_srid);
521 
522  // Generate call to GEOS wrapper
523  cgen_state_->needs_geos_ = true;
524  auto status_lv = cgen_state_->emitExternalCall(
525  func, llvm::Type::getInt1Ty(cgen_state_->context_), argument_list);
526  // Need to check the status and throw an error if this call has failed.
527  llvm::BasicBlock* geos_ok_bb{nullptr};
528  llvm::BasicBlock* geos_fail_bb{nullptr};
529  geos_ok_bb = llvm::BasicBlock::Create(
530  cgen_state_->context_, "geos_ok_bb", cgen_state_->current_func_);
531  geos_fail_bb = llvm::BasicBlock::Create(
532  cgen_state_->context_, "geos_fail_bb", cgen_state_->current_func_);
533  if (!status_lv) {
534  status_lv = cgen_state_->llBool(false);
535  }
536  cgen_state_->ir_builder_.CreateCondBr(status_lv, geos_ok_bb, geos_fail_bb);
537  cgen_state_->ir_builder_.SetInsertPoint(geos_fail_bb);
538  cgen_state_->ir_builder_.CreateRet(cgen_state_->llInt(int32_t(ErrorCode::GEOS)));
540  cgen_state_->ir_builder_.SetInsertPoint(geos_ok_bb);
541 
542  // TODO: Currently forcing the output to MULTIPOLYGON, but need to handle
543  // other possible geometries that geos may return, e.g. a POINT, a LINESTRING
544  // Need to handle empty result, e.g. empty intersection.
545  // The type of result is returned in `result_type`
546 
547  // Load return values
548  auto buf1 = cgen_state_->ir_builder_.CreateLoad(
549  result_coords->getType()->getPointerElementType(), result_coords);
550  auto buf1s = cgen_state_->ir_builder_.CreateLoad(
551  result_coords_size->getType()->getPointerElementType(), result_coords_size);
552  auto buf2 = cgen_state_->ir_builder_.CreateLoad(
553  result_ring_sizes->getType()->getPointerElementType(), result_ring_sizes);
554  auto buf2s = cgen_state_->ir_builder_.CreateLoad(
555  result_ring_sizes_size->getType()->getPointerElementType(), result_ring_sizes_size);
556  auto buf3 = cgen_state_->ir_builder_.CreateLoad(
557  result_poly_rings->getType()->getPointerElementType(), result_poly_rings);
558  auto buf3s = cgen_state_->ir_builder_.CreateLoad(
559  result_poly_rings_size->getType()->getPointerElementType(), result_poly_rings_size);
560 
561  // generate register_buffer_with_executor_rsm() calls to register all output buffers
563  "register_buffer_with_executor_rsm",
564  llvm::Type::getVoidTy(cgen_state_->context_),
565  {cgen_state_->llInt(reinterpret_cast<int64_t>(executor())),
566  cgen_state_->ir_builder_.CreatePointerCast(buf1, pi8_type)});
567  cgen_state_->emitExternalCall(
568  "register_buffer_with_executor_rsm",
569  llvm::Type::getVoidTy(cgen_state_->context_),
570  {cgen_state_->llInt(reinterpret_cast<int64_t>(executor())),
571  cgen_state_->ir_builder_.CreatePointerCast(buf2, pi8_type)});
572  cgen_state_->emitExternalCall(
573  "register_buffer_with_executor_rsm",
574  llvm::Type::getVoidTy(cgen_state_->context_),
575  {cgen_state_->llInt(reinterpret_cast<int64_t>(executor())),
576  cgen_state_->ir_builder_.CreatePointerCast(buf3, pi8_type)});
577 
578  return {cgen_state_->ir_builder_.CreatePointerCast(buf1, pi8_type),
579  buf1s,
580  cgen_state_->ir_builder_.CreatePointerCast(buf2, pi32_type),
581  buf2s,
582  cgen_state_->ir_builder_.CreatePointerCast(buf3, pi32_type),
583  buf3s};
584 }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
const SQLTypeInfo getTypeInfo0() const
Definition: Analyzer.h:3091
const std::vector< std::shared_ptr< Analyzer::Expr > > & getArgs0() const
Definition: Analyzer.h:3093
void mark_logical_column_to_fetch(const Analyzer::GeoOperator *geo_operator, PlanState *plan_state)
Definition: GeoIR.cpp:133
static bool colvar_comp(const ColumnVar *l, const ColumnVar *r)
Definition: Analyzer.h:215
const SQLTypeInfo getTypeInfo0() const
Definition: Analyzer.h:3062
CgenState * cgen_state_
std::map< std::pair< llvm::Value *, llvm::Value * >, ArrayLoadCodegen > array_load_cache_
Definition: CgenState.h:403
void addColumnToFetch(const shared::ColumnKey &column_key, bool unmark_lazy_fetch=false)
Definition: PlanState.cpp:124
llvm::IRBuilder ir_builder_
Definition: CgenState.h:384
int32_t get_compression_scheme(const SQLTypeInfo &ti)
Definition: Compression.cpp:23
llvm::Value * posArg(const Analyzer::Expr *) const
Definition: ColumnIR.cpp:590
#define UNREACHABLE()
Definition: Logger.h:338
const SQLTypeInfo getTypeInfo1() const
Definition: Analyzer.h:3092
llvm::ConstantInt * llBool(const bool v) const
Definition: CgenState.h:263
bool needs_geos_
Definition: CgenState.h:406
HOST DEVICE SQLTypes get_type() const
Definition: sqltypes.h:391
llvm::Type * get_int_type(const int width, llvm::LLVMContext &context)
std::vector< llvm::Value * > codegenGeoBinOper(const Analyzer::GeoBinOper *, const CompilationOptions &)
Definition: GeoIR.cpp:263
std::unordered_map< std::string, llvm::Value * > geo_target_cache_
Definition: CgenState.h:404
std::vector< llvm::Value * > codegenGeoExpr(const Analyzer::GeoExpr *, const CompilationOptions &)
Definition: GeoIR.cpp:97
llvm::LLVMContext & context_
Definition: CgenState.h:382
llvm::Function * current_func_
Definition: CgenState.h:376
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)
Definition: CgenState.cpp:395
std::vector< llvm::Value * > codegenGeoOperator(const Analyzer::GeoOperator *, const CompilationOptions &)
Definition: GeoIR.cpp:149
std::vector< llvm::Value * > codegenGeoUOper(const Analyzer::GeoUOper *, const CompilationOptions &)
Definition: GeoIR.cpp:183
const std::vector< std::shared_ptr< Analyzer::Expr > > & getArgs0() const
Definition: Analyzer.h:3063
std::string toString() const override
Definition: Analyzer.cpp:2717
const ColumnDescriptor * get_column_descriptor(const shared::ColumnKey &column_key)
Definition: Execute.h:213
const std::string & getName() const
Definition: Analyzer.h:3298
bool needs_error_check_
Definition: CgenState.h:405
llvm::ConstantFP * llFp(const float v) const
Definition: CgenState.h:253
#define AUTOMATIC_IR_METADATA(CGENSTATE)
std::vector< llvm::Value * > codegenGeosConstructorCall(const std::string &, std::vector< llvm::Value * >, llvm::Value *, const CompilationOptions &)
Definition: GeoIR.cpp:485
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:79
ExecutorDeviceType device_type
PlanState * plan_state_
std::vector< llvm::Value * > codegen(const Analyzer::Expr *, const bool fetch_columns, const CompilationOptions &)
Definition: IRCodegen.cpp:30
virtual std::string toString() const =0
const shared::ColumnKey & getColumnKey() const
Definition: Analyzer.h:198
std::vector< llvm::Value * > codegenGeosPredicateCall(const std::string &, std::vector< llvm::Value * >, const CompilationOptions &)
Definition: GeoIR.cpp:452
static ArrayLoadCodegen codegenGeoArrayLoadAndNullcheck(llvm::Value *byte_stream, llvm::Value *pos, const SQLTypeInfo &ti, CgenState *cgen_state)
Definition: GeoIR.cpp:25
std::vector< llvm::Value * > codegenGeoColumnVar(const Analyzer::GeoColumnVar *, const bool fetch_columns, const CompilationOptions &co)
Definition: GeoIR.cpp:54
HOST DEVICE int get_input_srid() const
Definition: sqltypes.h:395
llvm::ConstantInt * llInt(const T v) const
Definition: CgenState.h:249
std::vector< llvm::Value * > codegenGeoArgs(const std::vector< std::shared_ptr< Analyzer::Expr >> &, const CompilationOptions &)
Definition: GeoIR.cpp:371
#define CHECK(condition)
Definition: Logger.h:291
Geospatial::GeoBase::GeoOp getOp() const
Definition: Analyzer.h:3061
std::vector< llvm::Value * > codegenGeoConstant(const Analyzer::GeoConstant *, const CompilationOptions &)
Definition: GeoIR.cpp:111
uint32_t log2_bytes(const uint32_t bytes)
Definition: Execute.h:198
std::shared_ptr< Analyzer::Constant > makePhysicalConstant(const size_t index) const
Definition: Analyzer.cpp:4087
void collect_column_var(std::set< const ColumnVar *, bool(*)(const ColumnVar *, const ColumnVar *)> &colvar_set, bool include_agg) const final
Definition: Analyzer.cpp:4174
bool transforms() const
Definition: sqltypes.h:626
HOST DEVICE bool get_notnull() const
Definition: sqltypes.h:398
std::string toString() const override
Definition: Analyzer.cpp:4183
int32_t get_rte_idx() const
Definition: Analyzer.h:202
int get_physical_coord_cols() const
Definition: sqltypes.h:451
size_t physicalCols() const
Definition: Analyzer.cpp:4082
Geospatial::GeoBase::GeoOp getOp() const
Definition: Analyzer.h:3090
static std::unique_ptr< Codegen > init(const Analyzer::GeoOperator *geo_operator)
Definition: Codegen.cpp:22
const std::vector< std::shared_ptr< Analyzer::Expr > > & getArgs1() const
Definition: Analyzer.h:3094
HOST DEVICE int get_output_srid() const
Definition: sqltypes.h:397
Executor * executor() const