[clang] [libcxxabi] [lldb] [llvm] [lldb][Expression] Add structor variant to LLDB's function call labels (PR #149827)
cmtice wrote: > > Even a 3-4% increase in binary size is going to cause serious problems for > > us at Google. Is there any way that this work could be guarded by a flag, > > so that we can turn it off until we find a way to work around the problems > > it will cause for us? > > Yup I put this behind a clang flag in #154142 Thank you!! :-) https://github.com/llvm/llvm-project/pull/149827 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libcxxabi] [lldb] [llvm] [lldb][Expression] Add structor variant to LLDB's function call labels (PR #149827)
Michael137 wrote: > Even a 3-4% increase in binary size is going to cause serious problems for us > at Google. Is there any way that this work could be guarded by a flag, so > that we can turn it off until we find a way to work around the problems it > will cause for us? Yup I put this behind a clang flag in https://github.com/llvm/llvm-project/pull/154142 https://github.com/llvm/llvm-project/pull/149827 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libcxxabi] [lldb] [llvm] [lldb][Expression] Add structor variant to LLDB's function call labels (PR #149827)
cmtice wrote: Even a 3-4% increase in binary size is going to cause serious problems for us at Google. Is there any way that this work could be guarded by a flag, so that we can turn it off until we find a way to work around the problems it will cause for us? https://github.com/llvm/llvm-project/pull/149827 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libcxxabi] [lldb] [llvm] [lldb][Expression] Add structor variant to LLDB's function call labels (PR #149827)
Michael137 wrote: > > Not sure where we go from here then if this is a blocker. > > It's definitely a "problem", but I'm not sure if it's a "blocker". We had > some discussions about what we could do to absorb that cost, but it's not > trivial and it's getting kind of over my head. The thing is that, while the > size increase is unfortunate, the change also makes a lot sense as it makes > things consistent, both with gcc and with clang's non-structor functions. > This week is also pretty busy for all the llvm people, so we don't really > have an official position on this. Ok good to hear there could be a way forward. I'll split out the debug-info changes into a separate PR on which we can discuss further. > > without having to do structural matching on the DIE context. I suppose we > > can go back to that method. That would also still leave the cross-module > > case an open question.. > > I like the structural match method, as it would open the door to potentially > removing the linkage names from declaration DIEs (thereby _saving_ debug_str > space), but that's a more speculative approach, with unknown performance and > other possible issues, so I don't feel entirely comfortable asking you to go > down that path. The cross module thing is tricky, but I don't think it's > fundamentally unsolvable -- basically, we just need to find a way to pass DIE > information from one module to another. Ack https://github.com/llvm/llvm-project/pull/149827 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libcxxabi] [lldb] [llvm] [lldb][Expression] Add structor variant to LLDB's function call labels (PR #149827)
labath wrote: I re-ran the number, and the results are roughly the same. > Am I misremembering that this came up before elsewhere? I guess that's what > the simple-template-name stuff fixed? Yes, simple template names came about because some targets were overflowing the debug_str section. I'm kinda surprised it's overflowing again, but I don't know the details/numbers there. > Not sure where we go from here then if this is a blocker. It's definitely a "problem", but I'm not sure if it's a "blocker". We had some discussions about what we could do to absorb that cost, but it's not trivial and it's getting kind of over my head. The thing is that, while the size increase is unfortunate, the change also makes a lot sense as it makes things consistent, both with gcc and with clang's non-structor functions. This week is also pretty busy for all the llvm people, so we don't really have an official position on this. > Maybe there's a way to reduce the amount of linkage names we emit, though not > sure off the top how we would decide that. I don't know either. I was looking at the generated debug info with @dwblaikie, and we didn't find anything obvious. > without having to do structural matching on the DIE context. I suppose we can > go back to that method. That would also still leave the cross-module case an > open question.. I like the structural match method, as it would open the door to potentially removing the linkage names from declaration DIEs (thereby *saving* debug_str space), but that's a more speculative approach, with unknown performance and other possible issues, so I don't feel entirely comfortable asking you to go down that path. The cross module thing is tricky, but I don't think it's fundamentally unsolvable -- basically, we just need to find a way to pass DIE information from one module to another. > And from digging around, it looks like on linux we already rely on the > ManglingSubstitutor for the aliased structor variant case. Yeah, that's because linux (elf?) will simply not generate the symbol for the C1 if the ABI doesn't require it to do that (and it's equivalent to C2). This actually brings back (painful) memories of when I (some 10 years ago) tried to remove this "optimization" and it caused an large increase in the .symtab section. https://github.com/llvm/llvm-project/pull/149827 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libcxxabi] [lldb] [llvm] [lldb][Expression] Add structor variant to LLDB's function call labels (PR #149827)
Michael137 wrote: Latest commit has the changes that make use of the unified structor mangling to do the cross-module lookup. Still not the prettiest because it relies on the `ManglingSubstitutor`, but it makes the cross-module case work pretty seamlessly. And from digging around, it looks like on linux we already rely on the `ManglingSubstitutor` for the aliased structor variant case. https://github.com/llvm/llvm-project/pull/149827 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libcxxabi] [lldb] [llvm] [lldb][Expression] Add structor variant to LLDB's function call labels (PR #149827)
https://github.com/Michael137 updated
https://github.com/llvm/llvm-project/pull/149827
>From c094d29dd10161d62131a1de15562ce6024d5e2d Mon Sep 17 00:00:00 2001
From: Michael Buch
Date: Mon, 4 Aug 2025 14:20:45 +0100
Subject: [PATCH 01/10] [clang][Mangle] Inject structor type into mangled name
when mangling for LLDB JIT expressions
This patch adds special handling for `AsmLabel`s created by LLDB. LLDB
uses `AsmLabel`s to encode information about a function declaration to
make it easier to locate function symbols when JITing C++ expressions.
For constructors/destructors LLDB doesn't know at the time of creating
the `AsmLabelAttr` which structor variant the expression evaluator will
need to call (this is decided when compiling the expression). So we make
the Clang mangler inject this information into our custom label when
we're JITting the expression.
---
clang/lib/AST/Mangle.cpp | 33 +-
clang/unittests/AST/DeclTest.cpp | 75
2 files changed, 107 insertions(+), 1 deletion(-)
diff --git a/clang/lib/AST/Mangle.cpp b/clang/lib/AST/Mangle.cpp
index 0bfb51c11f0a5..1131477fa7200 100644
--- a/clang/lib/AST/Mangle.cpp
+++ b/clang/lib/AST/Mangle.cpp
@@ -152,6 +152,33 @@ bool MangleContext::shouldMangleDeclName(const NamedDecl
*D) {
return shouldMangleCXXName(D);
}
+static llvm::StringRef g_lldb_func_call_label_prefix = "$__lldb_func:";
+
+/// Given an LLDB function call label, this function prints the label
+/// into \c Out, together with the structor type of \c GD (if the
+/// decl is a constructor/destructor). LLDB knows how to handle mangled
+/// names with this encoding.
+///
+/// Example input label:
+/// $__lldb_func::123:456:~Foo
+///
+/// Example output:
+/// $__lldb_func:D1:123:456:~Foo
+///
+static void emitLLDBAsmLabel(llvm::StringRef label, GlobalDecl GD,
+ llvm::raw_ostream &Out) {
+ assert(label.starts_with(g_lldb_func_call_label_prefix));
+
+ Out << g_lldb_func_call_label_prefix;
+
+ if (llvm::isa(GD.getDecl()))
+Out << "C" << GD.getCtorType();
+ else if (llvm::isa(GD.getDecl()))
+Out << "D" << GD.getDtorType();
+
+ Out << label.substr(g_lldb_func_call_label_prefix.size());
+}
+
void MangleContext::mangleName(GlobalDecl GD, raw_ostream &Out) {
const ASTContext &ASTContext = getASTContext();
const NamedDecl *D = cast(GD.getDecl());
@@ -185,7 +212,11 @@ void MangleContext::mangleName(GlobalDecl GD, raw_ostream
&Out) {
if (!UserLabelPrefix.empty())
Out << '\01'; // LLVM IR Marker for __asm("foo")
-Out << ALA->getLabel();
+if (ALA->getLabel().starts_with(g_lldb_func_call_label_prefix))
+ emitLLDBAsmLabel(ALA->getLabel(), GD, Out);
+else
+ Out << ALA->getLabel();
+
return;
}
diff --git a/clang/unittests/AST/DeclTest.cpp b/clang/unittests/AST/DeclTest.cpp
index 6b443918ec137..4bd7886ef9b35 100644
--- a/clang/unittests/AST/DeclTest.cpp
+++ b/clang/unittests/AST/DeclTest.cpp
@@ -16,6 +16,7 @@
#include "clang/AST/Mangle.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Basic/ABI.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/TargetInfo.h"
@@ -102,6 +103,80 @@ TEST(Decl, AsmLabelAttr) {
"foo");
}
+TEST(Decl, AsmLabelAttr_LLDB) {
+ StringRef Code = R"(
+struct S {
+ void f() {}
+ S() = default;
+ ~S() = default;
+};
+ )";
+ auto AST =
+ tooling::buildASTFromCodeWithArgs(Code, {"-target",
"i386-apple-darwin"});
+ ASTContext &Ctx = AST->getASTContext();
+ assert(Ctx.getTargetInfo().getUserLabelPrefix() == StringRef("_") &&
+ "Expected target to have a global prefix");
+ DiagnosticsEngine &Diags = AST->getDiagnostics();
+
+ const auto *DeclS =
+ selectFirst("d", match(cxxRecordDecl().bind("d"), Ctx));
+
+ auto *DeclF = *DeclS->method_begin();
+ auto *Ctor = *DeclS->ctor_begin();
+ auto *Dtor = DeclS->getDestructor();
+
+ ASSERT_TRUE(DeclF);
+ ASSERT_TRUE(Ctor);
+ ASSERT_TRUE(Dtor);
+
+ DeclF->addAttr(AsmLabelAttr::Create(Ctx, "$__lldb_func::123:123:_Z1fv"));
+ Ctor->addAttr(AsmLabelAttr::Create(Ctx, "$__lldb_func::123:123:S"));
+ Dtor->addAttr(AsmLabelAttr::Create(Ctx, "$__lldb_func::123:123:~S"));
+
+ std::unique_ptr MC(
+ ItaniumMangleContext::create(Ctx, Diags));
+
+ {
+std::string Mangled;
+llvm::raw_string_ostream OS_Mangled(Mangled);
+MC->mangleName(DeclF, OS_Mangled);
+
+ASSERT_EQ(Mangled, "\x01$__lldb_func::123:123:_Z1fv");
+ };
+
+ {
+std::string Mangled;
+llvm::raw_string_ostream OS_Mangled(Mangled);
+MC->mangleName(GlobalDecl(Ctor, CXXCtorType::Ctor_Complete), OS_Mangled);
+
+ASSERT_EQ(Mangled, "\x01$__lldb_func:C0:123:123:S");
+ };
+
+ {
+std::string Mangled;
+llvm::raw_string_ostream OS_Mangled(Mangled);
+MC->mangleName(GlobalDecl(Ctor, CXXCtorType::Ctor_Base), OS_Mangled);
+
+ASSERT_EQ(Mangled
[clang] [libcxxabi] [lldb] [llvm] [lldb][Expression] Add structor variant to LLDB's function call labels (PR #149827)
https://github.com/Michael137 updated
https://github.com/llvm/llvm-project/pull/149827
>From c094d29dd10161d62131a1de15562ce6024d5e2d Mon Sep 17 00:00:00 2001
From: Michael Buch
Date: Mon, 4 Aug 2025 14:20:45 +0100
Subject: [PATCH 1/8] [clang][Mangle] Inject structor type into mangled name
when mangling for LLDB JIT expressions
This patch adds special handling for `AsmLabel`s created by LLDB. LLDB
uses `AsmLabel`s to encode information about a function declaration to
make it easier to locate function symbols when JITing C++ expressions.
For constructors/destructors LLDB doesn't know at the time of creating
the `AsmLabelAttr` which structor variant the expression evaluator will
need to call (this is decided when compiling the expression). So we make
the Clang mangler inject this information into our custom label when
we're JITting the expression.
---
clang/lib/AST/Mangle.cpp | 33 +-
clang/unittests/AST/DeclTest.cpp | 75
2 files changed, 107 insertions(+), 1 deletion(-)
diff --git a/clang/lib/AST/Mangle.cpp b/clang/lib/AST/Mangle.cpp
index 0bfb51c11f0a5..1131477fa7200 100644
--- a/clang/lib/AST/Mangle.cpp
+++ b/clang/lib/AST/Mangle.cpp
@@ -152,6 +152,33 @@ bool MangleContext::shouldMangleDeclName(const NamedDecl
*D) {
return shouldMangleCXXName(D);
}
+static llvm::StringRef g_lldb_func_call_label_prefix = "$__lldb_func:";
+
+/// Given an LLDB function call label, this function prints the label
+/// into \c Out, together with the structor type of \c GD (if the
+/// decl is a constructor/destructor). LLDB knows how to handle mangled
+/// names with this encoding.
+///
+/// Example input label:
+/// $__lldb_func::123:456:~Foo
+///
+/// Example output:
+/// $__lldb_func:D1:123:456:~Foo
+///
+static void emitLLDBAsmLabel(llvm::StringRef label, GlobalDecl GD,
+ llvm::raw_ostream &Out) {
+ assert(label.starts_with(g_lldb_func_call_label_prefix));
+
+ Out << g_lldb_func_call_label_prefix;
+
+ if (llvm::isa(GD.getDecl()))
+Out << "C" << GD.getCtorType();
+ else if (llvm::isa(GD.getDecl()))
+Out << "D" << GD.getDtorType();
+
+ Out << label.substr(g_lldb_func_call_label_prefix.size());
+}
+
void MangleContext::mangleName(GlobalDecl GD, raw_ostream &Out) {
const ASTContext &ASTContext = getASTContext();
const NamedDecl *D = cast(GD.getDecl());
@@ -185,7 +212,11 @@ void MangleContext::mangleName(GlobalDecl GD, raw_ostream
&Out) {
if (!UserLabelPrefix.empty())
Out << '\01'; // LLVM IR Marker for __asm("foo")
-Out << ALA->getLabel();
+if (ALA->getLabel().starts_with(g_lldb_func_call_label_prefix))
+ emitLLDBAsmLabel(ALA->getLabel(), GD, Out);
+else
+ Out << ALA->getLabel();
+
return;
}
diff --git a/clang/unittests/AST/DeclTest.cpp b/clang/unittests/AST/DeclTest.cpp
index 6b443918ec137..4bd7886ef9b35 100644
--- a/clang/unittests/AST/DeclTest.cpp
+++ b/clang/unittests/AST/DeclTest.cpp
@@ -16,6 +16,7 @@
#include "clang/AST/Mangle.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Basic/ABI.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/TargetInfo.h"
@@ -102,6 +103,80 @@ TEST(Decl, AsmLabelAttr) {
"foo");
}
+TEST(Decl, AsmLabelAttr_LLDB) {
+ StringRef Code = R"(
+struct S {
+ void f() {}
+ S() = default;
+ ~S() = default;
+};
+ )";
+ auto AST =
+ tooling::buildASTFromCodeWithArgs(Code, {"-target",
"i386-apple-darwin"});
+ ASTContext &Ctx = AST->getASTContext();
+ assert(Ctx.getTargetInfo().getUserLabelPrefix() == StringRef("_") &&
+ "Expected target to have a global prefix");
+ DiagnosticsEngine &Diags = AST->getDiagnostics();
+
+ const auto *DeclS =
+ selectFirst("d", match(cxxRecordDecl().bind("d"), Ctx));
+
+ auto *DeclF = *DeclS->method_begin();
+ auto *Ctor = *DeclS->ctor_begin();
+ auto *Dtor = DeclS->getDestructor();
+
+ ASSERT_TRUE(DeclF);
+ ASSERT_TRUE(Ctor);
+ ASSERT_TRUE(Dtor);
+
+ DeclF->addAttr(AsmLabelAttr::Create(Ctx, "$__lldb_func::123:123:_Z1fv"));
+ Ctor->addAttr(AsmLabelAttr::Create(Ctx, "$__lldb_func::123:123:S"));
+ Dtor->addAttr(AsmLabelAttr::Create(Ctx, "$__lldb_func::123:123:~S"));
+
+ std::unique_ptr MC(
+ ItaniumMangleContext::create(Ctx, Diags));
+
+ {
+std::string Mangled;
+llvm::raw_string_ostream OS_Mangled(Mangled);
+MC->mangleName(DeclF, OS_Mangled);
+
+ASSERT_EQ(Mangled, "\x01$__lldb_func::123:123:_Z1fv");
+ };
+
+ {
+std::string Mangled;
+llvm::raw_string_ostream OS_Mangled(Mangled);
+MC->mangleName(GlobalDecl(Ctor, CXXCtorType::Ctor_Complete), OS_Mangled);
+
+ASSERT_EQ(Mangled, "\x01$__lldb_func:C0:123:123:S");
+ };
+
+ {
+std::string Mangled;
+llvm::raw_string_ostream OS_Mangled(Mangled);
+MC->mangleName(GlobalDecl(Ctor, CXXCtorType::Ctor_Base), OS_Mangled);
+
+ASSERT_EQ(Mangled,
[clang] [libcxxabi] [lldb] [llvm] [lldb][Expression] Add structor variant to LLDB's function call labels (PR #149827)
https://github.com/Michael137 updated
https://github.com/llvm/llvm-project/pull/149827
>From c094d29dd10161d62131a1de15562ce6024d5e2d Mon Sep 17 00:00:00 2001
From: Michael Buch
Date: Mon, 4 Aug 2025 14:20:45 +0100
Subject: [PATCH 1/8] [clang][Mangle] Inject structor type into mangled name
when mangling for LLDB JIT expressions
This patch adds special handling for `AsmLabel`s created by LLDB. LLDB
uses `AsmLabel`s to encode information about a function declaration to
make it easier to locate function symbols when JITing C++ expressions.
For constructors/destructors LLDB doesn't know at the time of creating
the `AsmLabelAttr` which structor variant the expression evaluator will
need to call (this is decided when compiling the expression). So we make
the Clang mangler inject this information into our custom label when
we're JITting the expression.
---
clang/lib/AST/Mangle.cpp | 33 +-
clang/unittests/AST/DeclTest.cpp | 75
2 files changed, 107 insertions(+), 1 deletion(-)
diff --git a/clang/lib/AST/Mangle.cpp b/clang/lib/AST/Mangle.cpp
index 0bfb51c11f0a5..1131477fa7200 100644
--- a/clang/lib/AST/Mangle.cpp
+++ b/clang/lib/AST/Mangle.cpp
@@ -152,6 +152,33 @@ bool MangleContext::shouldMangleDeclName(const NamedDecl
*D) {
return shouldMangleCXXName(D);
}
+static llvm::StringRef g_lldb_func_call_label_prefix = "$__lldb_func:";
+
+/// Given an LLDB function call label, this function prints the label
+/// into \c Out, together with the structor type of \c GD (if the
+/// decl is a constructor/destructor). LLDB knows how to handle mangled
+/// names with this encoding.
+///
+/// Example input label:
+/// $__lldb_func::123:456:~Foo
+///
+/// Example output:
+/// $__lldb_func:D1:123:456:~Foo
+///
+static void emitLLDBAsmLabel(llvm::StringRef label, GlobalDecl GD,
+ llvm::raw_ostream &Out) {
+ assert(label.starts_with(g_lldb_func_call_label_prefix));
+
+ Out << g_lldb_func_call_label_prefix;
+
+ if (llvm::isa(GD.getDecl()))
+Out << "C" << GD.getCtorType();
+ else if (llvm::isa(GD.getDecl()))
+Out << "D" << GD.getDtorType();
+
+ Out << label.substr(g_lldb_func_call_label_prefix.size());
+}
+
void MangleContext::mangleName(GlobalDecl GD, raw_ostream &Out) {
const ASTContext &ASTContext = getASTContext();
const NamedDecl *D = cast(GD.getDecl());
@@ -185,7 +212,11 @@ void MangleContext::mangleName(GlobalDecl GD, raw_ostream
&Out) {
if (!UserLabelPrefix.empty())
Out << '\01'; // LLVM IR Marker for __asm("foo")
-Out << ALA->getLabel();
+if (ALA->getLabel().starts_with(g_lldb_func_call_label_prefix))
+ emitLLDBAsmLabel(ALA->getLabel(), GD, Out);
+else
+ Out << ALA->getLabel();
+
return;
}
diff --git a/clang/unittests/AST/DeclTest.cpp b/clang/unittests/AST/DeclTest.cpp
index 6b443918ec137..4bd7886ef9b35 100644
--- a/clang/unittests/AST/DeclTest.cpp
+++ b/clang/unittests/AST/DeclTest.cpp
@@ -16,6 +16,7 @@
#include "clang/AST/Mangle.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Basic/ABI.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/TargetInfo.h"
@@ -102,6 +103,80 @@ TEST(Decl, AsmLabelAttr) {
"foo");
}
+TEST(Decl, AsmLabelAttr_LLDB) {
+ StringRef Code = R"(
+struct S {
+ void f() {}
+ S() = default;
+ ~S() = default;
+};
+ )";
+ auto AST =
+ tooling::buildASTFromCodeWithArgs(Code, {"-target",
"i386-apple-darwin"});
+ ASTContext &Ctx = AST->getASTContext();
+ assert(Ctx.getTargetInfo().getUserLabelPrefix() == StringRef("_") &&
+ "Expected target to have a global prefix");
+ DiagnosticsEngine &Diags = AST->getDiagnostics();
+
+ const auto *DeclS =
+ selectFirst("d", match(cxxRecordDecl().bind("d"), Ctx));
+
+ auto *DeclF = *DeclS->method_begin();
+ auto *Ctor = *DeclS->ctor_begin();
+ auto *Dtor = DeclS->getDestructor();
+
+ ASSERT_TRUE(DeclF);
+ ASSERT_TRUE(Ctor);
+ ASSERT_TRUE(Dtor);
+
+ DeclF->addAttr(AsmLabelAttr::Create(Ctx, "$__lldb_func::123:123:_Z1fv"));
+ Ctor->addAttr(AsmLabelAttr::Create(Ctx, "$__lldb_func::123:123:S"));
+ Dtor->addAttr(AsmLabelAttr::Create(Ctx, "$__lldb_func::123:123:~S"));
+
+ std::unique_ptr MC(
+ ItaniumMangleContext::create(Ctx, Diags));
+
+ {
+std::string Mangled;
+llvm::raw_string_ostream OS_Mangled(Mangled);
+MC->mangleName(DeclF, OS_Mangled);
+
+ASSERT_EQ(Mangled, "\x01$__lldb_func::123:123:_Z1fv");
+ };
+
+ {
+std::string Mangled;
+llvm::raw_string_ostream OS_Mangled(Mangled);
+MC->mangleName(GlobalDecl(Ctor, CXXCtorType::Ctor_Complete), OS_Mangled);
+
+ASSERT_EQ(Mangled, "\x01$__lldb_func:C0:123:123:S");
+ };
+
+ {
+std::string Mangled;
+llvm::raw_string_ostream OS_Mangled(Mangled);
+MC->mangleName(GlobalDecl(Ctor, CXXCtorType::Ctor_Base), OS_Mangled);
+
+ASSERT_EQ(Mangled,
[clang] [libcxxabi] [lldb] [llvm] [lldb][Expression] Add structor variant to LLDB's function call labels (PR #149827)
Michael137 wrote: @labath Thanks for the reviews so far. The latest commit contains a prototype of adding the GCC-style unified mangled name to constructor/destructor declarations. Turns out this wasn't too hard and actually solves all the issues we talked about pretty nicely. Mainly needed to ensure the accelerator tables map the unified mangled name to the definition DIE. And thus also had to adjust the `GetFunctions` LLDB implementation (though there may be better ways of doing that). The issue of checking that the specification came from the right place is redundant now because we lookup structors within a SymbolFile up by mangled name too. And the fallback path in case the definition is in a different module works too because we encode the mangled structor name in the label (albeit the unified one, so there may still need to be some work to be done to ensure we pick the right variant). Also for older clang versions, if the structor declaration doesn't have a mangled name, which just don't attach an `AsmLabel`, so that would work as LLDB does today. Let me know what you think. I'll prepare a separate PR to discuss these changes https://github.com/llvm/llvm-project/pull/149827 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libcxxabi] [lldb] [llvm] [lldb][Expression] Add structor variant to LLDB's function call labels (PR #149827)
github-actions[bot] wrote: :warning: Python code formatter, darker found issues in your code. :warning: You can test this locally with the following command: ``bash darker --check --diff -r HEAD~1...HEAD lldb/test/API/lang/cpp/abi_tag_structors/TestAbiTagStructors.py lldb/test/API/lang/cpp/constructors/TestCppConstructors.py lldb/test/API/lang/cpp/expr-definition-in-dylib/TestExprDefinitionInDylib.py `` View the diff from darker here. ``diff --- constructors/TestCppConstructors.py 2025-08-08 19:36:13.00 + +++ constructors/TestCppConstructors.py 2025-08-08 19:42:41.572316 + @@ -37,20 +37,20 @@ error=True, substrs=["Couldn't look up symbols:"], ) # FIXME: Calling deleted constructors should fail before linking. -#self.expect( +# self.expect( #"expr ClassWithDeletedCtor(1).value", #error=True, #substrs=["Couldn't look up symbols:"], -#) -#self.expect( +# ) +# self.expect( #"expr ClassWithDeletedDefaultCtor().value", #error=True, #substrs=["Couldn't look up symbols:", "function", "optimized out"], -#) +# ) @skipIfWindows # Can't find operator new. @skipIfLinux # Fails on some Linux systems with SIGABRT. def test_constructors_new(self): self.build() `` https://github.com/llvm/llvm-project/pull/149827 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libcxxabi] [lldb] [llvm] [lldb][Expression] Add structor variant to LLDB's function call labels (PR #149827)
https://github.com/Michael137 updated
https://github.com/llvm/llvm-project/pull/149827
>From c094d29dd10161d62131a1de15562ce6024d5e2d Mon Sep 17 00:00:00 2001
From: Michael Buch
Date: Mon, 4 Aug 2025 14:20:45 +0100
Subject: [PATCH 1/8] [clang][Mangle] Inject structor type into mangled name
when mangling for LLDB JIT expressions
This patch adds special handling for `AsmLabel`s created by LLDB. LLDB
uses `AsmLabel`s to encode information about a function declaration to
make it easier to locate function symbols when JITing C++ expressions.
For constructors/destructors LLDB doesn't know at the time of creating
the `AsmLabelAttr` which structor variant the expression evaluator will
need to call (this is decided when compiling the expression). So we make
the Clang mangler inject this information into our custom label when
we're JITting the expression.
---
clang/lib/AST/Mangle.cpp | 33 +-
clang/unittests/AST/DeclTest.cpp | 75
2 files changed, 107 insertions(+), 1 deletion(-)
diff --git a/clang/lib/AST/Mangle.cpp b/clang/lib/AST/Mangle.cpp
index 0bfb51c11f0a5..1131477fa7200 100644
--- a/clang/lib/AST/Mangle.cpp
+++ b/clang/lib/AST/Mangle.cpp
@@ -152,6 +152,33 @@ bool MangleContext::shouldMangleDeclName(const NamedDecl
*D) {
return shouldMangleCXXName(D);
}
+static llvm::StringRef g_lldb_func_call_label_prefix = "$__lldb_func:";
+
+/// Given an LLDB function call label, this function prints the label
+/// into \c Out, together with the structor type of \c GD (if the
+/// decl is a constructor/destructor). LLDB knows how to handle mangled
+/// names with this encoding.
+///
+/// Example input label:
+/// $__lldb_func::123:456:~Foo
+///
+/// Example output:
+/// $__lldb_func:D1:123:456:~Foo
+///
+static void emitLLDBAsmLabel(llvm::StringRef label, GlobalDecl GD,
+ llvm::raw_ostream &Out) {
+ assert(label.starts_with(g_lldb_func_call_label_prefix));
+
+ Out << g_lldb_func_call_label_prefix;
+
+ if (llvm::isa(GD.getDecl()))
+Out << "C" << GD.getCtorType();
+ else if (llvm::isa(GD.getDecl()))
+Out << "D" << GD.getDtorType();
+
+ Out << label.substr(g_lldb_func_call_label_prefix.size());
+}
+
void MangleContext::mangleName(GlobalDecl GD, raw_ostream &Out) {
const ASTContext &ASTContext = getASTContext();
const NamedDecl *D = cast(GD.getDecl());
@@ -185,7 +212,11 @@ void MangleContext::mangleName(GlobalDecl GD, raw_ostream
&Out) {
if (!UserLabelPrefix.empty())
Out << '\01'; // LLVM IR Marker for __asm("foo")
-Out << ALA->getLabel();
+if (ALA->getLabel().starts_with(g_lldb_func_call_label_prefix))
+ emitLLDBAsmLabel(ALA->getLabel(), GD, Out);
+else
+ Out << ALA->getLabel();
+
return;
}
diff --git a/clang/unittests/AST/DeclTest.cpp b/clang/unittests/AST/DeclTest.cpp
index 6b443918ec137..4bd7886ef9b35 100644
--- a/clang/unittests/AST/DeclTest.cpp
+++ b/clang/unittests/AST/DeclTest.cpp
@@ -16,6 +16,7 @@
#include "clang/AST/Mangle.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Basic/ABI.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/TargetInfo.h"
@@ -102,6 +103,80 @@ TEST(Decl, AsmLabelAttr) {
"foo");
}
+TEST(Decl, AsmLabelAttr_LLDB) {
+ StringRef Code = R"(
+struct S {
+ void f() {}
+ S() = default;
+ ~S() = default;
+};
+ )";
+ auto AST =
+ tooling::buildASTFromCodeWithArgs(Code, {"-target",
"i386-apple-darwin"});
+ ASTContext &Ctx = AST->getASTContext();
+ assert(Ctx.getTargetInfo().getUserLabelPrefix() == StringRef("_") &&
+ "Expected target to have a global prefix");
+ DiagnosticsEngine &Diags = AST->getDiagnostics();
+
+ const auto *DeclS =
+ selectFirst("d", match(cxxRecordDecl().bind("d"), Ctx));
+
+ auto *DeclF = *DeclS->method_begin();
+ auto *Ctor = *DeclS->ctor_begin();
+ auto *Dtor = DeclS->getDestructor();
+
+ ASSERT_TRUE(DeclF);
+ ASSERT_TRUE(Ctor);
+ ASSERT_TRUE(Dtor);
+
+ DeclF->addAttr(AsmLabelAttr::Create(Ctx, "$__lldb_func::123:123:_Z1fv"));
+ Ctor->addAttr(AsmLabelAttr::Create(Ctx, "$__lldb_func::123:123:S"));
+ Dtor->addAttr(AsmLabelAttr::Create(Ctx, "$__lldb_func::123:123:~S"));
+
+ std::unique_ptr MC(
+ ItaniumMangleContext::create(Ctx, Diags));
+
+ {
+std::string Mangled;
+llvm::raw_string_ostream OS_Mangled(Mangled);
+MC->mangleName(DeclF, OS_Mangled);
+
+ASSERT_EQ(Mangled, "\x01$__lldb_func::123:123:_Z1fv");
+ };
+
+ {
+std::string Mangled;
+llvm::raw_string_ostream OS_Mangled(Mangled);
+MC->mangleName(GlobalDecl(Ctor, CXXCtorType::Ctor_Complete), OS_Mangled);
+
+ASSERT_EQ(Mangled, "\x01$__lldb_func:C0:123:123:S");
+ };
+
+ {
+std::string Mangled;
+llvm::raw_string_ostream OS_Mangled(Mangled);
+MC->mangleName(GlobalDecl(Ctor, CXXCtorType::Ctor_Base), OS_Mangled);
+
+ASSERT_EQ(Mangled,
[clang] [libcxxabi] [lldb] [llvm] [lldb][Expression] Add structor variant to LLDB's function call labels (PR #149827)
https://github.com/Michael137 updated
https://github.com/llvm/llvm-project/pull/149827
>From c094d29dd10161d62131a1de15562ce6024d5e2d Mon Sep 17 00:00:00 2001
From: Michael Buch
Date: Mon, 4 Aug 2025 14:20:45 +0100
Subject: [PATCH 1/8] [clang][Mangle] Inject structor type into mangled name
when mangling for LLDB JIT expressions
This patch adds special handling for `AsmLabel`s created by LLDB. LLDB
uses `AsmLabel`s to encode information about a function declaration to
make it easier to locate function symbols when JITing C++ expressions.
For constructors/destructors LLDB doesn't know at the time of creating
the `AsmLabelAttr` which structor variant the expression evaluator will
need to call (this is decided when compiling the expression). So we make
the Clang mangler inject this information into our custom label when
we're JITting the expression.
---
clang/lib/AST/Mangle.cpp | 33 +-
clang/unittests/AST/DeclTest.cpp | 75
2 files changed, 107 insertions(+), 1 deletion(-)
diff --git a/clang/lib/AST/Mangle.cpp b/clang/lib/AST/Mangle.cpp
index 0bfb51c11f0a5..1131477fa7200 100644
--- a/clang/lib/AST/Mangle.cpp
+++ b/clang/lib/AST/Mangle.cpp
@@ -152,6 +152,33 @@ bool MangleContext::shouldMangleDeclName(const NamedDecl
*D) {
return shouldMangleCXXName(D);
}
+static llvm::StringRef g_lldb_func_call_label_prefix = "$__lldb_func:";
+
+/// Given an LLDB function call label, this function prints the label
+/// into \c Out, together with the structor type of \c GD (if the
+/// decl is a constructor/destructor). LLDB knows how to handle mangled
+/// names with this encoding.
+///
+/// Example input label:
+/// $__lldb_func::123:456:~Foo
+///
+/// Example output:
+/// $__lldb_func:D1:123:456:~Foo
+///
+static void emitLLDBAsmLabel(llvm::StringRef label, GlobalDecl GD,
+ llvm::raw_ostream &Out) {
+ assert(label.starts_with(g_lldb_func_call_label_prefix));
+
+ Out << g_lldb_func_call_label_prefix;
+
+ if (llvm::isa(GD.getDecl()))
+Out << "C" << GD.getCtorType();
+ else if (llvm::isa(GD.getDecl()))
+Out << "D" << GD.getDtorType();
+
+ Out << label.substr(g_lldb_func_call_label_prefix.size());
+}
+
void MangleContext::mangleName(GlobalDecl GD, raw_ostream &Out) {
const ASTContext &ASTContext = getASTContext();
const NamedDecl *D = cast(GD.getDecl());
@@ -185,7 +212,11 @@ void MangleContext::mangleName(GlobalDecl GD, raw_ostream
&Out) {
if (!UserLabelPrefix.empty())
Out << '\01'; // LLVM IR Marker for __asm("foo")
-Out << ALA->getLabel();
+if (ALA->getLabel().starts_with(g_lldb_func_call_label_prefix))
+ emitLLDBAsmLabel(ALA->getLabel(), GD, Out);
+else
+ Out << ALA->getLabel();
+
return;
}
diff --git a/clang/unittests/AST/DeclTest.cpp b/clang/unittests/AST/DeclTest.cpp
index 6b443918ec137..4bd7886ef9b35 100644
--- a/clang/unittests/AST/DeclTest.cpp
+++ b/clang/unittests/AST/DeclTest.cpp
@@ -16,6 +16,7 @@
#include "clang/AST/Mangle.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Basic/ABI.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/TargetInfo.h"
@@ -102,6 +103,80 @@ TEST(Decl, AsmLabelAttr) {
"foo");
}
+TEST(Decl, AsmLabelAttr_LLDB) {
+ StringRef Code = R"(
+struct S {
+ void f() {}
+ S() = default;
+ ~S() = default;
+};
+ )";
+ auto AST =
+ tooling::buildASTFromCodeWithArgs(Code, {"-target",
"i386-apple-darwin"});
+ ASTContext &Ctx = AST->getASTContext();
+ assert(Ctx.getTargetInfo().getUserLabelPrefix() == StringRef("_") &&
+ "Expected target to have a global prefix");
+ DiagnosticsEngine &Diags = AST->getDiagnostics();
+
+ const auto *DeclS =
+ selectFirst("d", match(cxxRecordDecl().bind("d"), Ctx));
+
+ auto *DeclF = *DeclS->method_begin();
+ auto *Ctor = *DeclS->ctor_begin();
+ auto *Dtor = DeclS->getDestructor();
+
+ ASSERT_TRUE(DeclF);
+ ASSERT_TRUE(Ctor);
+ ASSERT_TRUE(Dtor);
+
+ DeclF->addAttr(AsmLabelAttr::Create(Ctx, "$__lldb_func::123:123:_Z1fv"));
+ Ctor->addAttr(AsmLabelAttr::Create(Ctx, "$__lldb_func::123:123:S"));
+ Dtor->addAttr(AsmLabelAttr::Create(Ctx, "$__lldb_func::123:123:~S"));
+
+ std::unique_ptr MC(
+ ItaniumMangleContext::create(Ctx, Diags));
+
+ {
+std::string Mangled;
+llvm::raw_string_ostream OS_Mangled(Mangled);
+MC->mangleName(DeclF, OS_Mangled);
+
+ASSERT_EQ(Mangled, "\x01$__lldb_func::123:123:_Z1fv");
+ };
+
+ {
+std::string Mangled;
+llvm::raw_string_ostream OS_Mangled(Mangled);
+MC->mangleName(GlobalDecl(Ctor, CXXCtorType::Ctor_Complete), OS_Mangled);
+
+ASSERT_EQ(Mangled, "\x01$__lldb_func:C0:123:123:S");
+ };
+
+ {
+std::string Mangled;
+llvm::raw_string_ostream OS_Mangled(Mangled);
+MC->mangleName(GlobalDecl(Ctor, CXXCtorType::Ctor_Base), OS_Mangled);
+
+ASSERT_EQ(Mangled,
[clang] [libcxxabi] [lldb] [llvm] [lldb][Expression] Add structor variant to LLDB's function call labels (PR #149827)
https://github.com/Michael137 updated
https://github.com/llvm/llvm-project/pull/149827
>From c094d29dd10161d62131a1de15562ce6024d5e2d Mon Sep 17 00:00:00 2001
From: Michael Buch
Date: Mon, 4 Aug 2025 14:20:45 +0100
Subject: [PATCH 1/8] [clang][Mangle] Inject structor type into mangled name
when mangling for LLDB JIT expressions
This patch adds special handling for `AsmLabel`s created by LLDB. LLDB
uses `AsmLabel`s to encode information about a function declaration to
make it easier to locate function symbols when JITing C++ expressions.
For constructors/destructors LLDB doesn't know at the time of creating
the `AsmLabelAttr` which structor variant the expression evaluator will
need to call (this is decided when compiling the expression). So we make
the Clang mangler inject this information into our custom label when
we're JITting the expression.
---
clang/lib/AST/Mangle.cpp | 33 +-
clang/unittests/AST/DeclTest.cpp | 75
2 files changed, 107 insertions(+), 1 deletion(-)
diff --git a/clang/lib/AST/Mangle.cpp b/clang/lib/AST/Mangle.cpp
index 0bfb51c11f0a5..1131477fa7200 100644
--- a/clang/lib/AST/Mangle.cpp
+++ b/clang/lib/AST/Mangle.cpp
@@ -152,6 +152,33 @@ bool MangleContext::shouldMangleDeclName(const NamedDecl
*D) {
return shouldMangleCXXName(D);
}
+static llvm::StringRef g_lldb_func_call_label_prefix = "$__lldb_func:";
+
+/// Given an LLDB function call label, this function prints the label
+/// into \c Out, together with the structor type of \c GD (if the
+/// decl is a constructor/destructor). LLDB knows how to handle mangled
+/// names with this encoding.
+///
+/// Example input label:
+/// $__lldb_func::123:456:~Foo
+///
+/// Example output:
+/// $__lldb_func:D1:123:456:~Foo
+///
+static void emitLLDBAsmLabel(llvm::StringRef label, GlobalDecl GD,
+ llvm::raw_ostream &Out) {
+ assert(label.starts_with(g_lldb_func_call_label_prefix));
+
+ Out << g_lldb_func_call_label_prefix;
+
+ if (llvm::isa(GD.getDecl()))
+Out << "C" << GD.getCtorType();
+ else if (llvm::isa(GD.getDecl()))
+Out << "D" << GD.getDtorType();
+
+ Out << label.substr(g_lldb_func_call_label_prefix.size());
+}
+
void MangleContext::mangleName(GlobalDecl GD, raw_ostream &Out) {
const ASTContext &ASTContext = getASTContext();
const NamedDecl *D = cast(GD.getDecl());
@@ -185,7 +212,11 @@ void MangleContext::mangleName(GlobalDecl GD, raw_ostream
&Out) {
if (!UserLabelPrefix.empty())
Out << '\01'; // LLVM IR Marker for __asm("foo")
-Out << ALA->getLabel();
+if (ALA->getLabel().starts_with(g_lldb_func_call_label_prefix))
+ emitLLDBAsmLabel(ALA->getLabel(), GD, Out);
+else
+ Out << ALA->getLabel();
+
return;
}
diff --git a/clang/unittests/AST/DeclTest.cpp b/clang/unittests/AST/DeclTest.cpp
index 6b443918ec137..4bd7886ef9b35 100644
--- a/clang/unittests/AST/DeclTest.cpp
+++ b/clang/unittests/AST/DeclTest.cpp
@@ -16,6 +16,7 @@
#include "clang/AST/Mangle.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Basic/ABI.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/TargetInfo.h"
@@ -102,6 +103,80 @@ TEST(Decl, AsmLabelAttr) {
"foo");
}
+TEST(Decl, AsmLabelAttr_LLDB) {
+ StringRef Code = R"(
+struct S {
+ void f() {}
+ S() = default;
+ ~S() = default;
+};
+ )";
+ auto AST =
+ tooling::buildASTFromCodeWithArgs(Code, {"-target",
"i386-apple-darwin"});
+ ASTContext &Ctx = AST->getASTContext();
+ assert(Ctx.getTargetInfo().getUserLabelPrefix() == StringRef("_") &&
+ "Expected target to have a global prefix");
+ DiagnosticsEngine &Diags = AST->getDiagnostics();
+
+ const auto *DeclS =
+ selectFirst("d", match(cxxRecordDecl().bind("d"), Ctx));
+
+ auto *DeclF = *DeclS->method_begin();
+ auto *Ctor = *DeclS->ctor_begin();
+ auto *Dtor = DeclS->getDestructor();
+
+ ASSERT_TRUE(DeclF);
+ ASSERT_TRUE(Ctor);
+ ASSERT_TRUE(Dtor);
+
+ DeclF->addAttr(AsmLabelAttr::Create(Ctx, "$__lldb_func::123:123:_Z1fv"));
+ Ctor->addAttr(AsmLabelAttr::Create(Ctx, "$__lldb_func::123:123:S"));
+ Dtor->addAttr(AsmLabelAttr::Create(Ctx, "$__lldb_func::123:123:~S"));
+
+ std::unique_ptr MC(
+ ItaniumMangleContext::create(Ctx, Diags));
+
+ {
+std::string Mangled;
+llvm::raw_string_ostream OS_Mangled(Mangled);
+MC->mangleName(DeclF, OS_Mangled);
+
+ASSERT_EQ(Mangled, "\x01$__lldb_func::123:123:_Z1fv");
+ };
+
+ {
+std::string Mangled;
+llvm::raw_string_ostream OS_Mangled(Mangled);
+MC->mangleName(GlobalDecl(Ctor, CXXCtorType::Ctor_Complete), OS_Mangled);
+
+ASSERT_EQ(Mangled, "\x01$__lldb_func:C0:123:123:S");
+ };
+
+ {
+std::string Mangled;
+llvm::raw_string_ostream OS_Mangled(Mangled);
+MC->mangleName(GlobalDecl(Ctor, CXXCtorType::Ctor_Base), OS_Mangled);
+
+ASSERT_EQ(Mangled,
[clang] [libcxxabi] [lldb] [llvm] [lldb][Expression] Add structor variant to LLDB's function call labels (PR #149827)
https://github.com/Michael137 updated
https://github.com/llvm/llvm-project/pull/149827
>From 0efab8b369c3938d6b3f441060c5df5f4b9ba739 Mon Sep 17 00:00:00 2001
From: Michael Buch
Date: Mon, 4 Aug 2025 14:20:45 +0100
Subject: [PATCH 1/8] [clang][Mangle] Inject structor type into mangled name
when mangling for LLDB JIT expressions
This patch adds special handling for `AsmLabel`s created by LLDB. LLDB
uses `AsmLabel`s to encode information about a function declaration to
make it easier to locate function symbols when JITing C++ expressions.
For constructors/destructors LLDB doesn't know at the time of creating
the `AsmLabelAttr` which structor variant the expression evaluator will
need to call (this is decided when compiling the expression). So we make
the Clang mangler inject this information into our custom label when
we're JITting the expression.
---
clang/lib/AST/Mangle.cpp | 33 +-
clang/unittests/AST/DeclTest.cpp | 75
2 files changed, 107 insertions(+), 1 deletion(-)
diff --git a/clang/lib/AST/Mangle.cpp b/clang/lib/AST/Mangle.cpp
index 0bfb51c11f0a5..1131477fa7200 100644
--- a/clang/lib/AST/Mangle.cpp
+++ b/clang/lib/AST/Mangle.cpp
@@ -152,6 +152,33 @@ bool MangleContext::shouldMangleDeclName(const NamedDecl
*D) {
return shouldMangleCXXName(D);
}
+static llvm::StringRef g_lldb_func_call_label_prefix = "$__lldb_func:";
+
+/// Given an LLDB function call label, this function prints the label
+/// into \c Out, together with the structor type of \c GD (if the
+/// decl is a constructor/destructor). LLDB knows how to handle mangled
+/// names with this encoding.
+///
+/// Example input label:
+/// $__lldb_func::123:456:~Foo
+///
+/// Example output:
+/// $__lldb_func:D1:123:456:~Foo
+///
+static void emitLLDBAsmLabel(llvm::StringRef label, GlobalDecl GD,
+ llvm::raw_ostream &Out) {
+ assert(label.starts_with(g_lldb_func_call_label_prefix));
+
+ Out << g_lldb_func_call_label_prefix;
+
+ if (llvm::isa(GD.getDecl()))
+Out << "C" << GD.getCtorType();
+ else if (llvm::isa(GD.getDecl()))
+Out << "D" << GD.getDtorType();
+
+ Out << label.substr(g_lldb_func_call_label_prefix.size());
+}
+
void MangleContext::mangleName(GlobalDecl GD, raw_ostream &Out) {
const ASTContext &ASTContext = getASTContext();
const NamedDecl *D = cast(GD.getDecl());
@@ -185,7 +212,11 @@ void MangleContext::mangleName(GlobalDecl GD, raw_ostream
&Out) {
if (!UserLabelPrefix.empty())
Out << '\01'; // LLVM IR Marker for __asm("foo")
-Out << ALA->getLabel();
+if (ALA->getLabel().starts_with(g_lldb_func_call_label_prefix))
+ emitLLDBAsmLabel(ALA->getLabel(), GD, Out);
+else
+ Out << ALA->getLabel();
+
return;
}
diff --git a/clang/unittests/AST/DeclTest.cpp b/clang/unittests/AST/DeclTest.cpp
index afaf413493299..6c7b65d7e82d7 100644
--- a/clang/unittests/AST/DeclTest.cpp
+++ b/clang/unittests/AST/DeclTest.cpp
@@ -16,6 +16,7 @@
#include "clang/AST/Mangle.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Basic/ABI.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/TargetInfo.h"
@@ -102,6 +103,80 @@ TEST(Decl, AsmLabelAttr) {
"foo");
}
+TEST(Decl, AsmLabelAttr_LLDB) {
+ StringRef Code = R"(
+struct S {
+ void f() {}
+ S() = default;
+ ~S() = default;
+};
+ )";
+ auto AST =
+ tooling::buildASTFromCodeWithArgs(Code, {"-target",
"i386-apple-darwin"});
+ ASTContext &Ctx = AST->getASTContext();
+ assert(Ctx.getTargetInfo().getUserLabelPrefix() == StringRef("_") &&
+ "Expected target to have a global prefix");
+ DiagnosticsEngine &Diags = AST->getDiagnostics();
+
+ const auto *DeclS =
+ selectFirst("d", match(cxxRecordDecl().bind("d"), Ctx));
+
+ auto *DeclF = *DeclS->method_begin();
+ auto *Ctor = *DeclS->ctor_begin();
+ auto *Dtor = DeclS->getDestructor();
+
+ ASSERT_TRUE(DeclF);
+ ASSERT_TRUE(Ctor);
+ ASSERT_TRUE(Dtor);
+
+ DeclF->addAttr(AsmLabelAttr::Create(Ctx, "$__lldb_func::123:123:_Z1fv"));
+ Ctor->addAttr(AsmLabelAttr::Create(Ctx, "$__lldb_func::123:123:S"));
+ Dtor->addAttr(AsmLabelAttr::Create(Ctx, "$__lldb_func::123:123:~S"));
+
+ std::unique_ptr MC(
+ ItaniumMangleContext::create(Ctx, Diags));
+
+ {
+std::string Mangled;
+llvm::raw_string_ostream OS_Mangled(Mangled);
+MC->mangleName(DeclF, OS_Mangled);
+
+ASSERT_EQ(Mangled, "\x01$__lldb_func::123:123:_Z1fv");
+ };
+
+ {
+std::string Mangled;
+llvm::raw_string_ostream OS_Mangled(Mangled);
+MC->mangleName(GlobalDecl(Ctor, CXXCtorType::Ctor_Complete), OS_Mangled);
+
+ASSERT_EQ(Mangled, "\x01$__lldb_func:C0:123:123:S");
+ };
+
+ {
+std::string Mangled;
+llvm::raw_string_ostream OS_Mangled(Mangled);
+MC->mangleName(GlobalDecl(Ctor, CXXCtorType::Ctor_Base), OS_Mangled);
+
+ASSERT_EQ(Mangled,
[clang] [libcxxabi] [lldb] [llvm] [lldb][Expression] Add structor variant to LLDB's function call labels (PR #149827)
@@ -2482,6 +2485,134 @@ bool SymbolFileDWARF::ResolveFunction(const DWARFDIE
&orig_die,
return false;
}
+static int ClangToItaniumCtorKind(clang::CXXCtorType kind) {
+ switch (kind) {
+ case clang::CXXCtorType::Ctor_Complete:
+return 1;
+ case clang::CXXCtorType::Ctor_Base:
+return 2;
+ case clang::CXXCtorType::Ctor_CopyingClosure:
+ case clang::CXXCtorType::Ctor_DefaultClosure:
+ case clang::CXXCtorType::Ctor_Comdat:
+llvm_unreachable("Unexpected constructor kind.");
+ }
+}
+
+static int ClangToItaniumDtorKind(clang::CXXDtorType kind) {
+ switch (kind) {
+ case clang::CXXDtorType::Dtor_Deleting:
+return 0;
+ case clang::CXXDtorType::Dtor_Complete:
+return 1;
+ case clang::CXXDtorType::Dtor_Base:
+return 2;
+ case clang::CXXDtorType::Dtor_Comdat:
+llvm_unreachable("Unexpected destructor kind.");
+ }
+}
+
+static std::optional
+GetItaniumCtorDtorVariant(llvm::StringRef discriminator) {
+ const bool is_ctor = discriminator.consume_front("C");
+ if (!is_ctor && !discriminator.consume_front("D"))
+return std::nullopt;
+
+ uint64_t structor_kind;
+ if (!llvm::to_integer(discriminator, structor_kind))
+return std::nullopt;
+
+ if (is_ctor) {
+if (structor_kind > clang::CXXCtorType::Ctor_DefaultClosure)
+ return std::nullopt;
+
+return ClangToItaniumCtorKind(
+static_cast(structor_kind));
+ }
+
+ if (structor_kind > clang::CXXDtorType::Dtor_Comdat)
+return std::nullopt;
+
+ return
ClangToItaniumDtorKind(static_cast(structor_kind));
+}
+
+DWARFDIE SymbolFileDWARF::FindFunctionDefinition(const FunctionCallLabel
&label,
+ const DWARFDIE &declaration) {
+ DWARFDIE definition;
+ llvm::DenseMap structor_variant_to_die;
+
+ // eFunctionNameTypeFull for mangled name lookup.
+ // eFunctionNameTypeMethod is required for structor lookups (since we look
+ // those up by DW_AT_name).
+ Module::LookupInfo info(ConstString(label.lookup_name),
+ lldb::eFunctionNameTypeFull |
+ lldb::eFunctionNameTypeMethod,
+ lldb::eLanguageTypeUnknown);
+
+ m_index->GetFunctions(info, *this, {}, [&](DWARFDIE entry) {
+if (entry.GetAttributeValueAsUnsigned(llvm::dwarf::DW_AT_declaration, 0))
+ return IterationAction::Continue;
+
+auto spec = entry.GetAttributeValueAsReferenceDIE(DW_AT_specification);
+if (!spec)
+ return IterationAction::Continue;
+
+if (spec != declaration)
labath wrote:
> But I think it would be one of the pre-requisites to landing this, right?
Yeah, I suppose that's true.
https://github.com/llvm/llvm-project/pull/149827
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libcxxabi] [lldb] [llvm] [lldb][Expression] Add structor variant to LLDB's function call labels (PR #149827)
@@ -2482,6 +2485,134 @@ bool SymbolFileDWARF::ResolveFunction(const DWARFDIE
&orig_die,
return false;
}
+static int ClangToItaniumCtorKind(clang::CXXCtorType kind) {
+ switch (kind) {
+ case clang::CXXCtorType::Ctor_Complete:
+return 1;
+ case clang::CXXCtorType::Ctor_Base:
+return 2;
+ case clang::CXXCtorType::Ctor_CopyingClosure:
+ case clang::CXXCtorType::Ctor_DefaultClosure:
+ case clang::CXXCtorType::Ctor_Comdat:
+llvm_unreachable("Unexpected constructor kind.");
+ }
+}
+
+static int ClangToItaniumDtorKind(clang::CXXDtorType kind) {
+ switch (kind) {
+ case clang::CXXDtorType::Dtor_Deleting:
+return 0;
+ case clang::CXXDtorType::Dtor_Complete:
+return 1;
+ case clang::CXXDtorType::Dtor_Base:
+return 2;
+ case clang::CXXDtorType::Dtor_Comdat:
+llvm_unreachable("Unexpected destructor kind.");
+ }
+}
+
+static std::optional
+GetItaniumCtorDtorVariant(llvm::StringRef discriminator) {
+ const bool is_ctor = discriminator.consume_front("C");
+ if (!is_ctor && !discriminator.consume_front("D"))
+return std::nullopt;
+
+ uint64_t structor_kind;
+ if (!llvm::to_integer(discriminator, structor_kind))
+return std::nullopt;
+
+ if (is_ctor) {
+if (structor_kind > clang::CXXCtorType::Ctor_DefaultClosure)
+ return std::nullopt;
+
+return ClangToItaniumCtorKind(
+static_cast(structor_kind));
+ }
+
+ if (structor_kind > clang::CXXDtorType::Dtor_Comdat)
+return std::nullopt;
+
+ return
ClangToItaniumDtorKind(static_cast(structor_kind));
+}
+
+DWARFDIE SymbolFileDWARF::FindFunctionDefinition(const FunctionCallLabel
&label,
+ const DWARFDIE &declaration) {
+ DWARFDIE definition;
+ llvm::DenseMap structor_variant_to_die;
+
+ // eFunctionNameTypeFull for mangled name lookup.
+ // eFunctionNameTypeMethod is required for structor lookups (since we look
+ // those up by DW_AT_name).
+ Module::LookupInfo info(ConstString(label.lookup_name),
+ lldb::eFunctionNameTypeFull |
+ lldb::eFunctionNameTypeMethod,
+ lldb::eLanguageTypeUnknown);
+
+ m_index->GetFunctions(info, *this, {}, [&](DWARFDIE entry) {
+if (entry.GetAttributeValueAsUnsigned(llvm::dwarf::DW_AT_declaration, 0))
+ return IterationAction::Continue;
+
+auto spec = entry.GetAttributeValueAsReferenceDIE(DW_AT_specification);
+if (!spec)
+ return IterationAction::Continue;
+
+if (spec != declaration)
Michael137 wrote:
> Getting the information from one module to another would be tricky, but not
> impossible
But I think it would be one of the pre-requisites to landing this, right? Since
that already works today (albeit maybe not completely correctly for all cases),
and seems like a common thing people would run into in a non-trivial program.
> That said, the idea to add linkage names to constructors makes perfect sense
> as well. It aligns with what gcc does for constructors and also aligns with
> what both gcc and clang do with regular functions. I am slightly worried
> about what will that do to debug info size, but I can't say if that will be a
> problem or not.
Let me see what the debug-info size impact of this would be
https://github.com/llvm/llvm-project/pull/149827
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libcxxabi] [lldb] [llvm] [lldb][Expression] Add structor variant to LLDB's function call labels (PR #149827)
https://github.com/Michael137 updated
https://github.com/llvm/llvm-project/pull/149827
>From 0efab8b369c3938d6b3f441060c5df5f4b9ba739 Mon Sep 17 00:00:00 2001
From: Michael Buch
Date: Mon, 4 Aug 2025 14:20:45 +0100
Subject: [PATCH 1/7] [clang][Mangle] Inject structor type into mangled name
when mangling for LLDB JIT expressions
This patch adds special handling for `AsmLabel`s created by LLDB. LLDB
uses `AsmLabel`s to encode information about a function declaration to
make it easier to locate function symbols when JITing C++ expressions.
For constructors/destructors LLDB doesn't know at the time of creating
the `AsmLabelAttr` which structor variant the expression evaluator will
need to call (this is decided when compiling the expression). So we make
the Clang mangler inject this information into our custom label when
we're JITting the expression.
---
clang/lib/AST/Mangle.cpp | 33 +-
clang/unittests/AST/DeclTest.cpp | 75
2 files changed, 107 insertions(+), 1 deletion(-)
diff --git a/clang/lib/AST/Mangle.cpp b/clang/lib/AST/Mangle.cpp
index 0bfb51c11f0a5..1131477fa7200 100644
--- a/clang/lib/AST/Mangle.cpp
+++ b/clang/lib/AST/Mangle.cpp
@@ -152,6 +152,33 @@ bool MangleContext::shouldMangleDeclName(const NamedDecl
*D) {
return shouldMangleCXXName(D);
}
+static llvm::StringRef g_lldb_func_call_label_prefix = "$__lldb_func:";
+
+/// Given an LLDB function call label, this function prints the label
+/// into \c Out, together with the structor type of \c GD (if the
+/// decl is a constructor/destructor). LLDB knows how to handle mangled
+/// names with this encoding.
+///
+/// Example input label:
+/// $__lldb_func::123:456:~Foo
+///
+/// Example output:
+/// $__lldb_func:D1:123:456:~Foo
+///
+static void emitLLDBAsmLabel(llvm::StringRef label, GlobalDecl GD,
+ llvm::raw_ostream &Out) {
+ assert(label.starts_with(g_lldb_func_call_label_prefix));
+
+ Out << g_lldb_func_call_label_prefix;
+
+ if (llvm::isa(GD.getDecl()))
+Out << "C" << GD.getCtorType();
+ else if (llvm::isa(GD.getDecl()))
+Out << "D" << GD.getDtorType();
+
+ Out << label.substr(g_lldb_func_call_label_prefix.size());
+}
+
void MangleContext::mangleName(GlobalDecl GD, raw_ostream &Out) {
const ASTContext &ASTContext = getASTContext();
const NamedDecl *D = cast(GD.getDecl());
@@ -185,7 +212,11 @@ void MangleContext::mangleName(GlobalDecl GD, raw_ostream
&Out) {
if (!UserLabelPrefix.empty())
Out << '\01'; // LLVM IR Marker for __asm("foo")
-Out << ALA->getLabel();
+if (ALA->getLabel().starts_with(g_lldb_func_call_label_prefix))
+ emitLLDBAsmLabel(ALA->getLabel(), GD, Out);
+else
+ Out << ALA->getLabel();
+
return;
}
diff --git a/clang/unittests/AST/DeclTest.cpp b/clang/unittests/AST/DeclTest.cpp
index afaf413493299..6c7b65d7e82d7 100644
--- a/clang/unittests/AST/DeclTest.cpp
+++ b/clang/unittests/AST/DeclTest.cpp
@@ -16,6 +16,7 @@
#include "clang/AST/Mangle.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Basic/ABI.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/TargetInfo.h"
@@ -102,6 +103,80 @@ TEST(Decl, AsmLabelAttr) {
"foo");
}
+TEST(Decl, AsmLabelAttr_LLDB) {
+ StringRef Code = R"(
+struct S {
+ void f() {}
+ S() = default;
+ ~S() = default;
+};
+ )";
+ auto AST =
+ tooling::buildASTFromCodeWithArgs(Code, {"-target",
"i386-apple-darwin"});
+ ASTContext &Ctx = AST->getASTContext();
+ assert(Ctx.getTargetInfo().getUserLabelPrefix() == StringRef("_") &&
+ "Expected target to have a global prefix");
+ DiagnosticsEngine &Diags = AST->getDiagnostics();
+
+ const auto *DeclS =
+ selectFirst("d", match(cxxRecordDecl().bind("d"), Ctx));
+
+ auto *DeclF = *DeclS->method_begin();
+ auto *Ctor = *DeclS->ctor_begin();
+ auto *Dtor = DeclS->getDestructor();
+
+ ASSERT_TRUE(DeclF);
+ ASSERT_TRUE(Ctor);
+ ASSERT_TRUE(Dtor);
+
+ DeclF->addAttr(AsmLabelAttr::Create(Ctx, "$__lldb_func::123:123:_Z1fv"));
+ Ctor->addAttr(AsmLabelAttr::Create(Ctx, "$__lldb_func::123:123:S"));
+ Dtor->addAttr(AsmLabelAttr::Create(Ctx, "$__lldb_func::123:123:~S"));
+
+ std::unique_ptr MC(
+ ItaniumMangleContext::create(Ctx, Diags));
+
+ {
+std::string Mangled;
+llvm::raw_string_ostream OS_Mangled(Mangled);
+MC->mangleName(DeclF, OS_Mangled);
+
+ASSERT_EQ(Mangled, "\x01$__lldb_func::123:123:_Z1fv");
+ };
+
+ {
+std::string Mangled;
+llvm::raw_string_ostream OS_Mangled(Mangled);
+MC->mangleName(GlobalDecl(Ctor, CXXCtorType::Ctor_Complete), OS_Mangled);
+
+ASSERT_EQ(Mangled, "\x01$__lldb_func:C0:123:123:S");
+ };
+
+ {
+std::string Mangled;
+llvm::raw_string_ostream OS_Mangled(Mangled);
+MC->mangleName(GlobalDecl(Ctor, CXXCtorType::Ctor_Base), OS_Mangled);
+
+ASSERT_EQ(Mangled,
[clang] [libcxxabi] [lldb] [llvm] [lldb][Expression] Add structor variant to LLDB's function call labels (PR #149827)
@@ -2482,6 +2485,134 @@ bool SymbolFileDWARF::ResolveFunction(const DWARFDIE
&orig_die,
return false;
}
+static int ClangToItaniumCtorKind(clang::CXXCtorType kind) {
+ switch (kind) {
+ case clang::CXXCtorType::Ctor_Complete:
+return 1;
+ case clang::CXXCtorType::Ctor_Base:
+return 2;
+ case clang::CXXCtorType::Ctor_CopyingClosure:
+ case clang::CXXCtorType::Ctor_DefaultClosure:
+ case clang::CXXCtorType::Ctor_Comdat:
+llvm_unreachable("Unexpected constructor kind.");
+ }
+}
+
+static int ClangToItaniumDtorKind(clang::CXXDtorType kind) {
+ switch (kind) {
+ case clang::CXXDtorType::Dtor_Deleting:
+return 0;
+ case clang::CXXDtorType::Dtor_Complete:
+return 1;
+ case clang::CXXDtorType::Dtor_Base:
+return 2;
+ case clang::CXXDtorType::Dtor_Comdat:
+llvm_unreachable("Unexpected destructor kind.");
+ }
+}
+
+static std::optional
+GetItaniumCtorDtorVariant(llvm::StringRef discriminator) {
+ const bool is_ctor = discriminator.consume_front("C");
+ if (!is_ctor && !discriminator.consume_front("D"))
+return std::nullopt;
+
+ uint64_t structor_kind;
+ if (!llvm::to_integer(discriminator, structor_kind))
+return std::nullopt;
+
+ if (is_ctor) {
+if (structor_kind > clang::CXXCtorType::Ctor_DefaultClosure)
+ return std::nullopt;
+
+return ClangToItaniumCtorKind(
+static_cast(structor_kind));
+ }
+
+ if (structor_kind > clang::CXXDtorType::Dtor_Comdat)
+return std::nullopt;
+
+ return
ClangToItaniumDtorKind(static_cast(structor_kind));
+}
+
+DWARFDIE SymbolFileDWARF::FindFunctionDefinition(const FunctionCallLabel
&label,
+ const DWARFDIE &declaration) {
+ DWARFDIE definition;
+ llvm::DenseMap structor_variant_to_die;
+
+ // eFunctionNameTypeFull for mangled name lookup.
+ // eFunctionNameTypeMethod is required for structor lookups (since we look
+ // those up by DW_AT_name).
+ Module::LookupInfo info(ConstString(label.lookup_name),
+ lldb::eFunctionNameTypeFull |
+ lldb::eFunctionNameTypeMethod,
+ lldb::eLanguageTypeUnknown);
+
+ m_index->GetFunctions(info, *this, {}, [&](DWARFDIE entry) {
+if (entry.GetAttributeValueAsUnsigned(llvm::dwarf::DW_AT_declaration, 0))
+ return IterationAction::Continue;
+
+auto spec = entry.GetAttributeValueAsReferenceDIE(DW_AT_specification);
+if (!spec)
+ return IterationAction::Continue;
+
+if (spec != declaration)
labath wrote:
If both modules are DWARF, then I think it's doable. Getting the information
from one module to another would be tricky, but not impossible. And I don't
think there's a particularly pressing need to resolve DWARF declarations with
definitions from a PDB.
That said, the idea to add linkage names to constructors makes perfect sense as
well. It aligns with what gcc does for constructors and also aligns with what
both gcc and clang do with regular functions. I am slightly worried about what
will that do to debug info size, but I can't say if that will be a problem or
not.
https://github.com/llvm/llvm-project/pull/149827
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libcxxabi] [lldb] [llvm] [lldb][Expression] Add structor variant to LLDB's function call labels (PR #149827)
@@ -2482,6 +2485,134 @@ bool SymbolFileDWARF::ResolveFunction(const DWARFDIE
&orig_die,
return false;
}
+static int ClangToItaniumCtorKind(clang::CXXCtorType kind) {
+ switch (kind) {
+ case clang::CXXCtorType::Ctor_Complete:
+return 1;
+ case clang::CXXCtorType::Ctor_Base:
+return 2;
+ case clang::CXXCtorType::Ctor_CopyingClosure:
+ case clang::CXXCtorType::Ctor_DefaultClosure:
+ case clang::CXXCtorType::Ctor_Comdat:
+llvm_unreachable("Unexpected constructor kind.");
+ }
+}
+
+static int ClangToItaniumDtorKind(clang::CXXDtorType kind) {
+ switch (kind) {
+ case clang::CXXDtorType::Dtor_Deleting:
+return 0;
+ case clang::CXXDtorType::Dtor_Complete:
+return 1;
+ case clang::CXXDtorType::Dtor_Base:
+return 2;
+ case clang::CXXDtorType::Dtor_Comdat:
+llvm_unreachable("Unexpected destructor kind.");
+ }
+}
+
+static std::optional
+GetItaniumCtorDtorVariant(llvm::StringRef discriminator) {
+ const bool is_ctor = discriminator.consume_front("C");
+ if (!is_ctor && !discriminator.consume_front("D"))
+return std::nullopt;
+
+ uint64_t structor_kind;
+ if (!llvm::to_integer(discriminator, structor_kind))
+return std::nullopt;
+
+ if (is_ctor) {
+if (structor_kind > clang::CXXCtorType::Ctor_DefaultClosure)
+ return std::nullopt;
+
+return ClangToItaniumCtorKind(
+static_cast(structor_kind));
+ }
+
+ if (structor_kind > clang::CXXDtorType::Dtor_Comdat)
+return std::nullopt;
+
+ return
ClangToItaniumDtorKind(static_cast(structor_kind));
+}
+
+DWARFDIE SymbolFileDWARF::FindFunctionDefinition(const FunctionCallLabel
&label,
+ const DWARFDIE &declaration) {
+ DWARFDIE definition;
+ llvm::DenseMap structor_variant_to_die;
+
+ // eFunctionNameTypeFull for mangled name lookup.
+ // eFunctionNameTypeMethod is required for structor lookups (since we look
+ // those up by DW_AT_name).
+ Module::LookupInfo info(ConstString(label.lookup_name),
+ lldb::eFunctionNameTypeFull |
+ lldb::eFunctionNameTypeMethod,
+ lldb::eLanguageTypeUnknown);
+
+ m_index->GetFunctions(info, *this, {}, [&](DWARFDIE entry) {
+if (entry.GetAttributeValueAsUnsigned(llvm::dwarf::DW_AT_declaration, 0))
+ return IterationAction::Continue;
+
+auto spec = entry.GetAttributeValueAsReferenceDIE(DW_AT_specification);
+if (!spec)
+ return IterationAction::Continue;
+
+if (spec != declaration)
labath wrote:
> For the structural match, were you suggesting we re-use the innards of
> `CopyUniqueClassMethodTypes` to do so, or that there is something on the
> `DWARFASTParserClang` that should've been cached about the fact that the two
> DIEs are structurally the same?
I'm not sure. It would be great if we could reuse that code, but it may require
refactoring something. I can't say I'm very familiar with how that code works
-- I just know it's used in situations (see the `class_type->GetID() !=
decl_ctx_die.GetID()` check in `DWARFASTParserClang::ParseCXXMethod`) where we
parse type from a DIE which is different that the type DIE we found by parsing
one of its methods -- which sounds very similar to the situation we have here.
I don't think we can rely on anything being cached already, because lldb may
not have had a reason to access the CU containing this constructor yet, but we
may be able to force that information into cache by calling `ParseCXXMethod` or
some part of it.
https://github.com/llvm/llvm-project/pull/149827
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libcxxabi] [lldb] [llvm] [lldb][Expression] Add structor variant to LLDB's function call labels (PR #149827)
@@ -2482,6 +2485,134 @@ bool SymbolFileDWARF::ResolveFunction(const DWARFDIE
&orig_die,
return false;
}
+static int ClangToItaniumCtorKind(clang::CXXCtorType kind) {
+ switch (kind) {
+ case clang::CXXCtorType::Ctor_Complete:
+return 1;
+ case clang::CXXCtorType::Ctor_Base:
+return 2;
+ case clang::CXXCtorType::Ctor_CopyingClosure:
+ case clang::CXXCtorType::Ctor_DefaultClosure:
+ case clang::CXXCtorType::Ctor_Comdat:
+llvm_unreachable("Unexpected constructor kind.");
+ }
+}
+
+static int ClangToItaniumDtorKind(clang::CXXDtorType kind) {
+ switch (kind) {
+ case clang::CXXDtorType::Dtor_Deleting:
+return 0;
+ case clang::CXXDtorType::Dtor_Complete:
+return 1;
+ case clang::CXXDtorType::Dtor_Base:
+return 2;
+ case clang::CXXDtorType::Dtor_Comdat:
+llvm_unreachable("Unexpected destructor kind.");
+ }
+}
+
+static std::optional
+GetItaniumCtorDtorVariant(llvm::StringRef discriminator) {
+ const bool is_ctor = discriminator.consume_front("C");
+ if (!is_ctor && !discriminator.consume_front("D"))
+return std::nullopt;
+
+ uint64_t structor_kind;
+ if (!llvm::to_integer(discriminator, structor_kind))
+return std::nullopt;
+
+ if (is_ctor) {
+if (structor_kind > clang::CXXCtorType::Ctor_DefaultClosure)
+ return std::nullopt;
+
+return ClangToItaniumCtorKind(
+static_cast(structor_kind));
+ }
+
+ if (structor_kind > clang::CXXDtorType::Dtor_Comdat)
+return std::nullopt;
+
+ return
ClangToItaniumDtorKind(static_cast(structor_kind));
+}
+
+DWARFDIE SymbolFileDWARF::FindFunctionDefinition(const FunctionCallLabel
&label,
+ const DWARFDIE &declaration) {
+ DWARFDIE definition;
+ llvm::DenseMap structor_variant_to_die;
+
+ // eFunctionNameTypeFull for mangled name lookup.
+ // eFunctionNameTypeMethod is required for structor lookups (since we look
+ // those up by DW_AT_name).
+ Module::LookupInfo info(ConstString(label.lookup_name),
+ lldb::eFunctionNameTypeFull |
+ lldb::eFunctionNameTypeMethod,
+ lldb::eLanguageTypeUnknown);
+
+ m_index->GetFunctions(info, *this, {}, [&](DWARFDIE entry) {
+if (entry.GetAttributeValueAsUnsigned(llvm::dwarf::DW_AT_declaration, 0))
+ return IterationAction::Continue;
+
+auto spec = entry.GetAttributeValueAsReferenceDIE(DW_AT_specification);
+if (!spec)
+ return IterationAction::Continue;
+
+if (spec != declaration)
Michael137 wrote:
> Unless I'm mistaked, if we start attaching asm labels to constructors, we
> will suppress that behavior, and we only get whatever name we put into the
> asm label -- currently that's the bare name of the constructor. That is
> woefully inadequate the find the right constructor -- in any module. Even if
> there is just a single class with that name, there's no way to tell which
> constructor (out of potentially many) is that name referring to.
Yes very true, I got confused. The fallback wouldn't find the name correctly
for structors, only for functions with proper mangled names. That's quite
tricky since it does work today. So it would regress unless we address the
cross-module problem.
https://github.com/llvm/llvm-project/pull/149827
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libcxxabi] [lldb] [llvm] [lldb][Expression] Add structor variant to LLDB's function call labels (PR #149827)
https://github.com/Michael137 updated
https://github.com/llvm/llvm-project/pull/149827
>From b8f31ec8f556169a45370938cf28bd8582134a5c Mon Sep 17 00:00:00 2001
From: Michael Buch
Date: Sun, 3 Aug 2025 11:38:07 +0100
Subject: [PATCH 1/8] [clang][Attr] Remove 'literal label' form of AsmLabelAttr
This was added purely for the needs of LLDB. However, starting with
https://github.com/llvm/llvm-project/pull/151355 and
https://github.com/llvm/llvm-project/pull/148877 we no longer create literal
AsmLabels in LLDB either. So this is unused and we can get rid of it.
In the near future LLDB will want to add special support for mangling
`AsmLabel`s, and the "literal label" codepath in the mangler made this more
cumbersome.
(cherry picked from commit 342f0d5cd722ae7ec3f48f136472923ce38f9981)
---
clang/include/clang/Basic/Attr.td | 17 -
clang/lib/AST/Mangle.cpp| 4 ++--
clang/lib/Sema/SemaDecl.cpp | 13 +
clang/unittests/AST/DeclTest.cpp| 9 +
.../TypeSystem/Clang/TypeSystemClang.cpp| 7 +++
5 files changed, 15 insertions(+), 35 deletions(-)
diff --git a/clang/include/clang/Basic/Attr.td
b/clang/include/clang/Basic/Attr.td
index b3ff45b3e90a3..a0efb21218312 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -1059,22 +1059,13 @@ def AVRSignal : InheritableAttr,
TargetSpecificAttr {
def AsmLabel : InheritableAttr {
let Spellings = [CustomKeyword<"asm">, CustomKeyword<"__asm__">];
let Args = [
-// Label specifies the mangled name for the decl.
-StringArgument<"Label">,
-
-// IsLiteralLabel specifies whether the label is literal (i.e. suppresses
-// the global C symbol prefix) or not. If not, the mangle-suppression
prefix
-// ('\01') is omitted from the decl name at the LLVM IR level.
-//
-// Non-literal labels are used by some external AST sources like LLDB.
-BoolArgument<"IsLiteralLabel", /*optional=*/0, /*fake=*/1>
- ];
+ // Label specifies the mangled name for the decl.
+ StringArgument<"Label">, ];
let SemaHandler = 0;
let Documentation = [AsmLabelDocs];
- let AdditionalMembers =
-[{
+ let AdditionalMembers = [{
bool isEquivalent(AsmLabelAttr *Other) const {
- return getLabel() == Other->getLabel() && getIsLiteralLabel() ==
Other->getIsLiteralLabel();
+ return getLabel() == Other->getLabel();
}
}];
}
diff --git a/clang/lib/AST/Mangle.cpp b/clang/lib/AST/Mangle.cpp
index 9652fdbc4e125..0bfb51c11f0a5 100644
--- a/clang/lib/AST/Mangle.cpp
+++ b/clang/lib/AST/Mangle.cpp
@@ -161,9 +161,9 @@ void MangleContext::mangleName(GlobalDecl GD, raw_ostream
&Out) {
if (const AsmLabelAttr *ALA = D->getAttr()) {
// If we have an asm name, then we use it as the mangling.
-// If the label isn't literal, or if this is an alias for an LLVM
intrinsic,
+// If the label is an alias for an LLVM intrinsic,
// do not add a "\01" prefix.
-if (!ALA->getIsLiteralLabel() || ALA->getLabel().starts_with("llvm.")) {
+if (ALA->getLabel().starts_with("llvm.")) {
Out << ALA->getLabel();
return;
}
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index e2ac648320c0f..885d04b9ab926 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -8113,9 +8113,7 @@ NamedDecl *Sema::ActOnVariableDeclarator(
}
}
-NewVD->addAttr(AsmLabelAttr::Create(Context, Label,
-/*IsLiteralLabel=*/true,
-SE->getStrTokenLoc(0)));
+NewVD->addAttr(AsmLabelAttr::Create(Context, Label,
SE->getStrTokenLoc(0)));
} else if (!ExtnameUndeclaredIdentifiers.empty()) {
llvm::DenseMap::iterator I =
ExtnameUndeclaredIdentifiers.find(NewVD->getIdentifier());
@@ -10345,9 +10343,8 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D,
DeclContext *DC,
if (Expr *E = D.getAsmLabel()) {
// The parser guarantees this is a string.
StringLiteral *SE = cast(E);
-NewFD->addAttr(AsmLabelAttr::Create(Context, SE->getString(),
-/*IsLiteralLabel=*/true,
-SE->getStrTokenLoc(0)));
+NewFD->addAttr(
+AsmLabelAttr::Create(Context, SE->getString(), SE->getStrTokenLoc(0)));
} else if (!ExtnameUndeclaredIdentifiers.empty()) {
llvm::DenseMap::iterator I =
ExtnameUndeclaredIdentifiers.find(NewFD->getIdentifier());
@@ -20598,8 +20595,8 @@ void Sema::ActOnPragmaRedefineExtname(IdentifierInfo*
Name,
LookupOrdinaryName);
AttributeCommonInfo Info(AliasName, SourceRange(AliasNameLoc),
AttributeCommonInfo::Form::Pragma());
- AsmLabelAttr *Attr = AsmLabelAttr::CreateImplicit(
- Context, AliasName->getName(), /*IsLiteralLabel=*/true, Info);
+ AsmLabelAttr *Attr =
+ AsmLab
[clang] [libcxxabi] [lldb] [llvm] [lldb][Expression] Add structor variant to LLDB's function call labels (PR #149827)
@@ -2482,6 +2485,134 @@ bool SymbolFileDWARF::ResolveFunction(const DWARFDIE
&orig_die,
return false;
}
+static int ClangToItaniumCtorKind(clang::CXXCtorType kind) {
+ switch (kind) {
+ case clang::CXXCtorType::Ctor_Complete:
+return 1;
+ case clang::CXXCtorType::Ctor_Base:
+return 2;
+ case clang::CXXCtorType::Ctor_CopyingClosure:
+ case clang::CXXCtorType::Ctor_DefaultClosure:
+ case clang::CXXCtorType::Ctor_Comdat:
+llvm_unreachable("Unexpected constructor kind.");
+ }
+}
+
+static int ClangToItaniumDtorKind(clang::CXXDtorType kind) {
+ switch (kind) {
+ case clang::CXXDtorType::Dtor_Deleting:
+return 0;
+ case clang::CXXDtorType::Dtor_Complete:
+return 1;
+ case clang::CXXDtorType::Dtor_Base:
+return 2;
+ case clang::CXXDtorType::Dtor_Comdat:
+llvm_unreachable("Unexpected destructor kind.");
+ }
+}
+
+static std::optional
+GetItaniumCtorDtorVariant(llvm::StringRef discriminator) {
+ const bool is_ctor = discriminator.consume_front("C");
+ if (!is_ctor && !discriminator.consume_front("D"))
+return std::nullopt;
+
+ uint64_t structor_kind;
+ if (!llvm::to_integer(discriminator, structor_kind))
+return std::nullopt;
+
+ if (is_ctor) {
+if (structor_kind > clang::CXXCtorType::Ctor_DefaultClosure)
+ return std::nullopt;
+
+return ClangToItaniumCtorKind(
+static_cast(structor_kind));
+ }
+
+ if (structor_kind > clang::CXXDtorType::Dtor_Comdat)
+return std::nullopt;
+
+ return
ClangToItaniumDtorKind(static_cast(structor_kind));
+}
+
+DWARFDIE SymbolFileDWARF::FindFunctionDefinition(const FunctionCallLabel
&label,
+ const DWARFDIE &declaration) {
+ DWARFDIE definition;
+ llvm::DenseMap structor_variant_to_die;
+
+ // eFunctionNameTypeFull for mangled name lookup.
+ // eFunctionNameTypeMethod is required for structor lookups (since we look
+ // those up by DW_AT_name).
+ Module::LookupInfo info(ConstString(label.lookup_name),
+ lldb::eFunctionNameTypeFull |
+ lldb::eFunctionNameTypeMethod,
+ lldb::eLanguageTypeUnknown);
+
+ m_index->GetFunctions(info, *this, {}, [&](DWARFDIE entry) {
+if (entry.GetAttributeValueAsUnsigned(llvm::dwarf::DW_AT_declaration, 0))
+ return IterationAction::Continue;
+
+auto spec = entry.GetAttributeValueAsReferenceDIE(DW_AT_specification);
+if (!spec)
+ return IterationAction::Continue;
+
+if (spec != declaration)
labath wrote:
> For constructors we just would behave as we do today.
Is that true? Today, we don't attach any asm labels to a constructor, which
means it gets the mangled name according to normal rules. If we get that right
(the AST fidelity is good enough) we get the correct mangled name, and we can
look up the constructor this way.
Unless I'm mistaked, if we start attaching asm labels to constructors, we will
suppress that behavior, and we only get whatever name we put into the asm label
-- currently that's the bare name of the constructor. That is woefully
inadequate the find the right constructor -- in *any* module. Even if there is
just a single class with that name, there's no way to tell which constructor
(out of potentially many) is that name referring to.
https://github.com/llvm/llvm-project/pull/149827
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libcxxabi] [lldb] [llvm] [lldb][Expression] Add structor variant to LLDB's function call labels (PR #149827)
@@ -2482,6 +2485,134 @@ bool SymbolFileDWARF::ResolveFunction(const DWARFDIE
&orig_die,
return false;
}
+static int ClangToItaniumCtorKind(clang::CXXCtorType kind) {
+ switch (kind) {
+ case clang::CXXCtorType::Ctor_Complete:
+return 1;
+ case clang::CXXCtorType::Ctor_Base:
+return 2;
+ case clang::CXXCtorType::Ctor_CopyingClosure:
+ case clang::CXXCtorType::Ctor_DefaultClosure:
+ case clang::CXXCtorType::Ctor_Comdat:
+llvm_unreachable("Unexpected constructor kind.");
+ }
+}
+
+static int ClangToItaniumDtorKind(clang::CXXDtorType kind) {
+ switch (kind) {
+ case clang::CXXDtorType::Dtor_Deleting:
+return 0;
+ case clang::CXXDtorType::Dtor_Complete:
+return 1;
+ case clang::CXXDtorType::Dtor_Base:
+return 2;
+ case clang::CXXDtorType::Dtor_Comdat:
+llvm_unreachable("Unexpected destructor kind.");
+ }
+}
+
+static std::optional
+GetItaniumCtorDtorVariant(llvm::StringRef discriminator) {
+ const bool is_ctor = discriminator.consume_front("C");
+ if (!is_ctor && !discriminator.consume_front("D"))
+return std::nullopt;
+
+ uint64_t structor_kind;
+ if (!llvm::to_integer(discriminator, structor_kind))
+return std::nullopt;
+
+ if (is_ctor) {
+if (structor_kind > clang::CXXCtorType::Ctor_DefaultClosure)
+ return std::nullopt;
+
+return ClangToItaniumCtorKind(
+static_cast(structor_kind));
+ }
+
+ if (structor_kind > clang::CXXDtorType::Dtor_Comdat)
+return std::nullopt;
+
+ return
ClangToItaniumDtorKind(static_cast(structor_kind));
+}
+
+DWARFDIE SymbolFileDWARF::FindFunctionDefinition(const FunctionCallLabel
&label,
+ const DWARFDIE &declaration) {
+ DWARFDIE definition;
+ llvm::DenseMap structor_variant_to_die;
+
+ // eFunctionNameTypeFull for mangled name lookup.
+ // eFunctionNameTypeMethod is required for structor lookups (since we look
+ // those up by DW_AT_name).
+ Module::LookupInfo info(ConstString(label.lookup_name),
+ lldb::eFunctionNameTypeFull |
+ lldb::eFunctionNameTypeMethod,
+ lldb::eLanguageTypeUnknown);
+
+ m_index->GetFunctions(info, *this, {}, [&](DWARFDIE entry) {
+if (entry.GetAttributeValueAsUnsigned(llvm::dwarf::DW_AT_declaration, 0))
+ return IterationAction::Continue;
+
+auto spec = entry.GetAttributeValueAsReferenceDIE(DW_AT_specification);
+if (!spec)
+ return IterationAction::Continue;
+
+if (spec != declaration)
labath wrote:
> Would a structural match here help though? If the declaration DIE for a ctor
> got encoded into the AsmLabel but the definition lives in a different CU (and
> thus SymbolFile), we wouldn't be able to find it anyway using our approach
> right?
The scenario I have in mind is this:
```
$ head a.h a.cc b.cc
==> a.h <==
struct A {
int x;
A();
};
==> a.cc <==
#include "a.h"
A a;
int main() {
return a.x;
}
==> b.cc <==
#include "a.h"
A::A() : x(47) {}
```
if you compile this (on linux you need to use -fstandalone-debug to get the
definition of `A` in both files, on darwin you need to make sure dsymutil
doesn't get run an coalesce the definitions), you will have a definition of `A`
in both files, a *declaration* of `A::A` in both files, and a *definition* of
`A::A` in `b.o` *only*.
The existence of two declarations is the problem. We normally assume, per the
ODR rule, that two definitions of the type are equivalent. And they basically
are -- the two definitions of `A` (and the declaration of `A::A` contained
within them) will have the exact same DIE tree. But of course, only one of
those DIEs will be referred to via `DW_AT_specification` from the definition of
`A::A`.
If lldb parses `A` using the definition from `a.o` (the easiest way to ensure
that is do a `target variable a` -- this makes lldb reach the `A` DIE by
following the `DW_AT_type` from the variable `a` (which exists only in `a.o`),
the type and all of the methods contained within it will be associated with the
copies in `a.o`. This will cause a mismatch as that not the DIE you will reach
by following `DW_AT_specification` from the constructor definition.
Some sort of a structural match is needed to ensure the two DIEs are in fact
the same constructor. You're right that this only works if the two types are in
the same module (I consider a collection of `.o` modules on Darwin as a single
module as there's SymbolFileDWARFDebugMap sitting on top of them), but I hope
that's enough for now. We could do it across modules, but we'd have to come up
with a way to compare DIE trees across modules (without breaking plugin
abstractions).
https://github.com/llvm/llvm-project/pull/149827
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libcxxabi] [lldb] [llvm] [lldb][Expression] Add structor variant to LLDB's function call labels (PR #149827)
@@ -2482,6 +2485,134 @@ bool SymbolFileDWARF::ResolveFunction(const DWARFDIE
&orig_die,
return false;
}
+static int ClangToItaniumCtorKind(clang::CXXCtorType kind) {
+ switch (kind) {
+ case clang::CXXCtorType::Ctor_Complete:
+return 1;
+ case clang::CXXCtorType::Ctor_Base:
+return 2;
+ case clang::CXXCtorType::Ctor_CopyingClosure:
+ case clang::CXXCtorType::Ctor_DefaultClosure:
+ case clang::CXXCtorType::Ctor_Comdat:
+llvm_unreachable("Unexpected constructor kind.");
+ }
+}
+
+static int ClangToItaniumDtorKind(clang::CXXDtorType kind) {
+ switch (kind) {
+ case clang::CXXDtorType::Dtor_Deleting:
+return 0;
+ case clang::CXXDtorType::Dtor_Complete:
+return 1;
+ case clang::CXXDtorType::Dtor_Base:
+return 2;
+ case clang::CXXDtorType::Dtor_Comdat:
+llvm_unreachable("Unexpected destructor kind.");
+ }
+}
+
+static std::optional
+GetItaniumCtorDtorVariant(llvm::StringRef discriminator) {
+ const bool is_ctor = discriminator.consume_front("C");
+ if (!is_ctor && !discriminator.consume_front("D"))
+return std::nullopt;
+
+ uint64_t structor_kind;
+ if (!llvm::to_integer(discriminator, structor_kind))
+return std::nullopt;
+
+ if (is_ctor) {
+if (structor_kind > clang::CXXCtorType::Ctor_DefaultClosure)
+ return std::nullopt;
+
+return ClangToItaniumCtorKind(
+static_cast(structor_kind));
+ }
+
+ if (structor_kind > clang::CXXDtorType::Dtor_Comdat)
+return std::nullopt;
+
+ return
ClangToItaniumDtorKind(static_cast(structor_kind));
+}
+
+DWARFDIE SymbolFileDWARF::FindFunctionDefinition(const FunctionCallLabel
&label,
+ const DWARFDIE &declaration) {
+ DWARFDIE definition;
+ llvm::DenseMap structor_variant_to_die;
+
+ // eFunctionNameTypeFull for mangled name lookup.
+ // eFunctionNameTypeMethod is required for structor lookups (since we look
+ // those up by DW_AT_name).
+ Module::LookupInfo info(ConstString(label.lookup_name),
+ lldb::eFunctionNameTypeFull |
+ lldb::eFunctionNameTypeMethod,
+ lldb::eLanguageTypeUnknown);
+
+ m_index->GetFunctions(info, *this, {}, [&](DWARFDIE entry) {
+if (entry.GetAttributeValueAsUnsigned(llvm::dwarf::DW_AT_declaration, 0))
+ return IterationAction::Continue;
+
+auto spec = entry.GetAttributeValueAsReferenceDIE(DW_AT_specification);
+if (!spec)
+ return IterationAction::Continue;
+
+if (spec != declaration)
Michael137 wrote:
For the structural match, were you suggesting we re-use the innards of
`CopyUniqueClassMethodTypes` to do so, or that there is something on the
`DWARFASTParserClang` that should've been cached about the fact that the two
DIEs are structurally the same?
https://github.com/llvm/llvm-project/pull/149827
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libcxxabi] [lldb] [llvm] [lldb][Expression] Add structor variant to LLDB's function call labels (PR #149827)
https://github.com/Michael137 edited https://github.com/llvm/llvm-project/pull/149827 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libcxxabi] [lldb] [llvm] [lldb][Expression] Add structor variant to LLDB's function call labels (PR #149827)
https://github.com/Michael137 edited https://github.com/llvm/llvm-project/pull/149827 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libcxxabi] [lldb] [llvm] [lldb][Expression] Add structor variant to LLDB's function call labels (PR #149827)
https://github.com/Michael137 edited https://github.com/llvm/llvm-project/pull/149827 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libcxxabi] [lldb] [llvm] [lldb][Expression] Add structor variant to LLDB's function call labels (PR #149827)
https://github.com/Michael137 edited https://github.com/llvm/llvm-project/pull/149827 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libcxxabi] [lldb] [llvm] [lldb][Expression] Add structor variant to LLDB's function call labels (PR #149827)
@@ -2482,6 +2485,134 @@ bool SymbolFileDWARF::ResolveFunction(const DWARFDIE
&orig_die,
return false;
}
+static int ClangToItaniumCtorKind(clang::CXXCtorType kind) {
+ switch (kind) {
+ case clang::CXXCtorType::Ctor_Complete:
+return 1;
+ case clang::CXXCtorType::Ctor_Base:
+return 2;
+ case clang::CXXCtorType::Ctor_CopyingClosure:
+ case clang::CXXCtorType::Ctor_DefaultClosure:
+ case clang::CXXCtorType::Ctor_Comdat:
+llvm_unreachable("Unexpected constructor kind.");
+ }
+}
+
+static int ClangToItaniumDtorKind(clang::CXXDtorType kind) {
+ switch (kind) {
+ case clang::CXXDtorType::Dtor_Deleting:
+return 0;
+ case clang::CXXDtorType::Dtor_Complete:
+return 1;
+ case clang::CXXDtorType::Dtor_Base:
+return 2;
+ case clang::CXXDtorType::Dtor_Comdat:
+llvm_unreachable("Unexpected destructor kind.");
+ }
+}
+
+static std::optional
+GetItaniumCtorDtorVariant(llvm::StringRef discriminator) {
+ const bool is_ctor = discriminator.consume_front("C");
+ if (!is_ctor && !discriminator.consume_front("D"))
+return std::nullopt;
+
+ uint64_t structor_kind;
+ if (!llvm::to_integer(discriminator, structor_kind))
+return std::nullopt;
+
+ if (is_ctor) {
+if (structor_kind > clang::CXXCtorType::Ctor_DefaultClosure)
+ return std::nullopt;
+
+return ClangToItaniumCtorKind(
+static_cast(structor_kind));
+ }
+
+ if (structor_kind > clang::CXXDtorType::Dtor_Comdat)
+return std::nullopt;
+
+ return
ClangToItaniumDtorKind(static_cast(structor_kind));
+}
+
+DWARFDIE SymbolFileDWARF::FindFunctionDefinition(const FunctionCallLabel
&label,
+ const DWARFDIE &declaration) {
+ DWARFDIE definition;
+ llvm::DenseMap structor_variant_to_die;
+
+ // eFunctionNameTypeFull for mangled name lookup.
+ // eFunctionNameTypeMethod is required for structor lookups (since we look
+ // those up by DW_AT_name).
+ Module::LookupInfo info(ConstString(label.lookup_name),
+ lldb::eFunctionNameTypeFull |
+ lldb::eFunctionNameTypeMethod,
+ lldb::eLanguageTypeUnknown);
+
+ m_index->GetFunctions(info, *this, {}, [&](DWARFDIE entry) {
+if (entry.GetAttributeValueAsUnsigned(llvm::dwarf::DW_AT_declaration, 0))
+ return IterationAction::Continue;
+
+auto spec = entry.GetAttributeValueAsReferenceDIE(DW_AT_specification);
+if (!spec)
+ return IterationAction::Continue;
+
+if (spec != declaration)
Michael137 wrote:
> > is actually redundant because we can just rely on the fallback lookup
>
> Is it? I can see how the fallback lookup can work for functions where you
> have mangled names, as those are more-or-less unique. However, I don't see
> how we could find the correct constructor if all we have is the name of the
> class.
Yup that's correct. I meant it should work for mangled name lookup. For
constructors we just would behave as we do today. Not ideal, but not a
regression. But yea, ideally we'd fix this as you suggest. All that is to say,
the type-unit check in this PR is redundant (regardless of which route we take).
> > Happy to try and change it to a structural match though.
>
> I think that is necessary for this to work. Otherwise, this will fail
> whenever we parse a type from a CU which does not contain the definition of
> the methods (at least constructors) of that type. And I think that can happen
> pretty easily in a big binary.
Would a structural match here help though? If the declaration DIE for a ctor
got encoded into the `AsmLabel` but the definition lives in a different CU (and
thus `SymbolFile`), we wouldn't be able to find it anyway using our approach
right? AFAIU, the case where a structural match would help is if:
1. constructor declaration DIE (and its module) got encoded into the `AsmLabel`
2. the definition lives in the same module but the `DW_AT_specification` points
outside of the module
I have been having a hard time coming up with an example of (2) happening. But
I'm sure compilers are allowed to do this (and probably already do?). With
type-units this can happen because the declaration lives in `.debug_types` but
the definition (and its specification) lives in `.debug_info. So the
`SymbolFile` lookup will find the definition but the specification DIE is not
the same as the declaration DIE. So there a structural match would help.
> > Here a in lib.o would point to the DW_TAG_structure_type of main.o, but the
> > subprogram definitions for the constructors are different (and local to
> > each CU).
>
> Hm... That's confusing. I was under the impression that ld64 doesn't touch
> debug info (that it just leaves breadcrumbs so that the debug info can be
> linked later. Did that change? If not, how can lib.o point to a different
> file. Surely clang does not inspect main.o when compiling lib.o.
>
> Or did you mean that this happens
[clang] [libcxxabi] [lldb] [llvm] [lldb][Expression] Add structor variant to LLDB's function call labels (PR #149827)
@@ -2482,6 +2485,134 @@ bool SymbolFileDWARF::ResolveFunction(const DWARFDIE
&orig_die,
return false;
}
+static int ClangToItaniumCtorKind(clang::CXXCtorType kind) {
+ switch (kind) {
+ case clang::CXXCtorType::Ctor_Complete:
+return 1;
+ case clang::CXXCtorType::Ctor_Base:
+return 2;
+ case clang::CXXCtorType::Ctor_CopyingClosure:
+ case clang::CXXCtorType::Ctor_DefaultClosure:
+ case clang::CXXCtorType::Ctor_Comdat:
+llvm_unreachable("Unexpected constructor kind.");
+ }
+}
+
+static int ClangToItaniumDtorKind(clang::CXXDtorType kind) {
+ switch (kind) {
+ case clang::CXXDtorType::Dtor_Deleting:
+return 0;
+ case clang::CXXDtorType::Dtor_Complete:
+return 1;
+ case clang::CXXDtorType::Dtor_Base:
+return 2;
+ case clang::CXXDtorType::Dtor_Comdat:
+llvm_unreachable("Unexpected destructor kind.");
+ }
+}
+
+static std::optional
+GetItaniumCtorDtorVariant(llvm::StringRef discriminator) {
+ const bool is_ctor = discriminator.consume_front("C");
+ if (!is_ctor && !discriminator.consume_front("D"))
+return std::nullopt;
+
+ uint64_t structor_kind;
+ if (!llvm::to_integer(discriminator, structor_kind))
+return std::nullopt;
+
+ if (is_ctor) {
+if (structor_kind > clang::CXXCtorType::Ctor_DefaultClosure)
+ return std::nullopt;
+
+return ClangToItaniumCtorKind(
+static_cast(structor_kind));
+ }
+
+ if (structor_kind > clang::CXXDtorType::Dtor_Comdat)
+return std::nullopt;
+
+ return
ClangToItaniumDtorKind(static_cast(structor_kind));
+}
+
+DWARFDIE SymbolFileDWARF::FindFunctionDefinition(const FunctionCallLabel
&label,
+ const DWARFDIE &declaration) {
+ DWARFDIE definition;
+ llvm::DenseMap structor_variant_to_die;
+
+ // eFunctionNameTypeFull for mangled name lookup.
+ // eFunctionNameTypeMethod is required for structor lookups (since we look
+ // those up by DW_AT_name).
+ Module::LookupInfo info(ConstString(label.lookup_name),
+ lldb::eFunctionNameTypeFull |
+ lldb::eFunctionNameTypeMethod,
+ lldb::eLanguageTypeUnknown);
+
+ m_index->GetFunctions(info, *this, {}, [&](DWARFDIE entry) {
+if (entry.GetAttributeValueAsUnsigned(llvm::dwarf::DW_AT_declaration, 0))
+ return IterationAction::Continue;
+
+auto spec = entry.GetAttributeValueAsReferenceDIE(DW_AT_specification);
+if (!spec)
+ return IterationAction::Continue;
+
+if (spec != declaration)
labath wrote:
> is actually redundant because we can just rely on the fallback lookup
Is it? I can see how the fallback lookup can work for functions where you have
mangled names, as those are more-or-less unique. However, I don't see how we
could find the correct constructor if all we have is the name of the class.
> Happy to try and change it to a structural match though.
I think that is necessary for this to work. Otherwise, this will fail whenever
we parse a type from a CU which does not contain the definition of the methods
(at least constructors) of that type. And I think that can happen pretty easily
in a big binary.
> Here a in lib.o would point to the DW_TAG_structure_type of main.o, but the
> subprogram definitions for the constructors are different (and local to each
> CU).
Hm... That's confusing. I was under the impression that ld64 doesn't touch
debug info (that it just leaves breadcrumbs so that the debug info can be
linked later. Did that change? If not, how can lib.o point to a different file.
Surely clang does not inspect main.o when compiling lib.o.
Or did you mean that this happens after running dsymutil over the binary?
Because this matches what I would expect dsymutil to do.
> I don't think we had reservations about encoding ABI-tag information into
> DWARF. The concerns were:
>
> 1. debug-info size (libc++ uses these tags on a ton of APIs).
Yes, I can see how that could be an issue.
> 2. whether we want to rely on AST fidelity again
Yeah, I don't want to rely on being able to roundtrip clang ASTs. The thing
which changed the calculus for me is that the realisation that this is
necessary even to just understand the DWARF correctly. Like, with ABI tags, I
can safely link a binary which contains two versions of `struct Foo` (as long
as they are not used in the same CU). However, if I now have a third CU, which
defines a constructor for `Foo`, I have no way to tell which of the two struct
definitions it refers to.
> 3. libc++ makes no guarantee that they'll continue annotating individual
> APIs in the future and might put the tags on namespaces/structures. At which
> point LLDB will need to take care to propagate the tags appropriately (maybe
> this will be handled by Clang out-of-the-box, though I haven't thought about
> this specific point in detail)
I'm not particularly concerned by that, for one because I don't (primarily)
[clang] [libcxxabi] [lldb] [llvm] [lldb][Expression] Add structor variant to LLDB's function call labels (PR #149827)
https://github.com/Michael137 edited https://github.com/llvm/llvm-project/pull/149827 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libcxxabi] [lldb] [llvm] [lldb][Expression] Add structor variant to LLDB's function call labels (PR #149827)
@@ -2482,6 +2485,134 @@ bool SymbolFileDWARF::ResolveFunction(const DWARFDIE
&orig_die,
return false;
}
+static int ClangToItaniumCtorKind(clang::CXXCtorType kind) {
+ switch (kind) {
+ case clang::CXXCtorType::Ctor_Complete:
+return 1;
+ case clang::CXXCtorType::Ctor_Base:
+return 2;
+ case clang::CXXCtorType::Ctor_CopyingClosure:
+ case clang::CXXCtorType::Ctor_DefaultClosure:
+ case clang::CXXCtorType::Ctor_Comdat:
+llvm_unreachable("Unexpected constructor kind.");
+ }
+}
+
+static int ClangToItaniumDtorKind(clang::CXXDtorType kind) {
+ switch (kind) {
+ case clang::CXXDtorType::Dtor_Deleting:
+return 0;
+ case clang::CXXDtorType::Dtor_Complete:
+return 1;
+ case clang::CXXDtorType::Dtor_Base:
+return 2;
+ case clang::CXXDtorType::Dtor_Comdat:
+llvm_unreachable("Unexpected destructor kind.");
+ }
+}
+
+static std::optional
+GetItaniumCtorDtorVariant(llvm::StringRef discriminator) {
+ const bool is_ctor = discriminator.consume_front("C");
+ if (!is_ctor && !discriminator.consume_front("D"))
+return std::nullopt;
+
+ uint64_t structor_kind;
+ if (!llvm::to_integer(discriminator, structor_kind))
+return std::nullopt;
+
+ if (is_ctor) {
+if (structor_kind > clang::CXXCtorType::Ctor_DefaultClosure)
+ return std::nullopt;
+
+return ClangToItaniumCtorKind(
+static_cast(structor_kind));
+ }
+
+ if (structor_kind > clang::CXXDtorType::Dtor_Comdat)
+return std::nullopt;
+
+ return
ClangToItaniumDtorKind(static_cast(structor_kind));
+}
+
+DWARFDIE SymbolFileDWARF::FindFunctionDefinition(const FunctionCallLabel
&label,
+ const DWARFDIE &declaration) {
+ DWARFDIE definition;
+ llvm::DenseMap structor_variant_to_die;
+
+ // eFunctionNameTypeFull for mangled name lookup.
+ // eFunctionNameTypeMethod is required for structor lookups (since we look
+ // those up by DW_AT_name).
+ Module::LookupInfo info(ConstString(label.lookup_name),
+ lldb::eFunctionNameTypeFull |
+ lldb::eFunctionNameTypeMethod,
+ lldb::eLanguageTypeUnknown);
+
+ m_index->GetFunctions(info, *this, {}, [&](DWARFDIE entry) {
+if (entry.GetAttributeValueAsUnsigned(llvm::dwarf::DW_AT_declaration, 0))
+ return IterationAction::Continue;
+
+auto spec = entry.GetAttributeValueAsReferenceDIE(DW_AT_specification);
+if (!spec)
+ return IterationAction::Continue;
+
+if (spec != declaration)
Michael137 wrote:
> Okay, I guess this is why. I don't think this will work, for the reasons
> outlined in the other comment. This needs to be a structural match between
> the two DIEs, maybe facilitated by
> DWARFASTParserClang::CopyUniqueClassMethodTypes.
That's a good point. This mainly cropped up in the test-suite for type-units,
but yea this need not be related to them. I guess this is similar to the other
case you pointed out where the declaration DIE might be in a different module
than the definition. For those cases we also ended up falling back on the old
lookup. So the type-unit check is actually redundant because we can just rely
on the fallback lookup. But if we want to support a wider range we'd have to
change this specification check. Happy to try and change it to a structural
match though.
> Given then ABI tags are meant to allow different versions of the same class
> to coexist, then if you want to support these different versions coexisting,
> then the DWARF sort of has to contain the ABI tag information as it relies on
> structural matches to connect DIEs from different compilation units. Maybe
> this is irrelevant as you don't want to support this "coexistence" (I believe
> you just want to "deal with" the presence of ABI tags), but I think this
> might make a reasonable case for encoding the ABI tag information (in one way
> or another) in DWARF.
Hmm interesting point. Trying out the case where we have two ABI-tagged
structures in two TUs, it looks like Clang/ld64 decide to emit two structure
types with the same name only if there is a structural mismatch:
```
// lib.cpp
#include
struct [[gnu::abi_tag("Lib")]] A {
A() {}
int mem = 5;
} a;
void func() {
assert (a.mem == 5);
}
// main.cpp
#include
struct [[gnu::abi_tag("Main")]] A {
A() {}
int mem = 10;
} a;
void func();
int main(int argc, char **argv) {
func();
assert (a.mem == 10);
return 0;
}
```
Here `a` in `lib.o` would point to the `DW_TAG_structure_type` of `main.o`, but
the subprogram definitions for the constructors are different (and local to
each CU).
If we change the structure layout though we get a `DW_TAG_structure_type` in
each CU. But if they only differ by which methods they carry we only emit 1
definition!
I guess for now the goal of the expression evaluator is to just support two
versions of the same function (with different tags). Which is the easier
[clang] [libcxxabi] [lldb] [llvm] [lldb][Expression] Add structor variant to LLDB's function call labels (PR #149827)
@@ -250,11 +250,52 @@ static unsigned GetCXXMethodCVQuals(const DWARFDIE
&subprogram,
return cv_quals;
}
+static const char *GetMangledOrStructorName(const DWARFDIE &die) {
+ const char *name = die.GetMangledName(/*substitute_name_allowed*/ false);
+ if (name)
+return name;
+
+ name = die.GetName();
+ if (!name)
+return nullptr;
+
+ DWARFDIE parent = die.GetParent();
+ if (!parent.IsStructUnionOrClass())
+return nullptr;
+
+ const char *parent_name = parent.GetName();
+ if (!parent_name)
+return nullptr;
+
+ // Constructor.
+ if (::strcmp(parent_name, name) == 0)
+return name;
+
+ // Destructor.
+ if (name[0] == '~' && ::strcmp(parent_name, name + 1) == 0)
+return name;
+
+ return nullptr;
+}
+
static std::string MakeLLDBFuncAsmLabel(const DWARFDIE &die) {
- char const *name = die.GetMangledName(/*substitute_name_allowed*/ false);
+ char const *name = GetMangledOrStructorName(die);
if (!name)
return {};
+ auto *cu = die.GetCU();
+ if (!cu)
+return {};
+
+ // FIXME: When resolving function call labels, we check that
+ // that the definition's DW_AT_specification points to the
+ // declaration that we encoded into the label here. But if the
+ // declaration came from a type-unit (and the definition from
+ // .debug_info), that check won't work. So for now, don't use
+ // function call labels for declaration DIEs from type-units.
+ if (cu->IsTypeUnit())
+return {};
labath wrote:
I don't understand how this is related to type units. Even without them, I
don't see how we can guarantee we always wind up at the same declaration DIE. A
definition of the type (along with declarations of its methods) can be present
in ~every CU, but the definition of a specific method will (normally) only be
present in a single CU (however, it doesn't always have to be the same CU as
c++ allows you to spread the definition of a class across multiple CUs). That
definition DIE will point to *a* declaration, but that doesn't have to be the
same declaration that we started with.
If anything, type units should make finding the canonical declaration easier
because the linker will deduplicate all of the type definitions (similar to how
dsymutil would do it), but even that's not guaranteed because not all CUs have
to have type units enabled.
Why do we need to go back the the original DIE?
I don't quite understand how, but I think lldb deals with this problem
(multiple definitions of a using the
`DWARFASTParserClang::CopyUniqueClassMethodTypes` function. Is it possible this
patch breaks that somehow?
https://github.com/llvm/llvm-project/pull/149827
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libcxxabi] [lldb] [llvm] [lldb][Expression] Add structor variant to LLDB's function call labels (PR #149827)
@@ -2482,6 +2485,134 @@ bool SymbolFileDWARF::ResolveFunction(const DWARFDIE
&orig_die,
return false;
}
+static int ClangToItaniumCtorKind(clang::CXXCtorType kind) {
+ switch (kind) {
+ case clang::CXXCtorType::Ctor_Complete:
+return 1;
+ case clang::CXXCtorType::Ctor_Base:
+return 2;
+ case clang::CXXCtorType::Ctor_CopyingClosure:
+ case clang::CXXCtorType::Ctor_DefaultClosure:
+ case clang::CXXCtorType::Ctor_Comdat:
+llvm_unreachable("Unexpected constructor kind.");
+ }
+}
+
+static int ClangToItaniumDtorKind(clang::CXXDtorType kind) {
+ switch (kind) {
+ case clang::CXXDtorType::Dtor_Deleting:
+return 0;
+ case clang::CXXDtorType::Dtor_Complete:
+return 1;
+ case clang::CXXDtorType::Dtor_Base:
+return 2;
+ case clang::CXXDtorType::Dtor_Comdat:
+llvm_unreachable("Unexpected destructor kind.");
+ }
+}
+
+static std::optional
+GetItaniumCtorDtorVariant(llvm::StringRef discriminator) {
+ const bool is_ctor = discriminator.consume_front("C");
+ if (!is_ctor && !discriminator.consume_front("D"))
+return std::nullopt;
+
+ uint64_t structor_kind;
+ if (!llvm::to_integer(discriminator, structor_kind))
+return std::nullopt;
+
+ if (is_ctor) {
+if (structor_kind > clang::CXXCtorType::Ctor_DefaultClosure)
+ return std::nullopt;
+
+return ClangToItaniumCtorKind(
+static_cast(structor_kind));
+ }
+
+ if (structor_kind > clang::CXXDtorType::Dtor_Comdat)
+return std::nullopt;
+
+ return
ClangToItaniumDtorKind(static_cast(structor_kind));
+}
+
+DWARFDIE SymbolFileDWARF::FindFunctionDefinition(const FunctionCallLabel
&label,
+ const DWARFDIE &declaration) {
+ DWARFDIE definition;
+ llvm::DenseMap structor_variant_to_die;
+
+ // eFunctionNameTypeFull for mangled name lookup.
+ // eFunctionNameTypeMethod is required for structor lookups (since we look
+ // those up by DW_AT_name).
+ Module::LookupInfo info(ConstString(label.lookup_name),
+ lldb::eFunctionNameTypeFull |
+ lldb::eFunctionNameTypeMethod,
+ lldb::eLanguageTypeUnknown);
+
+ m_index->GetFunctions(info, *this, {}, [&](DWARFDIE entry) {
+if (entry.GetAttributeValueAsUnsigned(llvm::dwarf::DW_AT_declaration, 0))
+ return IterationAction::Continue;
+
+auto spec = entry.GetAttributeValueAsReferenceDIE(DW_AT_specification);
+if (!spec)
+ return IterationAction::Continue;
+
+if (spec != declaration)
labath wrote:
Okay, I guess this is why. I don't think this will work, for the reasons
outlined in the other comment. This needs to be a structural match between the
two DIEs, maybe facilitated by
`DWARFASTParserClang::CopyUniqueClassMethodTypes`.
I admit this is more complicated that I originally expected. I didn't realise
just how load-bearing the mangling is for constructors. As clang does not emit
DW_AT_linkage_name for constructors (for better or worse, gcc does, using the
funny `C4` variant), the way we were looking up the right constructor versions
was by making sure the mangler roundtrips the exact same mangled name.
I still think this is better than relying on the mangling roundtrip, though it
brings up an interesting point. Given then ABI tags are meant to allow
different versions of the same class to coexist, then *if* you want to support
these different versions coexisting, then the DWARF sort of has to contain the
ABI tag information as it relies on structural matches to connect DIEs from
different compilation units. Maybe this is irrelevant as you don't want to
support this "coexistence" (I believe you just want to "deal with" the presence
of ABI tags), but I think this might make a reasonable case for encoding the
ABI tag information (in one way or another) in DWARF.
https://github.com/llvm/llvm-project/pull/149827
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libcxxabi] [lldb] [llvm] [lldb][Expression] Add structor variant to LLDB's function call labels (PR #149827)
https://github.com/Michael137 updated
https://github.com/llvm/llvm-project/pull/149827
>From b8f31ec8f556169a45370938cf28bd8582134a5c Mon Sep 17 00:00:00 2001
From: Michael Buch
Date: Sun, 3 Aug 2025 11:38:07 +0100
Subject: [PATCH 1/4] [clang][Attr] Remove 'literal label' form of AsmLabelAttr
This was added purely for the needs of LLDB. However, starting with
https://github.com/llvm/llvm-project/pull/151355 and
https://github.com/llvm/llvm-project/pull/148877 we no longer create literal
AsmLabels in LLDB either. So this is unused and we can get rid of it.
In the near future LLDB will want to add special support for mangling
`AsmLabel`s, and the "literal label" codepath in the mangler made this more
cumbersome.
(cherry picked from commit 342f0d5cd722ae7ec3f48f136472923ce38f9981)
---
clang/include/clang/Basic/Attr.td | 17 -
clang/lib/AST/Mangle.cpp| 4 ++--
clang/lib/Sema/SemaDecl.cpp | 13 +
clang/unittests/AST/DeclTest.cpp| 9 +
.../TypeSystem/Clang/TypeSystemClang.cpp| 7 +++
5 files changed, 15 insertions(+), 35 deletions(-)
diff --git a/clang/include/clang/Basic/Attr.td
b/clang/include/clang/Basic/Attr.td
index b3ff45b3e90a3..a0efb21218312 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -1059,22 +1059,13 @@ def AVRSignal : InheritableAttr,
TargetSpecificAttr {
def AsmLabel : InheritableAttr {
let Spellings = [CustomKeyword<"asm">, CustomKeyword<"__asm__">];
let Args = [
-// Label specifies the mangled name for the decl.
-StringArgument<"Label">,
-
-// IsLiteralLabel specifies whether the label is literal (i.e. suppresses
-// the global C symbol prefix) or not. If not, the mangle-suppression
prefix
-// ('\01') is omitted from the decl name at the LLVM IR level.
-//
-// Non-literal labels are used by some external AST sources like LLDB.
-BoolArgument<"IsLiteralLabel", /*optional=*/0, /*fake=*/1>
- ];
+ // Label specifies the mangled name for the decl.
+ StringArgument<"Label">, ];
let SemaHandler = 0;
let Documentation = [AsmLabelDocs];
- let AdditionalMembers =
-[{
+ let AdditionalMembers = [{
bool isEquivalent(AsmLabelAttr *Other) const {
- return getLabel() == Other->getLabel() && getIsLiteralLabel() ==
Other->getIsLiteralLabel();
+ return getLabel() == Other->getLabel();
}
}];
}
diff --git a/clang/lib/AST/Mangle.cpp b/clang/lib/AST/Mangle.cpp
index 9652fdbc4e125..0bfb51c11f0a5 100644
--- a/clang/lib/AST/Mangle.cpp
+++ b/clang/lib/AST/Mangle.cpp
@@ -161,9 +161,9 @@ void MangleContext::mangleName(GlobalDecl GD, raw_ostream
&Out) {
if (const AsmLabelAttr *ALA = D->getAttr()) {
// If we have an asm name, then we use it as the mangling.
-// If the label isn't literal, or if this is an alias for an LLVM
intrinsic,
+// If the label is an alias for an LLVM intrinsic,
// do not add a "\01" prefix.
-if (!ALA->getIsLiteralLabel() || ALA->getLabel().starts_with("llvm.")) {
+if (ALA->getLabel().starts_with("llvm.")) {
Out << ALA->getLabel();
return;
}
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index e2ac648320c0f..885d04b9ab926 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -8113,9 +8113,7 @@ NamedDecl *Sema::ActOnVariableDeclarator(
}
}
-NewVD->addAttr(AsmLabelAttr::Create(Context, Label,
-/*IsLiteralLabel=*/true,
-SE->getStrTokenLoc(0)));
+NewVD->addAttr(AsmLabelAttr::Create(Context, Label,
SE->getStrTokenLoc(0)));
} else if (!ExtnameUndeclaredIdentifiers.empty()) {
llvm::DenseMap::iterator I =
ExtnameUndeclaredIdentifiers.find(NewVD->getIdentifier());
@@ -10345,9 +10343,8 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D,
DeclContext *DC,
if (Expr *E = D.getAsmLabel()) {
// The parser guarantees this is a string.
StringLiteral *SE = cast(E);
-NewFD->addAttr(AsmLabelAttr::Create(Context, SE->getString(),
-/*IsLiteralLabel=*/true,
-SE->getStrTokenLoc(0)));
+NewFD->addAttr(
+AsmLabelAttr::Create(Context, SE->getString(), SE->getStrTokenLoc(0)));
} else if (!ExtnameUndeclaredIdentifiers.empty()) {
llvm::DenseMap::iterator I =
ExtnameUndeclaredIdentifiers.find(NewFD->getIdentifier());
@@ -20598,8 +20595,8 @@ void Sema::ActOnPragmaRedefineExtname(IdentifierInfo*
Name,
LookupOrdinaryName);
AttributeCommonInfo Info(AliasName, SourceRange(AliasNameLoc),
AttributeCommonInfo::Form::Pragma());
- AsmLabelAttr *Attr = AsmLabelAttr::CreateImplicit(
- Context, AliasName->getName(), /*IsLiteralLabel=*/true, Info);
+ AsmLabelAttr *Attr =
+ AsmLab
[clang] [libcxxabi] [lldb] [llvm] [lldb][Expression] Add structor variant to LLDB's function call labels (PR #149827)
AaronBallman wrote: > > Clang bits LGTM > > @AaronBallman Sorry for the back and forth but I had some of the Clang > changes not split into separate commits. Not sure if you looked at the entire > diff or just the Clang commits, but I split out one more commit just now just > in case I looked just at the Clang bits, the rest was more "cursory look" than actual review because I don't have the expertise for my sign-off to mean much. https://github.com/llvm/llvm-project/pull/149827 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libcxxabi] [lldb] [llvm] [lldb][Expression] Add structor variant to LLDB's function call labels (PR #149827)
https://github.com/Michael137 updated
https://github.com/llvm/llvm-project/pull/149827
>From b8f31ec8f556169a45370938cf28bd8582134a5c Mon Sep 17 00:00:00 2001
From: Michael Buch
Date: Sun, 3 Aug 2025 11:38:07 +0100
Subject: [PATCH 1/4] [clang][Attr] Remove 'literal label' form of AsmLabelAttr
This was added purely for the needs of LLDB. However, starting with
https://github.com/llvm/llvm-project/pull/151355 and
https://github.com/llvm/llvm-project/pull/148877 we no longer create literal
AsmLabels in LLDB either. So this is unused and we can get rid of it.
In the near future LLDB will want to add special support for mangling
`AsmLabel`s, and the "literal label" codepath in the mangler made this more
cumbersome.
(cherry picked from commit 342f0d5cd722ae7ec3f48f136472923ce38f9981)
---
clang/include/clang/Basic/Attr.td | 17 -
clang/lib/AST/Mangle.cpp| 4 ++--
clang/lib/Sema/SemaDecl.cpp | 13 +
clang/unittests/AST/DeclTest.cpp| 9 +
.../TypeSystem/Clang/TypeSystemClang.cpp| 7 +++
5 files changed, 15 insertions(+), 35 deletions(-)
diff --git a/clang/include/clang/Basic/Attr.td
b/clang/include/clang/Basic/Attr.td
index b3ff45b3e90a3..a0efb21218312 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -1059,22 +1059,13 @@ def AVRSignal : InheritableAttr,
TargetSpecificAttr {
def AsmLabel : InheritableAttr {
let Spellings = [CustomKeyword<"asm">, CustomKeyword<"__asm__">];
let Args = [
-// Label specifies the mangled name for the decl.
-StringArgument<"Label">,
-
-// IsLiteralLabel specifies whether the label is literal (i.e. suppresses
-// the global C symbol prefix) or not. If not, the mangle-suppression
prefix
-// ('\01') is omitted from the decl name at the LLVM IR level.
-//
-// Non-literal labels are used by some external AST sources like LLDB.
-BoolArgument<"IsLiteralLabel", /*optional=*/0, /*fake=*/1>
- ];
+ // Label specifies the mangled name for the decl.
+ StringArgument<"Label">, ];
let SemaHandler = 0;
let Documentation = [AsmLabelDocs];
- let AdditionalMembers =
-[{
+ let AdditionalMembers = [{
bool isEquivalent(AsmLabelAttr *Other) const {
- return getLabel() == Other->getLabel() && getIsLiteralLabel() ==
Other->getIsLiteralLabel();
+ return getLabel() == Other->getLabel();
}
}];
}
diff --git a/clang/lib/AST/Mangle.cpp b/clang/lib/AST/Mangle.cpp
index 9652fdbc4e125..0bfb51c11f0a5 100644
--- a/clang/lib/AST/Mangle.cpp
+++ b/clang/lib/AST/Mangle.cpp
@@ -161,9 +161,9 @@ void MangleContext::mangleName(GlobalDecl GD, raw_ostream
&Out) {
if (const AsmLabelAttr *ALA = D->getAttr()) {
// If we have an asm name, then we use it as the mangling.
-// If the label isn't literal, or if this is an alias for an LLVM
intrinsic,
+// If the label is an alias for an LLVM intrinsic,
// do not add a "\01" prefix.
-if (!ALA->getIsLiteralLabel() || ALA->getLabel().starts_with("llvm.")) {
+if (ALA->getLabel().starts_with("llvm.")) {
Out << ALA->getLabel();
return;
}
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index e2ac648320c0f..885d04b9ab926 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -8113,9 +8113,7 @@ NamedDecl *Sema::ActOnVariableDeclarator(
}
}
-NewVD->addAttr(AsmLabelAttr::Create(Context, Label,
-/*IsLiteralLabel=*/true,
-SE->getStrTokenLoc(0)));
+NewVD->addAttr(AsmLabelAttr::Create(Context, Label,
SE->getStrTokenLoc(0)));
} else if (!ExtnameUndeclaredIdentifiers.empty()) {
llvm::DenseMap::iterator I =
ExtnameUndeclaredIdentifiers.find(NewVD->getIdentifier());
@@ -10345,9 +10343,8 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D,
DeclContext *DC,
if (Expr *E = D.getAsmLabel()) {
// The parser guarantees this is a string.
StringLiteral *SE = cast(E);
-NewFD->addAttr(AsmLabelAttr::Create(Context, SE->getString(),
-/*IsLiteralLabel=*/true,
-SE->getStrTokenLoc(0)));
+NewFD->addAttr(
+AsmLabelAttr::Create(Context, SE->getString(), SE->getStrTokenLoc(0)));
} else if (!ExtnameUndeclaredIdentifiers.empty()) {
llvm::DenseMap::iterator I =
ExtnameUndeclaredIdentifiers.find(NewFD->getIdentifier());
@@ -20598,8 +20595,8 @@ void Sema::ActOnPragmaRedefineExtname(IdentifierInfo*
Name,
LookupOrdinaryName);
AttributeCommonInfo Info(AliasName, SourceRange(AliasNameLoc),
AttributeCommonInfo::Form::Pragma());
- AsmLabelAttr *Attr = AsmLabelAttr::CreateImplicit(
- Context, AliasName->getName(), /*IsLiteralLabel=*/true, Info);
+ AsmLabelAttr *Attr =
+ AsmLab
[clang] [libcxxabi] [lldb] [llvm] [lldb][Expression] Add structor variant to LLDB's function call labels (PR #149827)
https://github.com/Michael137 updated
https://github.com/llvm/llvm-project/pull/149827
>From b8f31ec8f556169a45370938cf28bd8582134a5c Mon Sep 17 00:00:00 2001
From: Michael Buch
Date: Sun, 3 Aug 2025 11:38:07 +0100
Subject: [PATCH 1/4] [clang][Attr] Remove 'literal label' form of AsmLabelAttr
This was added purely for the needs of LLDB. However, starting with
https://github.com/llvm/llvm-project/pull/151355 and
https://github.com/llvm/llvm-project/pull/148877 we no longer create literal
AsmLabels in LLDB either. So this is unused and we can get rid of it.
In the near future LLDB will want to add special support for mangling
`AsmLabel`s, and the "literal label" codepath in the mangler made this more
cumbersome.
(cherry picked from commit 342f0d5cd722ae7ec3f48f136472923ce38f9981)
---
clang/include/clang/Basic/Attr.td | 17 -
clang/lib/AST/Mangle.cpp| 4 ++--
clang/lib/Sema/SemaDecl.cpp | 13 +
clang/unittests/AST/DeclTest.cpp| 9 +
.../TypeSystem/Clang/TypeSystemClang.cpp| 7 +++
5 files changed, 15 insertions(+), 35 deletions(-)
diff --git a/clang/include/clang/Basic/Attr.td
b/clang/include/clang/Basic/Attr.td
index b3ff45b3e90a3..a0efb21218312 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -1059,22 +1059,13 @@ def AVRSignal : InheritableAttr,
TargetSpecificAttr {
def AsmLabel : InheritableAttr {
let Spellings = [CustomKeyword<"asm">, CustomKeyword<"__asm__">];
let Args = [
-// Label specifies the mangled name for the decl.
-StringArgument<"Label">,
-
-// IsLiteralLabel specifies whether the label is literal (i.e. suppresses
-// the global C symbol prefix) or not. If not, the mangle-suppression
prefix
-// ('\01') is omitted from the decl name at the LLVM IR level.
-//
-// Non-literal labels are used by some external AST sources like LLDB.
-BoolArgument<"IsLiteralLabel", /*optional=*/0, /*fake=*/1>
- ];
+ // Label specifies the mangled name for the decl.
+ StringArgument<"Label">, ];
let SemaHandler = 0;
let Documentation = [AsmLabelDocs];
- let AdditionalMembers =
-[{
+ let AdditionalMembers = [{
bool isEquivalent(AsmLabelAttr *Other) const {
- return getLabel() == Other->getLabel() && getIsLiteralLabel() ==
Other->getIsLiteralLabel();
+ return getLabel() == Other->getLabel();
}
}];
}
diff --git a/clang/lib/AST/Mangle.cpp b/clang/lib/AST/Mangle.cpp
index 9652fdbc4e125..0bfb51c11f0a5 100644
--- a/clang/lib/AST/Mangle.cpp
+++ b/clang/lib/AST/Mangle.cpp
@@ -161,9 +161,9 @@ void MangleContext::mangleName(GlobalDecl GD, raw_ostream
&Out) {
if (const AsmLabelAttr *ALA = D->getAttr()) {
// If we have an asm name, then we use it as the mangling.
-// If the label isn't literal, or if this is an alias for an LLVM
intrinsic,
+// If the label is an alias for an LLVM intrinsic,
// do not add a "\01" prefix.
-if (!ALA->getIsLiteralLabel() || ALA->getLabel().starts_with("llvm.")) {
+if (ALA->getLabel().starts_with("llvm.")) {
Out << ALA->getLabel();
return;
}
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index e2ac648320c0f..885d04b9ab926 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -8113,9 +8113,7 @@ NamedDecl *Sema::ActOnVariableDeclarator(
}
}
-NewVD->addAttr(AsmLabelAttr::Create(Context, Label,
-/*IsLiteralLabel=*/true,
-SE->getStrTokenLoc(0)));
+NewVD->addAttr(AsmLabelAttr::Create(Context, Label,
SE->getStrTokenLoc(0)));
} else if (!ExtnameUndeclaredIdentifiers.empty()) {
llvm::DenseMap::iterator I =
ExtnameUndeclaredIdentifiers.find(NewVD->getIdentifier());
@@ -10345,9 +10343,8 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D,
DeclContext *DC,
if (Expr *E = D.getAsmLabel()) {
// The parser guarantees this is a string.
StringLiteral *SE = cast(E);
-NewFD->addAttr(AsmLabelAttr::Create(Context, SE->getString(),
-/*IsLiteralLabel=*/true,
-SE->getStrTokenLoc(0)));
+NewFD->addAttr(
+AsmLabelAttr::Create(Context, SE->getString(), SE->getStrTokenLoc(0)));
} else if (!ExtnameUndeclaredIdentifiers.empty()) {
llvm::DenseMap::iterator I =
ExtnameUndeclaredIdentifiers.find(NewFD->getIdentifier());
@@ -20598,8 +20595,8 @@ void Sema::ActOnPragmaRedefineExtname(IdentifierInfo*
Name,
LookupOrdinaryName);
AttributeCommonInfo Info(AliasName, SourceRange(AliasNameLoc),
AttributeCommonInfo::Form::Pragma());
- AsmLabelAttr *Attr = AsmLabelAttr::CreateImplicit(
- Context, AliasName->getName(), /*IsLiteralLabel=*/true, Info);
+ AsmLabelAttr *Attr =
+ AsmLab
[clang] [libcxxabi] [lldb] [llvm] [lldb][Expression] Add structor variant to LLDB's function call labels (PR #149827)
https://github.com/Michael137 updated
https://github.com/llvm/llvm-project/pull/149827
>From b8f31ec8f556169a45370938cf28bd8582134a5c Mon Sep 17 00:00:00 2001
From: Michael Buch
Date: Sun, 3 Aug 2025 11:38:07 +0100
Subject: [PATCH 1/4] [clang][Attr] Remove 'literal label' form of AsmLabelAttr
This was added purely for the needs of LLDB. However, starting with
https://github.com/llvm/llvm-project/pull/151355 and
https://github.com/llvm/llvm-project/pull/148877 we no longer create literal
AsmLabels in LLDB either. So this is unused and we can get rid of it.
In the near future LLDB will want to add special support for mangling
`AsmLabel`s, and the "literal label" codepath in the mangler made this more
cumbersome.
(cherry picked from commit 342f0d5cd722ae7ec3f48f136472923ce38f9981)
---
clang/include/clang/Basic/Attr.td | 17 -
clang/lib/AST/Mangle.cpp| 4 ++--
clang/lib/Sema/SemaDecl.cpp | 13 +
clang/unittests/AST/DeclTest.cpp| 9 +
.../TypeSystem/Clang/TypeSystemClang.cpp| 7 +++
5 files changed, 15 insertions(+), 35 deletions(-)
diff --git a/clang/include/clang/Basic/Attr.td
b/clang/include/clang/Basic/Attr.td
index b3ff45b3e90a3..a0efb21218312 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -1059,22 +1059,13 @@ def AVRSignal : InheritableAttr,
TargetSpecificAttr {
def AsmLabel : InheritableAttr {
let Spellings = [CustomKeyword<"asm">, CustomKeyword<"__asm__">];
let Args = [
-// Label specifies the mangled name for the decl.
-StringArgument<"Label">,
-
-// IsLiteralLabel specifies whether the label is literal (i.e. suppresses
-// the global C symbol prefix) or not. If not, the mangle-suppression
prefix
-// ('\01') is omitted from the decl name at the LLVM IR level.
-//
-// Non-literal labels are used by some external AST sources like LLDB.
-BoolArgument<"IsLiteralLabel", /*optional=*/0, /*fake=*/1>
- ];
+ // Label specifies the mangled name for the decl.
+ StringArgument<"Label">, ];
let SemaHandler = 0;
let Documentation = [AsmLabelDocs];
- let AdditionalMembers =
-[{
+ let AdditionalMembers = [{
bool isEquivalent(AsmLabelAttr *Other) const {
- return getLabel() == Other->getLabel() && getIsLiteralLabel() ==
Other->getIsLiteralLabel();
+ return getLabel() == Other->getLabel();
}
}];
}
diff --git a/clang/lib/AST/Mangle.cpp b/clang/lib/AST/Mangle.cpp
index 9652fdbc4e125..0bfb51c11f0a5 100644
--- a/clang/lib/AST/Mangle.cpp
+++ b/clang/lib/AST/Mangle.cpp
@@ -161,9 +161,9 @@ void MangleContext::mangleName(GlobalDecl GD, raw_ostream
&Out) {
if (const AsmLabelAttr *ALA = D->getAttr()) {
// If we have an asm name, then we use it as the mangling.
-// If the label isn't literal, or if this is an alias for an LLVM
intrinsic,
+// If the label is an alias for an LLVM intrinsic,
// do not add a "\01" prefix.
-if (!ALA->getIsLiteralLabel() || ALA->getLabel().starts_with("llvm.")) {
+if (ALA->getLabel().starts_with("llvm.")) {
Out << ALA->getLabel();
return;
}
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index e2ac648320c0f..885d04b9ab926 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -8113,9 +8113,7 @@ NamedDecl *Sema::ActOnVariableDeclarator(
}
}
-NewVD->addAttr(AsmLabelAttr::Create(Context, Label,
-/*IsLiteralLabel=*/true,
-SE->getStrTokenLoc(0)));
+NewVD->addAttr(AsmLabelAttr::Create(Context, Label,
SE->getStrTokenLoc(0)));
} else if (!ExtnameUndeclaredIdentifiers.empty()) {
llvm::DenseMap::iterator I =
ExtnameUndeclaredIdentifiers.find(NewVD->getIdentifier());
@@ -10345,9 +10343,8 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D,
DeclContext *DC,
if (Expr *E = D.getAsmLabel()) {
// The parser guarantees this is a string.
StringLiteral *SE = cast(E);
-NewFD->addAttr(AsmLabelAttr::Create(Context, SE->getString(),
-/*IsLiteralLabel=*/true,
-SE->getStrTokenLoc(0)));
+NewFD->addAttr(
+AsmLabelAttr::Create(Context, SE->getString(), SE->getStrTokenLoc(0)));
} else if (!ExtnameUndeclaredIdentifiers.empty()) {
llvm::DenseMap::iterator I =
ExtnameUndeclaredIdentifiers.find(NewFD->getIdentifier());
@@ -20598,8 +20595,8 @@ void Sema::ActOnPragmaRedefineExtname(IdentifierInfo*
Name,
LookupOrdinaryName);
AttributeCommonInfo Info(AliasName, SourceRange(AliasNameLoc),
AttributeCommonInfo::Form::Pragma());
- AsmLabelAttr *Attr = AsmLabelAttr::CreateImplicit(
- Context, AliasName->getName(), /*IsLiteralLabel=*/true, Info);
+ AsmLabelAttr *Attr =
+ AsmLab
[clang] [libcxxabi] [lldb] [llvm] [lldb][Expression] Add structor variant to LLDB's function call labels (PR #149827)
https://github.com/Michael137 updated
https://github.com/llvm/llvm-project/pull/149827
>From b8f31ec8f556169a45370938cf28bd8582134a5c Mon Sep 17 00:00:00 2001
From: Michael Buch
Date: Sun, 3 Aug 2025 11:38:07 +0100
Subject: [PATCH 1/4] [clang][Attr] Remove 'literal label' form of AsmLabelAttr
This was added purely for the needs of LLDB. However, starting with
https://github.com/llvm/llvm-project/pull/151355 and
https://github.com/llvm/llvm-project/pull/148877 we no longer create literal
AsmLabels in LLDB either. So this is unused and we can get rid of it.
In the near future LLDB will want to add special support for mangling
`AsmLabel`s, and the "literal label" codepath in the mangler made this more
cumbersome.
(cherry picked from commit 342f0d5cd722ae7ec3f48f136472923ce38f9981)
---
clang/include/clang/Basic/Attr.td | 17 -
clang/lib/AST/Mangle.cpp| 4 ++--
clang/lib/Sema/SemaDecl.cpp | 13 +
clang/unittests/AST/DeclTest.cpp| 9 +
.../TypeSystem/Clang/TypeSystemClang.cpp| 7 +++
5 files changed, 15 insertions(+), 35 deletions(-)
diff --git a/clang/include/clang/Basic/Attr.td
b/clang/include/clang/Basic/Attr.td
index b3ff45b3e90a3..a0efb21218312 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -1059,22 +1059,13 @@ def AVRSignal : InheritableAttr,
TargetSpecificAttr {
def AsmLabel : InheritableAttr {
let Spellings = [CustomKeyword<"asm">, CustomKeyword<"__asm__">];
let Args = [
-// Label specifies the mangled name for the decl.
-StringArgument<"Label">,
-
-// IsLiteralLabel specifies whether the label is literal (i.e. suppresses
-// the global C symbol prefix) or not. If not, the mangle-suppression
prefix
-// ('\01') is omitted from the decl name at the LLVM IR level.
-//
-// Non-literal labels are used by some external AST sources like LLDB.
-BoolArgument<"IsLiteralLabel", /*optional=*/0, /*fake=*/1>
- ];
+ // Label specifies the mangled name for the decl.
+ StringArgument<"Label">, ];
let SemaHandler = 0;
let Documentation = [AsmLabelDocs];
- let AdditionalMembers =
-[{
+ let AdditionalMembers = [{
bool isEquivalent(AsmLabelAttr *Other) const {
- return getLabel() == Other->getLabel() && getIsLiteralLabel() ==
Other->getIsLiteralLabel();
+ return getLabel() == Other->getLabel();
}
}];
}
diff --git a/clang/lib/AST/Mangle.cpp b/clang/lib/AST/Mangle.cpp
index 9652fdbc4e125..0bfb51c11f0a5 100644
--- a/clang/lib/AST/Mangle.cpp
+++ b/clang/lib/AST/Mangle.cpp
@@ -161,9 +161,9 @@ void MangleContext::mangleName(GlobalDecl GD, raw_ostream
&Out) {
if (const AsmLabelAttr *ALA = D->getAttr()) {
// If we have an asm name, then we use it as the mangling.
-// If the label isn't literal, or if this is an alias for an LLVM
intrinsic,
+// If the label is an alias for an LLVM intrinsic,
// do not add a "\01" prefix.
-if (!ALA->getIsLiteralLabel() || ALA->getLabel().starts_with("llvm.")) {
+if (ALA->getLabel().starts_with("llvm.")) {
Out << ALA->getLabel();
return;
}
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index e2ac648320c0f..885d04b9ab926 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -8113,9 +8113,7 @@ NamedDecl *Sema::ActOnVariableDeclarator(
}
}
-NewVD->addAttr(AsmLabelAttr::Create(Context, Label,
-/*IsLiteralLabel=*/true,
-SE->getStrTokenLoc(0)));
+NewVD->addAttr(AsmLabelAttr::Create(Context, Label,
SE->getStrTokenLoc(0)));
} else if (!ExtnameUndeclaredIdentifiers.empty()) {
llvm::DenseMap::iterator I =
ExtnameUndeclaredIdentifiers.find(NewVD->getIdentifier());
@@ -10345,9 +10343,8 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D,
DeclContext *DC,
if (Expr *E = D.getAsmLabel()) {
// The parser guarantees this is a string.
StringLiteral *SE = cast(E);
-NewFD->addAttr(AsmLabelAttr::Create(Context, SE->getString(),
-/*IsLiteralLabel=*/true,
-SE->getStrTokenLoc(0)));
+NewFD->addAttr(
+AsmLabelAttr::Create(Context, SE->getString(), SE->getStrTokenLoc(0)));
} else if (!ExtnameUndeclaredIdentifiers.empty()) {
llvm::DenseMap::iterator I =
ExtnameUndeclaredIdentifiers.find(NewFD->getIdentifier());
@@ -20598,8 +20595,8 @@ void Sema::ActOnPragmaRedefineExtname(IdentifierInfo*
Name,
LookupOrdinaryName);
AttributeCommonInfo Info(AliasName, SourceRange(AliasNameLoc),
AttributeCommonInfo::Form::Pragma());
- AsmLabelAttr *Attr = AsmLabelAttr::CreateImplicit(
- Context, AliasName->getName(), /*IsLiteralLabel=*/true, Info);
+ AsmLabelAttr *Attr =
+ AsmLab
[clang] [libcxxabi] [lldb] [llvm] [lldb][Expression] Add structor variant to LLDB's function call labels (PR #149827)
Michael137 wrote: > Clang bits LGTM Sorry for the back and forth but I had some of the Clang changes not split into separate commits. Not sure if you looked at the entire diff or just the Clang commits, but I split out one more commit just now. https://github.com/llvm/llvm-project/pull/149827 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libcxxabi] [lldb] [llvm] [lldb][Expression] Add structor variant to LLDB's function call labels (PR #149827)
https://github.com/Michael137 updated
https://github.com/llvm/llvm-project/pull/149827
>From b8f31ec8f556169a45370938cf28bd8582134a5c Mon Sep 17 00:00:00 2001
From: Michael Buch
Date: Sun, 3 Aug 2025 11:38:07 +0100
Subject: [PATCH 1/4] [clang][Attr] Remove 'literal label' form of AsmLabelAttr
This was added purely for the needs of LLDB. However, starting with
https://github.com/llvm/llvm-project/pull/151355 and
https://github.com/llvm/llvm-project/pull/148877 we no longer create literal
AsmLabels in LLDB either. So this is unused and we can get rid of it.
In the near future LLDB will want to add special support for mangling
`AsmLabel`s, and the "literal label" codepath in the mangler made this more
cumbersome.
(cherry picked from commit 342f0d5cd722ae7ec3f48f136472923ce38f9981)
---
clang/include/clang/Basic/Attr.td | 17 -
clang/lib/AST/Mangle.cpp| 4 ++--
clang/lib/Sema/SemaDecl.cpp | 13 +
clang/unittests/AST/DeclTest.cpp| 9 +
.../TypeSystem/Clang/TypeSystemClang.cpp| 7 +++
5 files changed, 15 insertions(+), 35 deletions(-)
diff --git a/clang/include/clang/Basic/Attr.td
b/clang/include/clang/Basic/Attr.td
index b3ff45b3e90a3..a0efb21218312 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -1059,22 +1059,13 @@ def AVRSignal : InheritableAttr,
TargetSpecificAttr {
def AsmLabel : InheritableAttr {
let Spellings = [CustomKeyword<"asm">, CustomKeyword<"__asm__">];
let Args = [
-// Label specifies the mangled name for the decl.
-StringArgument<"Label">,
-
-// IsLiteralLabel specifies whether the label is literal (i.e. suppresses
-// the global C symbol prefix) or not. If not, the mangle-suppression
prefix
-// ('\01') is omitted from the decl name at the LLVM IR level.
-//
-// Non-literal labels are used by some external AST sources like LLDB.
-BoolArgument<"IsLiteralLabel", /*optional=*/0, /*fake=*/1>
- ];
+ // Label specifies the mangled name for the decl.
+ StringArgument<"Label">, ];
let SemaHandler = 0;
let Documentation = [AsmLabelDocs];
- let AdditionalMembers =
-[{
+ let AdditionalMembers = [{
bool isEquivalent(AsmLabelAttr *Other) const {
- return getLabel() == Other->getLabel() && getIsLiteralLabel() ==
Other->getIsLiteralLabel();
+ return getLabel() == Other->getLabel();
}
}];
}
diff --git a/clang/lib/AST/Mangle.cpp b/clang/lib/AST/Mangle.cpp
index 9652fdbc4e125..0bfb51c11f0a5 100644
--- a/clang/lib/AST/Mangle.cpp
+++ b/clang/lib/AST/Mangle.cpp
@@ -161,9 +161,9 @@ void MangleContext::mangleName(GlobalDecl GD, raw_ostream
&Out) {
if (const AsmLabelAttr *ALA = D->getAttr()) {
// If we have an asm name, then we use it as the mangling.
-// If the label isn't literal, or if this is an alias for an LLVM
intrinsic,
+// If the label is an alias for an LLVM intrinsic,
// do not add a "\01" prefix.
-if (!ALA->getIsLiteralLabel() || ALA->getLabel().starts_with("llvm.")) {
+if (ALA->getLabel().starts_with("llvm.")) {
Out << ALA->getLabel();
return;
}
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index e2ac648320c0f..885d04b9ab926 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -8113,9 +8113,7 @@ NamedDecl *Sema::ActOnVariableDeclarator(
}
}
-NewVD->addAttr(AsmLabelAttr::Create(Context, Label,
-/*IsLiteralLabel=*/true,
-SE->getStrTokenLoc(0)));
+NewVD->addAttr(AsmLabelAttr::Create(Context, Label,
SE->getStrTokenLoc(0)));
} else if (!ExtnameUndeclaredIdentifiers.empty()) {
llvm::DenseMap::iterator I =
ExtnameUndeclaredIdentifiers.find(NewVD->getIdentifier());
@@ -10345,9 +10343,8 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D,
DeclContext *DC,
if (Expr *E = D.getAsmLabel()) {
// The parser guarantees this is a string.
StringLiteral *SE = cast(E);
-NewFD->addAttr(AsmLabelAttr::Create(Context, SE->getString(),
-/*IsLiteralLabel=*/true,
-SE->getStrTokenLoc(0)));
+NewFD->addAttr(
+AsmLabelAttr::Create(Context, SE->getString(), SE->getStrTokenLoc(0)));
} else if (!ExtnameUndeclaredIdentifiers.empty()) {
llvm::DenseMap::iterator I =
ExtnameUndeclaredIdentifiers.find(NewFD->getIdentifier());
@@ -20598,8 +20595,8 @@ void Sema::ActOnPragmaRedefineExtname(IdentifierInfo*
Name,
LookupOrdinaryName);
AttributeCommonInfo Info(AliasName, SourceRange(AliasNameLoc),
AttributeCommonInfo::Form::Pragma());
- AsmLabelAttr *Attr = AsmLabelAttr::CreateImplicit(
- Context, AliasName->getName(), /*IsLiteralLabel=*/true, Info);
+ AsmLabelAttr *Attr =
+ AsmLab
[clang] [libcxxabi] [lldb] [llvm] [lldb][Expression] Add structor variant to LLDB's function call labels (PR #149827)
https://github.com/AaronBallman approved this pull request. Clang bits LGTM https://github.com/llvm/llvm-project/pull/149827 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libcxxabi] [lldb] [llvm] [lldb][Expression] Add structor variant to LLDB's function call labels (PR #149827)
https://github.com/Michael137 edited https://github.com/llvm/llvm-project/pull/149827 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libcxxabi] [lldb] [llvm] [lldb][Expression] Add structor variant to LLDB's function call labels (PR #149827)
https://github.com/Michael137 edited https://github.com/llvm/llvm-project/pull/149827 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libcxxabi] [lldb] [llvm] [lldb][Expression] Add structor variant to LLDB's function call labels (PR #149827)
https://github.com/Michael137 edited https://github.com/llvm/llvm-project/pull/149827 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libcxxabi] [lldb] [llvm] [lldb][Expression] Add structor variant to LLDB's function call labels (PR #149827)
https://github.com/Michael137 edited https://github.com/llvm/llvm-project/pull/149827 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libcxxabi] [lldb] [llvm] [lldb][Expression] Add structor variant to LLDB's function call labels (PR #149827)
Michael137 wrote: CC @AaronBallman for the Clang side of this https://github.com/llvm/llvm-project/pull/149827 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libcxxabi] [lldb] [llvm] [lldb][Expression] Add structor variant to LLDB's function call labels (PR #149827)
https://github.com/Michael137 edited https://github.com/llvm/llvm-project/pull/149827 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libcxxabi] [lldb] [llvm] [lldb][Expression] Add structor variant to LLDB's function call labels (PR #149827)
https://github.com/Michael137 edited https://github.com/llvm/llvm-project/pull/149827 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libcxxabi] [lldb] [llvm] [lldb][Expression] Add structor variant to LLDB's function call labels (PR #149827)
https://github.com/Michael137 edited https://github.com/llvm/llvm-project/pull/149827 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libcxxabi] [lldb] [llvm] [lldb][Expression] Add structor variant to LLDB's function call labels (PR #149827)
Michael137 wrote: This should be reviewable now. I split the Clang and demangler changes into separate commits. Ended up being a bit more involved that I had hoped but let me know what you think (particularly with the Clang mangler interaction). Also lacks some LLDB tests, which I'll add shortly. https://github.com/llvm/llvm-project/pull/149827 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libcxxabi] [lldb] [llvm] [lldb][Expression] Add structor variant to LLDB's function call labels (PR #149827)
https://github.com/Michael137 edited https://github.com/llvm/llvm-project/pull/149827 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libcxxabi] [lldb] [llvm] [lldb][Expression] Add structor variant to LLDB's function call labels (PR #149827)
llvmbot wrote:
@llvm/pr-subscribers-clang
Author: Michael Buch (Michael137)
Changes
Depends on https://github.com/llvm/llvm-project/pull/148877
---
Patch is 30.28 KiB, truncated to 20.00 KiB below, full version:
https://github.com/llvm/llvm-project/pull/149827.diff
16 Files Affected:
- (modified) clang/include/clang/Basic/Attr.td (+4-13)
- (modified) clang/lib/AST/Mangle.cpp (+21-3)
- (modified) clang/lib/Sema/SemaDecl.cpp (+5-8)
- (modified) clang/unittests/AST/DeclTest.cpp (+1-8)
- (modified) libcxxabi/src/demangle/ItaniumDemangle.h (+2)
- (modified) lldb/include/lldb/Expression/Expression.h (+6-2)
- (modified) lldb/source/Expression/Expression.cpp (+17-12)
- (modified) lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
(+45-2)
- (modified) lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp (+131-18)
- (modified) lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h (+4)
- (modified) lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp (+3-4)
- (modified) lldb/unittests/Expression/ExpressionTest.cpp (+22-15)
- (modified) lldb/unittests/Symbol/TestTypeSystemClang.cpp (+7-7)
- (modified) llvm/include/llvm/Demangle/Demangle.h (+3)
- (modified) llvm/include/llvm/Demangle/ItaniumDemangle.h (+2)
- (modified) llvm/lib/Demangle/ItaniumDemangle.cpp (+7-3)
``diff
diff --git a/clang/include/clang/Basic/Attr.td
b/clang/include/clang/Basic/Attr.td
index b3ff45b3e90a3..a0efb21218312 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -1059,22 +1059,13 @@ def AVRSignal : InheritableAttr,
TargetSpecificAttr {
def AsmLabel : InheritableAttr {
let Spellings = [CustomKeyword<"asm">, CustomKeyword<"__asm__">];
let Args = [
-// Label specifies the mangled name for the decl.
-StringArgument<"Label">,
-
-// IsLiteralLabel specifies whether the label is literal (i.e. suppresses
-// the global C symbol prefix) or not. If not, the mangle-suppression
prefix
-// ('\01') is omitted from the decl name at the LLVM IR level.
-//
-// Non-literal labels are used by some external AST sources like LLDB.
-BoolArgument<"IsLiteralLabel", /*optional=*/0, /*fake=*/1>
- ];
+ // Label specifies the mangled name for the decl.
+ StringArgument<"Label">, ];
let SemaHandler = 0;
let Documentation = [AsmLabelDocs];
- let AdditionalMembers =
-[{
+ let AdditionalMembers = [{
bool isEquivalent(AsmLabelAttr *Other) const {
- return getLabel() == Other->getLabel() && getIsLiteralLabel() ==
Other->getIsLiteralLabel();
+ return getLabel() == Other->getLabel();
}
}];
}
diff --git a/clang/lib/AST/Mangle.cpp b/clang/lib/AST/Mangle.cpp
index 9652fdbc4e125..58029476572c5 100644
--- a/clang/lib/AST/Mangle.cpp
+++ b/clang/lib/AST/Mangle.cpp
@@ -152,6 +152,20 @@ bool MangleContext::shouldMangleDeclName(const NamedDecl
*D) {
return shouldMangleCXXName(D);
}
+static llvm::StringRef g_lldb_func_call_label_prefix = "$__lldb_func";
+
+static void emitLLDBAsmLabel(llvm::StringRef label, GlobalDecl GD,
+ llvm::raw_ostream &Out) {
+ Out << g_lldb_func_call_label_prefix << ":";
+
+ if (llvm::isa(GD.getDecl()))
+Out << "C" << GD.getCtorType();
+ else if (llvm::isa(GD.getDecl()))
+Out << "D" << GD.getDtorType();
+
+ Out << label.substr(g_lldb_func_call_label_prefix.size() + 1);
+}
+
void MangleContext::mangleName(GlobalDecl GD, raw_ostream &Out) {
const ASTContext &ASTContext = getASTContext();
const NamedDecl *D = cast(GD.getDecl());
@@ -161,9 +175,9 @@ void MangleContext::mangleName(GlobalDecl GD, raw_ostream
&Out) {
if (const AsmLabelAttr *ALA = D->getAttr()) {
// If we have an asm name, then we use it as the mangling.
-// If the label isn't literal, or if this is an alias for an LLVM
intrinsic,
+// If the label is an alias for an LLVM intrinsic,
// do not add a "\01" prefix.
-if (!ALA->getIsLiteralLabel() || ALA->getLabel().starts_with("llvm.")) {
+if (ALA->getLabel().starts_with("llvm.")) {
Out << ALA->getLabel();
return;
}
@@ -185,7 +199,11 @@ void MangleContext::mangleName(GlobalDecl GD, raw_ostream
&Out) {
if (!UserLabelPrefix.empty())
Out << '\01'; // LLVM IR Marker for __asm("foo")
-Out << ALA->getLabel();
+if (ALA->getLabel().starts_with(g_lldb_func_call_label_prefix))
+ emitLLDBAsmLabel(ALA->getLabel(), GD, Out);
+else
+ Out << ALA->getLabel();
+
return;
}
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index e2ac648320c0f..885d04b9ab926 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -8113,9 +8113,7 @@ NamedDecl *Sema::ActOnVariableDeclarator(
}
}
-NewVD->addAttr(AsmLabelAttr::Create(Context, Label,
-/*IsLiteralLabel=*/true,
-SE->getStrTokenLoc(0)));
+NewVD->addAttr(AsmLabelAttr::Create(Context,
[clang] [libcxxabi] [lldb] [llvm] [lldb][Expression] Add structor variant to LLDB's function call labels (PR #149827)
llvmbot wrote:
@llvm/pr-subscribers-libcxxabi
Author: Michael Buch (Michael137)
Changes
Depends on https://github.com/llvm/llvm-project/pull/148877
---
Patch is 30.28 KiB, truncated to 20.00 KiB below, full version:
https://github.com/llvm/llvm-project/pull/149827.diff
16 Files Affected:
- (modified) clang/include/clang/Basic/Attr.td (+4-13)
- (modified) clang/lib/AST/Mangle.cpp (+21-3)
- (modified) clang/lib/Sema/SemaDecl.cpp (+5-8)
- (modified) clang/unittests/AST/DeclTest.cpp (+1-8)
- (modified) libcxxabi/src/demangle/ItaniumDemangle.h (+2)
- (modified) lldb/include/lldb/Expression/Expression.h (+6-2)
- (modified) lldb/source/Expression/Expression.cpp (+17-12)
- (modified) lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
(+45-2)
- (modified) lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp (+131-18)
- (modified) lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h (+4)
- (modified) lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp (+3-4)
- (modified) lldb/unittests/Expression/ExpressionTest.cpp (+22-15)
- (modified) lldb/unittests/Symbol/TestTypeSystemClang.cpp (+7-7)
- (modified) llvm/include/llvm/Demangle/Demangle.h (+3)
- (modified) llvm/include/llvm/Demangle/ItaniumDemangle.h (+2)
- (modified) llvm/lib/Demangle/ItaniumDemangle.cpp (+7-3)
``diff
diff --git a/clang/include/clang/Basic/Attr.td
b/clang/include/clang/Basic/Attr.td
index b3ff45b3e90a3..a0efb21218312 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -1059,22 +1059,13 @@ def AVRSignal : InheritableAttr,
TargetSpecificAttr {
def AsmLabel : InheritableAttr {
let Spellings = [CustomKeyword<"asm">, CustomKeyword<"__asm__">];
let Args = [
-// Label specifies the mangled name for the decl.
-StringArgument<"Label">,
-
-// IsLiteralLabel specifies whether the label is literal (i.e. suppresses
-// the global C symbol prefix) or not. If not, the mangle-suppression
prefix
-// ('\01') is omitted from the decl name at the LLVM IR level.
-//
-// Non-literal labels are used by some external AST sources like LLDB.
-BoolArgument<"IsLiteralLabel", /*optional=*/0, /*fake=*/1>
- ];
+ // Label specifies the mangled name for the decl.
+ StringArgument<"Label">, ];
let SemaHandler = 0;
let Documentation = [AsmLabelDocs];
- let AdditionalMembers =
-[{
+ let AdditionalMembers = [{
bool isEquivalent(AsmLabelAttr *Other) const {
- return getLabel() == Other->getLabel() && getIsLiteralLabel() ==
Other->getIsLiteralLabel();
+ return getLabel() == Other->getLabel();
}
}];
}
diff --git a/clang/lib/AST/Mangle.cpp b/clang/lib/AST/Mangle.cpp
index 9652fdbc4e125..58029476572c5 100644
--- a/clang/lib/AST/Mangle.cpp
+++ b/clang/lib/AST/Mangle.cpp
@@ -152,6 +152,20 @@ bool MangleContext::shouldMangleDeclName(const NamedDecl
*D) {
return shouldMangleCXXName(D);
}
+static llvm::StringRef g_lldb_func_call_label_prefix = "$__lldb_func";
+
+static void emitLLDBAsmLabel(llvm::StringRef label, GlobalDecl GD,
+ llvm::raw_ostream &Out) {
+ Out << g_lldb_func_call_label_prefix << ":";
+
+ if (llvm::isa(GD.getDecl()))
+Out << "C" << GD.getCtorType();
+ else if (llvm::isa(GD.getDecl()))
+Out << "D" << GD.getDtorType();
+
+ Out << label.substr(g_lldb_func_call_label_prefix.size() + 1);
+}
+
void MangleContext::mangleName(GlobalDecl GD, raw_ostream &Out) {
const ASTContext &ASTContext = getASTContext();
const NamedDecl *D = cast(GD.getDecl());
@@ -161,9 +175,9 @@ void MangleContext::mangleName(GlobalDecl GD, raw_ostream
&Out) {
if (const AsmLabelAttr *ALA = D->getAttr()) {
// If we have an asm name, then we use it as the mangling.
-// If the label isn't literal, or if this is an alias for an LLVM
intrinsic,
+// If the label is an alias for an LLVM intrinsic,
// do not add a "\01" prefix.
-if (!ALA->getIsLiteralLabel() || ALA->getLabel().starts_with("llvm.")) {
+if (ALA->getLabel().starts_with("llvm.")) {
Out << ALA->getLabel();
return;
}
@@ -185,7 +199,11 @@ void MangleContext::mangleName(GlobalDecl GD, raw_ostream
&Out) {
if (!UserLabelPrefix.empty())
Out << '\01'; // LLVM IR Marker for __asm("foo")
-Out << ALA->getLabel();
+if (ALA->getLabel().starts_with(g_lldb_func_call_label_prefix))
+ emitLLDBAsmLabel(ALA->getLabel(), GD, Out);
+else
+ Out << ALA->getLabel();
+
return;
}
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index e2ac648320c0f..885d04b9ab926 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -8113,9 +8113,7 @@ NamedDecl *Sema::ActOnVariableDeclarator(
}
}
-NewVD->addAttr(AsmLabelAttr::Create(Context, Label,
-/*IsLiteralLabel=*/true,
-SE->getStrTokenLoc(0)));
+NewVD->addAttr(AsmLabelAttr::Create(Conte
[clang] [libcxxabi] [lldb] [llvm] [lldb][Expression] Add structor variant to LLDB's function call labels (PR #149827)
llvmbot wrote:
@llvm/pr-subscribers-lldb
Author: Michael Buch (Michael137)
Changes
Depends on https://github.com/llvm/llvm-project/pull/148877
---
Patch is 30.28 KiB, truncated to 20.00 KiB below, full version:
https://github.com/llvm/llvm-project/pull/149827.diff
16 Files Affected:
- (modified) clang/include/clang/Basic/Attr.td (+4-13)
- (modified) clang/lib/AST/Mangle.cpp (+21-3)
- (modified) clang/lib/Sema/SemaDecl.cpp (+5-8)
- (modified) clang/unittests/AST/DeclTest.cpp (+1-8)
- (modified) libcxxabi/src/demangle/ItaniumDemangle.h (+2)
- (modified) lldb/include/lldb/Expression/Expression.h (+6-2)
- (modified) lldb/source/Expression/Expression.cpp (+17-12)
- (modified) lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
(+45-2)
- (modified) lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp (+131-18)
- (modified) lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h (+4)
- (modified) lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp (+3-4)
- (modified) lldb/unittests/Expression/ExpressionTest.cpp (+22-15)
- (modified) lldb/unittests/Symbol/TestTypeSystemClang.cpp (+7-7)
- (modified) llvm/include/llvm/Demangle/Demangle.h (+3)
- (modified) llvm/include/llvm/Demangle/ItaniumDemangle.h (+2)
- (modified) llvm/lib/Demangle/ItaniumDemangle.cpp (+7-3)
``diff
diff --git a/clang/include/clang/Basic/Attr.td
b/clang/include/clang/Basic/Attr.td
index b3ff45b3e90a3..a0efb21218312 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -1059,22 +1059,13 @@ def AVRSignal : InheritableAttr,
TargetSpecificAttr {
def AsmLabel : InheritableAttr {
let Spellings = [CustomKeyword<"asm">, CustomKeyword<"__asm__">];
let Args = [
-// Label specifies the mangled name for the decl.
-StringArgument<"Label">,
-
-// IsLiteralLabel specifies whether the label is literal (i.e. suppresses
-// the global C symbol prefix) or not. If not, the mangle-suppression
prefix
-// ('\01') is omitted from the decl name at the LLVM IR level.
-//
-// Non-literal labels are used by some external AST sources like LLDB.
-BoolArgument<"IsLiteralLabel", /*optional=*/0, /*fake=*/1>
- ];
+ // Label specifies the mangled name for the decl.
+ StringArgument<"Label">, ];
let SemaHandler = 0;
let Documentation = [AsmLabelDocs];
- let AdditionalMembers =
-[{
+ let AdditionalMembers = [{
bool isEquivalent(AsmLabelAttr *Other) const {
- return getLabel() == Other->getLabel() && getIsLiteralLabel() ==
Other->getIsLiteralLabel();
+ return getLabel() == Other->getLabel();
}
}];
}
diff --git a/clang/lib/AST/Mangle.cpp b/clang/lib/AST/Mangle.cpp
index 9652fdbc4e125..58029476572c5 100644
--- a/clang/lib/AST/Mangle.cpp
+++ b/clang/lib/AST/Mangle.cpp
@@ -152,6 +152,20 @@ bool MangleContext::shouldMangleDeclName(const NamedDecl
*D) {
return shouldMangleCXXName(D);
}
+static llvm::StringRef g_lldb_func_call_label_prefix = "$__lldb_func";
+
+static void emitLLDBAsmLabel(llvm::StringRef label, GlobalDecl GD,
+ llvm::raw_ostream &Out) {
+ Out << g_lldb_func_call_label_prefix << ":";
+
+ if (llvm::isa(GD.getDecl()))
+Out << "C" << GD.getCtorType();
+ else if (llvm::isa(GD.getDecl()))
+Out << "D" << GD.getDtorType();
+
+ Out << label.substr(g_lldb_func_call_label_prefix.size() + 1);
+}
+
void MangleContext::mangleName(GlobalDecl GD, raw_ostream &Out) {
const ASTContext &ASTContext = getASTContext();
const NamedDecl *D = cast(GD.getDecl());
@@ -161,9 +175,9 @@ void MangleContext::mangleName(GlobalDecl GD, raw_ostream
&Out) {
if (const AsmLabelAttr *ALA = D->getAttr()) {
// If we have an asm name, then we use it as the mangling.
-// If the label isn't literal, or if this is an alias for an LLVM
intrinsic,
+// If the label is an alias for an LLVM intrinsic,
// do not add a "\01" prefix.
-if (!ALA->getIsLiteralLabel() || ALA->getLabel().starts_with("llvm.")) {
+if (ALA->getLabel().starts_with("llvm.")) {
Out << ALA->getLabel();
return;
}
@@ -185,7 +199,11 @@ void MangleContext::mangleName(GlobalDecl GD, raw_ostream
&Out) {
if (!UserLabelPrefix.empty())
Out << '\01'; // LLVM IR Marker for __asm("foo")
-Out << ALA->getLabel();
+if (ALA->getLabel().starts_with(g_lldb_func_call_label_prefix))
+ emitLLDBAsmLabel(ALA->getLabel(), GD, Out);
+else
+ Out << ALA->getLabel();
+
return;
}
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index e2ac648320c0f..885d04b9ab926 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -8113,9 +8113,7 @@ NamedDecl *Sema::ActOnVariableDeclarator(
}
}
-NewVD->addAttr(AsmLabelAttr::Create(Context, Label,
-/*IsLiteralLabel=*/true,
-SE->getStrTokenLoc(0)));
+NewVD->addAttr(AsmLabelAttr::Create(Context, L
[clang] [libcxxabi] [lldb] [llvm] [lldb][Expression] Add structor variant to LLDB's function call labels (PR #149827)
https://github.com/Michael137 edited https://github.com/llvm/llvm-project/pull/149827 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libcxxabi] [lldb] [llvm] [lldb][Expression] Add structor variant to LLDB's function call labels (PR #149827)
https://github.com/Michael137 ready_for_review https://github.com/llvm/llvm-project/pull/149827 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
