Skip to content

Commit 1d90b04

Browse files
committed
Really reinstate "[SILGen] Implement NSString -> String bridging through _ObjectiveCBridgeable."
This reverts commit 052d2d0. The only actual issue with the original change was a missing change to the UIApplicationMain SILGen test, which needs to build SILGen overlays to execute properly; -enable-source-import doesn't suffice.
1 parent 052d2d0 commit 1d90b04

File tree

16 files changed

+418
-63
lines changed

16 files changed

+418
-63
lines changed

lib/AST/Type.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -798,9 +798,9 @@ Type TypeBase::replaceCovariantResultType(Type newResultType,
798798
bool preserveOptionality) {
799799
if (uncurryLevel == 0) {
800800
if (preserveOptionality) {
801-
assert(!newResultType->getAnyOptionalObjectType());
802801
OptionalTypeKind resultOTK;
803802
if (auto objectType = getAnyOptionalObjectType(resultOTK)) {
803+
assert(!newResultType->getAnyOptionalObjectType());
804804
return OptionalType::get(
805805
resultOTK,
806806
objectType->replaceCovariantResultType(

lib/SILGen/SILGen.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,37 @@ FuncDecl *SILGenModule::getBridgeToObjectiveCRequirement(SILLocation loc) {
203203
return found;
204204
}
205205

206+
FuncDecl *SILGenModule::getUnconditionallyBridgeFromObjectiveCRequirement(
207+
SILLocation loc) {
208+
if (UnconditionallyBridgeFromObjectiveCRequirement)
209+
return *UnconditionallyBridgeFromObjectiveCRequirement;
210+
211+
// Find the _ObjectiveCBridgeable protocol.
212+
auto proto = getObjectiveCBridgeable(loc);
213+
if (!proto) {
214+
UnconditionallyBridgeFromObjectiveCRequirement = nullptr;
215+
return nullptr;
216+
}
217+
218+
// Look for _bridgeToObjectiveC().
219+
auto &ctx = getASTContext();
220+
FuncDecl *found = nullptr;
221+
DeclName name(ctx, ctx.getIdentifier("_unconditionallyBridgeFromObjectiveC"),
222+
llvm::makeArrayRef(Identifier()));
223+
for (auto member : proto->lookupDirect(name, true)) {
224+
if (auto func = dyn_cast<FuncDecl>(member)) {
225+
found = func;
226+
break;
227+
}
228+
}
229+
230+
if (!found)
231+
diagnose(loc, diag::bridging_objcbridgeable_broken, name);
232+
233+
UnconditionallyBridgeFromObjectiveCRequirement = found;
234+
return found;
235+
}
236+
206237
AssociatedTypeDecl *
207238
SILGenModule::getBridgedObjectiveCTypeRequirement(SILLocation loc) {
208239
if (BridgedObjectiveCType)

lib/SILGen/SILGen.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ class LLVM_LIBRARY_VISIBILITY SILGenModule : public ASTVisitor<SILGenModule> {
126126

127127
Optional<ProtocolDecl*> ObjectiveCBridgeable;
128128
Optional<FuncDecl*> BridgeToObjectiveCRequirement;
129+
Optional<FuncDecl*> UnconditionallyBridgeFromObjectiveCRequirement;
129130
Optional<AssociatedTypeDecl*> BridgedObjectiveCType;
130131

131132
public:
@@ -358,6 +359,11 @@ class LLVM_LIBRARY_VISIBILITY SILGenModule : public ASTVisitor<SILGenModule> {
358359
/// Retrieve the _ObjectiveCBridgeable._bridgeToObjectiveC requirement.
359360
FuncDecl *getBridgeToObjectiveCRequirement(SILLocation loc);
360361

362+
/// Retrieve the
363+
/// _ObjectiveCBridgeable._unconditionallyBridgeFromObjectiveC
364+
/// requirement.
365+
FuncDecl *getUnconditionallyBridgeFromObjectiveCRequirement(SILLocation loc);
366+
361367
/// Retrieve the _ObjectiveCBridgeable._ObjectiveCType requirement.
362368
AssociatedTypeDecl *getBridgedObjectiveCTypeRequirement(SILLocation loc);
363369

lib/SILGen/SILGenBridging.cpp

Lines changed: 88 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,10 @@ using namespace Lowering;
2828
/// object, using the appropriate witness for the
2929
/// _ObjectiveCBridgeable._bridgeToObjectiveC requirement.
3030
static Optional<ManagedValue>
31-
emitBridgeToObjectiveC(SILGenFunction &gen,
32-
SILLocation loc,
33-
ManagedValue swiftValue,
34-
ProtocolConformance *conformance) {
31+
emitBridgeNativeToObjectiveC(SILGenFunction &gen,
32+
SILLocation loc,
33+
ManagedValue swiftValue,
34+
ProtocolConformance *conformance) {
3535
// Dig out the nominal type we're bridging from.
3636
Type swiftValueType = swiftValue.getSwiftType()->getRValueType();
3737

@@ -80,9 +80,10 @@ emitBridgeToObjectiveC(SILGenFunction &gen,
8080
/// Bridge the given Swift value to its corresponding Objective-C
8181
/// object, using the appropriate witness for the
8282
/// _ObjectiveCBridgeable._bridgeToObjectiveC requirement.
83-
static Optional<ManagedValue> emitBridgeToObjectiveC(SILGenFunction &gen,
84-
SILLocation loc,
85-
ManagedValue swiftValue) {
83+
static Optional<ManagedValue>
84+
emitBridgeNativeToObjectiveC(SILGenFunction &gen,
85+
SILLocation loc,
86+
ManagedValue swiftValue) {
8687
// Dig out the nominal type we're bridging from.
8788
Type swiftValueType = swiftValue.getSwiftType()->getRValueType();
8889

@@ -91,7 +92,7 @@ static Optional<ManagedValue> emitBridgeToObjectiveC(SILGenFunction &gen,
9192
gen.SGM.getConformanceToObjectiveCBridgeable(loc, swiftValueType);
9293
if (!conformance) return None;
9394

94-
return emitBridgeToObjectiveC(gen, loc, swiftValue, conformance);
95+
return emitBridgeNativeToObjectiveC(gen, loc, swiftValue, conformance);
9596
}
9697

9798
static ManagedValue emitBridgeStringToNSString(SILGenFunction &gen,
@@ -100,26 +101,80 @@ static ManagedValue emitBridgeStringToNSString(SILGenFunction &gen,
100101
llvm_unreachable("Handled via the _bridgeToObjectiveC witness");
101102
}
102103

103-
static ManagedValue emitBridgeNSStringToString(SILGenFunction &gen,
104-
SILLocation loc,
105-
ManagedValue nsstr) {
106-
SILValue bridgeFn =
107-
gen.emitGlobalFunctionRef(loc, gen.SGM.getNSStringToStringFn());
104+
/// Bridge the given Objective-C object to its corresponding Swift
105+
/// value, using the appropriate witness for the
106+
/// _ObjectiveCBridgeable._unconditionallyBridgeFromObjectiveC requirement.
107+
static Optional<ManagedValue>
108+
emitBridgeObjectiveCToNative(SILGenFunction &gen,
109+
SILLocation loc,
110+
ManagedValue objcValue,
111+
ProtocolConformance *conformance) {
112+
// Find the _unconditionallyBridgeFromObjectiveC requirement.
113+
auto requirement =
114+
gen.SGM.getUnconditionallyBridgeFromObjectiveCRequirement(loc);
115+
if (!requirement) return None;
108116

109-
Type inputType = nsstr.getType().getSwiftRValueType();
110-
if (!inputType->getOptionalObjectType()) {
111-
SILType loweredOptTy = gen.SGM.getLoweredType(OptionalType::get(inputType));
117+
// Retrieve the _unconditionallyBridgeFromObjectiveC witness.
118+
auto witness = conformance->getWitness(requirement, nullptr);
119+
assert(witness);
120+
121+
// Create a reference to the witness.
122+
SILDeclRef witnessConstant(witness.getDecl());
123+
auto witnessRef = gen.emitGlobalFunctionRef(loc, witnessConstant);
124+
125+
// Determine the substitutions.
126+
ArrayRef<Substitution> substitutions;
127+
auto witnessFnTy = witnessRef->getType().castTo<SILFunctionType>();
128+
129+
Type swiftValueType = conformance->getType();
130+
if (auto valueTypeBGT = swiftValueType->getAs<BoundGenericType>()) {
131+
// Compute the substitutions.
132+
substitutions = valueTypeBGT->getSubstitutions(gen.SGM.SwiftModule,
133+
nullptr);
134+
}
135+
136+
// Substitute into the witness function type.
137+
if (!substitutions.empty())
138+
witnessFnTy = witnessFnTy->substGenericArgs(gen.SGM.M, gen.SGM.SwiftModule,
139+
substitutions);
140+
141+
// If the Objective-C value isn't optional, wrap it in an optional.
142+
Type objcValueType = objcValue.getType().getSwiftRValueType();
143+
if (!objcValueType->getOptionalObjectType()) {
144+
SILType loweredOptTy =
145+
gen.SGM.getLoweredType(OptionalType::get(objcValueType));
112146
auto *someDecl = gen.getASTContext().getOptionalSomeDecl();
113-
auto *enumInst = gen.B.createEnum(loc, nsstr.getValue(), someDecl,
147+
auto *enumInst = gen.B.createEnum(loc, objcValue.getValue(), someDecl,
114148
loweredOptTy);
115-
nsstr = ManagedValue(enumInst, nsstr.getCleanup());
149+
objcValue = ManagedValue(enumInst, objcValue.getCleanup());
116150
}
117151

118-
SILType nativeTy = gen.getLoweredType(gen.SGM.Types.getStringType());
119-
SILValue str = gen.B.createApply(loc, bridgeFn, bridgeFn->getType(), nativeTy,
120-
{}, { nsstr.forward(gen) });
121-
122-
return gen.emitManagedRValueWithCleanup(str);
152+
// Call the witness.
153+
Type metatype = MetatypeType::get(swiftValueType);
154+
SILValue metatypeValue = gen.B.createMetatype(loc,
155+
gen.getLoweredType(metatype));
156+
157+
auto witnessCI = gen.getConstantInfo(witnessConstant);
158+
CanType formalResultTy = witnessCI.LoweredInterfaceType.getResult();
159+
160+
// Set up the generic signature.
161+
CanGenericSignature witnessGenericSignature;
162+
if (auto genericSig =
163+
cast<AbstractFunctionDecl>(witness.getDecl())->getGenericSignature())
164+
witnessGenericSignature = genericSig->getCanonicalSignature();
165+
166+
GenericContextScope genericContextScope(gen.SGM.Types,
167+
witnessGenericSignature);
168+
return gen.emitApply(loc, ManagedValue::forUnmanaged(witnessRef),
169+
substitutions,
170+
{ objcValue, ManagedValue::forUnmanaged(metatypeValue) },
171+
witnessFnTy,
172+
AbstractionPattern(witnessGenericSignature,
173+
formalResultTy),
174+
swiftValueType->getCanonicalType(),
175+
ApplyOptions::None, None, None,
176+
SGFContext())
177+
.getAsSingleValue(gen, loc);
123178
}
124179

125180
static ManagedValue emitBridgeCollectionToNative(SILGenFunction &gen,
@@ -376,7 +431,7 @@ static ManagedValue emitNativeToCBridgedNonoptionalValue(SILGenFunction &gen,
376431
// hardcoding String -> NSString.
377432
if (loweredNativeTy == gen.SGM.Types.getStringType()
378433
&& loweredBridgedTy == gen.SGM.Types.getNSStringType()) {
379-
if (auto result = emitBridgeToObjectiveC(gen, loc, v))
434+
if (auto result = emitBridgeNativeToObjectiveC(gen, loc, v))
380435
return *result;
381436

382437
return gen.emitUndef(loc, bridgedTy);
@@ -413,7 +468,7 @@ static ManagedValue emitNativeToCBridgedNonoptionalValue(SILGenFunction &gen,
413468
// _bridgeToObjectiveC witness.
414469
if (auto conformance =
415470
gen.SGM.getConformanceToObjectiveCBridgeable(loc, loweredNativeTy)) {
416-
if (auto result = emitBridgeToObjectiveC(gen, loc, v, conformance))
471+
if (auto result = emitBridgeNativeToObjectiveC(gen, loc, v, conformance))
417472
return *result;
418473

419474
return gen.emitUndef(loc, bridgedTy);
@@ -607,7 +662,14 @@ static ManagedValue emitCBridgedToNativeValue(SILGenFunction &gen,
607662
// Bridge NSString to String.
608663
if (auto stringDecl = gen.getASTContext().getStringDecl()) {
609664
if (nativeTy.getSwiftRValueType()->getAnyNominal() == stringDecl) {
610-
return emitBridgeNSStringToString(gen, loc, v);
665+
auto conformance =
666+
gen.SGM.getConformanceToObjectiveCBridgeable(loc, loweredNativeTy);
667+
assert(conformance &&
668+
"Missing String conformation to _ObjectiveCBridgeable?");
669+
if (auto result = emitBridgeObjectiveCToNative(gen, loc, v, conformance))
670+
return *result;
671+
672+
return gen.emitUndef(loc, nativeTy);
611673
}
612674
}
613675

lib/Sema/CSApply.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1276,9 +1276,11 @@ namespace {
12761276
// Find the conformance of the value type to _BridgedToObjectiveC.
12771277
Type valueType = value->getType()->getRValueType();
12781278
ProtocolConformance *conformance = nullptr;
1279-
bool conforms = tc.conformsToProtocol(valueType, bridgedProto, cs.DC,
1280-
ConformanceCheckFlags::InExpression,
1281-
&conformance);
1279+
bool conforms =
1280+
tc.conformsToProtocol(valueType, bridgedProto, cs.DC,
1281+
(ConformanceCheckFlags::InExpression|
1282+
ConformanceCheckFlags::Used),
1283+
&conformance);
12821284
assert(conforms && "Should already have checked the conformance");
12831285
(void)conforms;
12841286

@@ -1318,7 +1320,8 @@ namespace {
13181320
= tc.conformsToProtocol(valueType,
13191321
bridgedProto,
13201322
cs.DC,
1321-
ConformanceCheckFlags::InExpression,
1323+
(ConformanceCheckFlags::InExpression|
1324+
ConformanceCheckFlags::Used),
13221325
&conformance);
13231326

13241327
FuncDecl *fn = nullptr;

0 commit comments

Comments
 (0)