Codegen for EvalConjuncts. The generated signature is the same as EvalConjuncts(). For a node with two conjunct predicates: define i1 @EvalConjuncts(%"class.impala::ScalarExprEvaluator"** %evals, i32 %num_evals, %"class.impala::TupleRow"* %row) #34 { entry: %eval_ptr = getelementptr inbounds %"class.impala::ScalarExprEvaluator"*, %"class.impala::ScalarExprEvaluator"** %evals, i32 0 %eval = load
| 578 | // } |
| 579 | // |
| 580 | Status ExecNode::CodegenEvalConjuncts(LlvmCodeGen* codegen, |
| 581 | const vector<ScalarExpr*>& conjuncts, llvm::Function** fn, const char* name) { |
| 582 | llvm::Function* conjunct_fns[conjuncts.size()]; |
| 583 | for (int i = 0; i < conjuncts.size(); ++i) { |
| 584 | RETURN_IF_ERROR(conjuncts[i]->GetCodegendComputeFn(codegen, false, &conjunct_fns[i])); |
| 585 | if (i >= LlvmCodeGen::CODEGEN_INLINE_EXPRS_THRESHOLD) { |
| 586 | // Avoid bloating EvalConjuncts by inlining everything into it. |
| 587 | codegen->SetNoInline(conjunct_fns[i]); |
| 588 | } |
| 589 | } |
| 590 | |
| 591 | // Construct function signature to match |
| 592 | // bool EvalConjuncts(ScalarExprEvaluator**, int, TupleRow*) |
| 593 | llvm::PointerType* tuple_row_ptr_type = codegen->GetStructPtrType<TupleRow>(); |
| 594 | llvm::Type* eval_type = codegen->GetStructType<ScalarExprEvaluator>(); |
| 595 | |
| 596 | LlvmCodeGen::FnPrototype prototype(codegen, name, codegen->bool_type()); |
| 597 | prototype.AddArgument( |
| 598 | LlvmCodeGen::NamedVariable("evals", codegen->GetPtrPtrType(eval_type))); |
| 599 | prototype.AddArgument( |
| 600 | LlvmCodeGen::NamedVariable("num_evals", codegen->i32_type())); |
| 601 | prototype.AddArgument(LlvmCodeGen::NamedVariable("row", tuple_row_ptr_type)); |
| 602 | |
| 603 | LlvmBuilder builder(codegen->context()); |
| 604 | llvm::Value* args[3]; |
| 605 | *fn = prototype.GeneratePrototype(&builder, args); |
| 606 | llvm::Value* evals_arg = args[0]; |
| 607 | llvm::Value* tuple_row_arg = args[2]; |
| 608 | |
| 609 | if (conjuncts.size() > 0) { |
| 610 | llvm::LLVMContext& context = codegen->context(); |
| 611 | llvm::BasicBlock* false_block = llvm::BasicBlock::Create(context, "false", *fn); |
| 612 | |
| 613 | for (int i = 0; i < conjuncts.size(); ++i) { |
| 614 | llvm::BasicBlock* true_block = |
| 615 | llvm::BasicBlock::Create(context, "continue", *fn, false_block); |
| 616 | llvm::Value* eval_arg_ptr = builder.CreateInBoundsGEP( |
| 617 | NULL, evals_arg, codegen->GetI32Constant(i), "eval_ptr"); |
| 618 | llvm::Value* eval_arg = builder.CreateLoad(eval_arg_ptr, "eval"); |
| 619 | |
| 620 | // Call conjunct_fns[i] |
| 621 | CodegenAnyVal result = CodegenAnyVal::CreateCallWrapped(codegen, &builder, |
| 622 | conjuncts[i]->type(), conjunct_fns[i], {eval_arg, tuple_row_arg}, |
| 623 | "result"); |
| 624 | |
| 625 | // Return false if result.is_null || !result |
| 626 | llvm::Value* is_null = result.GetIsNull(); |
| 627 | llvm::Value* is_false = builder.CreateNot(result.GetVal(), "is_false"); |
| 628 | llvm::Value* return_false = builder.CreateOr(is_null, is_false, "return_false"); |
| 629 | builder.CreateCondBr(return_false, false_block, true_block); |
| 630 | |
| 631 | // Set insertion point for continue/end |
| 632 | builder.SetInsertPoint(true_block); |
| 633 | } |
| 634 | builder.CreateRet(codegen->true_value()); |
| 635 | |
| 636 | builder.SetInsertPoint(false_block); |
| 637 | builder.CreateRet(codegen->false_value()); |
nothing calls this directly
no test coverage detected