-
Notifications
You must be signed in to change notification settings - Fork 14.9k
[clang][Mangle] Inject structor type into mangled name when mangling for LLDB JIT expressions #155485
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
…for LLDB JIT expressions Part of llvm#149827 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.
@llvm/pr-subscribers-lldb @llvm/pr-subscribers-clang Author: Michael Buch (Michael137) ChangesPart of #149827 This patch adds special handling for Full diff: https://github.com/llvm/llvm-project/pull/155485.diff 2 Files Affected:
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<clang::CXXConstructorDecl>(GD.getDecl()))
+ Out << "C" << GD.getCtorType();
+ else if (llvm::isa<clang::CXXDestructorDecl>(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<NamedDecl>(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<CXXRecordDecl>("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<ItaniumMangleContext> 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, "\x01$__lldb_func:C1:123:123:S");
+ };
+
+ {
+ std::string Mangled;
+ llvm::raw_string_ostream OS_Mangled(Mangled);
+ MC->mangleName(GlobalDecl(Dtor, CXXDtorType::Dtor_Deleting), OS_Mangled);
+
+ ASSERT_EQ(Mangled, "\x01$__lldb_func:D0:123:123:~S");
+ };
+
+ {
+ std::string Mangled;
+ llvm::raw_string_ostream OS_Mangled(Mangled);
+ MC->mangleName(GlobalDecl(Dtor, CXXDtorType::Dtor_Base), OS_Mangled);
+
+ ASSERT_EQ(Mangled, "\x01$__lldb_func:D2:123:123:~S");
+ };
+}
+
TEST(Decl, MangleDependentSizedArray) {
StringRef Code = R"(
template <int ...N>
|
@AaronBallman I think you looked at this already in #149827, but thought it's best I split this out since it's sufficiently niche behaviour to warrant its own commit. |
LLDB doesn't currently support inheriting ctors in the expression evaluator but I added this capability here for completeness. |
Part of #149827
This patch adds special handling for
AsmLabel
s created by LLDB. LLDB usesAsmLabel
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 theAsmLabelAttr
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.