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:
Roman Levenstein
2015-03-14 02:23:07 +00:00
parent 8ffdfd59c8
commit eddfc3c57a
2 changed files with 89 additions and 5 deletions

View File

@@ -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;
}

View File

@@ -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())")