Skip to content
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

Bugfix/dwarf emit static defs #21

88 changes: 70 additions & 18 deletions clang/lib/CodeGen/CGDebugInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1691,6 +1691,7 @@ CGDebugInfo::CreateRecordStaticField(const VarDecl *Var, llvm::DIType *RecordTy,
llvm::DIDerivedType *GV = DBuilder.createStaticMemberType(
RecordTy, VName, VUnit, LineNumber, VTy, Flags, C, Align);
StaticDataMemberCache[Var->getCanonicalDecl()].reset(GV);
StaticDataMemberDefinitionsToEmit.push_back(Var->getCanonicalDecl());
return GV;
}

Expand Down Expand Up @@ -5574,25 +5575,8 @@ void CGDebugInfo::EmitGlobalVariable(const ValueDecl *VD, const APValue &Init) {
auto &GV = DeclCache[VD];
if (GV)
return;
llvm::DIExpression *InitExpr = nullptr;
if (CGM.getContext().getTypeSize(VD->getType()) <= 64) {
// FIXME: Add a representation for integer constants wider than 64 bits.
if (Init.isInt()) {
const llvm::APSInt &InitInt = Init.getInt();
std::optional<uint64_t> InitIntOpt;
if (InitInt.isUnsigned())
InitIntOpt = InitInt.tryZExtValue();
else if (auto tmp = InitInt.trySExtValue(); tmp.has_value())
// Transform a signed optional to unsigned optional. When cpp 23 comes,
// use std::optional::transform
InitIntOpt = (uint64_t)tmp.value();
if (InitIntOpt)
InitExpr = DBuilder.createConstantValueExpression(InitIntOpt.value());
} else if (Init.isFloat())
InitExpr = DBuilder.createConstantValueExpression(
Init.getFloat().bitcastToAPInt().getZExtValue());
}

llvm::DIExpression *InitExpr = createConstantValueExpression(VD, Init);
llvm::MDTuple *TemplateParameters = nullptr;

if (isa<VarTemplateSpecializationDecl>(VD))
Expand All @@ -5607,6 +5591,39 @@ void CGDebugInfo::EmitGlobalVariable(const ValueDecl *VD, const APValue &Init) {
TemplateParameters, Align));
}

void CGDebugInfo::EmitGlobalVariable(const VarDecl *VD) {
assert(VD->hasInit());
assert(CGM.getCodeGenOpts().hasReducedDebugInfo());
if (VD->hasAttr<NoDebugAttr>())
return;

auto &GV = DeclCache[VD];
if (GV)
return;

auto const *InitVal = VD->evaluateValue();
if (!InitVal)
return;

llvm::DIFile *Unit = nullptr;
llvm::DIScope *DContext = nullptr;
unsigned LineNo;
StringRef DeclName, LinkageName;
QualType T;
llvm::MDTuple *TemplateParameters = nullptr;
collectVarDeclProps(VD, Unit, LineNo, T, DeclName, LinkageName,
TemplateParameters, DContext);

auto Align = getDeclAlignIfRequired(VD, CGM.getContext());
llvm::DINodeArray Annotations = CollectBTFDeclTagAnnotations(VD);
llvm::DIExpression *InitExpr = createConstantValueExpression(VD, *InitVal);

GV.reset(DBuilder.createGlobalVariableExpression(
TheCU, DeclName, LinkageName, Unit, LineNo, getOrCreateType(T, Unit),
true, true, InitExpr, getOrCreateStaticDataMemberDeclarationOrNull(VD),
TemplateParameters, Align, Annotations));
}

