OmniSciDB  a5dc49c757
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
TableFunctionCompilationContext Class Reference

#include <TableFunctionCompilationContext.h>

+ Collaboration diagram for TableFunctionCompilationContext:

Public Member Functions

 TableFunctionCompilationContext (Executor *executor, const CompilationOptions &co)
 
 TableFunctionCompilationContext (const TableFunctionCompilationContext &)=delete
 
TableFunctionCompilationContextoperator= (const TableFunctionCompilationContext &)=delete
 
std::shared_ptr
< CompilationContext
compile (const TableFunctionExecutionUnit &exe_unit, bool emit_only_preflight_fn)
 

Private Member Functions

void generateEntryPoint (const TableFunctionExecutionUnit &exe_unit, bool emit_only_preflight_fn)
 
void generateTableFunctionCall (const TableFunctionExecutionUnit &exe_unit, const std::vector< llvm::Value * > &func_args, llvm::BasicBlock *bb_exit, llvm::Value *output_row_count_ptr, bool emit_only_preflight_fn)
 
void generateCastsForInputTypes (const TableFunctionExecutionUnit &exe_unit, const std::vector< std::pair< llvm::Value *, const SQLTypeInfo >> &columns_to_cast, llvm::Value *mgr_ptr)
 
void generateGpuKernel ()
 
bool passColumnsByValue (const TableFunctionExecutionUnit &exe_unit)
 
std::shared_ptr
< CompilationContext
finalize (bool emit_only_preflight_fn)
 

Private Attributes

llvm::Function * entry_point_func_
 
llvm::Function * kernel_func_
 
Executorexecutor_
 
const CompilationOptionsco_
 

Detailed Description

Definition at line 29 of file TableFunctionCompilationContext.h.

Constructor & Destructor Documentation

TableFunctionCompilationContext::TableFunctionCompilationContext ( Executor executor,
const CompilationOptions co 
)
inline

Definition at line 31 of file TableFunctionCompilationContext.h.

TableFunctionCompilationContext::TableFunctionCompilationContext ( const TableFunctionCompilationContext )
delete

Member Function Documentation

std::shared_ptr< CompilationContext > TableFunctionCompilationContext::compile ( const TableFunctionExecutionUnit exe_unit,
bool  emit_only_preflight_fn 
)

Definition at line 331 of file TableFunctionCompilationContext.cpp.

References CHECK, co_, DEBUG_TIMER, CompilationOptions::device_type, entry_point_func_, executor_, anonymous_namespace{TableFunctionCompilationContext.cpp}::exprsKey(), finalize(), anonymous_namespace{TableFunctionCompilationContext.cpp}::generate_entry_point(), generateEntryPoint(), generateGpuKernel(), QueryEngine::getInstance(), table_functions::TableFunction::getName(), GPU, TableFunctionExecutionUnit::input_exprs, TableFunctionExecutionUnit::table_func, TableFunctionExecutionUnit::target_exprs, and to_string().

Referenced by Executor::executeTableFunction().

