Codegen for HashTableCtx::Equals. For a group by with (bigint, string), the IR looks like: define i1 @Equals(%"class.impala::HashTableCtx"* %this_ptr, %"class.impala::TupleRow" %row, i8* %expr_values, i8* %expr_values_null) #34 { entry: %0 = alloca { i64, i8* } %result = call { i8, i64 } @GetSlotRef.2(%"class.impala::ExprContext" inttoptr (i64 139107136 to %"class.impala::ExprContext"*), %"class
| 1241 | // br i1 %cmp_raw10, label %continue3, label %false_block |
| 1242 | // } |
| 1243 | Status HashTableCtx::CodegenEquals(LlvmCodeGen* codegen, bool inclusive_equality, |
| 1244 | const HashTableConfig& config, llvm::Function** fn) { |
| 1245 | const std::vector<ScalarExpr*>& exprs = config.build_exprs; |
| 1246 | for (int i = 0; i < exprs.size(); ++i) { |
| 1247 | // Disable codegen for CHAR |
| 1248 | if (exprs[i]->type().type == TYPE_CHAR) { |
| 1249 | return Status("HashTableCtx::CodegenEquals(): CHAR NYI"); |
| 1250 | } |
| 1251 | } |
| 1252 | |
| 1253 | // Get types to generate function prototype |
| 1254 | llvm::PointerType* this_ptr_type = codegen->GetStructPtrType<HashTableCtx>(); |
| 1255 | llvm::PointerType* tuple_row_ptr_type = codegen->GetStructPtrType<TupleRow>(); |
| 1256 | |
| 1257 | LlvmCodeGen::FnPrototype prototype(codegen, "Equals", codegen->bool_type()); |
| 1258 | prototype.AddArgument(LlvmCodeGen::NamedVariable("this_ptr", this_ptr_type)); |
| 1259 | prototype.AddArgument(LlvmCodeGen::NamedVariable("row", tuple_row_ptr_type)); |
| 1260 | prototype.AddArgument(LlvmCodeGen::NamedVariable("expr_values", codegen->ptr_type())); |
| 1261 | prototype.AddArgument( |
| 1262 | LlvmCodeGen::NamedVariable("expr_values_null", codegen->ptr_type())); |
| 1263 | |
| 1264 | llvm::LLVMContext& context = codegen->context(); |
| 1265 | LlvmBuilder builder(context); |
| 1266 | llvm::Value* args[4]; |
| 1267 | *fn = prototype.GeneratePrototype(&builder, args); |
| 1268 | llvm::Value* this_ptr = args[0]; |
| 1269 | llvm::Value* row = args[1]; |
| 1270 | llvm::Value* expr_values = args[2]; |
| 1271 | llvm::Value* expr_values_null = args[3]; |
| 1272 | |
| 1273 | // eval_vector = build_expr_evals_.data() |
| 1274 | llvm::Value* eval_vector = codegen->CodegenCallFunction(&builder, |
| 1275 | IRFunction::HASH_TABLE_GET_BUILD_EXPR_EVALUATORS, this_ptr, "eval_vector"); |
| 1276 | |
| 1277 | llvm::BasicBlock* false_block = llvm::BasicBlock::Create(context, "false_block", *fn); |
| 1278 | for (int i = 0; i < exprs.size(); ++i) { |
| 1279 | llvm::BasicBlock* null_block = llvm::BasicBlock::Create(context, "null", *fn); |
| 1280 | llvm::BasicBlock* not_null_block = llvm::BasicBlock::Create(context, "not_null", *fn); |
| 1281 | llvm::BasicBlock* continue_block = llvm::BasicBlock::Create(context, "continue", *fn); |
| 1282 | |
| 1283 | // call GetValue on build_exprs[i] |
| 1284 | llvm::Function* expr_fn; |
| 1285 | Status status = exprs[i]->GetCodegendComputeFn(codegen, false, &expr_fn); |
| 1286 | if (!status.ok()) { |
| 1287 | *fn = NULL; |
| 1288 | return Status( |
| 1289 | Substitute("Problem with HashTableCtx::CodegenEquals: $0", status.GetDetail())); |
| 1290 | } |
| 1291 | if (exprs.size() > LlvmCodeGen::CODEGEN_INLINE_EXPRS_THRESHOLD) { |
| 1292 | // Avoid bloating function by inlining too many exprs into it. |
| 1293 | codegen->SetNoInline(expr_fn); |
| 1294 | } |
| 1295 | |
| 1296 | // Load ScalarExprEvaluator*: eval = eval_vector[i]; |
| 1297 | llvm::Value* eval_arg = codegen->CodegenArrayAt(&builder, eval_vector, i, "eval"); |
| 1298 | // Evaluate the expression. |
| 1299 | CodegenAnyVal result = CodegenAnyVal::CreateCallWrapped( |
| 1300 | codegen, &builder, exprs[i]->type(), expr_fn, {eval_arg, row}, "result"); |
nothing calls this directly
no test coverage detected