Skip to content

Commit 96c2c1f

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, and fixes a bug where @_originallyDefinedIn that should be ignored was still being used when mangling. rdar://137146961
1 parent 0c7e7f3 commit 96c2c1f

9 files changed

+191
-56
lines changed

lib/AST/ASTMangler.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -717,7 +717,7 @@ std::string ASTMangler::mangleTypeForDebugger(Type Ty, GenericSignature sig) {
717717
Ty);
718718

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

lib/AST/Decl.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -979,7 +979,7 @@ const ExternalSourceLocs *Decl::getSerializedLocs() const {
979979
StringRef Decl::getAlternateModuleName() const {
980980
for (auto *Att: Attrs) {
981981
if (auto *OD = dyn_cast<OriginallyDefinedInAttr>(Att)) {
982-
if (OD->isActivePlatform(getASTContext())) {
982+
if (!OD->isInvalid() && OD->isActivePlatform(getASTContext())) {
983983
return OD->OriginalModuleName;
984984
}
985985
}

lib/IRGen/IRGenDebugInfo.cpp

Lines changed: 115 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,16 @@
2323
#include "IRBuilder.h"
2424
#include "swift/AST/ASTDemangler.h"
2525
#include "swift/AST/ASTMangler.h"
26+
#include "swift/AST/Attr.h"
27+
#include "swift/AST/Decl.h"
2628
#include "swift/AST/Expr.h"
2729
#include "swift/AST/GenericEnvironment.h"
2830
#include "swift/AST/IRGenOptions.h"
2931
#include "swift/AST/Module.h"
3032
#include "swift/AST/ModuleLoader.h"
3133
#include "swift/AST/Pattern.h"
3234
#include "swift/AST/TypeDifferenceVisitor.h"
35+
#include "swift/AST/TypeWalker.h"
3336
#include "swift/Basic/Assertions.h"
3437
#include "swift/Basic/Compiler.h"
3538
#include "swift/Basic/SourceManager.h"
@@ -137,7 +140,7 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
137140
return Line == other.Line && Column == other.Column && File == other.File;
138141
}
139142
};
140-
143+
141144
/// Various caches.
142145
/// \{
143146
llvm::StringSet<> VarNames;
@@ -150,6 +153,7 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
150153
llvm::DenseMap<const void *, llvm::TrackingMDNodeRef> DIModuleCache;
151154
llvm::StringMap<llvm::TrackingMDNodeRef> DIFileCache;
152155
llvm::StringMap<llvm::TrackingMDNodeRef> RuntimeErrorFnCache;
156+
llvm::StringSet<> OriginallyDefinedInTypes;
153157
TrackingDIRefMap DIRefMap;
154158
TrackingDIRefMap InnerTypeCache;
155159
/// \}
@@ -1026,9 +1030,12 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
10261030
Mangle::ASTMangler Mangler(IGM.Context);
10271031
std::string Result = Mangler.mangleTypeForDebugger(Ty, Sig);
10281032

1033+
bool IsTypeOriginallyDefinedIn =
1034+
containsOriginallyDefinedIn(DbgTy.getType());
10291035
// TODO(https://github.com/apple/swift/issues/57699): We currently cannot round trip some C++ types.
1036+
// There's no way to round trip when respecting @_originallyDefinedIn for a type.
10301037
if (!Opts.DisableRoundTripDebugTypes &&
1031-
!Ty->getASTContext().LangOpts.EnableCXXInterop) {
1038+
!Ty->getASTContext().LangOpts.EnableCXXInterop && !IsTypeOriginallyDefinedIn) {
10321039
// Make sure we can reconstruct mangled types for the debugger.
10331040
auto &Ctx = Ty->getASTContext();
10341041
Type Reconstructed = Demangle::getTypeForMangling(Ctx, Result, Sig);
@@ -1507,7 +1514,7 @@ createSpecializedStructOrClassType(NominalOrBoundGenericNominalType *Type,
15071514
/// anchor any typedefs that may appear in parameters so they can be
15081515
/// resolved in the debugger without needing to query the Swift module.
15091516
llvm::DINodeArray
1510-
collectGenericParams(NominalOrBoundGenericNominalType *BGT) {
1517+
collectGenericParams(NominalOrBoundGenericNominalType *BGT, bool AsForwardDeclarations = false) {
15111518

15121519
// Collect the generic args from the type and its parent.
15131520
std::vector<Type> GenericArgs;
@@ -1522,7 +1529,8 @@ createSpecializedStructOrClassType(NominalOrBoundGenericNominalType *Type,
15221529
SmallVector<llvm::Metadata *, 16> TemplateParams;
15231530
for (auto Arg : GenericArgs) {
15241531
DebugTypeInfo ParamDebugType;
1525-
if (Opts.DebugInfoLevel > IRGenDebugInfoLevel::ASTTypes)
1532+
if (Opts.DebugInfoLevel > IRGenDebugInfoLevel::ASTTypes &&
1533+
!AsForwardDeclarations)
15261534
// For the DwarfTypes level don't generate just a forward declaration
15271535
// for the generic type parameters.
15281536
ParamDebugType = DebugTypeInfo::getFromTypeInfo(
@@ -1790,39 +1798,19 @@ createSpecializedStructOrClassType(NominalOrBoundGenericNominalType *Type,
17901798
}
17911799

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

18141802
// Here goes!
18151803
switch (BaseTy->getKind()) {
18161804
case TypeKind::BuiltinUnboundGeneric:
18171805
llvm_unreachable("not a real type");
1818-
1806+
18191807
case TypeKind::BuiltinFixedArray: {
18201808
// TODO: provide proper array debug info
18211809
unsigned FwdDeclLine = 0;
18221810
return createOpaqueStruct(Scope, "Builtin.FixedArray", MainFile, FwdDeclLine,
18231811
SizeInBits, AlignInBits, Flags, MangledName);
18241812
}
1825-
1813+
18261814
case TypeKind::BuiltinPackIndex:
18271815
case TypeKind::BuiltinInteger: {
18281816
Encoding = llvm::dwarf::DW_ATE_unsigned;
@@ -1846,7 +1834,7 @@ createSpecializedStructOrClassType(NominalOrBoundGenericNominalType *Type,
18461834
break;
18471835
}
18481836

1849-
case TypeKind::BuiltinNativeObject:
1837+
case TypeKind::BuiltinNativeObject:
18501838
case TypeKind::BuiltinBridgeObject:
18511839
case TypeKind::BuiltinRawPointer:
18521840
case TypeKind::BuiltinRawUnsafeContinuation:
@@ -1928,7 +1916,7 @@ createSpecializedStructOrClassType(NominalOrBoundGenericNominalType *Type,
19281916
assert(SizeInBits ==
19291917
CI.getTargetInfo().getPointerWidth(clang::LangAS::Default));
19301918
if (Opts.DebugInfoLevel > IRGenDebugInfoLevel::ASTTypes) {
1931-
if (ClassTy->isSpecialized())
1919+
if (ClassTy->isSpecialized())
19321920
return createSpecializedStructOrClassType(
19331921
ClassTy, Decl, Scope, L.File, L.Line, SizeInBits, AlignInBits,
19341922
Flags, MangledName);
@@ -2011,7 +1999,7 @@ createSpecializedStructOrClassType(NominalOrBoundGenericNominalType *Type,
20111999
auto L = getFileAndLocation(Decl);
20122000
unsigned FwdDeclLine = 0;
20132001

2014-
if (Opts.DebugInfoLevel > IRGenDebugInfoLevel::ASTTypes)
2002+
if (Opts.DebugInfoLevel > IRGenDebugInfoLevel::ASTTypes)
20152003
return createSpecializedStructOrClassType(
20162004
ClassTy, Decl, Scope, L.File, L.Line, SizeInBits, AlignInBits,
20172005
Flags, MangledName);
@@ -2315,8 +2303,8 @@ createSpecializedStructOrClassType(NominalOrBoundGenericNominalType *Type,
23152303
unsigned CachedSizeInBits = getSizeInBits(CachedType);
23162304
if ((SizeInBits && CachedSizeInBits != *SizeInBits) ||
23172305
(!SizeInBits && CachedSizeInBits)) {
2318-
// In some situation a specialized type is emitted with size 0, even if the real
2319-
// type has a size.
2306+
// In some situation a specialized type is emitted with size 0, even if
2307+
// the real type has a size.
23202308
if (DbgTy.getType()->isSpecialized() && SizeInBits && *SizeInBits > 0 &&
23212309
CachedSizeInBits == 0)
23222310
return true;
@@ -2336,7 +2324,7 @@ createSpecializedStructOrClassType(NominalOrBoundGenericNominalType *Type,
23362324
/// needed to correctly calculate the layout of more complex types built on
23372325
/// top of them.
23382326
void createSpecialStlibBuiltinTypes() {
2339-
if (Opts.DebugInfoLevel <= IRGenDebugInfoLevel::ASTTypes)
2327+
if (Opts.DebugInfoLevel <= IRGenDebugInfoLevel::ASTTypes)
23402328
return;
23412329
for (auto BuiltinType: IGM.getOrCreateSpecialStlibBuiltinTypes()) {
23422330
auto DbgTy = DebugTypeInfo::getFromTypeInfo(
@@ -2345,6 +2333,86 @@ createSpecializedStructOrClassType(NominalOrBoundGenericNominalType *Type,
23452333
}
23462334
}
23472335

2336+
struct OriginallyDefinedInFinder : public TypeWalker {
2337+
bool visitedOriginallyDefinedIn = false;
2338+
2339+
TypeWalker::Action walkToTypePre(Type T) override {
2340+
if (visitedOriginallyDefinedIn)
2341+
return TypeWalker::Action::Stop;
2342+
2343+
auto *TypeDecl = T->getNominalOrBoundGenericNominal();
2344+
if (!TypeDecl)
2345+
return TypeWalker::Action::Continue;
2346+
2347+
NominalTypeDecl *ParentDecl = TypeDecl;
2348+
while (llvm::isa_and_nonnull<NominalTypeDecl>(ParentDecl->getParent()))
2349+
ParentDecl = llvm::cast<NominalTypeDecl>(ParentDecl->getParent());
2350+
2351+
if (ParentDecl->getAttrs().hasAttribute<OriginallyDefinedInAttr>()) {
2352+
visitedOriginallyDefinedIn = true;
2353+
return TypeWalker::Action::Stop;
2354+
}
2355+
2356+
return TypeWalker::Action::Continue;
2357+
}
2358+
};
2359+
2360+
/// Returns true if the type's mangled name is affected by an
2361+
/// @_originallyDefinedIn annotation. This annotation can be on the type
2362+
/// itself, one of its generic arguments, etc.
2363+
bool containsOriginallyDefinedIn(Type T) {
2364+
OriginallyDefinedInFinder Walker;
2365+
T.walk(Walker);
2366+
return Walker.visitedOriginallyDefinedIn;
2367+
}
2368+
2369+
/// Returns the decl of the type's parent chain annotated by
2370+
/// @_originallyDefinedIn. Returns null if no type is annotated.
2371+
NominalTypeDecl *getDeclAnnotatedByOriginallyDefinedIn(DebugTypeInfo DbgTy) {
2372+
auto Type = DbgTy.getType();
2373+
auto *TypeDecl = Type->getNominalOrBoundGenericNominal();
2374+
if (!TypeDecl)
2375+
return nullptr;
2376+
2377+
// Find the outermost type, since only those can have @_originallyDefinedIn
2378+
// attached to them.
2379+
NominalTypeDecl *ParentDecl = TypeDecl;
2380+
while (llvm::isa_and_nonnull<NominalTypeDecl>(ParentDecl->getParent()))
2381+
ParentDecl = llvm::cast<NominalTypeDecl>(ParentDecl->getParent());
2382+
2383+
if (ParentDecl->getAttrs().hasAttribute<OriginallyDefinedInAttr>())
2384+
return ParentDecl;;
2385+
2386+
return nullptr;
2387+
}
2388+
2389+
/// If this is a nominal type that has the @_originallyDefinedIn
2390+
/// attribute, IRGenDebugInfo emits an imported declaration of the type as
2391+
/// a child of the real module. We do this so LLDB has enough
2392+
/// information to both find the type in reflection metadata (the module name
2393+
/// in the type's mangled name), and find it in the swiftmodule (the type's
2394+
/// imported declaration's parent module name).
2395+
void handleOriginallyDefinedIn(DebugTypeInfo DbgTy, llvm::DIType *DITy,
2396+
StringRef MangledName, llvm::DIFile *File) {
2397+
if (OriginallyDefinedInTypes.contains(MangledName))
2398+
return;
2399+
2400+
// Force the generation of the generic type parameters as forward
2401+
// declarations, as those types might be annotated with
2402+
// @_originallyDefinedIn.
2403+
if (auto *BoundDecl = llvm::dyn_cast<BoundGenericType>(DbgTy.getType()))
2404+
collectGenericParams(BoundDecl, /*AsForwardDeclarations=*/true);
2405+
2406+
NominalTypeDecl *OriginallyDefinedInDecl = getDeclAnnotatedByOriginallyDefinedIn(DbgTy);
2407+
if (!OriginallyDefinedInDecl)
2408+
return;
2409+
2410+
// Emit the imported declaration under the real swiftmodule the type lives on.
2411+
auto RealModule = getOrCreateContext(OriginallyDefinedInDecl->getParent());
2412+
DBuilder.createImportedDeclaration(RealModule, DITy, File, 0, MangledName);
2413+
OriginallyDefinedInTypes.insert(MangledName);
2414+
}
2415+
23482416
llvm::DIType *getOrCreateType(DebugTypeInfo DbgTy,
23492417
llvm::DIScope *Scope = nullptr) {
23502418
// Is this an empty type?
@@ -2389,7 +2457,18 @@ createSpecializedStructOrClassType(NominalOrBoundGenericNominalType *Type,
23892457
ClangDecl = AliasDecl->getClangDecl();
23902458
} else if (auto *ND = DbgTy.getType()->getNominalOrBoundGenericNominal()) {
23912459
TypeDecl = ND;
2392-
Context = ND->getParent();
2460+
// If this is an originally defined in type, we want to emit this type's
2461+
// scope to be the ABI module.
2462+
if (auto Attribute =
2463+
ND->getAttrs().getAttribute<OriginallyDefinedInAttr>()) {
2464+
auto Identifier = IGM.getSILModule().getASTContext().getIdentifier(
2465+
Attribute->OriginalModuleName);
2466+
void *Key = (void *)Identifier.get();
2467+
Scope =
2468+
getOrCreateModule(Key, TheCU, Attribute->OriginalModuleName, {});
2469+
} else {
2470+
Context = ND->getParent();
2471+
}
23932472
ClangDecl = ND->getClangDecl();
23942473
} else if (auto BNO = dyn_cast<BuiltinType>(DbgTy.getType())) {
23952474
Context = BNO->getASTContext().TheBuiltinModule;
@@ -2438,6 +2517,8 @@ createSpecializedStructOrClassType(NominalOrBoundGenericNominalType *Type,
24382517
FwdDeclTypes.emplace_back(
24392518
std::piecewise_construct, std::make_tuple(MangledName),
24402519
std::make_tuple(static_cast<llvm::Metadata *>(FwdDecl)));
2520+
2521+
handleOriginallyDefinedIn(DbgTy, FwdDecl, MangledName, getFile(Scope));
24412522
return FwdDecl;
24422523
}
24432524
llvm::DIType *DITy = createType(DbgTy, MangledName, Scope, getFile(Scope));
@@ -2466,6 +2547,7 @@ createSpecializedStructOrClassType(NominalOrBoundGenericNominalType *Type,
24662547
// Store it in the cache.
24672548
DITypeCache.insert({DbgTy.getType(), llvm::TrackingMDNodeRef(DITy)});
24682549

2550+
handleOriginallyDefinedIn(DbgTy, DITy, MangledName, getFile(Scope));
24692551
return DITy;
24702552
}
24712553
};
Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,8 @@
11
@available(macOS 10, *)
2-
@_originallyDefinedIn(module: "Barn", macOS 10.1) public struct Horse {}
2+
@_originallyDefinedIn(module: "Barn", macOS 10.1)
3+
public struct Horse {
4+
public init() {}
5+
}
6+
7+
@available(macOS 10, *)
8+
@_originallyDefinedIn(module: "Barn", macOS 10.1) public class Cow {}

test/DebugInfo/local_type_originally_defined_in.swift

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,19 @@ public func localTypeAliasTest(horse: Horse) {
1313

1414
let info = UnsafeMutablePointer<A>.allocate(capacity: 1)
1515
_ = info
16-
}
16+
}
17+
18+
public func localTypeAliasTest() -> Horse {
19+
typealias A = Int
20+
21+
let info = UnsafeMutablePointer<A>.allocate(capacity: 1)
22+
_ = info
23+
return Horse()
24+
}
25+
26+
public func localTypeAliasTestGeneric<T: Cow>(cow: T) {
27+
typealias A = Int
28+
29+
let info = UnsafeMutablePointer<A>.allocate(capacity: 1)
30+
_ = info
31+
}

test/DebugInfo/module_abi_name.swift

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,5 @@
33
class SomeClass {}
44
// CHECK: DICompositeType(tag: DW_TAG_structure_type, name: "SomeClass",{{.*}}runtimeLang: DW_LANG_Swift, identifier: "$s7Goodbye9SomeClassCD"
55

6-
@available(macOS 10.13, *)
7-
@_originallyDefinedIn(module: "ThirdModule", OSX 10.12)
8-
class DefinedElsewhere {}
9-
// CHECK: DICompositeType(tag: DW_TAG_structure_type, name: "DefinedElsewhere",{{.*}}runtimeLang: DW_LANG_Swift, identifier: "$s7Goodbye16DefinedElsewhereCD")
10-
116
let v1 = SomeClass()
12-
let v2 = DefinedElsewhere()
137

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// RUN: %target-swift-frontend -primary-file %s -emit-ir -g -module-name=Hello -module-abi-name Goodbye -emit-ir -o - | %FileCheck %s
2+
3+
// REQUIRES: OS=macosx
4+
//
5+
@available(iOS 1.0, macOS 1.0, tvOS 1.0, watchOS 1.0, *)
6+
@_originallyDefinedIn(
7+
module: "ThirdModule", iOS 2.0, macOS 2.0, tvOS 2.0, watchOS 2.0)
8+
public class DefinedElsewhere {}
9+
// CHECK: DICompositeType(tag: DW_TAG_structure_type, name: "DefinedElsewhere",{{.*}}runtimeLang: DW_LANG_Swift, identifier: "$s11ThirdModule16DefinedElsewhereCD")
10+
11+
let v2 = DefinedElsewhere()

0 commit comments

Comments
 (0)