An example of the generated code for the following query: select a.outer_struct, b.small_struct from functional_orc_def.complextypes_nested_structs a inner join functional_orc_def.complextypes_structs b on b.small_struct.i = a.outer_struct.inner_struct2.i + 19091; define i1 @FilterContextEval(%"struct.impala::FilterContext"* %this, %"class.impala::TupleRow"* %row) #50 { entry: %0 = alloca i64 %e
| 187 | // ret i1 %passed_filter |
| 188 | // } |
| 189 | Status FilterContext::CodegenEval( |
| 190 | LlvmCodeGen* codegen, ScalarExpr* filter_expr, llvm::Function** fn) { |
| 191 | llvm::LLVMContext& context = codegen->context(); |
| 192 | LlvmBuilder builder(context); |
| 193 | |
| 194 | *fn = nullptr; |
| 195 | llvm::PointerType* this_type = codegen->GetStructPtrType<FilterContext>(); |
| 196 | llvm::PointerType* tuple_row_ptr_type = codegen->GetStructPtrType<TupleRow>(); |
| 197 | LlvmCodeGen::FnPrototype prototype(codegen, "FilterContextEval", |
| 198 | codegen->bool_type()); |
| 199 | prototype.AddArgument(LlvmCodeGen::NamedVariable("this", this_type)); |
| 200 | prototype.AddArgument(LlvmCodeGen::NamedVariable("row", tuple_row_ptr_type)); |
| 201 | |
| 202 | llvm::Value* args[2]; |
| 203 | llvm::Function* eval_filter_fn = prototype.GeneratePrototype(&builder, args); |
| 204 | llvm::Value* this_arg = args[0]; |
| 205 | llvm::Value* row_arg = args[1]; |
| 206 | |
| 207 | llvm::Function* compute_fn; |
| 208 | RETURN_IF_ERROR(filter_expr->GetCodegendComputeFn(codegen, false, &compute_fn)); |
| 209 | DCHECK(compute_fn != nullptr); |
| 210 | |
| 211 | // The function for checking against the bloom filter for match. |
| 212 | llvm::Function* runtime_filter_fn = |
| 213 | codegen->GetFunction(IRFunction::RUNTIME_FILTER_EVAL, false); |
| 214 | DCHECK(runtime_filter_fn != nullptr); |
| 215 | |
| 216 | // Load 'expr_eval' from 'this_arg' FilterContext object. |
| 217 | llvm::Value* expr_eval_ptr = |
| 218 | builder.CreateStructGEP(nullptr, this_arg, 0, "expr_eval_ptr"); |
| 219 | llvm::Value* expr_eval_arg = builder.CreateLoad(expr_eval_ptr, "expr_eval_arg"); |
| 220 | |
| 221 | // Evaluate the row against the filter's expression. |
| 222 | llvm::Value* compute_fn_args[] = {expr_eval_arg, row_arg}; |
| 223 | CodegenAnyVal result = CodegenAnyVal::CreateCallWrapped(codegen, &builder, |
| 224 | filter_expr->type(), compute_fn, compute_fn_args, "result"); |
| 225 | |
| 226 | CodegenAnyValReadWriteInfo rwi = result.ToReadWriteInfo(); |
| 227 | rwi.entry_block().BranchTo(&builder); |
| 228 | |
| 229 | llvm::BasicBlock* eval_filter_block = |
| 230 | llvm::BasicBlock::Create(context, "eval_filter", eval_filter_fn); |
| 231 | |
| 232 | // Set the pointer to NULL in case it evaluates to NULL. |
| 233 | builder.SetInsertPoint(rwi.null_block()); |
| 234 | llvm::Value* null_ptr = codegen->null_ptr_value(); |
| 235 | builder.CreateBr(eval_filter_block); |
| 236 | |
| 237 | // Saves 'result' on the stack and passes a pointer to it to 'runtime_filter_fn'. |
| 238 | builder.SetInsertPoint(rwi.non_null_block()); |
| 239 | llvm::Value* native_ptr = SlotDescriptor::CodegenStoreNonNullAnyValToNewAlloca(rwi); |
| 240 | native_ptr = builder.CreatePointerCast(native_ptr, codegen->ptr_type(), "native_ptr"); |
| 241 | builder.CreateBr(eval_filter_block); |
| 242 | |
| 243 | // Get the arguments in place to call 'runtime_filter_fn' to see if the row passes. |
| 244 | builder.SetInsertPoint(eval_filter_block); |
| 245 | llvm::PHINode* val_ptr_phi = rwi.CodegenNullPhiNode(native_ptr, null_ptr, |
| 246 | "val_ptr_phi"); |
nothing calls this directly
no test coverage detected