Skip to content

Commit 4eb064d

Browse files
committed
IRGen: Emit opaque type descriptors for runtime lookup.
If -enable-anonymous-context-mangled-names is enabled, meaning that we assign names to anonymous context descriptors for discovery by RemoteAST, then include opaque type descriptors in the type metadata record table so that they can also be found at runtime by RemoteAST for debugger support.
1 parent 9c6bc9c commit 4eb064d

File tree

4 files changed

+69
-34
lines changed

4 files changed

+69
-34
lines changed

lib/IRGen/GenDecl.cpp

Lines changed: 36 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -826,14 +826,16 @@ void IRGenModule::addObjCClass(llvm::Constant *classPtr, bool nonlazy) {
826826
ObjCNonLazyClasses.push_back(classPtr);
827827
}
828828

829-
void IRGenModule::addRuntimeResolvableType(NominalTypeDecl *nominal) {
829+
void IRGenModule::addRuntimeResolvableType(GenericTypeDecl *type) {
830830
// Collect the nominal type records we emit into a special section.
831-
RuntimeResolvableTypes.push_back(nominal);
831+
RuntimeResolvableTypes.push_back(type);
832832

833-
// As soon as the type metadata is available, all the type's conformances
834-
// must be available, too. The reason is that a type (with the help of its
835-
// metadata) can be checked at runtime if it conforms to a protocol.
836-
addLazyConformances(nominal);
833+
if (auto nominal = dyn_cast<NominalTypeDecl>(type)) {
834+
// As soon as the type metadata is available, all the type's conformances
835+
// must be available, too. The reason is that a type (with the help of its
836+
// metadata) can be checked at runtime if it conforms to a protocol.
837+
addLazyConformances(nominal);
838+
}
837839
}
838840

839841
ConstantReference
@@ -2744,41 +2746,49 @@ getObjCClassByNameReference(IRGenModule &IGM, ClassDecl *cls) {
27442746
SmallString<64> objcRuntimeNameBuffer;
27452747
auto ref = IGM.getAddrOfGlobalString(
27462748
cls->getObjCRuntimeName(objcRuntimeNameBuffer),
2747-
/*willByRelativelyAddressed=*/true);
2749+
/*willBeRelativelyAddressed=*/true);
27482750

27492751
return TypeEntityReference(kind, ref);
27502752
}
27512753

