mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Debug Info: Improve the accuracy of enum elements' sizes within the
limitations of LLVM.
This commit is contained in:
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
18
test/DebugInfo/NestedTypes.swift
Normal file
18
test/DebugInfo/NestedTypes.swift
Normal 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,
|
||||||
|
|
||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user