Skip to content

Commit 1f6ffa6

Browse files
authored
Merge pull request swiftlang#24325 from slavapestov/alloc-ref-dynamic-fix
SILGen: Allocating entry points for @objc dynamic inits should use alloc_ref_dynamic
2 parents c09f84d + 1f37941 commit 1f6ffa6

File tree

5 files changed

+69
-45
lines changed

5 files changed

+69
-45
lines changed

lib/SILGen/SILGenApply.cpp

Lines changed: 11 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1019,6 +1019,12 @@ class SILGenApply : public Lowering::ExprVisitor<SILGenApply> {
10191019
if (!ctor->isRequired())
10201020
return false;
10211021

1022+
// @objc dynamic initializers are statically dispatched (we're
1023+
// calling the allocating entry point, which is a thunk that
1024+
// does the dynamic dispatch for us).
1025+
if (ctor->isObjCDynamic())
1026+
return false;
1027+
10221028
// Required constructors are statically dispatched when the 'self'
10231029
// value is statically derived.
10241030
ApplyExpr *thisCallSite = callSites.back();
@@ -1032,64 +1038,32 @@ class SILGenApply : public Lowering::ExprVisitor<SILGenApply> {
10321038
}
10331039

10341040
void processClassMethod(DeclRefExpr *e, AbstractFunctionDecl *afd) {
1035-
SILDeclRef::Kind kind;
1036-
bool requiresAllocRefDynamic = false;
1037-
1038-
if (isa<FuncDecl>(afd)) {
1039-
kind = SILDeclRef::Kind::Func;
1040-
} else {
1041-
if (requiresForeignEntryPoint(afd)) {
1042-
// When we're performing Objective-C dispatch, we don't have an
1043-
// allocating constructor to call. So, perform an alloc_ref_dynamic
1044-
// and pass that along to the initializer.
1045-
requiresAllocRefDynamic = true;
1046-
kind = SILDeclRef::Kind::Initializer;
1047-
} else {
1048-
kind = SILDeclRef::Kind::Allocator;
1049-
}
1050-
}
1051-
10521041
ApplyExpr *thisCallSite = callSites.back();
10531042
callSites.pop_back();
10541043

1055-
// If we require a dynamic allocation of the object here, do so now.
1056-
if (requiresAllocRefDynamic) {
1057-
SILLocation loc = thisCallSite->getArg();
1058-
RValue selfMetatype = SGF.emitRValue(thisCallSite->getArg());
1059-
auto selfValue =
1060-
allocateObject(std::move(selfMetatype).getAsSingleValue(SGF, loc),
1061-
loc, /*objc*/ true);
1062-
RValue self = RValue(SGF, loc, selfValue.getType().getASTType(),
1063-
selfValue);
1064-
ArgumentSource selfArgSource(thisCallSite->getArg(), std::move(self));
1065-
setSelfParam(std::move(selfArgSource), thisCallSite);
1066-
} else {
1067-
ArgumentSource selfArgSource(thisCallSite->getArg());
1068-
setSelfParam(std::move(selfArgSource), thisCallSite);
1069-
}
1044+
ArgumentSource selfArgSource(thisCallSite->getArg());
1045+
setSelfParam(std::move(selfArgSource), thisCallSite);
10701046

10711047
// Directly dispatch to calls of the replaced function inside of
10721048
// '@_dynamicReplacement(for:)' methods.
10731049
bool isObjCReplacementCall = false;
10741050
if (isCallToReplacedInDynamicReplacement(SGF, afd, isObjCReplacementCall) &&
10751051
thisCallSite->getArg()->isSelfExprOf(
10761052
cast<AbstractFunctionDecl>(SGF.FunctionDC->getAsDecl()), false)) {
1077-
auto constant = SILDeclRef(afd, kind).asForeign(
1053+
auto constant = SILDeclRef(afd).asForeign(
10781054
!isObjCReplacementCall && requiresForeignEntryPoint(e->getDecl()));
10791055
auto subs = e->getDeclRef().getSubstitutions();
10801056
if (isObjCReplacementCall)
10811057
setCallee(Callee::forDirect(SGF, constant, subs, e));
10821058
else
10831059
setCallee(Callee::forDirect(
10841060
SGF,
1085-
SILDeclRef(cast<AbstractFunctionDecl>(SGF.FunctionDC->getAsDecl()),
1086-
kind),
1061+
SILDeclRef(cast<AbstractFunctionDecl>(SGF.FunctionDC->getAsDecl())),
10871062
subs, e, true));
10881063
return;
10891064
}
10901065

1091-
auto constant = SILDeclRef(afd, kind)
1092-
.asForeign(requiresForeignEntryPoint(afd));
1066+
auto constant = SILDeclRef(afd).asForeign(requiresForeignEntryPoint(afd));
10931067

10941068
auto subs = e->getDeclRef().getSubstitutions();
10951069
setCallee(Callee::forClassMethod(SGF, constant, subs, e));

lib/SILGen/SILGenConstructor.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -530,7 +530,9 @@ void SILGenFunction::emitClassConstructorAllocator(ConstructorDecl *ctor) {
530530
// Allocate the 'self' value.
531531
bool useObjCAllocation = usesObjCAllocator(selfClassDecl);
532532

533-
if (ctor->hasClangNode() || ctor->isConvenienceInit()) {
533+
if (ctor->hasClangNode() ||
534+
ctor->isObjCDynamic() ||
535+
ctor->isConvenienceInit()) {
534536
assert(ctor->hasClangNode() || ctor->isObjC());
535537
// For an allocator thunk synthesized for an @objc convenience initializer
536538
// or imported Objective-C init method, allocate using the metatype.

test/Interpreter/objc_metatypes.swift

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// RUN: %target-run-simple-swift
2+
// REQUIRES: executable_test
3+
// REQUIRES: objc_interop
4+
5+
import StdlibUnittest
6+
import Foundation
7+
8+
protocol Horse {
9+
init()
10+
}
11+
12+
class Pony : NSObject, Horse {
13+
override required init() {}
14+
}
15+
16+
class ChincoteaguePony : Pony {}
17+
18+
var ObjCMetatypesTest = TestSuite("ObjCMetatypes")
19+
20+
ObjCMetatypesTest.test("ClassInit") {
21+
let metatype: Pony.Type = ChincoteaguePony.self
22+
let instance = metatype.init()
23+
expectEqual(type(of: instance), ChincoteaguePony.self)
24+
}
25+
26+
ObjCMetatypesTest.test("ProtocolInit") {
27+
let metatype: Horse.Type = ChincoteaguePony.self
28+
let instance = metatype.init()
29+
expectEqual(type(of: instance), ChincoteaguePony.self)
30+
}
31+
32+
runAllTests()

test/SILGen/dynamic_self.swift

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -117,13 +117,11 @@ class ObjCInit {
117117
@objc dynamic required init() { }
118118
}
119119

120-
// CHECK-LABEL: sil hidden [ossa] @$s12dynamic_self12testObjCInit{{[_0-9a-zA-Z]*}}F : $@convention(thin) (@thick ObjCInit.Type) -> ()
120+
// CHECK-LABEL: sil hidden [ossa] @$s12dynamic_self12testObjCInit4metayAA0dE0Cm_tF : $@convention(thin) (@thick ObjCInit.Type) -> ()
121121
func testObjCInit(meta: ObjCInit.Type) {
122122
// CHECK: bb0([[THICK_META:%[0-9]+]] : $@thick ObjCInit.Type):
123-
// CHECK: [[OBJC_META:%[0-9]+]] = thick_to_objc_metatype [[THICK_META]] : $@thick ObjCInit.Type to $@objc_metatype ObjCInit.Type
124-
// CHECK: [[OBJ:%[0-9]+]] = alloc_ref_dynamic [objc] [[OBJC_META]] : $@objc_metatype ObjCInit.Type, $ObjCInit
125-
// CHECK: [[INIT:%[0-9]+]] = objc_method [[OBJ]] : $ObjCInit, #ObjCInit.init!initializer.1.foreign : (ObjCInit.Type) -> () -> ObjCInit, $@convention(objc_method) (@owned ObjCInit) -> @owned ObjCInit
126-
// CHECK: [[RESULT_OBJ:%[0-9]+]] = apply [[INIT]]([[OBJ]]) : $@convention(objc_method) (@owned ObjCInit) -> @owned ObjCInit
123+
// CHECK: [[INIT:%[0-9]+]] = function_ref @$s12dynamic_self8ObjCInitCACycfC : $@convention(method) (@thick ObjCInit.Type) -> @owned ObjCInit
124+
// CHECK: [[RESULT_OBJ:%[0-9]+]] = apply [[INIT]]([[THICK_META]]) : $@convention(method) (@thick ObjCInit.Type) -> @owned ObjCInit
127125
// CHECK: [[RESULT:%[0-9]+]] = tuple ()
128126
// CHECK: return [[RESULT]] : $()
129127
_ = meta.init()

test/SILGen/objc_dynamic_init.swift

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,16 @@ class Gadget: NSObject, Hoozit {
1717
}
1818
}
1919

20+
// CHECK-LABEL: sil hidden [ossa] @$s17objc_dynamic_init6GadgetCACycfC : $@convention(method) (@thick Gadget.Type) -> @owned Gadget
21+
// CHECK: [[OBJC_METATYPE:%.*]] = thick_to_objc_metatype %0 : $@thick Gadget.Type to $@objc_metatype Gadget.Type
22+
// CHECK: [[SELF:%.*]] = alloc_ref_dynamic [objc] %1 : $@objc_metatype Gadget.Type, $Gadget
23+
// CHECK: [[INIT:%.*]] = function_ref @$s17objc_dynamic_init6GadgetCACycfcTD : $@convention(method) (@owned Gadget) -> @owned Gadget
24+
// CHECK: [[NEW_SELF:%.*]] = apply [[INIT]]([[SELF]]) : $@convention(method) (@owned Gadget) -> @owned Gadget
25+
// CHECK: return [[NEW_SELF]]
26+
27+
// CHECK-LABEL: sil private [transparent] [thunk] [ossa] @$s17objc_dynamic_init6GadgetCAA6HoozitA2aDPxycfCTW : $@convention(witness_method: Hoozit) (@thick Gadget.Type) -> @out Gadget {
28+
// CHECK: function_ref @$s17objc_dynamic_init6GadgetCACycfC
29+
2030
class Gizmo: Gadget, Wotsit {
2131
required init() {
2232
super.init()
@@ -35,8 +45,16 @@ final class Bobamathing: Thingamabob {
3545
}
3646
}
3747

38-
// CHECK-LABEL: sil private [transparent] [thunk] [ossa] @$s{{.*}}GadgetC{{.*}}CTW
39-
// CHECK: function_ref @{{.*}}Gadget{{.*}}fC :
48+
// CHECK-LABEL: sil hidden [ossa] @$s17objc_dynamic_init8callInityyF : $@convention(thin) () -> ()
49+
// CHECK: [[METATYPE:%.*]] = metatype $@thick Gadget.Type
50+
// CHECK: [[CTOR:%.*]] = function_ref @$s17objc_dynamic_init6GadgetCACycfC
51+
// CHECK: [[INSTANCE:%.*]] = apply [[CTOR]]([[METATYPE]])
52+
// CHECK: destroy_value [[INSTANCE]]
53+
54+
func callInit() {
55+
let metatype = Gadget.self
56+
_ = metatype.init()
57+
}
4058

4159
// CHECK-LABEL: sil_vtable Gadget {
4260
// CHECK-NOT: #Gadget.init!allocator.1

0 commit comments

Comments
 (0)