Skip to content

Commit 7bd0b96

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 7bd0b96

9 files changed

+227
-57
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: 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(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,103 @@ createSpecializedStructOrClassType(NominalOrBoundGenericNominalType *Type,
23452334
}
23462335
}
23472336

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

2568+
handleOriginallyDefinedIn(DbgTy, DITy, MangledName, getFile(Scope));
24692569
return DITy;
24702570
}
24712571
};
Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,19 @@
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)
9+
public class Cow {
10+
public init() {}
11+
}
12+
13+
14+
@available(macOS 10, *)
15+
@_originallyDefinedIn(module: "Barn", macOS 10.1)
16+
public class Sheep {
17+
public init() {}
18+
}
19+
Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
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
44

55
import local_type_originally_defined_in_other
66

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

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

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)