Skip to content

SILGen: Fix bug with bridging peephole #12456

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions lib/SILGen/SILGenConvert.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -695,6 +695,7 @@ ManagedValue SILGenFunction::emitExistentialErasure(
assert(existentialTL.isLoadable());

ManagedValue sub = F(SGFContext());
assert(concreteFormalType->isBridgeableObjectType());
return B.createInitExistentialRef(loc, existentialTL.getLoweredType(),
concreteFormalType, sub, conformances);
}
Expand Down Expand Up @@ -726,6 +727,7 @@ ManagedValue SILGenFunction::emitExistentialErasure(
auto eraseToAnyObject =
[&, concreteFormalType, F](SGFContext C) -> ManagedValue {
auto concreteValue = F(SGFContext());
assert(concreteFormalType->isBridgeableObjectType());
return B.createInitExistentialRef(
loc, SILType::getPrimitiveObjectType(anyObjectTy), concreteFormalType,
concreteValue, {});
Expand Down Expand Up @@ -1231,8 +1233,11 @@ static bool areRelatedTypesForBridgingPeephole(CanType sourceType,

// If the result type is AnyObject, then we can always apply the bridge
// via Any.
if (resultType->isAnyObject())
return true;
if (resultType->isAnyObject()) {
// ... as long as the source type is not an Optional.
if (sourceType->isBridgeableObjectType())
return true;
}

// TODO: maybe other class existentials? Existential conversions?
// They probably aren't important here.
Expand Down
1 change: 1 addition & 0 deletions lib/SILGen/SILGenLValue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -758,6 +758,7 @@ namespace {
base.getType().getObjectType(),
SGF.getASTContext().AllocateCopy(conformances));
} else {
assert(getSubstFormalType()->isBridgeableObjectType());
ref = SGF.B.createInitExistentialRef(
loc,
base.getType().getObjectType(),
Expand Down
145 changes: 145 additions & 0 deletions test/SILGen/objc_bridging_peephole.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ func useOptNS(_ : NSString?) {}
func makeNS() -> NSString { return "help" as NSString }
func makeOptNS() -> NSString? { return nil }

func useAnyObject(_: AnyObject) {}
func useOptAnyObject(_: AnyObject?) {}

/*** Return values ***********************************************************/

// CHECK-LABEL: sil hidden @_T022objc_bridging_peephole16testMethodResultySo10DummyClassC5dummy_tF
Expand Down Expand Up @@ -37,6 +40,35 @@ func testMethodResult(dummy: DummyClass) {
// CHECK-NEXT: apply [[USE]]([[RESULT]])
// CHECK-NEXT: end_borrow [[SELF]] from %0
useOptNS(dummy.fetchNonnullString() as NSString?)

// CHECK: [[USE:%.*]] = function_ref @_T022objc_bridging_peephole15useOptAnyObjectyyXlSgF
// CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
// CHECK-NEXT: [[METHOD:%.*]] = objc_method
// CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
// CHECK-NEXT: [[ANYOBJECT:%.*]] = unchecked_ref_cast [[RESULT]] : $Optional<NSString> to $Optional<AnyObject>
// CHECK-NEXT: apply [[USE]]([[ANYOBJECT]])
// CHECK-NEXT: end_borrow [[SELF]] from %0
useOptAnyObject(dummy.fetchNullableString() as AnyObject?)

// CHECK: [[USE:%.*]] = function_ref @_T022objc_bridging_peephole15useOptAnyObjectyyXlSgF
// CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
// CHECK-NEXT: [[METHOD:%.*]] = objc_method
// CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
// CHECK-NEXT: [[ANYOBJECT:%.*]] = unchecked_ref_cast [[RESULT]] : $Optional<NSString> to $Optional<AnyObject>
// CHECK-NEXT: apply [[USE]]([[ANYOBJECT]])
// CHECK-NEXT: end_borrow [[SELF]] from %0
useOptAnyObject(dummy.fetchNullproneString() as AnyObject?)

// CHECK: [[USE:%.*]] = function_ref @_T022objc_bridging_peephole15useOptAnyObjectyyXlSgF
// CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
// CHECK-NEXT: [[METHOD:%.*]] = objc_method
// CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
// CHECK-NEXT: [[ANYOBJECT:%.*]] = unchecked_ref_cast [[RESULT]] : $Optional<NSString> to $Optional<AnyObject>
// CHECK-NEXT: apply [[USE]]([[ANYOBJECT]])
// CHECK-NEXT: end_borrow [[SELF]] from %0
useOptAnyObject(dummy.fetchNonnullString() as AnyObject?)

// CHECK: return
}

// CHECK-LABEL: sil hidden @_T022objc_bridging_peephole23testNonNullMethodResultySo10DummyClassC5dummy_tF
Expand All @@ -52,6 +84,21 @@ func testNonNullMethodResult(dummy: DummyClass) {
// CHECK-NEXT: apply [[USE]]([[RESULT]])
// CHECK-NEXT: end_borrow [[SELF]] from %0
useNS(dummy.fetchNonnullString() as NSString)

// CHECK: [[USE:%.*]] = function_ref @_T022objc_bridging_peephole12useAnyObjectyyXlF
// CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
// CHECK-NEXT: [[METHOD:%.*]] = objc_method
// CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
// CHECK-NEXT: switch_enum [[RESULT]]
// CHECK: bb3:
// CHECK: function_ref @_T0s30_diagnoseUnexpectedNilOptionalyBp14_filenameStart_Bw01_E6LengthBi1_01_E7IsASCIIBw5_linetF
// CHECK: bb4([[RESULT:%.*]] : @owned $NSString):
// CHECK-NEXT: [[ANYOBJECT:%.*]] = init_existential_ref [[RESULT]] : $NSString : $NSString, $AnyObject
// CHECK-NEXT: apply [[USE]]([[ANYOBJECT]])
// CHECK-NEXT: end_borrow [[SELF]] from %0
useAnyObject(dummy.fetchNonnullString() as AnyObject)

// CHECK: return
}

// CHECK-LABEL: sil hidden @_T022objc_bridging_peephole22testForcedMethodResultySo10DummyClassC5dummy_tF
Expand All @@ -67,6 +114,21 @@ func testForcedMethodResult(dummy: DummyClass) {
// CHECK-NEXT: apply [[USE]]([[RESULT]])
// CHECK-NEXT: end_borrow [[SELF]] from %0
useNS(dummy.fetchNullproneString() as NSString)

// CHECK: [[USE:%.*]] = function_ref @_T022objc_bridging_peephole12useAnyObjectyyXlF
// CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
// CHECK-NEXT: [[METHOD:%.*]] = objc_method
// CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
// CHECK-NEXT: switch_enum [[RESULT]]
// CHECK: bb3:
// CHECK: function_ref @_T0s30_diagnoseUnexpectedNilOptionalyBp14_filenameStart_Bw01_E6LengthBi1_01_E7IsASCIIBw5_linetF
// CHECK: bb4([[RESULT:%.*]] : @owned $NSString):
// CHECK-NEXT: [[ANYOBJECT:%.*]] = init_existential_ref [[RESULT]] : $NSString : $NSString, $AnyObject
// CHECK-NEXT: apply [[USE]]([[ANYOBJECT]])
// CHECK-NEXT: end_borrow [[SELF]] from %0
useAnyObject(dummy.fetchNullproneString() as AnyObject)

// CHECK: return
}

/*** Property loads **********************************************************/
Expand Down Expand Up @@ -96,6 +158,35 @@ func testPropertyValue(dummy: DummyClass) {
// CHECK-NEXT: apply [[USE]]([[RESULT]])
// CHECK-NEXT: end_borrow [[SELF]] from %0
useOptNS(dummy.nonnullStringProperty as NSString?)

// CHECK: [[USE:%.*]] = function_ref @_T022objc_bridging_peephole15useOptAnyObjectyyXlSgF
// CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
// CHECK-NEXT: [[METHOD:%.*]] = objc_method
// CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
// CHECK-NEXT: [[ANYOBJECT:%.*]] = unchecked_ref_cast [[RESULT]] : $Optional<NSString> to $Optional<AnyObject>
// CHECK-NEXT: apply [[USE]]([[ANYOBJECT]])
// CHECK-NEXT: end_borrow [[SELF]] from %0
useOptAnyObject(dummy.nullableStringProperty as AnyObject?)

// CHECK: [[USE:%.*]] = function_ref @_T022objc_bridging_peephole15useOptAnyObjectyyXlSgF
// CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
// CHECK-NEXT: [[METHOD:%.*]] = objc_method
// CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
// CHECK-NEXT: [[ANYOBJECT:%.*]] = unchecked_ref_cast [[RESULT]] : $Optional<NSString> to $Optional<AnyObject>
// CHECK-NEXT: apply [[USE]]([[ANYOBJECT]])
// CHECK-NEXT: end_borrow [[SELF]] from %0
useOptAnyObject(dummy.nullproneStringProperty as AnyObject?)

// CHECK: [[USE:%.*]] = function_ref @_T022objc_bridging_peephole15useOptAnyObjectyyXlSgF
// CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
// CHECK-NEXT: [[METHOD:%.*]] = objc_method
// CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
// CHECK-NEXT: [[ANYOBJECT:%.*]] = unchecked_ref_cast [[RESULT]] : $Optional<NSString> to $Optional<AnyObject>
// CHECK-NEXT: apply [[USE]]([[ANYOBJECT]])
// CHECK-NEXT: end_borrow [[SELF]] from %0
useOptAnyObject(dummy.nonnullStringProperty as AnyObject?)

// CHECK: return
}

// CHECK-LABEL: sil hidden @_T022objc_bridging_peephole24testNonNullPropertyValueySo10DummyClassC5dummy_tF
Expand All @@ -111,6 +202,21 @@ func testNonNullPropertyValue(dummy: DummyClass) {
// CHECK-NEXT: apply [[USE]]([[RESULT]])
// CHECK-NEXT: end_borrow [[SELF]] from %0
useNS(dummy.nonnullStringProperty as NSString)

// CHECK: [[USE:%.*]] = function_ref @_T022objc_bridging_peephole12useAnyObjectyyXlF
// CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
// CHECK-NEXT: [[METHOD:%.*]] = objc_method
// CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
// CHECK-NEXT: switch_enum [[RESULT]]
// CHECK: bb3:
// CHECK: function_ref @_T0s30_diagnoseUnexpectedNilOptionalyBp14_filenameStart_Bw01_E6LengthBi1_01_E7IsASCIIBw5_linetF
// CHECK: bb4([[RESULT:%.*]] : @owned $NSString):
// CHECK-NEXT: [[ANYOBJECT:%.*]] = init_existential_ref [[RESULT]] : $NSString : $NSString, $AnyObject
// CHECK-NEXT: apply [[USE]]([[ANYOBJECT]])
// CHECK-NEXT: end_borrow [[SELF]] from %0
useAnyObject(dummy.nonnullStringProperty as AnyObject)

// CHECK: return
}

// CHECK-LABEL: sil hidden @_T022objc_bridging_peephole23testForcedPropertyValueySo10DummyClassC5dummy_tF
Expand All @@ -126,6 +232,21 @@ func testForcedPropertyValue(dummy: DummyClass) {
// CHECK-NEXT: apply [[USE]]([[RESULT]])
// CHECK-NEXT: end_borrow [[SELF]] from %0
useNS(dummy.nullproneStringProperty as NSString)

// CHECK: [[USE:%.*]] = function_ref @_T022objc_bridging_peephole12useAnyObjectyyXlF
// CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
// CHECK-NEXT: [[METHOD:%.*]] = objc_method
// CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
// CHECK-NEXT: switch_enum [[RESULT]]
// CHECK: bb3:
// CHECK: function_ref @_T0s30_diagnoseUnexpectedNilOptionalyBp14_filenameStart_Bw01_E6LengthBi1_01_E7IsASCIIBw5_linetF
// CHECK: bb4([[RESULT:%.*]] : @owned $NSString):
// CHECK-NEXT: [[ANYOBJECT:%.*]] = init_existential_ref [[RESULT]] : $NSString : $NSString, $AnyObject
// CHECK-NEXT: apply [[USE]]([[ANYOBJECT]])
// CHECK-NEXT: end_borrow [[SELF]] from %0
useAnyObject(dummy.nullproneStringProperty as AnyObject)

// CHECK: return
}

/*** Subscript loads *********************************************************/
Expand Down Expand Up @@ -158,6 +279,8 @@ func testNonnullSubscriptGet(object: NonnullSubscript, index: AnyObject) {
// CHECK-NEXT: apply [[USE]]([[RESULT]])
// CHECK: end_borrow [[SELF]] from %0
useNS(object[index] as NSString)

// CHECK: return
}

// CHECK-LABEL: sil hidden @_T022objc_bridging_peephole24testNullableSubscriptGetySo0eF0C6object_yXl5indextF
Expand All @@ -172,6 +295,8 @@ func testNullableSubscriptGet(object: NullableSubscript, index: AnyObject) {
// CHECK-NEXT: apply [[USE]]([[RESULT]])
// CHECK: end_borrow [[SELF]] from %0
useOptNS(object[index] as NSString?)

// CHECK: return
}

// CHECK-LABEL: sil hidden @_T022objc_bridging_peephole25testNullproneSubscriptGetySo0eF0C6object_yXl5indextF
Expand Down Expand Up @@ -200,6 +325,8 @@ func testNullproneSubscriptGet(object: NullproneSubscript, index: AnyObject) {
// CHECK-NEXT: apply [[USE]]([[RESULT]])
// CHECK: end_borrow [[SELF]] from %0
useNS(object[index] as NSString)

// CHECK: return
}

/*** Call arguments **********************************************************/
Expand Down Expand Up @@ -237,6 +364,8 @@ func testMethodArgument(dummy: DummyClass) {
// CHECK-NEXT: destroy_value [[OPTARG]]
// CHECK-NEXT: end_borrow [[SELF]] from %0
dummy.takeNullproneString(makeNS() as String)

// CHECK: return
}

// CHECK-LABEL: sil hidden @_T022objc_bridging_peephole28testValueToOptMethodArgumentySo10DummyClassC5dummy_tF
Expand All @@ -262,6 +391,8 @@ func testValueToOptMethodArgument(dummy: DummyClass) {
// CHECK-NEXT: destroy_value [[OPTARG]]
// CHECK-NEXT: end_borrow [[SELF]] from %0
dummy.takeNullproneString(makeNS() as String?)

// CHECK: return
}

// CHECK-LABEL: sil hidden @_T022objc_bridging_peephole09testOptToE14MethodArgumentySo10DummyClassC5dummy_tF
Expand All @@ -285,6 +416,8 @@ func testOptToOptMethodArgument(dummy: DummyClass) {
// CHECK-NEXT: destroy_value [[ARG]]
// CHECK-NEXT: end_borrow [[SELF]] from %0
dummy.takeNullproneString(makeOptNS() as String?)

// CHECK: return
}

/*** Property assignments ****************************************************/
Expand Down Expand Up @@ -322,6 +455,8 @@ func testPropertySetter(dummy: DummyClass) {
// CHECK-NEXT: destroy_value [[OPTARG]]
// CHECK-NEXT: end_borrow [[SELF]] from %0
dummy.nullproneStringProperty = makeNS() as String

// CHECK: return
}

// CHECK-LABEL: sil hidden @_T022objc_bridging_peephole28testValueToOptPropertySetterySo10DummyClassC5dummy_tF
Expand All @@ -347,6 +482,8 @@ func testValueToOptPropertySetter(dummy: DummyClass) {
// CHECK-NEXT: destroy_value [[OPTARG]]
// CHECK-NEXT: end_borrow [[SELF]] from %0
dummy.nullproneStringProperty = makeNS() as String?

// CHECK: return
}

// CHECK-LABEL: sil hidden @_T022objc_bridging_peephole09testOptToE14PropertySetterySo10DummyClassC5dummy_tF
Expand All @@ -370,6 +507,8 @@ func testOptToOptPropertySetter(dummy: DummyClass) {
// CHECK-NEXT: destroy_value [[ARG]]
// CHECK-NEXT: end_borrow [[SELF]] from %0
dummy.nullproneStringProperty = makeOptNS() as String?

// CHECK: return
}

/*** Subscript assignments ***************************************************/
Expand All @@ -389,6 +528,8 @@ func testNonnullSubscriptSet(object: NonnullSubscript, index: AnyObject) {
// CHECK: destroy_value [[ARG]]
// CHECK: end_borrow [[SELF]] from %0
object[index] = makeNS() as String

// CHECK: return
}

// CHECK-LABEL: sil hidden @_T022objc_bridging_peephole24testNullableSubscriptSetySo0eF0C6object_yXl5indextF
Expand Down Expand Up @@ -430,6 +571,8 @@ func testNullableSubscriptSet(object: NullableSubscript, index: AnyObject) {
// CHECK: destroy_value [[ARG]]
// CHECK: end_borrow [[SELF]] from %0
object[index] = makeOptNS() as String?

// CHECK: return
}

// CHECK-LABEL: sil hidden @_T022objc_bridging_peephole25testNullproneSubscriptSetySo0eF0C6object_yXl5indextF
Expand Down Expand Up @@ -471,6 +614,8 @@ func testNullproneSubscriptSet(object: NullproneSubscript, index: AnyObject) {
// CHECK: destroy_value [[ARG]]
// CHECK: end_borrow [[SELF]] from %0
object[index] = makeOptNS() as String?

// CHECK: return
}

/*** Bugfixes ***************************************************************/
Expand Down