mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Improve casts analysis for bridged types.
Check if the outcome of a cast from an ObjC type to a Swift type or from a Swift type to an ObjC type can be statically determined. This allows for folding of many such casts. Swift SVN r26125
This commit is contained in:
@@ -242,6 +242,11 @@ swift::classifyDynamicCast(Module *M,
|
||||
source = sourceMetatype.getInstanceType();
|
||||
target = targetMetatype.getInstanceType();
|
||||
|
||||
if (source == target &&
|
||||
targetMetatype.isAnyExistentialType() ==
|
||||
sourceMetatype.isAnyExistentialType())
|
||||
return DynamicCastFeasibility::WillSucceed;
|
||||
|
||||
if (targetMetatype.isAnyExistentialType() && isa<ProtocolType>(target)) {
|
||||
auto Feasibility = classifyDynamicCastToProtocol(source,
|
||||
target,
|
||||
@@ -320,13 +325,34 @@ swift::classifyDynamicCast(Module *M,
|
||||
// FIXME: tuple conversions?
|
||||
|
||||
// Check if there might be a bridging conversion.
|
||||
if (source->isBridgeableObjectType()
|
||||
&& mayBridgeToObjectiveC(M, target)) {
|
||||
if (source->isBridgeableObjectType() && mayBridgeToObjectiveC(M, target)) {
|
||||
// Try to get the ObjC type which is bridged to target type.
|
||||
assert(!target.isAnyExistentialType());
|
||||
Optional<Type> ObjCTy = M->getASTContext().getBridgedToObjC(
|
||||
M, /*inExpression*/ false, target, nullptr);
|
||||
if (ObjCTy) {
|
||||
// If the bridged ObjC type is known, check if
|
||||
// source type can be casted into it.
|
||||
return classifyDynamicCast(M, source,
|
||||
ObjCTy.getValue().getCanonicalTypeOrNull(),
|
||||
/* isSourceTypeExact */ false, isWholeModuleOpts);
|
||||
}
|
||||
return DynamicCastFeasibility::MaySucceed;
|
||||
}
|
||||
|
||||
if (target->isBridgeableObjectType()
|
||||
&& mayBridgeToObjectiveC(M, source)) {
|
||||
if (target->isBridgeableObjectType() && mayBridgeToObjectiveC(M, source)) {
|
||||
// Try to get the ObjC type which is bridged to source type.
|
||||
assert(!source.isAnyExistentialType());
|
||||
Optional<Type> ObjCTy = M->getASTContext().getBridgedToObjC(
|
||||
M, /*inExpression*/ false, source, nullptr);
|
||||
if (ObjCTy) {
|
||||
// If the bridged ObjC type is known, check if
|
||||
// this type can be casted into target type.
|
||||
return classifyDynamicCast(M,
|
||||
ObjCTy.getValue().getCanonicalTypeOrNull(),
|
||||
target,
|
||||
/* isSourceTypeExact */ false, isWholeModuleOpts);
|
||||
}
|
||||
return DynamicCastFeasibility::MaySucceed;
|
||||
}
|
||||
|
||||
|
||||
@@ -742,14 +742,72 @@ func callFooGeneric<T : PP>(c: T) -> Int {
|
||||
|
||||
// Check that the inlined version of callFooGeneric contains only a trap
|
||||
// followed by unreachable and no code afterwards
|
||||
// CHECK-LABEL: sil @_TF12cast_folding16callForGenericCCFCS_2CCT_
|
||||
// CHECK-LABEL: sil [noinline] @_TF12cast_folding16callForGenericCCFCS_2CCT_
|
||||
// CHECK: builtin "int_trap"
|
||||
// CHECK-NEXT: unreachable
|
||||
// CHECK-NEXT: }
|
||||
@inline(never)
|
||||
public func callForGenericCC(c: CC) {
|
||||
callFoo(c)
|
||||
}
|
||||
|
||||
// Check that compiler understands that this cast always succeeds
|
||||
// CHECK-LABEL: sil [noinline] @_TF12cast_folding30testBridgedCastFromObjCtoSwiftFCSo8NSStringSS
|
||||
// CHECK-NOT: cast
|
||||
// CHECK: function_ref @swift_bridgeNonVerbatimFromObjectiveC
|
||||
// CHECK: apply
|
||||
// CHECK: return
|
||||
@inline(never)
|
||||
public func testBridgedCastFromObjCtoSwift(ns: NSString) -> String {
|
||||
return ns as String
|
||||
}
|
||||
|
||||
// Check that compiler understands that this cast always succeeds
|
||||
// CHECK-LABEL: sil [noinline] @_TF12cast_folding30testBridgedCastFromSwiftToObjCFSSCSo8NSString
|
||||
// CHECK-NOT: cast
|
||||
// CHECK: function_ref @_TFE10FoundationSS19_bridgeToObjectiveCfSSFT_CSo8NSString
|
||||
// CHECK: apply
|
||||
// CHECK: return
|
||||
@inline(never)
|
||||
public func testBridgedCastFromSwiftToObjC(s: String) -> NSString {
|
||||
return s as NSString
|
||||
}
|
||||
|
||||
// Check that this cast does not get eliminated, because
|
||||
// the compiler does not statically know if this object
|
||||
// is NSNumber can can be converted into Int.
|
||||
// CHECK-LABEL: sil [noinline] @_TF12cast_folding35testMayBeBridgedCastFromObjCtoSwiftFPSs9AnyObject_Si
|
||||
// CHECK: unconditional_checked_cast_addr
|
||||
// CHECK: return
|
||||
@inline(never)
|
||||
public func testMayBeBridgedCastFromObjCtoSwift(o: AnyObject) -> Int {
|
||||
return o as! Int
|
||||
}
|
||||
|
||||
|
||||
public func castObjCToSwift<T>(t: T) -> Int {
|
||||
return t as! Int
|
||||
}
|
||||
|
||||
// Check that compiler understands that this cast always fails
|
||||
// CHECK-LABEL: sil [noinline] @_TF12cast_folding37testFailingBridgedCastFromObjCtoSwiftFCSo8NSStringSi
|
||||
// CHECK: builtin "int_trap"
|
||||
// CHECK-NEXT: unreachable
|
||||
// CHECK-NEXT: }
|
||||
@inline(never)
|
||||
public func testFailingBridgedCastFromObjCtoSwift(ns: NSString) -> Int {
|
||||
return castObjCToSwift(ns)
|
||||
}
|
||||
|
||||
// Check that compiler understands that this cast always fails
|
||||
// CHECK-LABEL: sil [noinline] @_TF12cast_folding37testFailingBridgedCastFromSwiftToObjCFSSSi
|
||||
// CHECK: builtin "int_trap"
|
||||
// CHECK-NEXT: unreachable
|
||||
// CHECK-NEXT: }
|
||||
@inline(never)
|
||||
public func testFailingBridgedCastFromSwiftToObjC(s: String) -> NSInteger {
|
||||
return s as! NSInteger
|
||||
}
|
||||
|
||||
println("test0=\(test0())")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user