Skip to content

Commit eac994b

Browse files
committed
[Definite initialization] Recognize delegation to a C function imported as an initializer.
Add yet one more flavor of hack to DI to recognize where we are delegating the initialization of 'self'. The existing hack in this area (for Objective-C factory initializers) is based on recognizing the value_metatype instruction that feeds into the application of the factory initializer. C functions imported as initializers don't have a metatype argument, so instead tag the assignment into the self box as the initialization of self. As a minor cleanup in this area, don't emit the dead value_metatype instruction when invoking a C-imported factory initializer.
1 parent 5f04b8c commit eac994b

File tree

4 files changed

+35
-6
lines changed

4 files changed

+35
-6
lines changed

lib/SILGen/SILGenApply.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1372,7 +1372,7 @@ class SILGenApply : public Lowering::ExprVisitor<SILGenApply> {
13721372
auto nominal = ctorRef->getDecl()->getDeclContext()
13731373
->getAsNominalTypeOrNominalTypeExtensionContext();
13741374
bool useAllocatingCtor;
1375-
1375+
13761376
// Value types only have allocating initializers.
13771377
if (isa<StructDecl>(nominal) || isa<EnumDecl>(nominal))
13781378
useAllocatingCtor = true;
@@ -1406,7 +1406,11 @@ class SILGenApply : public Lowering::ExprVisitor<SILGenApply> {
14061406
selfFormalType = CanMetatypeType::get(
14071407
selfFormalType->getInOutObjectType()->getCanonicalType());
14081408

1409-
if (SGF.AllocatorMetatype)
1409+
// If the initializer is a C function imported as a member,
1410+
// there is no 'self' parameter. Mark it undef.
1411+
if (ctorRef->getDecl()->isImportAsMember())
1412+
self = SGF.emitUndef(expr, selfFormalType);
1413+
else if (SGF.AllocatorMetatype)
14101414
self = emitCorrespondingSelfValue(
14111415
ManagedValue::forUnmanaged(SGF.AllocatorMetatype),
14121416
arg);

lib/SILOptimizer/Mandatory/DIMemoryUseCollector.cpp

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1279,11 +1279,23 @@ void ElementUseCollector::collectDelegatingClassInitSelfUses() {
12791279
if (isa<StoreInst>(User) && UI->getOperandNumber() == 1)
12801280
continue;
12811281

1282-
// For class initializers, the assign into the self box is captured as
1283-
// a SelfInit or SuperInit elsewhere.
1282+
// For class initializers, the assign into the self box may be
1283+
// captured as SelfInit or SuperInit elsewhere.
12841284
if (TheMemory.isClassInitSelf() &&
1285-
isa<AssignInst>(User) && UI->getOperandNumber() == 1)
1285+
isa<AssignInst>(User) && UI->getOperandNumber() == 1) {
1286+
// If the source of the assignment is an application of a C
1287+
// function, there is no metatype argument, so treat the
1288+
// assignment to the self box as the initialization.
1289+
if (auto apply = dyn_cast<ApplyInst>(cast<AssignInst>(User)->getSrc())) {
1290+
if (auto fn = apply->getCalleeFunction()) {
1291+
if (fn->getRepresentation()
1292+
== SILFunctionTypeRepresentation::CFunctionPointer)
1293+
Uses.push_back(DIMemoryUse(User, DIUseKind::SelfInit, 0, 1));
1294+
}
1295+
}
1296+
12861297
continue;
1298+
}
12871299

12881300
// Stores *to* the allocation are writes. If the value being stored is a
12891301
// call to self.init()... then we have a self.init call.

test/SILGen/import_as_member.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ public func useClass(d: Double, opts: SomeClass.Options) {
3939
extension SomeClass {
4040
// SIL-LABEL: sil hidden @_TFE16import_as_memberCSo9SomeClasscfT6doubleSd_S0_
4141
// SIL: bb0([[DOUBLE:%[0-9]+]] : $Double
42+
// SIL-NOT: value_metatype
4243
// SIL: [[FNREF:%[0-9]+]] = function_ref @MakeIAMSomeClass
4344
// SIL: apply [[FNREF]]([[DOUBLE]])
4445
convenience init(double: Double) {

test/SILOptimizer/definite_init_objc_factory_init.swift

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) %s -emit-sil | FileCheck %s
1+
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -I %S/../IDE/Inputs/custom-modules %s -emit-sil | FileCheck %s
22

33
// REQUIRES: objc_interop
44

55
import Foundation
6+
import ImportAsMember.Class
67

78
// CHECK-LABEL: sil shared [thunk] @_TTOFCSo4HiveCfT5queenGSQCSo3Bee__GSQS__ : $@convention(thin) (@owned ImplicitlyUnwrappedOptional<Bee>, @thick Hive.Type) -> @owned ImplicitlyUnwrappedOptional<Hive>
89
func testInstanceTypeFactoryMethod(queen: Bee) {
@@ -39,3 +40,14 @@ extension Hive {
3940
try self.init(flakyQueen: other)
4041
}
4142
}
43+
44+
extension SomeClass {
45+
// SIL-LABEL: sil hidden @_TFE16import_as_memberCSo9SomeClasscfT6doubleSd_S0_
46+
// SIL: bb0([[DOUBLE:%[0-9]+]] : $Double
47+
// SIL-NOT: value_metatype
48+
// SIL: [[FNREF:%[0-9]+]] = function_ref @MakeIAMSomeClass
49+
// SIL: apply [[FNREF]]([[DOUBLE]])
50+
convenience init(double: Double) {
51+
self.init(value: double)
52+
}
53+
}

0 commit comments

Comments
 (0)