Skip to content

Generate full debug info for special builtins and classes #71332

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Feb 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 57 additions & 43 deletions lib/IRGen/IRGenDebugInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
//===----------------------------------------------------------------------===//

#include "IRGenDebugInfo.h"
#include "GenEnum.h"
#include "GenOpaque.h"
#include "GenStruct.h"
#include "GenType.h"
Expand Down Expand Up @@ -1078,8 +1079,6 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
llvm::dwarf::DW_TAG_structure_type, UniqueID, Scope, File, Line,
llvm::dwarf::DW_LANG_Swift, SizeInBits, 0);
}
if (OffsetInBits > SizeInBits)
SizeInBits = OffsetInBits;

auto DITy = DBuilder.createStructType(
Scope, Name, File, Line, SizeInBits, AlignInBits, Flags, DerivedFrom,
Expand Down Expand Up @@ -1525,7 +1524,8 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
? 0
: DbgTy.getAlignment().getValue() * SizeOfByte;
unsigned Encoding = 0;
uint32_t NumExtraInhabitants = 0;
uint32_t NumExtraInhabitants = DbgTy.getNumExtraInhabitants().value_or(0);

llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero;

TypeBase *BaseTy = DbgTy.getType();
Expand All @@ -1549,17 +1549,13 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
Encoding = llvm::dwarf::DW_ATE_unsigned;
if (auto CompletedDbgTy = CompletedDebugTypeInfo::get(DbgTy))
SizeInBits = getSizeOfBasicType(*CompletedDbgTy);
if (auto DbgTyNumExtraInhabitants = DbgTy.getNumExtraInhabitants())
NumExtraInhabitants = *DbgTyNumExtraInhabitants;
break;
}

case TypeKind::BuiltinIntegerLiteral: {
Encoding = llvm::dwarf::DW_ATE_unsigned; // ?
if (auto CompletedDbgTy = CompletedDebugTypeInfo::get(DbgTy))
SizeInBits = getSizeOfBasicType(*CompletedDbgTy);
if (auto DbgTyNumExtraInhabitants = DbgTy.getNumExtraInhabitants())
NumExtraInhabitants = *DbgTyNumExtraInhabitants;
break;
}

Expand All @@ -1568,48 +1564,30 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
// Assuming that the bitwidth and FloatTy->getFPKind() are identical.
SizeInBits = FloatTy->getBitWidth();
Encoding = llvm::dwarf::DW_ATE_float;
if (auto DbgTyNumExtraInhabitants = DbgTy.getNumExtraInhabitants())
NumExtraInhabitants = *DbgTyNumExtraInhabitants;
break;
}

case TypeKind::BuiltinNativeObject: {
unsigned PtrSize = CI.getTargetInfo().getPointerWidth(clang::LangAS::Default);
auto PTy = DBuilder.createPointerType(nullptr, PtrSize, 0,
/* DWARFAddressSpace */ llvm::None,
MangledName);
return DBuilder.createObjectPointerType(PTy);
}

case TypeKind::BuiltinBridgeObject: {
unsigned PtrSize = CI.getTargetInfo().getPointerWidth(clang::LangAS::Default);
auto PTy = DBuilder.createPointerType(nullptr, PtrSize, 0,
/* DWARFAddressSpace */ llvm::None,
MangledName);
return DBuilder.createObjectPointerType(PTy);
}

