[flang] [clang-tools-extra] [llvm] [clang] [compiler-rt] [indvars] Missing variables at Og: (PR #69920)
@@ -1482,6 +1513,21 @@ int llvm::rewriteLoopExitValues(Loop *L, LoopInfo *LI, TargetLibraryInfo *TLI, (isa(Inst) || isa(Inst)) ? &*Inst->getParent()->getFirstInsertionPt() : Inst; RewritePhiSet.emplace_back(PN, i, ExitValue, InsertPt, HighCost); + +// Add debug values if the PN is a induction variable. CarlosAlbertoEnciso wrote: That code creates a debug value in the exit block if any of the incoming values for the PHI Node being replaced is the induction variable. Reworked in new patch. https://github.com/llvm/llvm-project/pull/69920 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[flang] [clang-tools-extra] [llvm] [clang] [compiler-rt] [indvars] Missing variables at Og: (PR #69920)
https://github.com/CarlosAlbertoEnciso edited https://github.com/llvm/llvm-project/pull/69920 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[libc] [lldb] [libcxx] [compiler-rt] [lld] [clang-tools-extra] [clang] [flang] [llvm] [IPSCCP] Variable not visible at Og: (PR #77901)
https://github.com/CarlosAlbertoEnciso updated https://github.com/llvm/llvm-project/pull/77901 >From cea029185ad219a4a0b6d03be00b0612675933ab Mon Sep 17 00:00:00 2001 From: Carlos Alberto Enciso Date: Fri, 12 Jan 2024 09:27:53 + Subject: [PATCH] [IPSCCP] Variable not visible at Og: https://bugs.llvm.org/show_bug.cgi?id=51559 https://github.com/llvm/llvm-project/issues/50901 IPSCCP pass removes the global variable and does not create a constant expression for the initializer value. Extend test coverage to include: - half and bfloat types. - checks for undef (int32 and ptr). --- llvm/lib/Transforms/Utils/Local.cpp | 3 +- llvm/test/Transforms/SCCP/pr50901.ll | 41 ++- llvm/unittests/Transforms/Utils/LocalTest.cpp | 20 + 3 files changed, 54 insertions(+), 10 deletions(-) diff --git a/llvm/lib/Transforms/Utils/Local.cpp b/llvm/lib/Transforms/Utils/Local.cpp index b9cad764aaef8b..ecbefca4549caf 100644 --- a/llvm/lib/Transforms/Utils/Local.cpp +++ b/llvm/lib/Transforms/Utils/Local.cpp @@ -3594,7 +3594,8 @@ DIExpression *llvm::getExpressionForConstant(DIBuilder &DIB, const Constant &C, return createIntegerExpression(C); auto *FP = dyn_cast(&C); - if (FP && (Ty.isFloatTy() || Ty.isDoubleTy())) { + if (FP && + (Ty.isFloatTy() || Ty.isDoubleTy() || Ty.isHalfTy() || Ty.isBFloatTy())) { const APFloat &APF = FP->getValueAPF(); return DIB.createConstantValueExpression( APF.bitcastToAPInt().getZExtValue()); diff --git a/llvm/test/Transforms/SCCP/pr50901.ll b/llvm/test/Transforms/SCCP/pr50901.ll index 11d6bba6f6a935..d48d67532d88bd 100644 --- a/llvm/test/Transforms/SCCP/pr50901.ll +++ b/llvm/test/Transforms/SCCP/pr50901.ll @@ -52,6 +52,16 @@ ; CHECK: = !DIGlobalVariableExpression(var: ![[DBG_FLOAT_UNDEF:.+]], expr: !DIExpression()) ; CHECK-DAG: ![[DBG_FLOAT_UNDEF]] = distinct !DIGlobalVariable(name: "g_float_undef" +; CHECK: ![[G8:[0-9]+]] = !DIGlobalVariableExpression(var: ![[DBG8:[0-9]+]], expr: !DIExpression(DW_OP_constu, 22136, DW_OP_stack_value)) +; CHECK-DAG: ![[DBG8]] = distinct !DIGlobalVariable(name: "g_88", {{.*}} +; CHECK: ![[G9:[0-9]+]] = !DIGlobalVariableExpression(var: ![[DBG9:[0-9]+]], expr: !DIExpression(DW_OP_constu, 23726, DW_OP_stack_value)) +; CHECK-DAG: ![[DBG9]] = distinct !DIGlobalVariable(name: "g_99", {{.*}} + +; CHECK-DAG: ![[DBGA:[0-9]+]] = distinct !DIGlobalVariable(name: "g_i32_undef" +; CHECK-DAG: ![[GA:[0-9]+]] = !DIGlobalVariableExpression(var: ![[DBGA]], expr: !DIExpression()) +; CHECK-DAG: ![[DBGB:[0-9]+]] = distinct !DIGlobalVariable(name: "g_ptr_undef" +; CHECK-DAG: ![[GB:[0-9]+]] = !DIGlobalVariableExpression(var: ![[DBGB]], expr: !DIExpression()) + @g_1 = dso_local global i32 -4, align 4, !dbg !0 @g_2 = dso_local global float 0x4011C28F6000, align 4, !dbg !8 @g_3 = dso_local global i8 97, align 1, !dbg !10 @@ -59,6 +69,8 @@ @g_5 = dso_local global i8 1, align 1, !dbg !16 @g_6 = dso_local global ptr null, align 8, !dbg !19 @g_7 = dso_local global ptr null, align 8, !dbg !23 +@g_8 = dso_local global half 0xH4321, align 4, !dbg !86 +@g_9 = dso_local global bfloat 0xR3F80, align 4, !dbg !90 @_ZL4g_11 = internal global i32 -5, align 4, !dbg !25 @_ZL4g_22 = internal global float 0x40164000, align 4, !dbg !27 @_ZL4g_33 = internal global i8 98, align 1, !dbg !29 @@ -67,6 +79,10 @@ @_ZL4g_66 = internal global ptr null, align 8, !dbg !35 @_ZL4g_77 = internal global ptr inttoptr (i64 70 to ptr), align 8, !dbg !37 @g_float_undef = internal global float undef, align 4, !dbg !83 +@_ZL4g_88 = internal global half 0xH5678, align 4, !dbg !88 +@_ZL4g_99 = internal global bfloat 0xR5CAE, align 4, !dbg !92 +@g_i32_undef = internal global i32 undef, align 4, !dbg !95 +@g_ptr_undef = internal global ptr undef, align 8, !dbg !97 define dso_local void @_Z3barv() !dbg !46 { entry: @@ -88,6 +104,15 @@ entry: store ptr %6, ptr @g_7, align 8, !dbg !59 %l = load float, ptr @g_float_undef, align 8, !dbg !59 store float %l, ptr @g_2, align 8, !dbg !59 + %7 = load half, ptr @_ZL4g_88, align 4, !dbg !59 + store half %7, ptr @g_8, align 4, !dbg !59 + %8 = load bfloat, ptr @_ZL4g_99, align 4, !dbg !59 + store bfloat %8, ptr @g_9, align 4, !dbg !59 + %9 = load i32, ptr @g_i32_undef, align 4, !dbg !59 + store i32 %9, ptr @g_1, align 4, !dbg !59 + %10 = load ptr, ptr @g_ptr_undef, align 8, !dbg !59 + store ptr %10, ptr @g_6, align 8, !dbg !59 + ret void, !dbg !59 } @@ -108,7 +133,7 @@ entry: !4 = !{!5} !5 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !6, size: 64) !6 = !DIBasicType(name: "float", size: 32, encoding: DW_ATE_float) -!7 = !{!0, !8, !10, !13, !16, !19, !23, !25, !27, !29, !31, !33, !35, !37, !83} +!7 = !{!0, !8, !10, !13, !16, !19, !23, !25, !27, !29, !31, !33, !35, !37, !83, !86, !88, !90, !92, !95, !97} !8 = !DIGlobalVariableExpression(var: !9, expr: !DIExpression()) !9 = distinct !DIGlobalVariable(name: "g_2", scope: !2, file: !3, l
[llvm] [clang-tools-extra] [clang] [indvars] Missing variables at Og: (PR #69920)
https://github.com/CarlosAlbertoEnciso updated https://github.com/llvm/llvm-project/pull/69920 >From 844ec47fb887a860b4f8e28d435848a245eeb388 Mon Sep 17 00:00:00 2001 From: Carlos Alberto Enciso Date: Mon, 23 Oct 2023 11:44:22 +0100 Subject: [PATCH 1/5] [indvars] Missing variables at Og: https://bugs.llvm.org/show_bug.cgi?id=51735 https://github.com/llvm/llvm-project/issues/51077 In the given test case: 4 ... 5 void bar() { 6 int End = 777; 7 int Index = 27; 8 char Var = 1; 9 for (; Index < End; ++Index) 10 ; 11 nop(Index); 12 } 13 ... Missing local variable 'Index' after loop 'Induction Variable Elimination'. When adding a breakpoint at line 11, LLDB does not have information on the variable. But it has info on 'Var' and 'End'. --- llvm/lib/Transforms/Scalar/IndVarSimplify.cpp | 25 .../test/Transforms/LoopSimplify/pr51735-1.ll | 115 ++ llvm/test/Transforms/LoopSimplify/pr51735.ll | 106 3 files changed, 246 insertions(+) create mode 100644 llvm/test/Transforms/LoopSimplify/pr51735-1.ll create mode 100644 llvm/test/Transforms/LoopSimplify/pr51735.ll diff --git a/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp b/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp index 41c4d6236173472..0e20b5e62040374 100644 --- a/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp +++ b/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp @@ -46,6 +46,7 @@ #include "llvm/IR/ConstantRange.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DataLayout.h" +#include "llvm/IR/DebugInfo.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Dominators.h" #include "llvm/IR/Function.h" @@ -1931,6 +1932,30 @@ bool IndVarSimplify::run(Loop *L) { } } + // The loop exit values have been updated; insert the debug location + // for the induction variable with its final value. + if (PHINode *IndVar = L->getInductionVariable(*SE)) { +const SCEV *IndVarSCEV = SE->getSCEVAtScope(IndVar, L->getParentLoop()); +if (IndVarSCEV->getSCEVType() == SCEVTypes::scConstant) { + Value *FinalIVValue = cast(IndVarSCEV)->getValue(); + SmallVector DbgUsers; + SmallVector DbgUsersCloned; + findDbgUsers(DbgUsers, IndVar); + for (auto &DebugUser : DbgUsers) { +auto *Cloned = cast(DebugUser->clone()); +Cloned->replaceVariableLocationOp(static_cast(0), + FinalIVValue); +DbgUsersCloned.push_back(Cloned); + } + + SmallVector ExitBlocks; + L->getExitBlocks(ExitBlocks); + for (BasicBlock *Exit : ExitBlocks) +for (auto &DebugUser : DbgUsersCloned) + DebugUser->insertBefore(Exit->getFirstNonPHI()); +} + } + // Eliminate redundant IV cycles. NumElimIV += Rewriter.replaceCongruentIVs(L, DT, DeadInsts, TTI); diff --git a/llvm/test/Transforms/LoopSimplify/pr51735-1.ll b/llvm/test/Transforms/LoopSimplify/pr51735-1.ll new file mode 100644 index 000..de9a74522095659 --- /dev/null +++ b/llvm/test/Transforms/LoopSimplify/pr51735-1.ll @@ -0,0 +1,115 @@ +; RUN: opt -passes=indvars -S -o - < %s | FileCheck %s + +; Missing local variable 'Index' after loop 'Induction Variable Elimination'. +; When adding a breakpoint at line 11, LLDB does not have information on +; the variable. But it has info on 'Var' and 'End'. + +; 1 __attribute__((optnone)) int nop(int Param) { +; 2 return 0; +; 3 } +; 4 +; 5 void bar() { +; 6int End = 777; +; 7 int Index = 27; +; 8 char Var = 1; +; 9 for (; Index < End; ++Index) +; 10 ; +; 11 nop(Index); +; 12 } +; 13 +; 14 int main () { +; 15 bar(); +; 16 } + +; CHECK: for.cond: {{.*}} +; CHECK: call void @llvm.dbg.value(metadata i32 poison, metadata ![[DBG:[0-9]+]], {{.*}} +; CHECK: call void @llvm.dbg.value(metadata i32 poison, metadata ![[DBG:[0-9]+]], {{.*}} +; CHECK: br i1 false, label %for.cond, label %for.end, {{.*}} +; CHECK: for.end: {{.*}} +; CHECK: call void @llvm.dbg.value(metadata i32 777, metadata ![[DBG:[0-9]+]], {{.*}} +; CHECK: %call = tail call noundef i32 @_Z3nopi(i32 noundef 777), {{.*}} +; CHECK-DAG: ![[DBG]] = !DILocalVariable(name: "Index"{{.*}}) + +define dso_local noundef i32 @_Z3nopi(i32 noundef %Param) local_unnamed_addr #0 !dbg !10 { +entry: + %Param.addr = alloca i32, align 4 + store i32 %Param, ptr %Param.addr, align 4 + call void @llvm.dbg.declare(metadata ptr %Param.addr, metadata !15, metadata !DIExpression()), !dbg !16 + ret i32 0, !dbg !17 +} + +define dso_local void @_Z3barv() local_unnamed_addr #2 !dbg !18 { +entry: + call void @llvm.dbg.value(metadata i32 777, metadata !21, metadata !DIExpression()), !dbg !22 + call void @llvm.dbg.value(metadata i32 27, metadata !23, metadata !DIExpression()), !dbg !22 + call void @llvm.dbg.value(metadata i32 1, metadata !24, metadata !DIExpression()), !dbg !22 + br label %for.cond, !dbg !25 + +for.cond: ; preds = %for.cond, %entry + %I
[clang] [Clang][DebugInfo] Clang generates an extra spurious unnamed 'dbg.declare' (PR #69681)
https://github.com/CarlosAlbertoEnciso created https://github.com/llvm/llvm-project/pull/69681 Do not emit call to llvm.dbg.declare when the variable declaration is a DecompositionDecl as its instance class is always unnamed. The emitted debug declare looks like: ``` call void @llvm.dbg.declare(metadata ..., metadata !xx, metadata ...) !xx = !DILocalVariable(scope: !..., file: !..., line: ..., type: !...) ``` >From 4e0131db5033ba426746729229bcd30148690ac2 Mon Sep 17 00:00:00 2001 From: Carlos Alberto Enciso Date: Fri, 20 Oct 2023 06:09:04 +0100 Subject: [PATCH] [Clang][DebugInfo] Clang generates an extra spurious unnamed 'dbg.declare'. Do not emit call to llvm.dbg.declare when the variable declaration is a DecompositionDecl as its instance class is always unnamed. The emitted debug declare looks like: call void @llvm.dbg.declare(metadata ..., metadata !xx, metadata ...) !xx = !DILocalVariable(scope: !..., file: !..., line: ..., type: !...) --- clang/lib/CodeGen/CGDebugInfo.cpp | 6 +- ...debug-info-structured-binding-bitfield.cpp | 3 --- .../debug-info-structured-binding-field.cpp | 20 +++ .../debug-info-structured-binding.cpp | 2 -- 4 files changed, 25 insertions(+), 6 deletions(-) create mode 100644 clang/test/CodeGenCXX/debug-info-structured-binding-field.cpp diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index c430713b0d77d79..b2646cd1d2a0f53 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -4879,11 +4879,15 @@ CGDebugInfo::EmitDeclareOfAutoVariable(const VarDecl *VD, llvm::Value *Storage, const bool UsePointerValue) { assert(CGM.getCodeGenOpts().hasReducedDebugInfo()); - if (auto *DD = dyn_cast(VD)) + if (auto *DD = dyn_cast(VD)) { for (auto *B : DD->bindings()) { EmitDeclare(B, Storage, std::nullopt, Builder, VD->getType()->isReferenceType()); } +// Don't emit an llvm.dbg.declare for the composite storage as it doesn't +// correspond to a user variable. +return nullptr; + } return EmitDeclare(VD, Storage, std::nullopt, Builder, UsePointerValue); } diff --git a/clang/test/CodeGenCXX/debug-info-structured-binding-bitfield.cpp b/clang/test/CodeGenCXX/debug-info-structured-binding-bitfield.cpp index b5ee96224565d3a..0234e41009f6225 100644 --- a/clang/test/CodeGenCXX/debug-info-structured-binding-bitfield.cpp +++ b/clang/test/CodeGenCXX/debug-info-structured-binding-bitfield.cpp @@ -189,7 +189,6 @@ struct S11 { // CHECK-LABEL: define dso_local void @_Z4fS11v // CHECK:alloca %struct.S11, align 4 // CHECK-NEXT:[[TMP0:%.*]] = alloca %struct.S11, align 4 -// CHECK: call void @llvm.dbg.declare(metadata ptr [[TMP0]] // CHECK-NOT: call void @llvm.dbg.declare(metadata ptr [[TMP0]] // void fS11() { @@ -206,7 +205,6 @@ struct S12 { // CHECK:alloca %struct.S12, align 4 // CHECK-NEXT:[[TMP0:%.*]] = alloca %struct.S12, align 4 // CHECK: call void @llvm.dbg.declare(metadata ptr [[TMP0]], metadata [[S12_A:![0-9]+]], metadata !DIExpression()) -// CHECK: call void @llvm.dbg.declare(metadata ptr [[TMP0]] // CHECK-NOT: call void @llvm.dbg.declare(metadata ptr [[TMP0]] // void fS12() { @@ -222,7 +220,6 @@ struct __attribute__((packed)) S13 { // CHECK-LABEL: define dso_local void @_Z4fS13v // CHECK:alloca %struct.S13, align 1 // CHECK-NEXT:[[TMP0:%.*]] = alloca %struct.S13, align 1 -// CHECK: call void @llvm.dbg.declare(metadata ptr [[TMP0]], metadata {{.*}}, metadata !DIExpression()) // CHECK-NOT: call void @llvm.dbg.declare(metadata ptr [[TMP0]] // void fS13() { diff --git a/clang/test/CodeGenCXX/debug-info-structured-binding-field.cpp b/clang/test/CodeGenCXX/debug-info-structured-binding-field.cpp new file mode 100644 index 000..928d22776d21093 --- /dev/null +++ b/clang/test/CodeGenCXX/debug-info-structured-binding-field.cpp @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -emit-llvm -debug-info-kind=standalone %s -o - | FileCheck %s + +struct Tuple { + int Fld_1; + int Fld_2; +}; +__attribute__((optnone)) Tuple get() { return {10, 20}; } + +// CHECK-LABEL: define dso_local noundef i32 @main +// CHECK: %retval = alloca i32, align 4 +// CHECK-NEXT: [[T0:%.*]] = alloca %struct.Tuple, align 4 +// CHECK: call void @llvm.dbg.declare(metadata ptr [[T0]], metadata {{.*}}, metadata !DIExpression()) +// CHECK: call void @llvm.dbg.declare(metadata ptr [[T0]], metadata {{.*}}, metadata !DIExpression(DW_OP_plus_uconst, {{[0-9]+}})) +// CHECK-NOT: call void @llvm.dbg.declare(metadata ptr [[T0]], metadata {{.*}}, metadata !DIExpression()) +// +int main() { + auto [Var_1, Var_2] = get(); + + return Var_1 + Var_2; +} diff --git a/clang/test/CodeGenCXX/debug-info-structured-binding.cpp b/clang/test/CodeGenCXX/debug-info-stru
[clang] [Clang][DebugInfo] Clang generates an extra spurious unnamed 'dbg.declare' (PR #69681)
https://github.com/CarlosAlbertoEnciso updated https://github.com/llvm/llvm-project/pull/69681 >From eef5d041e6b2fe02bba86113a41035324c6c81b8 Mon Sep 17 00:00:00 2001 From: Carlos Alberto Enciso Date: Fri, 20 Oct 2023 06:09:04 +0100 Subject: [PATCH 1/2] [Clang][DebugInfo] Clang generates an extra spurious unnamed 'dbg.declare'. Do not emit call to llvm.dbg.declare when the variable declaration is a DecompositionDecl as its instance class is always unnamed. The emitted debug declare looks like: call void @llvm.dbg.declare(metadata ..., metadata !xx, metadata ...) !xx = !DILocalVariable(scope: !..., file: !..., line: ..., type: !...) --- clang/lib/CodeGen/CGDebugInfo.cpp | 6 +- ...debug-info-structured-binding-bitfield.cpp | 3 --- .../debug-info-structured-binding-field.cpp | 20 +++ .../debug-info-structured-binding.cpp | 2 -- 4 files changed, 25 insertions(+), 6 deletions(-) create mode 100644 clang/test/CodeGenCXX/debug-info-structured-binding-field.cpp diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index 181e500b9671759..0aaf678bf287c6e 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -4881,11 +4881,15 @@ CGDebugInfo::EmitDeclareOfAutoVariable(const VarDecl *VD, llvm::Value *Storage, const bool UsePointerValue) { assert(CGM.getCodeGenOpts().hasReducedDebugInfo()); - if (auto *DD = dyn_cast(VD)) + if (auto *DD = dyn_cast(VD)) { for (auto *B : DD->bindings()) { EmitDeclare(B, Storage, std::nullopt, Builder, VD->getType()->isReferenceType()); } +// Don't emit an llvm.dbg.declare for the composite storage as it doesn't +// correspond to a user variable. +return nullptr; + } return EmitDeclare(VD, Storage, std::nullopt, Builder, UsePointerValue); } diff --git a/clang/test/CodeGenCXX/debug-info-structured-binding-bitfield.cpp b/clang/test/CodeGenCXX/debug-info-structured-binding-bitfield.cpp index b5ee96224565d3a..0234e41009f6225 100644 --- a/clang/test/CodeGenCXX/debug-info-structured-binding-bitfield.cpp +++ b/clang/test/CodeGenCXX/debug-info-structured-binding-bitfield.cpp @@ -189,7 +189,6 @@ struct S11 { // CHECK-LABEL: define dso_local void @_Z4fS11v // CHECK:alloca %struct.S11, align 4 // CHECK-NEXT:[[TMP0:%.*]] = alloca %struct.S11, align 4 -// CHECK: call void @llvm.dbg.declare(metadata ptr [[TMP0]] // CHECK-NOT: call void @llvm.dbg.declare(metadata ptr [[TMP0]] // void fS11() { @@ -206,7 +205,6 @@ struct S12 { // CHECK:alloca %struct.S12, align 4 // CHECK-NEXT:[[TMP0:%.*]] = alloca %struct.S12, align 4 // CHECK: call void @llvm.dbg.declare(metadata ptr [[TMP0]], metadata [[S12_A:![0-9]+]], metadata !DIExpression()) -// CHECK: call void @llvm.dbg.declare(metadata ptr [[TMP0]] // CHECK-NOT: call void @llvm.dbg.declare(metadata ptr [[TMP0]] // void fS12() { @@ -222,7 +220,6 @@ struct __attribute__((packed)) S13 { // CHECK-LABEL: define dso_local void @_Z4fS13v // CHECK:alloca %struct.S13, align 1 // CHECK-NEXT:[[TMP0:%.*]] = alloca %struct.S13, align 1 -// CHECK: call void @llvm.dbg.declare(metadata ptr [[TMP0]], metadata {{.*}}, metadata !DIExpression()) // CHECK-NOT: call void @llvm.dbg.declare(metadata ptr [[TMP0]] // void fS13() { diff --git a/clang/test/CodeGenCXX/debug-info-structured-binding-field.cpp b/clang/test/CodeGenCXX/debug-info-structured-binding-field.cpp new file mode 100644 index 000..928d22776d21093 --- /dev/null +++ b/clang/test/CodeGenCXX/debug-info-structured-binding-field.cpp @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -emit-llvm -debug-info-kind=standalone %s -o - | FileCheck %s + +struct Tuple { + int Fld_1; + int Fld_2; +}; +__attribute__((optnone)) Tuple get() { return {10, 20}; } + +// CHECK-LABEL: define dso_local noundef i32 @main +// CHECK: %retval = alloca i32, align 4 +// CHECK-NEXT: [[T0:%.*]] = alloca %struct.Tuple, align 4 +// CHECK: call void @llvm.dbg.declare(metadata ptr [[T0]], metadata {{.*}}, metadata !DIExpression()) +// CHECK: call void @llvm.dbg.declare(metadata ptr [[T0]], metadata {{.*}}, metadata !DIExpression(DW_OP_plus_uconst, {{[0-9]+}})) +// CHECK-NOT: call void @llvm.dbg.declare(metadata ptr [[T0]], metadata {{.*}}, metadata !DIExpression()) +// +int main() { + auto [Var_1, Var_2] = get(); + + return Var_1 + Var_2; +} diff --git a/clang/test/CodeGenCXX/debug-info-structured-binding.cpp b/clang/test/CodeGenCXX/debug-info-structured-binding.cpp index 8d4ae0aaf32636b..163c152efa19d0b 100644 --- a/clang/test/CodeGenCXX/debug-info-structured-binding.cpp +++ b/clang/test/CodeGenCXX/debug-info-structured-binding.cpp @@ -2,10 +2,8 @@ // CHECK: call void @llvm.dbg.declare(metadata ptr %{{[0-9]+}}, metadata !{{[0-9]+}}, metadata !DIExpressio
[clang] [Clang][DebugInfo] Clang generates an extra spurious unnamed 'dbg.declare' (PR #69681)
@@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -emit-llvm -debug-info-kind=standalone %s -o - | FileCheck %s + +struct Tuple { + int Fld_1; + int Fld_2; +}; +__attribute__((optnone)) Tuple get() { return {10, 20}; } + +// CHECK-LABEL: define dso_local noundef i32 @main +// CHECK: %retval = alloca i32, align 4 +// CHECK-NEXT: [[T0:%.*]] = alloca %struct.Tuple, align 4 +// CHECK: call void @llvm.dbg.declare(metadata ptr [[T0]], metadata {{.*}}, metadata !DIExpression()) +// CHECK: call void @llvm.dbg.declare(metadata ptr [[T0]], metadata {{.*}}, metadata !DIExpression(DW_OP_plus_uconst, {{[0-9]+}})) +// CHECK-NOT: call void @llvm.dbg.declare(metadata ptr [[T0]], metadata {{.*}}, metadata !DIExpression()) CarlosAlbertoEnciso wrote: Removed the test case. Added checks to check the variable names. https://github.com/llvm/llvm-project/pull/69681 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][DebugInfo] Clang generates an extra spurious unnamed 'dbg.declare' (PR #69681)
@@ -2,10 +2,8 @@ CarlosAlbertoEnciso wrote: Added the `--implicit-check-not` option. https://github.com/llvm/llvm-project/pull/69681 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][DebugInfo] Clang generates an extra spurious unnamed 'dbg.declare' (PR #69681)
CarlosAlbertoEnciso wrote: Uploaded new patch to address comments from @OCHyams https://github.com/llvm/llvm-project/pull/69681 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][DebugInfo] Clang generates an extra spurious unnamed 'dbg.declare' (PR #69681)
https://github.com/CarlosAlbertoEnciso updated https://github.com/llvm/llvm-project/pull/69681 >From 42df544996bb8fee93e5d1bab72e71578645bcc4 Mon Sep 17 00:00:00 2001 From: Carlos Alberto Enciso Date: Fri, 20 Oct 2023 06:09:04 +0100 Subject: [PATCH 1/3] [Clang][DebugInfo] Clang generates an extra spurious unnamed 'dbg.declare'. Do not emit call to llvm.dbg.declare when the variable declaration is a DecompositionDecl as its instance class is always unnamed. The emitted debug declare looks like: call void @llvm.dbg.declare(metadata ..., metadata !xx, metadata ...) !xx = !DILocalVariable(scope: !..., file: !..., line: ..., type: !...) --- clang/lib/CodeGen/CGDebugInfo.cpp | 6 +- ...debug-info-structured-binding-bitfield.cpp | 3 --- .../debug-info-structured-binding-field.cpp | 20 +++ .../debug-info-structured-binding.cpp | 2 -- 4 files changed, 25 insertions(+), 6 deletions(-) create mode 100644 clang/test/CodeGenCXX/debug-info-structured-binding-field.cpp diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index 181e500b9671759..0aaf678bf287c6e 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -4881,11 +4881,15 @@ CGDebugInfo::EmitDeclareOfAutoVariable(const VarDecl *VD, llvm::Value *Storage, const bool UsePointerValue) { assert(CGM.getCodeGenOpts().hasReducedDebugInfo()); - if (auto *DD = dyn_cast(VD)) + if (auto *DD = dyn_cast(VD)) { for (auto *B : DD->bindings()) { EmitDeclare(B, Storage, std::nullopt, Builder, VD->getType()->isReferenceType()); } +// Don't emit an llvm.dbg.declare for the composite storage as it doesn't +// correspond to a user variable. +return nullptr; + } return EmitDeclare(VD, Storage, std::nullopt, Builder, UsePointerValue); } diff --git a/clang/test/CodeGenCXX/debug-info-structured-binding-bitfield.cpp b/clang/test/CodeGenCXX/debug-info-structured-binding-bitfield.cpp index b5ee96224565d3a..0234e41009f6225 100644 --- a/clang/test/CodeGenCXX/debug-info-structured-binding-bitfield.cpp +++ b/clang/test/CodeGenCXX/debug-info-structured-binding-bitfield.cpp @@ -189,7 +189,6 @@ struct S11 { // CHECK-LABEL: define dso_local void @_Z4fS11v // CHECK:alloca %struct.S11, align 4 // CHECK-NEXT:[[TMP0:%.*]] = alloca %struct.S11, align 4 -// CHECK: call void @llvm.dbg.declare(metadata ptr [[TMP0]] // CHECK-NOT: call void @llvm.dbg.declare(metadata ptr [[TMP0]] // void fS11() { @@ -206,7 +205,6 @@ struct S12 { // CHECK:alloca %struct.S12, align 4 // CHECK-NEXT:[[TMP0:%.*]] = alloca %struct.S12, align 4 // CHECK: call void @llvm.dbg.declare(metadata ptr [[TMP0]], metadata [[S12_A:![0-9]+]], metadata !DIExpression()) -// CHECK: call void @llvm.dbg.declare(metadata ptr [[TMP0]] // CHECK-NOT: call void @llvm.dbg.declare(metadata ptr [[TMP0]] // void fS12() { @@ -222,7 +220,6 @@ struct __attribute__((packed)) S13 { // CHECK-LABEL: define dso_local void @_Z4fS13v // CHECK:alloca %struct.S13, align 1 // CHECK-NEXT:[[TMP0:%.*]] = alloca %struct.S13, align 1 -// CHECK: call void @llvm.dbg.declare(metadata ptr [[TMP0]], metadata {{.*}}, metadata !DIExpression()) // CHECK-NOT: call void @llvm.dbg.declare(metadata ptr [[TMP0]] // void fS13() { diff --git a/clang/test/CodeGenCXX/debug-info-structured-binding-field.cpp b/clang/test/CodeGenCXX/debug-info-structured-binding-field.cpp new file mode 100644 index 000..928d22776d21093 --- /dev/null +++ b/clang/test/CodeGenCXX/debug-info-structured-binding-field.cpp @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -emit-llvm -debug-info-kind=standalone %s -o - | FileCheck %s + +struct Tuple { + int Fld_1; + int Fld_2; +}; +__attribute__((optnone)) Tuple get() { return {10, 20}; } + +// CHECK-LABEL: define dso_local noundef i32 @main +// CHECK: %retval = alloca i32, align 4 +// CHECK-NEXT: [[T0:%.*]] = alloca %struct.Tuple, align 4 +// CHECK: call void @llvm.dbg.declare(metadata ptr [[T0]], metadata {{.*}}, metadata !DIExpression()) +// CHECK: call void @llvm.dbg.declare(metadata ptr [[T0]], metadata {{.*}}, metadata !DIExpression(DW_OP_plus_uconst, {{[0-9]+}})) +// CHECK-NOT: call void @llvm.dbg.declare(metadata ptr [[T0]], metadata {{.*}}, metadata !DIExpression()) +// +int main() { + auto [Var_1, Var_2] = get(); + + return Var_1 + Var_2; +} diff --git a/clang/test/CodeGenCXX/debug-info-structured-binding.cpp b/clang/test/CodeGenCXX/debug-info-structured-binding.cpp index 8d4ae0aaf32636b..163c152efa19d0b 100644 --- a/clang/test/CodeGenCXX/debug-info-structured-binding.cpp +++ b/clang/test/CodeGenCXX/debug-info-structured-binding.cpp @@ -2,10 +2,8 @@ // CHECK: call void @llvm.dbg.declare(metadata ptr %{{[0-9]+}}, metadata !{{[0-9]+}}, metadata !DIExpressio
[clang] [Clang][DebugInfo] Clang generates an extra spurious unnamed 'dbg.declare' (PR #69681)
CarlosAlbertoEnciso wrote: Uploaded new patch to address minor details with the test case: - Added check for missing captured `a` variable. - Check for the specific values in `DW_OP_plus_uconst`. https://github.com/llvm/llvm-project/pull/69681 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][DebugInfo] Clang generates an extra spurious unnamed 'dbg.declare' (PR #69681)
CarlosAlbertoEnciso wrote: @adrian-prantl, @OCHyams Thanks for your reviews. https://github.com/llvm/llvm-project/pull/69681 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][DebugInfo] Clang generates an extra spurious unnamed 'dbg.declare' (PR #69681)
https://github.com/CarlosAlbertoEnciso closed https://github.com/llvm/llvm-project/pull/69681 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] 177cbb1 - [CMake] Explicit bootstrap options override any passthrough ones.
Author: Carlos Alberto Enciso Date: 2022-08-17T08:16:10+01:00 New Revision: 177cbb1c9b661b15a7db35e4ec9255adf502a6cb URL: https://github.com/llvm/llvm-project/commit/177cbb1c9b661b15a7db35e4ec9255adf502a6cb DIFF: https://github.com/llvm/llvm-project/commit/177cbb1c9b661b15a7db35e4ec9255adf502a6cb.diff LOG: [CMake] Explicit bootstrap options override any passthrough ones. The https://reviews.llvm.org/D53014 added CMAKE_BUILD_TYPE to the list of BOOTSTRAP_DEFAULT_PASSTHROUGH variables. The downside is that both stage-1 and stage-2 configurations are the same. So it is not possible to build different stage configurations. This patch allow explicit bootstrap options to override any passthrough ones. For instance, the following settings would build: stage-1 (Release) and stage-2(Debug) -DCMAKE_BUILD_TYPE=Release -DBOOTSTRAP_CMAKE_BUILD_TYPE=Debug Reviewed By: @beanz Differential Revision: https://reviews.llvm.org/D131755 Added: Modified: clang/CMakeLists.txt Removed: diff --git a/clang/CMakeLists.txt b/clang/CMakeLists.txt index f6e860159435..60f6c162a2d5 100644 --- a/clang/CMakeLists.txt +++ b/clang/CMakeLists.txt @@ -758,6 +758,19 @@ if (CLANG_ENABLE_BOOTSTRAP) set(LTO_RANLIB) endif() + # Populate the passthrough variables + foreach(variableName ${CLANG_BOOTSTRAP_PASSTHROUGH} ${_BOOTSTRAP_DEFAULT_PASSTHROUGH}) +if(DEFINED ${variableName}) + if("${${variableName}}" STREQUAL "") +set(value "") + else() +string(REPLACE ";" "|" value "${${variableName}}") + endif() + list(APPEND PASSTHROUGH_VARIABLES +-D${variableName}=${value}) +endif() + endforeach() + # Find all variables that start with BOOTSTRAP_ and populate a variable with # them. get_cmake_property(variableNames VARIABLES) @@ -774,19 +787,6 @@ if (CLANG_ENABLE_BOOTSTRAP) endif() endforeach() - # Populate the passthrough variables - foreach(variableName ${CLANG_BOOTSTRAP_PASSTHROUGH} ${_BOOTSTRAP_DEFAULT_PASSTHROUGH}) -if(DEFINED ${variableName}) - if("${${variableName}}" STREQUAL "") -set(value "") - else() -string(REPLACE ";" "|" value "${${variableName}}") - endif() - list(APPEND PASSTHROUGH_VARIABLES --D${variableName}=${value}) -endif() - endforeach() - ExternalProject_Add(${NEXT_CLANG_STAGE} DEPENDS clang-bootstrap-deps PREFIX ${NEXT_CLANG_STAGE} ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] 6c6c4f6 - [CMake] Support passing arguments to build tool (bootstrap).
Author: Carlos Alberto Enciso Date: 2022-08-23T05:45:25+01:00 New Revision: 6c6c4f6a9b3ef2d7db937cb78784245ea8a61418 URL: https://github.com/llvm/llvm-project/commit/6c6c4f6a9b3ef2d7db937cb78784245ea8a61418 DIFF: https://github.com/llvm/llvm-project/commit/6c6c4f6a9b3ef2d7db937cb78784245ea8a61418.diff LOG: [CMake] Support passing arguments to build tool (bootstrap). For bootstrap builds (CLANG_ENABLE_BOOTSTRAP=ON) allow arguments to be passed to the native tool used in CMake for the stage2 step. Can be used to pass extra arguments for enhanced versions of build tools, e.g. distributed build options. Reviewed By: phosek Differential Revision: https://reviews.llvm.org/D131665 Added: Modified: clang/CMakeLists.txt Removed: diff --git a/clang/CMakeLists.txt b/clang/CMakeLists.txt index a6782db7b580..332df8f3b8bf 100644 --- a/clang/CMakeLists.txt +++ b/clang/CMakeLists.txt @@ -787,6 +787,14 @@ if (CLANG_ENABLE_BOOTSTRAP) endif() endforeach() + # Build arguments for native tool used in CMake. + set(build_configuration "$") + set(build_tool_args "${LLVM_EXTERNAL_PROJECT_BUILD_TOOL_ARGS}") + if(NOT build_tool_args STREQUAL "") +string(PREPEND build_tool_args "-- ") +separate_arguments(build_tool_args UNIX_COMMAND "${build_tool_args}") + endif() + ExternalProject_Add(${NEXT_CLANG_STAGE} DEPENDS clang-bootstrap-deps PREFIX ${NEXT_CLANG_STAGE} @@ -809,6 +817,9 @@ if (CLANG_ENABLE_BOOTSTRAP) ${${CLANG_STAGE}_RANLIB} ${${CLANG_STAGE}_OBJCOPY} ${${CLANG_STAGE}_STRIP} +BUILD_COMMAND ${CMAKE_COMMAND} --build ${BINARY_DIR} + --config ${build_configuration} + ${build_tool_args} INSTALL_COMMAND "" STEP_TARGETS configure build USES_TERMINAL_CONFIGURE 1 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [IPSCCP] Variable not visible at Og: (PR #66745)
https://github.com/CarlosAlbertoEnciso updated https://github.com/llvm/llvm-project/pull/66745 >From b24943f63025822a5c5ba90c4a7b47f7123ec4db Mon Sep 17 00:00:00 2001 From: Carlos Alberto Enciso Date: Mon, 18 Sep 2023 12:29:17 +0100 Subject: [PATCH] [IPSCCP] Variable not visible at Og: https://bugs.llvm.org/show_bug.cgi?id=51559 https://github.com/llvm/llvm-project/issues/50901 IPSCCP pass removes the global variable and does not create a constant expression for the initializer value. --- llvm/lib/Transforms/IPO/SCCP.cpp | 47 +++ llvm/test/Transforms/SCCP/pr50901.ll | 184 +++ 2 files changed, 231 insertions(+) create mode 100644 llvm/test/Transforms/SCCP/pr50901.ll diff --git a/llvm/lib/Transforms/IPO/SCCP.cpp b/llvm/lib/Transforms/IPO/SCCP.cpp index 84f5bbf7039416b..e09769e00148143 100644 --- a/llvm/lib/Transforms/IPO/SCCP.cpp +++ b/llvm/lib/Transforms/IPO/SCCP.cpp @@ -22,6 +22,7 @@ #include "llvm/Analysis/ValueTracking.h" #include "llvm/IR/AttributeMask.h" #include "llvm/IR/Constants.h" +#include "llvm/IR/DIBuilder.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/ModRef.h" @@ -371,6 +372,52 @@ static bool runIPSCCP( StoreInst *SI = cast(GV->user_back()); SI->eraseFromParent(); } + +// Try to create a debug constant expression for the glbal variable +// initializer value. +SmallVector GVEs; +GV->getDebugInfo(GVEs); +if (GVEs.size() == 1) { + DIBuilder DIB(M); + + // Create integer constant expression. + auto createIntExpression = [&DIB](const Constant *CV) -> DIExpression * { +const APInt &API = dyn_cast(CV)->getValue(); +std::optional InitIntOpt; +if (API.isNonNegative()) + InitIntOpt = API.tryZExtValue(); +else if (auto Temp = API.trySExtValue(); Temp.has_value()) + // Transform a signed optional to unsigned optional. + InitIntOpt = (uint64_t)Temp.value(); +return DIB.createConstantValueExpression(InitIntOpt.value()); + }; + + const Constant *CV = GV->getInitializer(); + Type *Ty = GV->getValueType(); + if (Ty->isIntegerTy()) { +GVEs[0]->replaceOperandWith(1, createIntExpression(CV)); + } else if (Ty->isFloatTy() || Ty->isDoubleTy()) { +const APFloat &APF = dyn_cast(CV)->getValueAPF(); +DIExpression *NewExpr = DIB.createConstantValueExpression( +APF.bitcastToAPInt().getZExtValue()); +GVEs[0]->replaceOperandWith(1, NewExpr); + } else if (Ty->isPointerTy()) { +if (isa(CV)) { + GVEs[0]->replaceOperandWith(1, DIB.createConstantValueExpression(0)); +} else { + if (const ConstantExpr *CE = dyn_cast(CV)) { +if (CE->getNumOperands() == 1) { + const Value *V = CE->getOperand(0); + const Constant *CV = dyn_cast(V); + if (CV && !isa(CV)) +if (const ConstantInt *CI = dyn_cast(CV)) + GVEs[0]->replaceOperandWith(1, createIntExpression(CI)); +} + } +} + } +} + MadeChanges = true; M.eraseGlobalVariable(GV); ++NumGlobalConst; diff --git a/llvm/test/Transforms/SCCP/pr50901.ll b/llvm/test/Transforms/SCCP/pr50901.ll new file mode 100644 index 000..56961d2e32db41c --- /dev/null +++ b/llvm/test/Transforms/SCCP/pr50901.ll @@ -0,0 +1,184 @@ +; RUN: opt -passes=ipsccp -S -o - < %s | FileCheck %s + +; Global variables g_11, g_22, g_33, g_44, g_55, g_66 and g_77 +; are not visible in the debugger. + +; 1 int g_1 = -4; +; 2 float g_2 = 4.44; +; 3 char g_3 = 'a'; +; 4 unsigned g_4 = 4; +; 5 bool g_5 = true; +; 6 int *g_6 = nullptr; +; 7 float*g_7 = nullptr; +; 8 +; 9 static int g_11 = -5; +; 10 static float g_22 = 5.55; +; 11 static char g_33 = 'b'; +; 12 static unsigned g_44 = 5; +; 13 static bool g_55 = true; +; 14 static int *g_66 = nullptr; +; 15 static float*g_77 = (float *)(55 + 15); +; 16 +; 17 void bar() { +; 18 g_1 = g_11; +; 19 g_2 = g_22; +; 20 g_3 = g_33; +; 21 g_4 = g_44; +; 22 g_5 = g_55; +; 23 g_6 = g_66; +; 24 g_7 = g_77; +; 25 } +; 26 +; 27 int main() { +; 28 { +; 29 bar(); +; 30 } +; 31 } + +; CHECK: ![[G1:[0-9]+]] = !DIGlobalVariableExpression(var: ![[DBG1:[0-9]+]], expr: !DIExpression(DW_OP_constu, 18446744073709551611, DW_OP_stack_value)) +; CHECK-DAG: ![[DBG1]] = distinct !DIGlobalVariable(name: "g_11", {{.*}} +; CHECK: ![[G2:[0-9]+]] = !DIGlobalVariableExpression(var: ![[DBG2:[0-9]+]], expr: !DIExpression(DW_OP_constu, 1085381018, DW_OP_stack_value)) +; CHECK-DAG: ![[DBG2]] = distinct !DIGlobalVariable(name: "g_22", {{.*}} +; CHECK: ![[G3:[0-9]+]] = !DIGlobalVariableExpression(var: ![[DBG3:[0-9]+]], expr: !DIExpression(DW_OP_constu, 98, DW_OP_stack_value)) +; CHECK-DAG: ![[DBG3]] = distinct !
[clang] [IPSCCP] Variable not visible at Og: (PR #66745)
https://github.com/CarlosAlbertoEnciso updated https://github.com/llvm/llvm-project/pull/66745 >From b24943f63025822a5c5ba90c4a7b47f7123ec4db Mon Sep 17 00:00:00 2001 From: Carlos Alberto Enciso Date: Mon, 18 Sep 2023 12:29:17 +0100 Subject: [PATCH] [IPSCCP] Variable not visible at Og: https://bugs.llvm.org/show_bug.cgi?id=51559 https://github.com/llvm/llvm-project/issues/50901 IPSCCP pass removes the global variable and does not create a constant expression for the initializer value. --- llvm/lib/Transforms/IPO/SCCP.cpp | 47 +++ llvm/test/Transforms/SCCP/pr50901.ll | 184 +++ 2 files changed, 231 insertions(+) create mode 100644 llvm/test/Transforms/SCCP/pr50901.ll diff --git a/llvm/lib/Transforms/IPO/SCCP.cpp b/llvm/lib/Transforms/IPO/SCCP.cpp index 84f5bbf7039416b..e09769e00148143 100644 --- a/llvm/lib/Transforms/IPO/SCCP.cpp +++ b/llvm/lib/Transforms/IPO/SCCP.cpp @@ -22,6 +22,7 @@ #include "llvm/Analysis/ValueTracking.h" #include "llvm/IR/AttributeMask.h" #include "llvm/IR/Constants.h" +#include "llvm/IR/DIBuilder.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/ModRef.h" @@ -371,6 +372,52 @@ static bool runIPSCCP( StoreInst *SI = cast(GV->user_back()); SI->eraseFromParent(); } + +// Try to create a debug constant expression for the glbal variable +// initializer value. +SmallVector GVEs; +GV->getDebugInfo(GVEs); +if (GVEs.size() == 1) { + DIBuilder DIB(M); + + // Create integer constant expression. + auto createIntExpression = [&DIB](const Constant *CV) -> DIExpression * { +const APInt &API = dyn_cast(CV)->getValue(); +std::optional InitIntOpt; +if (API.isNonNegative()) + InitIntOpt = API.tryZExtValue(); +else if (auto Temp = API.trySExtValue(); Temp.has_value()) + // Transform a signed optional to unsigned optional. + InitIntOpt = (uint64_t)Temp.value(); +return DIB.createConstantValueExpression(InitIntOpt.value()); + }; + + const Constant *CV = GV->getInitializer(); + Type *Ty = GV->getValueType(); + if (Ty->isIntegerTy()) { +GVEs[0]->replaceOperandWith(1, createIntExpression(CV)); + } else if (Ty->isFloatTy() || Ty->isDoubleTy()) { +const APFloat &APF = dyn_cast(CV)->getValueAPF(); +DIExpression *NewExpr = DIB.createConstantValueExpression( +APF.bitcastToAPInt().getZExtValue()); +GVEs[0]->replaceOperandWith(1, NewExpr); + } else if (Ty->isPointerTy()) { +if (isa(CV)) { + GVEs[0]->replaceOperandWith(1, DIB.createConstantValueExpression(0)); +} else { + if (const ConstantExpr *CE = dyn_cast(CV)) { +if (CE->getNumOperands() == 1) { + const Value *V = CE->getOperand(0); + const Constant *CV = dyn_cast(V); + if (CV && !isa(CV)) +if (const ConstantInt *CI = dyn_cast(CV)) + GVEs[0]->replaceOperandWith(1, createIntExpression(CI)); +} + } +} + } +} + MadeChanges = true; M.eraseGlobalVariable(GV); ++NumGlobalConst; diff --git a/llvm/test/Transforms/SCCP/pr50901.ll b/llvm/test/Transforms/SCCP/pr50901.ll new file mode 100644 index 000..56961d2e32db41c --- /dev/null +++ b/llvm/test/Transforms/SCCP/pr50901.ll @@ -0,0 +1,184 @@ +; RUN: opt -passes=ipsccp -S -o - < %s | FileCheck %s + +; Global variables g_11, g_22, g_33, g_44, g_55, g_66 and g_77 +; are not visible in the debugger. + +; 1 int g_1 = -4; +; 2 float g_2 = 4.44; +; 3 char g_3 = 'a'; +; 4 unsigned g_4 = 4; +; 5 bool g_5 = true; +; 6 int *g_6 = nullptr; +; 7 float*g_7 = nullptr; +; 8 +; 9 static int g_11 = -5; +; 10 static float g_22 = 5.55; +; 11 static char g_33 = 'b'; +; 12 static unsigned g_44 = 5; +; 13 static bool g_55 = true; +; 14 static int *g_66 = nullptr; +; 15 static float*g_77 = (float *)(55 + 15); +; 16 +; 17 void bar() { +; 18 g_1 = g_11; +; 19 g_2 = g_22; +; 20 g_3 = g_33; +; 21 g_4 = g_44; +; 22 g_5 = g_55; +; 23 g_6 = g_66; +; 24 g_7 = g_77; +; 25 } +; 26 +; 27 int main() { +; 28 { +; 29 bar(); +; 30 } +; 31 } + +; CHECK: ![[G1:[0-9]+]] = !DIGlobalVariableExpression(var: ![[DBG1:[0-9]+]], expr: !DIExpression(DW_OP_constu, 18446744073709551611, DW_OP_stack_value)) +; CHECK-DAG: ![[DBG1]] = distinct !DIGlobalVariable(name: "g_11", {{.*}} +; CHECK: ![[G2:[0-9]+]] = !DIGlobalVariableExpression(var: ![[DBG2:[0-9]+]], expr: !DIExpression(DW_OP_constu, 1085381018, DW_OP_stack_value)) +; CHECK-DAG: ![[DBG2]] = distinct !DIGlobalVariable(name: "g_22", {{.*}} +; CHECK: ![[G3:[0-9]+]] = !DIGlobalVariableExpression(var: ![[DBG3:[0-9]+]], expr: !DIExpression(DW_OP_constu, 98, DW_OP_stack_value)) +; CHECK-DAG: ![[DBG3]] = distinct !
[clang-tools-extra] [IPSCCP] Variable not visible at Og: (PR #66745)
@@ -371,6 +372,52 @@ static bool runIPSCCP( StoreInst *SI = cast(GV->user_back()); SI->eraseFromParent(); } + +// Try to create a debug constant expression for the glbal variable +// initializer value. CarlosAlbertoEnciso wrote: Moving the code to a helper function. https://github.com/llvm/llvm-project/pull/66745 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [IPSCCP] Variable not visible at Og: (PR #66745)
@@ -371,6 +372,52 @@ static bool runIPSCCP( StoreInst *SI = cast(GV->user_back()); SI->eraseFromParent(); } + +// Try to create a debug constant expression for the glbal variable +// initializer value. CarlosAlbertoEnciso wrote: Moving the code to a helper function. https://github.com/llvm/llvm-project/pull/66745 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [IPSCCP] Variable not visible at Og: (PR #66745)
@@ -371,6 +372,52 @@ static bool runIPSCCP( StoreInst *SI = cast(GV->user_back()); SI->eraseFromParent(); } + +// Try to create a debug constant expression for the glbal variable +// initializer value. +SmallVector GVEs; +GV->getDebugInfo(GVEs); +if (GVEs.size() == 1) { + DIBuilder DIB(M); + + // Create integer constant expression. + auto createIntExpression = [&DIB](const Constant *CV) -> DIExpression * { +const APInt &API = dyn_cast(CV)->getValue(); +std::optional InitIntOpt; +if (API.isNonNegative()) + InitIntOpt = API.tryZExtValue(); +else if (auto Temp = API.trySExtValue(); Temp.has_value()) + // Transform a signed optional to unsigned optional. + InitIntOpt = (uint64_t)Temp.value(); CarlosAlbertoEnciso wrote: Using instead `static_cast` https://github.com/llvm/llvm-project/pull/66745 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [IPSCCP] Variable not visible at Og: (PR #66745)
@@ -371,6 +372,52 @@ static bool runIPSCCP( StoreInst *SI = cast(GV->user_back()); SI->eraseFromParent(); } + +// Try to create a debug constant expression for the glbal variable +// initializer value. +SmallVector GVEs; +GV->getDebugInfo(GVEs); +if (GVEs.size() == 1) { + DIBuilder DIB(M); + + // Create integer constant expression. + auto createIntExpression = [&DIB](const Constant *CV) -> DIExpression * { +const APInt &API = dyn_cast(CV)->getValue(); +std::optional InitIntOpt; +if (API.isNonNegative()) + InitIntOpt = API.tryZExtValue(); +else if (auto Temp = API.trySExtValue(); Temp.has_value()) + // Transform a signed optional to unsigned optional. + InitIntOpt = (uint64_t)Temp.value(); CarlosAlbertoEnciso wrote: Using instead `static_cast` https://github.com/llvm/llvm-project/pull/66745 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [IPSCCP] Variable not visible at Og: (PR #66745)
@@ -371,6 +372,52 @@ static bool runIPSCCP( StoreInst *SI = cast(GV->user_back()); SI->eraseFromParent(); } + +// Try to create a debug constant expression for the glbal variable +// initializer value. +SmallVector GVEs; +GV->getDebugInfo(GVEs); +if (GVEs.size() == 1) { + DIBuilder DIB(M); + + // Create integer constant expression. + auto createIntExpression = [&DIB](const Constant *CV) -> DIExpression * { +const APInt &API = dyn_cast(CV)->getValue(); +std::optional InitIntOpt; +if (API.isNonNegative()) + InitIntOpt = API.tryZExtValue(); +else if (auto Temp = API.trySExtValue(); Temp.has_value()) + // Transform a signed optional to unsigned optional. + InitIntOpt = (uint64_t)Temp.value(); +return DIB.createConstantValueExpression(InitIntOpt.value()); CarlosAlbertoEnciso wrote: Changed to use `cast`. https://github.com/llvm/llvm-project/pull/66745 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [IPSCCP] Variable not visible at Og: (PR #66745)
@@ -371,6 +372,52 @@ static bool runIPSCCP( StoreInst *SI = cast(GV->user_back()); SI->eraseFromParent(); } + +// Try to create a debug constant expression for the glbal variable +// initializer value. +SmallVector GVEs; +GV->getDebugInfo(GVEs); +if (GVEs.size() == 1) { + DIBuilder DIB(M); + + // Create integer constant expression. + auto createIntExpression = [&DIB](const Constant *CV) -> DIExpression * { +const APInt &API = dyn_cast(CV)->getValue(); +std::optional InitIntOpt; +if (API.isNonNegative()) + InitIntOpt = API.tryZExtValue(); +else if (auto Temp = API.trySExtValue(); Temp.has_value()) + // Transform a signed optional to unsigned optional. + InitIntOpt = (uint64_t)Temp.value(); +return DIB.createConstantValueExpression(InitIntOpt.value()); CarlosAlbertoEnciso wrote: Changed to use `cast`. https://github.com/llvm/llvm-project/pull/66745 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [IPSCCP] Variable not visible at Og: (PR #66745)
@@ -371,6 +372,52 @@ static bool runIPSCCP( StoreInst *SI = cast(GV->user_back()); SI->eraseFromParent(); } + +// Try to create a debug constant expression for the glbal variable +// initializer value. +SmallVector GVEs; +GV->getDebugInfo(GVEs); +if (GVEs.size() == 1) { + DIBuilder DIB(M); + + // Create integer constant expression. + auto createIntExpression = [&DIB](const Constant *CV) -> DIExpression * { +const APInt &API = dyn_cast(CV)->getValue(); +std::optional InitIntOpt; +if (API.isNonNegative()) + InitIntOpt = API.tryZExtValue(); +else if (auto Temp = API.trySExtValue(); Temp.has_value()) + // Transform a signed optional to unsigned optional. + InitIntOpt = (uint64_t)Temp.value(); +return DIB.createConstantValueExpression(InitIntOpt.value()); + }; + + const Constant *CV = GV->getInitializer(); + Type *Ty = GV->getValueType(); + if (Ty->isIntegerTy()) { +GVEs[0]->replaceOperandWith(1, createIntExpression(CV)); CarlosAlbertoEnciso wrote: The function `replaceOperandWith` takes that into consideration. https://github.com/llvm/llvm-project/pull/66745 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [IPSCCP] Variable not visible at Og: (PR #66745)
@@ -371,6 +372,52 @@ static bool runIPSCCP( StoreInst *SI = cast(GV->user_back()); SI->eraseFromParent(); } + +// Try to create a debug constant expression for the glbal variable +// initializer value. +SmallVector GVEs; +GV->getDebugInfo(GVEs); +if (GVEs.size() == 1) { + DIBuilder DIB(M); + + // Create integer constant expression. + auto createIntExpression = [&DIB](const Constant *CV) -> DIExpression * { +const APInt &API = dyn_cast(CV)->getValue(); +std::optional InitIntOpt; +if (API.isNonNegative()) + InitIntOpt = API.tryZExtValue(); +else if (auto Temp = API.trySExtValue(); Temp.has_value()) + // Transform a signed optional to unsigned optional. + InitIntOpt = (uint64_t)Temp.value(); +return DIB.createConstantValueExpression(InitIntOpt.value()); + }; + + const Constant *CV = GV->getInitializer(); + Type *Ty = GV->getValueType(); + if (Ty->isIntegerTy()) { +GVEs[0]->replaceOperandWith(1, createIntExpression(CV)); CarlosAlbertoEnciso wrote: The function `replaceOperandWith` takes that into consideration. https://github.com/llvm/llvm-project/pull/66745 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [IPSCCP] Variable not visible at Og: (PR #66745)
@@ -371,6 +372,52 @@ static bool runIPSCCP( StoreInst *SI = cast(GV->user_back()); SI->eraseFromParent(); } + +// Try to create a debug constant expression for the glbal variable +// initializer value. +SmallVector GVEs; +GV->getDebugInfo(GVEs); +if (GVEs.size() == 1) { + DIBuilder DIB(M); + + // Create integer constant expression. + auto createIntExpression = [&DIB](const Constant *CV) -> DIExpression * { +const APInt &API = dyn_cast(CV)->getValue(); +std::optional InitIntOpt; +if (API.isNonNegative()) + InitIntOpt = API.tryZExtValue(); +else if (auto Temp = API.trySExtValue(); Temp.has_value()) + // Transform a signed optional to unsigned optional. + InitIntOpt = (uint64_t)Temp.value(); +return DIB.createConstantValueExpression(InitIntOpt.value()); + }; + + const Constant *CV = GV->getInitializer(); + Type *Ty = GV->getValueType(); + if (Ty->isIntegerTy()) { +GVEs[0]->replaceOperandWith(1, createIntExpression(CV)); + } else if (Ty->isFloatTy() || Ty->isDoubleTy()) { +const APFloat &APF = dyn_cast(CV)->getValueAPF(); CarlosAlbertoEnciso wrote: Changed to `cast` https://github.com/llvm/llvm-project/pull/66745 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [IPSCCP] Variable not visible at Og: (PR #66745)
@@ -371,6 +372,52 @@ static bool runIPSCCP( StoreInst *SI = cast(GV->user_back()); SI->eraseFromParent(); } + +// Try to create a debug constant expression for the glbal variable +// initializer value. +SmallVector GVEs; +GV->getDebugInfo(GVEs); +if (GVEs.size() == 1) { + DIBuilder DIB(M); + + // Create integer constant expression. + auto createIntExpression = [&DIB](const Constant *CV) -> DIExpression * { +const APInt &API = dyn_cast(CV)->getValue(); +std::optional InitIntOpt; +if (API.isNonNegative()) + InitIntOpt = API.tryZExtValue(); +else if (auto Temp = API.trySExtValue(); Temp.has_value()) + // Transform a signed optional to unsigned optional. + InitIntOpt = (uint64_t)Temp.value(); +return DIB.createConstantValueExpression(InitIntOpt.value()); + }; + + const Constant *CV = GV->getInitializer(); + Type *Ty = GV->getValueType(); + if (Ty->isIntegerTy()) { +GVEs[0]->replaceOperandWith(1, createIntExpression(CV)); + } else if (Ty->isFloatTy() || Ty->isDoubleTy()) { +const APFloat &APF = dyn_cast(CV)->getValueAPF(); CarlosAlbertoEnciso wrote: Changed to `cast` https://github.com/llvm/llvm-project/pull/66745 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [IPSCCP] Variable not visible at Og: (PR #66745)
@@ -371,6 +372,52 @@ static bool runIPSCCP( StoreInst *SI = cast(GV->user_back()); SI->eraseFromParent(); } + +// Try to create a debug constant expression for the glbal variable +// initializer value. +SmallVector GVEs; +GV->getDebugInfo(GVEs); +if (GVEs.size() == 1) { + DIBuilder DIB(M); + + // Create integer constant expression. + auto createIntExpression = [&DIB](const Constant *CV) -> DIExpression * { +const APInt &API = dyn_cast(CV)->getValue(); +std::optional InitIntOpt; +if (API.isNonNegative()) + InitIntOpt = API.tryZExtValue(); +else if (auto Temp = API.trySExtValue(); Temp.has_value()) + // Transform a signed optional to unsigned optional. + InitIntOpt = (uint64_t)Temp.value(); +return DIB.createConstantValueExpression(InitIntOpt.value()); + }; + + const Constant *CV = GV->getInitializer(); + Type *Ty = GV->getValueType(); + if (Ty->isIntegerTy()) { +GVEs[0]->replaceOperandWith(1, createIntExpression(CV)); + } else if (Ty->isFloatTy() || Ty->isDoubleTy()) { +const APFloat &APF = dyn_cast(CV)->getValueAPF(); +DIExpression *NewExpr = DIB.createConstantValueExpression( +APF.bitcastToAPInt().getZExtValue()); +GVEs[0]->replaceOperandWith(1, NewExpr); + } else if (Ty->isPointerTy()) { +if (isa(CV)) { + GVEs[0]->replaceOperandWith(1, DIB.createConstantValueExpression(0)); +} else { + if (const ConstantExpr *CE = dyn_cast(CV)) { +if (CE->getNumOperands() == 1) { + const Value *V = CE->getOperand(0); + const Constant *CV = dyn_cast(V); + if (CV && !isa(CV)) +if (const ConstantInt *CI = dyn_cast(CV)) + GVEs[0]->replaceOperandWith(1, createIntExpression(CI)); +} + } +} + } +} CarlosAlbertoEnciso wrote: Replaced with your suggested change. https://github.com/llvm/llvm-project/pull/66745 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [IPSCCP] Variable not visible at Og: (PR #66745)
@@ -371,6 +372,52 @@ static bool runIPSCCP( StoreInst *SI = cast(GV->user_back()); SI->eraseFromParent(); } + +// Try to create a debug constant expression for the glbal variable +// initializer value. +SmallVector GVEs; +GV->getDebugInfo(GVEs); +if (GVEs.size() == 1) { + DIBuilder DIB(M); + + // Create integer constant expression. + auto createIntExpression = [&DIB](const Constant *CV) -> DIExpression * { +const APInt &API = dyn_cast(CV)->getValue(); +std::optional InitIntOpt; +if (API.isNonNegative()) + InitIntOpt = API.tryZExtValue(); +else if (auto Temp = API.trySExtValue(); Temp.has_value()) + // Transform a signed optional to unsigned optional. + InitIntOpt = (uint64_t)Temp.value(); +return DIB.createConstantValueExpression(InitIntOpt.value()); + }; + + const Constant *CV = GV->getInitializer(); + Type *Ty = GV->getValueType(); + if (Ty->isIntegerTy()) { +GVEs[0]->replaceOperandWith(1, createIntExpression(CV)); + } else if (Ty->isFloatTy() || Ty->isDoubleTy()) { +const APFloat &APF = dyn_cast(CV)->getValueAPF(); +DIExpression *NewExpr = DIB.createConstantValueExpression( +APF.bitcastToAPInt().getZExtValue()); +GVEs[0]->replaceOperandWith(1, NewExpr); + } else if (Ty->isPointerTy()) { +if (isa(CV)) { + GVEs[0]->replaceOperandWith(1, DIB.createConstantValueExpression(0)); +} else { + if (const ConstantExpr *CE = dyn_cast(CV)) { +if (CE->getNumOperands() == 1) { + const Value *V = CE->getOperand(0); + const Constant *CV = dyn_cast(V); + if (CV && !isa(CV)) +if (const ConstantInt *CI = dyn_cast(CV)) + GVEs[0]->replaceOperandWith(1, createIntExpression(CI)); +} + } +} + } +} CarlosAlbertoEnciso wrote: Replaced with your suggested change. https://github.com/llvm/llvm-project/pull/66745 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [IPSCCP] Variable not visible at Og: (PR #66745)
https://github.com/CarlosAlbertoEnciso updated https://github.com/llvm/llvm-project/pull/66745 >From b24943f63025822a5c5ba90c4a7b47f7123ec4db Mon Sep 17 00:00:00 2001 From: Carlos Alberto Enciso Date: Mon, 18 Sep 2023 12:29:17 +0100 Subject: [PATCH 1/4] [IPSCCP] Variable not visible at Og: https://bugs.llvm.org/show_bug.cgi?id=51559 https://github.com/llvm/llvm-project/issues/50901 IPSCCP pass removes the global variable and does not create a constant expression for the initializer value. --- llvm/lib/Transforms/IPO/SCCP.cpp | 47 +++ llvm/test/Transforms/SCCP/pr50901.ll | 184 +++ 2 files changed, 231 insertions(+) create mode 100644 llvm/test/Transforms/SCCP/pr50901.ll diff --git a/llvm/lib/Transforms/IPO/SCCP.cpp b/llvm/lib/Transforms/IPO/SCCP.cpp index 84f5bbf7039416b..e09769e00148143 100644 --- a/llvm/lib/Transforms/IPO/SCCP.cpp +++ b/llvm/lib/Transforms/IPO/SCCP.cpp @@ -22,6 +22,7 @@ #include "llvm/Analysis/ValueTracking.h" #include "llvm/IR/AttributeMask.h" #include "llvm/IR/Constants.h" +#include "llvm/IR/DIBuilder.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/ModRef.h" @@ -371,6 +372,52 @@ static bool runIPSCCP( StoreInst *SI = cast(GV->user_back()); SI->eraseFromParent(); } + +// Try to create a debug constant expression for the glbal variable +// initializer value. +SmallVector GVEs; +GV->getDebugInfo(GVEs); +if (GVEs.size() == 1) { + DIBuilder DIB(M); + + // Create integer constant expression. + auto createIntExpression = [&DIB](const Constant *CV) -> DIExpression * { +const APInt &API = dyn_cast(CV)->getValue(); +std::optional InitIntOpt; +if (API.isNonNegative()) + InitIntOpt = API.tryZExtValue(); +else if (auto Temp = API.trySExtValue(); Temp.has_value()) + // Transform a signed optional to unsigned optional. + InitIntOpt = (uint64_t)Temp.value(); +return DIB.createConstantValueExpression(InitIntOpt.value()); + }; + + const Constant *CV = GV->getInitializer(); + Type *Ty = GV->getValueType(); + if (Ty->isIntegerTy()) { +GVEs[0]->replaceOperandWith(1, createIntExpression(CV)); + } else if (Ty->isFloatTy() || Ty->isDoubleTy()) { +const APFloat &APF = dyn_cast(CV)->getValueAPF(); +DIExpression *NewExpr = DIB.createConstantValueExpression( +APF.bitcastToAPInt().getZExtValue()); +GVEs[0]->replaceOperandWith(1, NewExpr); + } else if (Ty->isPointerTy()) { +if (isa(CV)) { + GVEs[0]->replaceOperandWith(1, DIB.createConstantValueExpression(0)); +} else { + if (const ConstantExpr *CE = dyn_cast(CV)) { +if (CE->getNumOperands() == 1) { + const Value *V = CE->getOperand(0); + const Constant *CV = dyn_cast(V); + if (CV && !isa(CV)) +if (const ConstantInt *CI = dyn_cast(CV)) + GVEs[0]->replaceOperandWith(1, createIntExpression(CI)); +} + } +} + } +} + MadeChanges = true; M.eraseGlobalVariable(GV); ++NumGlobalConst; diff --git a/llvm/test/Transforms/SCCP/pr50901.ll b/llvm/test/Transforms/SCCP/pr50901.ll new file mode 100644 index 000..56961d2e32db41c --- /dev/null +++ b/llvm/test/Transforms/SCCP/pr50901.ll @@ -0,0 +1,184 @@ +; RUN: opt -passes=ipsccp -S -o - < %s | FileCheck %s + +; Global variables g_11, g_22, g_33, g_44, g_55, g_66 and g_77 +; are not visible in the debugger. + +; 1 int g_1 = -4; +; 2 float g_2 = 4.44; +; 3 char g_3 = 'a'; +; 4 unsigned g_4 = 4; +; 5 bool g_5 = true; +; 6 int *g_6 = nullptr; +; 7 float*g_7 = nullptr; +; 8 +; 9 static int g_11 = -5; +; 10 static float g_22 = 5.55; +; 11 static char g_33 = 'b'; +; 12 static unsigned g_44 = 5; +; 13 static bool g_55 = true; +; 14 static int *g_66 = nullptr; +; 15 static float*g_77 = (float *)(55 + 15); +; 16 +; 17 void bar() { +; 18 g_1 = g_11; +; 19 g_2 = g_22; +; 20 g_3 = g_33; +; 21 g_4 = g_44; +; 22 g_5 = g_55; +; 23 g_6 = g_66; +; 24 g_7 = g_77; +; 25 } +; 26 +; 27 int main() { +; 28 { +; 29 bar(); +; 30 } +; 31 } + +; CHECK: ![[G1:[0-9]+]] = !DIGlobalVariableExpression(var: ![[DBG1:[0-9]+]], expr: !DIExpression(DW_OP_constu, 18446744073709551611, DW_OP_stack_value)) +; CHECK-DAG: ![[DBG1]] = distinct !DIGlobalVariable(name: "g_11", {{.*}} +; CHECK: ![[G2:[0-9]+]] = !DIGlobalVariableExpression(var: ![[DBG2:[0-9]+]], expr: !DIExpression(DW_OP_constu, 1085381018, DW_OP_stack_value)) +; CHECK-DAG: ![[DBG2]] = distinct !DIGlobalVariable(name: "g_22", {{.*}} +; CHECK: ![[G3:[0-9]+]] = !DIGlobalVariableExpression(var: ![[DBG3:[0-9]+]], expr: !DIExpression(DW_OP_constu, 98, DW_OP_stack_value)) +; CHECK-DAG: ![[DBG3]] = distin
[clang-tools-extra] [IPSCCP] Variable not visible at Og: (PR #66745)
CarlosAlbertoEnciso wrote: @jryans, @felipepiovezan, @nikic, @dwblaikie: Thanks for all your feedback. I have uploaded a new patch that addresses all your points. I am sorry if there are extra commits on this branch. This is the first update since moving to GitHub. https://github.com/llvm/llvm-project/pull/66745 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [IPSCCP] Variable not visible at Og. (PR #66745)
https://github.com/CarlosAlbertoEnciso edited https://github.com/llvm/llvm-project/pull/66745 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[libunwind] [IPSCCP] Variable not visible at Og. (PR #66745)
https://github.com/CarlosAlbertoEnciso updated https://github.com/llvm/llvm-project/pull/66745 >From b24943f63025822a5c5ba90c4a7b47f7123ec4db Mon Sep 17 00:00:00 2001 From: Carlos Alberto Enciso Date: Mon, 18 Sep 2023 12:29:17 +0100 Subject: [PATCH 1/4] [IPSCCP] Variable not visible at Og: https://bugs.llvm.org/show_bug.cgi?id=51559 https://github.com/llvm/llvm-project/issues/50901 IPSCCP pass removes the global variable and does not create a constant expression for the initializer value. --- llvm/lib/Transforms/IPO/SCCP.cpp | 47 +++ llvm/test/Transforms/SCCP/pr50901.ll | 184 +++ 2 files changed, 231 insertions(+) create mode 100644 llvm/test/Transforms/SCCP/pr50901.ll diff --git a/llvm/lib/Transforms/IPO/SCCP.cpp b/llvm/lib/Transforms/IPO/SCCP.cpp index 84f5bbf7039416b..e09769e00148143 100644 --- a/llvm/lib/Transforms/IPO/SCCP.cpp +++ b/llvm/lib/Transforms/IPO/SCCP.cpp @@ -22,6 +22,7 @@ #include "llvm/Analysis/ValueTracking.h" #include "llvm/IR/AttributeMask.h" #include "llvm/IR/Constants.h" +#include "llvm/IR/DIBuilder.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/ModRef.h" @@ -371,6 +372,52 @@ static bool runIPSCCP( StoreInst *SI = cast(GV->user_back()); SI->eraseFromParent(); } + +// Try to create a debug constant expression for the glbal variable +// initializer value. +SmallVector GVEs; +GV->getDebugInfo(GVEs); +if (GVEs.size() == 1) { + DIBuilder DIB(M); + + // Create integer constant expression. + auto createIntExpression = [&DIB](const Constant *CV) -> DIExpression * { +const APInt &API = dyn_cast(CV)->getValue(); +std::optional InitIntOpt; +if (API.isNonNegative()) + InitIntOpt = API.tryZExtValue(); +else if (auto Temp = API.trySExtValue(); Temp.has_value()) + // Transform a signed optional to unsigned optional. + InitIntOpt = (uint64_t)Temp.value(); +return DIB.createConstantValueExpression(InitIntOpt.value()); + }; + + const Constant *CV = GV->getInitializer(); + Type *Ty = GV->getValueType(); + if (Ty->isIntegerTy()) { +GVEs[0]->replaceOperandWith(1, createIntExpression(CV)); + } else if (Ty->isFloatTy() || Ty->isDoubleTy()) { +const APFloat &APF = dyn_cast(CV)->getValueAPF(); +DIExpression *NewExpr = DIB.createConstantValueExpression( +APF.bitcastToAPInt().getZExtValue()); +GVEs[0]->replaceOperandWith(1, NewExpr); + } else if (Ty->isPointerTy()) { +if (isa(CV)) { + GVEs[0]->replaceOperandWith(1, DIB.createConstantValueExpression(0)); +} else { + if (const ConstantExpr *CE = dyn_cast(CV)) { +if (CE->getNumOperands() == 1) { + const Value *V = CE->getOperand(0); + const Constant *CV = dyn_cast(V); + if (CV && !isa(CV)) +if (const ConstantInt *CI = dyn_cast(CV)) + GVEs[0]->replaceOperandWith(1, createIntExpression(CI)); +} + } +} + } +} + MadeChanges = true; M.eraseGlobalVariable(GV); ++NumGlobalConst; diff --git a/llvm/test/Transforms/SCCP/pr50901.ll b/llvm/test/Transforms/SCCP/pr50901.ll new file mode 100644 index 000..56961d2e32db41c --- /dev/null +++ b/llvm/test/Transforms/SCCP/pr50901.ll @@ -0,0 +1,184 @@ +; RUN: opt -passes=ipsccp -S -o - < %s | FileCheck %s + +; Global variables g_11, g_22, g_33, g_44, g_55, g_66 and g_77 +; are not visible in the debugger. + +; 1 int g_1 = -4; +; 2 float g_2 = 4.44; +; 3 char g_3 = 'a'; +; 4 unsigned g_4 = 4; +; 5 bool g_5 = true; +; 6 int *g_6 = nullptr; +; 7 float*g_7 = nullptr; +; 8 +; 9 static int g_11 = -5; +; 10 static float g_22 = 5.55; +; 11 static char g_33 = 'b'; +; 12 static unsigned g_44 = 5; +; 13 static bool g_55 = true; +; 14 static int *g_66 = nullptr; +; 15 static float*g_77 = (float *)(55 + 15); +; 16 +; 17 void bar() { +; 18 g_1 = g_11; +; 19 g_2 = g_22; +; 20 g_3 = g_33; +; 21 g_4 = g_44; +; 22 g_5 = g_55; +; 23 g_6 = g_66; +; 24 g_7 = g_77; +; 25 } +; 26 +; 27 int main() { +; 28 { +; 29 bar(); +; 30 } +; 31 } + +; CHECK: ![[G1:[0-9]+]] = !DIGlobalVariableExpression(var: ![[DBG1:[0-9]+]], expr: !DIExpression(DW_OP_constu, 18446744073709551611, DW_OP_stack_value)) +; CHECK-DAG: ![[DBG1]] = distinct !DIGlobalVariable(name: "g_11", {{.*}} +; CHECK: ![[G2:[0-9]+]] = !DIGlobalVariableExpression(var: ![[DBG2:[0-9]+]], expr: !DIExpression(DW_OP_constu, 1085381018, DW_OP_stack_value)) +; CHECK-DAG: ![[DBG2]] = distinct !DIGlobalVariable(name: "g_22", {{.*}} +; CHECK: ![[G3:[0-9]+]] = !DIGlobalVariableExpression(var: ![[DBG3:[0-9]+]], expr: !DIExpression(DW_OP_constu, 98, DW_OP_stack_value)) +; CHECK-DAG: ![[DBG3]] = distin
[clang] [IPSCCP] Variable not visible at Og. (PR #66745)
https://github.com/CarlosAlbertoEnciso updated https://github.com/llvm/llvm-project/pull/66745 >From b24943f63025822a5c5ba90c4a7b47f7123ec4db Mon Sep 17 00:00:00 2001 From: Carlos Alberto Enciso Date: Mon, 18 Sep 2023 12:29:17 +0100 Subject: [PATCH 1/4] [IPSCCP] Variable not visible at Og: https://bugs.llvm.org/show_bug.cgi?id=51559 https://github.com/llvm/llvm-project/issues/50901 IPSCCP pass removes the global variable and does not create a constant expression for the initializer value. --- llvm/lib/Transforms/IPO/SCCP.cpp | 47 +++ llvm/test/Transforms/SCCP/pr50901.ll | 184 +++ 2 files changed, 231 insertions(+) create mode 100644 llvm/test/Transforms/SCCP/pr50901.ll diff --git a/llvm/lib/Transforms/IPO/SCCP.cpp b/llvm/lib/Transforms/IPO/SCCP.cpp index 84f5bbf7039416b..e09769e00148143 100644 --- a/llvm/lib/Transforms/IPO/SCCP.cpp +++ b/llvm/lib/Transforms/IPO/SCCP.cpp @@ -22,6 +22,7 @@ #include "llvm/Analysis/ValueTracking.h" #include "llvm/IR/AttributeMask.h" #include "llvm/IR/Constants.h" +#include "llvm/IR/DIBuilder.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/ModRef.h" @@ -371,6 +372,52 @@ static bool runIPSCCP( StoreInst *SI = cast(GV->user_back()); SI->eraseFromParent(); } + +// Try to create a debug constant expression for the glbal variable +// initializer value. +SmallVector GVEs; +GV->getDebugInfo(GVEs); +if (GVEs.size() == 1) { + DIBuilder DIB(M); + + // Create integer constant expression. + auto createIntExpression = [&DIB](const Constant *CV) -> DIExpression * { +const APInt &API = dyn_cast(CV)->getValue(); +std::optional InitIntOpt; +if (API.isNonNegative()) + InitIntOpt = API.tryZExtValue(); +else if (auto Temp = API.trySExtValue(); Temp.has_value()) + // Transform a signed optional to unsigned optional. + InitIntOpt = (uint64_t)Temp.value(); +return DIB.createConstantValueExpression(InitIntOpt.value()); + }; + + const Constant *CV = GV->getInitializer(); + Type *Ty = GV->getValueType(); + if (Ty->isIntegerTy()) { +GVEs[0]->replaceOperandWith(1, createIntExpression(CV)); + } else if (Ty->isFloatTy() || Ty->isDoubleTy()) { +const APFloat &APF = dyn_cast(CV)->getValueAPF(); +DIExpression *NewExpr = DIB.createConstantValueExpression( +APF.bitcastToAPInt().getZExtValue()); +GVEs[0]->replaceOperandWith(1, NewExpr); + } else if (Ty->isPointerTy()) { +if (isa(CV)) { + GVEs[0]->replaceOperandWith(1, DIB.createConstantValueExpression(0)); +} else { + if (const ConstantExpr *CE = dyn_cast(CV)) { +if (CE->getNumOperands() == 1) { + const Value *V = CE->getOperand(0); + const Constant *CV = dyn_cast(V); + if (CV && !isa(CV)) +if (const ConstantInt *CI = dyn_cast(CV)) + GVEs[0]->replaceOperandWith(1, createIntExpression(CI)); +} + } +} + } +} + MadeChanges = true; M.eraseGlobalVariable(GV); ++NumGlobalConst; diff --git a/llvm/test/Transforms/SCCP/pr50901.ll b/llvm/test/Transforms/SCCP/pr50901.ll new file mode 100644 index 000..56961d2e32db41c --- /dev/null +++ b/llvm/test/Transforms/SCCP/pr50901.ll @@ -0,0 +1,184 @@ +; RUN: opt -passes=ipsccp -S -o - < %s | FileCheck %s + +; Global variables g_11, g_22, g_33, g_44, g_55, g_66 and g_77 +; are not visible in the debugger. + +; 1 int g_1 = -4; +; 2 float g_2 = 4.44; +; 3 char g_3 = 'a'; +; 4 unsigned g_4 = 4; +; 5 bool g_5 = true; +; 6 int *g_6 = nullptr; +; 7 float*g_7 = nullptr; +; 8 +; 9 static int g_11 = -5; +; 10 static float g_22 = 5.55; +; 11 static char g_33 = 'b'; +; 12 static unsigned g_44 = 5; +; 13 static bool g_55 = true; +; 14 static int *g_66 = nullptr; +; 15 static float*g_77 = (float *)(55 + 15); +; 16 +; 17 void bar() { +; 18 g_1 = g_11; +; 19 g_2 = g_22; +; 20 g_3 = g_33; +; 21 g_4 = g_44; +; 22 g_5 = g_55; +; 23 g_6 = g_66; +; 24 g_7 = g_77; +; 25 } +; 26 +; 27 int main() { +; 28 { +; 29 bar(); +; 30 } +; 31 } + +; CHECK: ![[G1:[0-9]+]] = !DIGlobalVariableExpression(var: ![[DBG1:[0-9]+]], expr: !DIExpression(DW_OP_constu, 18446744073709551611, DW_OP_stack_value)) +; CHECK-DAG: ![[DBG1]] = distinct !DIGlobalVariable(name: "g_11", {{.*}} +; CHECK: ![[G2:[0-9]+]] = !DIGlobalVariableExpression(var: ![[DBG2:[0-9]+]], expr: !DIExpression(DW_OP_constu, 1085381018, DW_OP_stack_value)) +; CHECK-DAG: ![[DBG2]] = distinct !DIGlobalVariable(name: "g_22", {{.*}} +; CHECK: ![[G3:[0-9]+]] = !DIGlobalVariableExpression(var: ![[DBG3:[0-9]+]], expr: !DIExpression(DW_OP_constu, 98, DW_OP_stack_value)) +; CHECK-DAG: ![[DBG3]] = distin
[clang] 0ba922f - Revert "Reapply D146987 "[Assignment Tracking] Enable by default""
Author: Carlos Alberto Enciso Date: 2023-04-21T09:11:40+01:00 New Revision: 0ba922f600469df273c753f873668e41025487c0 URL: https://github.com/llvm/llvm-project/commit/0ba922f600469df273c753f873668e41025487c0 DIFF: https://github.com/llvm/llvm-project/commit/0ba922f600469df273c753f873668e41025487c0.diff LOG: Revert "Reapply D146987 "[Assignment Tracking] Enable by default"" This reverts commit b74aeaccbae876ca348aa87a3db05d444052ae65. Note: The author (Orlando) asked to revert this commit. Added: Modified: clang/include/clang/Driver/Options.td clang/test/CodeGen/assignment-tracking/flag.cpp Removed: diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 604b4a45fffc1..eed0d517a1ad7 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -5817,7 +5817,7 @@ def fexperimental_assignment_tracking_EQ : Joined<["-"], "fexperimental-assignme Group, CodeGenOpts<"EnableAssignmentTracking">, NormalizedValuesScope<"CodeGenOptions::AssignmentTrackingOpts">, Values<"disabled,enabled,forced">, NormalizedValues<["Disabled","Enabled","Forced"]>, - MarshallingInfoEnum, "Enabled">; + MarshallingInfoEnum, "Disabled">; } // let Flags = [CC1Option, NoDriverOption] diff --git a/clang/test/CodeGen/assignment-tracking/flag.cpp b/clang/test/CodeGen/assignment-tracking/flag.cpp index 3bd974fe07c6c..aa1f054dae4d7 100644 --- a/clang/test/CodeGen/assignment-tracking/flag.cpp +++ b/clang/test/CodeGen/assignment-tracking/flag.cpp @@ -8,10 +8,10 @@ // RUN: -emit-llvm %s -o - -fexperimental-assignment-tracking=disabled -O1\ // RUN: | FileCheck %s --check-prefixes=DISABLE - Enabled by default: + Disabled by default: // RUN: %clang_cc1 -triple x86_64-none-linux-gnu -debug-info-kind=standalone \ // RUN: -emit-llvm %s -o - -O1 \ -// RUN: | FileCheck %s --check-prefixes=ENABLE +// RUN: | FileCheck %s --check-prefixes=DISABLE Disabled at O0 unless forced. // RUN: %clang_cc1 -triple x86_64-none-linux-gnu -debug-info-kind=standalone \ ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Extend EmitPseudoVariable to support debug records (PR #94956)
@@ -5766,28 +5766,16 @@ void CGDebugInfo::EmitPseudoVariable(CGBuilderTy &Builder, // it is loaded upon use, so we identify such pattern here. if (llvm::LoadInst *Load = dyn_cast(Value)) { llvm::Value *Var = Load->getPointerOperand(); -if (llvm::Metadata *MDValue = llvm::ValueAsMetadata::getIfExists(Var)) { - if (llvm::Value *DbgValue = llvm::MetadataAsValue::getIfExists( - CGM.getLLVMContext(), MDValue)) { -for (llvm::User *U : DbgValue->users()) { - if (llvm::CallInst *DbgDeclare = dyn_cast(U)) { -if (DbgDeclare->getCalledFunction()->getIntrinsicID() == -llvm::Intrinsic::dbg_declare && -DbgDeclare->getArgOperand(0) == DbgValue) { - // There can be implicit type cast applied on a variable if it is - // an opaque ptr, in this case its debug info may not match the - // actual type of object being used as in the next instruction, so - // we will need to emit a pseudo variable for type-casted value. - llvm::DILocalVariable *MDNode = cast( - cast(DbgDeclare->getOperand(1)) - ->getMetadata()); - if (MDNode->getType() == Type) -return; -} - } -} - } -} +// There can be implicit type cast applied on a variable if it is an opaque +// ptr, in this case its debug info may not match the actual type of object +// being used as in the next instruction, so we will need to emit a pseudo +// variable for type-casted value. +auto DeclareTypeMatches = [&](auto *DbgDeclare) { + return DbgDeclare->getVariable()->getType() == Type; +}; +if (any_of(llvm::findDbgDeclares(Var), DeclareMatches) || CarlosAlbertoEnciso wrote: `DeclareMatches` or `DeclareTypeMatches`? https://github.com/llvm/llvm-project/pull/94956 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [clang][DebugInfo] Add symbol for debugger with VTable information. (PR #130255)
CarlosAlbertoEnciso wrote: As pointed out by @Michael137 > If we're given the `_vtable$` artificial member, there's nothing useful we > can do with it right? ``` 0x0042: DW_TAG_variable DW_AT_specification (0x005c "_vtable$") DW_AT_alignment (8) DW_AT_location (DW_OP_addrx 0x1) DW_AT_linkage_name ("_ZTV8CDerived") 0x004c: DW_TAG_structure_type ("CDerived") ... 0x005c: DW_TAG_variable DW_AT_name ("_vtable$") DW_AT_type (0x0041 "void *") DW_AT_external(true) DW_AT_declaration (true) DW_AT_artificial (true) DW_AT_accessibility (DW_ACCESS_private) DW_AT_containing_type <0x0042> --> VTable global variable ... .debug_addr contents: Addrs: [ 0x 0x <- DW_OP_addrx 0x1 0x ] ``` And taking a variation of what @tromey described, maybe we can add a `DW_AT_containing_type` pointing back to the global variable, providing 2 ways to use the new vtable information entry: - Given the `_vtable$` artificial member: use the `DW_AT_containing_type` to find the vtable global variable. - Given the vtable global variable: use the `DW_AT_specification` to find the object definition. https://github.com/llvm/llvm-project/pull/130255 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [clang][DebugInfo] Add symbol for debugger with VTable information. (PR #130255)
CarlosAlbertoEnciso wrote: > > Given the _vtable$ artificial member: use the DW_AT_containing_type to find > > the vtable global variable. > > It seems to me that this attribute should refer to a type and not a variable. Good point. Another option is to use `DW_AT_specification`. ``` 0x0042: DW_TAG_variable DW_AT_specification (0x005c "_vtable$") DW_AT_linkage_name ("_ZTV8CDerived") ... 0x004c: DW_TAG_structure_type ("CDerived") ... 0x005c: DW_TAG_variable DW_AT_name ("_vtable$") DW_AT_artificial (true) DW_AT_specification <0x0042> --> VTable global variable ... ``` But potentially consumers can go into a loop if they follow both `DW_AT_specification`, without having additional knowledge about the `artificial` DIE. ``` 0x0042: DW_TAG_variable DW_AT_linkage_name ("_ZTV8CDerived") ... 0x004c: DW_TAG_structure_type ("CDerived") ... 0x005c: DW_TAG_variable DW_AT_name ("_vtable$") DW_AT_artificial (true) DW_AT_specification <0x0042> --> VTable global variable ... ``` If we remove the first `DW_AT_specification`, we lost the ability to traverse the global variables (vtable's) and find their associated compound type. https://github.com/llvm/llvm-project/pull/130255 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [clang][DebugInfo] Add symbol for debugger with VTable information. (PR #130255)
CarlosAlbertoEnciso wrote: @clayborg Thanks very much for the extra information. > FYI: There is already VTable support in our lldb::SBValue class and it is > part of the public API in LLDB and doesn't require any of this: > > ``` > $ cat main.cpp >1 #include >2 >3 class Foo { >4 public: >5virtual ~Foo() = default; >6virtual void Dump() { >7 puts(__PRETTY_FUNCTION__); >8} >9 }; >10 >11 int main(int argc, const char **argv) { >12 Foo f; >13 f.Dump(); >14 return 0; >15 } > ``` > > Then when you debug: > > ``` > (lldb) script > Python Interactive Interpreter. To exit, type 'quit()', 'exit()' or Ctrl-D. > >>> v = lldb.frame.FindVariable('f') > >>> v.GetVTable() > vtable for Foo = 0x00014030 { > [0] = 0x00013ea4 a.out`Foo::~Foo() at main.cpp:5 > [1] = 0x00013ef4 a.out`Foo::~Foo() at main.cpp:5 > [2] = 0x00013e7c a.out`Foo::Dump() at main.cpp:6 > } > ``` > > Doesn't require any debug info. Just a question: Can that functionality be used before the object is constructed? https://github.com/llvm/llvm-project/pull/130255 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [clang][DebugInfo] Add symbol for debugger with VTable information. (PR #130255)
CarlosAlbertoEnciso wrote: > > To work out which class A this refers to would involve parsing the template > > parameter correctly and matching to the correct anonymous namespace. While > > this technically isn’t impossible > > Are you sure about that? Anonymous types are confined to a single CU > statically, but their values can definitely leak out at runtime. So if I'm > stopped in a random CU and I see am object whose dynamic type is `(anonymous > namespace)::X`, I don't see how one could determine which type (out of > possibly many) is that vtable referring to. @labath I will double check with our debugger team. https://github.com/llvm/llvm-project/pull/130255 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [clang][DebugInfo] Add symbol for debugger with VTable information. (PR #130255)
CarlosAlbertoEnciso wrote: > > > To work out which class A this refers to would involve parsing the > > > template parameter correctly and matching to the correct anonymous > > > namespace. While this technically isn’t impossible > > > > > > Are you sure about that? Anonymous types are confined to a single CU > > statically, but their values can definitely leak out at runtime. So if I'm > > stopped in a random CU and I see am object whose dynamic type is > > `(anonymous namespace)::X`, I don't see how one could determine which type > > (out of possibly many) is that vtable referring to. > > @labath I will double check with our debugger team. >From our debugger team: "You could in theory look at the ELF File symbol for the VTable symbol to work out which CU the anonymous namespace refers to, which is why we say it’s *technically* possible. You’d have to transfer that information to the debugger during loading though which we don’t currently do." https://github.com/llvm/llvm-project/pull/130255 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [clang][DebugInfo] Add symbol for debugger with VTable information. (PR #130255)
CarlosAlbertoEnciso wrote: > Though I haven't thought seriously about the representation - truly off the > cuff, take with a grain of salt, etc, the static member that is the vtable > seems sort of reasonable to me. > > Not sure why it'd be necessary to make that vtable global variable "global" > rather than static within the class? Is that for debug_names lookup? (I think > static members are still in the index, right?) If it's a class member you can > still do bidirectional lookup, right? IF you find the variable, you can find > its parent to see which class it applies to, and if you have the class you > can find the vtable variable inside it? We used the global variable approach to give the debugger (SCE) a similar mechanism to an existing one to identify symbols that represent vtables. I think using just the static member will work and have the additional benefit of smaller debug info. I will check with the debugger team. https://github.com/llvm/llvm-project/pull/130255 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [clang][DebugInfo] Add symbol for debugger with VTable information. (PR #130255)
CarlosAlbertoEnciso wrote: @dwblaikie: > Not sure why it'd be necessary to make that vtable global variable "global" > rather than static within the class? Is that for debug_names lookup? (I think > static members are still in the index, right?) If it's a class member you can > still do bidirectional lookup, right? IF you find the variable, you can find > its parent to see which class it applies to, and if you have the class you > can find the vtable variable inside it? ``` 0x004c: DW_TAG_structure_type ("CDerived") ... 0x005c: DW_TAG_variable DW_AT_name ("_vtable$") DW_AT_type (0x0041 "void *") DW_AT_external (true) DW_AT_artificial (true) DW_AT_accessibility (DW_ACCESS_private) DW_AT_location (DW_OP_addrx 0x1) ... .debug_addr contents: Addrs: [ 0x 0x <- DW_OP_addrx 0x1 0x ] ``` Removing the vtable global variable and moving the "location info" into the static within the class, will work for the SCE debugger. https://github.com/llvm/llvm-project/pull/130255 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [clang][DebugInfo] Add symbol for debugger with VTable information. (PR #130255)
@@ -2518,6 +2518,59 @@ StringRef CGDebugInfo::getVTableName(const CXXRecordDecl *RD) { return internString("_vptr$", RD->getNameAsString()); } +// Emit symbol for the debugger that points to the vtable address for +// the given class. The symbol is named as '_vtable$'. +// The debugger does not need to know any details about the contents of the +// vtable as it can work this out using its knowledge of the ABI and the +// existing information in the DWARF. The type is assumed to be 'void *'. +void CGDebugInfo::emitVTableSymbol(llvm::GlobalVariable *VTable, + const CXXRecordDecl *RD) { + ASTContext &Context = CGM.getContext(); + SmallString<64> Buffer; + Twine SymbolName = internString("_vtable$"); + StringRef SymbolNameRef = SymbolName.toStringRef(Buffer); + DeclContext *DC = static_cast(const_cast(RD)); + SourceLocation Loc; + QualType VoidPtr = Context.getPointerType(Context.VoidTy); + + // We deal with two different contexts: + // - The type for the variable, which is part of the class that has the + // vtable, is placed in the context of the DICompositeType metadata. + // - The DIGlobalVariable for the vtable is put in the DICompileUnitScope. + + // The created non-member should be mark as 'artificial'. It will be + // placed it inside the scope of the C++ class/structure. + llvm::DIScope *DContext = getContextDescriptor(cast(DC), TheCU); + auto *Ctxt = cast(DContext); + llvm::DIFile *Unit = getOrCreateFile(Loc); + llvm::DIType *VTy = getOrCreateType(VoidPtr, Unit); + llvm::DINode::DIFlags Flags = getAccessFlag(AccessSpecifier::AS_private, RD); + auto Tag = CGM.getCodeGenOpts().DwarfVersion >= 5 + ? llvm::dwarf::DW_TAG_variable + : llvm::dwarf::DW_TAG_member; + llvm::DIDerivedType *OldDT = DBuilder.createStaticMemberType( + Ctxt, SymbolNameRef, Unit, /*LineNumber=*/0, VTy, Flags, + /*Val=*/nullptr, Tag); + llvm::DIDerivedType *DT = + static_cast(DBuilder.createArtificialType(OldDT)); CarlosAlbertoEnciso wrote: Very good point. https://github.com/llvm/llvm-project/pull/130255 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [clang][DebugInfo] Add symbol for debugger with VTable information. (PR #130255)
@@ -2518,6 +2518,59 @@ StringRef CGDebugInfo::getVTableName(const CXXRecordDecl *RD) { return internString("_vptr$", RD->getNameAsString()); } +// Emit symbol for the debugger that points to the vtable address for +// the given class. The symbol is named as '_vtable$'. +// The debugger does not need to know any details about the contents of the +// vtable as it can work this out using its knowledge of the ABI and the +// existing information in the DWARF. The type is assumed to be 'void *'. +void CGDebugInfo::emitVTableSymbol(llvm::GlobalVariable *VTable, + const CXXRecordDecl *RD) { + ASTContext &Context = CGM.getContext(); + SmallString<64> Buffer; + Twine SymbolName = internString("_vtable$"); + StringRef SymbolNameRef = SymbolName.toStringRef(Buffer); CarlosAlbertoEnciso wrote: You are right. Changed to be local. https://github.com/llvm/llvm-project/pull/130255 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [clang][DebugInfo] Add symbol for debugger with VTable information. (PR #130255)
CarlosAlbertoEnciso wrote: @Michael137, @dwblaikie Thanks for your feedback. https://github.com/llvm/llvm-project/pull/130255 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [clang][DebugInfo] Add symbol for debugger with VTable information. (PR #130255)
CarlosAlbertoEnciso wrote: > What sort of features are you picturing building with this? > Automatic type promotion: when displaying an object through a base pointer the debugger wants to still be able to show the object’s state. https://github.com/llvm/llvm-project/pull/130255 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [clang][DebugInfo] Add symbol for debugger with VTable information. (PR #130255)
CarlosAlbertoEnciso wrote: > The DWARF currently provides access to the vtable location for /instances/ of > the class, so curious what the distinction/need is for doing this from the > class, without instances? > > > Previously, this had to be done by searching for ELF symbols with matching > > names; something that was time-consuming and error-prone in certain edge > > cases. > > (I can appreciate that, if we are at the point of searching the symbol table, > it's not a great one - but could you talk more about the edge > cases/error-prone situations?) The simplest example of an edge-case is classes with VTables inside functions. This is because the demangled name of the VTable’s ELF symbol (e.g., `vtable for Func()::ClassA` ) is not a searchable name in the global context (in the SCE debugger at least). You could argue that it should be, but it is further complicated by things like template parameters, function overloading, anonymous namespaces etc. Another example, the demangled ELF symbol: `vtable for int (anonymous namespace)::Func<((anonymous namespace)::E)0>(int)::A`. To work out which class `A` this refers to would involve parsing the template parameter correctly and matching to the correct anonymous namespace. While this technically isn’t impossible, it would involve the debugger keeping a lot of extra information around to disambiguate these rare cases, something we’re unlikely to be able to justify. Implementing such demangling-and-interpretation would be error-prone, and the whole point of DWARF is to present information in a structured manner, so making it easy to access + interpret is part of its purpose. https://github.com/llvm/llvm-project/pull/130255 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [clang][DebugInfo] Add symbol for debugger with VTable information. (PR #130255)
CarlosAlbertoEnciso wrote: > The DWARF currently provides access to the vtable location for /instances/ of > the class, so curious what the distinction/need is for doing this from the > class, without instances? > The need to be done for the class is to give the debugger extra information about the vtables during the debug information loading before any code is executed. We are using it to construct a map of `vtable pointer` => `Class definition` to enable the type promotion. https://github.com/llvm/llvm-project/pull/130255 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [clang][DebugInfo] Add symbol for debugger with VTable information. (PR #130255)
@@ -2518,6 +2518,59 @@ StringRef CGDebugInfo::getVTableName(const CXXRecordDecl *RD) { return internString("_vptr$", RD->getNameAsString()); } +// Emit symbol for the debugger that points to the vtable address for +// the given class. The symbol is named as '_vtable$'. +// The debugger does not need to know any details about the contents of the +// vtable as it can work this out using its knowledge of the ABI and the +// existing information in the DWARF. The type is assumed to be 'void *'. +void CGDebugInfo::emitVTableSymbol(llvm::GlobalVariable *VTable, + const CXXRecordDecl *RD) { + ASTContext &Context = CGM.getContext(); + SmallString<64> Buffer; + Twine SymbolName = internString("_vtable$"); + StringRef SymbolNameRef = SymbolName.toStringRef(Buffer); + DeclContext *DC = static_cast(const_cast(RD)); + SourceLocation Loc; + QualType VoidPtr = Context.getPointerType(Context.VoidTy); + + // We deal with two different contexts: + // - The type for the variable, which is part of the class that has the + // vtable, is placed in the context of the DICompositeType metadata. + // - The DIGlobalVariable for the vtable is put in the DICompileUnitScope. + + // The created non-member should be mark as 'artificial'. It will be + // placed it inside the scope of the C++ class/structure. + llvm::DIScope *DContext = getContextDescriptor(cast(DC), TheCU); + auto *Ctxt = cast(DContext); + llvm::DIFile *Unit = getOrCreateFile(Loc); + llvm::DIType *VTy = getOrCreateType(VoidPtr, Unit); + llvm::DINode::DIFlags Flags = getAccessFlag(AccessSpecifier::AS_private, RD); + auto Tag = CGM.getCodeGenOpts().DwarfVersion >= 5 + ? llvm::dwarf::DW_TAG_variable + : llvm::dwarf::DW_TAG_member; + llvm::DIDerivedType *OldDT = DBuilder.createStaticMemberType( + Ctxt, SymbolNameRef, Unit, /*LineNumber=*/0, VTy, Flags, + /*Val=*/nullptr, Tag); + llvm::DIDerivedType *DT = + static_cast(DBuilder.createArtificialType(OldDT)); + + // Use the same vtable pointer to global alignment for the symbol. + LangAS AS = CGM.GetGlobalVarAddressSpace(nullptr); + unsigned PAlign = CGM.getItaniumVTableContext().isRelativeLayout() +? 32 +: CGM.getTarget().getPointerAlign(AS); CarlosAlbertoEnciso wrote: Created a helper function just to calculate the alignment. https://github.com/llvm/llvm-project/pull/130255 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [clang][DebugInfo] Add symbol for debugger with VTable information. (PR #130255)
@@ -2518,6 +2518,59 @@ StringRef CGDebugInfo::getVTableName(const CXXRecordDecl *RD) { return internString("_vptr$", RD->getNameAsString()); } +// Emit symbol for the debugger that points to the vtable address for +// the given class. The symbol is named as '_vtable$'. +// The debugger does not need to know any details about the contents of the +// vtable as it can work this out using its knowledge of the ABI and the +// existing information in the DWARF. The type is assumed to be 'void *'. +void CGDebugInfo::emitVTableSymbol(llvm::GlobalVariable *VTable, + const CXXRecordDecl *RD) { + ASTContext &Context = CGM.getContext(); + SmallString<64> Buffer; + Twine SymbolName = internString("_vtable$"); + StringRef SymbolNameRef = SymbolName.toStringRef(Buffer); + DeclContext *DC = static_cast(const_cast(RD)); + SourceLocation Loc; + QualType VoidPtr = Context.getPointerType(Context.VoidTy); + + // We deal with two different contexts: + // - The type for the variable, which is part of the class that has the + // vtable, is placed in the context of the DICompositeType metadata. + // - The DIGlobalVariable for the vtable is put in the DICompileUnitScope. + + // The created non-member should be mark as 'artificial'. It will be + // placed it inside the scope of the C++ class/structure. + llvm::DIScope *DContext = getContextDescriptor(cast(DC), TheCU); + auto *Ctxt = cast(DContext); + llvm::DIFile *Unit = getOrCreateFile(Loc); + llvm::DIType *VTy = getOrCreateType(VoidPtr, Unit); + llvm::DINode::DIFlags Flags = getAccessFlag(AccessSpecifier::AS_private, RD); + auto Tag = CGM.getCodeGenOpts().DwarfVersion >= 5 + ? llvm::dwarf::DW_TAG_variable + : llvm::dwarf::DW_TAG_member; + llvm::DIDerivedType *OldDT = DBuilder.createStaticMemberType( + Ctxt, SymbolNameRef, Unit, /*LineNumber=*/0, VTy, Flags, + /*Val=*/nullptr, Tag); + llvm::DIDerivedType *DT = + static_cast(DBuilder.createArtificialType(OldDT)); + + // Use the same vtable pointer to global alignment for the symbol. + LangAS AS = CGM.GetGlobalVarAddressSpace(nullptr); + unsigned PAlign = CGM.getItaniumVTableContext().isRelativeLayout() +? 32 +: CGM.getTarget().getPointerAlign(AS); CarlosAlbertoEnciso wrote: The whole function `emitVTableSymbol` now is guarded. https://github.com/llvm/llvm-project/pull/130255 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [clang][DebugInfo] Add symbol for debugger with VTable information. (PR #130255)
@@ -2518,6 +2518,59 @@ StringRef CGDebugInfo::getVTableName(const CXXRecordDecl *RD) { return internString("_vptr$", RD->getNameAsString()); } +// Emit symbol for the debugger that points to the vtable address for +// the given class. The symbol is named as '_vtable$'. +// The debugger does not need to know any details about the contents of the +// vtable as it can work this out using its knowledge of the ABI and the +// existing information in the DWARF. The type is assumed to be 'void *'. +void CGDebugInfo::emitVTableSymbol(llvm::GlobalVariable *VTable, + const CXXRecordDecl *RD) { + ASTContext &Context = CGM.getContext(); + SmallString<64> Buffer; + Twine SymbolName = internString("_vtable$"); + StringRef SymbolNameRef = SymbolName.toStringRef(Buffer); + DeclContext *DC = static_cast(const_cast(RD)); CarlosAlbertoEnciso wrote: Changed to: `const DeclContext *DC = static_cast(RD);` https://github.com/llvm/llvm-project/pull/130255 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [clang][DebugInfo] Add symbol for debugger with VTable information. (PR #130255)
https://github.com/CarlosAlbertoEnciso updated https://github.com/llvm/llvm-project/pull/130255 >From 4bd0c48e12114301d8b81e9abe59e538684a6f71 Mon Sep 17 00:00:00 2001 From: Carlos Alberto Enciso Date: Tue, 25 Feb 2025 09:23:24 + Subject: [PATCH 1/2] [DebugInfo] Add symbol for debugger with VTable information. The IR now includes a global variable for the debugger that holds the address of the vtable. Now every class that contains virtual functions, has a static member (marked as artificial) that identifies where that vtable is loaded in memory. The unmangled name is '_vtable$'. This new symbol will allow a debugger to easily associate classes with the physical location of their VTables using only the DWARF information. Previously, this had to be done by searching for ELF symbols with matching names; something that was time-consuming and error-prone in certain edge cases. --- clang/lib/CodeGen/CGDebugInfo.cpp | 53 + clang/lib/CodeGen/CGDebugInfo.h | 3 + clang/lib/CodeGen/ItaniumCXXABI.cpp | 4 + ...ble-debug-info-inheritance-simple-base.cpp | 14 ++ ...table-debug-info-inheritance-simple-base.h | 15 ++ ...-debug-info-inheritance-simple-derived.cpp | 13 ++ ...le-debug-info-inheritance-simple-derived.h | 14 ++ clang/test/CodeGenCXX/debug-info-class.cpp| 26 ++- .../CodeGenCXX/debug-info-template-member.cpp | 52 ++--- .../vtable-debug-info-inheritance-diamond.cpp | 87 ...vtable-debug-info-inheritance-multiple.cpp | 72 ++ ...ble-debug-info-inheritance-simple-main.cpp | 87 .../vtable-debug-info-inheritance-simple.cpp | 55 + .../vtable-debug-info-inheritance-virtual.cpp | 87 clang/test/Modules/ExtDebugInfo.cpp | 10 +- .../vtable-debug-info-inheritance-simple.ll | 206 ++ 16 files changed, 755 insertions(+), 43 deletions(-) create mode 100644 clang/test/CodeGenCXX/Inputs/vtable-debug-info-inheritance-simple-base.cpp create mode 100644 clang/test/CodeGenCXX/Inputs/vtable-debug-info-inheritance-simple-base.h create mode 100644 clang/test/CodeGenCXX/Inputs/vtable-debug-info-inheritance-simple-derived.cpp create mode 100644 clang/test/CodeGenCXX/Inputs/vtable-debug-info-inheritance-simple-derived.h create mode 100644 clang/test/CodeGenCXX/vtable-debug-info-inheritance-diamond.cpp create mode 100644 clang/test/CodeGenCXX/vtable-debug-info-inheritance-multiple.cpp create mode 100644 clang/test/CodeGenCXX/vtable-debug-info-inheritance-simple-main.cpp create mode 100644 clang/test/CodeGenCXX/vtable-debug-info-inheritance-simple.cpp create mode 100644 clang/test/CodeGenCXX/vtable-debug-info-inheritance-virtual.cpp create mode 100644 llvm/test/DebugInfo/X86/vtable-debug-info-inheritance-simple.ll diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index 0e6daa42ee7bf..9cadeadc54111 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -2518,6 +2518,59 @@ StringRef CGDebugInfo::getVTableName(const CXXRecordDecl *RD) { return internString("_vptr$", RD->getNameAsString()); } +// Emit symbol for the debugger that points to the vtable address for +// the given class. The symbol is named as '_vtable$'. +// The debugger does not need to know any details about the contents of the +// vtable as it can work this out using its knowledge of the ABI and the +// existing information in the DWARF. The type is assumed to be 'void *'. +void CGDebugInfo::emitVTableSymbol(llvm::GlobalVariable *VTable, + const CXXRecordDecl *RD) { + ASTContext &Context = CGM.getContext(); + SmallString<64> Buffer; + Twine SymbolName = internString("_vtable$"); + StringRef SymbolNameRef = SymbolName.toStringRef(Buffer); + DeclContext *DC = static_cast(const_cast(RD)); + SourceLocation Loc; + QualType VoidPtr = Context.getPointerType(Context.VoidTy); + + // We deal with two different contexts: + // - The type for the variable, which is part of the class that has the + // vtable, is placed in the context of the DICompositeType metadata. + // - The DIGlobalVariable for the vtable is put in the DICompileUnitScope. + + // The created non-member should be mark as 'artificial'. It will be + // placed it inside the scope of the C++ class/structure. + llvm::DIScope *DContext = getContextDescriptor(cast(DC), TheCU); + auto *Ctxt = cast(DContext); + llvm::DIFile *Unit = getOrCreateFile(Loc); + llvm::DIType *VTy = getOrCreateType(VoidPtr, Unit); + llvm::DINode::DIFlags Flags = getAccessFlag(AccessSpecifier::AS_private, RD); + auto Tag = CGM.getCodeGenOpts().DwarfVersion >= 5 + ? llvm::dwarf::DW_TAG_variable + : llvm::dwarf::DW_TAG_member; + llvm::DIDerivedType *OldDT = DBuilder.createStaticMemberType( + Ctxt, SymbolNameRef, Unit, /*LineNumber=*/0, VTy, Flags, + /*Val=*/nullptr, Tag); + llvm::DIDerivedType *DT = + static_cast(DBu
[clang] [llvm] [clang][DebugInfo] Add symbol for debugger with VTable information. (PR #130255)
https://github.com/CarlosAlbertoEnciso created https://github.com/llvm/llvm-project/pull/130255 The IR now includes a global variable for the debugger that holds the address of the vtable. Now every class that contains virtual functions, has a static member (marked as artificial) that identifies where that vtable is loaded in memory. The unmangled name is '_vtable$'. This new symbol will allow a debugger to easily associate classes with the physical location of their VTables using only the DWARF information. Previously, this had to be done by searching for ELF symbols with matching names; something that was time-consuming and error-prone in certain edge cases. >From 4bd0c48e12114301d8b81e9abe59e538684a6f71 Mon Sep 17 00:00:00 2001 From: Carlos Alberto Enciso Date: Tue, 25 Feb 2025 09:23:24 + Subject: [PATCH] [DebugInfo] Add symbol for debugger with VTable information. The IR now includes a global variable for the debugger that holds the address of the vtable. Now every class that contains virtual functions, has a static member (marked as artificial) that identifies where that vtable is loaded in memory. The unmangled name is '_vtable$'. This new symbol will allow a debugger to easily associate classes with the physical location of their VTables using only the DWARF information. Previously, this had to be done by searching for ELF symbols with matching names; something that was time-consuming and error-prone in certain edge cases. --- clang/lib/CodeGen/CGDebugInfo.cpp | 53 + clang/lib/CodeGen/CGDebugInfo.h | 3 + clang/lib/CodeGen/ItaniumCXXABI.cpp | 4 + ...ble-debug-info-inheritance-simple-base.cpp | 14 ++ ...table-debug-info-inheritance-simple-base.h | 15 ++ ...-debug-info-inheritance-simple-derived.cpp | 13 ++ ...le-debug-info-inheritance-simple-derived.h | 14 ++ clang/test/CodeGenCXX/debug-info-class.cpp| 26 ++- .../CodeGenCXX/debug-info-template-member.cpp | 52 ++--- .../vtable-debug-info-inheritance-diamond.cpp | 87 ...vtable-debug-info-inheritance-multiple.cpp | 72 ++ ...ble-debug-info-inheritance-simple-main.cpp | 87 .../vtable-debug-info-inheritance-simple.cpp | 55 + .../vtable-debug-info-inheritance-virtual.cpp | 87 clang/test/Modules/ExtDebugInfo.cpp | 10 +- .../vtable-debug-info-inheritance-simple.ll | 206 ++ 16 files changed, 755 insertions(+), 43 deletions(-) create mode 100644 clang/test/CodeGenCXX/Inputs/vtable-debug-info-inheritance-simple-base.cpp create mode 100644 clang/test/CodeGenCXX/Inputs/vtable-debug-info-inheritance-simple-base.h create mode 100644 clang/test/CodeGenCXX/Inputs/vtable-debug-info-inheritance-simple-derived.cpp create mode 100644 clang/test/CodeGenCXX/Inputs/vtable-debug-info-inheritance-simple-derived.h create mode 100644 clang/test/CodeGenCXX/vtable-debug-info-inheritance-diamond.cpp create mode 100644 clang/test/CodeGenCXX/vtable-debug-info-inheritance-multiple.cpp create mode 100644 clang/test/CodeGenCXX/vtable-debug-info-inheritance-simple-main.cpp create mode 100644 clang/test/CodeGenCXX/vtable-debug-info-inheritance-simple.cpp create mode 100644 clang/test/CodeGenCXX/vtable-debug-info-inheritance-virtual.cpp create mode 100644 llvm/test/DebugInfo/X86/vtable-debug-info-inheritance-simple.ll diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index 0e6daa42ee7bf..9cadeadc54111 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -2518,6 +2518,59 @@ StringRef CGDebugInfo::getVTableName(const CXXRecordDecl *RD) { return internString("_vptr$", RD->getNameAsString()); } +// Emit symbol for the debugger that points to the vtable address for +// the given class. The symbol is named as '_vtable$'. +// The debugger does not need to know any details about the contents of the +// vtable as it can work this out using its knowledge of the ABI and the +// existing information in the DWARF. The type is assumed to be 'void *'. +void CGDebugInfo::emitVTableSymbol(llvm::GlobalVariable *VTable, + const CXXRecordDecl *RD) { + ASTContext &Context = CGM.getContext(); + SmallString<64> Buffer; + Twine SymbolName = internString("_vtable$"); + StringRef SymbolNameRef = SymbolName.toStringRef(Buffer); + DeclContext *DC = static_cast(const_cast(RD)); + SourceLocation Loc; + QualType VoidPtr = Context.getPointerType(Context.VoidTy); + + // We deal with two different contexts: + // - The type for the variable, which is part of the class that has the + // vtable, is placed in the context of the DICompositeType metadata. + // - The DIGlobalVariable for the vtable is put in the DICompileUnitScope. + + // The created non-member should be mark as 'artificial'. It will be + // placed it inside the scope of the C++ class/structure. + llvm::DIScope *DContext = getContextDescriptor(cast(DC), TheCU); +
[clang] [llvm] [clang][DebugInfo] Add symbol for debugger with VTable information. (PR #130255)
CarlosAlbertoEnciso wrote: @Michael137, @dwblaikie, @labath, @tromey Thanks very much for your valuable feedback. Is there any additional points about the current patch that you would like to address? Thanks https://github.com/llvm/llvm-project/pull/130255 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [clang][DebugInfo] Add symbol for debugger with VTable information. (PR #130255)
https://github.com/CarlosAlbertoEnciso updated https://github.com/llvm/llvm-project/pull/130255 Rate limit · GitHub body { background-color: #f6f8fa; color: #24292e; font-family: -apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol; font-size: 14px; line-height: 1.5; margin: 0; } .container { margin: 50px auto; max-width: 600px; text-align: center; padding: 0 24px; } a { color: #0366d6; text-decoration: none; } a:hover { text-decoration: underline; } h1 { line-height: 60px; font-size: 48px; font-weight: 300; margin: 0px; text-shadow: 0 1px 0 #fff; } p { color: rgba(0, 0, 0, 0.5); margin: 20px 0 40px; } ul { list-style: none; margin: 25px 0; padding: 0; } li { display: table-cell; font-weight: bold; width: 1%; } .logo { display: inline-block; margin-top: 35px; } .logo-img-2x { display: none; } @media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and ( min--moz-device-pixel-ratio: 2), only screen and ( -o-min-device-pixel-ratio: 2/1), only screen and (min-device-pixel-ratio: 2), only screen and (min-resolution: 192dpi), only screen and (min-resolution: 2dppx) { .logo-img-1x { display: none; } .logo-img-2x { display: inline-block; } } #suggestions { margin-top: 35px; color: #ccc; } #suggestions a { color: #66; font-weight: 200; font-size: 14px; margin: 0 10px; } Whoa there! You have exceeded a secondary rate limit. Please wait a few minutes before you try again; in some cases this may take up to an hour. https://support.github.com/contact";>Contact Support — https://githubstatus.com";>GitHub Status — https://twitter.com/githubstatus";>@githubstatus ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [clang][DebugInfo] Add symbol for debugger with VTable information. (PR #130255)
CarlosAlbertoEnciso wrote: Uploaded a patch that eliminates the global variable and it moves the vtable information into the static member; in that way, a consumer always will have access to the vtable information, just by having an object instance or the object definition. The patch has been tested by the (SCE) debugger team. https://github.com/llvm/llvm-project/pull/130255 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [clang][DebugInfo] Add symbol for debugger with VTable information. (PR #130255)
https://github.com/CarlosAlbertoEnciso updated https://github.com/llvm/llvm-project/pull/130255 >From 4bd0c48e12114301d8b81e9abe59e538684a6f71 Mon Sep 17 00:00:00 2001 From: Carlos Alberto Enciso Date: Tue, 25 Feb 2025 09:23:24 + Subject: [PATCH 1/4] [DebugInfo] Add symbol for debugger with VTable information. The IR now includes a global variable for the debugger that holds the address of the vtable. Now every class that contains virtual functions, has a static member (marked as artificial) that identifies where that vtable is loaded in memory. The unmangled name is '_vtable$'. This new symbol will allow a debugger to easily associate classes with the physical location of their VTables using only the DWARF information. Previously, this had to be done by searching for ELF symbols with matching names; something that was time-consuming and error-prone in certain edge cases. --- clang/lib/CodeGen/CGDebugInfo.cpp | 53 + clang/lib/CodeGen/CGDebugInfo.h | 3 + clang/lib/CodeGen/ItaniumCXXABI.cpp | 4 + ...ble-debug-info-inheritance-simple-base.cpp | 14 ++ ...table-debug-info-inheritance-simple-base.h | 15 ++ ...-debug-info-inheritance-simple-derived.cpp | 13 ++ ...le-debug-info-inheritance-simple-derived.h | 14 ++ clang/test/CodeGenCXX/debug-info-class.cpp| 26 ++- .../CodeGenCXX/debug-info-template-member.cpp | 52 ++--- .../vtable-debug-info-inheritance-diamond.cpp | 87 ...vtable-debug-info-inheritance-multiple.cpp | 72 ++ ...ble-debug-info-inheritance-simple-main.cpp | 87 .../vtable-debug-info-inheritance-simple.cpp | 55 + .../vtable-debug-info-inheritance-virtual.cpp | 87 clang/test/Modules/ExtDebugInfo.cpp | 10 +- .../vtable-debug-info-inheritance-simple.ll | 206 ++ 16 files changed, 755 insertions(+), 43 deletions(-) create mode 100644 clang/test/CodeGenCXX/Inputs/vtable-debug-info-inheritance-simple-base.cpp create mode 100644 clang/test/CodeGenCXX/Inputs/vtable-debug-info-inheritance-simple-base.h create mode 100644 clang/test/CodeGenCXX/Inputs/vtable-debug-info-inheritance-simple-derived.cpp create mode 100644 clang/test/CodeGenCXX/Inputs/vtable-debug-info-inheritance-simple-derived.h create mode 100644 clang/test/CodeGenCXX/vtable-debug-info-inheritance-diamond.cpp create mode 100644 clang/test/CodeGenCXX/vtable-debug-info-inheritance-multiple.cpp create mode 100644 clang/test/CodeGenCXX/vtable-debug-info-inheritance-simple-main.cpp create mode 100644 clang/test/CodeGenCXX/vtable-debug-info-inheritance-simple.cpp create mode 100644 clang/test/CodeGenCXX/vtable-debug-info-inheritance-virtual.cpp create mode 100644 llvm/test/DebugInfo/X86/vtable-debug-info-inheritance-simple.ll diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index 0e6daa42ee7bf..9cadeadc54111 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -2518,6 +2518,59 @@ StringRef CGDebugInfo::getVTableName(const CXXRecordDecl *RD) { return internString("_vptr$", RD->getNameAsString()); } +// Emit symbol for the debugger that points to the vtable address for +// the given class. The symbol is named as '_vtable$'. +// The debugger does not need to know any details about the contents of the +// vtable as it can work this out using its knowledge of the ABI and the +// existing information in the DWARF. The type is assumed to be 'void *'. +void CGDebugInfo::emitVTableSymbol(llvm::GlobalVariable *VTable, + const CXXRecordDecl *RD) { + ASTContext &Context = CGM.getContext(); + SmallString<64> Buffer; + Twine SymbolName = internString("_vtable$"); + StringRef SymbolNameRef = SymbolName.toStringRef(Buffer); + DeclContext *DC = static_cast(const_cast(RD)); + SourceLocation Loc; + QualType VoidPtr = Context.getPointerType(Context.VoidTy); + + // We deal with two different contexts: + // - The type for the variable, which is part of the class that has the + // vtable, is placed in the context of the DICompositeType metadata. + // - The DIGlobalVariable for the vtable is put in the DICompileUnitScope. + + // The created non-member should be mark as 'artificial'. It will be + // placed it inside the scope of the C++ class/structure. + llvm::DIScope *DContext = getContextDescriptor(cast(DC), TheCU); + auto *Ctxt = cast(DContext); + llvm::DIFile *Unit = getOrCreateFile(Loc); + llvm::DIType *VTy = getOrCreateType(VoidPtr, Unit); + llvm::DINode::DIFlags Flags = getAccessFlag(AccessSpecifier::AS_private, RD); + auto Tag = CGM.getCodeGenOpts().DwarfVersion >= 5 + ? llvm::dwarf::DW_TAG_variable + : llvm::dwarf::DW_TAG_member; + llvm::DIDerivedType *OldDT = DBuilder.createStaticMemberType( + Ctxt, SymbolNameRef, Unit, /*LineNumber=*/0, VTy, Flags, + /*Val=*/nullptr, Tag); + llvm::DIDerivedType *DT = + static_cast(DBu
[clang] [llvm] [clang][DebugInfo] Add symbol for debugger with VTable information. (PR #130255)
https://github.com/CarlosAlbertoEnciso updated https://github.com/llvm/llvm-project/pull/130255 Rate limit · GitHub body { background-color: #f6f8fa; color: #24292e; font-family: -apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol; font-size: 14px; line-height: 1.5; margin: 0; } .container { margin: 50px auto; max-width: 600px; text-align: center; padding: 0 24px; } a { color: #0366d6; text-decoration: none; } a:hover { text-decoration: underline; } h1 { line-height: 60px; font-size: 48px; font-weight: 300; margin: 0px; text-shadow: 0 1px 0 #fff; } p { color: rgba(0, 0, 0, 0.5); margin: 20px 0 40px; } ul { list-style: none; margin: 25px 0; padding: 0; } li { display: table-cell; font-weight: bold; width: 1%; } .logo { display: inline-block; margin-top: 35px; } .logo-img-2x { display: none; } @media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and ( min--moz-device-pixel-ratio: 2), only screen and ( -o-min-device-pixel-ratio: 2/1), only screen and (min-device-pixel-ratio: 2), only screen and (min-resolution: 192dpi), only screen and (min-resolution: 2dppx) { .logo-img-1x { display: none; } .logo-img-2x { display: inline-block; } } #suggestions { margin-top: 35px; color: #ccc; } #suggestions a { color: #66; font-weight: 200; font-size: 14px; margin: 0 10px; } Whoa there! You have exceeded a secondary rate limit. Please wait a few minutes before you try again; in some cases this may take up to an hour. https://support.github.com/contact";>Contact Support — https://githubstatus.com";>GitHub Status — https://twitter.com/githubstatus";>@githubstatus ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [clang][DebugInfo] Add symbol for debugger with VTable information. (PR #130255)
CarlosAlbertoEnciso wrote: > Got measurements on debug info size growth or any other metrics we should be > considering? I will prepare some measurements on debug info size. https://github.com/llvm/llvm-project/pull/130255 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [clang][DebugInfo] Add symbol for debugger with VTable information. (PR #130255)
https://github.com/CarlosAlbertoEnciso updated https://github.com/llvm/llvm-project/pull/130255 Rate limit · GitHub body { background-color: #f6f8fa; color: #24292e; font-family: -apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol; font-size: 14px; line-height: 1.5; margin: 0; } .container { margin: 50px auto; max-width: 600px; text-align: center; padding: 0 24px; } a { color: #0366d6; text-decoration: none; } a:hover { text-decoration: underline; } h1 { line-height: 60px; font-size: 48px; font-weight: 300; margin: 0px; text-shadow: 0 1px 0 #fff; } p { color: rgba(0, 0, 0, 0.5); margin: 20px 0 40px; } ul { list-style: none; margin: 25px 0; padding: 0; } li { display: table-cell; font-weight: bold; width: 1%; } .logo { display: inline-block; margin-top: 35px; } .logo-img-2x { display: none; } @media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and ( min--moz-device-pixel-ratio: 2), only screen and ( -o-min-device-pixel-ratio: 2/1), only screen and (min-device-pixel-ratio: 2), only screen and (min-resolution: 192dpi), only screen and (min-resolution: 2dppx) { .logo-img-1x { display: none; } .logo-img-2x { display: inline-block; } } #suggestions { margin-top: 35px; color: #ccc; } #suggestions a { color: #66; font-weight: 200; font-size: 14px; margin: 0 10px; } Whoa there! You have exceeded a secondary rate limit. Please wait a few minutes before you try again; in some cases this may take up to an hour. https://support.github.com/contact";>Contact Support — https://githubstatus.com";>GitHub Status — https://twitter.com/githubstatus";>@githubstatus ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [clang][DebugInfo] Add symbol for debugger with VTable information. (PR #130255)
CarlosAlbertoEnciso wrote: > Apologies if I missed it, but one thing I didn't see in the patch is a test > for the case where a class is defined inside a function. > > Given the discussion > [here](https://discourse.llvm.org/t/rfc-dwarfdebug-fix-and-improve-handling-imported-entities-types-and-static-local-in-subprogram-and-lexical-block-scopes/68544), > I guess this might not fully work correctly; but it seems to me that > checking that the vtable symbol is global could be done and might provide > some future-proofing. Added 2 test cases to cover when a class is define inside a function: Using `CBase` and `CDerived` from the previous test cases: - `CBase` defined at global scope and `CDerived` defined at function scope. - `CBase` and `CDerived` both defined at function scope. https://github.com/llvm/llvm-project/pull/130255 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [clang][DebugInfo] Add symbol for debugger with VTable information. (PR #130255)
@@ -1816,6 +1816,15 @@ class CodeGenModule : public CodeGenTypeCache { void requireVectorDestructorDefinition(const CXXRecordDecl *RD); bool classNeedsVectorDestructor(const CXXRecordDecl *RD); + // Helper to get the alignment for a variable. + unsigned getGlobalVarAlignment(const VarDecl *D = nullptr) { +LangAS AS = GetGlobalVarAddressSpace(D); +unsigned PAlign = getItaniumVTableContext().isRelativeLayout() + ? 32 + : getTarget().getPointerAlign(AS); +return PAlign; + } + CarlosAlbertoEnciso wrote: Changed function name to `getVtableGlobalVarAlignment`. https://github.com/llvm/llvm-project/pull/130255 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [clang][DebugInfo] Add symbol for debugger with VTable information. (PR #130255)
CarlosAlbertoEnciso wrote: Updated patch. https://github.com/llvm/llvm-project/pull/130255 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [clang][DebugInfo] Add symbol for debugger with VTable information. (PR #130255)
CarlosAlbertoEnciso wrote: > Could you remove the LLVM tests? They don't add coverage since tnhis isn't an > LLVM feature - as far as LLVM is concerned, this is another static member > variable like any other. Removed all the LLVM tests. > > Why do some of the test cases use distinct input files/headers? I'd have > thought these could all be written as standalone files with classes all > written in a single file? (easier to read the test case in isolation, no > implication that the header-ness matters (like this shouldn't be behaving > differently because some content exists in a header V not, right?)) Moved all the code into a single file. The performed checks are the same. Uploaded updated patch. https://github.com/llvm/llvm-project/pull/130255 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [clang][DebugInfo] Add symbol for debugger with VTable information. (PR #130255)
CarlosAlbertoEnciso wrote: @tromey You added a note about a missing test for the case where a class is defined inside a function. That case is handled by `clang/test/CodeGenCXX/vtable-debug-info-inheritance-simple-main.cpp` https://github.com/llvm/llvm-project/pull/130255 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [clang][DebugInfo] Add symbol for debugger with VTable information. (PR #130255)
CarlosAlbertoEnciso wrote: @dwblaikie I have used bloaty to get some debug info size changes. The VTable work is based on this specific revision c02019141. I built Clang using `DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_PROJECTS=clang`: - at that specific revision c02019141 (original Clang) --> **original**. - and that revision with the current patch applied --> **modified**. Using those builds I built Clang twice with debug info, using `DCMAKE_BUILD_TYPE=Debug -DLLVM_ENABLE_PROJECTS=clang`: Using **original** --> **reference** Using **modified** --> **vtables** These are the sizes reported by `bloaty` ``` $ [...]./bloaty [...]/vtables/bin/clang++ -- [...]/reference/bin/clang++ FILE SIZEVM SIZE -- -- +0.2% +436Ki [ = ] 0.debug_str +0.1% +361Ki [ = ] 0.debug_info +3.2% +300Ki [ = ] 0.debug_abbrev +0.3% +122Ki [ = ] 0.debug_addr +0.1% +69.9Ki [ = ] 0.debug_str_offsets +0.0% +9.75Ki [ = ] 0.debug_line +0.0% +2.51Ki [ = ] 0.debug_rnglists +0.0% +21 [ = ] 0.debug_line_str +9.9% +15 [ = ] 0.comment +0.0% +1 [ = ] 0.debug_loclists +0.1% +1.27Mi [ = ] 0TOTAL $ ls -Ll [...]/vtables/bin/clang++ [...]/reference/bin/clang++ -rwxrwxr-x 1 [...] 1678577192 May 20 10:53 [...]/vtables/bin/clang++ -rwxrwxr-x 1 [...] 1677243032 May 20 10:35 [...]/reference/bin/clang++ ``` ``` $ [...]./bloaty [...]/vtables/bin/llc -- [...]/reference/bin/llc FILE SIZEVM SIZE -- -- +0.2% +291Ki [ = ] 0.debug_str +0.1% +283Ki [ = ] 0.debug_info +3.0% +202Ki [ = ] 0.debug_abbrev +0.3% +71.1Ki [ = ] 0.debug_addr +0.1% +42.0Ki [ = ] 0.debug_str_offsets +0.0% +1.94Ki [ = ] 0.debug_rnglists +0.0%+486 [ = ] 0.debug_line +0.0% +18 [ = ] 0.debug_line_str +9.9% +15 [ = ] 0.comment +0.0% +1 [ = ] 0.debug_loclists +0.1% +892Ki [ = ] 0TOTAL ``` ``` $ [...]./bloaty [...]/vtables/bin/opt -- [...]/reference/bin/opt FILE SIZEVM SIZE -- -- +0.2% +293Ki [ = ] 0.debug_str +0.1% +283Ki [ = ] 0.debug_info +3.0% +202Ki [ = ] 0.debug_abbrev +0.3% +71.3Ki [ = ] 0.debug_addr +0.1% +42.1Ki [ = ] 0.debug_str_offsets +0.0% +1.93Ki [ = ] 0.debug_rnglists +0.0%+486 [ = ] 0.debug_line +0.0% +18 [ = ] 0.debug_line_str +9.9% +15 [ = ] 0.comment +0.0% +1 [ = ] 0.debug_loclists +0.1% +895Ki [ = ] 0TOTAL ``` ``` $ [...]./bloaty [...]/vtables/bin/llvm-as -- [...]/reference/bin/llvm-as FILE SIZEVM SIZE -- -- +0.1% +59.6Ki [ = ] 0.debug_info +0.1% +34.6Ki [ = ] 0.debug_str +2.7% +29.9Ki [ = ] 0.debug_abbrev +0.3% +11.2Ki [ = ] 0.debug_addr +0.1% +6.51Ki [ = ] 0.debug_str_offsets +0.0%+288 [ = ] 0.debug_rnglists +0.0% +18 [ = ] 0.debug_line_str +9.9% +15 [ = ] 0.comment -0.0% -22 [ = ] 0.debug_line +0.1% +142Ki [ = ] 0TOTAL ``` https://github.com/llvm/llvm-project/pull/130255 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits