Helper function to store a value into the results buffer if the expr evaluated to NULL. We don't want (NULL, 1) to hash to the same as (0,1) so we'll pick a more random value.
| 717 | // evaluated to NULL. We don't want (NULL, 1) to hash to the same as (0,1) so |
| 718 | // we'll pick a more random value. |
| 719 | static void CodegenAssignNullValue(LlvmCodeGen* codegen, LlvmBuilder* builder, |
| 720 | llvm::Value* dst, const ColumnType& type) { |
| 721 | uint64_t fnv_seed = HashUtil::FNV_SEED; |
| 722 | |
| 723 | if (type.type == TYPE_STRING || type.type == TYPE_VARCHAR) { |
| 724 | llvm::Value* null_len = codegen->GetI32Constant(fnv_seed); |
| 725 | llvm::Value* null_ptr = builder->CreateIntToPtr(null_len, codegen->ptr_type()); |
| 726 | llvm::Function* str_unsafe_assign_fn = codegen->GetFunction( |
| 727 | IRFunction::STRING_VALUE_UNSAFE_ASSIGN, false); |
| 728 | builder->CreateCall(str_unsafe_assign_fn, |
| 729 | llvm::ArrayRef<llvm::Value*>({dst, null_ptr, null_len})); |
| 730 | } else { |
| 731 | llvm::Value* null_value = NULL; |
| 732 | int byte_size = type.GetByteSize(); |
| 733 | // Get a type specific representation of fnv_seed |
| 734 | switch (type.type) { |
| 735 | case TYPE_BOOLEAN: |
| 736 | // In results, booleans are stored as 1 byte |
| 737 | dst = builder->CreateBitCast(dst, codegen->ptr_type()); |
| 738 | null_value = codegen->GetI8Constant(fnv_seed); |
| 739 | break; |
| 740 | case TYPE_TIMESTAMP: { |
| 741 | // Cast 'dst' to 'i128*' |
| 742 | DCHECK_EQ(byte_size, 16); |
| 743 | llvm::PointerType* fnv_seed_ptr_type = |
| 744 | codegen->GetPtrType(llvm::Type::getIntNTy(codegen->context(), byte_size * 8)); |
| 745 | dst = builder->CreateBitCast(dst, fnv_seed_ptr_type); |
| 746 | null_value = codegen->GetIntConstant(byte_size, fnv_seed, fnv_seed); |
| 747 | break; |
| 748 | } |
| 749 | case TYPE_TINYINT: |
| 750 | case TYPE_SMALLINT: |
| 751 | case TYPE_INT: |
| 752 | case TYPE_BIGINT: |
| 753 | case TYPE_DECIMAL: |
| 754 | case TYPE_DATE: |
| 755 | null_value = codegen->GetIntConstant(byte_size, fnv_seed, fnv_seed); |
| 756 | break; |
| 757 | case TYPE_FLOAT: { |
| 758 | // Don't care about the value, just the bit pattern |
| 759 | float fnv_seed_float = *reinterpret_cast<float*>(&fnv_seed); |
| 760 | null_value = |
| 761 | llvm::ConstantFP::get(codegen->context(), llvm::APFloat(fnv_seed_float)); |
| 762 | break; |
| 763 | } |
| 764 | case TYPE_DOUBLE: { |
| 765 | // Don't care about the value, just the bit pattern |
| 766 | double fnv_seed_double = *reinterpret_cast<double*>(&fnv_seed); |
| 767 | null_value = |
| 768 | llvm::ConstantFP::get(codegen->context(), llvm::APFloat(fnv_seed_double)); |
| 769 | break; |
| 770 | } |
| 771 | default: |
| 772 | DCHECK(false); |
| 773 | } |
| 774 | builder->CreateStore(null_value, dst); |
| 775 | } |
| 776 | } |
no test coverage detected