Sample IR for calling the following Java function: public String evaluate(String a, String b, String c) { if (a == null || b == null || c == null) return null; return a + b + c; } To reproduce, create the following function: create function concatenate(string, string, string) returns string location '/test-warehouse/impala-hive-udfs.jar' symbol='org.apache.impala.TestUdf'; then run the followin
| 544 | /// ret { i64, i8* } %ret |
| 545 | /// } |
| 546 | Status HiveUdfCall::GetCodegendComputeFnImpl(LlvmCodeGen* codegen, llvm::Function** fn) { |
| 547 | // Cross-compiled functions this hand-crafted function will call. |
| 548 | llvm::Function* const get_func_ctx_fn = |
| 549 | codegen->GetFunction(IRFunction::GET_FUNCTION_CTX, false); |
| 550 | llvm::Function* const get_jni_ctx_fn = |
| 551 | codegen->GetFunction(IRFunction::GET_JNI_CONTEXT, false); |
| 552 | llvm::Function* const call_java_fn = |
| 553 | codegen->GetFunction(IRFunction::HIVE_UDF_CALL_CALL_JAVA, false); |
| 554 | |
| 555 | // Function prototype. |
| 556 | llvm::LLVMContext& context = codegen->context(); |
| 557 | LlvmBuilder builder(context); |
| 558 | |
| 559 | llvm::Value* args[2]; |
| 560 | llvm::Function* const function = |
| 561 | CreateIrFunctionPrototype("HiveUdfCall", codegen, &args); |
| 562 | |
| 563 | // Codegen the initialisation of function context etc. |
| 564 | llvm::BasicBlock* const entry_block = |
| 565 | llvm::BasicBlock::Create(context, "entry", function); |
| 566 | builder.SetInsertPoint(entry_block); |
| 567 | |
| 568 | llvm::Value* const fn_ctx = builder.CreateCall( |
| 569 | get_func_ctx_fn, {args[0], codegen->GetI32Constant(fn_ctx_idx_)}, "fn_ctx"); |
| 570 | llvm::Value* const jni_ctx = builder.CreateCall(get_jni_ctx_fn, {fn_ctx}, "jni_ctx"); |
| 571 | |
| 572 | // Codegen the evaluation of children. |
| 573 | llvm::BasicBlock* const first_eval_child_block = |
| 574 | llvm::BasicBlock::Create(context, "eval_child", function); |
| 575 | builder.CreateBr(first_eval_child_block); |
| 576 | |
| 577 | llvm::BasicBlock* call_java_block = nullptr; |
| 578 | RETURN_IF_ERROR(CodegenEvalChildren(codegen, &builder, function, &args, jni_ctx, |
| 579 | first_eval_child_block, &call_java_block)); |
| 580 | |
| 581 | // Codegen the call to Java and returning the result. |
| 582 | call_java_block->setName("call_java"); |
| 583 | builder.SetInsertPoint(call_java_block); |
| 584 | |
| 585 | llvm::Value* const ir_type = type().ToIR(codegen); |
| 586 | llvm::Value* const ir_type_ptr = codegen->GetPtrTo(&builder, ir_type); |
| 587 | |
| 588 | llvm::Value* const ret_ptr = builder.CreateCall(call_java_fn, |
| 589 | {ir_type_ptr, fn_ctx, jni_ctx}, "ret_ptr"); |
| 590 | |
| 591 | llvm::Value* ret_val = CastPtrAndLoad(codegen, &builder, type(), ret_ptr, "ret"); |
| 592 | builder.CreateRet(ret_val); |
| 593 | |
| 594 | *fn = codegen->FinalizeFunction(function); |
| 595 | if (UNLIKELY(*fn == nullptr)) { |
| 596 | return Status(TErrorCode::IR_VERIFY_FAILED, "HiveUdfCall"); |
| 597 | } |
| 598 | return Status::OK(); |
| 599 | } |
| 600 | |
| 601 | string HiveUdfCall::DebugString() const { |
| 602 | stringstream out; |
nothing calls this directly
no test coverage detected