333  {
334  auto timer = DEBUG_TIMER(__func__);
335 
336  // Here we assume that Executor::tf_code_accessor is cleared when a
337  // UDTF implementation is changed. TODO: Ideally, the key should
338  // contain a hash of an UDTF implementation string. This could be
339  // achieved by including the hash value to the prefix of the UDTF
340  // name, for instance.
341  CodeCacheKey key{exe_unit.table_func.getName(),
342  exprsKey(exe_unit.input_exprs),
343  exprsKey(exe_unit.target_exprs),
344  std::to_string(emit_only_preflight_fn),
346 
347  auto cached_code = QueryEngine::getInstance()->tf_code_accessor->get_or_wait(key);
348  if (cached_code) {
349  return *cached_code;
350  }
351 
352  auto cgen_state = executor_->getCgenStatePtr();
353  CHECK(cgen_state);
354  CHECK(cgen_state->module_ == nullptr);
355  cgen_state->set_module_shallow_copy(executor_->get_rt_module());
356 
358 
359  generateEntryPoint(exe_unit, emit_only_preflight_fn);
360 
362  CHECK(!emit_only_preflight_fn);
364  }
365  std::shared_ptr<CompilationContext> code;
366  try {
367  code = finalize(emit_only_preflight_fn);
368  } catch (const std::exception& e) {
369  // Erase unsuccesful key and release lock from the get_or_wait(key) call above:
370  QueryEngine::getInstance()->tf_code_accessor->erase(key);
371  throw;
372  }
373  // get_or_wait added code with nullptr to cache, here we reset the
374  // cached code with the pointer to the generated code:
375  QueryEngine::getInstance()->tf_code_accessor->reset(key, code);
376  return code;
377 }
std::string exprsKey(const std::vector< Analyzer::Expr * > &exprs)
void generateEntryPoint(const TableFunctionExecutionUnit &exe_unit, bool emit_only_preflight_fn)
std::vector< Analyzer::Expr * > input_exprs
const table_functions::TableFunction table_func
llvm::Function * generate_entry_point(const CgenState *cgen_state)
std::shared_ptr< CompilationContext > finalize(bool emit_only_preflight_fn)
std::vector< std::string > CodeCacheKey
Definition: CodeCache.h:24
std::string to_string(char const *&&v)
std::string getName(const bool drop_suffix=false, const bool lower=false) const
ExecutorDeviceType device_type
#define CHECK(condition)
Definition: Logger.h:291
#define DEBUG_TIMER(name)
Definition: Logger.h:412
static std::shared_ptr< QueryEngine > getInstance()
Definition: QueryEngine.h:89
std::vector< Analyzer::Expr * > target_exprs

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

std::shared_ptr< CompilationContext > TableFunctionCompilationContext::finalize ( bool  emit_only_preflight_fn)
private

Definition at line 744 of file TableFunctionCompilationContext.cpp.

References CHECK, co_, DEBUG_TIMER, CompilationOptions::device_type, entry_point_func_, executor_, CodeGenerator::generateNativeCPUCode(), CodeGenerator::generateNativeGPUCode(), GPU, logger::IR, kernel_func_, CodeGenerator::link_udf_module(), LOG, and serialize_llvm_object().

Referenced by compile().

745  {
746  auto timer = DEBUG_TIMER(__func__);
747  /*
748  TODO 1: eliminate need for OverrideFromSrc
749  TODO 2: detect and link only the udf's that are needed
750  */
751  auto cgen_state = executor_->getCgenStatePtr();
752  auto is_gpu = co_.device_type == ExecutorDeviceType::GPU;
753  if (executor_->has_rt_udf_module(is_gpu)) {
754  CodeGenerator::link_udf_module(executor_->get_rt_udf_module(is_gpu),
755  *(cgen_state->module_),
756  cgen_state,
757  llvm::Linker::Flags::OverrideFromSrc);
758  }
759 
760  LOG(IR) << (emit_only_preflight_fn ? "Pre Flight Function Entry Point IR\n"
761  : "Table Function Entry Point IR\n")
763  std::shared_ptr<CompilationContext> code;
764  if (is_gpu) {
765  LOG(IR) << "Table Function Kernel IR\n" << serialize_llvm_object(kernel_func_);
766 
767  CHECK(executor_);
768  executor_->initializeNVPTXBackend();
769 
770  CodeGenerator::GPUTarget gpu_target{
771  executor_->nvptx_target_machine_.get(), executor_->cudaMgr(), cgen_state, false};
774  kernel_func_,
776  /*is_gpu_smem_used=*/false,
777  co_,
778  gpu_target);
779  } else {
780  auto ee =
782  auto cpu_code = std::make_shared<CpuCompilationContext>(std::move(ee));
783  cpu_code->setFunctionPointer(entry_point_func_);
784  code = cpu_code;
785  }
786  LOG(IR) << "End of IR";
787 
788  return code;
789 }
#define LOG(tag)
Definition: Logger.h:285
static ExecutionEngineWrapper generateNativeCPUCode(llvm::Function *func, const std::unordered_set< llvm::Function * > &live_funcs, const CompilationOptions &co)
static void link_udf_module(const std::unique_ptr< llvm::Module > &udf_module, llvm::Module &module, CgenState *cgen_state, llvm::Linker::Flags flags=llvm::Linker::Flags::None)
ExecutorDeviceType device_type
std::string serialize_llvm_object(const T *llvm_obj)
static std::shared_ptr< GpuCompilationContext > generateNativeGPUCode(Executor *executor, llvm::Function *func, llvm::Function *wrapper_func, const std::unordered_set< llvm::Function * > &live_funcs, const bool is_gpu_smem_used, const CompilationOptions &co, const GPUTarget &gpu_target)
#define CHECK(condition)
Definition: Logger.h:291
#define DEBUG_TIMER(name)
Definition: Logger.h:412

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void TableFunctionCompilationContext::generateCastsForInputTypes ( const TableFunctionExecutionUnit exe_unit,
const std::vector< std::pair< llvm::Value *, const SQLTypeInfo >> &  columns_to_cast,
llvm::Value *  mgr_ptr 
)
private
void TableFunctionCompilationContext::generateEntryPoint ( const TableFunctionExecutionUnit exe_unit,
bool  emit_only_preflight_fn 
)
private

