Skip to content

Commit 771eacb

Browse files
committed
IRGen: Emit method descriptors
1 parent 0b65480 commit 771eacb

File tree

5 files changed

+58
-7
lines changed

5 files changed

+58
-7
lines changed

lib/IRGen/GenMeta.cpp

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -550,12 +550,14 @@ namespace {
550550
Optional<ConstantAggregateBuilderBase::PlaceholderPosition>
551551
NumRequirementsInSignature,
552552
NumRequirements;
553+
554+
bool Resilient;
555+
553556
public:
554557
ProtocolDescriptorBuilder(IRGenModule &IGM, ProtocolDecl *Proto,
555558
SILDefaultWitnessTable *defaultWitnesses)
556-
: super(IGM), Proto(Proto), DefaultWitnesses(defaultWitnesses)
557-
{
558-
}
559+
: super(IGM), Proto(Proto), DefaultWitnesses(defaultWitnesses),
560+
Resilient(IGM.isResilient(Proto, ResilienceExpansion::Minimal)) {}
559561

560562
void layout() {
561563
super::layout();
@@ -649,7 +651,7 @@ namespace {
649651

650652
// Look up the dispatch thunk if the protocol is resilient.
651653
llvm::Constant *thunk = nullptr;
652-
if (IGM.isResilient(Proto, ResilienceExpansion::Minimal))
654+
if (Resilient)
653655
thunk = IGM.emitDispatchThunk(func);
654656

655657
// Classify the function.
@@ -668,6 +670,15 @@ namespace {
668670
pi.getNumWitnesses());
669671

670672
for (auto &entry : pi.getWitnessEntries()) {
673+
if (Resilient && entry.isFunction()) {
674+
// Define the method descriptor.
675+
SILDeclRef func(entry.getFunction());
676+
auto *descriptor =
677+
B.getAddrOfCurrentPosition(
678+
IGM.ProtocolRequirementStructTy);
679+
IGM.defineMethodDescriptor(func, Proto, descriptor);
680+
}
681+
671682
auto reqt = B.beginStruct(IGM.ProtocolRequirementStructTy);
672683

673684
auto info = getRequirementInfo(entry);
@@ -1207,13 +1218,13 @@ namespace {
12071218

12081219
SILVTable *VTable = nullptr;
12091220
unsigned VTableSize = 0;
1210-
bool isResilient;
1221+
bool Resilient;
12111222

12121223
public:
12131224
ClassContextDescriptorBuilder(IRGenModule &IGM, ClassDecl *Type,
12141225
RequireMetadata_t requireMetadata)
12151226
: super(IGM, Type, requireMetadata),
1216-
isResilient(IGM.isResilient(Type, ResilienceExpansion::Minimal)) {
1227+
Resilient(IGM.isResilient(Type, ResilienceExpansion::Minimal)) {
12171228

12181229
if (getType()->isForeign()) return;
12191230

@@ -1309,6 +1320,12 @@ namespace {
13091320
void addMethod(SILDeclRef fn) {
13101321
assert(VTable && "no vtable?!");
13111322

1323+
// Define the method descriptor to point to the current position in the
1324+
// nominal type descriptor.
1325+
IGM.defineMethodDescriptor(fn, Type,
1326+
B.getAddrOfCurrentPosition(IGM.MethodDescriptorStructTy));
1327+
1328+
// Actually build the descriptor.
13121329
auto *func = cast<AbstractFunctionDecl>(fn.getDecl());
13131330
auto descriptor = B.beginStruct(IGM.MethodDescriptorStructTy);
13141331

@@ -1343,7 +1360,7 @@ namespace {
13431360
descriptor.finishAndAddTo(B);
13441361

13451362
// Emit method dispatch thunk if the class is resilient.
1346-
if (isResilient &&
1363+
if (Resilient &&
13471364
func->getEffectiveAccess() >= AccessLevel::Public) {
13481365
IGM.emitDispatchThunk(fn);
13491366
}

lib/IRGen/GenThunk.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,3 +115,10 @@ llvm::Function *IRGenModule::emitDispatchThunk(SILDeclRef declRef) {
115115

116116
return f;
117117
}
118+
119+
llvm::GlobalValue *IRGenModule::defineMethodDescriptor(SILDeclRef declRef,
120+
NominalTypeDecl *nominalDecl,
121+
llvm::Constant *definition) {
122+
auto entity = LinkEntity::forMethodDescriptor(declRef);
123+
return defineAlias(entity, definition);
124+
}

lib/IRGen/IRGenModule.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1149,6 +1149,11 @@ private: \
11491149
llvm::GlobalValue *defineAlias(LinkEntity entity,
11501150
llvm::Constant *definition);
11511151

1152+
llvm::GlobalValue *defineMethodDescriptor(SILDeclRef declRef,
1153+
NominalTypeDecl *nominalDecl,
1154+
llvm::Constant *definition);
1155+
1156+
11521157
Address getAddrOfEnumCase(EnumElementDecl *Case,
11531158
ForDefinition_t forDefinition);
11541159
Address getAddrOfFieldOffset(VarDecl *D, ForDefinition_t forDefinition);

test/IRGen/generic_vtable.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,17 @@ public class Concrete : Derived<Int> {
107107
// CHECK-SAME: }>, align
108108

109109

110+
//// Method descriptors
111+
112+
// CHECK-LABEL: @"$S14generic_vtable4BaseC2m1yyFTq" ={{( dllexport)?}}{{( protected)?}} alias %swift.method_descriptor, getelementptr inbounds (<{{.*}}>* @"$S14generic_vtable4BaseCMn", i32 0, i32 13)
113+
// CHECK-LABEL: @"$S14generic_vtable4BaseC2m2yyFTq" ={{( dllexport)?}}{{( protected)?}} alias %swift.method_descriptor, getelementptr inbounds (<{{.*}}* @"$S14generic_vtable4BaseCMn", i32 0, i32 14)
114+
// CHECK-LABEL: @"$S14generic_vtable4BaseCACycfcTq" = hidden alias %swift.method_descriptor, getelementptr inbounds (<{{.*}}* @"$S14generic_vtable4BaseCMn", i32 0, i32 15)
115+
116+
// CHECK-LABEL: @"$S14generic_vtable7DerivedC2m3yyFTq" ={{( dllexport)?}}{{( protected)?}} alias %swift.method_descriptor, getelementptr inbounds (<{{.*}}>* @"$S14generic_vtable7DerivedCMn", i32 0, i32 23)
117+
118+
// CHECK-LABEL: @"$S14generic_vtable8ConcreteC2m4yyFTq" ={{( dllexport)?}}{{( protected)?}} alias %swift.method_descriptor, getelementptr inbounds (<{{.*}}>* @"$S14generic_vtable8ConcreteCMn", i32 0, i32 16)
119+
120+
110121
//// Metadata initialization function for 'Derived' copies superclass vtable
111122
//// and installs overrides for 'm2()' and 'init()'.
112123

test/IRGen/protocol_resilience_thunks.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,17 @@
77

88
import resilient_protocol
99

10+
// Method descriptors
11+
12+
// CHECK-LABEL: @"$S26protocol_resilience_thunks19MyResilientProtocolP11returnsVoid1xySb_tFTq" ={{( dllexport)?}}{{( protected)?}} alias %swift.protocol_requirement, getelementptr inbounds (<{{.*}}>* @"$S26protocol_resilience_thunks19MyResilientProtocolMp", i32 0, i32 6)
13+
// CHECK-LABEL: @"$S26protocol_resilience_thunks19MyResilientProtocolP11returnsBoolSbyFTq" ={{( dllexport)?}}{{( protected)?}} alias %swift.protocol_requirement, getelementptr inbounds (<{{.*}}>* @"$S26protocol_resilience_thunks19MyResilientProtocolMp", i32 0, i32 7)
14+
// CHECK-LABEL: @"$S26protocol_resilience_thunks19MyResilientProtocolP10returnsAnyypyFTq" ={{( dllexport)?}}{{( protected)?}} alias %swift.protocol_requirement, getelementptr inbounds (<{{.*}}>* @"$S26protocol_resilience_thunks19MyResilientProtocolMp", i32 0, i32 8)
15+
// CHECK-LABEL: @"$S26protocol_resilience_thunks19MyResilientProtocolP12throwingFuncyyKFTq" ={{( dllexport)?}}{{( protected)?}} alias %swift.protocol_requirement, getelementptr inbounds (<{{.*}}>* @"$S26protocol_resilience_thunks19MyResilientProtocolMp", i32 0, i32 9)
16+
// CHECK-LABEL: @"$S26protocol_resilience_thunks19MyResilientProtocolP11genericFuncyqd__qd__lFTq" ={{( dllexport)?}}{{( protected)?}} alias %swift.protocol_requirement, getelementptr inbounds (<{{.*}}>* @"$S26protocol_resilience_thunks19MyResilientProtocolMp", i32 0, i32 10)
17+
// CHECK-LABEL: @"$S26protocol_resilience_thunks19MyResilientProtocolP8propertySbvgTq" ={{( dllexport)?}}{{( protected)?}} alias %swift.protocol_requirement, getelementptr inbounds (<{{.*}}>* @"$S26protocol_resilience_thunks19MyResilientProtocolMp", i32 0, i32 11)
18+
// CHECK-LABEL: @"$S26protocol_resilience_thunks19MyResilientProtocolP8propertySbvsTq" ={{( dllexport)?}}{{( protected)?}} alias %swift.protocol_requirement, getelementptr inbounds (<{{.*}}>* @"$S26protocol_resilience_thunks19MyResilientProtocolMp", i32 0, i32 12)
19+
// CHECK-LABEL: @"$S26protocol_resilience_thunks19MyResilientProtocolP8propertySbvMTq" ={{( dllexport)?}}{{( protected)?}} alias %swift.protocol_requirement, getelementptr inbounds (<{{.*}}>* @"$S26protocol_resilience_thunks19MyResilientProtocolMp", i32 0, i32 13)
20+
1021
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @"$S26protocol_resilience_thunks26callResilientWitnessMethodyyx010resilient_A00E12BaseProtocolRzlF"(%swift.opaque* noalias nocapture, %swift.type* %T, i8** %T.ResilientBaseProtocol)
1122
// CHECK: call swiftcc [[INT]] @"$S18resilient_protocol21ResilientBaseProtocolP11requirementSiyFTj"(%swift.opaque* noalias nocapture swiftself %0, %swift.type* %T, i8** %T.ResilientBaseProtocol)
1223
// CHECK: ret void

0 commit comments

Comments
 (0)