OmniSciDB  5ade3759e0
ArrayIR.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2017 MapD Technologies, 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 "CodeGenerator.h"
18 #include "Execute.h"
19 
21  const CompilationOptions& co) {
22  return codegen(uoper->get_operand(), true, co).front();
23 }
24 
25 llvm::Value* CodeGenerator::codegenArrayAt(const Analyzer::BinOper* array_at,
26  const CompilationOptions& co) {
27  const auto arr_expr = array_at->get_left_operand();
28  const auto idx_expr = array_at->get_right_operand();
29  const auto& idx_ti = idx_expr->get_type_info();
30  CHECK(idx_ti.is_integer());
31  auto idx_lvs = codegen(idx_expr, true, co);
32  CHECK_EQ(size_t(1), idx_lvs.size());
33  auto idx_lv = idx_lvs.front();
34  if (idx_ti.get_logical_size() < 8) {
35  idx_lv = cgen_state_->ir_builder_.CreateCast(llvm::Instruction::CastOps::SExt,
36  idx_lv,
38  }
39  const auto& array_ti = arr_expr->get_type_info();
40  CHECK(array_ti.is_array());
41  const auto& elem_ti = array_ti.get_elem_type();
42  const std::string array_at_fname{
43  elem_ti.is_fp()
44  ? "array_at_" + std::string(elem_ti.get_type() == kDOUBLE ? "double_checked"
45  : "float_checked")
46  : "array_at_int" + std::to_string(elem_ti.get_logical_size() * 8) +
47  "_t_checked"};
48  const auto ret_ty =
49  elem_ti.is_fp()
50  ? (elem_ti.get_type() == kDOUBLE
51  ? llvm::Type::getDoubleTy(cgen_state_->context_)
52  : llvm::Type::getFloatTy(cgen_state_->context_))
53  : get_int_type(elem_ti.get_logical_size() * 8, cgen_state_->context_);
54  const auto arr_lvs = codegen(arr_expr, true, co);
55  CHECK_EQ(size_t(1), arr_lvs.size());
57  array_at_fname,
58  ret_ty,
59  {arr_lvs.front(),
60  posArg(arr_expr),
61  idx_lv,
62  elem_ti.is_fp() ? static_cast<llvm::Value*>(cgen_state_->inlineFpNull(elem_ti))
63  : static_cast<llvm::Value*>(cgen_state_->inlineIntNull(elem_ti))});
64 }
65 
67  const CompilationOptions& co) {
68  const auto arr_expr = expr->get_arg();
69  const auto& array_ti = arr_expr->get_type_info();
70  CHECK(array_ti.is_array());
71  const auto& elem_ti = array_ti.get_elem_type();
72  auto arr_lv = codegen(arr_expr, true, co);
73  std::string fn_name("array_size");
74 
75  std::vector<llvm::Value*> array_size_args{
76  arr_lv.front(),
77  posArg(arr_expr),
78  cgen_state_->llInt(log2_bytes(elem_ti.get_logical_size()))};
79  const bool is_nullable{!arr_expr->get_type_info().get_notnull()};
80  if (is_nullable) {
81  fn_name += "_nullable";
82  array_size_args.push_back(cgen_state_->inlineIntNull(expr->get_type_info()));
83  }
85  fn_name, get_int_type(32, cgen_state_->context_), array_size_args);
86 }
87 
88 std::vector<llvm::Value*> CodeGenerator::codegenArrayExpr(
89  Analyzer::ArrayExpr const* array_expr,
90  CompilationOptions const& co) {
91  using ValueVector = std::vector<llvm::Value*>;
92  ValueVector argument_list;
93  auto& ir_builder(cgen_state_->ir_builder_);
94 
95  const auto& return_type = array_expr->get_type_info();
96  for (size_t i = 0; i < array_expr->getElementCount(); i++) {
97  const auto arg = array_expr->getElement(i);
98  const auto arg_lvs = codegen(arg, true, co);
99  if (arg_lvs.size() == 1) {
100  argument_list.push_back(arg_lvs.front());
101  } else {
102  throw std::runtime_error(
103  "Unexpected argument count during array[] code generation.");
104  }
105  }
106 
107  auto array_element_size_bytes =
108  return_type.get_elem_type().get_array_context_logical_size();
109  auto* array_index_type =
110  get_int_type(array_element_size_bytes * 8, cgen_state_->context_);
111  auto* array_type = get_int_array_type(
112  array_element_size_bytes * 8, array_expr->getElementCount(), cgen_state_->context_);
113 
114  llvm::Value* allocated_target_buffer;
115  if (array_expr->isLocalAlloc()) {
116  allocated_target_buffer = ir_builder.CreateAlloca(array_type);
117  } else {
119  throw QueryMustRunOnCpu();
120  }
121 
122  allocated_target_buffer =
123  cgen_state_->emitExternalCall("allocate_varlen_buffer",
124  llvm::Type::getInt8PtrTy(cgen_state_->context_),
125  {cgen_state_->llInt(array_expr->getElementCount()),
126  cgen_state_->llInt(array_element_size_bytes)});
128  "register_buffer_with_executor_rsm",
129  llvm::Type::getVoidTy(cgen_state_->context_),
130  {cgen_state_->llInt(reinterpret_cast<int64_t>(executor())),
131  allocated_target_buffer});
132  }
133  llvm::Value* casted_allocated_target_buffer =
134  ir_builder.CreatePointerCast(allocated_target_buffer, array_type->getPointerTo());
135 
136  for (size_t i = 0; i < array_expr->getElementCount(); i++) {
137  auto* element = argument_list[i];
138  auto* element_ptr =
139  ir_builder.CreateGEP(array_type,
140  casted_allocated_target_buffer,
141  {cgen_state_->llInt(0), cgen_state_->llInt(i)});
142 
144  kSMALLINT,
145  kINT,
146  kBIGINT,
147  kTIMESTAMP,
148  kDATE,
149  kTIME,
150  kNUMERIC,
151  kDECIMAL,
154  kVARCHAR,
155  kTEXT,
156  kCHAR>(return_type.get_elem_type())) {
157  auto sign_extended_element = ir_builder.CreateSExt(element, array_index_type);
158  ir_builder.CreateStore(sign_extended_element, element_ptr);
159  } else if (is_member_of_typeset<kBOOLEAN>(return_type.get_elem_type())) {
160  auto byte_casted_bit = ir_builder.CreateIntCast(element, array_index_type, true);
161  ir_builder.CreateStore(byte_casted_bit, element_ptr);
162  } else if (is_member_of_typeset<kFLOAT>(return_type.get_elem_type())) {
163  auto float_element_ptr = ir_builder.CreatePointerCast(
164  element_ptr, llvm::Type::getFloatPtrTy(cgen_state_->context_));
165  ir_builder.CreateStore(element, float_element_ptr);
166  } else if (is_member_of_typeset<kDOUBLE>(return_type.get_elem_type())) {
167  auto double_element_ptr = ir_builder.CreatePointerCast(
168  element_ptr, llvm::Type::getDoublePtrTy(cgen_state_->context_));
169  ir_builder.CreateStore(element, double_element_ptr);
170  } else {
171  throw std::runtime_error("Unsupported type used in ARRAY construction.");
172  }
173  }
174 
175  return {ir_builder.CreateGEP(
176  array_type, casted_allocated_target_buffer, cgen_state_->llInt(0)),
177  cgen_state_->llInt(array_expr->getElementCount())};
178 }
#define CHECK_EQ(x, y)
Definition: Logger.h:195
Definition: sqltypes.h:51
size_t getElementCount() const
Definition: Analyzer.h:1380
CgenState * cgen_state_
bool is_member_of_typeset(SQL_INFO_TYPE const &s)
llvm::IRBuilder ir_builder_
Definition: CgenState.h:268
bool isLocalAlloc() const
Definition: Analyzer.h:1382
llvm::Value * codegenArrayAt(const Analyzer::BinOper *, const CompilationOptions &)
Definition: ArrayIR.cpp:25
llvm::Type * get_int_type(const int width, llvm::LLVMContext &context)
const Expr * get_arg() const
Definition: Analyzer.h:743
std::string to_string(char const *&&v)
const Analyzer::Expr * getElement(const size_t i) const
Definition: Analyzer.h:1384
llvm::LLVMContext & context_
Definition: CgenState.h:266
llvm::ConstantInt * inlineIntNull(const SQLTypeInfo &)
Definition: CgenState.cpp:24
llvm::Value * emitExternalCall(const std::string &fname, llvm::Type *ret_type, const std::vector< llvm::Value *> args, const std::vector< llvm::Attribute::AttrKind > &fnattrs={})
Definition: CgenState.h:203
std::vector< llvm::Value * > codegenArrayExpr(const Analyzer::ArrayExpr *, const CompilationOptions &)
Definition: ArrayIR.cpp:88
ExecutorDeviceType device_type_
std::vector< llvm::Value * > codegen(const Analyzer::Expr *, const bool fetch_columns, const CompilationOptions &)
Definition: IRCodegen.cpp:25
Definition: sqltypes.h:54
Definition: sqltypes.h:55
Definition: sqltypes.h:43
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:77
llvm::Value * codegenUnnest(const Analyzer::UOper *, const CompilationOptions &)
Definition: ArrayIR.cpp:20
llvm::Value * posArg(const Analyzer::Expr *) const
Definition: ColumnIR.cpp:503
#define CHECK(condition)
Definition: Logger.h:187
uint32_t log2_bytes(const uint32_t bytes)
Definition: Execute.h:124
Definition: sqltypes.h:47
llvm::ArrayType * get_int_array_type(int const width, int count, llvm::LLVMContext &context)
llvm::ConstantInt * llInt(const T v) const
Definition: CgenState.h:247
const Expr * get_right_operand() const
Definition: Analyzer.h:436
llvm::ConstantFP * inlineFpNull(const SQLTypeInfo &)
Definition: CgenState.cpp:62
const Expr * get_left_operand() const
Definition: Analyzer.h:435
const Expr * get_operand() const
Definition: Analyzer.h:364