Skip to content

Commit 05786df

Browse files
Merge pull request #78271 from augusto2112/orig-defined-in-6
[cherry-pick][DebugInfo] Fix handling of @_originallyDefinedIn types
2 parents 02d91e8 + f246e6c commit 05786df

9 files changed

+232
-58
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
"mangling type for debugger", 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
@@ -978,7 +978,7 @@ const ExternalSourceLocs *Decl::getSerializedLocs() const {
978978
StringRef Decl::getAlternateModuleName() const {
979979
for (auto *Att: Attrs) {
980980
if (auto *OD = dyn_cast<OriginallyDefinedInAttr>(Att)) {
981-
if (OD->isActivePlatform(getASTContext())) {
981+
if (!OD->isInvalid() && OD->isActivePlatform(getASTContext())) {
982982
return OD->OriginalModuleName;
983983
}
984984
}

lib/IRGen/IRGenDebugInfo.cpp

Lines changed: 133 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,17 @@
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"
33+
#include "swift/AST/ParameterList.h"
3134
#include "swift/AST/Pattern.h"
3235
#include "swift/AST/TypeDifferenceVisitor.h"
36+
#include "swift/AST/TypeWalker.h"
3337
#include "swift/Basic/Assertions.h"
3438
#include "swift/Basic/Compiler.h"
3539
#include "swift/Basic/SourceManager.h"
@@ -137,7 +141,7 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
137141
return Line == other.Line && Column == other.Column && File == other.File;
138142
}
139143
};
140-
144+
141145
/// Various caches.
142146
/// \{
143147
llvm::StringSet<> VarNames;
@@ -150,6 +154,7 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
150154
llvm::DenseMap<const void *, llvm::TrackingMDNodeRef> DIModuleCache;
151155
llvm::StringMap<llvm::TrackingMDNodeRef> DIFileCache;
152156
llvm::StringMap<llvm::TrackingMDNodeRef> RuntimeErrorFnCache;
157+
llvm::StringSet<> OriginallyDefinedInTypes;
153158
TrackingDIRefMap DIRefMap;
154159
TrackingDIRefMap InnerTypeCache;
155160
/// \}
@@ -1026,9 +1031,12 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
10261031
Mangle::ASTMangler Mangler;
10271032
std::string Result = Mangler.mangleTypeForDebugger(Ty, Sig);
10281033

1034+
bool IsTypeOriginallyDefinedIn =
1035+
containsOriginallyDefinedIn(DbgTy.getType());
10291036
// TODO(https://github.com/apple/swift/issues/57699): We currently cannot round trip some C++ types.
1037+
// There's no way to round trip when respecting @_originallyDefinedIn for a type.
10301038
if (!Opts.DisableRoundTripDebugTypes &&
1031-
!Ty->getASTContext().LangOpts.EnableCXXInterop) {
1039+
!Ty->getASTContext().LangOpts.EnableCXXInterop && !IsTypeOriginallyDefinedIn) {
10321040
// Make sure we can reconstruct mangled types for the debugger.
10331041
auto &Ctx = Ty->getASTContext();
10341042
Type Reconstructed = Demangle::getTypeForMangling(Ctx, Result, Sig);
@@ -1506,7 +1514,7 @@ createSpecializedStructOrClassType(NominalOrBoundGenericNominalType *Type,
15061514
/// anchor any typedefs that may appear in parameters so they can be
15071515
/// resolved in the debugger without needing to query the Swift module.
15081516
llvm::DINodeArray
1509-
collectGenericParams(NominalOrBoundGenericNominalType *BGT) {
1517+
collectGenericParams(NominalOrBoundGenericNominalType *BGT, bool AsForwardDeclarations = false) {
15101518

15111519
// Collect the generic args from the type and its parent.
15121520
std::vector<Type> GenericArgs;
@@ -1521,7 +1529,8 @@ createSpecializedStructOrClassType(NominalOrBoundGenericNominalType *Type,
15211529
SmallVector<llvm::Metadata *, 16> TemplateParams;
15221530
for (auto Arg : GenericArgs) {
15231531
DebugTypeInfo ParamDebugType;
1524-
if (Opts.DebugInfoLevel > IRGenDebugInfoLevel::ASTTypes)
1532+
if (Opts.DebugInfoLevel > IRGenDebugInfoLevel::ASTTypes &&
1533+
!AsForwardDeclarations)
15251534
// For the DwarfTypes level don't generate just a forward declaration
15261535
// for the generic type parameters.
15271536
ParamDebugType = DebugTypeInfo::getFromTypeInfo(
@@ -1789,39 +1798,19 @@ createSpecializedStructOrClassType(NominalOrBoundGenericNominalType *Type,
17891798
}
17901799

17911800
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-
}
18121801

18131802
// Here goes!
18141803
switch (BaseTy->getKind()) {
18151804
case TypeKind::BuiltinUnboundGeneric:
18161805
llvm_unreachable("not a real type");
1817-
1806+
18181807
case TypeKind::BuiltinFixedArray: {
18191808
// TODO: provide proper array debug info
18201809
unsigned FwdDeclLine = 0;
18211810
return createOpaqueStruct(Scope, "Builtin.FixedArray", MainFile, FwdDeclLine,
18221811
SizeInBits, AlignInBits, Flags, MangledName);
18231812
}
1824-
1813+
18251814
case TypeKind::BuiltinPackIndex:
18261815
case TypeKind::BuiltinInteger: {
18271816
Encoding = llvm::dwarf::DW_ATE_unsigned;
@@ -1845,7 +1834,7 @@ createSpecializedStructOrClassType(NominalOrBoundGenericNominalType *Type,
18451834
break;
18461835
}
18471836

1848-
case TypeKind::BuiltinNativeObject:
1837+
case TypeKind::BuiltinNativeObject:
18491838
case TypeKind::BuiltinBridgeObject:
18501839
case TypeKind::BuiltinRawPointer:
18511840
case TypeKind::BuiltinRawUnsafeContinuation:
@@ -1927,7 +1916,7 @@ createSpecializedStructOrClassType(NominalOrBoundGenericNominalType *Type,
19271916
assert(SizeInBits ==
19281917
CI.getTargetInfo().getPointerWidth(clang::LangAS::Default));
19291918
if (Opts.DebugInfoLevel > IRGenDebugInfoLevel::ASTTypes) {
1930-
if (ClassTy->isSpecialized())
1919+
if (ClassTy->isSpecialized())
19311920
return createSpecializedStructOrClassType(
19321921
ClassTy, Decl, Scope, L.File, L.Line, SizeInBits, AlignInBits,
19331922
Flags, MangledName);
@@ -2010,7 +1999,7 @@ createSpecializedStructOrClassType(NominalOrBoundGenericNominalType *Type,
20101999
auto L = getFileAndLocation(Decl);
20112000
unsigned FwdDeclLine = 0;
20122001

2013-
if (Opts.DebugInfoLevel > IRGenDebugInfoLevel::ASTTypes)
2002+
if (Opts.DebugInfoLevel > IRGenDebugInfoLevel::ASTTypes)
20142003
return createSpecializedStructOrClassType(
20152004
ClassTy, Decl, Scope, L.File, L.Line, SizeInBits, AlignInBits,
20162005
Flags, MangledName);
@@ -2308,8 +2297,8 @@ createSpecializedStructOrClassType(NominalOrBoundGenericNominalType *Type,
23082297
unsigned CachedSizeInBits = getSizeInBits(CachedType);
23092298
if ((SizeInBits && CachedSizeInBits != *SizeInBits) ||
23102299
(!SizeInBits && CachedSizeInBits)) {
2311-
// In some situation a specialized type is emitted with size 0, even if the real
2312-
// type has a size.
2300+
// In some situation a specialized type is emitted with size 0, even if
2301+
// the real type has a size.
23132302
if (DbgTy.getType()->isSpecialized() && SizeInBits && *SizeInBits > 0 &&
23142303
CachedSizeInBits == 0)
23152304
return true;
@@ -2329,7 +2318,7 @@ createSpecializedStructOrClassType(NominalOrBoundGenericNominalType *Type,
23292318
/// needed to correctly calculate the layout of more complex types built on
23302319
/// top of them.
23312320
void createSpecialStlibBuiltinTypes() {
2332-
if (Opts.DebugInfoLevel <= IRGenDebugInfoLevel::ASTTypes)
2321+
if (Opts.DebugInfoLevel <= IRGenDebugInfoLevel::ASTTypes)
23332322
return;
23342323
for (auto BuiltinType: IGM.getOrCreateSpecialStlibBuiltinTypes()) {
23352324
auto DbgTy = DebugTypeInfo::getFromTypeInfo(
@@ -2338,6 +2327,103 @@ createSpecializedStructOrClassType(NominalOrBoundGenericNominalType *Type,
23382327
}
23392328
}
23402329

2330+
/// A TypeWalker that finds if a given type's mangling is affected by an
2331+
/// @_originallyDefinedIn annotation.
2332+
struct OriginallyDefinedInFinder : public TypeWalker {
2333+
bool visitedOriginallyDefinedIn = false;
2334+
2335+
TypeWalker::Action walkToTypePre(Type T) override {
2336+
if (visitedOriginallyDefinedIn)
2337+
return TypeWalker::Action::Stop;
2338+
2339+
// A typealias inside a function used that function's signature as part of
2340+
// its mangling, so check if any types in the generic signature are
2341+
// annotated with @_originallyDefinedIn.
2342+
if (auto *TAT = llvm::dyn_cast<TypeAliasType>(T)) {
2343+
auto D = TAT->getDecl()->getDeclContext();
2344+
if (auto AFD = llvm::dyn_cast<AbstractFunctionDecl>(D)) {
2345+
OriginallyDefinedInFinder InnerWalker;
2346+
AFD->getInterfaceType().walk(InnerWalker);
2347+
if (InnerWalker.visitedOriginallyDefinedIn) {
2348+
visitedOriginallyDefinedIn = true;
2349+
return TypeWalker::Action::Stop;
2350+
}
2351+
}
2352+
}
2353+
2354+
auto *TypeDecl = T->getNominalOrBoundGenericNominal();
2355+
if (!TypeDecl)
2356+
return TypeWalker::Action::Continue;
2357+
2358+
NominalTypeDecl *ParentDecl = TypeDecl;
2359+
while (llvm::isa_and_nonnull<NominalTypeDecl>(ParentDecl->getParent()))
2360+
ParentDecl = llvm::cast<NominalTypeDecl>(ParentDecl->getParent());
2361+
2362+
if (ParentDecl->getAttrs().hasAttribute<OriginallyDefinedInAttr>()) {
2363+
visitedOriginallyDefinedIn = true;
2364+
return TypeWalker::Action::Stop;
2365+
}
2366+
2367+
return TypeWalker::Action::Continue;
2368+
}
2369+
};
2370+
2371+
/// Returns true if the type's mangled name is affected by an
2372+
/// @_originallyDefinedIn annotation. This annotation can be on the type
2373+
/// itself, one of its generic arguments, etc.
2374+
bool containsOriginallyDefinedIn(Type T) {
2375+
OriginallyDefinedInFinder Walker;
2376+
T.walk(Walker);
2377+
return Walker.visitedOriginallyDefinedIn;
2378+
}
2379+
2380+
/// Returns the decl of the type's parent chain annotated by
2381+
/// @_originallyDefinedIn. Returns null if no type is annotated.
2382+
NominalTypeDecl *getDeclAnnotatedByOriginallyDefinedIn(DebugTypeInfo DbgTy) {
2383+
auto Type = DbgTy.getType();
2384+
auto *TypeDecl = Type->getNominalOrBoundGenericNominal();
2385+
if (!TypeDecl)
2386+
return nullptr;
2387+
2388+
// Find the outermost type, since only those can have @_originallyDefinedIn
2389+
// attached to them.
2390+
NominalTypeDecl *ParentDecl = TypeDecl;
2391+
while (llvm::isa_and_nonnull<NominalTypeDecl>(ParentDecl->getParent()))
2392+
ParentDecl = llvm::cast<NominalTypeDecl>(ParentDecl->getParent());
2393+
2394+
if (ParentDecl->getAttrs().hasAttribute<OriginallyDefinedInAttr>())
2395+
return ParentDecl;;
2396+
2397+
return nullptr;
2398+
}
2399+
2400+
/// If this is a nominal type that has the @_originallyDefinedIn
2401+
/// attribute, IRGenDebugInfo emits an imported declaration of the type as
2402+
/// a child of the real module. We do this so LLDB has enough
2403+
/// information to both find the type in reflection metadata (the module name
2404+
/// in the type's mangled name), and find it in the swiftmodule (the type's
2405+
/// imported declaration's parent module name).
2406+
void handleOriginallyDefinedIn(DebugTypeInfo DbgTy, llvm::DIType *DITy,
2407+
StringRef MangledName, llvm::DIFile *File) {
2408+
if (OriginallyDefinedInTypes.contains(MangledName))
2409+
return;
2410+
2411+
// Force the generation of the generic type parameters as forward
2412+
// declarations, as those types might be annotated with
2413+
// @_originallyDefinedIn.
2414+
if (auto *BoundDecl = llvm::dyn_cast<BoundGenericType>(DbgTy.getType()))
2415+
collectGenericParams(BoundDecl, /*AsForwardDeclarations=*/true);
2416+
2417+
NominalTypeDecl *OriginallyDefinedInDecl = getDeclAnnotatedByOriginallyDefinedIn(DbgTy);
2418+
if (!OriginallyDefinedInDecl)
2419+
return;
2420+
2421+
// Emit the imported declaration under the real swiftmodule the type lives on.
2422+
auto RealModule = getOrCreateContext(OriginallyDefinedInDecl->getParent());
2423+
DBuilder.createImportedDeclaration(RealModule, DITy, File, 0, MangledName);
2424+
OriginallyDefinedInTypes.insert(MangledName);
2425+
}
2426+
23412427
llvm::DIType *getOrCreateType(DebugTypeInfo DbgTy,
23422428
llvm::DIScope *Scope = nullptr) {
23432429
// Is this an empty type?
@@ -2382,7 +2468,18 @@ createSpecializedStructOrClassType(NominalOrBoundGenericNominalType *Type,
23822468
ClangDecl = AliasDecl->getClangDecl();
23832469
} else if (auto *ND = DbgTy.getType()->getNominalOrBoundGenericNominal()) {
23842470
TypeDecl = ND;
2385-
Context = ND->getParent();
2471+
// If this is an originally defined in type, we want to emit this type's
2472+
// scope to be the ABI module.
2473+
if (auto Attribute =
2474+
ND->getAttrs().getAttribute<OriginallyDefinedInAttr>()) {
2475+
auto Identifier = IGM.getSILModule().getASTContext().getIdentifier(
2476+
Attribute->OriginalModuleName);
2477+
void *Key = (void *)Identifier.get();
2478+
Scope =
2479+
getOrCreateModule(Key, TheCU, Attribute->OriginalModuleName, {});
2480+
} else {
2481+
Context = ND->getParent();
2482+
}
23862483
ClangDecl = ND->getClangDecl();
23872484
} else if (auto BNO = dyn_cast<BuiltinType>(DbgTy.getType())) {
23882485
Context = BNO->getASTContext().TheBuiltinModule;
@@ -2431,6 +2528,8 @@ createSpecializedStructOrClassType(NominalOrBoundGenericNominalType *Type,
24312528
FwdDeclTypes.emplace_back(
24322529
std::piecewise_construct, std::make_tuple(MangledName),
24332530
std::make_tuple(static_cast<llvm::Metadata *>(FwdDecl)));
2531+
2532+
handleOriginallyDefinedIn(DbgTy, FwdDecl, MangledName, getFile(Scope));
24342533
return FwdDecl;
24352534
}
24362535
llvm::DIType *DITy = createType(DbgTy, MangledName, Scope, getFile(Scope));
@@ -2459,6 +2558,7 @@ createSpecializedStructOrClassType(NominalOrBoundGenericNominalType *Type,
24592558
// Store it in the cache.
24602559
DITypeCache.insert({DbgTy.getType(), llvm::TrackingMDNodeRef(DITy)});
24612560

2561+
handleOriginallyDefinedIn(DbgTy, DITy, MangledName, getFile(Scope));
24622562
return DITy;
24632563
}
24642564
};
Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,22 @@
1-
@available(macOS 10, *)
2-
@_originallyDefinedIn(module: "Barn", macOS 10.1) public struct Horse {}
1+
@_originallyDefinedIn(
2+
module: "Barn", iOS 2.0, macOS 2.0, tvOS 2.0, watchOS 2.0)
3+
@available(iOS 1.0, macOS 1.0, tvOS 1.0, watchOS 1.0, *)
4+
public struct Horse {
5+
public init() {}
6+
}
7+
8+
@_originallyDefinedIn(
9+
module: "Barn", iOS 2.0, macOS 2.0, tvOS 2.0, watchOS 2.0)
10+
@available(iOS 1.0, macOS 1.0, tvOS 1.0, watchOS 1.0, *)
11+
public class Cow {
12+
public init() {}
13+
}
14+
15+
16+
@_originallyDefinedIn(
17+
module: "Barn", iOS 2.0, macOS 2.0, tvOS 2.0, watchOS 2.0)
18+
@available(iOS 1.0, macOS 1.0, tvOS 1.0, watchOS 1.0, *)
19+
public class Sheep {
20+
public init() {}
21+
}
22+
Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
// RUN: %empty-directory(%t)
22
// RUN: %target-swift-frontend -emit-module -emit-module-path %t/local_type_originally_defined_in_other.swiftmodule %S/Inputs/local_type_originally_defined_in_other.swift
3-
// RUN: %target-swift-frontend -I%t -g -emit-ir %s
3+
// RUN: %target-swift-frontend -I%t -g -emit-ir %s -o - | %FileCheck %s
4+
// REQUIRES: OS=macosx
45

56
import local_type_originally_defined_in_other
67

8+
public func definedInOtherModule() {
9+
let s = Sheep()
10+
// CHECK: DICompositeType(tag: DW_TAG_structure_type, name: "Sheep"{{.*}}identifier: "$s4Barn5SheepCD
11+
}
712
public func localTypeAliasTest(horse: Horse) {
813
// The local type mangling for 'A' mentions 'Horse', which must
914
// be mangled using it's current module name, and not the
@@ -13,4 +18,21 @@ public func localTypeAliasTest(horse: Horse) {
1318

1419
let info = UnsafeMutablePointer<A>.allocate(capacity: 1)
1520
_ = info
16-
}
21+
// CHECK: DIDerivedType(tag: DW_TAG_typedef, name: "$s32local_type_originally_defined_in0A13TypeAliasTest5horsey4Barn5HorseV_tF1AL_aD"
22+
}
23+
24+
public func localTypeAliasTest() -> Horse {
25+
typealias B = Int
26+
27+
let info = UnsafeMutablePointer<B>.allocate(capacity: 1)
28+
_ = info
29+
return Horse()
30+
// CHECK: DIDerivedType(tag: DW_TAG_typedef, name: "$s32local_type_originally_defined_in0A13TypeAliasTest4Barn5HorseVyF1BL_aD"
31+
}
32+
33+
public func localTypeAliasTestGeneric<T: Cow>(cow: T) {
34+
typealias C = Int
35+
36+
let info = UnsafeMutablePointer<C>.allocate(capacity: 1)
37+
_ = info
38+
}

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

0 commit comments

Comments
 (0)