OmniSciDB  04ee39c94c
ExtensionsIR.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 #include "ExtensionFunctions.hpp"
22 
23 namespace {
24 
25 llvm::Type* ext_arg_type_to_llvm_type(const ExtArgumentType ext_arg_type,
26  llvm::LLVMContext& ctx) {
27  switch (ext_arg_type) {
28  case ExtArgumentType::Bool: // pass thru to Int8
30  return get_int_type(8, ctx);
32  return get_int_type(16, ctx);
34  return get_int_type(32, ctx);
36  return get_int_type(64, ctx);
38  return llvm::Type::getFloatTy(ctx);
40  return llvm::Type::getDoubleTy(ctx);
41  default:
42  CHECK(false);
43  }
44  CHECK(false);
45  return nullptr;
46 }
47 
48 inline SQLTypeInfo get_sql_type_from_llvm_type(const llvm::Type* ll_type) {
49  CHECK(ll_type);
50  const auto bits = ll_type->getPrimitiveSizeInBits();
51 
52  if (ll_type->isFloatingPointTy()) {
53  switch (bits) {
54  case 32:
55  return SQLTypeInfo(kFLOAT, true);
56  case 64:
57  return SQLTypeInfo(kDOUBLE, true);
58  default:
59  LOG(FATAL) << "Unsupported llvm floating point type: " << bits
60  << ", only 32 and 64 bit floating point is supported.";
61  }
62  } else {
63  switch (bits) {
64  case 1:
65  return SQLTypeInfo(kBOOLEAN, true);
66  case 8:
67  return SQLTypeInfo(kTINYINT, true);
68  case 16:
69  return SQLTypeInfo(kSMALLINT, true);
70  case 32:
71  return SQLTypeInfo(kINT, true);
72  case 64:
73  return SQLTypeInfo(kBIGINT, true);
74  default:
75  LOG(FATAL) << "Unrecognized llvm type for SQL type: "
76  << bits; // TODO let's get the real name here
77  }
78  }
79  UNREACHABLE();
80  return SQLTypeInfo();
81 }
82 
84  for (size_t i = 0; i < function_oper->getArity(); ++i) {
85  const auto arg = function_oper->getArg(i);
86  const auto& arg_ti = arg->get_type_info();
87  if (!arg_ti.get_notnull() && !arg_ti.is_array() && !arg_ti.is_geometry()) {
88  return true;
89  }
90  }
91  return false;
92 }
93 
94 } // namespace
95 
96 #include "../Shared/sql_type_to_string.h"
97 
98 extern "C" void register_buffer_with_executor_rsm(int64_t exec, int8_t* buffer) {
99  Executor* exec_ptr = reinterpret_cast<Executor*>(exec);
100  if (buffer != nullptr) {
101  exec_ptr->getRowSetMemoryOwner()->addVarlenBuffer(buffer);
102  }
103 }
104 
106  const Analyzer::FunctionOper* function_oper,
107  const CompilationOptions& co) {
108  auto ext_func_sig = bind_function(function_oper);
109 
110  const auto& ret_ti = function_oper->get_type_info();
111  CHECK(ret_ti.is_integer() || ret_ti.is_fp() || ret_ti.is_boolean());
112  const auto ret_ty =
113  ext_arg_type_to_llvm_type(ext_func_sig.getRet(), cgen_state_->context_);
114  const auto current_bb = cgen_state_->ir_builder_.GetInsertBlock();
115  for (auto it : cgen_state_->ext_call_cache_) {
116  if (*it.foper == *function_oper) {
117  auto inst = llvm::dyn_cast<llvm::Instruction>(it.lv);
118  if (inst && inst->getParent() == current_bb) {
119  return it.lv;
120  }
121  }
122  }
123  std::vector<llvm::Value*> orig_arg_lvs;
124  std::unordered_map<llvm::Value*, llvm::Value*> const_arr_size;
125  for (size_t i = 0; i < function_oper->getArity(); ++i) {
126  const auto arg = function_oper->getArg(i);
127  const auto arg_cast = dynamic_cast<const Analyzer::UOper*>(arg);
128  const auto arg0 =
129  (arg_cast && arg_cast->get_optype() == kCAST) ? arg_cast->get_operand() : arg;
130  const auto array_expr_arg = dynamic_cast<const Analyzer::ArrayExpr*>(arg0);
131  auto is_local_alloc = (array_expr_arg && array_expr_arg->isLocalAlloc());
132  const auto& arg_ti = arg->get_type_info();
133  const auto arg_lvs = codegen(arg, true, co);
134  // TODO(adb / d): Assuming no const array cols for geo (for now)
135  if (arg_ti.is_geometry()) {
136  CHECK_EQ(static_cast<size_t>(arg_ti.get_physical_coord_cols()), arg_lvs.size());
137  for (size_t i = 0; i < arg_lvs.size(); i++) {
138  orig_arg_lvs.push_back(arg_lvs[i]);
139  }
140  } else {
141  if (arg_lvs.size() > 1) {
142  CHECK(arg_ti.is_array());
143  CHECK_EQ(size_t(2), arg_lvs.size());
144  const_arr_size[arg_lvs.front()] = arg_lvs.back();
145  } else {
146  CHECK_EQ(size_t(1), arg_lvs.size());
147  if (is_local_alloc && arg_ti.get_size() > 0) {
148  const_arr_size[arg_lvs.front()] = cgen_state_->llInt(arg_ti.get_size());
149  }
150  }
151  orig_arg_lvs.push_back(arg_lvs.front());
152  }
153  }
154  // The extension function implementations don't handle NULL, they work under
155  // the assumption that the inputs are validated before calling them. Generate
156  // code to do the check at the call site: if any argument is NULL, return NULL
157  // without calling the function at all.
158  const auto bbs = beginArgsNullcheck(function_oper, orig_arg_lvs);
159  CHECK_GE(orig_arg_lvs.size(), function_oper->getArity());
160  // Arguments must be converted to the types the extension function can handle.
161  const auto args = codegenFunctionOperCastArgs(
162  function_oper, &ext_func_sig, orig_arg_lvs, const_arr_size, co);
163  auto ext_call = cgen_state_->emitExternalCall(ext_func_sig.getName(), ret_ty, args);
164  // Cast the return of the extension function to match the FunctionOper
165  const auto extension_ret_ti = get_sql_type_from_llvm_type(ret_ty);
166  if (bbs.args_null_bb &&
167  extension_ret_ti.get_type() != function_oper->get_type_info().get_type()) {
168  ext_call = codegenCast(
169  ext_call, extension_ret_ti, function_oper->get_type_info(), false, co);
170  }
171 
172  auto ext_call_nullcheck = endArgsNullcheck(bbs, ext_call, function_oper);
173  cgen_state_->ext_call_cache_.push_back({function_oper, ext_call_nullcheck});
174  return ext_call_nullcheck;
175 }
176 
177 // Start the control flow needed for a call site check of NULL arguments.
179  const Analyzer::FunctionOper* function_oper,
180  const std::vector<llvm::Value*>& orig_arg_lvs) {
181  llvm::BasicBlock* args_null_bb{nullptr};
182  llvm::BasicBlock* args_notnull_bb{nullptr};
183  llvm::BasicBlock* orig_bb = cgen_state_->ir_builder_.GetInsertBlock();
184  // Only generate the check if required (at least one argument must be nullable).
185  if (ext_func_call_requires_nullcheck(function_oper)) {
186  const auto args_notnull_lv = cgen_state_->ir_builder_.CreateNot(
187  codegenFunctionOperNullArg(function_oper, orig_arg_lvs));
188  args_notnull_bb = llvm::BasicBlock::Create(
189  cgen_state_->context_, "args_notnull", cgen_state_->row_func_);
190  args_null_bb = llvm::BasicBlock::Create(
191  cgen_state_->context_, "args_null", cgen_state_->row_func_);
192  cgen_state_->ir_builder_.CreateCondBr(args_notnull_lv, args_notnull_bb, args_null_bb);
193  cgen_state_->ir_builder_.SetInsertPoint(args_notnull_bb);
194  }
195  return {args_null_bb, args_notnull_bb, orig_bb};
196 }
197 
198 // Wrap up the control flow needed for NULL argument handling.
200  const ArgNullcheckBBs& bbs,
201  llvm::Value* fn_ret_lv,
202  const Analyzer::FunctionOper* function_oper) {
203  if (bbs.args_null_bb) {
204  CHECK(bbs.args_notnull_bb);
205  cgen_state_->ir_builder_.CreateBr(bbs.args_null_bb);
206  cgen_state_->ir_builder_.SetInsertPoint(bbs.args_null_bb);
207 
208  // The return type of the FunctionOper. The extension function call will be cast to
209  // this type if required.
210  const auto& func_oper_ret_ti = function_oper->get_type_info();
211 
212  auto ext_call_phi = cgen_state_->ir_builder_.CreatePHI(
213  func_oper_ret_ti.is_fp()
214  ? get_fp_type(func_oper_ret_ti.get_size() * 8, cgen_state_->context_)
215  : get_int_type(func_oper_ret_ti.get_size() * 8, cgen_state_->context_),
216  2);
217 
218  ext_call_phi->addIncoming(fn_ret_lv, bbs.args_notnull_bb);
219 
220  const auto null_lv =
221  func_oper_ret_ti.is_fp()
222  ? static_cast<llvm::Value*>(cgen_state_->inlineFpNull(func_oper_ret_ti))
223  : static_cast<llvm::Value*>(cgen_state_->inlineIntNull(func_oper_ret_ti));
224  ext_call_phi->addIncoming(null_lv, bbs.orig_bb);
225  return ext_call_phi;
226  }
227  return fn_ret_lv;
228 }
229 
230 namespace {
231 
233  const auto& ret_ti = function_oper->get_type_info();
234  if (!ret_ti.is_integer() && !ret_ti.is_fp()) {
235  return true;
236  }
237  for (size_t i = 0; i < function_oper->getArity(); ++i) {
238  const auto arg = function_oper->getArg(i);
239  const auto& arg_ti = arg->get_type_info();
240  if (!arg_ti.is_integer() && !arg_ti.is_fp()) {
241  return true;
242  }
243  }
244  return false;
245 }
246 
247 } // namespace
248 
251  const CompilationOptions& co) {
252  if (call_requires_custom_type_handling(function_oper)) {
253  // Some functions need the return type to be the same as the input type.
254  if (function_oper->getName() == "FLOOR" || function_oper->getName() == "CEIL") {
255  CHECK_EQ(size_t(1), function_oper->getArity());
256  const auto arg = function_oper->getArg(0);
257  const auto& arg_ti = arg->get_type_info();
258  CHECK(arg_ti.is_decimal());
259  const auto arg_lvs = codegen(arg, true, co);
260  CHECK_EQ(size_t(1), arg_lvs.size());
261  const auto arg_lv = arg_lvs.front();
262  CHECK(arg_lv->getType()->isIntegerTy(64));
263  const auto bbs = beginArgsNullcheck(function_oper, {arg_lvs});
264  const std::string func_name =
265  (function_oper->getName() == "FLOOR") ? "decimal_floor" : "decimal_ceil";
266  const auto covar_result_lv = cgen_state_->emitCall(
267  func_name, {arg_lv, cgen_state_->llInt(exp_to_scale(arg_ti.get_scale()))});
268  const auto ret_ti = function_oper->get_type_info();
269  CHECK(ret_ti.is_decimal());
270  CHECK_EQ(0, ret_ti.get_scale());
271  const auto result_lv = cgen_state_->ir_builder_.CreateSDiv(
272  covar_result_lv, cgen_state_->llInt(exp_to_scale(arg_ti.get_scale())));
273  return endArgsNullcheck(bbs, result_lv, function_oper);
274  } else if (function_oper->getName() == "ROUND" &&
275  function_oper->getArg(0)->get_type_info().is_decimal()) {
276  CHECK_EQ(size_t(2), function_oper->getArity());
277 
278  const auto arg0 = function_oper->getArg(0);
279  const auto& arg0_ti = arg0->get_type_info();
280  const auto arg0_lvs = codegen(arg0, true, co);
281  CHECK_EQ(size_t(1), arg0_lvs.size());
282  const auto arg0_lv = arg0_lvs.front();
283  CHECK(arg0_lv->getType()->isIntegerTy(64));
284 
285  const auto arg1 = function_oper->getArg(1);
286  const auto& arg1_ti = arg1->get_type_info();
287  CHECK(arg1_ti.is_integer());
288  const auto arg1_lvs = codegen(arg1, true, co);
289  auto arg1_lv = arg1_lvs.front();
290  if (arg1_ti.get_type() != kINT) {
291  arg1_lv = codegenCast(arg1_lv, arg1_ti, SQLTypeInfo(kINT, true), false, co);
292  }
293 
294  const auto bbs0 = beginArgsNullcheck(function_oper, {arg0_lv, arg1_lvs.front()});
295 
296  const std::string func_name = "Round__4";
297  const auto ret_ti = function_oper->get_type_info();
298  CHECK(ret_ti.is_decimal());
299  const auto result_lv = cgen_state_->emitExternalCall(
300  func_name,
302  {arg0_lv, arg1_lv, cgen_state_->llInt(arg0_ti.get_scale())});
303 
304  return endArgsNullcheck(bbs0, result_lv, function_oper);
305  }
306  throw std::runtime_error("Type combination not supported for function " +
307  function_oper->getName());
308  }
309  return codegenFunctionOper(function_oper, co);
310 }
311 
312 // Generates code which returns true iff at least one of the arguments is NULL.
314  const Analyzer::FunctionOper* function_oper,
315  const std::vector<llvm::Value*>& orig_arg_lvs) {
316  llvm::Value* one_arg_null =
317  llvm::ConstantInt::get(llvm::IntegerType::getInt1Ty(cgen_state_->context_), false);
318  for (size_t i = 0; i < function_oper->getArity(); ++i) {
319  const auto arg = function_oper->getArg(i);
320  const auto& arg_ti = arg->get_type_info();
321  if (arg_ti.get_notnull() || arg_ti.is_array() || arg_ti.is_geometry()) {
322  continue;
323  }
324  CHECK(arg_ti.is_number());
325  one_arg_null = cgen_state_->ir_builder_.CreateOr(
326  one_arg_null, codegenIsNullNumber(orig_arg_lvs[i], arg_ti));
327  }
328  return one_arg_null;
329 }
330 
331 // Generate CAST operations for arguments in `orig_arg_lvs` to the types required by
332 // `ext_func_sig`.
334  const Analyzer::FunctionOper* function_oper,
335  const ExtensionFunction* ext_func_sig,
336  const std::vector<llvm::Value*>& orig_arg_lvs,
337  const std::unordered_map<llvm::Value*, llvm::Value*>& const_arr_size,
338  const CompilationOptions& co) {
339  CHECK(ext_func_sig);
340  const auto& ext_func_args = ext_func_sig->getArgs();
341  CHECK_LE(function_oper->getArity(), ext_func_args.size());
342  std::vector<llvm::Value*> args;
343  // i: argument in RA for the function op
344  // j: extra offset in orig_arg_lvs (to account for additional values required for a col,
345  // e.g. array cols) k: origin_arg_lvs counter
346  for (size_t i = 0, j = 0, k = 0; i < function_oper->getArity(); ++i, ++k) {
347  const auto arg = function_oper->getArg(i);
348  const auto& arg_ti = arg->get_type_info();
349  llvm::Value* arg_lv{nullptr};
350  if (arg_ti.is_array()) {
351  bool const_arr = (const_arr_size.count(orig_arg_lvs[k]) > 0);
352  const auto elem_ti = arg_ti.get_elem_type();
353  // TODO: switch to fast fixlen variants
354  const auto ptr_lv = (const_arr)
355  ? orig_arg_lvs[k]
357  "array_buff",
358  llvm::Type::getInt8PtrTy(cgen_state_->context_),
359  {orig_arg_lvs[k], posArg(arg)});
360  const auto len_lv =
361  (const_arr) ? const_arr_size.at(orig_arg_lvs[k])
363  "array_size",
365  {orig_arg_lvs[k],
366  posArg(arg),
367  cgen_state_->llInt(log2_bytes(elem_ti.get_logical_size()))});
368  args.push_back(castArrayPointer(ptr_lv, elem_ti));
369  args.push_back(cgen_state_->ir_builder_.CreateZExt(
370  len_lv, get_int_type(64, cgen_state_->context_)));
371  j++;
372  } else if (arg_ti.is_geometry()) {
373  // Coords
374  bool const_arr = (const_arr_size.count(orig_arg_lvs[k]) > 0);
375  // NOTE(adb): We're generating code to handle the TINYINT array only -- the actual
376  // geo encoding (or lack thereof) does not matter here
377  const auto elem_ti = SQLTypeInfo(SQLTypes::kARRAY,
378  0,
379  0,
380  false,
382  0,
384  .get_elem_type();
385  llvm::Value* ptr_lv;
386  llvm::Value* len_lv;
387  int32_t fixlen = -1;
388  if (arg_ti.get_type() == kPOINT) {
389  const auto col_var = dynamic_cast<const Analyzer::ColumnVar*>(arg);
390  if (col_var) {
391  const auto coords_cd = executor()->getPhysicalColumnDescriptor(col_var, 1);
392  if (coords_cd && coords_cd->columnType.get_type() == kARRAY) {
393  fixlen = coords_cd->columnType.get_size();
394  }
395  }
396  }
397  if (fixlen > 0) {
398  ptr_lv =
399  cgen_state_->emitExternalCall("fast_fixlen_array_buff",
400  llvm::Type::getInt8PtrTy(cgen_state_->context_),
401  {orig_arg_lvs[k], posArg(arg)});
402  len_lv = cgen_state_->llInt(int64_t(fixlen));
403  } else {
404  // TODO: remove const_arr and related code if it's not needed
405  ptr_lv = (const_arr) ? orig_arg_lvs[k]
407  "array_buff",
408  llvm::Type::getInt8PtrTy(cgen_state_->context_),
409  {orig_arg_lvs[k], posArg(arg)});
410  len_lv = (const_arr)
411  ? const_arr_size.at(orig_arg_lvs[k])
413  "array_size",
415  {orig_arg_lvs[k],
416  posArg(arg),
417  cgen_state_->llInt(log2_bytes(elem_ti.get_logical_size()))});
418  }
419  args.push_back(castArrayPointer(ptr_lv, elem_ti));
420  args.push_back(cgen_state_->ir_builder_.CreateZExt(
421  len_lv, get_int_type(64, cgen_state_->context_)));
422  j++;
423  switch (arg_ti.get_type()) {
424  case kPOINT:
425  case kLINESTRING:
426  break;
427  case kPOLYGON: {
428  k++;
429  // Ring Sizes
430  const auto elem_ti = SQLTypeInfo(SQLTypes::kARRAY,
431  0,
432  0,
433  false,
435  0,
437  .get_elem_type();
438  const auto ptr_lv = cgen_state_->emitExternalCall(
439  "array_buff",
440  llvm::Type::getInt32PtrTy(cgen_state_->context_),
441  {orig_arg_lvs[k], posArg(arg)});
442  const auto len_lv = cgen_state_->emitExternalCall(
443  "array_size",
445  {orig_arg_lvs[k],
446  posArg(arg),
447  cgen_state_->llInt(log2_bytes(elem_ti.get_logical_size()))});
448  args.push_back(castArrayPointer(ptr_lv, elem_ti));
449  args.push_back(cgen_state_->ir_builder_.CreateZExt(
450  len_lv, get_int_type(64, cgen_state_->context_)));
451  j++;
452  break;
453  }
454  case kMULTIPOLYGON: {
455  k++;
456  // Ring Sizes
457  {
458  const auto elem_ti = SQLTypeInfo(SQLTypes::kARRAY,
459  0,
460  0,
461  false,
463  0,
465  .get_elem_type();
466  const auto ptr_lv = cgen_state_->emitExternalCall(
467  "array_buff",
468  llvm::Type::getInt32PtrTy(cgen_state_->context_),
469  {orig_arg_lvs[k], posArg(arg)});
470  const auto len_lv = cgen_state_->emitExternalCall(
471  "array_size",
473  {orig_arg_lvs[k],
474  posArg(arg),
475  cgen_state_->llInt(log2_bytes(elem_ti.get_logical_size()))});
476  args.push_back(castArrayPointer(ptr_lv, elem_ti));
477  args.push_back(cgen_state_->ir_builder_.CreateZExt(
478  len_lv, get_int_type(64, cgen_state_->context_)));
479  }
480  j++, k++;
481 
482  // Poly Rings
483  {
484  const auto elem_ti = SQLTypeInfo(SQLTypes::kARRAY,
485  0,
486  0,
487  false,
489  0,
491  .get_elem_type();
492  const auto ptr_lv = cgen_state_->emitExternalCall(
493  "array_buff",
494  llvm::Type::getInt32PtrTy(cgen_state_->context_),
495  {orig_arg_lvs[k], posArg(arg)});
496  const auto len_lv = cgen_state_->emitExternalCall(
497  "array_size",
499  {orig_arg_lvs[k],
500  posArg(arg),
501  cgen_state_->llInt(log2_bytes(elem_ti.get_logical_size()))});
502  args.push_back(castArrayPointer(ptr_lv, elem_ti));
503  args.push_back(cgen_state_->ir_builder_.CreateZExt(
504  len_lv, get_int_type(64, cgen_state_->context_)));
505  }
506  j++;
507  break;
508  }
509  default:
510  CHECK(false);
511  }
512  } else {
513  const auto arg_target_ti = ext_arg_type_to_type_info(ext_func_args[k + j]);
514  if (arg_ti.get_type() != arg_target_ti.get_type()) {
515  arg_lv = codegenCast(orig_arg_lvs[k], arg_ti, arg_target_ti, false, co);
516  } else {
517  arg_lv = orig_arg_lvs[k];
518  }
519  CHECK_EQ(arg_lv->getType(),
520  ext_arg_type_to_llvm_type(ext_func_args[k + j], cgen_state_->context_));
521  args.push_back(arg_lv);
522  }
523  }
524  return args;
525 }
526 
527 llvm::Value* CodeGenerator::castArrayPointer(llvm::Value* ptr,
528  const SQLTypeInfo& elem_ti) {
529  if (elem_ti.get_type() == kFLOAT) {
530  return cgen_state_->ir_builder_.CreatePointerCast(
531  ptr, llvm::Type::getFloatPtrTy(cgen_state_->context_));
532  }
533  if (elem_ti.get_type() == kDOUBLE) {
534  return cgen_state_->ir_builder_.CreatePointerCast(
535  ptr, llvm::Type::getDoublePtrTy(cgen_state_->context_));
536  }
537  CHECK(elem_ti.is_integer() ||
538  (elem_ti.is_string() && elem_ti.get_compression() == kENCODING_DICT));
539  switch (elem_ti.get_size()) {
540  case 1:
541  return cgen_state_->ir_builder_.CreatePointerCast(
542  ptr, llvm::Type::getInt8PtrTy(cgen_state_->context_));
543  case 2:
544  return cgen_state_->ir_builder_.CreatePointerCast(
545  ptr, llvm::Type::getInt16PtrTy(cgen_state_->context_));
546  case 4:
547  return cgen_state_->ir_builder_.CreatePointerCast(
548  ptr, llvm::Type::getInt32PtrTy(cgen_state_->context_));
549  case 8:
550  return cgen_state_->ir_builder_.CreatePointerCast(
551  ptr, llvm::Type::getInt64PtrTy(cgen_state_->context_));
552  default:
553  CHECK(false);
554  }
555  return nullptr;
556 }
#define CHECK_EQ(x, y)
Definition: Logger.h:195
HOST DEVICE int get_size() const
Definition: sqltypes.h:333
llvm::BasicBlock * args_notnull_bb
std::string getName() const
Definition: Analyzer.h:1250
CgenState * cgen_state_
const Analyzer::Expr * getArg(const size_t i) const
Definition: Analyzer.h:1254
Executor * executor() const
#define LOG(tag)
Definition: Logger.h:182
ExtensionFunction bind_function(std::string name, Analyzer::ExpressionPtrVector func_args, const std::vector< ExtensionFunction > &ext_funcs)
llvm::IRBuilder ir_builder_
Definition: CgenState.h:268
llvm::Value * codegenFunctionOperNullArg(const Analyzer::FunctionOper *, const std::vector< llvm::Value *> &)
HOST DEVICE SQLTypes get_type() const
Definition: sqltypes.h:323
llvm::Value * castArrayPointer(llvm::Value *ptr, const SQLTypeInfo &elem_ti)
#define UNREACHABLE()
Definition: Logger.h:231
#define CHECK_GE(x, y)
Definition: Logger.h:200
std::vector< llvm::Value * > codegenFunctionOperCastArgs(const Analyzer::FunctionOper *, const ExtensionFunction *, const std::vector< llvm::Value *> &, const std::unordered_map< llvm::Value *, llvm::Value *> &, const CompilationOptions &)
Definition: sqldefs.h:49
llvm::Type * get_fp_type(const int width, llvm::LLVMContext &context)
bool call_requires_custom_type_handling(const Analyzer::FunctionOper *function_oper)
size_t getArity() const
Definition: Analyzer.h:1252
llvm::Type * get_int_type(const int width, llvm::LLVMContext &context)
bool ext_func_call_requires_nullcheck(const Analyzer::FunctionOper *function_oper)
HOST DEVICE EncodingType get_compression() const
Definition: sqltypes.h:331
SQLTypeInfo get_sql_type_from_llvm_type(const llvm::Type *ll_type)
std::vector< FunctionOperValue > ext_call_cache_
Definition: CgenState.h:274
llvm::Function * row_func_
Definition: CgenState.h:264
bool is_integer() const
Definition: sqltypes.h:452
llvm::LLVMContext & context_
Definition: CgenState.h:266
const std::vector< ExtArgumentType > & getArgs() const
bool is_decimal() const
Definition: sqltypes.h:453
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
llvm::Value * codegenFunctionOper(const Analyzer::FunctionOper *, const CompilationOptions &)
ArgNullcheckBBs beginArgsNullcheck(const Analyzer::FunctionOper *function_oper, const std::vector< llvm::Value *> &orig_arg_lvs)
SQLTypeInfoCore get_elem_type() const
Definition: sqltypes.h:632
llvm::BasicBlock * args_null_bb
llvm::Type * ext_arg_type_to_llvm_type(const ExtArgumentType ext_arg_type, llvm::LLVMContext &ctx)
SQLTypeInfoCore< ArrayContextTypeSizer, ExecutorTypePackaging, DateTimeFacilities > SQLTypeInfo
Definition: sqltypes.h:823
std::vector< llvm::Value * > codegen(const Analyzer::Expr *, const bool fetch_columns, const CompilationOptions &)
Definition: IRCodegen.cpp:25
#define CHECK_LE(x, y)
Definition: Logger.h:198
llvm::Value * emitCall(const std::string &fname, const std::vector< llvm::Value *> &args)
Definition: CgenState.cpp:134
llvm::Value * endArgsNullcheck(const ArgNullcheckBBs &, llvm::Value *, const Analyzer::FunctionOper *)
llvm::Value * codegenFunctionOperWithCustomTypeHandling(const Analyzer::FunctionOperWithCustomTypeHandling *, const CompilationOptions &)
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:77
#define CHECK(condition)
Definition: Logger.h:187
llvm::Value * codegenIsNullNumber(llvm::Value *, const SQLTypeInfo &)
Definition: LogicalIR.cpp:392
uint64_t exp_to_scale(const unsigned exp)
llvm::Value * codegenCast(const Analyzer::UOper *, const CompilationOptions &)
Definition: CastIR.cpp:20
Definition: sqltypes.h:47
void register_buffer_with_executor_rsm(int64_t exec, int8_t *buffer)
bool is_string() const
Definition: sqltypes.h:450
SQLTypeInfo ext_arg_type_to_type_info(const ExtArgumentType ext_arg_type)
llvm::ConstantInt * llInt(const T v) const
Definition: CgenState.h:247
llvm::ConstantFP * inlineFpNull(const SQLTypeInfo &)
Definition: CgenState.cpp:62
const Expr * get_operand() const
Definition: Analyzer.h:364