Skip to content

Commit d401976

Browse files
committed
[DebugInfo] Fix handling of @_originallyDefinedIn types
Emit an imported declaration for @_originallyDefinedIn under the real module that these types live in. This patch also changes the mangling for the debugger to respect @_originallyDefinedIn. rdar://137146961
1 parent f9424ce commit d401976

File tree

5 files changed

+73
-35
lines changed

5 files changed

+73
-35
lines changed

include/swift/AST/ASTMangler.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -348,7 +348,8 @@ class ASTMangler : public Mangler {
348348
GenericSignature signature,
349349
ResilienceExpansion expansion);
350350

351-
std::string mangleTypeForDebugger(Type decl, GenericSignature sig);
351+
std::string mangleTypeForDebugger(Type decl, GenericSignature sig,
352+
bool RespectOriginallyDefinedIn = false);
352353

353354
/// Create a mangled name to be used for _typeName constant propagation.
354355
std::string mangleTypeForTypeName(Type type);

lib/AST/ASTMangler.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -712,12 +712,12 @@ static Type getTypeForDWARFMangling(Type t) {
712712
MakeAbstractConformanceForGenericType());
713713
}
714714

715-
std::string ASTMangler::mangleTypeForDebugger(Type Ty, GenericSignature sig) {
715+
std::string ASTMangler::mangleTypeForDebugger(Type Ty, GenericSignature sig, bool RespectOriginallyDefinedIn) {
716716
PrettyStackTraceType prettyStackTrace(Ty->getASTContext(),
717717
"mangling type for debugger", Ty);
718718

719719
DWARFMangling = true;
720-
RespectOriginallyDefinedIn = false;
720+
this->RespectOriginallyDefinedIn = RespectOriginallyDefinedIn;
721721
OptimizeProtocolNames = false;
722722
beginMangling();
723723

lib/IRGen/IRGenDebugInfo.cpp

Lines changed: 62 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
150150
llvm::DenseMap<const void *, llvm::TrackingMDNodeRef> DIModuleCache;
151151
llvm::StringMap<llvm::TrackingMDNodeRef> DIFileCache;
152152
llvm::StringMap<llvm::TrackingMDNodeRef> RuntimeErrorFnCache;
153+
llvm::StringSet<> OriginallyDefinedInTypes;
153154
TrackingDIRefMap DIRefMap;
154155
TrackingDIRefMap InnerTypeCache;
155156
/// \}
@@ -972,7 +973,7 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
972973
return SizeInBits;
973974
}
974975

975-
StringRef getMangledName(DebugTypeInfo DbgTy) {
976+
StringRef getMangledName(DebugTypeInfo DbgTy, bool RespectOriginallyDefinedIn) {
976977
if (DbgTy.isMetadataType())
977978
return MetadataTypeDeclCache.find(DbgTy.getDecl()->getName().str())
978979
->getKey();
@@ -1024,11 +1025,12 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
10241025
IGM.getSILModule());
10251026

10261027
Mangle::ASTMangler Mangler;
1027-
std::string Result = Mangler.mangleTypeForDebugger(Ty, Sig);
1028+
std::string Result = Mangler.mangleTypeForDebugger(Ty, Sig, RespectOriginallyDefinedIn);
10281029

10291030
// TODO(https://github.com/apple/swift/issues/57699): We currently cannot round trip some C++ types.
1031+
// There's no way to round trip when respecting @_originallyDefinedIn for a type.
10301032
if (!Opts.DisableRoundTripDebugTypes &&
1031-
!Ty->getASTContext().LangOpts.EnableCXXInterop) {
1033+
!Ty->getASTContext().LangOpts.EnableCXXInterop && !RespectOriginallyDefinedIn) {
10321034
// Make sure we can reconstruct mangled types for the debugger.
10331035
auto &Ctx = Ty->getASTContext();
10341036
Type Reconstructed = Demangle::getTypeForMangling(Ctx, Result, Sig);
@@ -1506,7 +1508,7 @@ createSpecializedStructOrClassType(NominalOrBoundGenericNominalType *Type,
15061508
/// anchor any typedefs that may appear in parameters so they can be
15071509
/// resolved in the debugger without needing to query the Swift module.
15081510
llvm::DINodeArray
1509-
collectGenericParams(NominalOrBoundGenericNominalType *BGT) {
1511+
collectGenericParams(NominalOrBoundGenericNominalType *BGT, bool AsForwardDeclarations = false) {
15101512

15111513
// Collect the generic args from the type and its parent.
15121514
std::vector<Type> GenericArgs;
@@ -1521,7 +1523,7 @@ createSpecializedStructOrClassType(NominalOrBoundGenericNominalType *Type,
15211523
SmallVector<llvm::Metadata *, 16> TemplateParams;
15221524
for (auto Arg : GenericArgs) {
15231525
DebugTypeInfo ParamDebugType;
1524-
if (Opts.DebugInfoLevel > IRGenDebugInfoLevel::ASTTypes)
1526+
if (Opts.DebugInfoLevel > IRGenDebugInfoLevel::ASTTypes && !llvm::isa<GenericTypeParamType>(Arg) && !AsForwardDeclarations)
15251527
// For the DwarfTypes level don't generate just a forward declaration
15261528
// for the generic type parameters.
15271529
ParamDebugType = DebugTypeInfo::getFromTypeInfo(
@@ -1789,26 +1791,6 @@ createSpecializedStructOrClassType(NominalOrBoundGenericNominalType *Type,
17891791
}
17901792

17911793
llvm::DIType *SpecificationOf = nullptr;
1792-
if (auto *TypeDecl = DbgTy.getType()->getNominalOrBoundGenericNominal()) {
1793-
// If this is a nominal type that has the @_originallyDefinedIn attribute,
1794-
// IRGenDebugInfo emits a forward declaration of the type as a child
1795-
// of the original module, and the type with a specification pointing to
1796-
// the forward declaraation. We do this so LLDB has enough information to
1797-
// both find the type in reflection metadata (the parent module name) and
1798-
// find it in the swiftmodule (the module name in the type mangled name).
1799-
if (auto Attribute =
1800-
TypeDecl->getAttrs().getAttribute<OriginallyDefinedInAttr>()) {
1801-
auto Identifier = IGM.getSILModule().getASTContext().getIdentifier(
1802-
Attribute->OriginalModuleName);
1803-
1804-
void *Key = (void *)Identifier.get();
1805-
auto InnerScope =
1806-
getOrCreateModule(Key, TheCU, Attribute->OriginalModuleName, {});
1807-
SpecificationOf = DBuilder.createForwardDecl(
1808-
llvm::dwarf::DW_TAG_structure_type, TypeDecl->getNameStr(),
1809-
InnerScope, File, 0, llvm::dwarf::DW_LANG_Swift, 0, 0);
1810-
}
1811-
}
18121794

18131795
// Here goes!
18141796
switch (BaseTy->getKind()) {
@@ -2338,6 +2320,45 @@ createSpecializedStructOrClassType(NominalOrBoundGenericNominalType *Type,
23382320
}
23392321
}
23402322

2323+
/// If this is a nominal type that has the @_originallyDefinedIn
2324+
/// attribute, IRGenDebugInfo emits an imported declaration of the type as
2325+
/// a child of the real module. We do this so LLDB has enough
2326+
/// information to both find the type in reflection metadata (the module name
2327+
/// in the type's mangled name), and find it in the swiftmodule (the type's
2328+
/// imported declaration's parent module name).
2329+
void handleOriginallyDefinedIn(DebugTypeInfo DbgTy, llvm::DIType *DITy,
2330+
StringRef MangledName, llvm::DIFile *File) {
2331+
if (OriginallyDefinedInTypes.contains(MangledName))
2332+
return;
2333+
2334+
auto Type = DbgTy.getType();
2335+
auto *TypeDecl = Type->getNominalOrBoundGenericNominal();
2336+
if (!TypeDecl)
2337+
return;
2338+
2339+
// Force the generation of the generic type parameters as forward
2340+
// declarations, as those types might be annotated with
2341+
// @_originallyDefinedIn.
2342+
if (auto *BoundDecl = llvm::dyn_cast<BoundGenericType>(DbgTy.getType()))
2343+
collectGenericParams(BoundDecl, /*AsForwardDeclarations=*/true);
2344+
2345+
// Find the outermost type, since only those can have @_originallyDefinedIn
2346+
// attached to them.
2347+
NominalTypeDecl *ParentDecl = TypeDecl;
2348+
while (llvm::isa_and_nonnull<NominalTypeDecl>(ParentDecl->getParent()))
2349+
ParentDecl = llvm::cast<NominalTypeDecl>(ParentDecl->getParent());
2350+
2351+
auto Attribute =
2352+
ParentDecl->getAttrs().getAttribute<OriginallyDefinedInAttr>();
2353+
if (!Attribute)
2354+
return;
2355+
2356+
// Find the module the imported declaration should be emitted under, this is the real module the type lives under.
2357+
auto RealModule = getOrCreateContext(ParentDecl->getParent());
2358+
DBuilder.createImportedDeclaration(RealModule, DITy, File, 0, MangledName);
2359+
OriginallyDefinedInTypes.insert(MangledName);
2360+
}
2361+
23412362
llvm::DIType *getOrCreateType(DebugTypeInfo DbgTy,
23422363
llvm::DIScope *Scope = nullptr) {
23432364
// Is this an empty type?
@@ -2357,7 +2378,7 @@ createSpecializedStructOrClassType(NominalOrBoundGenericNominalType *Type,
23572378
StringRef MangledName;
23582379
llvm::MDString *UID = nullptr;
23592380
if (canMangle(DbgTy.getType())) {
2360-
MangledName = getMangledName(DbgTy);
2381+
MangledName = getMangledName(DbgTy, /*RespectOriginallyDefinedIn=*/true);
23612382
UID = llvm::MDString::get(IGM.getLLVMContext(), MangledName);
23622383
if (llvm::Metadata *CachedTy = DIRefMap.lookup(UID)) {
23632384
auto DITy = cast<llvm::DIType>(CachedTy);
@@ -2382,7 +2403,18 @@ createSpecializedStructOrClassType(NominalOrBoundGenericNominalType *Type,
23822403
ClangDecl = AliasDecl->getClangDecl();
23832404
} else if (auto *ND = DbgTy.getType()->getNominalOrBoundGenericNominal()) {
23842405
TypeDecl = ND;
2385-
Context = ND->getParent();
2406+
// If this is an originally defined in type, we want to emit this type's scope
2407+
// to be the ABI module.
2408+
if (auto Attribute =
2409+
ND->getAttrs().getAttribute<OriginallyDefinedInAttr>()) {
2410+
auto Identifier = IGM.getSILModule().getASTContext().getIdentifier(
2411+
Attribute->OriginalModuleName);
2412+
void *Key = (void *)Identifier.get();
2413+
Scope =
2414+
getOrCreateModule(Key, TheCU, Attribute->OriginalModuleName, {});
2415+
} else {
2416+
Context = ND->getParent();
2417+
}
23862418
ClangDecl = ND->getClangDecl();
23872419
} else if (auto BNO = dyn_cast<BuiltinType>(DbgTy.getType())) {
23882420
Context = BNO->getASTContext().TheBuiltinModule;
@@ -2431,6 +2463,8 @@ createSpecializedStructOrClassType(NominalOrBoundGenericNominalType *Type,
24312463
FwdDeclTypes.emplace_back(
24322464
std::piecewise_construct, std::make_tuple(MangledName),
24332465
std::make_tuple(static_cast<llvm::Metadata *>(FwdDecl)));
2466+
2467+
handleOriginallyDefinedIn(DbgTy, FwdDecl, MangledName, getFile(Scope));
24342468
return FwdDecl;
24352469
}
24362470
llvm::DIType *DITy = createType(DbgTy, MangledName, Scope, getFile(Scope));
@@ -2459,6 +2493,7 @@ createSpecializedStructOrClassType(NominalOrBoundGenericNominalType *Type,
24592493
// Store it in the cache.
24602494
DITypeCache.insert({DbgTy.getType(), llvm::TrackingMDNodeRef(DITy)});
24612495

2496+
handleOriginallyDefinedIn(DbgTy, DITy, MangledName, getFile(Scope));
24622497
return DITy;
24632498
}
24642499
};

test/DebugInfo/module_abi_name.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ class SomeClass {}
66
@available(macOS 10.13, *)
77
@_originallyDefinedIn(module: "ThirdModule", OSX 10.12)
88
class DefinedElsewhere {}
9-
// CHECK: DICompositeType(tag: DW_TAG_structure_type, name: "DefinedElsewhere",{{.*}}runtimeLang: DW_LANG_Swift, identifier: "$s7Goodbye16DefinedElsewhereCD")
9+
// CHECK: DICompositeType(tag: DW_TAG_structure_type, name: "DefinedElsewhere",{{.*}}runtimeLang: DW_LANG_Swift, identifier: "$s11ThirdModule16DefinedElsewhereCD")
1010

1111
let v1 = SomeClass()
1212
let v2 = DefinedElsewhere()

test/DebugInfo/originally_defined_in.swift

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,10 @@
77
let i = 10
88
}
99

10-
// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "A",{{.*}}identifier: "$s21originally_defined_in1AVD",{{.*}}specification: ![[S1:[0-9]+]]
11-
// CHECK: [[S1]] = !DICompositeType(tag: DW_TAG_structure_type, name: "A", scope: ![[S2:[0-9]+]]
12-
// CHECK: [[S2]] = !DIModule({{.*}}name: "Other"
13-
10+
// CHECK: ![[MOD:[0-9]+]] = !DIModule(scope: null, name: "originally_defined_in"
11+
//
12+
// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "A",{{.*}}scope: ![[S:[0-9]+]]{{.*}}identifier: "$s5Other1AVD"
13+
// CHECK: [[S]] = !DIModule({{.*}}name: "Other"
14+
15+
// CHECK: !DIImportedEntity(tag: DW_TAG_imported_declaration, name: "$s5Other1AVD",{{.*}}scope: ![[MOD]]
1416
let a = A()

0 commit comments

Comments
 (0)