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();
|
source = sourceMetatype.getInstanceType();
|
||||||
target = targetMetatype.getInstanceType();
|
target = targetMetatype.getInstanceType();
|
||||||
|
|
||||||
|
if (source == target &&
|
||||||
|
targetMetatype.isAnyExistentialType() ==
|
||||||
|
sourceMetatype.isAnyExistentialType())
|
||||||
|
return DynamicCastFeasibility::WillSucceed;
|
||||||
|
|
||||||
if (targetMetatype.isAnyExistentialType() && isa<ProtocolType>(target)) {
|
if (targetMetatype.isAnyExistentialType() && isa<ProtocolType>(target)) {
|
||||||
auto Feasibility = classifyDynamicCastToProtocol(source,
|
auto Feasibility = classifyDynamicCastToProtocol(source,
|
||||||
target,
|
target,
|
||||||
@@ -320,13 +325,34 @@ swift::classifyDynamicCast(Module *M,
|
|||||||
// FIXME: tuple conversions?
|
// FIXME: tuple conversions?
|
||||||
|
|
||||||
// Check if there might be a bridging conversion.
|
// Check if there might be a bridging conversion.
|
||||||
if (source->isBridgeableObjectType()
|
if (source->isBridgeableObjectType() && mayBridgeToObjectiveC(M, target)) {
|
||||||
&& 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;
|
return DynamicCastFeasibility::MaySucceed;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (target->isBridgeableObjectType()
|
if (target->isBridgeableObjectType() && mayBridgeToObjectiveC(M, source)) {
|
||||||
&& 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;
|
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
|
// Check that the inlined version of callFooGeneric contains only a trap
|
||||||
// followed by unreachable and no code afterwards
|
// 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: builtin "int_trap"
|
||||||
// CHECK-NEXT: unreachable
|
// CHECK-NEXT: unreachable
|
||||||
// CHECK-NEXT: }
|
// CHECK-NEXT: }
|
||||||
|
@inline(never)
|
||||||
public func callForGenericCC(c: CC) {
|
public func callForGenericCC(c: CC) {
|
||||||
callFoo(c)
|
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())")
|
println("test0=\(test0())")
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user