An example of generated code. Used the following query to generate it: use functional_orc_def; select a.outer_struct, b.small_struct from complextypes_nested_structs a full outer join complextypes_structs b on b.small_struct.i = a.outer_struct.inner_struct2.i + 19091; define i64 @KrpcDataStreamSenderHashRow(%"class.impala::KrpcDataStreamSender"* %this, %"class.impala::TupleRow"* %row, i64 %seed)
| 951 | // ret i64 %hash_val |
| 952 | // } |
| 953 | Status KrpcDataStreamSenderConfig::CodegenHashRow( |
| 954 | LlvmCodeGen* codegen, llvm::Function** fn) { |
| 955 | llvm::LLVMContext& context = codegen->context(); |
| 956 | LlvmBuilder builder(context); |
| 957 | |
| 958 | LlvmCodeGen::FnPrototype prototype( |
| 959 | codegen, "KrpcDataStreamSenderHashRow", codegen->i64_type()); |
| 960 | prototype.AddArgument(LlvmCodeGen::NamedVariable( |
| 961 | "this", codegen->GetNamedPtrType(KrpcDataStreamSender::LLVM_CLASS_NAME))); |
| 962 | prototype.AddArgument( |
| 963 | LlvmCodeGen::NamedVariable("row", codegen->GetStructPtrType<TupleRow>())); |
| 964 | prototype.AddArgument(LlvmCodeGen::NamedVariable("seed", codegen->i64_type())); |
| 965 | |
| 966 | llvm::Value* args[3]; |
| 967 | llvm::Function* hash_row_fn = prototype.GeneratePrototype(&builder, args); |
| 968 | llvm::Value* this_arg = args[0]; |
| 969 | llvm::Value* row_arg = args[1]; |
| 970 | |
| 971 | // Store the initial seed to hash_val |
| 972 | llvm::Value* hash_val = args[2]; |
| 973 | |
| 974 | // Unroll the loop and codegen each of the partition expressions |
| 975 | for (int i = 0; i < partition_exprs_.size(); ++i) { |
| 976 | llvm::Function* compute_fn; |
| 977 | RETURN_IF_ERROR( |
| 978 | partition_exprs_[i]->GetCodegendComputeFn(codegen, false, &compute_fn)); |
| 979 | |
| 980 | // Load the expression evaluator for the i-th partition expression |
| 981 | llvm::Function* get_expr_eval_fn = |
| 982 | codegen->GetFunction(IRFunction::KRPC_DSS_GET_PART_EXPR_EVAL, false); |
| 983 | DCHECK(get_expr_eval_fn != nullptr); |
| 984 | llvm::Value* expr_eval_arg = |
| 985 | builder.CreateCall(get_expr_eval_fn, {this_arg, codegen->GetI32Constant(i)}); |
| 986 | |
| 987 | // Compute the value against the i-th partition expression |
| 988 | llvm::Value* compute_fn_args[] = {expr_eval_arg, row_arg}; |
| 989 | CodegenAnyVal partition_val = CodegenAnyVal::CreateCallWrapped(codegen, &builder, |
| 990 | partition_exprs_[i]->type(), compute_fn, compute_fn_args, "partition_val"); |
| 991 | |
| 992 | CodegenAnyValReadWriteInfo rwi = partition_val.ToReadWriteInfo(); |
| 993 | rwi.entry_block().BranchTo(&builder); |
| 994 | |
| 995 | llvm::BasicBlock* hash_val_block = |
| 996 | llvm::BasicBlock::Create(context, "hash_val_block", hash_row_fn); |
| 997 | |
| 998 | // Set the pointer to NULL in case 'partition_val' evaluates to NULL |
| 999 | builder.SetInsertPoint(rwi.null_block()); |
| 1000 | llvm::Value* null_ptr = codegen->null_ptr_value(); |
| 1001 | builder.CreateBr(hash_val_block); |
| 1002 | |
| 1003 | // Saves 'partition_val' on the stack and passes a pointer to it to the hash function |
| 1004 | builder.SetInsertPoint(rwi.non_null_block()); |
| 1005 | llvm::Value* native_ptr = SlotDescriptor::CodegenStoreNonNullAnyValToNewAlloca(rwi); |
| 1006 | native_ptr = builder.CreatePointerCast(native_ptr, codegen->ptr_type(), "native_ptr"); |
| 1007 | builder.CreateBr(hash_val_block); |
| 1008 | |
| 1009 | // Picks the input value to hash function |
| 1010 | builder.SetInsertPoint(hash_val_block); |
nothing calls this directly
no test coverage detected