Skip to content

Commit b12acc4

Browse files
authored
Merge pull request swiftlang#12806 from slavapestov/simplify-dynamic-dispatch
Simplify dynamic dispatch
2 parents f3e5396 + 447fb51 commit b12acc4

File tree

3 files changed

+27
-271
lines changed

3 files changed

+27
-271
lines changed

lib/SILGen/SILGenApply.cpp

Lines changed: 12 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -64,16 +64,6 @@ getIndirectApplyAbstractionPattern(SILGenFunction &SGF,
6464
llvm_unreachable("bad representation");
6565
}
6666

67-
static CanType getDynamicMethodSelfType(SILGenFunction &SGF,
68-
const ArgumentSource &proto,
69-
ValueDecl *member) {
70-
if (member->isInstanceMember()) {
71-
return SGF.getASTContext().getAnyObjectType();
72-
} else {
73-
return proto.getSILSubstType(SGF).getSwiftRValueType();
74-
}
75-
}
76-
7767
/// Return the formal type for the partial-apply result type of a
7868
/// dynamic method invocation.
7969
static CanFunctionType
@@ -113,39 +103,6 @@ getPartialApplyOfDynamicMethodFormalType(SILGenModule &SGM, SILDeclRef member,
113103
return fnType;
114104
}
115105

