Skip to content

Commit 123d27d

Browse files
authored
Merge pull request #19067 from slavapestov/method-descriptors
Method descriptors
2 parents 12fa674 + ee5deee commit 123d27d

22 files changed

+287
-152
lines changed

docs/ABI/Mangling.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,8 @@ field offsets are therefore required when accessing fields in generic
115115
types where the metadata itself has unknown layout.)
116116

117117
::
118+
global ::= global 'Tj' // resilient method dispatch thunk
119+
global ::= global 'Tq' // method descriptor
118120

119121
global ::= global 'TO' // ObjC-as-swift thunk
120122
global ::= global 'To' // swift-as-ObjC thunk

include/swift/AST/ASTMangler.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,6 @@ class ASTMangler : public Mangler {
5757
enum class SymbolKind {
5858
Default,
5959
DynamicThunk,
60-
SwiftDispatchThunk,
6160
SwiftAsObjCThunk,
6261
ObjCAsSwiftThunk,
6362
DirectMethodReferenceThunk,

include/swift/Demangling/DemangleNodes.def

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -203,8 +203,9 @@ NODE(ReflectionMetadataFieldDescriptor)
203203
NODE(ReflectionMetadataAssocTypeDescriptor)
204204
NODE(ReflectionMetadataSuperclassDescriptor)
205205
NODE(GenericTypeParamDecl)
206-
CONTEXT_NODE(CurryThunk)
207-
CONTEXT_NODE(DispatchThunk)
206+
NODE(CurryThunk)
207+
NODE(DispatchThunk)
208+
NODE(MethodDescriptor)
208209
NODE(ThrowsAnnotation)
209210
NODE(EmptyList)
210211
NODE(FirstElementMarker)

include/swift/IRGen/Linking.h

Lines changed: 48 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,18 @@ class LinkEntity {
117117
/// ConstructorDecl* inside a protocol or a class.
118118
DispatchThunkAllocator,
119119

120+
/// A method descriptor. The pointer is a FuncDecl* inside a protocol
121+
/// or a class.
122+
MethodDescriptor,
123+
124+
/// A method descriptor for an initializing constructor. The pointer
125+
/// is a ConstructorDecl* inside a class.
126+
MethodDescriptorInitializer,
127+
128+
/// A method descriptor for an allocating constructor. The pointer is a
129+
/// ConstructorDecl* inside a protocol or a class.
130+
MethodDescriptorAllocator,
131+
120132
/// A resilient enum tag index. The pointer is a EnumElementDecl*.
121133
EnumCase,
122134

@@ -412,18 +424,22 @@ class LinkEntity {
412424

413425
LinkEntity() = default;
414426

427+
static bool isValidResilientMethodRef(SILDeclRef declRef) {
428+
if (declRef.isForeign ||
429+
declRef.isDirectReference ||
430+
declRef.isCurried)
431+
return false;
432+
433+
auto *decl = declRef.getDecl();
434+
return (isa<ClassDecl>(decl->getDeclContext()) ||
435+
isa<ProtocolDecl>(decl->getDeclContext()));
436+
}
437+
415438
public:
416439
static LinkEntity forDispatchThunk(SILDeclRef declRef) {
417-
assert(!declRef.isForeign &&
418-
!declRef.isDirectReference &&
419-
!declRef.isCurried);
440+
assert(isValidResilientMethodRef(declRef));
420441

421442
LinkEntity::Kind kind;
422-
423-
auto *decl = declRef.getDecl();
424-
assert(isa<ClassDecl>(decl->getDeclContext()) ||
425-
isa<ProtocolDecl>(decl->getDeclContext()));
426-
427443
switch (declRef.kind) {
428444
case SILDeclRef::Kind::Func:
429445
kind = Kind::DispatchThunk;
@@ -439,7 +455,30 @@ class LinkEntity {
439455
}
440456

441457
LinkEntity entity;
442-
entity.setForDecl(kind, decl);
458+
entity.setForDecl(kind, declRef.getDecl());
459+
return entity;
460+
}
461+
462+
static LinkEntity forMethodDescriptor(SILDeclRef declRef) {
463+
assert(isValidResilientMethodRef(declRef));
464+
465+
LinkEntity::Kind kind;
466+
switch (declRef.kind) {
467+
case SILDeclRef::Kind::Func:
468+
kind = Kind::MethodDescriptor;
469+
break;
470+
case SILDeclRef::Kind::Initializer:
471+
kind = Kind::MethodDescriptorInitializer;
472+
break;
473+
case SILDeclRef::Kind::Allocator:
474+
kind = Kind::MethodDescriptorAllocator;
475+
break;
476+
default:
477+
llvm_unreachable("Bad SILDeclRef for method descriptor");
478+
}
479+
480+
LinkEntity entity;
481+
entity.setForDecl(kind, declRef.getDecl());
443482
return entity;
444483
}
445484

lib/AST/ASTMangler.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -535,7 +535,6 @@ void ASTMangler::appendSymbolKind(SymbolKind SKind) {
535535
switch (SKind) {
536536
case SymbolKind::Default: return;
537537
case SymbolKind::DynamicThunk: return appendOperator("TD");
538-
case SymbolKind::SwiftDispatchThunk: return appendOperator("Tj");
539538
case SymbolKind::SwiftAsObjCThunk: return appendOperator("To");
540539
case SymbolKind::ObjCAsSwiftThunk: return appendOperator("TO");
541540
case SymbolKind::DirectMethodReferenceThunk: return appendOperator("Td");

lib/Demangling/Demangler.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1702,6 +1702,7 @@ NodePointer Demangler::demangleThunkOrSpecialization() {
17021702
switch (char c = nextChar()) {
17031703
case 'c': return createWithChild(Node::Kind::CurryThunk, popNode(isEntity));
17041704
case 'j': return createWithChild(Node::Kind::DispatchThunk, popNode(isEntity));
1705+
case 'q': return createWithChild(Node::Kind::MethodDescriptor, popNode(isEntity));
17051706
case 'o': return createNode(Node::Kind::ObjCAttribute);
17061707
case 'O': return createNode(Node::Kind::NonObjCAttribute);
17071708
case 'D': return createNode(Node::Kind::DynamicAttribute);

lib/Demangling/NodePrinter.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,7 @@ class NodePrinter {
381381
case Node::Kind::MaterializeForSet:
382382
case Node::Kind::MergedFunction:
383383
case Node::Kind::Metaclass:
384+
case Node::Kind::MethodDescriptor:
384385
case Node::Kind::ModifyAccessor:
385386
case Node::Kind::NativeOwningAddressor:
386387
case Node::Kind::NativeOwningMutableAddressor:
@@ -907,6 +908,10 @@ NodePointer NodePrinter::print(NodePointer Node, bool asPrefixContext) {
907908
Printer << "dispatch thunk of ";
908909
print(Node->getChild(0));
909910
return nullptr;
911+
case Node::Kind::MethodDescriptor:
912+
Printer << "method descriptor for ";
913+
print(Node->getChild(0));
914+
return nullptr;
910915
case Node::Kind::OutlinedBridgedMethod:
911916
Printer << "outlined bridged method (" << Node->getText() << ") of ";
912917
return nullptr;

lib/Demangling/OldRemangler.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1931,14 +1931,18 @@ void Remangler::mangleGenericTypeParamDecl(Node *node) {
19311931
unreachable("todo");
19321932
}
19331933

1934-
void Remangler::mangleCurryThunk(Node *node, EntityContext &ctx) {
1934+
void Remangler::mangleCurryThunk(Node *node) {
19351935
Out << "<curry-thunk>";
19361936
}
19371937

1938-
void Remangler::mangleDispatchThunk(Node *node, EntityContext &ctx) {
1938+
void Remangler::mangleDispatchThunk(Node *node) {
19391939
Out << "<dispatch-thunk>";
19401940
}
19411941

1942+
void Remangler::mangleMethodDescriptor(Node *node) {
1943+
Out << "<method-descriptor>";
1944+
}
1945+
19421946
void Remangler::mangleEmptyList(Node *node) {
19431947
Out << "<empty>";
19441948
}

lib/Demangling/Remangler.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1887,6 +1887,11 @@ void Remangler::mangleDispatchThunk(Node *node) {
18871887
Buffer << "Tj";
18881888
}
18891889

1890+
void Remangler::mangleMethodDescriptor(Node *node) {
1891+
mangleSingleChildNode(node);
1892+
Buffer << "Tq";
1893+
}
1894+
18901895
void Remangler::mangleThrowsAnnotation(Node *node) {
18911896
Buffer << 'K';
18921897
}

lib/IRGen/GenClass.cpp

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1019,36 +1019,6 @@ void IRGenModule::emitClassDecl(ClassDecl *D) {
10191019

10201020
emitNestedTypeDecls(D->getMembers());
10211021
emitFieldMetadataRecord(D);
1022-
1023-
// If the class is resilient, emit dispatch thunks.
1024-
if (isResilient(D, ResilienceExpansion::Minimal)) {
1025-
struct ThunkEmitter : public SILVTableVisitor<ThunkEmitter> {
1026-
IRGenModule &IGM;
1027-
ClassDecl *D;
1028-
1029-
ThunkEmitter(IRGenModule &IGM, ClassDecl *D)
1030-
: IGM(IGM), D(D) {
1031-
addVTableEntries(D);
1032-
}
1033-
1034-
void addMethodOverride(SILDeclRef baseRef, SILDeclRef declRef) {}
1035-
1036-
void addMethod(SILDeclRef member) {
1037-
auto *func = cast<AbstractFunctionDecl>(member.getDecl());
1038-
if (func->getDeclContext() == D &&
1039-
func->getEffectiveAccess() >= AccessLevel::Public) {
1040-
IGM.emitDispatchThunk(member);
1041-
}
1042-
}
1043-
1044-
void addPlaceholder(MissingMemberDecl *m) {
1045-
assert(m->getNumberOfVTableEntries() == 0
1046-
&& "Should not be emitting class with missing members");
1047-
}
1048-
};
1049-
1050-
ThunkEmitter emitter(*this, D);
1051-
}
10521022
}
10531023

10541024
namespace {

lib/IRGen/GenDecl.cpp

Lines changed: 54 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1378,7 +1378,10 @@ SILLinkage LinkEntity::getLinkage(ForDefinition_t forDefinition) const {
13781378
switch (getKind()) {
13791379
case Kind::DispatchThunk:
13801380
case Kind::DispatchThunkInitializer:
1381-
case Kind::DispatchThunkAllocator: {
1381+
case Kind::DispatchThunkAllocator:
1382+
case Kind::MethodDescriptor:
1383+
case Kind::MethodDescriptorInitializer:
1384+
case Kind::MethodDescriptorAllocator: {
13821385
auto *decl = getDecl();
13831386

13841387
// Protocol requirements don't have their own access control
@@ -1586,7 +1589,10 @@ bool LinkEntity::isAvailableExternally(IRGenModule &IGM) const {
15861589
switch (getKind()) {
15871590
case Kind::DispatchThunk:
15881591
case Kind::DispatchThunkInitializer:
1589-
case Kind::DispatchThunkAllocator: {
1592+
case Kind::DispatchThunkAllocator:
1593+
case Kind::MethodDescriptor:
1594+
case Kind::MethodDescriptorInitializer:
1595+
case Kind::MethodDescriptorAllocator: {
15901596
auto *decl = getDecl();
15911597

15921598
// Protocol requirements don't have their own access control
@@ -3268,6 +3274,47 @@ IRGenModule::getAddrOfTypeMetadataSingletonInitializationCache(
32683274
return variable;
32693275
}
32703276

3277+
llvm::GlobalValue *IRGenModule::defineAlias(LinkEntity entity,
3278+
llvm::Constant *definition) {
3279+
// Check for an existing forward declaration of the alias.
3280+
auto &entry = GlobalVars[entity];
3281+
llvm::GlobalValue *existingVal = nullptr;
3282+
if (entry) {
3283+
existingVal = cast<llvm::GlobalValue>(entry);
3284+
// Clear the existing value's name so we can steal it.
3285+
existingVal->setName("");
3286+
}
3287+
3288+
LinkInfo link = LinkInfo::get(*this, entity, ForDefinition);
3289+
auto *ptrTy = cast<llvm::PointerType>(definition->getType());
3290+
auto *alias = llvm::GlobalAlias::create(
3291+
ptrTy->getElementType(), ptrTy->getAddressSpace(), link.getLinkage(),
3292+
link.getName(), definition, &Module);
3293+
alias->setVisibility(link.getVisibility());
3294+
alias->setDLLStorageClass(link.getDLLStorage());
3295+
3296+
if (link.isUsed()) {
3297+
addUsedGlobal(alias);
3298+
}
3299+
3300+
// Replace an existing external declaration for the address point.
3301+
if (entry) {
3302+
auto existingVal = cast<llvm::GlobalValue>(entry);
3303+
3304+
// FIXME: MC breaks when emitting alias references on some platforms
3305+
// (rdar://problem/22450593 ). Work around this by referring to the aliasee
3306+
// instead.
3307+
llvm::Constant *aliasCast = alias->getAliasee();
3308+
aliasCast = llvm::ConstantExpr::getBitCast(aliasCast,
3309+
entry->getType());
3310+
existingVal->replaceAllUsesWith(aliasCast);
3311+
existingVal->eraseFromParent();
3312+
}
3313+
entry = alias;
3314+
3315+
return alias;
3316+
}
3317+
32713318
/// Define the metadata for a type.
32723319
///
32733320
/// Some type metadata has information before the address point that the
@@ -3320,6 +3367,10 @@ llvm::GlobalValue *IRGenModule::defineTypeMetadata(CanType concreteType,
33203367
if (!section.empty())
33213368
var->setSection(section);
33223369

3370+
LinkInfo link = LinkInfo::get(*this, entity, ForDefinition);
3371+
if (link.isUsed())
3372+
addUsedGlobal(var);
3373+
33233374
// Keep type metadata around for all types.
33243375
if (auto nominal = concreteType->getAnyNominal())
33253376
addRuntimeResolvableType(nominal);
@@ -3339,47 +3390,7 @@ llvm::GlobalValue *IRGenModule::defineTypeMetadata(CanType concreteType,
33393390
addr, indices);
33403391
}
33413392
addr = llvm::ConstantExpr::getBitCast(addr, TypeMetadataPtrTy);
3342-
3343-
// Check for an existing forward declaration of the address point.
3344-
auto &directEntry = GlobalVars[directEntity];
3345-
llvm::GlobalValue *existingVal = nullptr;
3346-
if (directEntry) {
3347-
existingVal = cast<llvm::GlobalValue>(directEntry);
3348-
// Clear the existing value's name so we can steal it.
3349-
existingVal->setName("");
3350-
}
3351-
3352-
LinkInfo link = LinkInfo::get(*this, directEntity, ForDefinition);
3353-
auto *ptrTy = cast<llvm::PointerType>(addr->getType());
3354-
auto *alias = llvm::GlobalAlias::create(
3355-
ptrTy->getElementType(), ptrTy->getAddressSpace(), link.getLinkage(),
3356-
link.getName(), addr, &Module);
3357-
alias->setVisibility(link.getVisibility());
3358-
alias->setDLLStorageClass(link.getDLLStorage());
3359-
3360-
// The full metadata is used based on the visibility of the address point,
3361-
// not the metadata itself.
3362-
if (link.isUsed()) {
3363-
addUsedGlobal(var);
3364-
addUsedGlobal(alias);
3365-
}
3366-
3367-
// Replace an existing external declaration for the address point.
3368-
if (directEntry) {
3369-
auto existingVal = cast<llvm::GlobalValue>(directEntry);
3370-
3371-
// FIXME: MC breaks when emitting alias references on some platforms
3372-
// (rdar://problem/22450593 ). Work around this by referring to the aliasee
3373-
// instead.
3374-
llvm::Constant *aliasCast = alias->getAliasee();
3375-
aliasCast = llvm::ConstantExpr::getBitCast(aliasCast,
3376-
directEntry->getType());
3377-
existingVal->replaceAllUsesWith(aliasCast);
3378-
existingVal->eraseFromParent();
3379-
}
3380-
directEntry = alias;
3381-
3382-
return alias;
3393+
return defineAlias(directEntity, addr);
33833394
}
33843395

33853396
/// Fetch the declaration of the metadata (or metadata template) for a

0 commit comments

Comments
 (0)