OmniSciDB  6686921089
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
PointN.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 namespace spatial_type {
22 
23 class PointN : public Codegen {
24  public:
25  PointN(const Analyzer::GeoOperator* geo_operator,
26  const Catalog_Namespace::Catalog* catalog)
27  : Codegen(geo_operator, catalog) {
28  CHECK_EQ(operator_->size(), size_t(2));
29  // set is nullable to true, because an index outside of the linestring will return
30  // null
31  // note we could probably just set this based on the operator type, as the operator
32  // type needs to match
33  this->is_nullable_ = true;
34  }
35 
36  std::unique_ptr<CodeGenerator::NullCheckCodegen> getNullCheckCodegen(
37  llvm::Value* null_lv,
38  CgenState* cgen_state,
39  Executor* executor) final {
40  if (isNullable()) {
41  CHECK(null_lv);
42  return std::make_unique<CodeGenerator::NullCheckCodegen>(
43  cgen_state, executor, null_lv, getNullType(), getName() + "_nullcheck");
44  } else {
45  return nullptr;
46  }
47  }
48 
49  size_t size() const final { return 2; }
50 
52  // nullability is the expression `linestring is null OR size within bounds`
53  return SQLTypeInfo(kBOOLEAN);
54  }
55 
56  // returns arguments lvs and null lv
57  std::tuple<std::vector<llvm::Value*>, llvm::Value*> codegenLoads(
58  const std::vector<llvm::Value*>& arg_lvs,
59  const std::vector<llvm::Value*>& pos_lvs,
60  CgenState* cgen_state) final {
61  CHECK_EQ(pos_lvs.size(), size());
62  CHECK_EQ(pos_lvs.front(), pos_lvs.back());
63  auto operand = getOperand(0);
64  CHECK(operand);
65  const auto& geo_ti = operand->get_type_info();
66  CHECK(geo_ti.get_type() == kLINESTRING);
67 
68  auto& builder = cgen_state->ir_builder_;
69 
70  std::vector<llvm::Value*> array_operand_lvs;
71  CHECK(!arg_lvs.empty());
72  auto index_lv = builder.CreateMul(
73  builder.CreateSub(arg_lvs.back(), cgen_state->llInt(static_cast<int32_t>(1))),
74  cgen_state->llInt(static_cast<int32_t>(2)));
75  llvm::Value* is_null_lv{nullptr};
76  if (arg_lvs.size() == 2) {
77  // col byte stream from column on disk
78  array_operand_lvs.push_back(
79  cgen_state->emitExternalCall("array_buff",
80  llvm::Type::getInt8PtrTy(cgen_state->context_),
81  {arg_lvs.front(), pos_lvs.front()}));
82  const bool is_nullable = !geo_ti.get_notnull();
83  std::string size_fn_name = "array_size";
84  if (is_nullable) {
85  size_fn_name += "_nullable";
86  }
87 
88  uint32_t elem_sz = 1; // TINYINT coords array
89  std::vector<llvm::Value*> array_sz_args{
90  arg_lvs.front(), pos_lvs.front(), cgen_state->llInt(log2_bytes(elem_sz))};
91  if (is_nullable) {
92  array_sz_args.push_back(
93  cgen_state->llInt(static_cast<int32_t>(inline_int_null_value<int32_t>())));
94  }
95  array_operand_lvs.push_back(cgen_state->emitExternalCall(
96  size_fn_name, get_int_type(32, cgen_state->context_), array_sz_args));
97 
98  auto geo_size_lv = array_operand_lvs.back();
99  // convert the index to a byte index
100  const auto outside_linestring_bounds_lv = builder.CreateNot(builder.CreateICmp(
101  llvm::ICmpInst::ICMP_SLT,
102  builder.CreateMul(index_lv, cgen_state->llInt(static_cast<int32_t>(8))),
103  geo_size_lv));
104  outside_linestring_bounds_lv->setName("outside_linestring_bounds");
105  const auto input_is_null_lv = builder.CreateICmp(
106  llvm::ICmpInst::ICMP_EQ,
107  geo_size_lv,
108  cgen_state->llInt(static_cast<int32_t>(inline_int_null_value<int32_t>())));
109  input_is_null_lv->setName("input_is_null");
110  is_null_lv = builder.CreateOr(outside_linestring_bounds_lv, input_is_null_lv);
111  } else {
112  CHECK_EQ(arg_lvs.size(), size_t(3)); // ptr, size, index
113  array_operand_lvs.push_back(arg_lvs[0]);
114  array_operand_lvs.push_back(arg_lvs[1]);
115 
116  const auto geo_size_lv = arg_lvs[1];
117  // TODO: bounds indices are 64 bits but should be 32 bits, as array length is
118  // limited to 32 bits
119  is_null_lv = builder.CreateNot(
120  builder.CreateICmp(llvm::ICmpInst::ICMP_SLT, index_lv, geo_size_lv));
121  }
122  array_operand_lvs.push_back(index_lv);
123  return std::make_tuple(array_operand_lvs, is_null_lv);
124  }
125 
126  std::vector<llvm::Value*> codegen(const std::vector<llvm::Value*>& args,
127  CodeGenerator::NullCheckCodegen* nullcheck_codegen,
128  CgenState* cgen_state,
129  const CompilationOptions& co) final {
130  CHECK_EQ(args.size(), size_t(3)); // ptr, size, index
131  const auto& geo_ti = getOperand(0)->get_type_info();
132  CHECK(geo_ti.is_geometry());
133 
134  llvm::Value* array_buff_cast{nullptr};
135 
136  auto& builder = cgen_state->ir_builder_;
137  if (geo_ti.get_compression() == kENCODING_GEOINT) {
138  array_buff_cast = builder.CreateBitCast(
139  args.front(), llvm::Type::getInt32PtrTy(cgen_state->context_));
140  } else {
141  array_buff_cast = builder.CreateBitCast(
142  args.front(), llvm::Type::getDoublePtrTy(cgen_state->context_));
143  }
144 
145  const auto index_lv = args.back();
146  auto array_offset_lv =
147  builder.CreateGEP(array_buff_cast, index_lv, operator_->getName() + "_Offset");
148  CHECK(nullcheck_codegen);
149  auto ret_lv = nullcheck_codegen->finalize(
150  llvm::ConstantPointerNull::get(
151  geo_ti.get_compression() == kENCODING_GEOINT
152  ? llvm::PointerType::get(llvm::Type::getInt32Ty(cgen_state->context_), 0)
153  : llvm::PointerType::get(llvm::Type::getDoubleTy(cgen_state->context_),
154  0)),
155  array_offset_lv);
156  const auto geo_size_lv = args[1];
157  return {ret_lv, geo_size_lv};
158  }
159 };
160 
161 } // namespace spatial_type
#define CHECK_EQ(x, y)
Definition: Logger.h:217
class for a per-database catalog. also includes metadata for the current database and the current use...
Definition: Catalog.h:111
std::unique_ptr< CodeGenerator::NullCheckCodegen > getNullCheckCodegen(llvm::Value *null_lv, CgenState *cgen_state, Executor *executor) final
Definition: PointN.h:36
#define const
llvm::Type * get_int_type(const int width, llvm::LLVMContext &context)
SQLTypeInfo getNullType() const final
Definition: PointN.h:51
std::vector< llvm::Value * > codegen(const std::vector< llvm::Value * > &args, CodeGenerator::NullCheckCodegen *nullcheck_codegen, CgenState *cgen_state, const CompilationOptions &co) final
Definition: PointN.h:126
auto isNullable() const
Definition: Codegen.h:35
PointN(const Analyzer::GeoOperator *geo_operator, const Catalog_Namespace::Catalog *catalog)
Definition: PointN.h:25
const Analyzer::GeoOperator * operator_
Definition: Codegen.h:70
size_t size() const
Definition: Analyzer.cpp:3640
size_t size() const final
Definition: PointN.h:49
#define CHECK(condition)
Definition: Logger.h:209
virtual const Analyzer::Expr * getOperand(const size_t index)
Definition: Codegen.cpp:63
std::string getName() const
Definition: Codegen.h:39
uint32_t log2_bytes(const uint32_t bytes)
Definition: Execute.h:174
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
Definition: PointN.h:57