Debug Info: Improve the accuracy of enum elements' sizes within the

limitations of LLVM.
This commit is contained in:
Adrian Prantl
2016-03-10 10:13:40 -08:00
parent d8bbe8a258
commit 5726370c1a
3 changed files with 46 additions and 22 deletions

View File

@@ -1227,37 +1227,43 @@ llvm::DICompositeType *IRGenDebugInfo::createStructType(
/// Return an array with the DITypes for each of an enum's elements. /// Return an array with the DITypes for each of an enum's elements.
llvm::DINodeArray IRGenDebugInfo::getEnumElements(DebugTypeInfo DbgTy, llvm::DINodeArray IRGenDebugInfo::getEnumElements(DebugTypeInfo DbgTy,
EnumDecl *D, EnumDecl *ED,
llvm::DIScope *Scope, llvm::DIScope *Scope,
llvm::DIFile *File, llvm::DIFile *File,
unsigned Flags) { unsigned Flags) {
SmallVector<llvm::Metadata *, 16> Elements; SmallVector<llvm::Metadata *, 16> Elements;
for (auto *ElemDecl : D->getAllElements()) { for (auto *ElemDecl : ED->getAllElements()) {
// FIXME <rdar://problem/14845818> Support enums. // FIXME <rdar://problem/14845818> Support enums.
// Swift Enums can be both like DWARF enums and DWARF unions. // Swift Enums can be both like DWARF enums and discriminated unions.
// They should probably be emitted as DW_TAG_variant_type.
if (ElemDecl->hasType()) { if (ElemDecl->hasType()) {
// Use Decl as DeclContext.
DebugTypeInfo ElemDbgTy; DebugTypeInfo ElemDbgTy;
if (ElemDecl->hasArgumentType()) if (ED->hasRawType())
ElemDbgTy = DebugTypeInfo(ElemDecl->getArgumentType(), // An enum with a raw type (enum E : Int {}), similar to a
DbgTy.StorageType, // DWARF enum.
DbgTy.size, DbgTy.align, D); //
else // The storage occupied by the enum may be smaller than the
if (D->hasRawType()) // one of the raw type as long as it is large enough to hold
ElemDbgTy = DebugTypeInfo(D->getRawType(), DbgTy.StorageType, // all enum values. Use the raw type for the debug type, but
DbgTy.size, DbgTy.align, D); // the storage size from the enum.
else ElemDbgTy = DebugTypeInfo(ED->getRawType(), DbgTy.StorageType,
// Fallback to Int as the element type. DbgTy.size, DbgTy.align, ED);
ElemDbgTy = DebugTypeInfo(IGM.Context.getIntDecl()->getDeclaredType(), else if (ElemDecl->hasArgumentType()) {
DbgTy.StorageType, // A discriminated union. This should really be described as a
DbgTy.size, DbgTy.align, D); // DW_TAG_variant_type. For now only describing the data.
auto &TI = IGM.getTypeInfoForUnlowered(ElemDecl->getArgumentType());
ElemDbgTy = DebugTypeInfo(ElemDecl->getArgumentType(), TI, ED);
} else {
// Discriminated union case without argument. Fallback to Int
// as the element type; there is no storage here.
Type IntTy = IGM.Context.getIntDecl()->getDeclaredType();
ElemDbgTy = DebugTypeInfo(IntTy, DbgTy.StorageType, 0, 1, ED);
}
unsigned Offset = 0; unsigned Offset = 0;
auto MTy = createMemberType(ElemDbgTy, ElemDecl->getName().str(), Offset, auto MTy = createMemberType(ElemDbgTy, ElemDecl->getName().str(), Offset,
Scope, File, Flags); Scope, File, Flags);
Elements.push_back(MTy); Elements.push_back(MTy);
if (D->isIndirect() || ElemDecl->isIndirect()) if (ED->isIndirect() || ElemDecl->isIndirect())
IndirectEnumCases.insert(MTy); IndirectEnumCases.insert(MTy);
} }
} }

View File

@@ -0,0 +1,18 @@
// RUN: %target-swift-frontend -primary-file %s -emit-ir -g -o - | FileCheck %s
// Verify that the size of a class that has not been created before
// its outer type is emitted is emitted correctly.
public struct S { var x : Int64; var y : Int64}
public enum Enum {
case WithClass(C)
case WithStruct(S)
}
public class C { }
public let e : Enum = .WithClass(C())
// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "WithClass",
// CHECK-SAME: size: 64,
// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "WithStruct",
// CHECK-SAME: size: 128,

View File

@@ -6,6 +6,7 @@
// CHECK-SAME: size: 8, align: 8, // CHECK-SAME: size: 8, align: 8,
// CHECK-SAME: identifier: "_TtO4enum5Color" // CHECK-SAME: identifier: "_TtO4enum5Color"
enum Color : UInt64 { enum Color : UInt64 {
// This is effectively a 2-bit bitfield:
// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "Red" // CHECK: !DIDerivedType(tag: DW_TAG_member, name: "Red"
// CHECK-SAME: baseType: !"_TtVs6UInt64" // CHECK-SAME: baseType: !"_TtVs6UInt64"
// CHECK-SAME: size: 8, align: 8{{[,)]}} // CHECK-SAME: size: 8, align: 8{{[,)]}}
@@ -18,12 +19,11 @@ enum Color : UInt64 {
// CHECK-SAME: identifier: "_TtO4enum12MaybeIntPair" // CHECK-SAME: identifier: "_TtO4enum12MaybeIntPair"
enum MaybeIntPair { enum MaybeIntPair {
// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "none" // CHECK: !DIDerivedType(tag: DW_TAG_member, name: "none"
// CHECK-SAME: baseType: !"_TtSi" // CHECK-SAME: baseType: !"_TtSi", align: 8{{[,)]}}
// CHECK-SAME: size: 136, align: 64{{[,)]}}
case none case none
// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "just" // CHECK: !DIDerivedType(tag: DW_TAG_member, name: "just"
// CHECK-SAME: baseType: !"_TtTVs5Int64S__" // CHECK-SAME: baseType: !"_TtTVs5Int64S__"
// CHECK-SAME: size: 136, align: 64{{[,)]}} // CHECK-SAME: size: 128, align: 64{{[,)]}}
case just(Int64, Int64) case just(Int64, Int64)
} }