OmniSciDB  91042dcc5b
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
PointConstructor.h
Go to the documentation of this file.
1 /*
2  * Copyright 2021 OmniSci, 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 #pragma once
18 
20 
21 #include "Shared/SqlTypesLayout.h"
22 
23 namespace spatial_type {
24 
25 // ST_Point
26 class PointConstructor : public Codegen {
27  public:
29  const Catalog_Namespace::Catalog* catalog)
30  : Codegen(geo_operator, catalog) {
31  CHECK_EQ(operator_->size(), size_t(2));
32  const auto& ti = geo_operator->get_type_info();
33  if (ti.get_notnull()) {
34  is_nullable_ = false;
35  } else {
36  is_nullable_ = true;
37  }
38  }
39 
40  std::unique_ptr<CodeGenerator::NullCheckCodegen> getNullCheckCodegen(
41  llvm::Value* null_lv,
42  CgenState* cgen_state,
43  Executor* executor) final {
44  if (isNullable()) {
45  // do the standard nullcheck codegen, but modify the null basic block to emplace the
46  // null sentinel into the array
47  auto nullcheck_codegen = std::make_unique<CodeGenerator::NullCheckCodegen>(
48  cgen_state, executor, null_lv, getNullType(), getName() + "_nullcheck");
49 
50  auto& builder = cgen_state->ir_builder_;
52 
53  auto prev_insert_block = builder.GetInsertBlock();
54  auto crt_insert_block = nullcheck_codegen->null_check->cond_true_;
55  CHECK(crt_insert_block);
56  auto& instruction_list = crt_insert_block->getInstList();
57  CHECK_EQ(instruction_list.size(), size_t(1));
58  builder.SetInsertPoint(crt_insert_block, instruction_list.begin());
59 
60  auto x_coord_ptr = builder.CreateGEP(
61  pt_local_storage_lv_->getType()->getScalarType()->getPointerElementType(),
63  {cgen_state->llInt(0), cgen_state->llInt(0)},
64  "x_coord_ptr");
65  const auto& geo_ti = operator_->get_type_info();
66  if (geo_ti.get_compression() == kENCODING_GEOINT) {
67  // TODO: probably wrong
68  builder.CreateStore(cgen_state->llInt(inline_int_null_val(SQLTypeInfo(kINT))),
69  x_coord_ptr);
70  } else {
71  builder.CreateStore(cgen_state->llFp(static_cast<double>(NULL_ARRAY_DOUBLE)),
72  x_coord_ptr);
73  }
74  builder.SetInsertPoint(prev_insert_block);
75 
76  return nullcheck_codegen;
77  } else {
78  return nullptr;
79  }
80  }
81 
82  size_t size() const final { return 2; }
83 
85 
86  // returns arguments lvs and null lv
87  std::tuple<std::vector<llvm::Value*>, llvm::Value*> codegenLoads(
88  const std::vector<llvm::Value*>& arg_lvs,
89  const std::vector<llvm::Value*>& pos_lvs,
90  CgenState* cgen_state) final {
91  CHECK_EQ(pos_lvs.size(),
92  size()); // note both pos arguments should be the same, as both inputs are
93  // expected to be from the same table, though this is moot in this
94  // function as position argumnts are not used here
95  CHECK_EQ(arg_lvs.size(), size_t(2));
96 
97  auto& builder = cgen_state->ir_builder_;
98 
99  llvm::Value* is_null{nullptr};
100  auto x_operand = getOperand(0);
101  const auto& x_ti = x_operand->get_type_info();
102  if (!x_ti.get_notnull()) {
103  CHECK(x_ti.is_integer() || x_ti.is_fp());
104  // TODO: centralize nullcheck logic for all sqltypes
105  is_null = x_ti.is_integer()
106  ? builder.CreateICmp(llvm::CmpInst::ICMP_EQ,
107  arg_lvs.front(),
108  cgen_state->llInt(inline_int_null_val(x_ti)))
109  : builder.CreateFCmp(llvm::FCmpInst::FCMP_OEQ,
110  arg_lvs.front(),
111  cgen_state->llFp(inline_fp_null_val(x_ti)));
112  }
113 
114  auto y_operand = getOperand(0);
115  const auto& y_ti = y_operand->get_type_info();
116  if (!y_ti.get_notnull()) {
117  auto y_is_null =
118  y_ti.is_integer()
119  ? builder.CreateICmp(llvm::CmpInst::ICMP_EQ,
120  arg_lvs.front(),
121  cgen_state->llInt(inline_int_null_val(y_ti)))
122  : builder.CreateFCmp(llvm::FCmpInst::FCMP_OEQ,
123  arg_lvs.front(),
124  cgen_state->llFp(inline_fp_null_val(y_ti)));
125  if (is_null) {
126  is_null = builder.CreateAnd(is_null, y_is_null);
127  } else {
128  is_null = y_is_null;
129  }
130  }
131 
132  if (is_nullable_ && !is_null) {
133  // if the inputs are not null, set the output to be not null
134  // TODO: we should do this in the translator and just confirm it here
135  is_nullable_ = false;
136  }
137 
138  // do the alloca before nullcheck codegen, as either way we will return a point array
139  const auto& geo_ti = operator_->get_type_info();
140  CHECK(geo_ti.get_type() == kPOINT);
141 
142  llvm::ArrayType* arr_type{nullptr};
143  if (geo_ti.get_compression() == kENCODING_GEOINT) {
144  auto elem_ty = llvm::Type::getInt32Ty(cgen_state->context_);
145  arr_type = llvm::ArrayType::get(elem_ty, 2);
146  } else {
147  CHECK(geo_ti.get_compression() == kENCODING_NONE);
148  auto elem_ty = llvm::Type::getDoubleTy(cgen_state->context_);
149  arr_type = llvm::ArrayType::get(elem_ty, 2);
150  }
152  builder.CreateAlloca(arr_type, nullptr, operator_->getName() + "_Local_Storage");
153 
154  return std::make_tuple(arg_lvs, is_null);
155  }
156 
157  std::vector<llvm::Value*> codegen(const std::vector<llvm::Value*>& args,
158  CodeGenerator::NullCheckCodegen* nullcheck_codegen,
159  CgenState* cgen_state,
160  const CompilationOptions& co) final {
161  CHECK_EQ(args.size(), size_t(2));
162 
163  const auto& geo_ti = operator_->get_type_info();
164  CHECK(geo_ti.get_type() == kPOINT);
165 
166  auto& builder = cgen_state->ir_builder_;
168 
169  const bool is_compressed = geo_ti.get_compression() == kENCODING_GEOINT;
170 
171  // store x coord
172  auto x_coord_ptr = builder.CreateGEP(
173  pt_local_storage_lv_->getType()->getScalarType()->getPointerElementType(),
175  {cgen_state->llInt(0), cgen_state->llInt(0)},
176  "x_coord_ptr");
177  if (is_compressed) {
178  auto compressed_lv =
179  cgen_state->emitExternalCall("compress_x_coord_geoint",
180  llvm::Type::getInt32Ty(cgen_state->context_),
181  {args.front()});
182  builder.CreateStore(compressed_lv, x_coord_ptr);
183  } else {
184  builder.CreateStore(args.front(), x_coord_ptr);
185  }
186 
187  // store y coord
188  auto y_coord_ptr = builder.CreateGEP(
189  pt_local_storage_lv_->getType()->getScalarType()->getPointerElementType(),
191  {cgen_state->llInt(0), cgen_state->llInt(1)},
192  "y_coord_ptr");
193  if (is_compressed) {
194  auto compressed_lv =
195  cgen_state->emitExternalCall("compress_y_coord_geoint",
196  llvm::Type::getInt32Ty(cgen_state->context_),
197  {args.back()});
198  builder.CreateStore(compressed_lv, y_coord_ptr);
199  } else {
200  builder.CreateStore(args.back(), y_coord_ptr);
201  }
202 
203  llvm::Value* ret = pt_local_storage_lv_;
204  if (is_nullable_) {
205  CHECK(nullcheck_codegen);
206  ret = nullcheck_codegen->finalize(ret, ret);
207  }
208  return {builder.CreateBitCast(ret,
209  geo_ti.get_compression() == kENCODING_GEOINT
210  ? llvm::Type::getInt32PtrTy(cgen_state->context_)
211  : llvm::Type::getDoublePtrTy(cgen_state->context_)),
212  cgen_state->llInt(static_cast<int32_t>(
213  geo_ti.get_compression() == kENCODING_GEOINT ? 8 : 16))};
214  }
215 
216  private:
217  llvm::AllocaInst* pt_local_storage_lv_{nullptr};
218 };
219 
220 } // namespace spatial_type
std::vector< llvm::Value * > codegen(const std::vector< llvm::Value * > &args, CodeGenerator::NullCheckCodegen *nullcheck_codegen, CgenState *cgen_state, const CompilationOptions &co) final
#define CHECK_EQ(x, y)
Definition: Logger.h:219
class for a per-database catalog. also includes metadata for the current database and the current use...
Definition: Catalog.h:114
SQLTypeInfo getNullType() const final
#define const
PointConstructor(const Analyzer::GeoOperator *geo_operator, const Catalog_Namespace::Catalog *catalog)
double inline_fp_null_val(const SQL_TYPE_INFO &ti)
CONSTEXPR DEVICE bool is_null(const T &value)
const std::string & getName() const
Definition: Analyzer.h:1925
auto isNullable() const
Definition: Codegen.h:35
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:77
std::tuple< std::vector< llvm::Value * >, llvm::Value * > codegenLoads(const std::vector< llvm::Value * > &arg_lvs, const std::vector< llvm::Value * > &pos_lvs, CgenState *cgen_state) final
llvm::AllocaInst * pt_local_storage_lv_
const Analyzer::GeoOperator * operator_
Definition: Codegen.h:70
size_t size() const
Definition: Analyzer.cpp:3644
#define NULL_ARRAY_DOUBLE
#define CHECK(condition)
Definition: Logger.h:211
virtual const Analyzer::Expr * getOperand(const size_t index)
Definition: Codegen.cpp:63
int64_t inline_int_null_val(const SQL_TYPE_INFO &ti)
std::string getName() const
Definition: Codegen.h:39
std::unique_ptr< CodeGenerator::NullCheckCodegen > getNullCheckCodegen(llvm::Value *null_lv, CgenState *cgen_state, Executor *executor) final
Definition: sqltypes.h:45