Returns the last block generated so we can set it as a predecessor in PHI nodes.
| 852 | |
| 853 | // Returns the last block generated so we can set it as a predecessor in PHI nodes. |
| 854 | llvm::BasicBlock* CodegenAnyVal::CreateStructValFromReadWriteInfo( |
| 855 | const CodegenAnyValReadWriteInfo& read_write_info, |
| 856 | llvm::Value** ptr, llvm::Value** len, llvm::BasicBlock* struct_produce_value_block) { |
| 857 | LlvmCodeGen* codegen = read_write_info.codegen(); |
| 858 | LlvmBuilder* builder = read_write_info.builder(); |
| 859 | |
| 860 | DCHECK(read_write_info.type().IsStructType() && read_write_info.children().size() > 0); |
| 861 | DCHECK(read_write_info.GetEval() != nullptr); |
| 862 | DCHECK_GT(read_write_info.GetFnCtxIdx(), -1); |
| 863 | |
| 864 | // Cross-compiled functions this hand-crafted function will call. |
| 865 | llvm::Function* const allocate_for_results_fn = |
| 866 | codegen->GetFunction(IRFunction::FN_CTX_ALLOCATE_FOR_RESULTS, false); |
| 867 | llvm::Function* const store_result_in_eval_fn = |
| 868 | codegen->GetFunction(IRFunction::STORE_RESULT_IN_EVALUATOR, false); |
| 869 | |
| 870 | builder->SetInsertPoint(read_write_info.non_null_block()); |
| 871 | std::size_t num_children = read_write_info.children().size(); |
| 872 | DCHECK_GT(num_children, 0); |
| 873 | llvm::Value* fn_ctx = read_write_info.CodegenGetFnCtx(); |
| 874 | |
| 875 | // Allocate a buffer for the child pointers. If allocation fails, the struct will be |
| 876 | // null. |
| 877 | llvm::Value* children_ptrs_buffer = builder->CreateCall(allocate_for_results_fn, |
| 878 | {fn_ctx, codegen->GetI64Constant(num_children * sizeof(uint8_t*))}, |
| 879 | "children_ptrs_buffer"); |
| 880 | llvm::Value* cast_children_ptrs_buffer = builder->CreateBitCast( |
| 881 | children_ptrs_buffer, codegen->ptr_ptr_type(), "cast_children_ptrs_buffer"); |
| 882 | llvm::Value* buffer_is_null = builder->CreateIsNull( |
| 883 | cast_children_ptrs_buffer, "buffer_is_null"); |
| 884 | |
| 885 | // Branch based on 'buffer_is_null'. |
| 886 | read_write_info.children()[0].entry_block().BranchToIfNot(builder, buffer_is_null, |
| 887 | NonWritableBasicBlock(read_write_info.null_block())); |
| 888 | for (std::size_t i = 0; i < num_children; ++i) { |
| 889 | const CodegenAnyValReadWriteInfo& child_codegen_value_read_write_info = |
| 890 | read_write_info.children()[i]; |
| 891 | CodegenAnyVal child_any_val = |
| 892 | CreateFromReadWriteInfo(child_codegen_value_read_write_info); |
| 893 | |
| 894 | llvm::ConstantStruct* child_type_ir = |
| 895 | child_codegen_value_read_write_info.GetIrType(); |
| 896 | llvm::Value* child_type_ir_ptr = codegen->CreateEntryBlockAlloca( |
| 897 | *builder, child_type_ir->getType(), "child_type_ptr"); |
| 898 | builder->CreateStore(child_type_ir, child_type_ir_ptr); |
| 899 | |
| 900 | llvm::Value* child_any_val_ptr = child_any_val.GetAnyValPtr("child_ptr"); |
| 901 | |
| 902 | // Convert and store the child in the corresponding ScalarExprEvaluator - this takes |
| 903 | // care of the lifetime of the object. |
| 904 | llvm::Value* stored_child_ptr = builder->CreateCall(store_result_in_eval_fn, |
| 905 | {child_codegen_value_read_write_info.GetEval(), child_any_val_ptr, |
| 906 | child_type_ir_ptr}, |
| 907 | "stored_value"); |
| 908 | |
| 909 | // The address where the child pointer should be written. This is in the pointer list |
| 910 | // of the StructVal. |
| 911 | llvm::Value* dst_child_ptr_addr = builder->CreateInBoundsGEP( |
nothing calls this directly
no test coverage detected