Definition at line 439 of file TableFunctionCompilationContext.cpp.

References anonymous_namespace{TableFunctionCompilationContext.cpp}::alloc_array(), anonymous_namespace{TableFunctionCompilationContext.cpp}::alloc_column(), anonymous_namespace{TableFunctionCompilationContext.cpp}::alloc_column_list(), CHECK, CHECK_EQ, co_, CPU, DEBUG_TIMER, CompilationOptions::device_type, entry_point_func_, executor_, generate_column_heads_load(), generateTableFunctionCall(), get_bit_width(), get_fp_ptr_type(), get_int_ptr_type(), get_int_type(), GPU, table_functions::TableFunction::hasOutputSizeKnownPreLaunch(), table_functions::TableFunction::hasPreFlightOutputSizer(), TableFunctionExecutionUnit::input_exprs, passColumnsByValue(), TableFunctionExecutionUnit::table_func, TableFunctionExecutionUnit::target_exprs, to_string(), table_functions::TableFunction::usesManager(), and verify_function_ir().

Referenced by compile().

441  {
442  auto timer = DEBUG_TIMER(__func__);
444  CHECK_EQ(entry_point_func_->arg_size(), 7);
445  auto arg_it = entry_point_func_->arg_begin();
446  const auto mgr_ptr = &*arg_it;
447  const auto input_cols_arg = &*(++arg_it);
448  const auto input_row_counts_arg = &*(++arg_it);
449  const auto input_str_dict_proxies_arg = &*(++arg_it);
450  const auto output_buffers_arg = &*(++arg_it);
451  const auto output_str_dict_proxies_arg = &*(++arg_it);
452  const auto output_row_count_ptr = &*(++arg_it);
453  auto cgen_state = executor_->getCgenStatePtr();
454  CHECK(cgen_state);
455  auto& ctx = cgen_state->context_;
456 
457  llvm::BasicBlock* bb_entry =
458  llvm::BasicBlock::Create(ctx, ".entry", entry_point_func_, 0);
459  cgen_state->ir_builder_.SetInsertPoint(bb_entry);
460 
461  llvm::BasicBlock* bb_exit = llvm::BasicBlock::Create(ctx, ".exit", entry_point_func_);
462 
463  llvm::BasicBlock* func_body_bb = llvm::BasicBlock::Create(
464  ctx, ".func_body0", cgen_state->ir_builder_.GetInsertBlock()->getParent());
465 
466  cgen_state->ir_builder_.SetInsertPoint(bb_entry);
467  cgen_state->ir_builder_.CreateBr(func_body_bb);
468 
469  cgen_state->ir_builder_.SetInsertPoint(func_body_bb);
470  auto col_heads = generate_column_heads_load(
471  exe_unit.input_exprs.size(), input_cols_arg, cgen_state->ir_builder_, ctx);
472  CHECK_EQ(exe_unit.input_exprs.size(), col_heads.size());
473  auto row_count_heads = generate_column_heads_load(
474  exe_unit.input_exprs.size(), input_row_counts_arg, cgen_state->ir_builder_, ctx);
475 
476  auto input_str_dict_proxy_heads = std::vector<llvm::Value*>();
478  input_str_dict_proxy_heads = generate_column_heads_load(exe_unit.input_exprs.size(),
479  input_str_dict_proxies_arg,
480  cgen_state->ir_builder_,
481  ctx);
482  }
483  // The column arguments of C++ UDTFs processed by clang must be
484  // passed by reference, see rbc issues 200 and 289.
485  auto pass_column_by_value = passColumnsByValue(exe_unit);
486  std::vector<llvm::Value*> func_args;
487  size_t func_arg_index = 0;
488  if (exe_unit.table_func.usesManager()) {
489  func_args.push_back(mgr_ptr);
490  func_arg_index++;
491  }
492  int col_index = -1;
493 
494  for (size_t i = 0; i < exe_unit.input_exprs.size(); i++) {
495  const auto& expr = exe_unit.input_exprs[i];
496  const auto& ti = expr->get_type_info();
497  if (col_index == -1) {
498  func_arg_index += 1;
499  }
500  if (ti.is_fp()) {
501  auto r = cgen_state->ir_builder_.CreateBitCast(
502  col_heads[i], get_fp_ptr_type(get_bit_width(ti), ctx));
503  llvm::LoadInst* scalar_fp = cgen_state->ir_builder_.CreateLoad(
504  r->getType()->getPointerElementType(),
505  r,
506  "input_scalar_fp." + std::to_string(func_arg_index));
507  func_args.push_back(scalar_fp);
508  CHECK_EQ(col_index, -1);
509  } else if (ti.is_integer() || ti.is_boolean() || ti.is_timestamp() ||
510  ti.is_timeinterval()) {
511  auto r = cgen_state->ir_builder_.CreateBitCast(
512  col_heads[i], get_int_ptr_type(get_bit_width(ti), ctx));
513  llvm::LoadInst* scalar_int = cgen_state->ir_builder_.CreateLoad(
514  r->getType()->getPointerElementType(),
515  r,
516  "input_scalar_int." + std::to_string(func_arg_index));
517  func_args.push_back(scalar_int);
518  CHECK_EQ(col_index, -1);
519  } else if (ti.is_text_encoding_none()) {
520  auto varchar_size =
521  cgen_state->ir_builder_.CreateBitCast(col_heads[i], get_int_ptr_type(64, ctx));
522  auto varchar_ptr = cgen_state->ir_builder_.CreateGEP(
523  col_heads[i]->getType()->getScalarType()->getPointerElementType(),
524  col_heads[i],
525  cgen_state->llInt(8));
526  auto [varchar_struct, varchar_struct_ptr] = alloc_column(
527  std::string("input_varchar_literal.") + std::to_string(func_arg_index),
528  i,
529  ti,
530  varchar_ptr,
531  varchar_size,
532  nullptr,
533  ctx,
534  cgen_state->ir_builder_);
535  func_args.push_back(
536  (pass_column_by_value
537  ? cgen_state->ir_builder_.CreateLoad(
538  varchar_struct->getType()->getPointerElementType(), varchar_struct)
539  : varchar_struct_ptr));
540  CHECK_EQ(col_index, -1);
541  } else if (ti.is_column()) {
542  auto [col, col_ptr] = alloc_column(
543  std::string("input_col.") + std::to_string(func_arg_index),
544  i,
545  ti.get_elem_type(),
546  col_heads[i],
547  row_count_heads[i],
549  : input_str_dict_proxy_heads[i],
550  ctx,
551  cgen_state->ir_builder_);
552  func_args.push_back((pass_column_by_value
553  ? cgen_state->ir_builder_.CreateLoad(
554  col->getType()->getPointerElementType(), col)
555  : col_ptr));
556  CHECK_EQ(col_index, -1);
557  } else if (ti.is_column_list()) {
558  if (col_index == -1) {
559  auto col_list = alloc_column_list(
560  std::string("input_col_list.") + std::to_string(func_arg_index),
561  ti.get_elem_type(),
562  col_heads[i],
563  ti.get_dimension(),
564  row_count_heads[i],
565  input_str_dict_proxy_heads[i],
566  ctx,
567  cgen_state->ir_builder_);
568  func_args.push_back(col_list);
569  }
570  col_index++;
571  if (col_index + 1 == ti.get_dimension()) {
572  col_index = -1;
573  }
574  } else if (ti.is_array()) {
575  /*
576  Literal array expression is encoded in a contiguous buffer
577  with the following memory layout:
578 
579  | <array size> | <array is_null> | <array data> |
580  |<-- 8 bytes ->|<-- 8 bytes ---->|<-- <array size> * <array element size> -->|
581 
582  Notice that while is_null in the `struct Array` has type
583  int8_t, in the buffer we use int64_t value to hold the
584  is_null state in order to have the array data 64-bit
585  aligned.
586  */
587  auto array_size =
588  cgen_state->ir_builder_.CreateBitCast(col_heads[i], get_int_ptr_type(64, ctx));
589  auto array_is_null_ptr = cgen_state->ir_builder_.CreateGEP(
590  col_heads[i]->getType()->getScalarType()->getPointerElementType(),
591  col_heads[i],
592  cgen_state->llInt(8));
593  auto array_is_null = cgen_state->ir_builder_.CreateLoad(
594  array_is_null_ptr->getType()->getPointerElementType(), array_is_null_ptr);
595 
596  auto array_ptr = cgen_state->ir_builder_.CreateGEP(
597  col_heads[i]->getType()->getScalarType()->getPointerElementType(),
598  col_heads[i],
599  cgen_state->llInt(16));
600  array_size->setName(std::string("array_size.") + std::to_string(func_arg_index));
601  array_is_null->setName(std::string("array_is_null.") +
602  std::to_string(func_arg_index));
603  array_ptr->setName(std::string("array_ptr.") + std::to_string(func_arg_index));
604 
605  auto array_struct_ptr =
606  alloc_array(std::string("literal_array.") + std::to_string(func_arg_index),
607  i,
608  ti,
609  array_ptr,
610  array_size,
611  array_is_null,
612  ctx,
613  cgen_state->ir_builder_);
614 
615  // passing columns by value is a historical artifact, so no need
616  // to support it for array expressions:
617  CHECK_EQ(pass_column_by_value, false);
618  func_args.push_back(array_struct_ptr);
619  CHECK_EQ(col_index, -1);
620  } else {
621  throw std::runtime_error("Table function input has unsupported type: " +
622  ti.get_type_name());
623  }
624  }
625  auto output_str_dict_proxy_heads =
627  ? (generate_column_heads_load(exe_unit.target_exprs.size(),
628  output_str_dict_proxies_arg,
629  cgen_state->ir_builder_,
630  ctx))
631  : std::vector<llvm::Value*>();
632 
633  std::vector<llvm::Value*> output_col_args;
634  for (size_t i = 0; i < exe_unit.target_exprs.size(); i++) {
635  auto* gep = cgen_state->ir_builder_.CreateGEP(
636  output_buffers_arg->getType()->getScalarType()->getPointerElementType(),
637  output_buffers_arg,
638  cgen_state->llInt(i));
639  auto output_load =
640  cgen_state->ir_builder_.CreateLoad(gep->getType()->getPointerElementType(), gep);
641  const auto& expr = exe_unit.target_exprs[i];
642  const auto& ti = expr->get_type_info();
643  CHECK(!ti.is_column()); // UDTF output column type is its data type
644  CHECK(!ti.is_column_list()); // TODO: when UDTF outputs column_list, convert it to
645  // output columns
646  // UDTF output columns use FlatBuffer storage whenever type supports it
647  CHECK_EQ(ti.supportsFlatBuffer(), ti.usesFlatBuffer()) << ti;
648  auto [col, col_ptr] = alloc_column(
649  std::string("output_col.") + std::to_string(i),
650  i,
651  ti,
653  ? output_load
654  : nullptr), // CPU: set_output_row_size will set the output
655  // Column ptr member
656  output_row_count_ptr,
657  co_.device_type == ExecutorDeviceType::CPU ? output_str_dict_proxy_heads[i]
658  : nullptr,
659  ctx,
660  cgen_state->ir_builder_);
661  if (co_.device_type == ExecutorDeviceType::CPU && !emit_only_preflight_fn) {
662  cgen_state->emitExternalCall(
663  "TableFunctionManager_register_output_column",
664  llvm::Type::getVoidTy(ctx),
665  {mgr_ptr, llvm::ConstantInt::get(get_int_type(32, ctx), i, true), col_ptr});
666  }
667  output_col_args.push_back((pass_column_by_value ? col : col_ptr));
668  }
669 
670  // output column members must be set before loading column when
671  // column instances are passed by value
672  if ((exe_unit.table_func.hasOutputSizeKnownPreLaunch() ||
673  exe_unit.table_func.hasPreFlightOutputSizer()) &&
674  (co_.device_type == ExecutorDeviceType::CPU) && !emit_only_preflight_fn) {
675  cgen_state->emitExternalCall(
676  "TableFunctionManager_set_output_row_size",
677  llvm::Type::getVoidTy(ctx),
678  {mgr_ptr,
679  cgen_state->ir_builder_.CreateLoad(
680  output_row_count_ptr->getType()->getPointerElementType(),
681  output_row_count_ptr)});
682  }
683 
684  if (!emit_only_preflight_fn) {
685  for (auto& col : output_col_args) {
686  func_args.push_back((pass_column_by_value
687  ? cgen_state->ir_builder_.CreateLoad(
688  col->getType()->getPointerElementType(), col)
689  : col));
690  }
691  }
692 
694  exe_unit, func_args, bb_exit, output_row_count_ptr, emit_only_preflight_fn);
695 
696  // std::cout << "=================================" << std::endl;
697  // entry_point_func_->print(llvm::outs());
698  // std::cout << "=================================" << std::endl;
699 
701 }
llvm::Type * get_fp_ptr_type(const int width, llvm::LLVMContext &context)
#define CHECK_EQ(x, y)
Definition: Logger.h:301
bool passColumnsByValue(const TableFunctionExecutionUnit &exe_unit)
std::vector< Analyzer::Expr * > input_exprs
const table_functions::TableFunction table_func
std::tuple< llvm::Value *, llvm::Value * > alloc_column(std::string col_name, const size_t index, const SQLTypeInfo &data_target_info, llvm::Value *data_ptr, llvm::Value *data_size, llvm::Value *data_str_dict_proxy_ptr, llvm::LLVMContext &ctx, llvm::IRBuilder<> &ir_builder)
llvm::Type * get_int_type(const int width, llvm::LLVMContext &context)
llvm::Value * alloc_column_list(std::string col_list_name, const SQLTypeInfo &data_target_info, llvm::Value *data_ptrs, int length, llvm::Value *data_size, llvm::Value *data_str_dict_proxy_ptrs, llvm::LLVMContext &ctx, llvm::IRBuilder<> &ir_builder)
std::string to_string(char const *&&v)
llvm::Value * alloc_array(std::string arr_name, const size_t index, const SQLTypeInfo &data_target_info, llvm::Value *data_ptr, llvm::Value *data_size, llvm::Value *data_is_null, llvm::LLVMContext &ctx, llvm::IRBuilder<> &ir_builder)
void verify_function_ir(const llvm::Function *func)
size_t get_bit_width(const SQLTypeInfo &ti)
void generateTableFunctionCall(const TableFunctionExecutionUnit &exe_unit, const std::vector< llvm::Value * > &func_args, llvm::BasicBlock *bb_exit, llvm::Value *output_row_count_ptr, bool emit_only_preflight_fn)
ExecutorDeviceType device_type
std::vector< llvm::Value * > generate_column_heads_load(const int num_columns, llvm::Value *byte_stream_arg, llvm::IRBuilder<> &ir_builder, llvm::LLVMContext &ctx)
#define CHECK(condition)
Definition: Logger.h:291
#define DEBUG_TIMER(name)
Definition: Logger.h:412
std::vector< Analyzer::Expr * > target_exprs
llvm::Type * get_int_ptr_type(const int width, llvm::LLVMContext &context)

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void TableFunctionCompilationContext::generateGpuKernel ( )
private

