Skip to content

Commit bce1f5e

Browse files
committed
Runtime: Provide ABI space for source location info in unconditional casts.
Currently ignored, but this will allow future compilers to pass down source location information for cast failure runtime errors without backward deployment constraints.
1 parent cd0012d commit bce1f5e

14 files changed

+190
-82
lines changed

include/swift/Runtime/Casting.h

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -62,12 +62,16 @@ swift_dynamicCastClass(const void *object, const ClassMetadata *targetType);
6262
/// \param object The object to cast.
6363
/// \param targetType The type to which we are casting, which is known to be
6464
/// a Swift class type.
65+
/// \param file The source filename from which to report failure. May be null.
66+
/// \param line The source line from which to report failure.
67+
/// \param column The source column from which to report failure.
6568
///
6669
/// \returns the object.
6770
SWIFT_RUNTIME_EXPORT
6871
const void *
6972
swift_dynamicCastClassUnconditional(const void *object,
70-
const ClassMetadata *targetType);
73+
const ClassMetadata *targetType,
74+
const char *file, unsigned line, unsigned column);
7175

7276
#if SWIFT_OBJC_INTEROP
7377
/// Checked Objective-C-style dynamic cast to a class type.
@@ -103,25 +107,33 @@ swift_dynamicCastForeignClass(const void *object,
103107
/// \param object The object to cast, or nil.
104108
/// \param targetType The type to which we are casting, which is known to be
105109
/// a class type, but not necessarily valid type metadata.
110+
/// \param file The source filename from which to report failure. May be null.
111+
/// \param line The source line from which to report failure.
112+
/// \param column The source column from which to report failure.
106113
///
107114
/// \returns the object.
108115
SWIFT_RUNTIME_EXPORT
109116
const void *
110117
swift_dynamicCastObjCClassUnconditional(const void *object,
111-
const ClassMetadata *targetType);
118+
const ClassMetadata *targetType,
119+
const char *file, unsigned line, unsigned column);
112120

113121
/// Unconditional, checked dynamic cast to a foreign class type.
114122
///
115123
/// \param object The object to cast, or nil.
116124
/// \param targetType The type to which we are casting, which is known to be
117125
/// a foreign class type.
126+
/// \param file The source filename from which to report failure. May be null.
127+
/// \param line The source line from which to report failure.
128+
/// \param column The source column from which to report failure.
118129
///
119130
/// \returns the object if the cast succeeds, or null otherwise.
120131
SWIFT_RUNTIME_EXPORT
121132
const void *
122133
swift_dynamicCastForeignClassUnconditional(
123134
const void *object,
124-
const ForeignClassMetadata *targetType);
135+
const ForeignClassMetadata *targetType,
136+
const char *file, unsigned line, unsigned column);
125137
#endif
126138

127139
/// Checked dynamic cast of a class instance pointer to the given type.
@@ -146,11 +158,16 @@ swift_dynamicCastUnknownClass(const void *object, const Metadata *targetType);
146158
/// \param targetType The type to which we are casting, which may be either a
147159
/// class type or a wrapped Objective-C class type.
148160
///
161+
/// \param file The source filename from which to report failure. May be null.
162+
/// \param line The source line from which to report failure.
163+
/// \param column The source column from which to report failure.
164+
///
149165
/// \returns the object.
150166
SWIFT_RUNTIME_EXPORT
151167
const void *
152168
swift_dynamicCastUnknownClassUnconditional(const void *object,
153-
const Metadata *targetType);
169+
const Metadata *targetType,
170+
const char *file, unsigned line, unsigned column);
154171

