IR Generation for updating a single aggregation slot. Signature is: void UpdateSlot(AggFnEvaluator* agg_expr_eval, AggTuple* agg_tuple, char** row) The IR for sum(double_col), which is constructed directly with the IRBuilder, is: define void @UpdateSlot(%"class.impala::AggFnEvaluator"* %agg_fn_eval, <{ double, i8 }>* %agg_tuple, %"class.impala::TupleRow"* %row) #33 { entry: %input_evals_vector =
| 309 | // } |
| 310 | // |
| 311 | Status AggregatorConfig::CodegenUpdateSlot(LlvmCodeGen* codegen, int agg_fn_idx, |
| 312 | SlotDescriptor* slot_desc, llvm::Function** fn) { |
| 313 | llvm::PointerType* agg_fn_eval_type = codegen->GetStructPtrType<AggFnEvaluator>(); |
| 314 | llvm::StructType* tuple_struct = intermediate_tuple_desc_->GetLlvmStruct(codegen); |
| 315 | if (tuple_struct == nullptr) { |
| 316 | return Status("Aggregator::CodegenUpdateSlot(): failed to generate " |
| 317 | "intermediate tuple desc"); |
| 318 | } |
| 319 | llvm::PointerType* tuple_ptr_type = codegen->GetPtrType(tuple_struct); |
| 320 | llvm::PointerType* tuple_row_ptr_type = codegen->GetStructPtrType<TupleRow>(); |
| 321 | |
| 322 | LlvmCodeGen::FnPrototype prototype(codegen, "UpdateSlot", codegen->void_type()); |
| 323 | prototype.AddArgument(LlvmCodeGen::NamedVariable("agg_fn_eval", agg_fn_eval_type)); |
| 324 | prototype.AddArgument(LlvmCodeGen::NamedVariable("agg_tuple", tuple_ptr_type)); |
| 325 | prototype.AddArgument(LlvmCodeGen::NamedVariable("row", tuple_row_ptr_type)); |
| 326 | |
| 327 | LlvmBuilder builder(codegen->context()); |
| 328 | llvm::Value* args[3]; |
| 329 | *fn = prototype.GeneratePrototype(&builder, &args[0]); |
| 330 | llvm::Value* agg_fn_eval_arg = args[0]; |
| 331 | llvm::Value* agg_tuple_arg = args[1]; |
| 332 | llvm::Value* row_arg = args[2]; |
| 333 | |
| 334 | // Get the vector of input expressions' evaluators. |
| 335 | llvm::Value* input_evals_vector = codegen->CodegenCallFunction(&builder, |
| 336 | IRFunction::AGG_FN_EVALUATOR_INPUT_EVALUATORS, agg_fn_eval_arg, |
| 337 | "input_evals_vector"); |
| 338 | |
| 339 | AggFn* agg_fn = aggregate_functions_[agg_fn_idx]; |
| 340 | const int num_inputs = agg_fn->GetNumChildren(); |
| 341 | DCHECK_GE(num_inputs, 1); |
| 342 | vector<CodegenAnyVal> input_vals; |
| 343 | for (int i = 0; i < num_inputs; ++i) { |
| 344 | ScalarExpr* input_expr = agg_fn->GetChild(i); |
| 345 | llvm::Function* input_expr_fn; |
| 346 | RETURN_IF_ERROR(input_expr->GetCodegendComputeFn(codegen, false, &input_expr_fn)); |
| 347 | DCHECK(input_expr_fn != nullptr); |
| 348 | |
| 349 | // Call input expr function with the matching evaluator to get src slot value. |
| 350 | llvm::Value* input_eval = |
| 351 | codegen->CodegenArrayAt(&builder, input_evals_vector, i, "input_eval"); |
| 352 | string input_name = Substitute("input$0", i); |
| 353 | CodegenAnyVal input_val = CodegenAnyVal::CreateCallWrapped(codegen, &builder, |
| 354 | input_expr->type(), input_expr_fn, |
| 355 | llvm::ArrayRef<llvm::Value*>({input_eval, row_arg}), input_name.c_str()); |
| 356 | input_vals.push_back(input_val); |
| 357 | } |
| 358 | |
| 359 | AggFn::AggregationOp agg_op = agg_fn->agg_op(); |
| 360 | const ColumnType& dst_type = agg_fn->intermediate_type(); |
| 361 | bool dst_is_int_or_float_or_bool = dst_type.IsIntegerType() |
| 362 | || dst_type.IsFloatingPointType() || dst_type.IsBooleanType(); |
| 363 | bool dst_is_numeric_or_bool = dst_is_int_or_float_or_bool || dst_type.IsDecimalType() |
| 364 | || dst_type.IsDateType(); |
| 365 | |
| 366 | llvm::BasicBlock* ret_block = llvm::BasicBlock::Create(codegen->context(), "ret", *fn); |
| 367 | |
| 368 | // Emit the code to compute 'result' and set the NULL indicator if needed. First check |
nothing calls this directly
no test coverage detected