Skip to content

Commit 5726370

Browse files
committed
Debug Info: Improve the accuracy of enum elements' sizes within the
limitations of LLVM.
1 parent d8bbe8a commit 5726370

File tree

3 files changed

+46
-22
lines changed

3 files changed

+46
-22
lines changed

lib/IRGen/IRGenDebugInfo.cpp

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1227,37 +1227,43 @@ llvm::DICompositeType *IRGenDebugInfo::createStructType(
12271227

12281228
/// Return an array with the DITypes for each of an enum's elements.
12291229
llvm::DINodeArray IRGenDebugInfo::getEnumElements(DebugTypeInfo DbgTy,
1230-
EnumDecl *D,
1230+
EnumDecl *ED,
12311231
llvm::DIScope *Scope,
12321232
llvm::DIFile *File,
12331233
unsigned Flags) {
12341234
SmallVector<llvm::Metadata *, 16> Elements;
12351235

1236-
for (auto *ElemDecl : D->getAllElements()) {
1236+
for (auto *ElemDecl : ED->getAllElements()) {
12371237
// FIXME <rdar://problem/14845818> Support enums.
1238-
// Swift Enums can be both like DWARF enums and DWARF unions.
1239-
// They should probably be emitted as DW_TAG_variant_type.
1238+
// Swift Enums can be both like DWARF enums and discriminated unions.
12401239
if (ElemDecl->hasType()) {
1241-
// Use Decl as DeclContext.
12421240
DebugTypeInfo ElemDbgTy;
1243-
if (ElemDecl->hasArgumentType())
1244-
ElemDbgTy = DebugTypeInfo(ElemDecl->getArgumentType(),
1245-
DbgTy.StorageType,
1246-
DbgTy.size, DbgTy.align, D);
1247-
else
1248-
if (D->hasRawType())
1249-
ElemDbgTy = DebugTypeInfo(D->getRawType(), DbgTy.StorageType,
1250-
DbgTy.size, DbgTy.align, D);
1251-
else
1252-
// Fallback to Int as the element type.
1253-
ElemDbgTy = DebugTypeInfo(IGM.Context.getIntDecl()->getDeclaredType(),
1254-
DbgTy.StorageType,
1255-
DbgTy.size, DbgTy.align, D);
1241+
if (ED->hasRawType())
1242+
// An enum with a raw type (enum E : Int {}), similar to a
1243+
// DWARF enum.
1244+
//
1245+
// The storage occupied by the enum may be smaller than the
1246+
// one of the raw type as long as it is large enough to hold
1247+
// all enum values. Use the raw type for the debug type, but
1248+
// the storage size from the enum.
1249+
ElemDbgTy = DebugTypeInfo(ED->getRawType(), DbgTy.StorageType,
1250+
DbgTy.size, DbgTy.align, ED);
1251+
else if (ElemDecl->hasArgumentType()) {
1252+
// A discriminated union. This should really be described as a
1253+
// DW_TAG_variant_type. For now only describing the data.
1254+
auto &TI = IGM.getTypeInfoForUnlowered(ElemDecl->getArgumentType());
1255+
ElemDbgTy = DebugTypeInfo(ElemDecl->getArgumentType(), TI, ED);
1256+
} else {
1257+
// Discriminated union case without argument. Fallback to Int
1258+
// as the element type; there is no storage here.
1259+
Type IntTy = IGM.Context.getIntDecl()->getDeclaredType();
1260+
ElemDbgTy = DebugTypeInfo(IntTy, DbgTy.StorageType, 0, 1, ED);
1261+
}
12561262
unsigned Offset = 0;
12571263
auto MTy = createMemberType(ElemDbgTy, ElemDecl->getName().str(), Offset,
12581264
Scope, File, Flags);
12591265
Elements.push_back(MTy);
1260-
if (D->isIndirect() || ElemDecl->isIndirect())
1266+
if (ED->isIndirect() || ElemDecl->isIndirect())
12611267
IndirectEnumCases.insert(MTy);
12621268
}
12631269
}

test/DebugInfo/NestedTypes.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// RUN: %target-swift-frontend -primary-file %s -emit-ir -g -o - | FileCheck %s
2+
3+
// Verify that the size of a class that has not been created before
4+
// its outer type is emitted is emitted correctly.
5+
public struct S { var x : Int64; var y : Int64}
6+
public enum Enum {
7+
case WithClass(C)
8+
case WithStruct(S)
9+
}
10+
public class C { }
11+
12+
public let e : Enum = .WithClass(C())
13+
14+
// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "WithClass",
15+
// CHECK-SAME: size: 64,
16+
// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "WithStruct",
17+
// CHECK-SAME: size: 128,
18+

test/DebugInfo/enum.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
// CHECK-SAME: size: 8, align: 8,
77
// CHECK-SAME: identifier: "_TtO4enum5Color"
88
enum Color : UInt64 {
9+
// This is effectively a 2-bit bitfield:
910
// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "Red"
1011
// CHECK-SAME: baseType: !"_TtVs6UInt64"
1112
// CHECK-SAME: size: 8, align: 8{{[,)]}}
@@ -18,12 +19,11 @@ enum Color : UInt64 {
1819
// CHECK-SAME: identifier: "_TtO4enum12MaybeIntPair"
1920
enum MaybeIntPair {
2021
// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "none"
21-
// CHECK-SAME: baseType: !"_TtSi"
22-
// CHECK-SAME: size: 136, align: 64{{[,)]}}
22+
// CHECK-SAME: baseType: !"_TtSi", align: 8{{[,)]}}
2323
case none
2424
// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "just"
2525
// CHECK-SAME: baseType: !"_TtTVs5Int64S__"
26-
// CHECK-SAME: size: 136, align: 64{{[,)]}}
26+
// CHECK-SAME: size: 128, align: 64{{[,)]}}
2727
case just(Int64, Int64)
2828
}
2929

0 commit comments

Comments
 (0)