[clang] [KeyInstr][Clang] Catch variable init atom (PR #134641)
Orlando Cazalet-Hyams via cfe-commits
cfe-commits at lists.llvm.org
Fri May 23 02:16:06 PDT 2025
https://github.com/OCHyams updated https://github.com/llvm/llvm-project/pull/134641
>From ae032c5dd3537662508d77bbb447808f52481f5d Mon Sep 17 00:00:00 2001
From: Orlando Cazalet-Hyams <orlando.hyams at sony.com>
Date: Tue, 1 Apr 2025 11:59:24 +0100
Subject: [PATCH 01/33] [KeyInstr][Clang] Add ApplyAtomGroup
This is a scoped helper similar to ApplyDebugLocation that creates a new source
atom group which instructions can be added to.
A source atom is a source construct that is "interesting" for debug stepping
purposes. We use an atom group number to track the instruction(s) that implement
the functionality for the atom, plus backup instructions/source locations.
---
This patch is part of a stack that teaches Clang to generate Key Instructions
metadata for C and C++.
The Key Instructions project is introduced, including a "quick summary" section
at the top which adds context for this PR, here:
https://discourse.llvm.org/t/rfc-improving-is-stmt-placement-for-better-interactive-debugging/82668
The feature is only functional in LLVM if LLVM is built with CMake flag
LLVM_EXPERIMENTAL_KEY_INSTRUCTIONs. Eventually that flag will be removed.
The Clang-side work is demoed here:
https://github.com/llvm/llvm-project/pull/130943
---
clang/lib/CodeGen/CGDebugInfo.cpp | 119 +++++++++++++++++++++++++++-
clang/lib/CodeGen/CGDebugInfo.h | 50 ++++++++++++
clang/lib/CodeGen/CodeGenFunction.h | 14 ++++
3 files changed, 182 insertions(+), 1 deletion(-)
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index 2a11eebf1b682..f4c5c57a38b3e 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -43,6 +43,7 @@
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DerivedTypes.h"
+#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/Metadata.h"
@@ -52,6 +53,7 @@
#include "llvm/Support/SHA1.h"
#include "llvm/Support/SHA256.h"
#include "llvm/Support/TimeProfiler.h"
+#include <cstdint>
#include <optional>
using namespace clang;
using namespace clang::CodeGen;
@@ -119,6 +121,114 @@ CGDebugInfo::~CGDebugInfo() {
"Region stack mismatch, stack not empty!");
}
+void CGDebugInfo::addInstSourceAtomMetadata(llvm::Instruction *I,
+ uint64_t Group, uint8_t Rank) {
+ if (!I->getDebugLoc() || Group == 0 || !I->getDebugLoc()->getLine())
+ return;
+
+ // Saturate the 3-bit rank.
+ Rank = std::min<uint8_t>(Rank, 7);
+
+ const llvm::DebugLoc &DL = I->getDebugLoc();
+
+ // Each instruction can only be attributed to one source atom (a limitation of
+ // the implementation). If this instruction is already part of a source atom,
+ // pick the group in which it has highest precedence (lowest rank).
+ if (DL.get()->getAtomGroup() && DL.get()->getAtomRank() &&
+ DL.get()->getAtomRank() < Rank) {
+ Group = DL.get()->getAtomGroup();
+ Rank = DL.get()->getAtomRank();
+ }
+
+ // Update the function-local watermark so we don't reuse this number for
+ // another atom.
+ KeyInstructionsInfo.HighestEmittedAtom =
+ std::max(Group, KeyInstructionsInfo.HighestEmittedAtom);
+
+ // Apply the new DILocation to the instruction.
+ llvm::DILocation *NewDL = llvm::DILocation::get(
+ I->getContext(), DL.getLine(), DL.getCol(), DL.getScope(),
+ DL.getInlinedAt(), DL.isImplicitCode(), Group, Rank);
+ I->setDebugLoc(NewDL);
+};
+
+void CGDebugInfo::addInstToCurrentSourceAtom(llvm::Instruction *KeyInstruction,
+ llvm::Value *Backup) {
+ if (!CGM.getCodeGenOpts().DebugKeyInstructions)
+ return;
+
+ uint64_t Group = KeyInstructionsInfo.CurrentAtom;
+ if (!Group)
+ return;
+
+ addInstSourceAtomMetadata(KeyInstruction, Group, /*Rank=*/1);
+
+ llvm::Instruction *BackupI =
+ llvm::dyn_cast_or_null<llvm::Instruction>(Backup);
+ if (!BackupI)
+ return;
+
+ // Add the backup instruction to the group.
+ addInstSourceAtomMetadata(BackupI, Group, /*Rank=*/2);
+
+ // Look through chains of casts too, as they're probably going to evaporate.
+ // FIXME: And other nops like zero length geps?
+ // FIXME: Should use Cast->isNoopCast()?
+ uint8_t Rank = 3;
+ while (auto *Cast = dyn_cast<llvm::CastInst>(BackupI)) {
+ BackupI = dyn_cast<llvm::Instruction>(Cast->getOperand(0));
+ if (!BackupI)
+ break;
+ addInstSourceAtomMetadata(BackupI, Group, Rank++);
+ }
+}
+
+void CGDebugInfo::addRetToOverrideOrNewSourceAtom(llvm::ReturnInst *Ret,
+ llvm::Value *Backup) {
+ if (KeyInstructionsInfo.RetAtomOverride) {
+ uint64_t CurrentAtom = KeyInstructionsInfo.CurrentAtom;
+ KeyInstructionsInfo.CurrentAtom = KeyInstructionsInfo.RetAtomOverride;
+ addInstToCurrentSourceAtom(Ret, Backup);
+ KeyInstructionsInfo.CurrentAtom = CurrentAtom;
+ KeyInstructionsInfo.RetAtomOverride = 0;
+ } else {
+ auto Grp = ApplyAtomGroup(this);
+ addInstToCurrentSourceAtom(Ret, Backup);
+ }
+}
+
+void CGDebugInfo::setRetInstSourceAtomOverride(uint64_t Group) {
+ assert(KeyInstructionsInfo.RetAtomOverride == 0);
+ KeyInstructionsInfo.RetAtomOverride = Group;
+}
+
+void CGDebugInfo::completeFunction() {
+ // Reset the atom group number tracker as the numbers are function-local.
+ KeyInstructionsInfo.NextAtom = 1;
+ KeyInstructionsInfo.HighestEmittedAtom = 0;
+ KeyInstructionsInfo.CurrentAtom = 0;
+ KeyInstructionsInfo.RetAtomOverride = 0;
+}
+
+ApplyAtomGroup::ApplyAtomGroup(CGDebugInfo *DI) : DI(DI) {
+ if (!DI)
+ return;
+ OriginalAtom = DI->KeyInstructionsInfo.CurrentAtom;
+ DI->KeyInstructionsInfo.CurrentAtom = DI->KeyInstructionsInfo.NextAtom++;
+}
+
+ApplyAtomGroup::~ApplyAtomGroup() {
+ if (!DI)
+ return;
+
+ // We may not have used the group number at all.
+ DI->KeyInstructionsInfo.NextAtom =
+ std::min(DI->KeyInstructionsInfo.HighestEmittedAtom + 1,
+ DI->KeyInstructionsInfo.NextAtom);
+
+ DI->KeyInstructionsInfo.CurrentAtom = OriginalAtom;
+}
+
ApplyDebugLocation::ApplyDebugLocation(CodeGenFunction &CGF,
SourceLocation TemporaryLocation)
: CGF(&CGF) {
@@ -174,8 +284,15 @@ ApplyDebugLocation::ApplyDebugLocation(CodeGenFunction &CGF, llvm::DebugLoc Loc)
return;
}
OriginalLocation = CGF.Builder.getCurrentDebugLocation();
- if (Loc)
+ if (Loc) {
+ // Key Instructions: drop the atom group and rank to avoid accidentally
+ // propagating it around.
+ if (Loc->getAtomGroup())
+ Loc = llvm::DILocation::get(Loc->getContext(), Loc.getLine(),
+ Loc->getColumn(), Loc->getScope(),
+ Loc->getInlinedAt(), Loc.isImplicitCode());
CGF.Builder.SetCurrentDebugLocation(std::move(Loc));
+ }
}
ApplyDebugLocation::~ApplyDebugLocation() {
diff --git a/clang/lib/CodeGen/CGDebugInfo.h b/clang/lib/CodeGen/CGDebugInfo.h
index b287ce7b92eee..d9081d9bb3ffb 100644
--- a/clang/lib/CodeGen/CGDebugInfo.h
+++ b/clang/lib/CodeGen/CGDebugInfo.h
@@ -58,6 +58,8 @@ class CGBlockInfo;
class CGDebugInfo {
friend class ApplyDebugLocation;
friend class SaveAndRestoreLocation;
+ friend class ApplyAtomGroup;
+
CodeGenModule &CGM;
const llvm::codegenoptions::DebugInfoKind DebugKind;
bool DebugTypeExtRefs;
@@ -179,6 +181,17 @@ class CGDebugInfo {
/// The key is coroutine real parameters, value is DIVariable in LLVM IR.
Param2DILocTy ParamDbgMappings;
+ /// Key Instructions bookkeeping.
+ /// Source atoms are identified by a {AtomGroup, InlinedAt} pair, meaning
+ /// AtomGroup numbers can be repeated across different functions.
+ struct {
+ uint64_t NextAtom = 1;
+ uint64_t HighestEmittedAtom = 0;
+ uint64_t CurrentAtom = 0;
+ uint64_t RetAtomOverride = 0;
+ } KeyInstructionsInfo;
+
+private:
/// Helper functions for getOrCreateType.
/// @{
/// Currently the checksum of an interface includes the number of
@@ -643,7 +656,30 @@ class CGDebugInfo {
llvm::DILocation *CreateSyntheticInlineAt(llvm::DebugLoc Location,
StringRef FuncName);
+ /// Reset internal state.
+ void completeFunction();
+
+ /// Add \p KeyInstruction and an optional \p Backup instruction to the
+ /// current atom group, created using ApplyAtomGroup.
+ void addInstToCurrentSourceAtom(llvm::Instruction *KeyInstruction,
+ llvm::Value *Backup);
+
+ /// Add \p Ret and an optional \p Backup instruction to the
+ /// saved override used for some ret instructions if it exists, or a new atom.
+ void addRetToOverrideOrNewSourceAtom(llvm::ReturnInst *Ret,
+ llvm::Value *Backup);
+
+ /// Set an atom group override for use in addRetToOverrideOrNewSourceAtom.
+ void setRetInstSourceAtomOverride(uint64_t Group);
+
private:
+ /// Amend \p I's DebugLoc with \p Group (its source atom group) and \p
+ /// Rank (lower nonzero rank is higher precedence). Does nothing if \p I
+ /// has no DebugLoc, and chooses the atom group in which the instruction
+ /// has the highest precedence if it's already in one.
+ void addInstSourceAtomMetadata(llvm::Instruction *I, uint64_t Group,
+ uint8_t Rank);
+
/// Emit call to llvm.dbg.declare for a variable declaration.
/// Returns a pointer to the DILocalVariable associated with the
/// llvm.dbg.declare, or nullptr otherwise.
@@ -860,6 +896,20 @@ class CGDebugInfo {
}
};
+/// A scoped helper to set the current source atom group for
+/// CGDebugInfo::addInstToCurrentSourceAtom. A source atom is a source construct
+/// that is "interesting" for debug stepping purposes. We use an atom group
+/// number to track the instruction(s) that implement the functionality for the
+/// atom, plus backup instructions/source locations.
+class ApplyAtomGroup {
+ uint64_t OriginalAtom = 0;
+ CGDebugInfo *DI = nullptr;
+
+public:
+ ApplyAtomGroup(CGDebugInfo *DI);
+ ~ApplyAtomGroup();
+};
+
/// A scoped helper to set the current debug location to the specified
/// location or preferred location of the specified Expr.
class ApplyDebugLocation {
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index 603e38d763aa4..aec29d4ea61e8 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -1740,6 +1740,20 @@ class CodeGenFunction : public CodeGenTypeCache {
/// recently incremented counter.
uint64_t getCurrentProfileCount() { return PGO.getCurrentRegionCount(); }
+ /// See CGDebugInfo::addInstToCurrentSourceAtom.
+ void addInstToCurrentSourceAtom(llvm::Instruction *KeyInstruction,
+ llvm::Value *Backup) {
+ if (CGDebugInfo *DI = getDebugInfo())
+ DI->addInstToCurrentSourceAtom(KeyInstruction, Backup);
+ }
+
+ /// See CGDebugInfo::addRetToOverrideOrNewSourceAtom.
+ void addRetToOverrideOrNewSourceAtom(llvm::ReturnInst *Ret,
+ llvm::Value *Backup) {
+ if (CGDebugInfo *DI = getDebugInfo())
+ DI->addRetToOverrideOrNewSourceAtom(Ret, Backup);
+ }
+
private:
/// SwitchInsn - This is nearest current switch instruction. It is null if
/// current context is not in a switch.
>From 69995e53f547279c887b498a6597043a1d4a8be5 Mon Sep 17 00:00:00 2001
From: Orlando Cazalet-Hyams <orlando.hyams at sony.com>
Date: Tue, 20 May 2025 17:09:56 +0100
Subject: [PATCH 02/33] fix rebase fallout (CGDebugInfo.h removed from this
header)
---
clang/lib/CodeGen/CodeGenFunction.cpp | 12 ++++++++++++
clang/lib/CodeGen/CodeGenFunction.h | 10 ++--------
2 files changed, 14 insertions(+), 8 deletions(-)
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index 4e79cdf0ef089..092346b627e6a 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -3326,3 +3326,15 @@ CodeGenFunction::EmitPointerAuthAuth(const CGPointerAuthInfo &PointerAuth,
return EmitPointerAuthCommon(*this, PointerAuth, Pointer,
llvm::Intrinsic::ptrauth_auth);
}
+
+void CodeGenFunction::addInstToCurrentSourceAtom(
+ llvm::Instruction *KeyInstruction, llvm::Value *Backup) {
+ if (CGDebugInfo *DI = getDebugInfo())
+ DI->addInstToCurrentSourceAtom(KeyInstruction, Backup);
+}
+
+void CodeGenFunction::addRetToOverrideOrNewSourceAtom(llvm::ReturnInst *Ret,
+ llvm::Value *Backup) {
+ if (CGDebugInfo *DI = getDebugInfo())
+ DI->addRetToOverrideOrNewSourceAtom(Ret, Backup);
+}
\ No newline at end of file
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index aec29d4ea61e8..ecd0362dd6f15 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -1742,17 +1742,11 @@ class CodeGenFunction : public CodeGenTypeCache {
/// See CGDebugInfo::addInstToCurrentSourceAtom.
void addInstToCurrentSourceAtom(llvm::Instruction *KeyInstruction,
- llvm::Value *Backup) {
- if (CGDebugInfo *DI = getDebugInfo())
- DI->addInstToCurrentSourceAtom(KeyInstruction, Backup);
- }
+ llvm::Value *Backup);
/// See CGDebugInfo::addRetToOverrideOrNewSourceAtom.
void addRetToOverrideOrNewSourceAtom(llvm::ReturnInst *Ret,
- llvm::Value *Backup) {
- if (CGDebugInfo *DI = getDebugInfo())
- DI->addRetToOverrideOrNewSourceAtom(Ret, Backup);
- }
+ llvm::Value *Backup);
private:
/// SwitchInsn - This is nearest current switch instruction. It is null if
>From 8e7f643e9d6bef7a54f48c33c7938611fe86d497 Mon Sep 17 00:00:00 2001
From: Orlando Cazalet-Hyams <orlando.hyams at sony.com>
Date: Tue, 20 May 2025 17:38:29 +0100
Subject: [PATCH 03/33] replace the ret-override mechanisms with
addInstToSpecificSourceAtom
---
clang/lib/CodeGen/CGDebugInfo.cpp | 31 ++++++---------------------
clang/lib/CodeGen/CGDebugInfo.h | 12 ++++-------
clang/lib/CodeGen/CodeGenFunction.cpp | 6 +++---
clang/lib/CodeGen/CodeGenFunction.h | 6 +++---
4 files changed, 17 insertions(+), 38 deletions(-)
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index f4c5c57a38b3e..1cc2c55a19f11 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -154,11 +154,14 @@ void CGDebugInfo::addInstSourceAtomMetadata(llvm::Instruction *I,
void CGDebugInfo::addInstToCurrentSourceAtom(llvm::Instruction *KeyInstruction,
llvm::Value *Backup) {
- if (!CGM.getCodeGenOpts().DebugKeyInstructions)
- return;
+ addInstToSpecificSourceAtom(KeyInstruction, Backup,
+ KeyInstructionsInfo.CurrentAtom);
+}
- uint64_t Group = KeyInstructionsInfo.CurrentAtom;
- if (!Group)
+void CGDebugInfo::addInstToSpecificSourceAtom(llvm::Instruction *KeyInstruction,
+ llvm::Value *Backup,
+ uint64_t Group) {
+ if (!Group || !CGM.getCodeGenOpts().DebugKeyInstructions)
return;
addInstSourceAtomMetadata(KeyInstruction, Group, /*Rank=*/1);
@@ -183,31 +186,11 @@ void CGDebugInfo::addInstToCurrentSourceAtom(llvm::Instruction *KeyInstruction,
}
}
-void CGDebugInfo::addRetToOverrideOrNewSourceAtom(llvm::ReturnInst *Ret,
- llvm::Value *Backup) {
- if (KeyInstructionsInfo.RetAtomOverride) {
- uint64_t CurrentAtom = KeyInstructionsInfo.CurrentAtom;
- KeyInstructionsInfo.CurrentAtom = KeyInstructionsInfo.RetAtomOverride;
- addInstToCurrentSourceAtom(Ret, Backup);
- KeyInstructionsInfo.CurrentAtom = CurrentAtom;
- KeyInstructionsInfo.RetAtomOverride = 0;
- } else {
- auto Grp = ApplyAtomGroup(this);
- addInstToCurrentSourceAtom(Ret, Backup);
- }
-}
-
-void CGDebugInfo::setRetInstSourceAtomOverride(uint64_t Group) {
- assert(KeyInstructionsInfo.RetAtomOverride == 0);
- KeyInstructionsInfo.RetAtomOverride = Group;
-}
-
void CGDebugInfo::completeFunction() {
// Reset the atom group number tracker as the numbers are function-local.
KeyInstructionsInfo.NextAtom = 1;
KeyInstructionsInfo.HighestEmittedAtom = 0;
KeyInstructionsInfo.CurrentAtom = 0;
- KeyInstructionsInfo.RetAtomOverride = 0;
}
ApplyAtomGroup::ApplyAtomGroup(CGDebugInfo *DI) : DI(DI) {
diff --git a/clang/lib/CodeGen/CGDebugInfo.h b/clang/lib/CodeGen/CGDebugInfo.h
index d9081d9bb3ffb..10739194fd70f 100644
--- a/clang/lib/CodeGen/CGDebugInfo.h
+++ b/clang/lib/CodeGen/CGDebugInfo.h
@@ -188,7 +188,6 @@ class CGDebugInfo {
uint64_t NextAtom = 1;
uint64_t HighestEmittedAtom = 0;
uint64_t CurrentAtom = 0;
- uint64_t RetAtomOverride = 0;
} KeyInstructionsInfo;
private:
@@ -664,13 +663,10 @@ class CGDebugInfo {
void addInstToCurrentSourceAtom(llvm::Instruction *KeyInstruction,
llvm::Value *Backup);
- /// Add \p Ret and an optional \p Backup instruction to the
- /// saved override used for some ret instructions if it exists, or a new atom.
- void addRetToOverrideOrNewSourceAtom(llvm::ReturnInst *Ret,
- llvm::Value *Backup);
-
- /// Set an atom group override for use in addRetToOverrideOrNewSourceAtom.
- void setRetInstSourceAtomOverride(uint64_t Group);
+ /// Add \p KeyInstruction and an optional \p Backup instruction to the atom
+ /// group \p Atom.
+ void addInstToSpecificSourceAtom(llvm::Instruction *KeyInstruction,
+ llvm::Value *Backup, uint64_t Atom);
private:
/// Amend \p I's DebugLoc with \p Group (its source atom group) and \p
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index 092346b627e6a..30bcf782c71e4 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -3333,8 +3333,8 @@ void CodeGenFunction::addInstToCurrentSourceAtom(
DI->addInstToCurrentSourceAtom(KeyInstruction, Backup);
}
-void CodeGenFunction::addRetToOverrideOrNewSourceAtom(llvm::ReturnInst *Ret,
- llvm::Value *Backup) {
+void CodeGenFunction::addInstToSpecificSourceAtom(
+ llvm::Instruction *KeyInstruction, llvm::Value *Backup, uint64_t Atom) {
if (CGDebugInfo *DI = getDebugInfo())
- DI->addRetToOverrideOrNewSourceAtom(Ret, Backup);
+ DI->addInstToSpecificSourceAtom(KeyInstruction, Backup, Atom);
}
\ No newline at end of file
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index ecd0362dd6f15..1743f558b37e9 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -1744,9 +1744,9 @@ class CodeGenFunction : public CodeGenTypeCache {
void addInstToCurrentSourceAtom(llvm::Instruction *KeyInstruction,
llvm::Value *Backup);
- /// See CGDebugInfo::addRetToOverrideOrNewSourceAtom.
- void addRetToOverrideOrNewSourceAtom(llvm::ReturnInst *Ret,
- llvm::Value *Backup);
+ /// See CGDebugInfo::addInstToSpecificSourceAtom.
+ void addInstToSpecificSourceAtom(llvm::Instruction *KeyInstruction,
+ llvm::Value *Backup, uint64_t Atom);
private:
/// SwitchInsn - This is nearest current switch instruction. It is null if
>From ca03a49ab660472728ea3b3e951bf319b8f24f92 Mon Sep 17 00:00:00 2001
From: Orlando Cazalet-Hyams <orlando.hyams at sony.com>
Date: Tue, 20 May 2025 17:43:23 +0100
Subject: [PATCH 04/33] whitespace
---
clang/lib/CodeGen/CodeGenFunction.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index 30bcf782c71e4..2256cc08e2212 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -3337,4 +3337,4 @@ void CodeGenFunction::addInstToSpecificSourceAtom(
llvm::Instruction *KeyInstruction, llvm::Value *Backup, uint64_t Atom) {
if (CGDebugInfo *DI = getDebugInfo())
DI->addInstToSpecificSourceAtom(KeyInstruction, Backup, Atom);
-}
\ No newline at end of file
+}
>From 8534d6e34772867640665bfa3ad3547babd1a12d Mon Sep 17 00:00:00 2001
From: Orlando Cazalet-Hyams <orlando.hyams at sony.com>
Date: Tue, 1 Apr 2025 14:50:41 +0100
Subject: [PATCH 05/33] [KeyInstr][Clang] Scalar init atom
This patch is part of a stack that teaches Clang to generate Key Instructions
metadata for C and C++.
The Key Instructions project is introduced, including a "quick summary" section
at the top which adds context for this PR, here:
https://discourse.llvm.org/t/rfc-improving-is-stmt-placement-for-better-interactive-debugging/82668
The feature is only functional in LLVM if LLVM is built with CMake flag
LLVM_EXPERIMENTAL_KEY_INSTRUCTIONs. Eventually that flag will be removed.
The Clang-side work is demoed here:
https://github.com/llvm/llvm-project/pull/130943
---
clang/lib/CodeGen/CGDecl.cpp | 1 +
clang/lib/CodeGen/CGExpr.cpp | 2 ++
.../DebugInfo/KeyInstructions/init-scalar.c | 19 +++++++++++++++++++
3 files changed, 22 insertions(+)
create mode 100644 clang/test/DebugInfo/KeyInstructions/init-scalar.c
diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp
index 4a8f7f6a42ecb..d02f2ad09d2f1 100644
--- a/clang/lib/CodeGen/CGDecl.cpp
+++ b/clang/lib/CodeGen/CGDecl.cpp
@@ -1925,6 +1925,7 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) {
const VarDecl &D = *emission.Variable;
auto DL = ApplyDebugLocation::CreateDefaultArtificial(*this, D.getLocation());
+ ApplyAtomGroup Grp(getDebugInfo());
QualType type = D.getType();
// If this local has an initializer, emit it now.
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index 708002a7f9ab3..1e426586620a2 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -2222,6 +2222,8 @@ void CodeGenFunction::EmitStoreOfScalar(llvm::Value *Value, Address Addr,
}
llvm::StoreInst *Store = Builder.CreateStore(Value, Addr, Volatile);
+ addInstToCurrentSourceAtom(Store, Value);
+
if (isNontemporal) {
llvm::MDNode *Node =
llvm::MDNode::get(Store->getContext(),
diff --git a/clang/test/DebugInfo/KeyInstructions/init-scalar.c b/clang/test/DebugInfo/KeyInstructions/init-scalar.c
new file mode 100644
index 0000000000000..c212c2a4fd623
--- /dev/null
+++ b/clang/test/DebugInfo/KeyInstructions/init-scalar.c
@@ -0,0 +1,19 @@
+// RUN: %clang -gkey-instructions -x c++ %s -gmlt -gcolumn-info -S -emit-llvm -o - \
+// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank
+
+// RUN: %clang -gkey-instructions -x c %s -gmlt -gcolumn-info -S -emit-llvm -o - \
+// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank
+
+void a() {
+// CHECK: store i32 0, ptr %A{{.*}}, !dbg [[G1R1:!.*]]
+ int A = 0;
+// CHECK: %add = add {{.*}}, !dbg [[G2R2:!.*]]
+// CHECK: store i32 %add, ptr %B, align 4, !dbg [[G2R1:!.*]]
+ int B = 2 * A + 1;
+// CHECK-TODO: ret{{.*}}, !dbg [[G3R1:!.*]]
+}
+
+// CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
+// CHECK: [[G2R2]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 2)
+// CHECK: [[G2R1]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1)
+// CHECK-TODO: [[G3R1]] = !DILocation({{.*}}, atomGroup: 3, atomRank: 1)
>From 2935186830de115687e4841e0d4c3fba4161a177 Mon Sep 17 00:00:00 2001
From: Orlando Cazalet-Hyams <orlando.hyams at sony.com>
Date: Wed, 21 May 2025 10:21:18 +0100
Subject: [PATCH 06/33] use %clang_cc1 in test
---
clang/test/DebugInfo/KeyInstructions/init-scalar.c | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/clang/test/DebugInfo/KeyInstructions/init-scalar.c b/clang/test/DebugInfo/KeyInstructions/init-scalar.c
index c212c2a4fd623..a86c029e47e8c 100644
--- a/clang/test/DebugInfo/KeyInstructions/init-scalar.c
+++ b/clang/test/DebugInfo/KeyInstructions/init-scalar.c
@@ -1,7 +1,7 @@
-// RUN: %clang -gkey-instructions -x c++ %s -gmlt -gcolumn-info -S -emit-llvm -o - \
+// RUN: %clang_cc1 -gkey-instructions -x c++ %s -debug-info-kind=line-tables-only -emit-llvm -o - \
// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank
-// RUN: %clang -gkey-instructions -x c %s -gmlt -gcolumn-info -S -emit-llvm -o - \
+// RUN: %clang_cc1 -gkey-instructions -x c %s -debug-info-kind=line-tables-only -emit-llvm -o - \
// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank
void a() {
@@ -10,10 +10,8 @@ void a() {
// CHECK: %add = add {{.*}}, !dbg [[G2R2:!.*]]
// CHECK: store i32 %add, ptr %B, align 4, !dbg [[G2R1:!.*]]
int B = 2 * A + 1;
-// CHECK-TODO: ret{{.*}}, !dbg [[G3R1:!.*]]
}
// CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
// CHECK: [[G2R2]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 2)
// CHECK: [[G2R1]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1)
-// CHECK-TODO: [[G3R1]] = !DILocation({{.*}}, atomGroup: 3, atomRank: 1)
>From fb714455f4123a40342c472b16dc940d55cd9bdb Mon Sep 17 00:00:00 2001
From: Orlando Cazalet-Hyams <orlando.hyams at sony.com>
Date: Tue, 1 Apr 2025 15:40:58 +0100
Subject: [PATCH 07/33] [KeyInstr][Clang] Agg init atom
This patch is part of a stack that teaches Clang to generate Key Instructions
metadata for C and C++.
The Key Instructions project is introduced, including a "quick summary" section
at the top which adds context for this PR, here:
https://discourse.llvm.org/t/rfc-improving-is-stmt-placement-for-better-interactive-debugging/82668
The feature is only functional in LLVM if LLVM is built with CMake flag
LLVM_EXPERIMENTAL_KEY_INSTRUCTIONs. Eventually that flag will be removed.
The Clang-side work is demoed here:
https://github.com/llvm/llvm-project/pull/130943
---
clang/lib/CodeGen/CGDecl.cpp | 2 ++
.../DebugInfo/KeyInstructions/init-agg.cpp | 22 +++++++++++++++++++
2 files changed, 24 insertions(+)
create mode 100644 clang/test/DebugInfo/KeyInstructions/init-agg.cpp
diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp
index d02f2ad09d2f1..8d43d531f6043 100644
--- a/clang/lib/CodeGen/CGDecl.cpp
+++ b/clang/lib/CodeGen/CGDecl.cpp
@@ -1270,6 +1270,8 @@ void CodeGenFunction::emitStoresForConstant(const VarDecl &D, Address Loc,
createUnnamedGlobalForMemcpyFrom(
CGM, D, Builder, constant, Loc.getAlignment()),
SizeVal, isVolatile);
+ addInstToCurrentSourceAtom(I, nullptr);
+
if (IsAutoInit)
I->addAnnotationMetadata("auto-init");
}
diff --git a/clang/test/DebugInfo/KeyInstructions/init-agg.cpp b/clang/test/DebugInfo/KeyInstructions/init-agg.cpp
new file mode 100644
index 0000000000000..b96256b532f3e
--- /dev/null
+++ b/clang/test/DebugInfo/KeyInstructions/init-agg.cpp
@@ -0,0 +1,22 @@
+
+// RUN: %clang -gkey-instructions %s -gmlt -S -emit-llvm -o - \
+// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank
+
+// The implicit-check-not is important; we don't want the GEPs created for the
+// store locations to be included in the atom group.
+
+int g;
+void a() {
+// CHECK: _Z1av()
+// CHECK: call void @llvm.memcpy{{.*}}, !dbg [[G1R1:!.*]]
+ int A[] = { 1, 2, 3 };
+// CHECK: store i32 1, ptr %{{.*}}, !dbg [[G2R1:!.*]]
+// CHECK: store i32 2, ptr %{{.*}}, !dbg [[G2R1]]
+// CHECK: %0 = load i32, ptr @g{{.*}}, !dbg [[G2R2:!.*]]
+// CHECK: store i32 %0, ptr %{{.*}}, !dbg [[G2R1]]
+ int B[] = { 1, 2, g };
+}
+
+// CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
+// CHECK: [[G2R1]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1)
+// CHECK: [[G2R2]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 2)
>From 253508197cdd0b6ed1c36fc32d1db38cfa428110 Mon Sep 17 00:00:00 2001
From: Orlando Cazalet-Hyams <orlando.hyams at sony.com>
Date: Tue, 1 Apr 2025 16:45:47 +0100
Subject: [PATCH 08/33] shouldUseBZeroPlusStoresToInitialize
---
clang/lib/CodeGen/CGDecl.cpp | 3 +++
clang/test/DebugInfo/KeyInstructions/init-agg.cpp | 12 +++++++++++-
2 files changed, 14 insertions(+), 1 deletion(-)
diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp
index 8d43d531f6043..bb13c31f8f5e4 100644
--- a/clang/lib/CodeGen/CGDecl.cpp
+++ b/clang/lib/CodeGen/CGDecl.cpp
@@ -945,6 +945,7 @@ void CodeGenFunction::emitStoresForInitAfterBZero(llvm::Constant *Init,
isa<llvm::ConstantVector>(Init) || isa<llvm::BlockAddress>(Init) ||
isa<llvm::ConstantExpr>(Init)) {
auto *I = Builder.CreateStore(Init, Loc, isVolatile);
+ addInstToCurrentSourceAtom(I, nullptr);
if (IsAutoInit)
I->addAnnotationMetadata("auto-init");
return;
@@ -1200,6 +1201,8 @@ void CodeGenFunction::emitStoresForConstant(const VarDecl &D, Address Loc,
if (shouldUseBZeroPlusStoresToInitialize(constant, ConstantSize)) {
auto *I = Builder.CreateMemSet(Loc, llvm::ConstantInt::get(CGM.Int8Ty, 0),
SizeVal, isVolatile);
+ addInstToCurrentSourceAtom(I, nullptr);
+
if (IsAutoInit)
I->addAnnotationMetadata("auto-init");
diff --git a/clang/test/DebugInfo/KeyInstructions/init-agg.cpp b/clang/test/DebugInfo/KeyInstructions/init-agg.cpp
index b96256b532f3e..854af3237ed98 100644
--- a/clang/test/DebugInfo/KeyInstructions/init-agg.cpp
+++ b/clang/test/DebugInfo/KeyInstructions/init-agg.cpp
@@ -1,22 +1,32 @@
-// RUN: %clang -gkey-instructions %s -gmlt -S -emit-llvm -o - \
+// RUN: %clang -gkey-instructions %s -gmlt -gno-column-info -S -emit-llvm -o - \
// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank
// The implicit-check-not is important; we don't want the GEPs created for the
// store locations to be included in the atom group.
int g;
+char gc;
void a() {
// CHECK: _Z1av()
// CHECK: call void @llvm.memcpy{{.*}}, !dbg [[G1R1:!.*]]
int A[] = { 1, 2, 3 };
+
// CHECK: store i32 1, ptr %{{.*}}, !dbg [[G2R1:!.*]]
// CHECK: store i32 2, ptr %{{.*}}, !dbg [[G2R1]]
// CHECK: %0 = load i32, ptr @g{{.*}}, !dbg [[G2R2:!.*]]
// CHECK: store i32 %0, ptr %{{.*}}, !dbg [[G2R1]]
int B[] = { 1, 2, g };
+
+// CHECK: call void @llvm.memset{{.*}}, !dbg [[G3R1:!.*]]
+// CHECK: store i8 97{{.*}}, !dbg [[G3R1]]
+// CHECK: store i8 98{{.*}}, !dbg [[G3R1]]
+// CHECK: store i8 99{{.*}}, !dbg [[G3R1]]
+// CHECK: store i8 100{{.*}}, !dbg [[G3R1]]
+ char big[65536] = { 'a', 'b', 'c', 'd' };
}
// CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
// CHECK: [[G2R1]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1)
// CHECK: [[G2R2]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 2)
+// CHECK: [[G3R1]] = !DILocation({{.*}}, atomGroup: 3, atomRank: 1)
\ No newline at end of file
>From 1171d504c557c81d0d905940dda9b80d98c2f9dc Mon Sep 17 00:00:00 2001
From: Orlando Cazalet-Hyams <orlando.hyams at sony.com>
Date: Tue, 1 Apr 2025 17:08:43 +0100
Subject: [PATCH 09/33] [KeyInstr] init-agg pattern
---
clang/lib/CodeGen/CGDecl.cpp | 1 +
clang/test/DebugInfo/KeyInstructions/init-agg.cpp | 7 +++++--
2 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp
index bb13c31f8f5e4..47d963123021b 100644
--- a/clang/lib/CodeGen/CGDecl.cpp
+++ b/clang/lib/CodeGen/CGDecl.cpp
@@ -1227,6 +1227,7 @@ void CodeGenFunction::emitStoresForConstant(const VarDecl &D, Address Loc,
}
auto *I = Builder.CreateMemSet(
Loc, llvm::ConstantInt::get(CGM.Int8Ty, Value), SizeVal, isVolatile);
+ addInstToCurrentSourceAtom(I, nullptr);
if (IsAutoInit)
I->addAnnotationMetadata("auto-init");
return;
diff --git a/clang/test/DebugInfo/KeyInstructions/init-agg.cpp b/clang/test/DebugInfo/KeyInstructions/init-agg.cpp
index 854af3237ed98..e2f12d73a4ecd 100644
--- a/clang/test/DebugInfo/KeyInstructions/init-agg.cpp
+++ b/clang/test/DebugInfo/KeyInstructions/init-agg.cpp
@@ -6,7 +6,6 @@
// store locations to be included in the atom group.
int g;
-char gc;
void a() {
// CHECK: _Z1av()
// CHECK: call void @llvm.memcpy{{.*}}, !dbg [[G1R1:!.*]]
@@ -24,9 +23,13 @@ void a() {
// CHECK: store i8 99{{.*}}, !dbg [[G3R1]]
// CHECK: store i8 100{{.*}}, !dbg [[G3R1]]
char big[65536] = { 'a', 'b', 'c', 'd' };
+
+// CHECK: call void @llvm.memset{{.*}}, !dbg [[G4R1:!.*]]
+ char arr[] = { 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, };
}
// CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
// CHECK: [[G2R1]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1)
// CHECK: [[G2R2]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 2)
-// CHECK: [[G3R1]] = !DILocation({{.*}}, atomGroup: 3, atomRank: 1)
\ No newline at end of file
+// CHECK: [[G3R1]] = !DILocation({{.*}}, atomGroup: 3, atomRank: 1)
+// CHECK: [[G4R1]] = !DILocation({{.*}}, atomGroup: 4, atomRank: 1)
>From a7fa7b7d0b90b377e427183b1824ac4cd1403f4a Mon Sep 17 00:00:00 2001
From: Orlando Cazalet-Hyams <orlando.hyams at sony.com>
Date: Wed, 2 Apr 2025 09:54:30 +0100
Subject: [PATCH 10/33] [KeyInstr][Clang] Init pattern atom
---
clang/lib/CodeGen/CGDecl.cpp | 1 +
clang/test/DebugInfo/KeyInstructions/init-agg.cpp | 6 +++++-
2 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp
index 47d963123021b..18135384021e8 100644
--- a/clang/lib/CodeGen/CGDecl.cpp
+++ b/clang/lib/CodeGen/CGDecl.cpp
@@ -1189,6 +1189,7 @@ void CodeGenFunction::emitStoresForConstant(const VarDecl &D, Address Loc,
Ty->isPtrOrPtrVectorTy() || Ty->isFPOrFPVectorTy();
if (canDoSingleStore) {
auto *I = Builder.CreateStore(constant, Loc, isVolatile);
+ addInstToCurrentSourceAtom(I, nullptr);
if (IsAutoInit)
I->addAnnotationMetadata("auto-init");
return;
diff --git a/clang/test/DebugInfo/KeyInstructions/init-agg.cpp b/clang/test/DebugInfo/KeyInstructions/init-agg.cpp
index e2f12d73a4ecd..f0cc67e659d95 100644
--- a/clang/test/DebugInfo/KeyInstructions/init-agg.cpp
+++ b/clang/test/DebugInfo/KeyInstructions/init-agg.cpp
@@ -1,5 +1,5 @@
-// RUN: %clang -gkey-instructions %s -gmlt -gno-column-info -S -emit-llvm -o - \
+// RUN: %clang -gkey-instructions %s -gmlt -gno-column-info -S -emit-llvm -o - -ftrivial-auto-var-init=pattern \
// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank
// The implicit-check-not is important; we don't want the GEPs created for the
@@ -26,6 +26,9 @@ void a() {
// CHECK: call void @llvm.memset{{.*}}, !dbg [[G4R1:!.*]]
char arr[] = { 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, };
+
+// CHECK: store i8 -86, ptr %uninit{{.*}}, !dbg [[G5R1:!.*]], !annotation
+ char uninit; // -ftrivial-auto-var-init=pattern
}
// CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
@@ -33,3 +36,4 @@ void a() {
// CHECK: [[G2R2]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 2)
// CHECK: [[G3R1]] = !DILocation({{.*}}, atomGroup: 3, atomRank: 1)
// CHECK: [[G4R1]] = !DILocation({{.*}}, atomGroup: 4, atomRank: 1)
+// CHECK: [[G5R1]] = !DILocation({{.*}}, atomGroup: 5, atomRank: 1)
>From 17837fd9abb03cc08f85be13f1fea586bf194dfb Mon Sep 17 00:00:00 2001
From: Orlando Cazalet-Hyams <orlando.hyams at sony.com>
Date: Wed, 21 May 2025 11:24:57 +0100
Subject: [PATCH 11/33] use %clang_cc1
---
clang/test/DebugInfo/KeyInstructions/init-agg.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/test/DebugInfo/KeyInstructions/init-agg.cpp b/clang/test/DebugInfo/KeyInstructions/init-agg.cpp
index f0cc67e659d95..e5025e51c1df3 100644
--- a/clang/test/DebugInfo/KeyInstructions/init-agg.cpp
+++ b/clang/test/DebugInfo/KeyInstructions/init-agg.cpp
@@ -1,5 +1,5 @@
-// RUN: %clang -gkey-instructions %s -gmlt -gno-column-info -S -emit-llvm -o - -ftrivial-auto-var-init=pattern \
+// RUN: %clang_cc1 -gkey-instructions %s -debug-info-kind=line-tables-only -gno-column-info -emit-llvm -o - -ftrivial-auto-var-init=pattern \
// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank
// The implicit-check-not is important; we don't want the GEPs created for the
>From 16e88e1e81bd7519d79002117040d2d9bbdb0424 Mon Sep 17 00:00:00 2001
From: Orlando Cazalet-Hyams <orlando.hyams at sony.com>
Date: Wed, 21 May 2025 11:49:48 +0100
Subject: [PATCH 12/33] test nits
---
.../DebugInfo/KeyInstructions/init-agg.cpp | 18 ++++++++++++------
1 file changed, 12 insertions(+), 6 deletions(-)
diff --git a/clang/test/DebugInfo/KeyInstructions/init-agg.cpp b/clang/test/DebugInfo/KeyInstructions/init-agg.cpp
index e5025e51c1df3..d3310b68429bc 100644
--- a/clang/test/DebugInfo/KeyInstructions/init-agg.cpp
+++ b/clang/test/DebugInfo/KeyInstructions/init-agg.cpp
@@ -8,20 +8,25 @@
int g;
void a() {
// CHECK: _Z1av()
-// CHECK: call void @llvm.memcpy{{.*}}, !dbg [[G1R1:!.*]]
+// CHECK: call void @llvm.memcpy{{.*}}%A, {{.*}}@__const._Z1av.A{{.*}}, !dbg [[G1R1:!.*]]
int A[] = { 1, 2, 3 };
+// CHECK: call void @llvm.memcpy{{.*}}%B, {{.*}}@__const._Z1av.B{{.*}}, !dbg [[G2R1:!.*]]
// CHECK: store i32 1, ptr %{{.*}}, !dbg [[G2R1:!.*]]
// CHECK: store i32 2, ptr %{{.*}}, !dbg [[G2R1]]
// CHECK: %0 = load i32, ptr @g{{.*}}, !dbg [[G2R2:!.*]]
// CHECK: store i32 %0, ptr %{{.*}}, !dbg [[G2R1]]
int B[] = { 1, 2, g };
-// CHECK: call void @llvm.memset{{.*}}, !dbg [[G3R1:!.*]]
-// CHECK: store i8 97{{.*}}, !dbg [[G3R1]]
-// CHECK: store i8 98{{.*}}, !dbg [[G3R1]]
-// CHECK: store i8 99{{.*}}, !dbg [[G3R1]]
-// CHECK: store i8 100{{.*}}, !dbg [[G3R1]]
+// CHECK: call void @llvm.memset{{.*}}, !dbg [[G3R1:!.*]]
+// CHECK-NEXT: %1 = getelementptr {{.*}}, ptr %big, i32 0, i32 0, !dbg [[LINE30:!.*]]
+// CHECK-NEXT: store i8 97, ptr %1{{.*}}, !dbg [[G3R1]]
+// CHECK-NEXT: %2 = getelementptr {{.*}}, ptr %big, i32 0, i32 1, !dbg [[LINE30]]
+// CHECK-NEXT: store i8 98, ptr %2{{.*}} !dbg [[G3R1]]
+// CHECK-NEXT: %3 = getelementptr {{.*}}, ptr %big, i32 0, i32 2, !dbg [[LINE30]]
+// CHECK-NEXT: store i8 99, ptr %3{{.*}} !dbg [[G3R1]]
+// CHECK-NEXT: %4 = getelementptr {{.*}}, ptr %big, i32 0, i32 3, !dbg [[LINE30]]
+// CHECK: store i8 100, ptr %4{{.*}} !dbg [[G3R1]]
char big[65536] = { 'a', 'b', 'c', 'd' };
// CHECK: call void @llvm.memset{{.*}}, !dbg [[G4R1:!.*]]
@@ -35,5 +40,6 @@ void a() {
// CHECK: [[G2R1]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1)
// CHECK: [[G2R2]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 2)
// CHECK: [[G3R1]] = !DILocation({{.*}}, atomGroup: 3, atomRank: 1)
+// CHECK: [[LINE30]] = !DILocation(line: 30, scope: ![[#]])
// CHECK: [[G4R1]] = !DILocation({{.*}}, atomGroup: 4, atomRank: 1)
// CHECK: [[G5R1]] = !DILocation({{.*}}, atomGroup: 5, atomRank: 1)
>From ed55fe5f266013b56ffe474f5a71d803b8068e15 Mon Sep 17 00:00:00 2001
From: Orlando Cazalet-Hyams <orlando.hyams at sony.com>
Date: Wed, 21 May 2025 14:36:21 +0100
Subject: [PATCH 13/33] improve test a bit more
---
.../DebugInfo/KeyInstructions/init-agg.cpp | 31 ++++++++++---------
1 file changed, 17 insertions(+), 14 deletions(-)
diff --git a/clang/test/DebugInfo/KeyInstructions/init-agg.cpp b/clang/test/DebugInfo/KeyInstructions/init-agg.cpp
index d3310b68429bc..5446aae155d63 100644
--- a/clang/test/DebugInfo/KeyInstructions/init-agg.cpp
+++ b/clang/test/DebugInfo/KeyInstructions/init-agg.cpp
@@ -11,25 +11,27 @@ void a() {
// CHECK: call void @llvm.memcpy{{.*}}%A, {{.*}}@__const._Z1av.A{{.*}}, !dbg [[G1R1:!.*]]
int A[] = { 1, 2, 3 };
-// CHECK: call void @llvm.memcpy{{.*}}%B, {{.*}}@__const._Z1av.B{{.*}}, !dbg [[G2R1:!.*]]
-// CHECK: store i32 1, ptr %{{.*}}, !dbg [[G2R1:!.*]]
-// CHECK: store i32 2, ptr %{{.*}}, !dbg [[G2R1]]
-// CHECK: %0 = load i32, ptr @g{{.*}}, !dbg [[G2R2:!.*]]
-// CHECK: store i32 %0, ptr %{{.*}}, !dbg [[G2R1]]
+// CHECK: call void @llvm.memcpy{{.*}}%B, {{.*}}@__const._Z1av.B{{.*}}, !dbg [[G2R1:!.*]]
+// CHECK-NEXT: store i32 1, ptr %B{{.*}}, !dbg [[G2R1:!.*]]
+// CHECK-NEXT: %arrayinit.element = getelementptr {{.*}}, ptr %B, i64 1, !dbg [[B_LINE:!.*]]
+// CHECK-NEXT: store i32 2, ptr %arrayinit.element{{.*}}, !dbg [[G2R1]]
+// CHECK-NEXT: %arrayinit.element1 = getelementptr {{.*}}, ptr %B, i64 2, !dbg [[B_LINE]]
+// CHECK-NEXT: %0 = load i32, ptr @g{{.*}}, !dbg [[G2R2:!.*]]
+// CHECK-NEXT: store i32 %0, ptr %arrayinit.element1{{.*}}, !dbg [[G2R1]]
int B[] = { 1, 2, g };
-// CHECK: call void @llvm.memset{{.*}}, !dbg [[G3R1:!.*]]
-// CHECK-NEXT: %1 = getelementptr {{.*}}, ptr %big, i32 0, i32 0, !dbg [[LINE30:!.*]]
+// CHECK: call void @llvm.memset{{.*}}%big{{.*}} !dbg [[G3R1:!.*]]
+// CHECK-NEXT: %1 = getelementptr {{.*}}, ptr %big, i32 0, i32 0, !dbg [[big_LINE:!.*]]
// CHECK-NEXT: store i8 97, ptr %1{{.*}}, !dbg [[G3R1]]
-// CHECK-NEXT: %2 = getelementptr {{.*}}, ptr %big, i32 0, i32 1, !dbg [[LINE30]]
-// CHECK-NEXT: store i8 98, ptr %2{{.*}} !dbg [[G3R1]]
-// CHECK-NEXT: %3 = getelementptr {{.*}}, ptr %big, i32 0, i32 2, !dbg [[LINE30]]
-// CHECK-NEXT: store i8 99, ptr %3{{.*}} !dbg [[G3R1]]
-// CHECK-NEXT: %4 = getelementptr {{.*}}, ptr %big, i32 0, i32 3, !dbg [[LINE30]]
+// CHECK-NEXT: %2 = getelementptr {{.*}}, ptr %big, i32 0, i32 1, !dbg [[big_LINE]]
+// CHECK-NEXT: store i8 98, ptr %2{{.*}}, !dbg [[G3R1]]
+// CHECK-NEXT: %3 = getelementptr {{.*}}, ptr %big, i32 0, i32 2, !dbg [[big_LINE]]
+// CHECK-NEXT: store i8 99, ptr %3{{.*}}, !dbg [[G3R1]]
+// CHECK-NEXT: %4 = getelementptr {{.*}}, ptr %big, i32 0, i32 3, !dbg [[big_LINE]]
// CHECK: store i8 100, ptr %4{{.*}} !dbg [[G3R1]]
char big[65536] = { 'a', 'b', 'c', 'd' };
-// CHECK: call void @llvm.memset{{.*}}, !dbg [[G4R1:!.*]]
+// CHECK: call void @llvm.memset{{.*}}%arr{{.*}}, !dbg [[G4R1:!.*]]
char arr[] = { 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, };
// CHECK: store i8 -86, ptr %uninit{{.*}}, !dbg [[G5R1:!.*]], !annotation
@@ -38,8 +40,9 @@ void a() {
// CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
// CHECK: [[G2R1]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1)
+// CHECK: [[B_LINE]] = !DILocation(line: 21, scope: ![[#]])
// CHECK: [[G2R2]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 2)
// CHECK: [[G3R1]] = !DILocation({{.*}}, atomGroup: 3, atomRank: 1)
-// CHECK: [[LINE30]] = !DILocation(line: 30, scope: ![[#]])
+// CHECK: [[big_LINE]] = !DILocation(line: 32, scope: ![[#]])
// CHECK: [[G4R1]] = !DILocation({{.*}}, atomGroup: 4, atomRank: 1)
// CHECK: [[G5R1]] = !DILocation({{.*}}, atomGroup: 5, atomRank: 1)
>From 76da803ee981898895061e5f9057c4e7a9de2921 Mon Sep 17 00:00:00 2001
From: Orlando Cazalet-Hyams <orlando.hyams at sony.com>
Date: Wed, 2 Apr 2025 17:42:48 +0100
Subject: [PATCH 14/33] [KeyInstr][Clang] Static variable init atom
This patch is part of a stack that teaches Clang to generate Key Instructions
metadata for C and C++.
The Key Instructions project is introduced, including a "quick summary" section
at the top which adds context for this PR, here:
https://discourse.llvm.org/t/rfc-improving-is-stmt-placement-for-better-interactive-debugging/82668
The feature is only functional in LLVM if LLVM is built with CMake flag
LLVM_EXPERIMENTAL_KEY_INSTRUCTIONs. Eventually that flag will be removed.
The Clang-side work is demoed here:
https://github.com/llvm/llvm-project/pull/130943
---
clang/lib/CodeGen/CGDecl.cpp | 4 +++-
clang/test/DebugInfo/KeyInstructions/init-static.cpp | 12 ++++++++++++
2 files changed, 15 insertions(+), 1 deletion(-)
create mode 100644 clang/test/DebugInfo/KeyInstructions/init-static.cpp
diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp
index 18135384021e8..f4549ab3033b2 100644
--- a/clang/lib/CodeGen/CGDecl.cpp
+++ b/clang/lib/CodeGen/CGDecl.cpp
@@ -429,8 +429,10 @@ void CodeGenFunction::EmitStaticVarDecl(const VarDecl &D,
bool isCudaSharedVar = getLangOpts().CUDA && getLangOpts().CUDAIsDevice &&
D.hasAttr<CUDASharedAttr>();
// If this value has an initializer, emit it.
- if (D.getInit() && !isCudaSharedVar)
+ if (D.getInit() && !isCudaSharedVar) {
+ ApplyAtomGroup Grp(getDebugInfo());
var = AddInitializerToStaticVarDecl(D, var);
+ }
var->setAlignment(alignment.getAsAlign());
diff --git a/clang/test/DebugInfo/KeyInstructions/init-static.cpp b/clang/test/DebugInfo/KeyInstructions/init-static.cpp
new file mode 100644
index 0000000000000..82e14b59df5e5
--- /dev/null
+++ b/clang/test/DebugInfo/KeyInstructions/init-static.cpp
@@ -0,0 +1,12 @@
+// RUN: %clang -gkey-instructions %s -gmlt -gcolumn-info -S -emit-llvm -o -\
+// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank
+
+void g(int *a) {
+ // CHECK: %2 = load ptr, ptr %a.addr{{.*}}, !dbg [[G1R2:!.*]]
+ // CHECK: store ptr %2, ptr @_ZZ1gPiE1b{{.*}}, !dbg [[G1R1:!.*]]
+ static int &b = *a;
+}
+
+// CHECK: [[G1R2]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 2)
+// CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
+
>From 4e082dd8397a469b8af9c69964405ec0e1f0701a Mon Sep 17 00:00:00 2001
From: Orlando Cazalet-Hyams <orlando.hyams at sony.com>
Date: Wed, 21 May 2025 14:41:31 +0100
Subject: [PATCH 15/33] cc1
---
clang/test/DebugInfo/KeyInstructions/init-static.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/test/DebugInfo/KeyInstructions/init-static.cpp b/clang/test/DebugInfo/KeyInstructions/init-static.cpp
index 82e14b59df5e5..745303a3c9d58 100644
--- a/clang/test/DebugInfo/KeyInstructions/init-static.cpp
+++ b/clang/test/DebugInfo/KeyInstructions/init-static.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang -gkey-instructions %s -gmlt -gcolumn-info -S -emit-llvm -o -\
+// RUN: %clang_cc1 -gkey-instructions %s -debug-info-kind=line-tables-only -emit-llvm -o -\
// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank
void g(int *a) {
>From 3b4ca1b09a659e575e022109fd8c607c9df3864f Mon Sep 17 00:00:00 2001
From: Orlando Cazalet-Hyams <orlando.hyams at sony.com>
Date: Wed, 2 Apr 2025 18:01:48 +0100
Subject: [PATCH 16/33] [KeyInstr][Clang] Assignment atom group
This patch is part of a stack that teaches Clang to generate Key Instructions
metadata for C and C++.
The Key Instructions project is introduced, including a "quick summary" section
at the top which adds context for this PR, here:
https://discourse.llvm.org/t/rfc-improving-is-stmt-placement-for-better-interactive-debugging/82668
The feature is only functional in LLVM if LLVM is built with CMake flag
LLVM_EXPERIMENTAL_KEY_INSTRUCTIONs. Eventually that flag will be removed.
The Clang-side work is demoed here:
https://github.com/llvm/llvm-project/pull/130943
---
clang/lib/CodeGen/CGExpr.cpp | 9 +++++++++
clang/test/DebugInfo/KeyInstructions/assign.cpp | 9 +++++++++
2 files changed, 18 insertions(+)
create mode 100644 clang/test/DebugInfo/KeyInstructions/assign.cpp
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index 1e426586620a2..9681fd9325fa7 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -5985,6 +5985,15 @@ LValue CodeGenFunction::EmitBinaryOperatorLValue(const BinaryOperator *E) {
assert(E->getOpcode() == BO_Assign && "unexpected binary l-value");
+ // This covers both LHS and RHS expressions, though nested RHS
+ // expressions may get subsequently separately grouped.
+ // FIXME(OCH): Not clear yet if we've got fine enough control
+ // to pick and choose when we need to. Currently looks ok:
+ // a = b = c -> Two atoms.
+ // x = new(1) -> One atom (for both addr store and value store).
+ // Complex and agg assignment -> One atom.
+ ApplyAtomGroup Grp(getDebugInfo());
+
// Note that in all of these cases, __block variables need the RHS
// evaluated first just in case the variable gets moved by the RHS.
diff --git a/clang/test/DebugInfo/KeyInstructions/assign.cpp b/clang/test/DebugInfo/KeyInstructions/assign.cpp
new file mode 100644
index 0000000000000..b09137430156f
--- /dev/null
+++ b/clang/test/DebugInfo/KeyInstructions/assign.cpp
@@ -0,0 +1,9 @@
+// RUN: %clang -gkey-instructions %s -gmlt -gcolumn-info -S -emit-llvm -o - -Wno-unused-variable \
+// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank
+
+unsigned long long g;
+void fun() { g = 0; }
+
+// CHECK: store i64 0, ptr @g{{.*}}, !dbg [[G1R1:!.*]]
+
+// CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
>From b6274d2afefac7c4546ba5b295b01ce2a3fa74d9 Mon Sep 17 00:00:00 2001
From: Orlando Cazalet-Hyams <orlando.hyams at sony.com>
Date: Wed, 2 Apr 2025 18:27:59 +0100
Subject: [PATCH 17/33] [KeyInstr][Clang] Multiple assignment (x = y = z)
---
clang/lib/CodeGen/CGExprScalar.cpp | 1 +
.../test/DebugInfo/KeyInstructions/assign.cpp | 18 ++++++++++++++++--
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp
index 5d618658bc615..1cc5c147c595b 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -5067,6 +5067,7 @@ llvm::Value *CodeGenFunction::EmitWithOriginalRHSBitfieldAssignment(
}
Value *ScalarExprEmitter::VisitBinAssign(const BinaryOperator *E) {
+ ApplyAtomGroup Grp(CGF.getDebugInfo());
bool Ignore = TestAndClearIgnoreResultAssign();
Value *RHS;
diff --git a/clang/test/DebugInfo/KeyInstructions/assign.cpp b/clang/test/DebugInfo/KeyInstructions/assign.cpp
index b09137430156f..d50062d21935b 100644
--- a/clang/test/DebugInfo/KeyInstructions/assign.cpp
+++ b/clang/test/DebugInfo/KeyInstructions/assign.cpp
@@ -2,8 +2,22 @@
// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank
unsigned long long g;
-void fun() { g = 0; }
-
+void fun() {
// CHECK: store i64 0, ptr @g{{.*}}, !dbg [[G1R1:!.*]]
+ g = 0;
+
+// Treat the two assignments as two atoms.
+//
+// FIXME: Because of the atomGroup implementation the load can only be
+// associated with one of the two stores, despite being a good backup
+// loction for both.
+// CHECK-NEXT: %0 = load i64, ptr @g{{.*}}, !dbg [[G2R2:!.*]]
+// CHECK-NEXT: store i64 %0, ptr @g{{.*}}, !dbg [[G3R1:!.*]]
+// CHECK-NEXT: store i64 %0, ptr @g{{.*}}, !dbg [[G2R1:!.*]]
+ g = g = g;
+}
// CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
+// CHECK: [[G2R2]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 2)
+// CHECK: [[G3R1]] = !DILocation({{.*}}, atomGroup: 3, atomRank: 1)
+// CHECK: [[G2R1]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1)
>From 0ce86c40443015f1f84d7e75dc60cf3e6fe6f7fa Mon Sep 17 00:00:00 2001
From: Orlando Cazalet-Hyams <orlando.hyams at sony.com>
Date: Thu, 3 Apr 2025 11:05:29 +0100
Subject: [PATCH 18/33] Compound assign
---
clang/lib/CodeGen/CGExprScalar.cpp | 2 ++
.../DebugInfo/KeyInstructions/assign-scalar.c | 34 +++++++++++++++++++
.../test/DebugInfo/KeyInstructions/assign.cpp | 13 ++++++-
3 files changed, 48 insertions(+), 1 deletion(-)
create mode 100644 clang/test/DebugInfo/KeyInstructions/assign-scalar.c
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp
index 1cc5c147c595b..366393dbdaf15 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -898,6 +898,7 @@ class ScalarExprEmitter
return result; \
} \
Value *VisitBin##OP##Assign(const CompoundAssignOperator *E) { \
+ ApplyAtomGroup Grp(CGF.getDebugInfo()); \
return EmitCompoundAssign(E, &ScalarExprEmitter::Emit##OP); \
}
HANDLEBINOP(Mul)
@@ -5850,6 +5851,7 @@ LValue CodeGenFunction::EmitObjCIsaExpr(const ObjCIsaExpr *E) {
LValue CodeGenFunction::EmitCompoundAssignmentLValue(
const CompoundAssignOperator *E) {
+ ApplyAtomGroup Grp(getDebugInfo());
ScalarExprEmitter Scalar(*this);
Value *Result = nullptr;
switch (E->getOpcode()) {
diff --git a/clang/test/DebugInfo/KeyInstructions/assign-scalar.c b/clang/test/DebugInfo/KeyInstructions/assign-scalar.c
new file mode 100644
index 0000000000000..1e08195b06eb5
--- /dev/null
+++ b/clang/test/DebugInfo/KeyInstructions/assign-scalar.c
@@ -0,0 +1,34 @@
+// RUN: %clang -gkey-instructions -x c++ %s -gmlt -gcolumn-info -S -emit-llvm -o - -Wno-unused-variable \
+// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank
+
+// RUN: %clang -gkey-instructions -x c %s -gmlt -gcolumn-info -S -emit-llvm -o - -Wno-unused-variable \
+// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank
+
+unsigned long long g;
+void fun() {
+// CHECK: store i64 0, ptr @g{{.*}}, !dbg [[G1R1:!.*]]
+ g = 0;
+
+// Treat the two assignments as two atoms.
+//
+// FIXME: Because of the atomGroup implementation the load can only be
+// associated with one of the two stores, despite being a good backup
+// loction for both.
+// CHECK-NEXT: %0 = load i64, ptr @g{{.*}}, !dbg [[G2R2:!.*]]
+// CHECK-NEXT: store i64 %0, ptr @g{{.*}}, !dbg [[G3R1:!.*]]
+// CHECK-NEXT: store i64 %0, ptr @g{{.*}}, !dbg [[G2R1:!.*]]
+ g = g = g;
+
+// Compound assignment.
+// CHECK: %1 = load i64, ptr @g
+// CHECK: %add = add i64 %1, 50, !dbg [[G4R2:!.*]]
+// CHECK: store i64 %add, ptr @g{{.*}}, !dbg [[G4R1:!.*]]
+ g += 50;
+}
+
+// CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
+// CHECK: [[G2R2]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 2)
+// CHECK: [[G3R1]] = !DILocation({{.*}}, atomGroup: 3, atomRank: 1)
+// CHECK: [[G2R1]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1)
+// CHECK: [[G4R2]] = !DILocation({{.*}}, atomGroup: 4, atomRank: 2)
+// CHECK: [[G4R1]] = !DILocation({{.*}}, atomGroup: 4, atomRank: 1)
diff --git a/clang/test/DebugInfo/KeyInstructions/assign.cpp b/clang/test/DebugInfo/KeyInstructions/assign.cpp
index d50062d21935b..1e08195b06eb5 100644
--- a/clang/test/DebugInfo/KeyInstructions/assign.cpp
+++ b/clang/test/DebugInfo/KeyInstructions/assign.cpp
@@ -1,4 +1,7 @@
-// RUN: %clang -gkey-instructions %s -gmlt -gcolumn-info -S -emit-llvm -o - -Wno-unused-variable \
+// RUN: %clang -gkey-instructions -x c++ %s -gmlt -gcolumn-info -S -emit-llvm -o - -Wno-unused-variable \
+// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank
+
+// RUN: %clang -gkey-instructions -x c %s -gmlt -gcolumn-info -S -emit-llvm -o - -Wno-unused-variable \
// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank
unsigned long long g;
@@ -15,9 +18,17 @@ void fun() {
// CHECK-NEXT: store i64 %0, ptr @g{{.*}}, !dbg [[G3R1:!.*]]
// CHECK-NEXT: store i64 %0, ptr @g{{.*}}, !dbg [[G2R1:!.*]]
g = g = g;
+
+// Compound assignment.
+// CHECK: %1 = load i64, ptr @g
+// CHECK: %add = add i64 %1, 50, !dbg [[G4R2:!.*]]
+// CHECK: store i64 %add, ptr @g{{.*}}, !dbg [[G4R1:!.*]]
+ g += 50;
}
// CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
// CHECK: [[G2R2]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 2)
// CHECK: [[G3R1]] = !DILocation({{.*}}, atomGroup: 3, atomRank: 1)
// CHECK: [[G2R1]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1)
+// CHECK: [[G4R2]] = !DILocation({{.*}}, atomGroup: 4, atomRank: 2)
+// CHECK: [[G4R1]] = !DILocation({{.*}}, atomGroup: 4, atomRank: 1)
>From 1ccc74bc5b36e1444f0c646320dd756dfb134b89 Mon Sep 17 00:00:00 2001
From: Orlando Cazalet-Hyams <orlando.hyams at sony.com>
Date: Thu, 3 Apr 2025 11:12:26 +0100
Subject: [PATCH 19/33] Pre/Post Inc/Dec
---
clang/lib/CodeGen/CGExprScalar.cpp | 1 +
.../test/DebugInfo/KeyInstructions/assign-scalar.c | 14 ++++++++++++++
2 files changed, 15 insertions(+)
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp
index 366393dbdaf15..b9eb12efd6670 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -3015,6 +3015,7 @@ class OMPLastprivateConditionalUpdateRAII {
llvm::Value *
ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
bool isInc, bool isPre) {
+ ApplyAtomGroup Grp(CGF.getDebugInfo());
OMPLastprivateConditionalUpdateRAII OMPRegion(CGF, E);
QualType type = E->getSubExpr()->getType();
llvm::PHINode *atomicPHI = nullptr;
diff --git a/clang/test/DebugInfo/KeyInstructions/assign-scalar.c b/clang/test/DebugInfo/KeyInstructions/assign-scalar.c
index 1e08195b06eb5..1f1fe8fda39e6 100644
--- a/clang/test/DebugInfo/KeyInstructions/assign-scalar.c
+++ b/clang/test/DebugInfo/KeyInstructions/assign-scalar.c
@@ -24,6 +24,16 @@ void fun() {
// CHECK: %add = add i64 %1, 50, !dbg [[G4R2:!.*]]
// CHECK: store i64 %add, ptr @g{{.*}}, !dbg [[G4R1:!.*]]
g += 50;
+
+// Pre/Post Inc/Dec.
+// CHECK: %2 = load i64, ptr @g
+// CHECK: %inc = add i64 %2, 1, !dbg [[G5R2:!.*]]
+// CHECK: store i64 %inc, ptr @g{{.*}}, !dbg [[G5R1:!.*]]
+ ++g;
+// CHECK: %3 = load i64, ptr @g
+// CHECK: %dec = add i64 %3, -1, !dbg [[G6R2:!.*]]
+// CHECK: store i64 %dec, ptr @g{{.*}}, !dbg [[G6R1:!.*]]
+ g--;
}
// CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
@@ -32,3 +42,7 @@ void fun() {
// CHECK: [[G2R1]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1)
// CHECK: [[G4R2]] = !DILocation({{.*}}, atomGroup: 4, atomRank: 2)
// CHECK: [[G4R1]] = !DILocation({{.*}}, atomGroup: 4, atomRank: 1)
+// CHECK: [[G5R2]] = !DILocation({{.*}}, atomGroup: 5, atomRank: 2)
+// CHECK: [[G5R1]] = !DILocation({{.*}}, atomGroup: 5, atomRank: 1)
+// CHECK: [[G6R2]] = !DILocation({{.*}}, atomGroup: 6, atomRank: 2)
+// CHECK: [[G6R1]] = !DILocation({{.*}}, atomGroup: 6, atomRank: 1)
>From 99c0f3a69161ee2a92e063a60fe082e40e89e20f Mon Sep 17 00:00:00 2001
From: Orlando Cazalet-Hyams <orlando.hyams at sony.com>
Date: Thu, 3 Apr 2025 11:27:18 +0100
Subject: [PATCH 20/33] Rename test & run C & C++
---
.../test/DebugInfo/KeyInstructions/init-agg.c | 41 +++++++++++++++++++
1 file changed, 41 insertions(+)
create mode 100644 clang/test/DebugInfo/KeyInstructions/init-agg.c
diff --git a/clang/test/DebugInfo/KeyInstructions/init-agg.c b/clang/test/DebugInfo/KeyInstructions/init-agg.c
new file mode 100644
index 0000000000000..ad298715286cd
--- /dev/null
+++ b/clang/test/DebugInfo/KeyInstructions/init-agg.c
@@ -0,0 +1,41 @@
+
+// RUN: %clang -gkey-instructions -x c++ %s -gmlt -gno-column-info -S -emit-llvm -o - -ftrivial-auto-var-init=pattern \
+// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank
+
+// RUN: %clang -gkey-instructions -x c %s -gmlt -gno-column-info -S -emit-llvm -o - -ftrivial-auto-var-init=pattern \
+// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank
+
+// The implicit-check-not is important; we don't want the GEPs created for the
+// store locations to be included in the atom group.
+
+int g;
+void a() {
+// CHECK: call void @llvm.memcpy{{.*}}, !dbg [[G1R1:!.*]]
+ int A[] = { 1, 2, 3 };
+
+// CHECK: store i32 1, ptr %{{.*}}, !dbg [[G2R1:!.*]]
+// CHECK: store i32 2, ptr %{{.*}}, !dbg [[G2R1]]
+// CHECK: %0 = load i32, ptr @g{{.*}}, !dbg [[G2R2:!.*]]
+// CHECK: store i32 %0, ptr %{{.*}}, !dbg [[G2R1]]
+ int B[] = { 1, 2, g };
+
+// CHECK: call void @llvm.memset{{.*}}, !dbg [[G3R1:!.*]]
+// CHECK: store i8 97{{.*}}, !dbg [[G3R1]]
+// CHECK: store i8 98{{.*}}, !dbg [[G3R1]]
+// CHECK: store i8 99{{.*}}, !dbg [[G3R1]]
+// CHECK: store i8 100{{.*}}, !dbg [[G3R1]]
+ char big[65536] = { 'a', 'b', 'c', 'd' };
+
+// CHECK: call void @llvm.memset{{.*}}, !dbg [[G4R1:!.*]]
+ char arr[] = { 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, };
+
+// CHECK: store i8 -86, ptr %uninit{{.*}}, !dbg [[G5R1:!.*]], !annotation
+ char uninit; // -ftrivial-auto-var-init=pattern
+}
+
+// CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
+// CHECK: [[G2R1]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1)
+// CHECK: [[G2R2]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 2)
+// CHECK: [[G3R1]] = !DILocation({{.*}}, atomGroup: 3, atomRank: 1)
+// CHECK: [[G4R1]] = !DILocation({{.*}}, atomGroup: 4, atomRank: 1)
+// CHECK: [[G5R1]] = !DILocation({{.*}}, atomGroup: 5, atomRank: 1)
>From 6f0135b3afce0539c406feee562dfb27dccb367a Mon Sep 17 00:00:00 2001
From: Orlando Cazalet-Hyams <orlando.hyams at sony.com>
Date: Wed, 21 May 2025 14:55:20 +0100
Subject: [PATCH 21/33] %cc1 and rename a .cpp -> c test
---
clang/test/DebugInfo/KeyInstructions/assign-scalar.c | 4 ++--
clang/test/DebugInfo/KeyInstructions/{assign.cpp => assign.c} | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
rename clang/test/DebugInfo/KeyInstructions/{assign.cpp => assign.c} (85%)
diff --git a/clang/test/DebugInfo/KeyInstructions/assign-scalar.c b/clang/test/DebugInfo/KeyInstructions/assign-scalar.c
index 1f1fe8fda39e6..903402b6d698c 100644
--- a/clang/test/DebugInfo/KeyInstructions/assign-scalar.c
+++ b/clang/test/DebugInfo/KeyInstructions/assign-scalar.c
@@ -1,7 +1,7 @@
-// RUN: %clang -gkey-instructions -x c++ %s -gmlt -gcolumn-info -S -emit-llvm -o - -Wno-unused-variable \
+// RUN: %clang_cc1 -gkey-instructions -x c++ %s -debug-info-kind=line-tables-only -emit-llvm -o - \
// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank
-// RUN: %clang -gkey-instructions -x c %s -gmlt -gcolumn-info -S -emit-llvm -o - -Wno-unused-variable \
+// RUN: %clang_cc1 -gkey-instructions -x c %s -debug-info-kind=line-tables-only -emit-llvm -o - \
// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank
unsigned long long g;
diff --git a/clang/test/DebugInfo/KeyInstructions/assign.cpp b/clang/test/DebugInfo/KeyInstructions/assign.c
similarity index 85%
rename from clang/test/DebugInfo/KeyInstructions/assign.cpp
rename to clang/test/DebugInfo/KeyInstructions/assign.c
index 1e08195b06eb5..d2ce2dceed2f8 100644
--- a/clang/test/DebugInfo/KeyInstructions/assign.cpp
+++ b/clang/test/DebugInfo/KeyInstructions/assign.c
@@ -1,7 +1,7 @@
-// RUN: %clang -gkey-instructions -x c++ %s -gmlt -gcolumn-info -S -emit-llvm -o - -Wno-unused-variable \
+// RUN: %clang_cc1 -gkey-instructions -x c++ %s -debug-info-kind=line-tables-only -emit-llvm -o - \
// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank
-// RUN: %clang -gkey-instructions -x c %s -gmlt -gcolumn-info -S -emit-llvm -o - -Wno-unused-variable \
+// RUN: %clang_cc1 -gkey-instructions -x c %s -debug-info-kind=line-tables-only -emit-llvm -o - \
// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank
unsigned long long g;
>From fd282a63fd709cdcdcdc2dacef58144dbf9b15c1 Mon Sep 17 00:00:00 2001
From: Orlando Cazalet-Hyams <orlando.hyams at sony.com>
Date: Thu, 3 Apr 2025 13:36:59 +0100
Subject: [PATCH 22/33] [KeyInstr] Complex assignment atoms
This patch is part of a stack that teaches Clang to generate Key Instructions
metadata for C and C++.
The Key Instructions project is introduced, including a "quick summary" section
at the top which adds context for this PR, here:
https://discourse.llvm.org/t/rfc-improving-is-stmt-placement-for-better-interactive-debugging/82668
The feature is only functional in LLVM if LLVM is built with CMake flag
LLVM_EXPERIMENTAL_KEY_INSTRUCTIONs. Eventually that flag will be removed.
The Clang-side work is demoed here:
https://github.com/llvm/llvm-project/pull/130943
---
clang/lib/CodeGen/CGExprComplex.cpp | 10 ++++-
.../test/DebugInfo/KeyInstructions/complex.c | 40 +++++++++++++++++++
2 files changed, 48 insertions(+), 2 deletions(-)
create mode 100644 clang/test/DebugInfo/KeyInstructions/complex.c
diff --git a/clang/lib/CodeGen/CGExprComplex.cpp b/clang/lib/CodeGen/CGExprComplex.cpp
index f556594f4a9ec..600f61f1b325f 100644
--- a/clang/lib/CodeGen/CGExprComplex.cpp
+++ b/clang/lib/CodeGen/CGExprComplex.cpp
@@ -461,8 +461,12 @@ void ComplexExprEmitter::EmitStoreOfComplex(ComplexPairTy Val, LValue lvalue,
Address RealPtr = CGF.emitAddrOfRealComponent(Ptr, lvalue.getType());
Address ImagPtr = CGF.emitAddrOfImagComponent(Ptr, lvalue.getType());
- Builder.CreateStore(Val.first, RealPtr, lvalue.isVolatileQualified());
- Builder.CreateStore(Val.second, ImagPtr, lvalue.isVolatileQualified());
+ auto *R =
+ Builder.CreateStore(Val.first, RealPtr, lvalue.isVolatileQualified());
+ CGF.addInstToCurrentSourceAtom(R, Val.first);
+ auto *I =
+ Builder.CreateStore(Val.second, ImagPtr, lvalue.isVolatileQualified());
+ CGF.addInstToCurrentSourceAtom(I, Val.second);
}
@@ -1209,6 +1213,7 @@ LValue ComplexExprEmitter::
EmitCompoundAssignLValue(const CompoundAssignOperator *E,
ComplexPairTy (ComplexExprEmitter::*Func)(const BinOpInfo&),
RValue &Val) {
+ ApplyAtomGroup Grp(CGF.getDebugInfo());
TestAndClearIgnoreReal();
TestAndClearIgnoreImag();
QualType LHSTy = E->getLHS()->getType();
@@ -1356,6 +1361,7 @@ LValue ComplexExprEmitter::EmitBinAssignLValue(const BinaryOperator *E,
}
ComplexPairTy ComplexExprEmitter::VisitBinAssign(const BinaryOperator *E) {
+ ApplyAtomGroup Grp(CGF.getDebugInfo());
ComplexPairTy Val;
LValue LV = EmitBinAssignLValue(E, Val);
diff --git a/clang/test/DebugInfo/KeyInstructions/complex.c b/clang/test/DebugInfo/KeyInstructions/complex.c
new file mode 100644
index 0000000000000..b97314e815bdc
--- /dev/null
+++ b/clang/test/DebugInfo/KeyInstructions/complex.c
@@ -0,0 +1,40 @@
+
+// RUN: %clang -gkey-instructions -x c++ %s -gmlt -gcolumn-info -S -emit-llvm -o - -Wno-unused-variable \
+// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank
+
+// RUN: %clang -gkey-instructions -x c %s -gmlt -gcolumn-info -S -emit-llvm -o - -Wno-unused-variable \
+// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank
+
+_Complex float ci;
+void test() {
+// CHECK: %ci.real = load float, ptr @ci{{.*}}, !dbg [[G1R2:!.*]]
+// CHECK: %ci.imag = load float, ptr getelementptr inbounds nuw ({ float, float }, ptr @ci, i32 0, i32 1){{.*}}, !dbg [[G1R2]]
+// CHECK: store float %ci.real, ptr %lc.realp{{.*}}, !dbg [[G1R1:!.*]]
+// CHECK: store float %ci.imag, ptr %lc.imagp{{.*}}, !dbg [[G1R1]]
+ _Complex float lc = ci;
+
+// CHECK: %ci.real1 = load float, ptr @ci{{.*}}, !dbg [[G2R2:!.*]]
+// CHECK: %ci.imag2 = load float, ptr getelementptr inbounds nuw ({ float, float }, ptr @ci, i32 0, i32 1){{.*}}, !dbg [[G2R2]]
+// CHECK: store float %ci.real1, ptr @ci{{.*}}, !dbg [[G2R1:!.*]]
+// CHECK: store float %ci.imag2, ptr getelementptr inbounds nuw ({ float, float }, ptr @ci, i32 0, i32 1){{.*}}, !dbg [[G2R1]]
+ ci = ci;
+
+// CHECK: %add.r = fadd float %ci.real5, %ci.real3, !dbg [[G3R2:!.*]]
+// CHECK: %add.i = fadd float %ci.imag6, %ci.imag4, !dbg [[G3R2]]
+// CHECK: store float %add.r, ptr @ci{{.*}}, !dbg [[G3R1:!.*]]
+// CHECK: store float %add.i, ptr getelementptr inbounds nuw ({ float, float }, ptr @ci, i32 0, i32 1){{.*}}, !dbg [[G3R1]]
+ ci += ci;
+
+// CHECK: %add = fadd float %0, %1, !dbg [[G4R2:!.*]]
+// CHECK: store float %add, ptr getelementptr inbounds nuw ({ float, float }, ptr @ci, i32 0, i32 1){{.*}}, !dbg [[G4R1:!.*]]
+ __imag ci = __imag ci + __imag ci;
+}
+
+// CHECK: [[G1R2]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 2)
+// CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
+// CHECK: [[G2R2]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 2)
+// CHECK: [[G2R1]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1)
+// CHECK: [[G3R2]] = !DILocation({{.*}}, atomGroup: 3, atomRank: 2)
+// CHECK: [[G3R1]] = !DILocation({{.*}}, atomGroup: 3, atomRank: 1)
+// CHECK: [[G4R2]] = !DILocation({{.*}}, atomGroup: 4, atomRank: 2)
+// CHECK: [[G4R1]] = !DILocation({{.*}}, atomGroup: 4, atomRank: 1)
>From 03a0a1cef3049e16e6f8802275b07e4e49014ad6 Mon Sep 17 00:00:00 2001
From: Orlando Cazalet-Hyams <orlando.hyams at sony.com>
Date: Wed, 21 May 2025 14:58:42 +0100
Subject: [PATCH 23/33] cc1
---
clang/test/DebugInfo/KeyInstructions/complex.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/clang/test/DebugInfo/KeyInstructions/complex.c b/clang/test/DebugInfo/KeyInstructions/complex.c
index b97314e815bdc..f922e5ff71a58 100644
--- a/clang/test/DebugInfo/KeyInstructions/complex.c
+++ b/clang/test/DebugInfo/KeyInstructions/complex.c
@@ -1,8 +1,8 @@
-// RUN: %clang -gkey-instructions -x c++ %s -gmlt -gcolumn-info -S -emit-llvm -o - -Wno-unused-variable \
+// RUN: %clang_cc1 -gkey-instructions -x c++ %s -debug-info-kind=line-tables-only -emit-llvm -o - \
// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank
-// RUN: %clang -gkey-instructions -x c %s -gmlt -gcolumn-info -S -emit-llvm -o - -Wno-unused-variable \
+// RUN: %clang_cc1 -gkey-instructions -x c %s -debug-info-kind=line-tables-only -emit-llvm -o - \
// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank
_Complex float ci;
>From 4ca985019d3884907185a89bda6aed2cc7050135 Mon Sep 17 00:00:00 2001
From: Orlando Cazalet-Hyams <orlando.hyams at sony.com>
Date: Wed, 21 May 2025 15:09:04 +0100
Subject: [PATCH 24/33] whitespace
---
clang/test/DebugInfo/KeyInstructions/complex.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/clang/test/DebugInfo/KeyInstructions/complex.c b/clang/test/DebugInfo/KeyInstructions/complex.c
index f922e5ff71a58..ff8557afb91e7 100644
--- a/clang/test/DebugInfo/KeyInstructions/complex.c
+++ b/clang/test/DebugInfo/KeyInstructions/complex.c
@@ -1,4 +1,3 @@
-
// RUN: %clang_cc1 -gkey-instructions -x c++ %s -debug-info-kind=line-tables-only -emit-llvm -o - \
// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank
>From 46ccd7a165bde6ad72f785551bf57cc7fb590378 Mon Sep 17 00:00:00 2001
From: Orlando Cazalet-Hyams <orlando.hyams at sony.com>
Date: Thu, 3 Apr 2025 15:15:39 +0100
Subject: [PATCH 25/33] [KeyInstr][Clang] Aggregate init + copy
This patch is part of a stack that teaches Clang to generate Key Instructions
metadata for C and C++.
The Key Instructions project is introduced, including a "quick summary" section
at the top which adds context for this PR, here:
https://discourse.llvm.org/t/rfc-improving-is-stmt-placement-for-better-interactive-debugging/82668
The feature is only functional in LLVM if LLVM is built with CMake flag
LLVM_EXPERIMENTAL_KEY_INSTRUCTIONs. Eventually that flag will be removed.
The Clang-side work is demoed here:
https://github.com/llvm/llvm-project/pull/130943
---
clang/lib/CodeGen/CGExprAgg.cpp | 3 ++-
clang/test/DebugInfo/KeyInstructions/agg.c | 12 ++++++++++++
clang/test/DebugInfo/KeyInstructions/init-agg.c | 2 ++
3 files changed, 16 insertions(+), 1 deletion(-)
create mode 100644 clang/test/DebugInfo/KeyInstructions/agg.c
diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp
index e6f18505a7d4d..c683b2a38225d 100644
--- a/clang/lib/CodeGen/CGExprAgg.cpp
+++ b/clang/lib/CodeGen/CGExprAgg.cpp
@@ -2393,7 +2393,8 @@ void CodeGenFunction::EmitAggregateCopy(LValue Dest, LValue Src, QualType Ty,
}
}
- auto Inst = Builder.CreateMemCpy(DestPtr, SrcPtr, SizeVal, isVolatile);
+ auto *Inst = Builder.CreateMemCpy(DestPtr, SrcPtr, SizeVal, isVolatile);
+ addInstToCurrentSourceAtom(Inst, nullptr);
// Determine the metadata to describe the position of any padding in this
// memcpy, as well as the TBAA tags for the members of the struct, in case
diff --git a/clang/test/DebugInfo/KeyInstructions/agg.c b/clang/test/DebugInfo/KeyInstructions/agg.c
new file mode 100644
index 0000000000000..5990859a5b548
--- /dev/null
+++ b/clang/test/DebugInfo/KeyInstructions/agg.c
@@ -0,0 +1,12 @@
+
+// RUN: %clang -gkey-instructions %s -gmlt -S -emit-llvm -o - \
+// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank
+
+typedef struct { int a, b, c; } Struct;
+void fun(Struct a) {
+// CHECK: call void @llvm.memcpy{{.*}}, !dbg [[G1R1:!.*]]
+ Struct b = a;
+}
+
+// CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
+
diff --git a/clang/test/DebugInfo/KeyInstructions/init-agg.c b/clang/test/DebugInfo/KeyInstructions/init-agg.c
index ad298715286cd..dc3ccaedc57b5 100644
--- a/clang/test/DebugInfo/KeyInstructions/init-agg.c
+++ b/clang/test/DebugInfo/KeyInstructions/init-agg.c
@@ -9,6 +9,8 @@
// store locations to be included in the atom group.
int g;
+typedef struct { int a, b, c; } Struct;
+Struct g2;
void a() {
// CHECK: call void @llvm.memcpy{{.*}}, !dbg [[G1R1:!.*]]
int A[] = { 1, 2, 3 };
>From 738d294f757ffeeb4a2ec26cd1f1214b5669c656 Mon Sep 17 00:00:00 2001
From: Orlando Cazalet-Hyams <orlando.hyams at sony.com>
Date: Thu, 3 Apr 2025 16:00:26 +0100
Subject: [PATCH 26/33] [KeyInstr][Clang] Agg copy atom
---
clang/lib/CodeGen/CGExprAgg.cpp | 1 +
clang/lib/CodeGen/CodeGenFunction.h | 1 +
clang/test/DebugInfo/KeyInstructions/agg.c | 11 ++++++++---
3 files changed, 10 insertions(+), 3 deletions(-)
diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp
index c683b2a38225d..cad6731173700 100644
--- a/clang/lib/CodeGen/CGExprAgg.cpp
+++ b/clang/lib/CodeGen/CGExprAgg.cpp
@@ -1332,6 +1332,7 @@ static bool isBlockVarRef(const Expr *E) {
}
void AggExprEmitter::VisitBinAssign(const BinaryOperator *E) {
+ ApplyAtomGroup Grp(CGF.getDebugInfo());
// For an assignment to work, the value on the right has
// to be compatible with the value on the left.
assert(CGF.getContext().hasSameUnqualifiedType(E->getLHS()->getType(),
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index 1743f558b37e9..47ed4e051ca47 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -3035,6 +3035,7 @@ class CodeGenFunction : public CodeGenTypeCache {
/// Emit an aggregate assignment.
void EmitAggregateAssign(LValue Dest, LValue Src, QualType EltTy) {
+ ApplyAtomGroup Grp(getDebugInfo());
bool IsVolatile = hasVolatileMember(EltTy);
EmitAggregateCopy(Dest, Src, EltTy, AggValueSlot::MayOverlap, IsVolatile);
}
diff --git a/clang/test/DebugInfo/KeyInstructions/agg.c b/clang/test/DebugInfo/KeyInstructions/agg.c
index 5990859a5b548..177e1ea8b9fc1 100644
--- a/clang/test/DebugInfo/KeyInstructions/agg.c
+++ b/clang/test/DebugInfo/KeyInstructions/agg.c
@@ -1,12 +1,17 @@
+// RUN: %clang -gkey-instructions -x c++ %s -gmlt -S -emit-llvm -o - \
+// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank
-// RUN: %clang -gkey-instructions %s -gmlt -S -emit-llvm -o - \
+// RUN: %clang -gkey-instructions -x c %s -gmlt -S -emit-llvm -o - \
// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank
typedef struct { int a, b, c; } Struct;
void fun(Struct a) {
-// CHECK: call void @llvm.memcpy{{.*}}, !dbg [[G1R1:!.*]]
+// CHECK: call void @llvm.memcpy{{.*}}, !dbg [[G1R1:!.*]]
Struct b = a;
+
+// CHECK: call void @llvm.memcpy{{.*}}, !dbg [[G2R1:!.*]]
+ b = a;
}
// CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
-
+// CHECK: [[G2R1]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1)
>From 35092c0b650a6e782549d813483d738f5788283f Mon Sep 17 00:00:00 2001
From: Orlando Cazalet-Hyams <orlando.hyams at sony.com>
Date: Wed, 21 May 2025 15:16:33 +0100
Subject: [PATCH 27/33] move ApplyAtomGroup into CodeGenFunction.h
(CGDebugInfo.h no longer included)
---
clang/lib/CodeGen/CGDebugInfo.h | 14 --------------
clang/lib/CodeGen/CodeGenFunction.h | 14 ++++++++++++++
2 files changed, 14 insertions(+), 14 deletions(-)
diff --git a/clang/lib/CodeGen/CGDebugInfo.h b/clang/lib/CodeGen/CGDebugInfo.h
index 10739194fd70f..79d031acbf19e 100644
--- a/clang/lib/CodeGen/CGDebugInfo.h
+++ b/clang/lib/CodeGen/CGDebugInfo.h
@@ -892,20 +892,6 @@ class CGDebugInfo {
}
};
-/// A scoped helper to set the current source atom group for
-/// CGDebugInfo::addInstToCurrentSourceAtom. A source atom is a source construct
-/// that is "interesting" for debug stepping purposes. We use an atom group
-/// number to track the instruction(s) that implement the functionality for the
-/// atom, plus backup instructions/source locations.
-class ApplyAtomGroup {
- uint64_t OriginalAtom = 0;
- CGDebugInfo *DI = nullptr;
-
-public:
- ApplyAtomGroup(CGDebugInfo *DI);
- ~ApplyAtomGroup();
-};
-
/// A scoped helper to set the current debug location to the specified
/// location or preferred location of the specified Expr.
class ApplyDebugLocation {
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index 47ed4e051ca47..78d71fc822bcb 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -258,6 +258,20 @@ template <> struct DominatingValue<RValue> {
}
};
+/// A scoped helper to set the current source atom group for
+/// CGDebugInfo::addInstToCurrentSourceAtom. A source atom is a source construct
+/// that is "interesting" for debug stepping purposes. We use an atom group
+/// number to track the instruction(s) that implement the functionality for the
+/// atom, plus backup instructions/source locations.
+class ApplyAtomGroup {
+ uint64_t OriginalAtom = 0;
+ CGDebugInfo *DI = nullptr;
+
+public:
+ ApplyAtomGroup(CGDebugInfo *DI);
+ ~ApplyAtomGroup();
+};
+
/// CodeGenFunction - This class organizes the per-function state that is used
/// while generating LLVM code.
class CodeGenFunction : public CodeGenTypeCache {
>From a9c75894442b8a6c5ffe8d9330958153f33c2502 Mon Sep 17 00:00:00 2001
From: Orlando Cazalet-Hyams <orlando.hyams at sony.com>
Date: Wed, 21 May 2025 15:19:13 +0100
Subject: [PATCH 28/33] cc1
---
clang/test/DebugInfo/KeyInstructions/agg.c | 4 ++--
clang/test/DebugInfo/KeyInstructions/init-agg.c | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/clang/test/DebugInfo/KeyInstructions/agg.c b/clang/test/DebugInfo/KeyInstructions/agg.c
index 177e1ea8b9fc1..06c9ebbb63369 100644
--- a/clang/test/DebugInfo/KeyInstructions/agg.c
+++ b/clang/test/DebugInfo/KeyInstructions/agg.c
@@ -1,7 +1,7 @@
-// RUN: %clang -gkey-instructions -x c++ %s -gmlt -S -emit-llvm -o - \
+// RUN: %clang_cc1 -gkey-instructions -x c++ %s -debug-info-kind=line-tables-only -emit-llvm -o - \
// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank
-// RUN: %clang -gkey-instructions -x c %s -gmlt -S -emit-llvm -o - \
+// RUN: %clang_cc1 -gkey-instructions -x c %s -debug-info-kind=line-tables-only -emit-llvm -o - \
// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank
typedef struct { int a, b, c; } Struct;
diff --git a/clang/test/DebugInfo/KeyInstructions/init-agg.c b/clang/test/DebugInfo/KeyInstructions/init-agg.c
index dc3ccaedc57b5..de1f247bb2722 100644
--- a/clang/test/DebugInfo/KeyInstructions/init-agg.c
+++ b/clang/test/DebugInfo/KeyInstructions/init-agg.c
@@ -1,8 +1,8 @@
-// RUN: %clang -gkey-instructions -x c++ %s -gmlt -gno-column-info -S -emit-llvm -o - -ftrivial-auto-var-init=pattern \
+// RUN: %clang_cc1 -gkey-instructions -x c++ %s -debug-info-kind=line-tables-only -gno-column-info -emit-llvm -o - -ftrivial-auto-var-init=pattern \
// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank
-// RUN: %clang -gkey-instructions -x c %s -gmlt -gno-column-info -S -emit-llvm -o - -ftrivial-auto-var-init=pattern \
+// RUN: %clang_cc1 -gkey-instructions -x c %s -debug-info-kind=line-tables-only -gno-column-info -emit-llvm -o - -ftrivial-auto-var-init=pattern \
// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank
// The implicit-check-not is important; we don't want the GEPs created for the
>From 2fc4653e3e2bd825114b8081df06696c0f2b6b43 Mon Sep 17 00:00:00 2001
From: Orlando Cazalet-Hyams <orlando.hyams at sony.com>
Date: Thu, 3 Apr 2025 17:00:09 +0100
Subject: [PATCH 29/33] [KeyInstr][Clang] Member initalization atom
This patch is part of a stack that teaches Clang to generate Key Instructions
metadata for C and C++.
The Key Instructions project is introduced, including a "quick summary" section
at the top which adds context for this PR, here:
https://discourse.llvm.org/t/rfc-improving-is-stmt-placement-for-better-interactive-debugging/82668
The feature is only functional in LLVM if LLVM is built with CMake flag
LLVM_EXPERIMENTAL_KEY_INSTRUCTIONs. Eventually that flag will be removed.
The Clang-side work is demoed here:
https://github.com/llvm/llvm-project/pull/130943
---
clang/lib/CodeGen/CGClass.cpp | 1 +
.../DebugInfo/KeyInstructions/init-member.cpp | 22 +++++++++++++++++++
2 files changed, 23 insertions(+)
create mode 100644 clang/test/DebugInfo/KeyInstructions/init-member.cpp
diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp
index 6beb2bccfeae0..251b059c256f6 100644
--- a/clang/lib/CodeGen/CGClass.cpp
+++ b/clang/lib/CodeGen/CGClass.cpp
@@ -1338,6 +1338,7 @@ void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD,
assert(!Member->isBaseInitializer());
assert(Member->isAnyMemberInitializer() &&
"Delegating initializer on non-delegating constructor");
+ ApplyAtomGroup Grp(getDebugInfo());
CM.addMemberInitializer(Member);
}
CM.finish();
diff --git a/clang/test/DebugInfo/KeyInstructions/init-member.cpp b/clang/test/DebugInfo/KeyInstructions/init-member.cpp
new file mode 100644
index 0000000000000..60949bd8a604a
--- /dev/null
+++ b/clang/test/DebugInfo/KeyInstructions/init-member.cpp
@@ -0,0 +1,22 @@
+// RUN: %clang -gkey-instructions %s -gmlt -S -emit-llvm -o - \
+// RUN: | FileCheck %s
+
+struct B {
+ float y;
+};
+
+class Cls {
+ public:
+ int x = 1;
+ B b = {5.f};
+};
+
+void fun() {
+ Cls c;
+}
+
+// CHECK: store i32 1, ptr %x{{.*}}, !dbg [[G1R1:!.*]]
+// CHECK: store float 5.000000e+00, ptr %y{{.*}}, !dbg [[G2R1:!.*]]
+
+// CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
+// CHECK: [[G2R1]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1)
>From 58f7f4d5dc33d81e0726c6dc332dd2842f821efb Mon Sep 17 00:00:00 2001
From: Orlando Cazalet-Hyams <orlando.hyams at sony.com>
Date: Wed, 21 May 2025 15:25:17 +0100
Subject: [PATCH 30/33] cc1
---
clang/test/DebugInfo/KeyInstructions/init-member.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/test/DebugInfo/KeyInstructions/init-member.cpp b/clang/test/DebugInfo/KeyInstructions/init-member.cpp
index 60949bd8a604a..5ccefd4064421 100644
--- a/clang/test/DebugInfo/KeyInstructions/init-member.cpp
+++ b/clang/test/DebugInfo/KeyInstructions/init-member.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang -gkey-instructions %s -gmlt -S -emit-llvm -o - \
+// RUN: %clang_cc1 -gkey-instructions %s -debug-info-kind=line-tables-only -emit-llvm -o - \
// RUN: | FileCheck %s
struct B {
>From d099e89b6de4363cf271e90cd12b61661a0eb51d Mon Sep 17 00:00:00 2001
From: Orlando Cazalet-Hyams <orlando.hyams at sony.com>
Date: Thu, 3 Apr 2025 17:31:32 +0100
Subject: [PATCH 31/33] [KeyInstr][Clang] Catch variable init atom
This patch is part of a stack that teaches Clang to generate Key Instructions
metadata for C and C++.
The Key Instructions project is introduced, including a "quick summary" section
at the top which adds context for this PR, here:
https://discourse.llvm.org/t/rfc-improving-is-stmt-placement-for-better-interactive-debugging/82668
The feature is only functional in LLVM if LLVM is built with CMake flag
LLVM_EXPERIMENTAL_KEY_INSTRUCTIONs. Eventually that flag will be removed.
The Clang-side work is demoed here:
https://github.com/llvm/llvm-project/pull/130943
---
clang/lib/CodeGen/ItaniumCXXABI.cpp | 1 +
.../DebugInfo/KeyInstructions/try-catch.cpp | 20 +++++++++++++++++++
2 files changed, 21 insertions(+)
create mode 100644 clang/test/DebugInfo/KeyInstructions/try-catch.cpp
diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp
index faa07024a6052..1041ae84dbdf1 100644
--- a/clang/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp
@@ -5055,6 +5055,7 @@ void ItaniumCXXABI::emitBeginCatch(CodeGenFunction &CGF,
// Emit the local.
CodeGenFunction::AutoVarEmission var = CGF.EmitAutoVarAlloca(*CatchParam);
+ ApplyAtomGroup Grp(CGF.getDebugInfo());
InitCatchParam(CGF, *CatchParam, var.getObjectAddress(CGF), S->getBeginLoc());
CGF.EmitAutoVarCleanups(var);
}
diff --git a/clang/test/DebugInfo/KeyInstructions/try-catch.cpp b/clang/test/DebugInfo/KeyInstructions/try-catch.cpp
new file mode 100644
index 0000000000000..3d1080aca2f07
--- /dev/null
+++ b/clang/test/DebugInfo/KeyInstructions/try-catch.cpp
@@ -0,0 +1,20 @@
+// RUN: %clang -gkey-instructions %s -gmlt -S -emit-llvm -o - -fexceptions \
+// RUN: | FileCheck %s
+
+void except() {
+ // FIXME(OCH): Should `store i32 32, ptr %exception` be key?
+ throw 32;
+}
+
+void attempt() {
+ try { except(); }
+// CHECK: catch:
+// CHECK: %4 = call ptr @__cxa_begin_catch(ptr %exn)
+// CHECK: %5 = load i32{{.*}}, !dbg [[G1R2:!.*]]
+// CHECK: store i32 %5, ptr %e{{.*}}, !dbg [[G1R1:!.*]]
+// CHECK: call void @__cxa_end_catch()
+ catch (int e) { }
+}
+
+// CHECK: [[G1R2]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 2)
+// CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
>From 54eca7132d6ed37a9a5f8eaeb3ed8b024870138a Mon Sep 17 00:00:00 2001
From: Orlando Cazalet-Hyams <orlando.hyams at sony.com>
Date: Wed, 21 May 2025 15:30:39 +0100
Subject: [PATCH 32/33] cc1
---
clang/test/DebugInfo/KeyInstructions/try-catch.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/test/DebugInfo/KeyInstructions/try-catch.cpp b/clang/test/DebugInfo/KeyInstructions/try-catch.cpp
index 3d1080aca2f07..d2b458f361e11 100644
--- a/clang/test/DebugInfo/KeyInstructions/try-catch.cpp
+++ b/clang/test/DebugInfo/KeyInstructions/try-catch.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang -gkey-instructions %s -gmlt -S -emit-llvm -o - -fexceptions \
+// RUN: %clang_cc1 -gkey-instructions %s -debug-info-kind=line-tables-only -emit-llvm -o - -fexceptions -fcxx-exceptions \
// RUN: | FileCheck %s
void except() {
>From 46e356a3b8e14d7a689582a43aff99b0f9319584 Mon Sep 17 00:00:00 2001
From: Orlando Cazalet-Hyams <orlando.hyams at sony.com>
Date: Fri, 23 May 2025 10:15:42 +0100
Subject: [PATCH 33/33] [KeyInstr][Clang] If stmt atom (#134642)
This patch is part of a stack that teaches Clang to generate Key Instructions
metadata for C and C++.
RFC:
https://discourse.llvm.org/t/rfc-improving-is-stmt-placement-for-better-interactive-debugging/82668
The feature is only functional in LLVM if LLVM is built with CMake flag
LLVM_EXPERIMENTAL_KEY_INSTRUCTIONs. Eventually that flag will be removed.
---
clang/lib/CodeGen/CodeGenFunction.cpp | 10 +++++
clang/lib/CodeGen/CodeGenFunction.h | 5 +++
clang/test/DebugInfo/KeyInstructions/if.c | 46 +++++++++++++++++++++++
3 files changed, 61 insertions(+)
create mode 100644 clang/test/DebugInfo/KeyInstructions/if.c
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index 2256cc08e2212..0356952f4f291 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -2118,6 +2118,8 @@ void CodeGenFunction::EmitBranchOnBoolExpr(
llvm::Instruction *BrInst = Builder.CreateCondBr(CondV, TrueBlock, FalseBlock,
Weights, Unpredictable);
+ addInstToNewSourceAtom(BrInst, CondV);
+
switch (HLSLControlFlowAttr) {
case HLSLControlFlowHintAttr::Microsoft_branch:
case HLSLControlFlowHintAttr::Microsoft_flatten: {
@@ -3338,3 +3340,11 @@ void CodeGenFunction::addInstToSpecificSourceAtom(
if (CGDebugInfo *DI = getDebugInfo())
DI->addInstToSpecificSourceAtom(KeyInstruction, Backup, Atom);
}
+
+void CodeGenFunction::addInstToNewSourceAtom(llvm::Instruction *KeyInstruction,
+ llvm::Value *Backup) {
+ if (CGDebugInfo *DI = getDebugInfo()) {
+ ApplyAtomGroup Grp(getDebugInfo());
+ DI->addInstToCurrentSourceAtom(KeyInstruction, Backup);
+ }
+}
\ No newline at end of file
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index 78d71fc822bcb..92e9ab8156ad2 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -1762,6 +1762,11 @@ class CodeGenFunction : public CodeGenTypeCache {
void addInstToSpecificSourceAtom(llvm::Instruction *KeyInstruction,
llvm::Value *Backup, uint64_t Atom);
+ /// Add \p KeyInstruction and an optional \p Backup instruction to a new atom
+ /// group (See ApplyAtomGroup for more info).
+ void addInstToNewSourceAtom(llvm::Instruction *KeyInstruction,
+ llvm::Value *Backup);
+
private:
/// SwitchInsn - This is nearest current switch instruction. It is null if
/// current context is not in a switch.
diff --git a/clang/test/DebugInfo/KeyInstructions/if.c b/clang/test/DebugInfo/KeyInstructions/if.c
new file mode 100644
index 0000000000000..df7d10d6ee7b8
--- /dev/null
+++ b/clang/test/DebugInfo/KeyInstructions/if.c
@@ -0,0 +1,46 @@
+// RUN: %clang_cc1 -gkey-instructions -x c++ -std=c++17 %s -debug-info-kind=line-tables-only -emit-llvm -o - \
+// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank --check-prefixes=CHECK,CHECK-CXX
+
+// RUN: %clang_cc1 -gkey-instructions -x c %s -debug-info-kind=line-tables-only -emit-llvm -o - \
+// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank
+
+int g;
+void a(int A) {
+// The branch is a key instruction, with the condition being its backup.
+// CHECK: entry:
+// CHECK: %tobool = icmp ne i32 %0, 0{{.*}}, !dbg [[G1R2:!.*]]
+// CHECK: br i1 %tobool, label %if.then, label %if.end{{.*}}, !dbg [[G1R1:!.*]]
+ if (A)
+ ;
+
+// The assignment in the if gets a distinct source atom group.
+// CHECK: if.end:
+// CHECK: %1 = load i32, ptr %A.addr{{.*}}, !dbg [[G2R2:!.*]]
+// CHECK: store i32 %1, ptr @g{{.*}}, !dbg [[G2R1:!.*]]
+// CHECK: %tobool1 = icmp ne i32 %1, 0{{.*}}, !dbg [[G3R2:!.*]]
+// CHECK: br i1 %tobool1, label %if.then2, label %if.end3{{.*}}, !dbg [[G3R1:!.*]]
+ if ((g = A))
+ ;
+
+#ifdef __cplusplus
+// The assignment in the if gets a distinct source atom group.
+// CHECK-CXX: if.end3:
+// CHECK-CXX: %2 = load i32, ptr %A.addr{{.*}}, !dbg [[G4R2:!.*]]
+// CHECK-CXX: store i32 %2, ptr %B{{.*}}, !dbg [[G4R1:!.*]]
+// CHECK-CXX: %tobool4 = icmp ne i32 %3, 0{{.*}}, !dbg [[G5R2:!.*]]
+// CHECK-CXX: br i1 %tobool4, label %if.then5, label %if.end6{{.*}}, !dbg [[G5R1:!.*]]
+ if (int B = A; B)
+ ;
+#endif
+}
+
+// CHECK: [[G1R2]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 2)
+// CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
+// CHECK: [[G2R2]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 2)
+// CHECK: [[G2R1]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1)
+// CHECK: [[G3R2]] = !DILocation({{.*}}, atomGroup: 3, atomRank: 2)
+// CHECK: [[G3R1]] = !DILocation({{.*}}, atomGroup: 3, atomRank: 1)
+// CHECK-CXX: [[G4R2]] = !DILocation({{.*}}, atomGroup: 4, atomRank: 2)
+// CHECK-CXX: [[G4R1]] = !DILocation({{.*}}, atomGroup: 4, atomRank: 1)
+// CHECK-CXX: [[G5R2]] = !DILocation({{.*}}, atomGroup: 5, atomRank: 2)
+// CHECK-CXX: [[G5R1]] = !DILocation({{.*}}, atomGroup: 5, atomRank: 1)
More information about the cfe-commits
mailing list