27522754
TypeEntityReference
2753-
IRGenModule::getTypeEntityReference(NominalTypeDecl *decl) {
2755+
IRGenModule::getTypeEntityReference(GenericTypeDecl *decl) {
27542756
if (auto protocol = dyn_cast<ProtocolDecl>(decl)) {
27552757
assert(!protocol->isObjC() && "imported protocols not handled here");
27562758
return getProtocolDescriptorEntityReference(*this, protocol);
27572759
}
2758-
2759-
auto clas = dyn_cast<ClassDecl>(decl);
2760-
if (!clas) {
2761-
return getTypeContextDescriptorEntityReference(*this, decl);
2760+
2761+
if (auto opaque = dyn_cast<OpaqueTypeDecl>(decl)) {
2762+
auto entity = LinkEntity::forOpaqueTypeDescriptor(opaque);
2763+
IRGen.noteUseOfOpaqueTypeDescriptor(opaque);
2764+
return getContextDescriptorEntityReference(*this, entity);
27622765
}
27632766

2764-
switch (clas->getForeignClassKind()) {
2765-
case ClassDecl::ForeignKind::RuntimeOnly:
2766-
return getObjCClassByNameReference(*this, clas);
2767+
if (auto nominal = dyn_cast<NominalTypeDecl>(decl)) {
2768+
auto clas = dyn_cast<ClassDecl>(decl);
2769+
if (!clas) {
2770+
return getTypeContextDescriptorEntityReference(*this, nominal);
2771+
}
27672772

2768-
case ClassDecl::ForeignKind::CFType:
2769-
return getTypeContextDescriptorEntityReference(*this, clas);
2773+
switch (clas->getForeignClassKind()) {
2774+
case ClassDecl::ForeignKind::RuntimeOnly:
2775+
return getObjCClassByNameReference(*this, clas);
27702776

2771-
case ClassDecl::ForeignKind::Normal:
2772-
if (hasKnownSwiftMetadata(*this, clas)) {
2777+
case ClassDecl::ForeignKind::CFType:
27732778
return getTypeContextDescriptorEntityReference(*this, clas);
2774-
}
27752779

2776-
// Note: we would like to use an Objective-C class reference, but the
2777-
// Darwin linker currently has a bug where it will coalesce these symbols
2778-
// *after* computing a relative offset, causing incorrect relative
2779-
// offsets in the metadata. Therefore, reference Objective-C classes by
2780-
// their runtime names.
2781-
return getObjCClassByNameReference(*this, clas);
2780+
case ClassDecl::ForeignKind::Normal:
2781+
if (hasKnownSwiftMetadata(*this, clas)) {
2782+
return getTypeContextDescriptorEntityReference(*this, clas);
2783+
}
2784+
2785+
// Note: we would like to use an Objective-C class reference, but the
2786+
// Darwin linker currently has a bug where it will coalesce these symbols
2787+
// *after* computing a relative offset, causing incorrect relative
2788+
// offsets in the metadata. Therefore, reference Objective-C classes by
2789+
// their runtime names.
2790+
return getObjCClassByNameReference(*this, clas);
2791+
}
27822792
}
27832793
llvm_unreachable("bad foreign type kind");
27842794
}

lib/IRGen/GenStruct.cpp

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -879,19 +879,29 @@ void IRGenModule::emitStructDecl(StructDecl *st) {
879879
emitNestedTypeDecls(st->getMembers());
880880
}
881881

882+
void IRGenModule::maybeEmitOpaqueTypeDecl(OpaqueTypeDecl *opaque) {
883+
if (IRGen.Opts.EnableAnonymousContextMangledNames) {
884+
// If we're emitting anonymous context mangled names for debuggability,
885+
// then emit all opaque type descriptors and make them runtime-discoverable
886+
// so that remote ast/mirror can recover them.
887+
addRuntimeResolvableType(opaque);
888+
emitOpaqueTypeDecl(opaque);
889+
} else if (!IRGen.hasLazyMetadata(opaque)) {
890+
emitOpaqueTypeDecl(opaque);
891+
}
892+
}
893+
882894
void IRGenModule::emitFuncDecl(FuncDecl *fd) {
883895
// If there's an opaque return type for this function, emit its descriptor.
884896
if (auto opaque = fd->getOpaqueResultTypeDecl()) {
885-
if (!IRGen.hasLazyMetadata(opaque))
886-
emitOpaqueTypeDecl(opaque);
897+
maybeEmitOpaqueTypeDecl(opaque);
887898
}
888899
}
889900

890901
void IRGenModule::emitAbstractStorageDecl(AbstractStorageDecl *fd) {
891902
// If there's an opaque return type for this function, emit its descriptor.
892903
if (auto opaque = fd->getOpaqueResultTypeDecl()) {
893-
if (!IRGen.hasLazyMetadata(opaque))
894-
emitOpaqueTypeDecl(opaque);
904+
maybeEmitOpaqueTypeDecl(opaque);
895905
}
896906
}
897907

lib/IRGen/IRGenModule.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -995,8 +995,8 @@ class IRGenModule {
995995
SmallVector<ProtocolDecl *, 4> SwiftProtocols;
996996
/// List of protocol conformances to generate descriptors for.
997997
std::vector<ConformanceDescription> ProtocolConformances;
998-
/// List of nominal types to generate type metadata records for.
999-
SmallVector<NominalTypeDecl *, 4> RuntimeResolvableTypes;
998+
/// List of types to generate runtime-resolvable metadata records for.
999+
SmallVector<GenericTypeDecl *, 4> RuntimeResolvableTypes;
10001000
/// List of ExtensionDecls corresponding to the generated
10011001
/// categories.
10021002
SmallVector<ExtensionDecl*, 4> ObjCCategoryDecls;
@@ -1270,7 +1270,7 @@ private: \
12701270
ConstantInitFuture init,
12711271
llvm::StringRef section = {});
12721272

1273-
TypeEntityReference getTypeEntityReference(NominalTypeDecl *D);
1273+
TypeEntityReference getTypeEntityReference(GenericTypeDecl *D);
12741274

12751275
llvm::Constant *getAddrOfTypeMetadata(CanType concreteType);
12761276
ConstantReference getAddrOfTypeMetadata(CanType concreteType,
@@ -1460,7 +1460,8 @@ private: \
14601460
llvm::Type *overrideDeclType = nullptr);
14611461

14621462
void emitLazyPrivateDefinitions();
1463-
void addRuntimeResolvableType(NominalTypeDecl *nominal);
1463+
void addRuntimeResolvableType(GenericTypeDecl *nominal);
1464+
void maybeEmitOpaqueTypeDecl(OpaqueTypeDecl *opaque);
14641465

14651466
/// Add all conformances of the given \c DeclContext LazyWitnessTables.
14661467
void addLazyConformances(DeclContext *dc);
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// RUN: %target-swift-frontend -emit-ir -enable-anonymous-context-mangled-names %s | %FileCheck %s
2+
3+
protocol P {}
4+
extension Int: P {}
5+
6+
// CHECK: [[DEFINER_NAME:@.*]] = {{.*}}constant [{{[0-9]+}} x i8] c"$s24opaque_result_type_debug3fooQryF\00"
7+
// CHECK: @"$s24opaque_result_type_debug3fooQryFMXX" = {{.*}}constant{{.*}} [[DEFINER_NAME]]
8+
// CHECK: @"$s24opaque_result_type_debug3fooQryFQOMQ" = {{.*}}constant{{.*}} @"$s24opaque_result_type_debug3fooQryFMXX"
9+
10+
// CHECK: @"\01l_type_metadata_table" = {{.*}} @"$s24opaque_result_type_debug3fooQryFQOMQ"
11+
12+
func foo() -> some P {
13+
return 0
14+
}

0 commit comments

Comments
 (0)