Definition at line 703 of file TableFunctionCompilationContext.cpp.

References CHECK, CHECK_EQ, DEBUG_TIMER, entry_point_func_, executor_, get_int_type(), and kernel_func_.

Referenced by compile().

703  {
704  auto timer = DEBUG_TIMER(__func__);
706  std::vector<llvm::Type*> arg_types;
707  arg_types.reserve(entry_point_func_->arg_size());
708  std::for_each(entry_point_func_->arg_begin(),
709  entry_point_func_->arg_end(),
710  [&arg_types](const auto& arg) { arg_types.push_back(arg.getType()); });
711  CHECK_EQ(arg_types.size(), entry_point_func_->arg_size());
712 
713  auto cgen_state = executor_->getCgenStatePtr();
714  CHECK(cgen_state);
715  auto& ctx = cgen_state->context_;
716 
717  std::vector<llvm::Type*> wrapper_arg_types(arg_types.size() + 1);
718  wrapper_arg_types[0] = llvm::PointerType::get(get_int_type(32, ctx), 0);
719  wrapper_arg_types[1] = arg_types[0];
720 
721  for (size_t i = 1; i < arg_types.size(); ++i) {
722  wrapper_arg_types[i + 1] = arg_types[i];
723  }
724 
725  auto wrapper_ft =
726  llvm::FunctionType::get(llvm::Type::getVoidTy(ctx), wrapper_arg_types, false);
727  kernel_func_ = llvm::Function::Create(wrapper_ft,
728  llvm::Function::ExternalLinkage,
729  "table_func_kernel",
730  cgen_state->module_);
731 
732  auto wrapper_bb_entry = llvm::BasicBlock::Create(ctx, ".entry", kernel_func_, 0);
733  llvm::IRBuilder<> b(ctx);
734  b.SetInsertPoint(wrapper_bb_entry);
735  std::vector<llvm::Value*> loaded_args = {kernel_func_->arg_begin() + 1};
736  for (size_t i = 2; i < wrapper_arg_types.size(); ++i) {
737  loaded_args.push_back(kernel_func_->arg_begin() + i);
738  }
739  auto error_lv = b.CreateCall(entry_point_func_, loaded_args);
740  b.CreateStore(error_lv, kernel_func_->arg_begin());
741  b.CreateRetVoid();
742 }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
llvm::Type * get_int_type(const int width, llvm::LLVMContext &context)
#define CHECK(condition)
Definition: Logger.h:291
#define DEBUG_TIMER(name)
Definition: Logger.h:412

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void TableFunctionCompilationContext::generateTableFunctionCall ( const TableFunctionExecutionUnit exe_unit,
const std::vector< llvm::Value * > &  func_args,
llvm::BasicBlock *  bb_exit,
llvm::Value *  output_row_count_ptr,
bool  emit_only_preflight_fn 
)
private