case TypeKind::BuiltinRawPointer: {
unsigned PtrSize = CI.getTargetInfo().getPointerWidth(clang::LangAS::Default);
return DBuilder.createPointerType(nullptr, PtrSize, 0,
/* DWARFAddressSpace */ llvm::None,
MangledName);
}
case TypeKind::BuiltinNativeObject:
case TypeKind::BuiltinBridgeObject:
case TypeKind::BuiltinRawPointer:
case TypeKind::BuiltinRawUnsafeContinuation:
case TypeKind::BuiltinJob: {
unsigned PtrSize =
CI.getTargetInfo().getPointerWidth(clang::LangAS::Default);
if (Opts.DebugInfoLevel > IRGenDebugInfoLevel::ASTTypes) {
Flags |= llvm::DINode::FlagArtificial;
llvm::DICompositeType *PTy = DBuilder.createStructType(
Scope, MangledName, File, 0, PtrSize, 0, Flags, nullptr, nullptr,
llvm::dwarf::DW_LANG_Swift, nullptr, {}, NumExtraInhabitants);
return PTy;

case TypeKind::BuiltinRawUnsafeContinuation: {
unsigned PtrSize = CI.getTargetInfo().getPointerWidth(clang::LangAS::Default);
return DBuilder.createPointerType(nullptr, PtrSize, 0,
/* DWARFAddressSpace */ llvm::None,
MangledName);
}
}
llvm::DIDerivedType *PTy = DBuilder.createPointerType(
nullptr, PtrSize, 0,
/* DWARFAddressSpace */ llvm::None, MangledName);

case TypeKind::BuiltinJob: {
unsigned PtrSize = CI.getTargetInfo().getPointerWidth(clang::LangAS::Default);
return DBuilder.createPointerType(nullptr, PtrSize, 0,
/* DWARFAddressSpace */ llvm::None,
MangledName);
return DBuilder.createObjectPointerType(PTy);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this intentionally change the behavior for BuiltinRawPointer?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I changed it because all of them seem artificial types to me (builtins not visible in user source code). What do you think?

}

case TypeKind::BuiltinExecutor: {
return createDoublePointerSizedStruct(
Scope, "Builtin.Executor", nullptr, MainFile, 0,
Expand Down Expand Up @@ -1663,6 +1641,25 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
unsigned FwdDeclLine = 0;
assert(SizeInBits ==
CI.getTargetInfo().getPointerWidth(clang::LangAS::Default));
if (Opts.DebugInfoLevel > IRGenDebugInfoLevel::ASTTypes) {
auto *DIType = createStructType(
DbgTy, Decl, ClassTy, Scope, File, L.Line, SizeInBits, AlignInBits,
Flags, nullptr, llvm::dwarf::DW_LANG_Swift, MangledName);
assert(DIType && "Unexpected null DIType!");
assert(DIType && "createStructType should never return null!");
auto SuperClassTy = ClassTy->getSuperclass();
if (SuperClassTy) {
auto SuperClassDbgTy = DebugTypeInfo::getFromTypeInfo(
SuperClassTy, IGM.getTypeInfoForUnlowered(SuperClassTy), IGM,
false);

llvm::DIType *SuperClassDITy = getOrCreateType(SuperClassDbgTy);
assert(SuperClassDITy && "getOrCreateType should never return null!");
DBuilder.retainType(DBuilder.createInheritance(
DIType, SuperClassDITy, 0, 0, llvm::DINode::FlagZero));
}
return DIType;
}
return createPointerSizedStruct(Scope, Decl->getNameStr(), L.File,
FwdDeclLine, Flags, MangledName);
}
Expand Down Expand Up @@ -2033,6 +2030,20 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
}
#endif

/// Emits the special builtin types into the debug info. These types are the
/// ones that are unconditionally emitted into the stdlib's metadata and are
/// needed to correctly calculate the layout of more complex types built on
/// top of them.
void createSpecialStlibBuiltinTypes() {
if (Opts.DebugInfoLevel <= IRGenDebugInfoLevel::ASTTypes)
return;
for (auto BuiltinType: IGM.getOrCreateSpecialStlibBuiltinTypes()) {
auto DbgTy = DebugTypeInfo::getFromTypeInfo(
BuiltinType, IGM.getTypeInfoForUnlowered(BuiltinType), IGM, false);
DBuilder.retainType(getOrCreateType(DbgTy));
}
}

llvm::DIType *getOrCreateType(DebugTypeInfo DbgTy) {
// Is this an empty type?
if (DbgTy.isNull())
Expand Down Expand Up @@ -2079,6 +2090,8 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
TypeDecl = ND;
Context = ND->getParent();
ClangDecl = ND->getClangDecl();
} else if (auto BNO = dyn_cast<BuiltinType>(DbgTy.getType())) {
Context = BNO->getASTContext().TheBuiltinModule;
}
if (ClangDecl) {
clang::ASTReader &Reader = *CI.getClangInstance().getASTReader();
Expand Down Expand Up @@ -2255,6 +2268,7 @@ IRGenDebugInfoImpl::IRGenDebugInfoImpl(const IRGenOptions &Opts,
}
OS << '"';
}
createSpecialStlibBuiltinTypes();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Commit #1 doesn't have any tests, but we should at least be able to test the special types?

}

void IRGenDebugInfoImpl::finalize() {
Expand Down
28 changes: 28 additions & 0 deletions test/DebugInfo/BuiltinStdlibTypes.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// RUN: %target-swift-frontend %s -Onone -emit-ir -gdwarf-types -o - | %FileCheck %s

// File is empty as this test check for the builtin stdlib types that should
// always be emitted.

// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "$sBoD",
// CHECK-SAME: size: 64, num_extra_inhabitants: {{2147483647|4096}}, flags: DIFlagArtificial,
// CHECK-SAME: runtimeLang: DW_LANG_Swift)

// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "$syXlD",
// CHECK-SAME: size: 64,

// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "$sBbD",
// CHECK-SAME: size: 64, num_extra_inhabitants: {{2147483647|4096}}, flags: DIFlagArtificial,
// CHECK-SAME: runtimeLang: DW_LANG_Swift)

// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "$sBpD",
// CHECK-SAME: size: 64, num_extra_inhabitants: 1, flags: DIFlagArtificial,
// CHECK-SAME: runtimeLang: DW_LANG_Swift)

// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "$syyXfD",
// CHECK-SAME: size: 64,
// CHECK-SAME: runtimeLang: DW_LANG_Swift

// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "$sypXpD", size: 64,
// CHECK-SAME: flags: DIFlagArtificial, runtimeLang: DW_LANG_Swift, identifier: "$sypXpD")


2 changes: 1 addition & 1 deletion test/DebugInfo/EagerTypeMetadata.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,6 @@ public class C<T>
}
// CHECK: !DIDerivedType(tag: DW_TAG_typedef, name: "T",
// CHECK-SAME: baseType: ![[PTRTY:[0-9]+]]
// CHECK: ![[PTRTY]] = !DIDerivedType(tag: DW_TAG_pointer_type, name: "$sBpD", baseType: null, size: {{64|32}})
// CHECK: ![[PTRTY]] = !DIDerivedType(tag: DW_TAG_pointer_type, name: "$sBpD", baseType: null, size: {{64|32}}, flags: DIFlagArtificial | DIFlagObjectPointer)
// CHECK: ![[LOC]] = !DILocation(line: 0,

15 changes: 15 additions & 0 deletions test/DebugInfo/classes.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// RUN: %target-swift-frontend -primary-file %s -emit-ir -gdwarf-types -o - | %FileCheck %s

class SomeClass {
let first = 4
let second = "Hello"
}

// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "SomeClass",
// CHECK-SAME: size: 64, elements:
// CHECK-SAME: runtimeLang: DW_LANG_Swift, identifier: "$s7classes9SomeClassCD")

// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "first",
// CHECK-SAME: size: 64)
// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "second",
// CHECK-SAME: size: 128, offset: 64)