@@ -1032,7 +1032,7 @@ void irgen::emitScalarCheckedCast(IRGenFunction &IGF,
1032
1032
}
1033
1033
1034
1034
if (llvm::Value *fastResult = emitFastClassCastIfPossible (
1035
- IGF, instance, sourceFormalType, targetFormalType,
1035
+ IGF, instance, sourceFormalType, targetFormalType, mode,
1036
1036
sourceWrappedInOptional, nilCheckBB, nilMergeBB)) {
1037
1037
Explosion fastExplosion;
1038
1038
fastExplosion.add (fastResult);
@@ -1054,7 +1054,7 @@ void irgen::emitScalarCheckedCast(IRGenFunction &IGF,
1054
1054
// / not required that the metadata is fully initialized.
1055
1055
llvm::Value *irgen::emitFastClassCastIfPossible (
1056
1056
IRGenFunction &IGF, llvm::Value *instance, CanType sourceFormalType,
1057
- CanType targetFormalType, bool sourceWrappedInOptional,
1057
+ CanType targetFormalType, CheckedCastMode mode, bool sourceWrappedInOptional,
1058
1058
llvm::BasicBlock *&nilCheckBB, llvm::BasicBlock *&nilMergeBB) {
1059
1059
if (!doesCastPreserveOwnershipForTypes (IGF.IGM .getSILModule (),
1060
1060
sourceFormalType, targetFormalType)) {
@@ -1089,15 +1089,18 @@ llvm::Value *irgen::emitFastClassCastIfPossible(
1089
1089
1090
1090
// If the source was originally wrapped in an Optional, check it for nil now.
1091
1091
if (sourceWrappedInOptional) {
1092
- auto isNotNil = IGF.Builder .CreateICmpNE (
1092
+ auto isNil = IGF.Builder .CreateICmpEQ (
1093
1093
instance, llvm::ConstantPointerNull::get (
1094
1094
cast<llvm::PointerType>(instance->getType ())));
1095
- auto *isNotNilContBB = llvm::BasicBlock::Create (IGF.IGM .getLLVMContext ());
1096
- nilMergeBB = llvm::BasicBlock::Create (IGF.IGM .getLLVMContext ());
1097
- nilCheckBB = IGF.Builder .GetInsertBlock ();
1098
- IGF.Builder .CreateCondBr (isNotNil, isNotNilContBB, nilMergeBB);
1099
-
1100
- IGF.Builder .emitBlock (isNotNilContBB);
1095
+ if (mode == CheckedCastMode::Unconditional) {
1096
+ IGF.emitConditionalTrap (isNil, " Unexpectedly found nil while unwrapping an Optional value" );
1097
+ } else {
1098
+ auto *isNotNilContBB = llvm::BasicBlock::Create (IGF.IGM .getLLVMContext ());
1099
+ nilMergeBB = llvm::BasicBlock::Create (IGF.IGM .getLLVMContext ());
1100
+ nilCheckBB = IGF.Builder .GetInsertBlock ();
1101
+ IGF.Builder .CreateCondBr (isNil, nilMergeBB, isNotNilContBB);
1102
+ IGF.Builder .emitBlock (isNotNilContBB);
1103
+ }
1101
1104
}
1102
1105
1103
1106
// Get the metadata pointer of the destination class type.
@@ -1121,11 +1124,15 @@ llvm::Value *irgen::emitFastClassCastIfPossible(
1121
1124
llvm::Value *rhs = IGF.Builder .CreateBitCast (objMetadata, IGF.IGM .Int8PtrTy );
1122
1125
1123
1126
// return isa_ptr == metadata_ptr ? instance : nullptr
1124
- llvm::Value *isEqual = IGF.Builder .CreateCmp (llvm::CmpInst::Predicate::ICMP_EQ ,
1127
+ llvm::Value *isNotEqual = IGF.Builder .CreateCmp (llvm::CmpInst::Predicate::ICMP_NE ,
1125
1128
lhs, rhs);
1129
+ if (mode == CheckedCastMode::Unconditional) {
1130
+ IGF.emitConditionalTrap (isNotEqual, " Unconditional cast failed" );
1131
+ return instance;
1132
+ }
1126
1133
auto *instanceTy = cast<llvm::PointerType>(instance->getType ());
1127
1134
auto *nullPtr = llvm::ConstantPointerNull::get (instanceTy);
1128
- auto *select = IGF.Builder .CreateSelect (isEqual, instance, nullPtr );
1135
+ auto *select = IGF.Builder .CreateSelect (isNotEqual, nullPtr, instance );
1129
1136
llvm::Type *destTy = IGF.getTypeInfoForUnlowered (targetFormalType).getStorageType ();
1130
1137
return IGF.Builder .CreateBitCast (select, destTy);
1131
1138
}
0 commit comments