Definition at line 394 of file TableFunctionCompilationContext.cpp.

References entry_point_func_, executor_, get_int_type(), table_functions::TableFunction::getName(), table_functions::TableFunction::getPreFlightFnName(), and TableFunctionExecutionUnit::table_func.

Referenced by generateEntryPoint().

399  {
400  auto cgen_state = executor_->getCgenStatePtr();
401  // Emit llvm IR code to call the table function
402  llvm::LLVMContext& ctx = cgen_state->context_;
403  llvm::IRBuilder<>* ir_builder = &cgen_state->ir_builder_;
404 
405  std::string func_name =
406  (emit_only_preflight_fn ? exe_unit.table_func.getPreFlightFnName()
407  : exe_unit.table_func.getName(false, true));
408  llvm::Value* table_func_return =
409  cgen_state->emitExternalCall(func_name, get_int_type(32, ctx), func_args);
410 
411  table_func_return->setName(emit_only_preflight_fn ? "preflight_check_func_ret"
412  : "table_func_ret");
413 
414  // If table_func_return is non-negative then store the value in
415  // output_row_count and return zero. Otherwise, return
416  // table_func_return that negative value contains the error code.
417  llvm::BasicBlock* bb_exit_0 =
418  llvm::BasicBlock::Create(ctx, ".exit0", entry_point_func_);
419 
420  llvm::Constant* const_zero =
421  llvm::ConstantInt::get(table_func_return->getType(), 0, true);
422  llvm::Value* is_ok = ir_builder->CreateICmpSGE(table_func_return, const_zero);
423  ir_builder->CreateCondBr(is_ok, bb_exit_0, bb_exit);
424 
425  ir_builder->SetInsertPoint(bb_exit_0);
426  llvm::Value* r =
427  ir_builder->CreateIntCast(table_func_return, get_int_type(64, ctx), true);
428  ir_builder->CreateStore(r, output_row_count_ptr);
429  ir_builder->CreateRet(const_zero);
430 
431  ir_builder->SetInsertPoint(bb_exit);
432  // when table_func_return == TableFunctionErrorCode::NotAnError,
433  // then the table function is considered a success while
434  // output_row_count_ptr will be uninitialized and the output row
435  // count is defined by other means, see QE-877.
436  ir_builder->CreateRet(table_func_return);
437 }
const table_functions::TableFunction table_func
llvm::Type * get_int_type(const int width, llvm::LLVMContext &context)
std::string getName(const bool drop_suffix=false, const bool lower=false) const

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