116-
/// Replace the 'self' parameter in the given type.
117-
static CanSILFunctionType
118-
replaceSelfTypeForDynamicLookup(ASTContext &ctx,
119-
CanSILFunctionType fnType,
120-
CanType newSelfType,
121-
SILDeclRef methodName) {
122-
assert(!fnType->isCoroutine());
123-
auto oldParams = fnType->getParameters();
124-
SmallVector<SILParameterInfo, 4> newParams;
125-
newParams.append(oldParams.begin(), oldParams.end() - 1);
126-
newParams.push_back({newSelfType, oldParams.back().getConvention()});
127-
128-
// If the method returns Self, substitute AnyObject for the result type.
129-
SmallVector<SILResultInfo, 4> newResults;
130-
newResults.append(fnType->getResults().begin(), fnType->getResults().end());
131-
if (auto fnDecl = dyn_cast<FuncDecl>(methodName.getDecl())) {
132-
if (fnDecl->hasDynamicSelf()) {
133-
auto anyObjectTy = ctx.getAnyObjectType();
134-
for (auto &result : newResults) {
135-
auto newResultTy
136-
= result.getType()->replaceCovariantResultType(anyObjectTy, 0);
137-
result = result.getWithType(newResultTy->getCanonicalType());
138-
}
139-
}
140-
}
141-
142-
return SILFunctionType::get(nullptr, fnType->getExtInfo(),
143-
SILCoroutineKind::None,
144-
fnType->getCalleeConvention(), newParams, {},
145-
newResults, fnType->getOptionalErrorResult(), ctx,
146-
fnType->getWitnessMethodConformanceOrNone());
147-
}
148-
149106
/// Retrieve the type to use for a method found via dynamic lookup.
150107
static CanSILFunctionType
151108
getDynamicMethodLoweredType(SILGenFunction &SGF, SILValue v,
@@ -163,7 +120,7 @@ getDynamicMethodLoweredType(SILGenFunction &SGF, SILValue v,
163120

164121
auto methodTy = SGF.SGM.M.Types
165122
.getUncachedSILFunctionTypeForConstant(methodName, objcFormalTy);
166-
return replaceSelfTypeForDynamicLookup(ctx, methodTy, selfTy, methodName);
123+
return methodTy;
167124
}
168125

169126
/// Check if we can perform a dynamic dispatch on a super method call.
@@ -400,13 +357,11 @@ class Callee {
400357
}
401358
static Callee forDynamic(SILGenFunction &SGF, ArgumentSource &&arg,
402359
SILDeclRef c, const SubstitutionList &constantSubs,
403-
CanAnyFunctionType partialSubstFormalType,
360+
CanAnyFunctionType substFormalType,
404361
SubstitutionList subs, SILLocation l) {
405362
auto &ci = SGF.getConstantInfo(c);
406363
AbstractionPattern origFormalType = ci.FormalPattern;
407364

408-
auto selfType = getDynamicMethodSelfType(SGF, arg, c.getDecl());
409-
410365
// Replace the original self type with the partially-applied subst type.
411366
auto origFormalFnType = cast<AnyFunctionType>(origFormalType.getType());
412367
if (auto genericFnType = dyn_cast<GenericFunctionType>(origFormalFnType)) {
@@ -420,16 +375,8 @@ class Callee {
420375
cast<FunctionType>(genericFnType->substGenericArgs(constantSubs)
421376
->getCanonicalType());
422377
}
423-
origFormalFnType = CanFunctionType::get(selfType,
424-
origFormalFnType.getResult(),
425-
origFormalFnType->getExtInfo());
426378
origFormalType.rewriteType(CanGenericSignature(), origFormalFnType);
427379

428-
// Add the self type clause to the partially-applied subst type.
429-
auto substFormalType = CanFunctionType::get(selfType,
430-
partialSubstFormalType,
431-
origFormalFnType->getExtInfo());
432-
433380
return Callee(Kind::DynamicMethod, SGF, std::move(arg), c, origFormalType,
434381
substFormalType, subs, l);
435382
}
@@ -520,22 +467,17 @@ class Callee {
520467
return Constant;
521468
}
522469

523-
SILType getDynamicMethodType(SILGenFunction &SGF) const {
470+
SILType getDynamicMethodType(SILModule &M) const {
524471
// Lower the substituted type from the AST, which should have any generic
525472
// parameters in the original signature erased to their upper bounds.
526473
auto substFormalType = getSubstFormalType();
527474
auto objcFormalType = substFormalType.withExtInfo(
528475
substFormalType->getExtInfo().withSILRepresentation(
529476
SILFunctionTypeRepresentation::ObjCMethod));
530-
auto fnType = SGF.SGM.M.Types.getUncachedSILFunctionTypeForConstant(
477+
auto fnType = M.Types.getUncachedSILFunctionTypeForConstant(
531478
Constant, objcFormalType);
532479

533-
auto closureType = replaceSelfTypeForDynamicLookup(
534-
SGF.getASTContext(), fnType,
535-
SelfValue.getValue().getSILSubstType(SGF).getSwiftRValueType(),
536-
Constant);
537-
538-
return SILType::getPrimitiveObjectType(closureType);
480+
return SILType::getPrimitiveObjectType(fnType);
539481
}
540482

541483
ManagedValue getFnValue(SILGenFunction &SGF, bool isCurried) const & {
@@ -623,7 +565,7 @@ class Callee {
623565
}
624566
case Kind::DynamicMethod: {
625567
assert(constant->isForeign);
626-
auto closureType = getDynamicMethodType(SGF);
568+
auto closureType = getDynamicMethodType(SGF.SGM.M);
627569

628570
Scope S(SGF, Loc);
629571
ManagedValue self =
@@ -677,7 +619,7 @@ class Callee {
677619
return createCalleeTypeInfo(SGF, constant, constantInfo.getSILType());
678620
}
679621
case Kind::DynamicMethod: {
680-
auto formalType = getDynamicMethodType(SGF);
622+
auto formalType = getDynamicMethodType(SGF.SGM.M);
681623
return createCalleeTypeInfo(SGF, constant, formalType);
682624
}
683625
}
@@ -1463,6 +1405,10 @@ class SILGenApply : public Lowering::ExprVisitor<SILGenApply> {
14631405
auto substFormalType =
14641406
cast<FunctionType>(dynamicMemberRef->getType()->getCanonicalType()
14651407
.getAnyOptionalObjectType());
1408+
substFormalType = CanFunctionType::get(
1409+
dynamicMemberRef->getBase()->getType()->getCanonicalType(),
1410+
substFormalType, AnyFunctionType::ExtInfo());
1411+
14661412
setCallee(Callee::forDynamic(SGF, baseArgSource.delayedBorrow(SGF),
14671413
member, memberRef.getSubstitutions(),
14681414
substFormalType, {}, e));
@@ -4128,8 +4074,7 @@ CallEmission::applyNormalCall(SGFContext C) {
41284074
// In C language modes, substitute the type of the AbstractionPattern
41294075
// so that we won't see type parameters down when we try to form bridging
41304076
// conversions.
4131-
CanSILFunctionType calleeFnTy = mv.getType().castTo<SILFunctionType>();
4132-
if (calleeFnTy->getLanguage() == SILFunctionLanguage::C) {
4077+
if (calleeTypeInfo.substFnType->getLanguage() == SILFunctionLanguage::C) {
41334078
if (auto genericFnType =
41344079
dyn_cast<GenericFunctionType>(origFormalType.getType())) {
41354080
auto fnType = genericFnType->substGenericArgs(callee.getSubstitutions());
Lines changed: 6 additions & 204 deletions
Original file line numberDiff line numberDiff line change
@@ -1,212 +1,14 @@
11
// RUN: %target-swift-frontend -emit-silgen -emit-verbose-sil -enable-sil-ownership %s | %FileCheck %s
22

33
// Test that the attribute gets set on default argument generators.
4-
@_transparent func transparentFuncWithDefaultArgument (x: Int = 1) -> Int {
5-
return x
6-
}
7-
func useTransparentFuncWithDefaultArgument() -> Int {
8-
return transparentFuncWithDefaultArgument();
94

10-
// CHECK-LABEL: sil hidden @_T021transparent_attribute37useTransparentFuncWithDefaultArgumentSiyF
11-
// CHECK: apply {{.*}} line:8:44
12-
// CHECK: apply {{.*}} line:8:10
13-
// CHECK: return
14-
15-
}
5+
// CHECK-LABEL: sil hidden [transparent] @_T021transparent_attribute0A23FuncWithDefaultArgumentS2i1x_tFfA_ : $@convention(thin) () -> Int {
166

17-
func transparentFuncWithoutDefaultArgument (x: Int = 1) -> Int {
18-
return x
19-
}
20-
func useTransparentFuncWithoutDefaultArgument() -> Int {
21-
return transparentFuncWithoutDefaultArgument();
22-
23-
// CHECK-LABEL: sil hidden @_T021transparent_attribute40useTransparentFuncWithoutDefaultArgumentSiyF
24-
// CHECK: apply {{.*}} line:21:47
25-
// CHECK-NOT: transparent
26-
// CHECK: apply {{.*}} line:21:10
27-
// CHECK: return
28-
29-
}
7+
// CHECK-LABEL: sil hidden [transparent] @_T021transparent_attribute0A23FuncWithDefaultArgumentS2i1x_tF : $@convention(thin) (Int) -> Int {
308

31-
// Make sure the transparent attribute is set on constructors (allocating and initializing).
32-
struct StructWithTranspConstructor {
33-
@_transparent init () {}
34-
}
35-
func testStructWithTranspConstructor() -> StructWithTranspConstructor {
36-
return StructWithTranspConstructor()
37-
38-
// transparent_attribute.StructWithTranspConstructor.constructor
39-
// CHECK-APPLY: sil hidden @_T021transparent_attribute27StructWithTranspConstructorV{{[_0-9a-zA-Z]*}}fC
40-
41-
// testStructWithTranspConstructor
42-
// CHECK-APPLY: _T21transparent_attribute31testStructWithTranspConstructorFT_VS_27StructWithTranspConstructor
43-
// CHECK: apply {{.*}} line:36:10
44-
45-
}
46-
47-
struct MySt {}
48-
var _x = MySt()
49-
var x1 : MySt {
50-
@_transparent
51-
get {
52-
return _x
53-
}
54-
@_transparent
55-
set {
56-
_x = newValue
57-
}
58-
}
59-
var x2 : MySt {
60-
@_transparent
61-
set(v) {
62-
_x = v
63-
}
64-
@_transparent
65-
get {
66-
return _x
67-
}
68-
}
69-
func testProperty(z: MySt) {
70-
x1 = z
71-
x2 = z
72-
var m1 : MySt = x1
73-
var m2 : MySt = x2
74-
// CHECK-APPLY: sil hidden @_T021transparent_attribute12testPropertyyAA4MyStV1z_tF
75-
// CHECK: function_ref @_T021transparent_attribute2x1AA4MyStVvs
76-
// CHECK-NEXT: apply
77-
// CHECK: function_ref @_T021transparent_attribute2x2AA4MyStVvs
78-
// CHECK-NEXT: apply
79-
// CHECK: function_ref @_T021transparent_attribute2x1AA4MyStVvg
80-
// CHECK-NEXT: apply
81-
// CHECK: function_ref @_T021transparent_attribute2x2AA4MyStVvg
82-
// CHECK-NEXT: apply
83-
}
84-
85-
var _tr2 = MySt()
86-
var _tr3 = MySt()
87-
struct MyTranspStruct {}
88-
extension MyTranspStruct {
89-
@_transparent
90-
init(input : MySt) {}
91-
mutating
92-
func tr1() {}
93-
var tr2: MySt {
94-
get {
95-
return _tr2
96-
}
97-
set {
98-
_tr2 = newValue
99-
}
100-
}
101-
}
102-
103-
extension MyTranspStruct {
104-
@_transparent
105-
var tr3: MySt {
106-
get {
107-
return _tr3
108-
}
109-
set {
110-
_tr3 = newValue
111-
}
112-
}
113-
}
114-
115-
func testStructExtension() {
116-
var c : MyTranspStruct = MyTranspStruct(input: _x)
117-
c.tr1()
118-
var s : MySt = c.tr2
119-
var t : MySt = c.tr3
120-
// CHECK-APPLY: sil hidden @_TF21transparent_attribute13testStructExtensionFT_T_
121-
// CHECK: [[INIT:%[0-9]+]] = function_ref @_T021transparent_attribute14MyTranspStructV{{[_0-9a-zA-Z]*}}fC
122-
// CHECK: apply [[INIT]]
123-
// CHECK: [[TR1:%[0-9]+]] = function_ref @_T021transparent_attribute14MyTranspStructV3tr1{{[_0-9a-zA-Z]*}}F
124-
// CHECK: apply [[TR1]]
125-
// CHECK: [[TR2:%[0-9]+]] = function_ref @_T021transparent_attribute14MyTranspStructV3tr2AA0C2StVvg
126-
// CHECK: apply [[TR2]]
127-
// CHECK: [[TR3:%[0-9]+]] = function_ref @_T021transparent_attribute14MyTranspStructV3tr3AA0C2StVvg
128-
// CHECK: apply [[TR3]]
129-
}
130-
131-
enum MyEnum {
132-
case onetransp
133-
case twotransp
134-
}
135-
136-
extension MyEnum {
137-
@_transparent
138-
func tr3() {}
139-
}
140-
141-
func testEnumExtension() {
142-
MyEnum.onetransp.tr3()
143-
// CHECK-APPLY: sil hidden @_T021transparent_attribute17testEnumExtensionyyF
144-
// CHECK: [[TR3:%[0-9]+]] = function_ref @_T021transparent_attribute6MyEnumO3tr3{{[_0-9a-zA-Z]*}}F
145-
// CHECK: [[INIT:%[0-9]+]] = enum $MyEnum, #MyEnum.onetransp!enumelt
146-
// CHECK: apply [[TR3]]([[INIT]])
147-
}
148-
149-
struct testVarDecl {
150-
@_transparent var max: Int {
151-
get {
152-
return 0xFF
153-
}
154-
mutating
155-
set {
156-
max = 0xFF
157-
}
158-
}
159-
func testVarDeclFoo () {
160-
var z: Int = max
161-
// CHECK-APPLY: sil hidden @_T021transparent_attribute11testVarDeclV0cdE3Foo{{[_0-9a-zA-Z]*}}F
162-
// CHECK: [[TR4:%[0-9]+]] = function_ref @_T021transparent_attribute11testVarDeclV3maxSivg
163-
// CHECK: apply [[TR4]]
164-
}
165-
}
166-
167-
struct testVarDeclShortenedSyntax {
168-
@_transparent static var max: Int { return 0xFF };
169-
func testVarDeclShortenedSyntaxfoo () {
170-
var z: Int = testVarDeclShortenedSyntax.max
171-
// CHECK-APPLY: sil hidden @_T021transparent_attribute26testVarDeclShortenedSyntaxV0cdeF9Syntaxfoo{{[_0-9a-zA-Z]*}}F
172-
// CHECK: [[TR5:%[0-9]+]] = function_ref @_T021transparent_attribute26testVarDeclShortenedSyntaxV3maxSivgZ
173-
// CHECK: apply [[TR5]]
174-
}
175-
};
176-
177-
@_transparent var transparentOnGlobalVar: Int {
178-
get {
179-
return 0xFF
180-
}
181-
}
182-
// CHECK: sil hidden [transparent] @_T021transparent_attribute0A11OnGlobalVarSivg
183-
184-
// Local functions in transparent context are fragile.
185-
@_transparent public func foo() {
186-
// CHECK-LABEL: sil shared [serialized] @_T021transparent_attribute3fooyyF3barL_yyF : $@convention(thin) () -> ()
187-
func bar() {}
188-
bar()
189-
190-
// CHECK-LABEL: sil shared [serialized] @_T021transparent_attribute3fooyyFyycfU_ : $@convention(thin) () -> () {
191-
let f: () -> () = {}
192-
f()
193-
194-
// CHECK-LABEL: sil shared [serialized] @_T021transparent_attribute3fooyyF3zimL_yyF : $@convention(thin) () -> () {
195-
func zim() {
196-
// CHECK-LABEL: sil shared [serialized] @_T021transparent_attribute3fooyyF3zimL_yyF4zangL_yyF : $@convention(thin) () -> () {
197-
func zang() {
198-
}
199-
zang()
200-
}
201-
zim()
9+
@_transparent func transparentFuncWithDefaultArgument (x: Int = 1) -> Int {
10+
return x
20211
}
203-
204-
205-
// Check that @_versioned entities have public linkage.
206-
// CHECK-LABEL: sil @_T021transparent_attribute25referencedFromTransparentyyF : $@convention(thin) () -> () {
207-
@_versioned func referencedFromTransparent() {}
208-
209-
// CHECK-LABEL: sil [transparent] [serialized] @_T021transparent_attribute23referencesVersionedFuncyycyF : $@convention(thin) () -> @owned @callee_owned () -> () {
210-
@_transparent public func referencesVersionedFunc() -> () -> () {
211-
return referencedFromTransparent
12+
func useTransparentFuncWithDefaultArgument() -> Int {
13+
return transparentFuncWithDefaultArgument()
21214
}

test/SILGen/versioned_attribute.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership -emit-verbose-sil %s | %FileCheck %s
22

3+
// Check that @_versioned entities have public linkage.
4+
// CHECK-LABEL: sil @_T019versioned_attribute25referencedFromTransparentyyF : $@convention(thin) () -> () {
5+
@_versioned func referencedFromTransparent() {}
6+
7+
// CHECK-LABEL: sil [serialized] @_T019versioned_attribute23referencesVersionedFuncyycyF : $@convention(thin) () -> @owned @callee_owned () -> () {
8+
@_inlineable public func referencesVersionedFunc() -> () -> () {
9+
return referencedFromTransparent
10+
}
11+
312
@_versioned class Horse {
413
var mouth: AnyObject?
514
}

0 commit comments

Comments
 (0)