mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[Debug Info] Do not emit children of bound generic types
This reverts the problematic parts of
fcbebc51c7 which had caused a lot of
unintended fallout, while preserving the actual feature supported by
the patch.
Before that patch (fcbeb), and after this one, we don't emit members
of specialized bound generic types, because these can be reconstructed
by substituting the "template parameters" in the unspecialized
type. This patch carves out an exception for inline arrays, because
DWARF has special support for arrays, which allows debuggers to reason
about them without needing special support.
rdar://146326633
This commit is contained in:
@@ -1226,8 +1226,7 @@ private:
|
||||
return DITy;
|
||||
}
|
||||
|
||||
std::pair<bool, Type>
|
||||
getUnsubstituedType(Type Ty, StringRef MangledName) {
|
||||
std::pair<bool, Type> getUnsubstitutedType(Type Ty, StringRef MangledName) {
|
||||
if (!Ty)
|
||||
return {false,{}};
|
||||
// Go from Pair<Int, Double> to Pair<T, U>.
|
||||
@@ -1252,7 +1251,7 @@ private:
|
||||
llvm::DIScope *Scope, llvm::DIFile *File,
|
||||
unsigned Line, llvm::DINode::DIFlags Flags) {
|
||||
auto [IsUnsubstituted, UnsubstitutedTy] =
|
||||
getUnsubstituedType(EnumTy, MangledName);
|
||||
getUnsubstitutedType(EnumTy, MangledName);
|
||||
auto UnsubstitutedDbgTy = DebugTypeInfo::getFromTypeInfo(
|
||||
UnsubstitutedTy, IGM.getTypeInfoForUnlowered(UnsubstitutedTy), IGM);
|
||||
if (IsUnsubstituted)
|
||||
@@ -1301,7 +1300,7 @@ private:
|
||||
Name);
|
||||
|
||||
auto [IsUnsubstitued, UnsubstitutedType] =
|
||||
getUnsubstituedType(Type, MangledName);
|
||||
getUnsubstitutedType(Type, MangledName);
|
||||
auto UnsubstitutedDbgTy = DebugTypeInfo::getFromTypeInfo(
|
||||
UnsubstitutedType, IGM.getTypeInfoForUnlowered(UnsubstitutedType), IGM);
|
||||
if (IsUnsubstitued)
|
||||
@@ -1326,19 +1325,24 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
// Recursive types such as `class A<B> { let a : A<A<B>> }` would produce an
|
||||
// infinite chain of expansions for the type of `a`. Break these cycles by
|
||||
// emitting any bound generics that still have type parameters as forward
|
||||
// declarations.
|
||||
if (Type->hasTypeParameter() || Type->hasPrimaryArchetype())
|
||||
return createOpaqueStructWithSizedContainer(
|
||||
Scope, Decl ? Decl->getNameStr() : "", File, Line, SizeInBits,
|
||||
AlignInBits, Flags, MangledName, collectGenericParams(Type, true),
|
||||
UnsubstitutedDITy);
|
||||
// Generally, we don't emit members of a specialized bound generic, because
|
||||
// these can be reconstructed by substituting the "template parameters" in
|
||||
// the unspecialized type. We make an exception for inline arrays, because
|
||||
// DWARF has special support for arrays.
|
||||
if (Type->isInlineArray() && !Type->hasTypeParameter() &&
|
||||
!Type->hasPrimaryArchetype())
|
||||
// Create the substituted type.
|
||||
return createStructType(Type, Decl, Scope, File, Line, SizeInBits,
|
||||
AlignInBits, Flags, MangledName,
|
||||
UnsubstitutedDITy);
|
||||
|
||||
// Create the substituted type.
|
||||
return createStructType(Type, Decl, Scope, File, Line, SizeInBits,
|
||||
AlignInBits, Flags, MangledName, UnsubstitutedDITy);
|
||||
// Create the substituted type (without members).
|
||||
llvm::DIType *SpecializedDITy = createOpaqueStructWithSizedContainer(
|
||||
Scope, Decl ? Decl->getNameStr() : "", File, Line, SizeInBits,
|
||||
AlignInBits, Flags, MangledName, collectGenericParams(Type),
|
||||
UnsubstitutedDITy);
|
||||
DBuilder.replaceTemporary(std::move(FwdDecl), SpecializedDITy);
|
||||
return SpecializedDITy;
|
||||
}
|
||||
|
||||
/// Create debug information for an enum with a raw type (enum E : Int {}).
|
||||
@@ -1600,6 +1604,10 @@ private:
|
||||
|
||||
llvm::Metadata *Elements[] = {DBuilder.createMemberType(
|
||||
Scope, "", File, 0, SizeInBits, AlignInBits, 0, Flags, UniqueType)};
|
||||
// FIXME: It's a limitation of LLVM that a forward declaration cannot have a
|
||||
// specificationOf, so this attritbute is put on the sized container type
|
||||
// instead. This is confusing consumers, and LLDB has to go out of its way
|
||||
// to parse these confusing types as intended.
|
||||
return DBuilder.createStructType(
|
||||
Scope, "", File, Line, SizeInBits, AlignInBits, Flags,
|
||||
/* DerivedFrom */ nullptr, DBuilder.getOrCreateArray(Elements),
|
||||
@@ -2338,7 +2346,7 @@ private:
|
||||
if (!isa<llvm::DICompositeType>(CachedType))
|
||||
return true;
|
||||
bool IsUnsubstituted =
|
||||
getUnsubstituedType(DbgTy.getType(), getMangledName(DbgTy).Canonical)
|
||||
getUnsubstitutedType(DbgTy.getType(), getMangledName(DbgTy).Canonical)
|
||||
.first;
|
||||
std::optional<uint64_t> SizeInBits;
|
||||
if (!IsUnsubstituted)
|
||||
|
||||
@@ -12,7 +12,7 @@ public let s = S<Int>(t: 0)
|
||||
// CHECK: ![[INTPARAM]] = !DITemplateTypeParameter(type: ![[INT:[0-9]+]])
|
||||
// CHECK: ![[INT]] = !DICompositeType(tag: DW_TAG_structure_type, {{.*}}"$sSiD"
|
||||
|
||||
// DWARF-DAG: !DICompositeType(tag: DW_TAG_structure_type, {{.*}}templateParams: ![[PARAMS:[0-9]+]]{{.*}}identifier: "$s18BoundGenericStruct1SVySiGD"{{.*}}specification:
|
||||
// DWARF-DAG: !DICompositeType(tag: DW_TAG_structure_type, {{.*}}name: "$s18BoundGenericStruct1SVySiGD"{{.*}}templateParams: ![[PARAMS:[0-9]+]]
|
||||
|
||||
// DWARF-DAG: ![[PARAMS]] = !{![[INTPARAM:[0-9]+]]}
|
||||
// DWARF-DAG: ![[INTPARAM]] = !DITemplateTypeParameter(type: ![[INT:[0-9]+]])
|
||||
@@ -34,14 +34,16 @@ public let inner = S2<Double>.Inner(t:4.2)
|
||||
// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "$s18BoundGenericStruct2S2VyxGD",
|
||||
// CHECK-SAME: flags: DIFlagFwdDecl, runtimeLang: DW_LANG_Swift)
|
||||
|
||||
// DWARF-DAG: !DICompositeType(tag: DW_TAG_structure_type, name: "Inner", scope: ![[SCOPE1:[0-9]+]],{{.*}} size: 64, elements: ![[ELEMENTS1:[0-9]+]], {{.*}}templateParams: ![[PARAMS2:[0-9]+]], identifier: "$s18BoundGenericStruct2S2V5InnerVySd_GD", specification: ![[SPECIFICATION:[0-9]+]])
|
||||
// DWARF-DAG: !DICompositeType(tag: DW_TAG_structure_type, name: "$s18BoundGenericStruct2S2V5InnerVySd_GD", scope: ![[SCOPE1:[0-9]+]], {{.*}}flags: DIFlagFwdDecl, runtimeLang: DW_LANG_Swift, templateParams: ![[PARAMS2:[0-9]+]])
|
||||
|
||||
// DWARF-DAG: ![[SCOPE1]] = !DICompositeType(tag: DW_TAG_structure_type, name: "$s18BoundGenericStruct2S2VyxGD",
|
||||
|
||||
// DWARF-DAG: ![[PARAMS2]] = !{![[PARAMS3:[0-9]+]]}
|
||||
// DWARF-DAG: ![[PARAMS3]] = !DITemplateTypeParameter(type: ![[PARAMS4:[0-9]+]])
|
||||
// DWARF-DAG: ![[PARAMS4]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Double"{{.*}} size: 64, {{.*}}runtimeLang: DW_LANG_Swift,{{.*}} identifier: "$sSdD")
|
||||
|
||||
// DWARF-DAG: [[SPECIFICATION]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Inner", {{.*}}runtimeLang: DW_LANG_Swift, identifier: "$s18BoundGenericStruct2S2V5InnerVyx_GD")
|
||||
// DWARF-DAG: ![[SPECIFICATION:[0-9]+]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Inner", {{.*}}elements: ![[ELEMENTS1:[0-9]+]], runtimeLang: DW_LANG_Swift, identifier: "$s18BoundGenericStruct2S2V5InnerVyx_GD")
|
||||
// DWARF-DAG: !DICompositeType(tag: DW_TAG_structure_type, {{.*}}line: 26, size: 64, {{.*}}specification: ![[SPECIFICATION]]
|
||||
|
||||
// DWARF-DAG: ![[ELEMENTS1]] = !{![[ELEMENTS2:[0-9]+]]}
|
||||
|
||||
|
||||
@@ -23,5 +23,5 @@ typedef struct S2 {
|
||||
|
||||
public var v: UnsafeMutablePointer<S1_t>? = nil
|
||||
|
||||
// CHECK: !DICompositeType(tag: DW_TAG_structure_type, {{.*}} identifier: "$eSpySo4S1_taGD"
|
||||
// CHECK: !DICompositeType(tag: DW_TAG_structure_type, {{.*}} identifier: "$eSpySo2S2VGD"
|
||||
// CHECK-DAG: !DICompositeType(tag: DW_TAG_structure_type, {{.*}}name: "$eSpySo4S1_taGD"
|
||||
// CHECK-DAG: !DICompositeType(tag: DW_TAG_structure_type, {{.*}}name: "$eSpySo2S2VGD"
|
||||
|
||||
@@ -16,14 +16,14 @@ struct Traits32: TraitsProtocol {
|
||||
let v : MyClass<Traits32>? = nil
|
||||
|
||||
|
||||
// This typedef is not necessary from a semantic point of view, but the result
|
||||
// of a trade-off done to preserve type sugar (= not generally canonicalizing types).
|
||||
// CHECK-DAG: !DIDerivedType(tag: DW_TAG_typedef, name: "$s4main7MyClassCyAC6TraitsayAA8Traits32V_GGSgD", {{.*}}baseType: ![[CANONICAL:[0-9]+]])
|
||||
// CHECK-DAG: ![[CANONICAL]] = !DICompositeType(tag: DW_TAG_structure_type, {{.*}}identifier: "$s4main7MyClassCyAA8Traits32VGSgD", specification: ![[OPTIONAL:[0-9]+]])
|
||||
// CHECK-DAG: ![[CANONICAL:.*]] = !DICompositeType(tag: DW_TAG_structure_type, {{.*}}identifier: "$s4main7MyClassCyAA8Traits32VGSgD", specification: ![[OPTIONAL:[0-9]+]])
|
||||
|
||||
// CHECK-DAG: ![[OPTIONAL]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Optional"
|
||||
|
||||
// CHECK-DAG: !DICompositeType(tag: DW_TAG_structure_type, name: "MyClass", {{.*}}templateParams: ![[PARAMS:[0-9]+]], identifier: "$s4main7MyClassCyAA8Traits32VGD", specification: ![[SPEC:[0-9]+]])
|
||||
// CHECK-DAG: ![[CONTAINER:.*]] = !DICompositeType(tag: DW_TAG_structure_type, {{.*}}line: 7, {{.*}}elements: ![[ELTS:[0-9]+]], runtimeLang: DW_LANG_Swift, specification: ![[SPEC:[0-9]+]])
|
||||
// CHECK-DAG: ![[ELTS]] = !{![[MEMBER:[0-9]+]]}
|
||||
// CHECK-DAG: ![[MEMBER]] = !DIDerivedType(tag: DW_TAG_member, {{.*}}baseType: ![[UNSIZED:[0-9]+]]
|
||||
// CHECK-DAG: ![[UNSIZED]] = !DICompositeType(tag: DW_TAG_structure_type, name: "$s4main7MyClassCyAA8Traits32VGD", {{.*}}flags: DIFlagFwdDecl, runtimeLang: DW_LANG_Swift, templateParams: ![[PARAMS:[0-9]+]])
|
||||
// CHECK-DAG: ![[PARAMS]] = !{![[PARAM:[0-9]+]]}
|
||||
// CHECK-DAG: ![[PARAM]] = !DITemplateTypeParameter(type: ![[TRAITS32:[0-9]+]])
|
||||
// CHECK-DAG: ![[TRAITS32]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Traits32"
|
||||
|
||||
@@ -5,7 +5,11 @@
|
||||
// we cannot preserve that LocalAlias = Bool.
|
||||
|
||||
// CHECK: !DIDerivedType(tag: DW_TAG_typedef, name: "$s1a10ClassAliasaD"{{.*}}baseType: ![[LOCAL_BOOLTY:[0-9]+]]
|
||||
// CHECK: ![[LOCAL_BOOLTY]] = !DICompositeType(tag: DW_TAG_structure_type, name: "MyClass", {{.*}}identifier: "$s1a7MyClassCyAA10LocalAliasaSbGD"
|
||||
// CHECK: ![[LOCAL_BOOLTY]] = !DICompositeType(tag: DW_TAG_structure_type, {{.*}}elements: ![[ELTS:[0-9]+]], runtimeLang: DW_LANG_Swift, specification: ![[SPEC:[0-9]+]])
|
||||
// CHECK-DAG: ![[ELTS]] = !{![[MEMBER:[0-9]+]]}
|
||||
// CHECK-DAG: ![[MEMBER]] = !DIDerivedType(tag: DW_TAG_member, {{.*}}baseType: ![[UNSIZED:[0-9]+]]
|
||||
// CHECK-DAG: ![[UNSIZED]] = !DICompositeType(tag: DW_TAG_structure_type, name: "$s1a7MyClassCyAA10LocalAliasaSbGD"
|
||||
// CHECK-DAG: ![[SPEC]] = !DICompositeType(tag: DW_TAG_structure_type, name: "MyClass"{{.*}}identifier: "$s1a7MyClassCyxq_GD")
|
||||
|
||||
// FIXME: !DIDerivedType(tag: DW_TAG_typedef, name: "$s1a10LocalAliasaD", {{.*}}baseType: ![[BASETY:[0-9]+]]
|
||||
// FIXME: ![[BASETY]]{{.*}}$sSbD
|
||||
|
||||
Reference in New Issue
Block a user