TableFunctionCompilationContext& TableFunctionCompilationContext::operator= ( const TableFunctionCompilationContext )
delete
bool TableFunctionCompilationContext::passColumnsByValue ( const TableFunctionExecutionUnit exe_unit)
private

Definition at line 379 of file TableFunctionCompilationContext.cpp.

References co_, CompilationOptions::device_type, executor_, GPU, table_functions::TableFunction::isRuntime(), and TableFunctionExecutionUnit::table_func.

Referenced by generateEntryPoint().

380  {
381  bool is_gpu = co_.device_type == ExecutorDeviceType::GPU;
382  auto mod = executor_->get_rt_udf_module(is_gpu).get();
383  if (mod != nullptr) {
384  auto* flag = mod->getModuleFlag("pass_column_arguments_by_value");
385  if (auto* cnt = llvm::mdconst::extract_or_null<llvm::ConstantInt>(flag)) {
386  return cnt->getZExtValue();
387  }
388  }
389 
390  // fallback to original behavior
391  return exe_unit.table_func.isRuntime();
392 }
const table_functions::TableFunction table_func
ExecutorDeviceType device_type

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

Member Data Documentation

const CompilationOptions& TableFunctionCompilationContext::co_
private
llvm::Function* TableFunctionCompilationContext::entry_point_func_
private
Executor* TableFunctionCompilationContext::executor_
private
llvm::Function* TableFunctionCompilationContext::kernel_func_
private

Definition at line 60 of file TableFunctionCompilationContext.h.

Referenced by finalize(), and generateGpuKernel().


The documentation for this class was generated from the following files: