Skip to content

Commit 5ea0bec

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 5ea0bec

File tree

7 files changed

+87
-44
lines changed

7 files changed

+87
-44
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);
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: 68 additions & 30 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);
@@ -1197,8 +1199,9 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
11971199
auto DbgTy = DebugTypeInfo::getFromTypeInfo(
11981200
UnsubstitutedTy, IGM.getTypeInfoForUnlowered(UnsubstitutedTy), IGM);
11991201
Mangle::ASTMangler Mangler;
1200-
std::string DeclTypeMangledName = Mangler.mangleTypeForDebugger(
1201-
UnsubstitutedTy->mapTypeOutOfContext(), {});
1202+
std::string DeclTypeMangledName =
1203+
Mangler.mangleTypeForDebugger(UnsubstitutedTy->mapTypeOutOfContext(),
1204+
{}, /*RespectOriginallyDefinedIn=*/true);
12021205
if (DeclTypeMangledName == MangledName) {
12031206
return createUnsubstitutedVariantType(DbgTy, Decl, MangledName, Scope,
12041207
File, 0, Flags);
@@ -1256,7 +1259,8 @@ createSpecializedStructOrClassType(NominalOrBoundGenericNominalType *Type,
12561259
UnsubstitutedTy, IGM.getTypeInfoForUnlowered(UnsubstitutedTy), IGM);
12571260
Mangle::ASTMangler Mangler;
12581261
std::string DeclTypeMangledName =
1259-
Mangler.mangleTypeForDebugger(UnsubstitutedTy->mapTypeOutOfContext(), {});
1262+
Mangler.mangleTypeForDebugger(UnsubstitutedTy->mapTypeOutOfContext(), {},
1263+
/*RespectOriginallyDefinedIn=*/true);
12601264
if (DeclTypeMangledName == MangledName) {
12611265
return createUnsubstitutedGenericStructOrClassType(
12621266
DbgTy, Decl, UnsubstitutedTy, Scope, File, Line, Flags, nullptr,
@@ -1506,7 +1510,7 @@ createSpecializedStructOrClassType(NominalOrBoundGenericNominalType *Type,
15061510
/// anchor any typedefs that may appear in parameters so they can be
15071511
/// resolved in the debugger without needing to query the Swift module.
15081512
llvm::DINodeArray
1509-
collectGenericParams(NominalOrBoundGenericNominalType *BGT) {
1513+
collectGenericParams(NominalOrBoundGenericNominalType *BGT, bool AsForwardDeclarations = false) {
15101514

15111515
// Collect the generic args from the type and its parent.
15121516
std::vector<Type> GenericArgs;
@@ -1521,7 +1525,8 @@ createSpecializedStructOrClassType(NominalOrBoundGenericNominalType *Type,
15211525
SmallVector<llvm::Metadata *, 16> TemplateParams;
15221526
for (auto Arg : GenericArgs) {
15231527
DebugTypeInfo ParamDebugType;
1524-
if (Opts.DebugInfoLevel > IRGenDebugInfoLevel::ASTTypes)
1528+
if (Opts.DebugInfoLevel > IRGenDebugInfoLevel::ASTTypes &&
1529+
!AsForwardDeclarations)
15251530
// For the DwarfTypes level don't generate just a forward declaration
15261531
// for the generic type parameters.
15271532
ParamDebugType = DebugTypeInfo::getFromTypeInfo(
@@ -1789,26 +1794,6 @@ createSpecializedStructOrClassType(NominalOrBoundGenericNominalType *Type,
17891794
}
17901795

17911796
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-
}
18121797

18131798
// Here goes!
18141799
switch (BaseTy->getKind()) {
@@ -2338,6 +2323,45 @@ createSpecializedStructOrClassType(NominalOrBoundGenericNominalType *Type,
23382323
}
23392324
}
23402325

2326+
/// If this is a nominal type that has the @_originallyDefinedIn
2327+
/// attribute, IRGenDebugInfo emits an imported declaration of the type as
2328+
/// a child of the real module. We do this so LLDB has enough
2329+
/// information to both find the type in reflection metadata (the module name
2330+
/// in the type's mangled name), and find it in the swiftmodule (the type's
2331+
/// imported declaration's parent module name).
2332+
void handleOriginallyDefinedIn(DebugTypeInfo DbgTy, llvm::DIType *DITy,
2333+
StringRef MangledName, llvm::DIFile *File) {
2334+
if (OriginallyDefinedInTypes.contains(MangledName))
2335+
return;
2336+
2337+
auto Type = DbgTy.getType();
2338+
auto *TypeDecl = Type->getNominalOrBoundGenericNominal();
2339+
if (!TypeDecl)
2340+
return;
2341+
2342+
// Force the generation of the generic type parameters as forward
2343+
// declarations, as those types might be annotated with
2344+
// @_originallyDefinedIn.
2345+
if (auto *BoundDecl = llvm::dyn_cast<BoundGenericType>(DbgTy.getType()))
2346+
collectGenericParams(BoundDecl, /*AsForwardDeclarations=*/true);
2347+
2348+
// Find the outermost type, since only those can have @_originallyDefinedIn
2349+
// attached to them.
2350+
NominalTypeDecl *ParentDecl = TypeDecl;
2351+
while (llvm::isa_and_nonnull<NominalTypeDecl>(ParentDecl->getParent()))
2352+
ParentDecl = llvm::cast<NominalTypeDecl>(ParentDecl->getParent());
2353+
2354+
auto Attribute =
2355+
ParentDecl->getAttrs().getAttribute<OriginallyDefinedInAttr>();
2356+
if (!Attribute)
2357+
return;
2358+
2359+
// Find the module the imported declaration should be emitted under, this is the real module the type lives under.
2360+
auto RealModule = getOrCreateContext(ParentDecl->getParent());
2361+
DBuilder.createImportedDeclaration(RealModule, DITy, File, 0, MangledName);
2362+
OriginallyDefinedInTypes.insert(MangledName);
2363+
}
2364+
23412365
llvm::DIType *getOrCreateType(DebugTypeInfo DbgTy,
23422366
llvm::DIScope *Scope = nullptr) {
23432367
// Is this an empty type?
@@ -2357,7 +2381,7 @@ createSpecializedStructOrClassType(NominalOrBoundGenericNominalType *Type,
23572381
StringRef MangledName;
23582382
llvm::MDString *UID = nullptr;
23592383
if (canMangle(DbgTy.getType())) {
2360-
MangledName = getMangledName(DbgTy);
2384+
MangledName = getMangledName(DbgTy, /*RespectOriginallyDefinedIn=*/true);
23612385
UID = llvm::MDString::get(IGM.getLLVMContext(), MangledName);
23622386
if (llvm::Metadata *CachedTy = DIRefMap.lookup(UID)) {
23632387
auto DITy = cast<llvm::DIType>(CachedTy);
@@ -2382,7 +2406,18 @@ createSpecializedStructOrClassType(NominalOrBoundGenericNominalType *Type,
23822406
ClangDecl = AliasDecl->getClangDecl();
23832407
} else if (auto *ND = DbgTy.getType()->getNominalOrBoundGenericNominal()) {
23842408
TypeDecl = ND;
2385-
Context = ND->getParent();
2409+
// If this is an originally defined in type, we want to emit this type's scope
2410+
// to be the ABI module.
2411+
if (auto Attribute =
2412+
ND->getAttrs().getAttribute<OriginallyDefinedInAttr>()) {
2413+
auto Identifier = IGM.getSILModule().getASTContext().getIdentifier(
2414+
Attribute->OriginalModuleName);
2415+
void *Key = (void *)Identifier.get();
2416+
Scope =
2417+
getOrCreateModule(Key, TheCU, Attribute->OriginalModuleName, {});
2418+
} else {
2419+
Context = ND->getParent();
2420+
}
23862421
ClangDecl = ND->getClangDecl();
23872422
} else if (auto BNO = dyn_cast<BuiltinType>(DbgTy.getType())) {
23882423
Context = BNO->getASTContext().TheBuiltinModule;
@@ -2431,6 +2466,8 @@ createSpecializedStructOrClassType(NominalOrBoundGenericNominalType *Type,
24312466
FwdDeclTypes.emplace_back(
24322467
std::piecewise_construct, std::make_tuple(MangledName),
24332468
std::make_tuple(static_cast<llvm::Metadata *>(FwdDecl)));
2469+
2470+
handleOriginallyDefinedIn(DbgTy, FwdDecl, MangledName, getFile(Scope));
24342471
return FwdDecl;
24352472
}
24362473
llvm::DIType *DITy = createType(DbgTy, MangledName, Scope, getFile(Scope));
@@ -2459,6 +2496,7 @@ createSpecializedStructOrClassType(NominalOrBoundGenericNominalType *Type,
24592496
// Store it in the cache.
24602497
DITypeCache.insert({DbgTy.getType(), llvm::TrackingMDNodeRef(DITy)});
24612498

2499+
handleOriginallyDefinedIn(DbgTy, DITy, MangledName, getFile(Scope));
24622500
return DITy;
24632501
}
24642502
};

lib/PrintAsClang/ClangSyntaxPrinter.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -491,11 +491,11 @@ void ClangSyntaxPrinter::printKnownCType(
491491
void ClangSyntaxPrinter::printSwiftMangledNameForDebugger(
492492
const NominalTypeDecl *typeDecl) {
493493
printIgnoredCxx17ExtensionDiagnosticBlock([&]() {
494-
495-
os << "#pragma clang diagnostic push\n";
496-
os << "#pragma clang diagnostic ignored \"-Wreserved-identifier\"\n";
494+
os << "#pragma clang diagnostic push\n";
495+
os << "#pragma clang diagnostic ignored \"-Wreserved-identifier\"\n";
497496
auto mangled_name = mangler.mangleTypeForDebugger(
498-
typeDecl->getDeclaredInterfaceType(), nullptr);
497+
typeDecl->getDeclaredInterfaceType(), nullptr,
498+
/*RespectOriginallyDefinedIn=*/true);
499499
if (!mangled_name.empty()) {
500500
os << " typedef char " << mangled_name << ";\n";
501501
os << " static inline constexpr " << mangled_name

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()

tools/swift-ide-test/swift-ide-test.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2701,7 +2701,8 @@ static int doPrintLocalTypes(const CompilerInvocation &InitInvok,
27012701
Mangle::ASTMangler Mangler;
27022702
std::string MangledName = Mangler.mangleTypeForDebugger(
27032703
LTD->getDeclaredInterfaceType(),
2704-
LTD->getInnermostDeclContext()->getGenericSignatureOfContext());
2704+
LTD->getInnermostDeclContext()->getGenericSignatureOfContext(),
2705+
/*RespectOriginallyDefinedIn=*/true);
27052706
MangledNames.push_back(MangledName);
27062707
}
27072708

@@ -3906,7 +3907,8 @@ class TypeReconstructWalker : public SourceEntityWalker {
39063907
void tryDemangleType(Type T, const DeclContext *DC, CharSourceRange range) {
39073908
Mangle::ASTMangler Mangler;
39083909
auto sig = DC->getGenericSignatureOfContext();
3909-
std::string mangledName(Mangler.mangleTypeForDebugger(T, sig));
3910+
std::string mangledName(Mangler.mangleTypeForDebugger(
3911+
T, sig, /*RespectOriginallyDefinedIn=*/true));
39103912
Type ReconstructedType = DC->mapTypeIntoContext(
39113913
Demangle::getTypeForMangling(Ctx, mangledName));
39123914
Stream << "type: ";

0 commit comments

Comments
 (0)