Sample IR output (with 3 tuple ids in the vector): define i64 @ValidTupleId(%"class.impala::ScalarExprEvaluator"* %eval, %"class.impala::TupleRow"* %row) #48 { entry: %0 = alloca i64 %1 = alloca i64 %2 = alloca i64 %tuple_row_ptr = getelementptr inbounds %"class.impala::TupleRow", %"class.impala::TupleRow"* %row, i32 0 %tuple_ptr = bitcast %"class.impala::TupleRow"* %tuple_row_ptr to %"class.impa
| 116 | // } |
| 117 | // |
| 118 | Status ValidTupleIdExpr::GetCodegendComputeFnImpl( |
| 119 | LlvmCodeGen* codegen, llvm::Function** fn) { |
| 120 | // Create a method with the expected signature. |
| 121 | llvm::Value* args[2]; |
| 122 | llvm::Function* new_fn = CreateIrFunctionPrototype("ValidTupleId", codegen, &args); |
| 123 | llvm::LLVMContext& context = codegen->context(); |
| 124 | llvm::BasicBlock* entry_block = llvm::BasicBlock::Create(context, "entry", new_fn); |
| 125 | LlvmBuilder builder(entry_block); |
| 126 | llvm::Value* row_ptr = args[1]; |
| 127 | |
| 128 | // Unroll the loop. |
| 129 | for (uint32_t i = 0; i < tuple_ids_.size(); i++) { |
| 130 | // Get the i'th Tuple* from the row. |
| 131 | llvm::Value* tuple_row_ptr = |
| 132 | builder.CreateInBoundsGEP(row_ptr, codegen->GetI32Constant(i), "tuple_row_ptr"); |
| 133 | // Cast to Tuple** |
| 134 | llvm::Type* tuple_ptr_ptr_type = |
| 135 | codegen->GetPtrType(codegen->GetNamedPtrType(Tuple::LLVM_CLASS_NAME)); |
| 136 | llvm::Value* tuple_ptr_ptr = |
| 137 | builder.CreateBitCast(tuple_row_ptr, tuple_ptr_ptr_type, "tuple_ptr_ptr"); |
| 138 | // Get the Tuple* and compare to nullptr. |
| 139 | llvm::Value* tuple_ptr = builder.CreateLoad(tuple_ptr_ptr, "tuple_ptr"); |
| 140 | llvm::Value* is_not_null = builder.CreateIsNotNull(tuple_ptr, "is_not_null"); |
| 141 | |
| 142 | // Create a conditional on the result. |
| 143 | llvm::BasicBlock* next = llvm::BasicBlock::Create(context, "next", new_fn); |
| 144 | llvm::BasicBlock* ret_block = llvm::BasicBlock::Create(context, "return", new_fn); |
| 145 | builder.CreateCondBr(is_not_null, ret_block, next); |
| 146 | |
| 147 | // Add code to the block that is executed if the Tuple* was not a nullptr. |
| 148 | builder.SetInsertPoint(ret_block); |
| 149 | // Generate code returning an IntVal containing the tuple id. |
| 150 | CodegenAnyVal result(codegen, &builder, ColumnType(TYPE_INT), nullptr, "ret"); |
| 151 | llvm::Constant* tuple_id = |
| 152 | codegen->GetI32Constant(static_cast<uint64_t>(tuple_ids_[i])); |
| 153 | result.SetVal(tuple_id); |
| 154 | builder.CreateRet(result.GetLoweredValue()); |
| 155 | |
| 156 | // Add code to the block that is executed if the Tuple* was null. |
| 157 | builder.SetInsertPoint(next); |
| 158 | } |
| 159 | // We fell out of the loop, return null. |
| 160 | builder.CreateRet(CodegenAnyVal::GetNullVal(codegen, type())); |
| 161 | |
| 162 | *fn = codegen->FinalizeFunction(new_fn); |
| 163 | if (UNLIKELY(*fn == nullptr)) { |
| 164 | return Status(TErrorCode::IR_VERIFY_FAILED, "ValidTupleId"); |
| 165 | } |
| 166 | return Status::OK(); |
| 167 | } |
| 168 | |
| 169 | string ValidTupleIdExpr::DebugString() const { |
| 170 | return "ValidTupleId()"; |
nothing calls this directly
no test coverage detected