void CGDebugInfo::EmitExternalVariable(llvm::GlobalVariable *Var,
const VarDecl *D) {
assert(CGM.getCodeGenOpts().hasReducedDebugInfo());
Expand Down Expand Up @@ -5877,6 +5894,16 @@ void CGDebugInfo::finalize() {
DBuilder.replaceTemporary(std::move(FwdDecl), cast<llvm::MDNode>(Repl));
}

for (auto const *VD : StaticDataMemberDefinitionsToEmit) {
if (auto It = DeclCache.find(VD); It != DeclCache.end())
continue;

if (!VD->hasInit())
continue;

EmitGlobalVariable(VD);
}

// We keep our own list of retained types, because we need to look
// up the final type in the type cache.
for (auto &RT : RetainedTypes)
Expand Down Expand Up @@ -5929,3 +5956,28 @@ llvm::DINode::DIFlags CGDebugInfo::getCallSiteRelatedAttrs() const {

return llvm::DINode::FlagAllCallsDescribed;
}

llvm::DIExpression *
CGDebugInfo::createConstantValueExpression(clang::ValueDecl const *VD,
const APValue &Val) {
llvm::DIExpression *ValExpr = nullptr;
if (CGM.getContext().getTypeSize(VD->getType()) <= 64) {
// FIXME: Add a representation for integer constants wider than 64 bits.
if (Val.isInt()) {
const llvm::APSInt &ValInt = Val.getInt();
std::optional<uint64_t> ValIntOpt;
if (ValInt.isUnsigned())
ValIntOpt = ValInt.tryZExtValue();
else if (auto tmp = ValInt.trySExtValue(); tmp.has_value())
// Transform a signed optional to unsigned optional. When cpp 23 comes,
// use std::optional::transform
ValIntOpt = (uint64_t)tmp.value();
if (ValIntOpt)
ValExpr = DBuilder.createConstantValueExpression(ValIntOpt.value());
} else if (Val.isFloat())
ValExpr = DBuilder.createConstantValueExpression(
Val.getFloat().bitcastToAPInt().getZExtValue());
}

return ValExpr;
}
9 changes: 9 additions & 0 deletions clang/lib/CodeGen/CGDebugInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ class CGDebugInfo {
NamespaceAliasCache;
llvm::DenseMap<const Decl *, llvm::TypedTrackingMDRef<llvm::DIDerivedType>>
StaticDataMemberCache;
std::vector<const VarDecl *> StaticDataMemberDefinitionsToEmit;

using ParamDecl2StmtTy = llvm::DenseMap<const ParmVarDecl *, const Stmt *>;
using Param2DILocTy =
Expand Down Expand Up @@ -526,6 +527,9 @@ class CGDebugInfo {
/// Emit a constant global variable's debug info.
void EmitGlobalVariable(const ValueDecl *VD, const APValue &Init);

/// Emit debug-info for a variable with a constant initializer.
void EmitGlobalVariable(const VarDecl *VD);

/// Emit information about an external variable.
void EmitExternalVariable(llvm::GlobalVariable *GV, const VarDecl *Decl);

Expand Down Expand Up @@ -800,6 +804,11 @@ class CGDebugInfo {
llvm::MDTuple *&TemplateParameters,
llvm::DIScope *&VDContext);

/// Create a DIExpression representing the constant corresponding
/// to the specified 'Val'. Returns nullptr on failure.
llvm::DIExpression *createConstantValueExpression(const clang::ValueDecl *VD,
const APValue &Val);

/// Allocate a copy of \p A using the DebugInfoNames allocator
/// and return a reference to it. If multiple arguments are given the strings
/// are concatenated.
Expand Down
13 changes: 9 additions & 4 deletions clang/test/CodeGenCXX/debug-info-class.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,11 +116,19 @@ int main(int argc, char **argv) {
// CHECK-SAME: DIFlagFwdDecl
// CHECK-NOT: identifier:
// CHECK-SAME: ){{$}}

// CHECK: !DIGlobalVariableExpression(var: ![[HDR_VAR:[0-9]+]], expr: !DIExpression(DW_OP_constu, 52, DW_OP_stack_value))
// CHECK: ![[HDR_VAR]] = distinct !DIGlobalVariable(name: "HdrSize",
// CHECK-SAME: isLocal: true, isDefinition: true, declaration: ![[HDR_VAR_DECL:[0-9]+]])
// CHECK: ![[INT:[0-9]+]] = !DIBasicType(name: "int"
// CHECK: ![[HDR_VAR_DECL]] = !DIDerivedType(tag: DW_TAG_member, name: "HdrSize"

// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "A"

// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "I"
// CHECK-NOT: DIFlagFwdDecl
// CHECK-SAME: ){{$}}

// CHECK: ![[INT:[0-9]+]] = !DIBasicType(name: "int"
// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "foo"
// CHECK: !DICompositeType(tag: DW_TAG_class_type, name: "bar"
// CHECK: !DICompositeType(tag: DW_TAG_union_type, name: "baz"
Expand Down Expand Up @@ -186,8 +194,5 @@ int main(int argc, char **argv) {
// CHECK: [[G_INNER_I]] = !DIDerivedType(tag: DW_TAG_member, name: "j"
// CHECK-SAME: baseType: ![[INT]]

// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "A"
// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "HdrSize"
//
// CHECK: ![[EXCEPTLOC]] = !DILocation(line: 100,
// CHECK: ![[RETLOC]] = !DILocation(line: 99,
79 changes: 79 additions & 0 deletions clang/test/CodeGenCXX/debug-info-static-inline-member.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// RUN: %clangxx -target arm64-apple-macosx11.0.0 -g %s -emit-llvm -S -o - | FileCheck --check-prefixes=CHECK %s

enum class Enum : int {
VAL = -1
};

struct Empty {};

constexpr auto func() { return 25; }

struct Foo {
static constexpr int cexpr_int = func();
static constexpr int cexpr_int2 = func() + 1;
static constexpr float cexpr_float = 2.0 + 1.0;
static constexpr Enum cexpr_enum = Enum::VAL;
static constexpr Empty cexpr_empty{};

template<typename T>
static constexpr T cexpr_template{};
};

int main() {
Foo f;

// Force global variable definitions to be emitted.
(void)&Foo::cexpr_int;
(void)&Foo::cexpr_empty;

return Foo::cexpr_int + Foo::cexpr_float
+ (int)Foo::cexpr_enum + Foo::cexpr_template<short>;
}

// CHECK: @{{.*}}cexpr_int{{.*}} =
// CHECK-SAME: !dbg ![[INT_GLOBAL:[0-9]+]]

// CHECK: @{{.*}}cexpr_empty{{.*}} =
// CHECK-SAME !dbg ![[EMPTY_GLOBAL:[0-9]+]]

// CHECK: !DIGlobalVariableExpression(var: ![[INT_VAR:[0-9]+]], expr: !DIExpression())
// CHECK: ![[INT_VAR]] = distinct !DIGlobalVariable(name: "cexpr_int", linkageName:
// CHECK-SAME: isLocal: false, isDefinition: true, declaration: ![[INT_DECL:[0-9]+]])

// CHECK: ![[INT_DECL]] = !DIDerivedType(tag: DW_TAG_member, name: "cexpr_int",
// CHECK-SAME: flags: DIFlagStaticMember, extraData: i32 25)

// CHECK: ![[INT_DECL2:[0-9]+]] = !DIDerivedType(tag: DW_TAG_member, name: "cexpr_int2",
// CHECK-SAME: flags: DIFlagStaticMember, extraData: i32 26)

// CHECK: ![[FLOAT_DECL:[0-9]+]] = !DIDerivedType(tag: DW_TAG_member, name: "cexpr_float",
// CHECK-SAME: flags: DIFlagStaticMember, extraData: float

// CHECK: ![[ENUM_DECL:[0-9]+]] = !DIDerivedType(tag: DW_TAG_member, name: "cexpr_enum",
// CHECK-SAME: flags: DIFlagStaticMember, extraData: i32 -1)

// CHECK: ![[EMPTY_DECL:[0-9]+]] = !DIDerivedType(tag: DW_TAG_member, name: "cexpr_empty",
// CHECK-SAME: flags: DIFlagStaticMember)

// CHECK: ![[TEMPLATE_DECL:[0-9]+]] = !DIDerivedType(tag: DW_TAG_member, name: "cexpr_template",
// CHECK-SAME: flags: DIFlagStaticMember, extraData: i16 0)

// CHECK: !DIGlobalVariableExpression(var: ![[EMPTY_VAR:[0-9]+]], expr: !DIExpression())
// CHECK: ![[EMPTY_VAR]] = distinct !DIGlobalVariable(name: "cexpr_empty", linkageName:
// CHECK-SAME: isLocal: false, isDefinition: true, declaration: ![[EMPTY_DECL]])

// CHECK: !DIGlobalVariableExpression(var: ![[INT_VAR2:[0-9]+]], expr: !DIExpression(DW_OP_constu, 26, DW_OP_stack_value))
// CHECK: ![[INT_VAR2]] = distinct !DIGlobalVariable(name: "cexpr_int2", linkageName:
// CHECK-SAME: isLocal: true, isDefinition: true, declaration: ![[INT_DECL2]])

// CHECK: !DIGlobalVariableExpression(var: ![[FLOAT_VAR:[0-9]+]], expr: !DIExpression(DW_OP_constu, {{.*}}, DW_OP_stack_value))
// CHECK: ![[FLOAT_VAR]] = distinct !DIGlobalVariable(name: "cexpr_float", linkageName:
// CHECK-SAME: isLocal: true, isDefinition: true, declaration: ![[FLOAT_DECL]])

// CHECK: !DIGlobalVariableExpression(var: ![[ENUM_VAR:[0-9]+]], expr: !DIExpression(DW_OP_constu, {{.*}}, DW_OP_stack_value))
// CHECK: ![[ENUM_VAR]] = distinct !DIGlobalVariable(name: "cexpr_enum", linkageName:
// CHECK-SAME: isLocal: true, isDefinition: true, declaration: ![[ENUM_DECL]])

// CHECK: !DIGlobalVariableExpression(var: ![[TEMPLATE_VAR:[0-9]+]], expr: !DIExpression(DW_OP_constu, 0, DW_OP_stack_value))
// CHECK: ![[TEMPLATE_VAR]] = distinct !DIGlobalVariable(name: "cexpr_template", linkageName:
// CHECK-SAME: isLocal: true, isDefinition: true, declaration: ![[TEMPLATE_DECL]], templateParams: ![[TEMPLATE_PARMS:[0-9]+]])
2 changes: 1 addition & 1 deletion lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3619,7 +3619,7 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc,
// found there.
location_list.SetModule(debug_map_symfile->GetObjectFile()->GetModule());

if (is_static_lifetime) {
if (is_static_lifetime && !location_is_const_value_data) {
if (is_external)
scope = eValueTypeVariableGlobal;
else
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,10 @@ def test(self):
# it does not crash.
self.expect("image lookup -t A")

# dsymutil strips the debug info for classes that only have const static
# data members without a definition namespace scope.
@expectedFailureAll(debug_info=["dsym"])
# For debug-info produced by older versions of clang, dsymutil strips the
# debug info for classes that only have const static data members without
# a definition namespace scope.
@expectedFailureAll(compiler=["clang"], compiler_version=["<", "18.0"])
def test_class_with_only_const_static(self):
self.build()
lldbutil.run_to_source_breakpoint(
Expand All @@ -113,6 +114,36 @@ def test_class_with_only_const_static(self):

self.expect_expr("ClassWithOnlyConstStatic::member", result_value="3")

def check_global_var(self, name: str, expect_type, expect_val):
var_list = self.target().FindGlobalVariables(name, lldb.UINT32_MAX)
self.assertEqual(len(var_list), 1)
varobj = var_list[0]
self.assertEqual(varobj.type.name, expect_type)
self.assertEqual(varobj.value, expect_val)

# For debug-info produced by older versions of clang, inline static data members
# wouldn't get indexed into the Names accelerator table preventing LLDB from finding
# them.
@expectedFailureAll(compiler=["clang"], compiler_version=["<", "18.0"])
def test_inline_static_members(self):
self.build()
lldbutil.run_to_source_breakpoint(
self, "// break here", lldb.SBFileSpec("main.cpp")
)

self.check_global_var("A::int_val", "const int", "1")
self.check_global_var("A::int_val_with_address", "const int", "2")
self.check_global_var("A::bool_val", "const bool", "true")
self.check_global_var("A::enum_val", "Enum", "enum_case2")
self.check_global_var("A::enum_bool_val", "EnumBool", "enum_bool_case1")
self.check_global_var("A::scoped_enum_val", "ScopedEnum", "scoped_enum_case2")

self.check_global_var("ClassWithOnlyConstStatic::member", "const int", "3")

self.check_global_var("ClassWithConstexprs::member", "const int", "2")
self.check_global_var("ClassWithConstexprs::enum_val", "Enum", "enum_case2")
self.check_global_var("ClassWithConstexprs::scoped_enum_val", "ScopedEnum", "scoped_enum_case2")

# With older versions of Clang, LLDB fails to evaluate classes with only
# constexpr members when dsymutil is enabled
@expectedFailureAll(
Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/CodeGen/MLRegAllocEvictAdvisor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
//
//===----------------------------------------------------------------------===//

// saadfhwoiroiajroifjksdkfasksnvoiwjewoififjoiwjefaskkdfksdnocoivjwoeijoiefoijsjdfkasdnckjnawejfoiwjejrpoikfaksldjnncasdfjdlsljflfjasdffhfhffhfhfhghghgfjfjfhgff

#include "AllocationOrder.h"
#include "RegAllocEvictionAdvisor.h"
#include "RegAllocGreedy.h"
Expand Down
Loading