Skip to content

Commit ae128a3

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 ae128a3

9 files changed

+207
-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: 131 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(IGM.Context);
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);
@@ -1507,7 +1515,7 @@ createSpecializedStructOrClassType(NominalOrBoundGenericNominalType *Type,
15071515
/// anchor any typedefs that may appear in parameters so they can be
15081516
/// resolved in the debugger without needing to query the Swift module.
15091517
llvm::DINodeArray
1510-
collectGenericParams(NominalOrBoundGenericNominalType *BGT) {
1518+
collectGenericParams(NominalOrBoundGenericNominalType *BGT, bool AsForwardDeclarations = false) {
15111519

15121520
// Collect the generic args from the type and its parent.
15131521
std::vector<Type> GenericArgs;
@@ -1522,7 +1530,8 @@ createSpecializedStructOrClassType(NominalOrBoundGenericNominalType *Type,
15221530
SmallVector<llvm::Metadata *, 16> TemplateParams;
15231531
for (auto Arg : GenericArgs) {
15241532
DebugTypeInfo ParamDebugType;
1525-
if (Opts.DebugInfoLevel > IRGenDebugInfoLevel::ASTTypes)
1533+
if (Opts.DebugInfoLevel > IRGenDebugInfoLevel::ASTTypes &&
1534+
!AsForwardDeclarations)
15261535
// For the DwarfTypes level don't generate just a forward declaration
15271536
// for the generic type parameters.
15281537
ParamDebugType = DebugTypeInfo::getFromTypeInfo(
@@ -1790,39 +1799,19 @@ createSpecializedStructOrClassType(NominalOrBoundGenericNominalType *Type,
17901799
}
17911800

17921801
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-
}
18131802

18141803
// Here goes!
18151804
switch (BaseTy->getKind()) {
18161805
case TypeKind::BuiltinUnboundGeneric:
18171806
llvm_unreachable("not a real type");
1818-
1807+
18191808
case TypeKind::BuiltinFixedArray: {
18201809
// TODO: provide proper array debug info
18211810
unsigned FwdDeclLine = 0;
18221811
return createOpaqueStruct(Scope, "Builtin.FixedArray", MainFile, FwdDeclLine,
18231812
SizeInBits, AlignInBits, Flags, MangledName);
18241813
}
1825-
1814+
18261815
case TypeKind::BuiltinPackIndex:
18271816
case TypeKind::BuiltinInteger: {
18281817
Encoding = llvm::dwarf::DW_ATE_unsigned;
@@ -1846,7 +1835,7 @@ createSpecializedStructOrClassType(NominalOrBoundGenericNominalType *Type,
18461835
break;
18471836
}
18481837

1849-
case TypeKind::BuiltinNativeObject:
1838+
case TypeKind::BuiltinNativeObject:
18501839
case TypeKind::BuiltinBridgeObject:
18511840
case TypeKind::BuiltinRawPointer:
18521841
case TypeKind::BuiltinRawUnsafeContinuation:
@@ -1928,7 +1917,7 @@ createSpecializedStructOrClassType(NominalOrBoundGenericNominalType *Type,
19281917
assert(SizeInBits ==
19291918
CI.getTargetInfo().getPointerWidth(clang::LangAS::Default));
19301919
if (Opts.DebugInfoLevel > IRGenDebugInfoLevel::ASTTypes) {
1931-
if (ClassTy->isSpecialized())
1920+
if (ClassTy->isSpecialized())
19321921
return createSpecializedStructOrClassType(
19331922
ClassTy, Decl, Scope, L.File, L.Line, SizeInBits, AlignInBits,
19341923
Flags, MangledName);
@@ -2011,7 +2000,7 @@ createSpecializedStructOrClassType(NominalOrBoundGenericNominalType *Type,
20112000
auto L = getFileAndLocation(Decl);
20122001
unsigned FwdDeclLine = 0;
20132002

2014-
if (Opts.DebugInfoLevel > IRGenDebugInfoLevel::ASTTypes)
2003+
if (Opts.DebugInfoLevel > IRGenDebugInfoLevel::ASTTypes)
20152004
return createSpecializedStructOrClassType(
20162005
ClassTy, Decl, Scope, L.File, L.Line, SizeInBits, AlignInBits,
20172006
Flags, MangledName);
@@ -2315,8 +2304,8 @@ createSpecializedStructOrClassType(NominalOrBoundGenericNominalType *Type,
23152304
unsigned CachedSizeInBits = getSizeInBits(CachedType);
23162305
if ((SizeInBits && CachedSizeInBits != *SizeInBits) ||
23172306
(!SizeInBits && CachedSizeInBits)) {
2318-
// In some situation a specialized type is emitted with size 0, even if the real
2319-
// type has a size.
2307+
// In some situation a specialized type is emitted with size 0, even if
2308+
// the real type has a size.
23202309
if (DbgTy.getType()->isSpecialized() && SizeInBits && *SizeInBits > 0 &&
23212310
CachedSizeInBits == 0)
23222311
return true;
@@ -2336,7 +2325,7 @@ createSpecializedStructOrClassType(NominalOrBoundGenericNominalType *Type,
23362325
/// needed to correctly calculate the layout of more complex types built on
23372326
/// top of them.
23382327
void createSpecialStlibBuiltinTypes() {
2339-
if (Opts.DebugInfoLevel <= IRGenDebugInfoLevel::ASTTypes)
2328+
if (Opts.DebugInfoLevel <= IRGenDebugInfoLevel::ASTTypes)
23402329
return;
23412330
for (auto BuiltinType: IGM.getOrCreateSpecialStlibBuiltinTypes()) {
23422331
auto DbgTy = DebugTypeInfo::getFromTypeInfo(
@@ -2345,6 +2334,101 @@ createSpecializedStructOrClassType(NominalOrBoundGenericNominalType *Type,
23452334
}
23462335
}
23472336

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

2566+
handleOriginallyDefinedIn(DbgTy, DITy, MangledName, getFile(Scope));
24692567
return DITy;
24702568
}
24712569
};
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)