| 3860 | stackPush(PHIRet); |
| 3861 | } |
| 3862 | void compileUnsignedTrunc(LLVM::Type IntType) noexcept { |
| 3863 | auto NormBB = LLVM::BasicBlock::create(LLContext, F.Fn, "utrunc.norm"); |
| 3864 | auto NotMinBB = LLVM::BasicBlock::create(LLContext, F.Fn, "utrunc.notmin"); |
| 3865 | auto NotMaxBB = LLVM::BasicBlock::create(LLContext, F.Fn, "utrunc.notmax"); |
| 3866 | auto Value = stackPop(); |
| 3867 | const auto [Precise, MinFp, MaxFp] = |
| 3868 | [IntType, Value]() -> std::tuple<bool, LLVM::Value, LLVM::Value> { |
| 3869 | const auto BitWidth = IntType.getIntegerBitWidth(); |
| 3870 | const auto [Min, Max] = [BitWidth]() -> std::tuple<uint64_t, uint64_t> { |
| 3871 | switch (BitWidth) { |
| 3872 | case 32: |
| 3873 | return {std::numeric_limits<uint32_t>::min(), |
| 3874 | std::numeric_limits<uint32_t>::max()}; |
| 3875 | case 64: |
| 3876 | return {std::numeric_limits<uint64_t>::min(), |
| 3877 | std::numeric_limits<uint64_t>::max()}; |
| 3878 | default: |
| 3879 | assumingUnreachable(); |
| 3880 | } |
| 3881 | }(); |
| 3882 | auto FPType = Value.getType(); |
| 3883 | assuming(FPType.isFloatTy() || FPType.isDoubleTy()); |
| 3884 | const auto FPWidth = FPType.getFPMantissaWidth(); |
| 3885 | return {BitWidth <= FPWidth, LLVM::Value::getConstReal(FPType, Min), |
| 3886 | LLVM::Value::getConstReal(FPType, Max)}; |
| 3887 | }(); |
| 3888 | |
| 3889 | auto IsNotNan = Builder.createLikely(Builder.createFCmpORD(Value, Value)); |
| 3890 | Builder.createCondBr(IsNotNan, NormBB, |
| 3891 | getTrapBB(ErrCode::Value::InvalidConvToInt)); |
| 3892 | |
| 3893 | Builder.positionAtEnd(NormBB); |
| 3894 | assuming(LLVM::Core::Trunc != LLVM::Core::NotIntrinsic); |
| 3895 | auto Trunc = Builder.createUnaryIntrinsic(LLVM::Core::Trunc, Value); |
| 3896 | auto IsNotUnderflow = |
| 3897 | Builder.createLikely(Builder.createFCmpOGE(Trunc, MinFp)); |
| 3898 | Builder.createCondBr(IsNotUnderflow, NotMinBB, |
| 3899 | getTrapBB(ErrCode::Value::IntegerOverflow)); |
| 3900 | |
| 3901 | Builder.positionAtEnd(NotMinBB); |
| 3902 | auto IsNotOverflow = Builder.createLikely( |
| 3903 | Builder.createFCmp(Precise ? LLVMRealOLE : LLVMRealOLT, Trunc, MaxFp)); |
| 3904 | Builder.createCondBr(IsNotOverflow, NotMaxBB, |
| 3905 | getTrapBB(ErrCode::Value::IntegerOverflow)); |
| 3906 | |
| 3907 | Builder.positionAtEnd(NotMaxBB); |
| 3908 | stackPush(Builder.createFPToUI(Trunc, IntType)); |
| 3909 | } |
| 3910 | void compileUnsignedTruncSat(LLVM::Type IntType) noexcept { |
| 3911 | auto CurrBB = Builder.getInsertBlock(); |
| 3912 | auto NormBB = LLVM::BasicBlock::create(LLContext, F.Fn, "usat.norm"); |
nothing calls this directly
no test coverage detected