| 2809 | } |
| 2810 | |
| 2811 | llvm::Value * convertCompileImpl(llvm::IRBuilderBase & builder, const ValuesWithType & arguments, const DataTypePtr & result_type) |
| 2812 | { |
| 2813 | llvm::Value * result = nullptr; |
| 2814 | castBothTypes( |
| 2815 | arguments[0].type.get(), |
| 2816 | result_type.get(), |
| 2817 | [&](const auto & left, const auto & right) |
| 2818 | { |
| 2819 | using LeftDataType = std::decay_t<decltype(left)>; |
| 2820 | using RightDataType = std::decay_t<decltype(right)>; |
| 2821 | if constexpr (IsDataTypeDecimalOrNumber<LeftDataType> && IsDataTypeDecimalOrNumber<RightDataType>) |
| 2822 | { |
| 2823 | using LeftFieldType = typename LeftDataType::FieldType; |
| 2824 | using RightFieldType = typename RightDataType::FieldType; |
| 2825 | |
| 2826 | if (isBool(right.getPtr())) |
| 2827 | { |
| 2828 | /// nativeBoolCast returns i1, but Bool (UInt8) needs i8 |
| 2829 | auto * bool_value = nativeBoolCast(builder, arguments[0]); |
| 2830 | result = builder.CreateZExt(bool_value, builder.getInt8Ty()); |
| 2831 | return true; |
| 2832 | } |
| 2833 | |
| 2834 | if constexpr (IsDataTypeNumber<LeftDataType> && IsDataTypeNumber<RightDataType>) |
| 2835 | { |
| 2836 | result = nativeCast(builder, arguments[0], right.getPtr()); |
| 2837 | return true; |
| 2838 | } |
| 2839 | else if constexpr (IsDataTypeNumber<LeftDataType> && IsDataTypeDecimal<RightDataType>) |
| 2840 | { |
| 2841 | auto scale = right.getScale(); |
| 2842 | auto multiplier = DecimalUtils::scaleMultiplier<NativeType<RightFieldType>>(scale); |
| 2843 | if constexpr (std::is_floating_point_v<LeftFieldType>) |
| 2844 | { |
| 2845 | /// left type is float and right type is decimal |
| 2846 | auto * from_type = arguments[0].value->getType(); |
| 2847 | auto * from_value = arguments[0].value; |
| 2848 | result = builder.CreateFMul(from_value, llvm::ConstantFP::get(from_type, static_cast<double>(multiplier))); |
| 2849 | result = nativeCast(builder, left.getPtr(), result, right.getPtr()); |
| 2850 | } |
| 2851 | else |
| 2852 | { |
| 2853 | /// left type is integer and right type is decimal |
| 2854 | auto * from_value = nativeCast(builder, arguments[0], right.getPtr()); |
| 2855 | auto * multiplier_value = getNativeValue(builder, right.getPtr(), RightFieldType(multiplier)); |
| 2856 | result = builder.CreateMul(from_value, multiplier_value); |
| 2857 | } |
| 2858 | return true; |
| 2859 | } |
| 2860 | else if constexpr (IsDataTypeDecimal<LeftDataType> && IsDataTypeNumber<RightDataType>) |
| 2861 | { |
| 2862 | auto scale = left.getScale(); |
| 2863 | auto divider = DecimalUtils::scaleMultiplier<NativeType<LeftFieldType>>(scale); |
| 2864 | if constexpr (std::is_floating_point_v<RightFieldType>) |
| 2865 | { |
| 2866 | DataTypePtr double_type = std::make_shared<DataTypeFloat64>(); |
| 2867 | auto * from_value = nativeCast(builder, arguments[0], double_type); |
| 2868 | auto * d = llvm::ConstantFP::get(builder.getDoubleTy(), static_cast<double>(divider)); |
no test coverage detected