Codegen for evaluating a tuple row over either build_expr_evals_ or probe_expr_evals_. Below is the IR generated for the following query: select bigint_col, string_col from functional.alltypestiny group by bigint_col, string_col; define i1 @EvalProbeRow(%"class.impala::HashTableCtx"* %this_ptr, %"class.impala::TupleRow"* %row, i8* %expr_values, i8* %expr_values_null) #53 { entry: %eval_vector =
| 869 | // ret i1 %has_null14 |
| 870 | // } |
| 871 | Status HashTableCtx::CodegenEvalRow(LlvmCodeGen* codegen, bool build_row, |
| 872 | const HashTableConfig& config, llvm::Function** fn) { |
| 873 | const std::vector<ScalarExpr*>& exprs = |
| 874 | build_row ? config.build_exprs : config.probe_exprs; |
| 875 | const ScalarExprsResultsRowLayout& result_row_layout = |
| 876 | config.build_exprs_results_row_layout; |
| 877 | for (int i = 0; i < exprs.size(); ++i) { |
| 878 | // Disable codegen for CHAR |
| 879 | if (exprs[i]->type().type == TYPE_CHAR) { |
| 880 | return Status("HashTableCtx::CodegenEvalRow(): CHAR NYI"); |
| 881 | } |
| 882 | } |
| 883 | |
| 884 | // Get types to generate function prototype |
| 885 | llvm::PointerType* this_ptr_type = codegen->GetStructPtrType<HashTableCtx>(); |
| 886 | llvm::PointerType* tuple_row_ptr_type = codegen->GetStructPtrType<TupleRow>(); |
| 887 | LlvmCodeGen::FnPrototype prototype( |
| 888 | codegen, build_row ? "EvalBuildRow" : "EvalProbeRow", codegen->bool_type()); |
| 889 | prototype.AddArgument(LlvmCodeGen::NamedVariable("this_ptr", this_ptr_type)); |
| 890 | prototype.AddArgument(LlvmCodeGen::NamedVariable("row", tuple_row_ptr_type)); |
| 891 | prototype.AddArgument(LlvmCodeGen::NamedVariable("expr_values", codegen->ptr_type())); |
| 892 | prototype.AddArgument( |
| 893 | LlvmCodeGen::NamedVariable("expr_values_null", codegen->ptr_type())); |
| 894 | |
| 895 | llvm::LLVMContext& context = codegen->context(); |
| 896 | LlvmBuilder builder(context); |
| 897 | llvm::Value* args[4]; |
| 898 | *fn = prototype.GeneratePrototype(&builder, args); |
| 899 | llvm::Value* this_ptr = args[0]; |
| 900 | llvm::Value* row = args[1]; |
| 901 | llvm::Value* expr_values = args[2]; |
| 902 | llvm::Value* expr_values_null = args[3]; |
| 903 | llvm::Value* has_null = codegen->false_value(); |
| 904 | |
| 905 | // evaluator_vector = build_expr_evals_.data() / probe_expr_evals_.data() |
| 906 | llvm::Value* eval_vector = codegen->CodegenCallFunction(&builder, |
| 907 | build_row ? IRFunction::HASH_TABLE_GET_BUILD_EXPR_EVALUATORS : |
| 908 | IRFunction::HASH_TABLE_GET_PROBE_EXPR_EVALUATORS, |
| 909 | this_ptr, "eval_vector"); |
| 910 | |
| 911 | DCHECK_EQ(exprs.size(), result_row_layout.expr_values_offsets.size()); |
| 912 | for (int i = 0; i < exprs.size(); ++i) { |
| 913 | // TODO: refactor this to somewhere else? This is not hash table specific except for |
| 914 | // the null handling bit and would be used for anyone that needs to materialize a |
| 915 | // vector of exprs |
| 916 | // Convert result buffer to llvm ptr type |
| 917 | int offset = result_row_layout.expr_values_offsets[i]; |
| 918 | llvm::Value* loc = builder.CreateInBoundsGEP( |
| 919 | NULL, expr_values, codegen->GetI32Constant(offset), "loc_addr"); |
| 920 | llvm::Value* llvm_loc = |
| 921 | builder.CreatePointerCast(loc, codegen->GetSlotPtrType(exprs[i]->type()), "loc"); |
| 922 | |
| 923 | // Call expr |
| 924 | llvm::Function* expr_fn; |
| 925 | Status status = exprs[i]->GetCodegendComputeFn(codegen, false, &expr_fn); |
| 926 | if (!status.ok()) { |
| 927 | *fn = NULL; |
| 928 | return Status(Substitute( |
nothing calls this directly
no test coverage detected