| 927 | } |
| 928 | |
| 929 | CodegenAnyVal CodegenAnyVal::CreateFromReadWriteInfo( |
| 930 | const CodegenAnyValReadWriteInfo& read_write_info) { |
| 931 | LlvmCodeGen* codegen = read_write_info.codegen(); |
| 932 | LlvmBuilder* builder = read_write_info.builder(); |
| 933 | const ColumnType& type = read_write_info.type(); |
| 934 | |
| 935 | llvm::LLVMContext& context = codegen->context(); |
| 936 | llvm::Function* fn = read_write_info.non_null_block()->getParent(); |
| 937 | |
| 938 | llvm::BasicBlock* produce_value_block = |
| 939 | llvm::BasicBlock::Create(context, "produce_value", fn); |
| 940 | |
| 941 | builder->SetInsertPoint(read_write_info.null_block()); |
| 942 | builder->CreateBr(produce_value_block); |
| 943 | |
| 944 | if (!type.IsStructType()) { |
| 945 | builder->SetInsertPoint(read_write_info.non_null_block()); |
| 946 | builder->CreateBr(produce_value_block); |
| 947 | } |
| 948 | |
| 949 | builder->SetInsertPoint(produce_value_block); |
| 950 | CodegenAnyVal result = CodegenAnyVal::GetNonNullVal(codegen, builder, type, "result"); |
| 951 | |
| 952 | // For structs the code that reads the value consists of multiple basic blocks, so the |
| 953 | // block that should branch to 'produce_value_block' is not |
| 954 | // 'read_write_info.non_null_block'. This variable will be set to the appropriate block. |
| 955 | llvm::BasicBlock* non_null_incoming_block = read_write_info.non_null_block(); |
| 956 | if (type.IsStringType() || type.type == TYPE_FIXED_UDA_INTERMEDIATE |
| 957 | || type.IsCollectionType() || type.IsStructType()) { |
| 958 | llvm::Value* ptr = nullptr; |
| 959 | llvm::Value* len = nullptr; |
| 960 | |
| 961 | if (type.IsStructType()) { |
| 962 | non_null_incoming_block = CreateStructValFromReadWriteInfo( |
| 963 | read_write_info, &ptr, &len, produce_value_block); |
| 964 | } else { |
| 965 | ptr = read_write_info.GetPtrAndLen().ptr; |
| 966 | len = read_write_info.GetPtrAndLen().len; |
| 967 | } |
| 968 | |
| 969 | DCHECK(ptr != nullptr); |
| 970 | DCHECK(len != nullptr); |
| 971 | |
| 972 | llvm::Value* ptr_null = llvm::Constant::getNullValue(ptr->getType()); |
| 973 | llvm::PHINode* ptr_phi = LlvmCodeGen::CreateBinaryPhiNode(builder, ptr, ptr_null, |
| 974 | non_null_incoming_block, read_write_info.null_block(), "ptr_phi"); |
| 975 | |
| 976 | llvm::Value* len_null = llvm::ConstantInt::get(len->getType(), 0); |
| 977 | llvm::PHINode* len_phi = LlvmCodeGen::CreateBinaryPhiNode(builder, len, len_null, |
| 978 | non_null_incoming_block, read_write_info.null_block(), "len_phi"); |
| 979 | |
| 980 | result.SetPtr(ptr_phi); |
| 981 | result.SetLen(len_phi); |
| 982 | } else if (type.type == TYPE_TIMESTAMP) { |
| 983 | llvm::Value* time_of_day_null = llvm::ConstantInt::get( |
| 984 | read_write_info.GetTimeAndDate().time_of_day->getType(), 0); |
| 985 | llvm::PHINode* time_of_day_phi = LlvmCodeGen::CreateBinaryPhiNode(builder, |
| 986 | read_write_info.GetTimeAndDate().time_of_day, time_of_day_null, |
nothing calls this directly
no test coverage detected