Skip to content

Commit 594f51a

Browse files
committed
Generate full debug info for enums
Replace the generation of debug info for enums from DW_TAG_union_type to either DW_TAG_enumeration_type or DW_TAG_variant_part, as these representation match Swift enums more closely.
1 parent 254ecb6 commit 594f51a

File tree

2 files changed

+129
-53
lines changed

2 files changed

+129
-53
lines changed

lib/IRGen/IRGenDebugInfo.cpp

Lines changed: 103 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1037,79 +1037,135 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
10371037
return DITy;
10381038
}
10391039

1040-
llvm::DICompositeType *createEnumType(CompletedDebugTypeInfo DbgTy,
1041-
EnumDecl *Decl, StringRef MangledName,
1042-
llvm::DIScope *Scope,
1043-
llvm::DIFile *File, unsigned Line,
1044-
llvm::DINode::DIFlags Flags) {
1040+
/// Create debug information for an enum with a raw type (enum E : Int {}).
1041+
llvm::DICompositeType *createRawEnumType(CompletedDebugTypeInfo DbgTy,
1042+
EnumDecl *Decl,
1043+
StringRef MangledName,
1044+
llvm::DIScope *Scope,
1045+
llvm::DIFile *File, unsigned Line,
1046+
llvm::DINode::DIFlags Flags) {
1047+
assert(
1048+
Decl->hasRawType() &&
1049+
"Trying to create a raw enum debug info from enum with no raw type!");
1050+
10451051
StringRef Name = Decl->getName().str();
10461052
unsigned SizeInBits = DbgTy.getSizeInBits();
10471053
// Default, since Swift doesn't allow specifying a custom alignment.
10481054
unsigned AlignInBits = 0;
10491055

1050-
// FIXME: Is DW_TAG_union_type the right thing here?
1051-
// Consider using a DW_TAG_variant_type instead.
10521056
auto FwdDecl = llvm::TempDIType(DBuilder.createReplaceableCompositeType(
1053-
llvm::dwarf::DW_TAG_union_type, MangledName, Scope, File, Line,
1057+
llvm::dwarf::DW_TAG_enumeration_type, MangledName, Scope, File, Line,
10541058
llvm::dwarf::DW_LANG_Swift, SizeInBits, AlignInBits, Flags,
10551059
MangledName));
10561060

10571061
auto TH = llvm::TrackingMDNodeRef(FwdDecl.get());
10581062
DITypeCache[DbgTy.getType()] = TH;
10591063

1064+
auto RawType = Decl->getRawType();
1065+
auto &TI = IGM.getTypeInfoForUnlowered(RawType);
1066+
llvm::Optional<CompletedDebugTypeInfo> ElemDbgTy =
1067+
CompletedDebugTypeInfo::getFromTypeInfo(RawType, TI, IGM);
1068+
if (!ElemDbgTy)
1069+
// Without complete type info we can only create a forward decl.
1070+
return DBuilder.createForwardDecl(
1071+
llvm::dwarf::DW_TAG_enumeration_type, Name, Scope, File, Line,
1072+
llvm::dwarf::DW_LANG_Swift, SizeInBits, 0, MangledName);
1073+
10601074
SmallVector<llvm::Metadata *, 16> Elements;
1075+
for (auto *ElemDecl : Decl->getAllElements()) {
1076+
// TODO: add the option to emit an enumerator with no value, and use that
1077+
// instead of emitting a 0.
1078+
auto MTy =
1079+
DBuilder.createEnumerator(ElemDecl->getBaseIdentifier().str(), 0);
1080+
Elements.push_back(MTy);
1081+
}
1082+
1083+
auto EnumType = getOrCreateType(*ElemDbgTy);
1084+
auto DITy = DBuilder.createEnumerationType(
1085+
Scope, Name, File, Line, SizeInBits, AlignInBits,
1086+
DBuilder.getOrCreateArray(Elements), EnumType,
1087+
llvm::dwarf::DW_LANG_Swift, MangledName, false);
1088+
1089+
DBuilder.replaceTemporary(std::move(FwdDecl), DITy);
1090+
return DITy;
1091+
}
1092+
1093+
// Create debug information for an enum with no raw type.
1094+
llvm::DICompositeType *createVariantType(CompletedDebugTypeInfo DbgTy,
1095+
EnumDecl *Decl,
1096+
StringRef MangledName,
1097+
llvm::DIScope *Scope,
1098+
llvm::DIFile *File, unsigned Line,
1099+
llvm::DINode::DIFlags Flags) {
1100+
assert(!Decl->getRawType() &&
1101+
"Attempting to create variant debug info from raw enum!");
1102+
1103+
StringRef Name = Decl->getName().str();
1104+
unsigned SizeInBits = DbgTy.getSizeInBits();
1105+
// Default, since Swift doesn't allow specifying a custom alignment.
1106+
unsigned AlignInBits = 0;
1107+
auto NumExtraInhabitants = DbgTy.getNumExtraInhabitants();
1108+
1109+
// A variant part should actually be a child to a DW_TAG_structure_type
1110+
// according to the DWARF spec.
1111+
auto FwdDecl = llvm::TempDIType(DBuilder.createReplaceableCompositeType(
1112+
llvm::dwarf::DW_TAG_structure_type, MangledName, Scope, File, Line,
1113+
llvm::dwarf::DW_LANG_Swift, SizeInBits, AlignInBits, Flags,
1114+
MangledName));
1115+
1116+
auto TH = llvm::TrackingMDNodeRef(FwdDecl.get());
1117+
DITypeCache[DbgTy.getType()] = TH;
10611118

1119+
SmallVector<llvm::Metadata *, 16> Elements;
10621120
for (auto *ElemDecl : Decl->getAllElements()) {
1063-
// FIXME <rdar://problem/14845818> Support enums.
1064-
// Swift Enums can be both like DWARF enums and discriminated unions.
1065-
// LLVM now supports variant types in debug metadata, which may be a
1066-
// better fit.
10671121
llvm::Optional<CompletedDebugTypeInfo> ElemDbgTy;
1068-
if (Decl->hasRawType()) {
1069-
// An enum with a raw type (enum E : Int {}), similar to a
1070-
// DWARF enum.
1071-
//
1072-
// The storage occupied by the enum may be smaller than the
1073-
// one of the raw type as long as it is large enough to hold
1074-
// all enum values. Use the raw type for the debug type, but
1075-
// the storage size from the enum.
1076-
auto RawType = Decl->getRawType();
1077-
auto &TI = IGM.getTypeInfoForUnlowered(RawType);
1078-
ElemDbgTy = CompletedDebugTypeInfo::getFromTypeInfo(RawType, TI, IGM);
1079-
} else if (auto ArgTy = ElemDecl->getArgumentInterfaceType()) {
1080-
// A discriminated union. This should really be described as a
1081-
// DW_TAG_variant_type. For now only describing the data.
1122+
if (auto ArgTy = ElemDecl->getArgumentInterfaceType()) {
1123+
// A variant case which carries a payload.
10821124
ArgTy = ElemDecl->getParentEnum()->mapTypeIntoContext(ArgTy);
10831125
auto &TI = IGM.getTypeInfoForUnlowered(ArgTy);
10841126
ElemDbgTy = CompletedDebugTypeInfo::getFromTypeInfo(ArgTy, TI, IGM);
1127+
if (!ElemDbgTy) {
1128+
// Without complete type info we can only create a forward decl.
1129+
return DBuilder.createForwardDecl(
1130+
llvm::dwarf::DW_TAG_structure_type, Name, Scope, File, Line,
1131+
llvm::dwarf::DW_LANG_Swift, SizeInBits, 0, MangledName);
1132+
}
1133+
unsigned Offset = 0;
1134+
auto MTy =
1135+
createMemberType(*ElemDbgTy, ElemDecl->getBaseIdentifier().str(),
1136+
Offset, Scope, File, Flags);
1137+
Elements.push_back(MTy);
10851138
} else {
1086-
// Discriminated union case without argument. Fallback to Int
1087-
// as the element type; there is no storage here.
1088-
Type IntTy = IGM.Context.getIntType();
1089-
auto &TI = IGM.getTypeInfoForUnlowered(IntTy);
1090-
ElemDbgTy = CompletedDebugTypeInfo::getFromTypeInfo(IntTy, TI, IGM);
1091-
}
1092-
if (!ElemDbgTy) {
1093-
// Without complete type info we can only create a forward decl.
1094-
return DBuilder.createForwardDecl(
1095-
llvm::dwarf::DW_TAG_union_type, Name, Scope, File, Line,
1096-
llvm::dwarf::DW_LANG_Swift, SizeInBits, 0, MangledName);
1139+
// A variant with no payload.
1140+
auto MTy = DBuilder.createMemberType(
1141+
Scope, ElemDecl->getBaseIdentifier().str(), File, 0, 0, 0, 0, Flags,
1142+
nullptr);
1143+
Elements.push_back(MTy);
10971144
}
1098-
unsigned Offset = 0;
1099-
auto MTy =
1100-
createMemberType(*ElemDbgTy, ElemDecl->getBaseIdentifier().str(),
1101-
Offset, Scope, File, Flags);
1102-
Elements.push_back(MTy);
11031145
}
1104-
auto DITy = DBuilder.createUnionType(
1105-
Scope, Name, File, Line, SizeInBits, AlignInBits,
1106-
Flags, DBuilder.getOrCreateArray(Elements),
1107-
llvm::dwarf::DW_LANG_Swift, MangledName);
1108-
1146+
auto VPTy = DBuilder.createVariantPart(Scope, {}, File, Line, SizeInBits,
1147+
AlignInBits, Flags, nullptr,
1148+
DBuilder.getOrCreateArray(Elements));
1149+
auto DITy = DBuilder.createStructType(
1150+
Scope, Name, File, Line, SizeInBits, AlignInBits, Flags, nullptr,
1151+
DBuilder.getOrCreateArray(VPTy), llvm::dwarf::DW_LANG_Swift, nullptr,
1152+
MangledName, NumExtraInhabitants ? *NumExtraInhabitants : 0);
11091153
DBuilder.replaceTemporary(std::move(FwdDecl), DITy);
11101154
return DITy;
11111155
}
11121156

1157+
llvm::DICompositeType *createEnumType(CompletedDebugTypeInfo DbgTy,
1158+
EnumDecl *Decl, StringRef MangledName,
1159+
llvm::DIScope *Scope,
1160+
llvm::DIFile *File, unsigned Line,
1161+
llvm::DINode::DIFlags Flags) {
1162+
if (Decl->hasRawType())
1163+
return createRawEnumType(DbgTy, Decl, MangledName, Scope, File, Line,
1164+
Flags);
1165+
return createVariantType(DbgTy, Decl, MangledName, Scope, File, Line,
1166+
Flags);
1167+
}
1168+
11131169
llvm::DIType *getOrCreateDesugaredType(Type Ty, DebugTypeInfo DbgTy) {
11141170
DebugTypeInfo BlandDbgTy(Ty, DbgTy.getFragmentStorageType(),
11151171
DbgTy.getRawSizeInBits(), DbgTy.getAlignment(),

test/DebugInfo/enum.swift

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,29 +9,49 @@ enum Either {
99
case First(Int64), Second(P), Neither
1010
// CHECK: !DICompositeType({{.*}}name: "Either",
1111
// CHECK-SAME: size: {{328|168}},
12+
13+
// DWARF: !DICompositeType(tag: DW_TAG_structure_type, name: "Either",
14+
// DWARF-SAME: size: 328, num_extra_inhabitants: 253,
15+
// DWARF-SAME: identifier: "$s4enum6EitherOD")
16+
17+
// DWARF: !DICompositeType(tag: DW_TAG_variant_part
18+
19+
// DWARF: DIDerivedType(tag: DW_TAG_member, name: "First",
20+
// DWARF-NEXT: DICompositeType(tag: DW_TAG_structure_type, name: "Int64",
21+
22+
// DWARF: DIDerivedType(tag: DW_TAG_member, name: "Second"
23+
// DWARF-NEXT: DICompositeType(tag: DW_TAG_structure_type, name: "P",
24+
25+
// DWARF: DIDerivedType(tag: DW_TAG_member, name: "Neither",
26+
// DWARF-SAME: baseType: null)
1227
}
1328
// CHECK: ![[EMPTY:.*]] = !{}
14-
// DWARF: ![[INT:.*]] = !DICompositeType({{.*}}identifier: "$sSiD"
1529
let E : Either = .Neither;
1630

1731
// CHECK: !DICompositeType({{.*}}name: "Color",
1832
// CHECK-SAME: size: 8,
1933
// CHECK-SAME: identifier: "$s4enum5ColorOD"
2034
enum Color : UInt64 {
2135
// This is effectively a 2-bit bitfield:
22-
// DWARF: !DIDerivedType(tag: DW_TAG_member, name: "Red"
23-
// DWARF-SAME: baseType: ![[UINT64:[0-9]+]]
24-
// DWARF-SAME: size: 64{{[,)]}}
25-
// DWARF: ![[UINT64]] = !DICompositeType({{.*}}identifier: "$ss6UInt64VD"
36+
// DWARF: DICompositeType(tag: DW_TAG_enumeration_type, name: "Color",
37+
// DWARF-NEXT: DICompositeType(tag: DW_TAG_structure_type, name: "UInt64"
38+
// DWARF: !DIEnumerator(name: "Red", value: 0)
39+
// DWARF-NEXT: !DIEnumerator(name: "Green", value: 0)
40+
// DWARF-NEXT: !DIEnumerator(name: "Blue", value: 0)
2641
case Red, Green, Blue
2742
}
2843

2944
// CHECK: !DICompositeType({{.*}}name: "MaybeIntPair",
3045
// CHECK-SAME: size: 136{{[,)]}}
3146
// CHECK-SAME: identifier: "$s4enum12MaybeIntPairOD"
47+
48+
// DWARF: DICompositeType(tag: DW_TAG_structure_type, name: "MaybeIntPair",
49+
// DWARF-SAME: identifier: "$s4enum12MaybeIntPairOD"
50+
// DWARF: DICompositeType(tag: DW_TAG_variant_part
51+
3252
enum MaybeIntPair {
3353
// DWARF: !DIDerivedType(tag: DW_TAG_member, name: "none"
34-
// DWARF-SAME: baseType: ![[INT]]{{[,)]}}
54+
// DWARF-SAME: baseType: null)
3555
case none
3656
// DWARF: !DIDerivedType(tag: DW_TAG_member, name: "just"
3757
// DWARF-SAME: baseType: ![[INTTUP:[0-9]+]]

0 commit comments

Comments
 (0)