forked from llvm/llvm-project
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[clang][DebugInfo] Emit global variable definitions for static data m…
…embers with constant initializers (llvm#70639) When an LLDB user asks for the value of a static data member, LLDB starts by searching the Names accelerator table for the corresponding variable definition DIE. For static data members with out-of-class definitions that works fine, because those get represented as global variables with a location and making them eligible to be added to the Names table. However, in-class definitions won’t get indexed because we usually don't emit global variables for them. So in DWARF we end up with a single `DW_TAG_member` that usually holds the constant initializer. But we don't get a corresponding CU-level `DW_TAG_variable` like we do for out-of-class definitions. To make it more convenient for debuggers to get to the value of inline static data members, this patch makes sure we emit definitions for static variables with constant initializers the same way we do for other static variables. This also aligns Clang closer to GCC, which produces CU-level definitions for inline statics and also emits these into `.debug_pubnames`. The implementation keeps track of newly created static data members. Then in `CGDebugInfo::finalize`, we emit a global `DW_TAG_variable` with a `DW_AT_const_value` for any of those declarations that didn't end up with a definition in the `DeclCache`. The newly emitted `DW_TAG_variable` will look as follows: ``` 0x0000007b: DW_TAG_structure_type DW_AT_calling_convention (DW_CC_pass_by_value) DW_AT_name ("Foo") ... 0x0000008d: DW_TAG_member DW_AT_name ("i") DW_AT_type (0x00000062 "const int") DW_AT_external (true) DW_AT_declaration (true) DW_AT_const_value (4) Newly added vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv 0x0000009a: DW_TAG_variable DW_AT_specification (0x0000008d "i") DW_AT_const_value (4) DW_AT_linkage_name ("_ZN2t2IiE1iIfEE") ``` This patch also drops the `DW_AT_const_value` off of the declaration since we now always have it on the definition. This ensures that the `DWARFParallelLinker` can type-merge class with static members where we couldn't attach the constant on the declaration in some CUs.
- Loading branch information
1 parent
72ad6cd
commit 4909814
Showing
7 changed files
with
197 additions
and
42 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
// 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_with_addr = 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_struct_with_addr{}; | ||
static inline Enum inline_enum = Enum::VAL; | ||
|
||
template<typename T> | ||
static constexpr T cexpr_template{}; | ||
}; | ||
|
||
int main() { | ||
Foo f; | ||
|
||
// Force global variable definitions to be emitted. | ||
(void)&Foo::cexpr_int_with_addr; | ||
(void)&Foo::cexpr_struct_with_addr; | ||
|
||
return Foo::cexpr_int_with_addr + Foo::cexpr_float | ||
+ (int)Foo::cexpr_enum + Foo::cexpr_template<short>; | ||
} | ||
|
||
// CHECK: @{{.*}}cexpr_int_with_addr{{.*}} = | ||
// CHECK-SAME: !dbg ![[INT_GLOBAL:[0-9]+]] | ||
|
||
// CHECK: @{{.*}}cexpr_struct_with_addr{{.*}} = | ||
// CHECK-SAME !dbg ![[EMPTY_GLOBAL:[0-9]+]] | ||
|
||
// CHECK: !DIGlobalVariableExpression(var: ![[INT_VAR:[0-9]+]], expr: !DIExpression()) | ||
// CHECK: ![[INT_VAR]] = distinct !DIGlobalVariable(name: "cexpr_int_with_addr", linkageName: | ||
// CHECK-SAME: isLocal: false, isDefinition: true, declaration: ![[INT_DECL:[0-9]+]]) | ||
|
||
// CHECK: ![[INT_DECL]] = !DIDerivedType(tag: DW_TAG_member, name: "cexpr_int_with_addr", | ||
// CHECK-SAME: flags: DIFlagStaticMember | ||
// CHECK-NOT: extraData: | ||
|
||
// CHECK: ![[INT_DECL2:[0-9]+]] = !DIDerivedType(tag: DW_TAG_member, name: "cexpr_int2", | ||
// CHECK-SAME: flags: DIFlagStaticMember | ||
// CHECK-NOT: extraData: | ||
|
||
// CHECK: ![[FLOAT_DECL:[0-9]+]] = !DIDerivedType(tag: DW_TAG_member, name: "cexpr_float", | ||
// CHECK-SAME: flags: DIFlagStaticMember | ||
// CHECK-NOT: extraData: | ||
|
||
// CHECK: ![[ENUM_DECL:[0-9]+]] = !DIDerivedType(tag: DW_TAG_member, name: "cexpr_enum", | ||
// CHECK-SAME: flags: DIFlagStaticMember | ||
// CHECK-NOT: extraData: | ||
|
||
// CHECK: ![[EMPTY_DECL:[0-9]+]] = !DIDerivedType(tag: DW_TAG_member, name: "cexpr_struct_with_addr", | ||
// CHECK-SAME: flags: DIFlagStaticMember | ||
// CHECK-NOT: extraData: | ||
|
||
// CHECK: ![[IENUM_DECL:[0-9]+]] = !DIDerivedType(tag: DW_TAG_member, name: "inline_enum", | ||
// CHECK-SAME: flags: DIFlagStaticMember | ||
// CHECK-NOT: extraData: | ||
|
||
// CHECK: ![[TEMPLATE_DECL:[0-9]+]] = !DIDerivedType(tag: DW_TAG_member, name: "cexpr_template", | ||
// CHECK-SAME: flags: DIFlagStaticMember | ||
// CHECK-NOT: extraData: | ||
|
||
// CHECK: !DIGlobalVariableExpression(var: ![[EMPTY_VAR:[0-9]+]], expr: !DIExpression()) | ||
// CHECK: ![[EMPTY_VAR]] = distinct !DIGlobalVariable(name: "cexpr_struct_with_addr", 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: ![[IENUM_VAR:[0-9]+]], expr: !DIExpression(DW_OP_constu, {{.*}}, DW_OP_stack_value)) | ||
// CHECK: ![[IENUM_VAR]] = distinct !DIGlobalVariable(name: "inline_enum", linkageName: | ||
// CHECK-SAME: isLocal: true, isDefinition: true, declaration: ![[IENUM_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]+]]) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters