@@ -164,7 +164,7 @@ getDynamicCastArguments(IRGenFunction &IGF,
164
164
165
165
// / Emit a checked unconditional downcast of a class value.
166
166
llvm::Value *irgen::emitClassDowncast (IRGenFunction &IGF, llvm::Value *from,
167
- SILType toType, CheckedCastMode mode) {
167
+ CanType toType, CheckedCastMode mode) {
168
168
// Emit the value we're casting from.
169
169
if (from->getType () != IGF.IGM .Int8PtrTy )
170
170
from = IGF.Builder .CreateBitOrPointerCast (from, IGF.IGM .Int8PtrTy );
@@ -174,11 +174,19 @@ llvm::Value *irgen::emitClassDowncast(IRGenFunction &IGF, llvm::Value *from,
174
174
llvm::Value *metadataRef;
175
175
llvm::Constant *castFn;
176
176
177
+ // If true, the target class is not known at compile time because it is a
178
+ // class-bounded archetype or the dynamic Self type.
179
+ bool nonSpecificClass = false ;
180
+
177
181
// Get the best known type information about the destination type.
178
182
ClassDecl *destClass = nullptr ;
179
- if (auto archetypeTy = toType.getAs <ArchetypeType>()) {
183
+ if (auto archetypeTy = dyn_cast<ArchetypeType>(toType)) {
184
+ nonSpecificClass = true ;
180
185
if (auto superclassTy = archetypeTy->getSuperclass ())
181
186
destClass = superclassTy->getClassOrBoundGenericClass ();
187
+ } else if (auto selfTy = dyn_cast<DynamicSelfType>(toType)) {
188
+ nonSpecificClass = true ;
189
+ destClass = selfTy->getSelfType ()->getClassOrBoundGenericClass ();
182
190
} else {
183
191
destClass = toType.getClassOrBoundGenericClass ();
184
192
assert (destClass != nullptr );
@@ -187,7 +195,7 @@ llvm::Value *irgen::emitClassDowncast(IRGenFunction &IGF, llvm::Value *from,
187
195
// If the destination type is known to have a Swift-compatible
188
196
// implementation, use the most specific entrypoint.
189
197
if (destClass && destClass->hasKnownSwiftImplementation ()) {
190
- metadataRef = IGF.emitTypeMetadataRef (toType. getASTType () );
198
+ metadataRef = IGF.emitTypeMetadataRef (toType);
191
199
192
200
switch (mode) {
193
201
case CheckedCastMode::Unconditional:
@@ -200,9 +208,9 @@ llvm::Value *irgen::emitClassDowncast(IRGenFunction &IGF, llvm::Value *from,
200
208
201
209
// If the destination type is a CF type or a non-specific
202
210
// class-bounded archetype, use the most general cast entrypoint.
203
- } else if (toType. is <ArchetypeType>() ||
211
+ } else if (nonSpecificClass ||
204
212
destClass->getForeignClassKind ()==ClassDecl::ForeignKind::CFType) {
205
- metadataRef = IGF.emitTypeMetadataRef (toType. getASTType () );
213
+ metadataRef = IGF.emitTypeMetadataRef (toType);
206
214
207
215
switch (mode) {
208
216
case CheckedCastMode::Unconditional:
@@ -249,7 +257,7 @@ llvm::Value *irgen::emitClassDowncast(IRGenFunction &IGF, llvm::Value *from,
249
257
call->setCallingConv (cc);
250
258
call->setDoesNotThrow ();
251
259
252
- llvm::Type *subTy = IGF.getTypeInfo (toType).getStorageType ();
260
+ llvm::Type *subTy = IGF.getTypeInfoForUnlowered (toType).getStorageType ();
253
261
return IGF.Builder .CreateBitCast (call, subTy);
254
262
}
255
263
@@ -871,12 +879,14 @@ void irgen::emitScalarExistentialDowncast(IRGenFunction &IGF,
871
879
// / isn't exposed.
872
880
void irgen::emitScalarCheckedCast (IRGenFunction &IGF,
873
881
Explosion &value,
874
- SILType sourceType,
875
- SILType targetType,
882
+ SILType sourceLoweredType,
883
+ CanType sourceFormalType,
884
+ SILType targetLoweredType,
885
+ CanType targetFormalType,
876
886
CheckedCastMode mode,
877
887
Explosion &out) {
878
- assert (sourceType .isObject ());
879
- assert (targetType .isObject ());
888
+ assert (sourceLoweredType .isObject ());
889
+ assert (targetLoweredType .isObject ());
880
890
881
891
llvm::BasicBlock *nilCheckBB = nullptr ;
882
892
llvm::BasicBlock *nilMergeBB = nullptr ;
@@ -906,22 +916,23 @@ void irgen::emitScalarCheckedCast(IRGenFunction &IGF,
906
916
}
907
917
};
908
918
909
- if (auto sourceOptObjectType = sourceType .getOptionalObjectType ()) {
919
+ if (auto sourceOptObjectType = sourceLoweredType .getOptionalObjectType ()) {
910
920
// Translate the value from an enum representation to a possibly-null
911
921
// representation. Note that we assume that this projection is safe
912
922
// for the particular case of an optional class-reference or metatype
913
923
// value.
914
924
Explosion optValue;
915
925
auto someDecl = IGF.IGM .Context .getOptionalSomeDecl ();
916
- emitProjectLoadableEnum (IGF, sourceType , value, someDecl, optValue);
926
+ emitProjectLoadableEnum (IGF, sourceLoweredType , value, someDecl, optValue);
917
927
918
928
assert (value.empty ());
919
929
value = std::move (optValue);
920
- sourceType = sourceOptObjectType;
930
+ sourceLoweredType = sourceOptObjectType;
931
+ sourceFormalType = sourceFormalType.getOptionalObjectType ();
921
932
922
933
// We need a null-check because the runtime function can't handle null in
923
934
// some of the cases.
924
- if (targetType .isExistentialType ()) {
935
+ if (targetLoweredType .isExistentialType ()) {
925
936
auto &Builder = IGF.Builder ;
926
937
auto val = value.getAll ()[0 ];
927
938
auto isNotNil = Builder.CreateICmpNE (
@@ -938,7 +949,7 @@ void irgen::emitScalarCheckedCast(IRGenFunction &IGF,
938
949
939
950
// If the source value is a metatype, either do a metatype-to-metatype
940
951
// cast or cast it to an object instance and continue.
941
- if (auto sourceMetatype = sourceType .getAs <AnyMetatypeType>()) {
952
+ if (auto sourceMetatype = sourceLoweredType .getAs <AnyMetatypeType>()) {
942
953
llvm::Value *metatypeVal = nullptr ;
943
954
if (sourceMetatype->getRepresentation () != MetatypeRepresentation::Thin)
944
955
metatypeVal = value.claimNext ();
@@ -952,60 +963,61 @@ void irgen::emitScalarCheckedCast(IRGenFunction &IGF,
952
963
SmallVector<ProtocolDecl*, 1 > protocols;
953
964
954
965
// Casts to existential metatypes.
955
- if (auto existential = targetType.getAs <ExistentialMetatypeType>()) {
956
- emitScalarExistentialDowncast (IGF, metatypeVal, sourceType, targetType,
957
- mode, existential->getRepresentation (),
966
+ if (auto existential = targetLoweredType.getAs <ExistentialMetatypeType>()) {
967
+ emitScalarExistentialDowncast (IGF, metatypeVal, sourceLoweredType,
968
+ targetLoweredType, mode,
969
+ existential->getRepresentation (),
958
970
out);
959
971
return ;
960
972
961
973
// Casts to concrete metatypes.
962
- } else if (auto destMetaType = targetType .getAs <MetatypeType>()) {
974
+ } else if (auto destMetaType = targetLoweredType .getAs <MetatypeType>()) {
963
975
emitMetatypeDowncast (IGF, metatypeVal, destMetaType, mode, out);
964
976
return ;
965
977
}
966
978
967
979
// Otherwise, this is a metatype-to-object cast.
968
- assert (targetType .isAnyClassReferenceType ());
980
+ assert (targetLoweredType .isAnyClassReferenceType ());
969
981
970
982
// Convert the metatype value to AnyObject.
971
983
llvm::Value *object =
972
984
emitMetatypeToAnyObjectDowncast (IGF, metatypeVal, sourceMetatype, mode);
973
985
974
- SILType anyObjectType =
975
- SILType::getPrimitiveObjectType (
976
- IGF.IGM .Context .getAnyObjectType ());
986
+ sourceFormalType = IGF.IGM .Context .getAnyObjectType ();
987
+ sourceLoweredType = SILType::getPrimitiveObjectType (sourceFormalType);
977
988
978
989
// Continue, pretending that the source value was an (optional) value.
979
990
Explosion newValue;
980
991
newValue.add (object);
981
992
value = std::move (newValue);
982
- sourceType = anyObjectType;
983
993
}
984
994
985
- assert (!targetType .is <AnyMetatypeType>() &&
995
+ assert (!targetLoweredType .is <AnyMetatypeType>() &&
986
996
" scalar cast of class reference to metatype is unimplemented" );
987
997
988
998
// If the source type is existential, project out the class pointer.
989
999
//
990
1000
// TODO: if we're casting to an existential type, don't throw away the
991
1001
// protocol conformance information we already have.
992
1002
llvm::Value *instance;
993
- if (sourceType .isExistentialType ()) {
994
- instance = emitClassExistentialProjection (IGF, value, sourceType ,
1003
+ if (sourceLoweredType .isExistentialType ()) {
1004
+ instance = emitClassExistentialProjection (IGF, value, sourceLoweredType ,
995
1005
CanArchetypeType ());
996
1006
} else {
997
1007
instance = value.claimNext ();
998
1008
}
999
1009
1000
- if (targetType .isExistentialType ()) {
1010
+ if (targetFormalType .isExistentialType ()) {
1001
1011
Explosion outRes;
1002
- emitScalarExistentialDowncast (IGF, instance, sourceType, targetType,
1003
- mode, /* not a metatype*/ None, outRes);
1012
+ emitScalarExistentialDowncast (IGF, instance, sourceLoweredType,
1013
+ targetLoweredType, mode,
1014
+ /* not a metatype*/ None, outRes);
1004
1015
returnNilCheckedResult (IGF.Builder , outRes);
1005
1016
return ;
1006
1017
}
1007
1018
1008
1019
Explosion outRes;
1009
- llvm::Value *result = emitClassDowncast (IGF, instance, targetType, mode);
1020
+ llvm::Value *result = emitClassDowncast (IGF, instance, targetFormalType,
1021
+ mode);
1010
1022
out.add (result);
1011
1023
}
0 commit comments