155172
SWIFT_RUNTIME_EXPORT
156173
const Metadata *
@@ -159,7 +176,8 @@ swift_dynamicCastMetatype(const Metadata *sourceType,
159176
SWIFT_RUNTIME_EXPORT
160177
const Metadata *
161178
swift_dynamicCastMetatypeUnconditional(const Metadata *sourceType,
162-
const Metadata *targetType);
179+
const Metadata *targetType,
180+
const char *file, unsigned line, unsigned column);
163181
#if SWIFT_OBJC_INTEROP
164182
SWIFT_RUNTIME_EXPORT
165183
const ClassMetadata *
@@ -168,7 +186,8 @@ swift_dynamicCastObjCClassMetatype(const ClassMetadata *sourceType,
168186
SWIFT_RUNTIME_EXPORT
169187
const ClassMetadata *
170188
swift_dynamicCastObjCClassMetatypeUnconditional(const ClassMetadata *sourceType,
171-
const ClassMetadata *targetType);
189+
const ClassMetadata *targetType,
190+
const char *file, unsigned line, unsigned column);
172191
#endif
173192

174193
SWIFT_RUNTIME_EXPORT
@@ -179,7 +198,8 @@ SWIFT_RUNTIME_EXPORT
179198
const ClassMetadata *
180199
swift_dynamicCastForeignClassMetatypeUnconditional(
181200
const ClassMetadata *sourceType,
182-
const ClassMetadata *targetType);
201+
const ClassMetadata *targetType,
202+
const char *file, unsigned line, unsigned column);
183203

184204
/// Return the dynamic type of an opaque value.
185205
///

