@@ -1032,7 +1032,7 @@ void irgen::emitScalarCheckedCast(IRGenFunction &IGF,
10321032 }
10331033
10341034 if (llvm::Value *fastResult = emitFastClassCastIfPossible (
1035- IGF, instance, sourceFormalType, targetFormalType,
1035+ IGF, instance, sourceFormalType, targetFormalType, mode,
10361036 sourceWrappedInOptional, nilCheckBB, nilMergeBB)) {
10371037 Explosion fastExplosion;
10381038 fastExplosion.add (fastResult);
@@ -1054,7 +1054,7 @@ void irgen::emitScalarCheckedCast(IRGenFunction &IGF,
10541054// / not required that the metadata is fully initialized.
10551055llvm::Value *irgen::emitFastClassCastIfPossible (
10561056 IRGenFunction &IGF, llvm::Value *instance, CanType sourceFormalType,
1057- CanType targetFormalType, bool sourceWrappedInOptional,
1057+ CanType targetFormalType, CheckedCastMode mode, bool sourceWrappedInOptional,
10581058 llvm::BasicBlock *&nilCheckBB, llvm::BasicBlock *&nilMergeBB) {
10591059 if (!doesCastPreserveOwnershipForTypes (IGF.IGM .getSILModule (),
10601060 sourceFormalType, targetFormalType)) {
@@ -1089,15 +1089,18 @@ llvm::Value *irgen::emitFastClassCastIfPossible(
10891089
10901090 // If the source was originally wrapped in an Optional, check it for nil now.
10911091 if (sourceWrappedInOptional) {
1092- auto isNotNil = IGF.Builder .CreateICmpNE (
1092+ auto isNil = IGF.Builder .CreateICmpEQ (
10931093 instance, llvm::ConstantPointerNull::get (
10941094 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+ }
11011104 }
11021105
11031106 // Get the metadata pointer of the destination class type.
@@ -1121,11 +1124,15 @@ llvm::Value *irgen::emitFastClassCastIfPossible(
11211124 llvm::Value *rhs = IGF.Builder .CreateBitCast (objMetadata, IGF.IGM .Int8PtrTy );
11221125
11231126 // 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 ,
11251128 lhs, rhs);
1129+ if (mode == CheckedCastMode::Unconditional) {
1130+ IGF.emitConditionalTrap (isNotEqual, " Unconditional cast failed" );
1131+ return instance;
1132+ }
11261133 auto *instanceTy = cast<llvm::PointerType>(instance->getType ());
11271134 auto *nullPtr = llvm::ConstantPointerNull::get (instanceTy);
1128- auto *select = IGF.Builder .CreateSelect (isEqual, instance, nullPtr );
1135+ auto *select = IGF.Builder .CreateSelect (isNotEqual, nullPtr, instance );
11291136 llvm::Type *destTy = IGF.getTypeInfoForUnlowered (targetFormalType).getStorageType ();
11301137 return IGF.Builder .CreateBitCast (select, destTy);
11311138}
0 commit comments