include/swift/Runtime/RuntimeFunctions.def

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -942,7 +942,7 @@ FUNCTION(DynamicCastClass, swift_dynamicCastClass, C_CC,
942942
FUNCTION(DynamicCastClassUnconditional, swift_dynamicCastClassUnconditional,
943943
C_CC,
944944
RETURNS(Int8PtrTy),
945-
ARGS(Int8PtrTy, Int8PtrTy),
945+
ARGS(Int8PtrTy, Int8PtrTy, Int8PtrTy, Int32Ty, Int32Ty),
946946
ATTRS(NoUnwind, ReadOnly))
947947

948948
// void *swift_dynamicCastObjCClass(void*, void*);
@@ -955,7 +955,7 @@ FUNCTION(DynamicCastObjCClass, swift_dynamicCastObjCClass, C_CC,
955955
FUNCTION(DynamicCastObjCClassUnconditional,
956956
swift_dynamicCastObjCClassUnconditional, C_CC,
957957
RETURNS(Int8PtrTy),
958-
ARGS(Int8PtrTy, Int8PtrTy),
958+
ARGS(Int8PtrTy, Int8PtrTy, Int8PtrTy, Int32Ty, Int32Ty),
959959
ATTRS(NoUnwind, ReadOnly))
960960

961961
// void *swift_dynamicCastUnknownClass(void*, void*);
@@ -968,7 +968,7 @@ FUNCTION(DynamicCastUnknownClass, swift_dynamicCastUnknownClass, C_CC,
968968
FUNCTION(DynamicCastUnknownClassUnconditional,
969969
swift_dynamicCastUnknownClassUnconditional, C_CC,
970970
RETURNS(Int8PtrTy),
971-
ARGS(Int8PtrTy, Int8PtrTy),
971+
ARGS(Int8PtrTy, Int8PtrTy, Int8PtrTy, Int32Ty, Int32Ty),
972972
ATTRS(NoUnwind, ReadOnly))
973973

974974
// type *swift_dynamicCastMetatype(type*, type*);
@@ -981,7 +981,7 @@ FUNCTION(DynamicCastMetatype, swift_dynamicCastMetatype, C_CC,
981981
FUNCTION(DynamicCastMetatypeUnconditional,
982982
swift_dynamicCastMetatypeUnconditional, C_CC,
983983
RETURNS(TypeMetadataPtrTy),
984-
ARGS(TypeMetadataPtrTy, TypeMetadataPtrTy),
984+
ARGS(TypeMetadataPtrTy, TypeMetadataPtrTy, Int8PtrTy, Int32Ty, Int32Ty),
985985
ATTRS(NoUnwind, ReadOnly))
986986

987987
// objc_class *swift_dynamicCastObjCClassMetatype(objc_class*, objc_class*);
@@ -995,7 +995,7 @@ FUNCTION(DynamicCastObjCClassMetatype, swift_dynamicCastObjCClassMetatype,
995995
FUNCTION(DynamicCastObjCClassMetatypeUnconditional,
996996
swift_dynamicCastObjCClassMetatypeUnconditional, C_CC,
997997
RETURNS(ObjCClassPtrTy),
998-
ARGS(ObjCClassPtrTy, ObjCClassPtrTy),
998+
ARGS(ObjCClassPtrTy, ObjCClassPtrTy, Int8PtrTy, Int32Ty, Int32Ty),
999999
ATTRS(NoUnwind, ReadOnly))
10001000

10011001
// bool swift_dynamicCast(opaque*, opaque*, type*, type*, size_t);
@@ -1011,7 +1011,7 @@ FUNCTION(DynamicCast, swift_dynamicCast, C_CC,
10111011
FUNCTION(DynamicCastTypeToObjCProtocolUnconditional,
10121012
swift_dynamicCastTypeToObjCProtocolUnconditional, C_CC,
10131013
RETURNS(TypeMetadataPtrTy),
1014-
ARGS(TypeMetadataPtrTy, SizeTy, Int8PtrPtrTy),
1014+
ARGS(TypeMetadataPtrTy, SizeTy, Int8PtrPtrTy, Int8PtrTy, Int32Ty, Int32Ty),
10151015
ATTRS(NoUnwind))
10161016

10171017
// type* swift_dynamicCastTypeToObjCProtocolConditional(type* object,
@@ -1029,7 +1029,7 @@ FUNCTION(DynamicCastTypeToObjCProtocolConditional,
10291029
FUNCTION(DynamicCastObjCProtocolUnconditional,
10301030
swift_dynamicCastObjCProtocolUnconditional, C_CC,
10311031
RETURNS(ObjCPtrTy),
1032-
ARGS(ObjCPtrTy, SizeTy, Int8PtrPtrTy),
1032+
ARGS(ObjCPtrTy, SizeTy, Int8PtrPtrTy, Int8PtrTy, Int32Ty, Int32Ty),
10331033
ATTRS(NoUnwind))
10341034

10351035
// id swift_dynamicCastObjCProtocolConditional(id object,
@@ -1045,7 +1045,7 @@ FUNCTION(DynamicCastObjCProtocolConditional,
10451045
FUNCTION(DynamicCastMetatypeToObjectUnconditional,
10461046
swift_dynamicCastMetatypeToObjectUnconditional, C_CC,
10471047
RETURNS(ObjCPtrTy),
1048-
ARGS(TypeMetadataPtrTy),
1048+
ARGS(TypeMetadataPtrTy, Int8PtrTy, Int32Ty, Int32Ty),
10491049
ATTRS(NoUnwind, ReadNone))
10501050

10511051
// id swift_dynamicCastMetatypeToObjectConditional(type *type);

lib/IRGen/GenCast.cpp

Lines changed: 68 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,34 @@ FailableCastResult irgen::emitClassIdenticalCast(IRGenFunction &IGF,
133133
return {cond, from};
134134
}
135135

136+
/// Returns an ArrayRef with the set of arguments to pass to a dynamic cast call.
137+
///
138+
/// `argsBuf` should be passed in as a reference to an array with three nullptr
139+
/// values at the end. These will be dropped from the return ArrayRef for a
140+
/// conditional cast, or filled in with source location arguments for an
141+
/// unconditional cast.
142+
template<unsigned n>
143+
static ArrayRef<llvm::Value*>
144+
getDynamicCastArguments(IRGenFunction &IGF,
145+
llvm::Value *(&argsBuf)[n], CheckedCastMode mode
146+
/*TODO , SILLocation location*/)
147+
{
148+
switch (mode) {
149+
case CheckedCastMode::Unconditional:
150+
// TODO: Pass along location info if available for unconditional casts, so
151+
// that the runtime error for a failed cast can report the source of the
152+
// error from user code.
153+
argsBuf[n-3] = llvm::ConstantPointerNull::get(IGF.IGM.Int8PtrTy);
154+
argsBuf[n-2] = llvm::ConstantInt::get(IGF.IGM.Int32Ty, 0);
155+
argsBuf[n-1] = llvm::ConstantInt::get(IGF.IGM.Int32Ty, 0);
156+
return argsBuf;
157+
158+
case CheckedCastMode::Conditional:
159+
return llvm::makeArrayRef(argsBuf, n-3);
160+
break;
161+
}
162+
}
163+
136164
/// Emit a checked unconditional downcast of a class value.
137165
llvm::Value *irgen::emitClassDowncast(IRGenFunction &IGF, llvm::Value *from,
138166
SILType toType, CheckedCastMode mode) {
@@ -206,9 +234,17 @@ llvm::Value *irgen::emitClassDowncast(IRGenFunction &IGF, llvm::Value *from,
206234
if (auto fun = dyn_cast<llvm::Function>(castFn))
207235
cc = fun->getCallingConv();
208236

237+
llvm::Value *argsBuf[] = {
238+
from,
239+
metadataRef,
240+
nullptr,
241+
nullptr,
242+
nullptr,
243+
};
244+
209245
auto call
210-
= IGF.Builder.CreateCall(castFn, {from, metadataRef});
211-
// FIXME: Eventually, we may want to throw.
246+
= IGF.Builder.CreateCall(castFn,
247+
getDynamicCastArguments(IGF, argsBuf, mode));
212248
call->setCallingConv(cc);
213249
call->setDoesNotThrow();
214250

@@ -267,8 +303,17 @@ void irgen::emitMetatypeDowncast(IRGenFunction &IGF,
267303
auto cc = IGF.IGM.DefaultCC;
268304
if (auto fun = dyn_cast<llvm::Function>(castFn))
269305
cc = fun->getCallingConv();
306+
307+
llvm::Value *argsBuf[] = {
308+
metatype,
309+
toMetadata,
310+
nullptr,
311+
nullptr,
312+
nullptr,
313+
};
270314

271-
auto call = IGF.Builder.CreateCall(castFn, {metatype, toMetadata});
315+
auto call = IGF.Builder.CreateCall(castFn,
316+
getDynamicCastArguments(IGF, argsBuf, mode));
272317
call->setCallingConv(cc);
273318
call->setDoesNotThrow();
274319
ex.add(call);
@@ -486,8 +531,16 @@ llvm::Value *irgen::emitMetatypeToAnyObjectDowncast(IRGenFunction &IGF,
486531
auto cc = IGF.IGM.DefaultCC;
487532
if (auto fun = dyn_cast<llvm::Function>(castFn))
488533
cc = fun->getCallingConv();
489-
490-
auto call = IGF.Builder.CreateCall(castFn, metatypeValue);
534+
535+
llvm::Value *argsBuf[] = {
536+
metatypeValue,
537+
nullptr,
538+
nullptr,
539+
nullptr,
540+
};
541+
542+
auto call = IGF.Builder.CreateCall(castFn,
543+
getDynamicCastArguments(IGF, argsBuf, mode));
491544
call->setCallingConv(cc);
492545
return call;
493546
}
@@ -672,11 +725,18 @@ void irgen::emitScalarExistentialDowncast(IRGenFunction &IGF,
672725
if (auto fun = dyn_cast<llvm::Function>(castFn))
673726
cc = fun->getCallingConv();
674727

728+
llvm::Value *argsBuf[] = {
729+
objcCastObject,
730+
IGF.IGM.getSize(Size(objcProtos.size())),
731+
protoRefsBuf.getAddress(),
732+
nullptr,
733+
nullptr,
734+
nullptr,
735+
};
675736

676737
auto call = IGF.Builder.CreateCall(
677-
castFn,
678-
{objcCastObject, IGF.IGM.getSize(Size(objcProtos.size())),
679-
protoRefsBuf.getAddress()});
738+
castFn,
739+
getDynamicCastArguments(IGF, argsBuf, mode));
680740
call->setCallingConv(cc);
681741
objcCast = call;
682742
resultValue = IGF.Builder.CreateBitCast(objcCast, resultType);

0 commit comments

Comments
 (0)