Skip to content

Commit 88e1c04

Browse files
committed
[clang][Mangle] Inject structor type into mangled name when mangling for LLDB JIT expressions (llvm#155485)
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. (cherry picked from commit db8cad0)
1 parent e4fbadb commit 88e1c04

File tree

3 files changed

+160
-5
lines changed

3 files changed

+160
-5
lines changed

clang/lib/AST/Mangle.cpp

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,37 @@ bool MangleContext::shouldMangleDeclName(const NamedDecl *D) {
152152
return shouldMangleCXXName(D);
153153
}
154154

155+
static llvm::StringRef g_lldb_func_call_label_prefix = "$__lldb_func:";
156+
157+
/// Given an LLDB function call label, this function prints the label
158+
/// into \c Out, together with the structor type of \c GD (if the
159+
/// decl is a constructor/destructor). LLDB knows how to handle mangled
160+
/// names with this encoding.
161+
///
162+
/// Example input label:
163+
/// $__lldb_func::123:456:~Foo
164+
///
165+
/// Example output:
166+
/// $__lldb_func:D1:123:456:~Foo
167+
///
168+
static void emitLLDBAsmLabel(llvm::StringRef label, GlobalDecl GD,
169+
llvm::raw_ostream &Out) {
170+
assert(label.starts_with(g_lldb_func_call_label_prefix));
171+
172+
Out << g_lldb_func_call_label_prefix;
173+
174+
if (auto *Ctor = llvm::dyn_cast<clang::CXXConstructorDecl>(GD.getDecl())) {
175+
Out << "C";
176+
if (Ctor->getInheritedConstructor().getConstructor())
177+
Out << "I";
178+
Out << GD.getCtorType();
179+
} else if (llvm::isa<clang::CXXDestructorDecl>(GD.getDecl())) {
180+
Out << "D" << GD.getDtorType();
181+
}
182+
183+
Out << label.substr(g_lldb_func_call_label_prefix.size());
184+
}
185+
155186
void MangleContext::mangleName(GlobalDecl GD, raw_ostream &Out) {
156187
const ASTContext &ASTContext = getASTContext();
157188
const NamedDecl *D = cast<NamedDecl>(GD.getDecl());
@@ -185,7 +216,11 @@ void MangleContext::mangleName(GlobalDecl GD, raw_ostream &Out) {
185216
if (!UserLabelPrefix.empty())
186217
Out << '\01'; // LLVM IR Marker for __asm("foo")
187218

188-
Out << ALA->getLabel();
219+
if (ALA->getLabel().starts_with(g_lldb_func_call_label_prefix))
220+
emitLLDBAsmLabel(ALA->getLabel(), GD, Out);
221+
else
222+
Out << ALA->getLabel();
223+
189224
return;
190225
}
191226

clang/unittests/AST/DeclTest.cpp

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,12 @@
1313
#include "MatchVerifier.h"
1414
#include "clang/AST/Decl.h"
1515
#include "clang/AST/ASTContext.h"
16+
#include "clang/AST/DeclCXX.h"
1617
#include "clang/AST/DeclTemplate.h"
1718
#include "clang/AST/Mangle.h"
1819
#include "clang/ASTMatchers/ASTMatchFinder.h"
1920
#include "clang/ASTMatchers/ASTMatchers.h"
21+
#include "clang/Basic/ABI.h"
2022
#include "clang/Basic/Diagnostic.h"
2123
#include "clang/Basic/LLVM.h"
2224
#include "clang/Basic/TargetInfo.h"
@@ -159,6 +161,124 @@ TEST(Decl, AsmLabelAttr) {
159161
"foo");
160162
}
161163

164+
TEST(Decl, AsmLabelAttr_LLDB) {
165+
StringRef Code = R"(
166+
struct S {
167+
void f() {}
168+
S() = default;
169+
~S() = default;
170+
};
171+
)";
172+
auto AST =
173+
tooling::buildASTFromCodeWithArgs(Code, {"-target", "i386-apple-darwin"});
174+
ASTContext &Ctx = AST->getASTContext();
175+
assert(Ctx.getTargetInfo().getUserLabelPrefix() == StringRef("_") &&
176+
"Expected target to have a global prefix");
177+
DiagnosticsEngine &Diags = AST->getDiagnostics();
178+
179+
const auto *DeclS =
180+
selectFirst<CXXRecordDecl>("d", match(cxxRecordDecl().bind("d"), Ctx));
181+
182+
auto *DeclF = *DeclS->method_begin();
183+
auto *Ctor = *DeclS->ctor_begin();
184+
auto *Dtor = DeclS->getDestructor();
185+
186+
ASSERT_TRUE(DeclF);
187+
ASSERT_TRUE(Ctor);
188+
ASSERT_TRUE(Dtor);
189+
190+
DeclF->addAttr(AsmLabelAttr::Create(Ctx, "$__lldb_func::123:123:_Z1fv"));
191+
Ctor->addAttr(AsmLabelAttr::Create(Ctx, "$__lldb_func::123:123:S"));
192+
Dtor->addAttr(AsmLabelAttr::Create(Ctx, "$__lldb_func::123:123:~S"));
193+
194+
std::unique_ptr<ItaniumMangleContext> MC(
195+
ItaniumMangleContext::create(Ctx, Diags));
196+
197+
{
198+
std::string Mangled;
199+
llvm::raw_string_ostream OS_Mangled(Mangled);
200+
MC->mangleName(DeclF, OS_Mangled);
201+
202+
ASSERT_EQ(Mangled, "\x01$__lldb_func::123:123:_Z1fv");
203+
};
204+
205+
{
206+
std::string Mangled;
207+
llvm::raw_string_ostream OS_Mangled(Mangled);
208+
MC->mangleName(GlobalDecl(Ctor, CXXCtorType::Ctor_Complete), OS_Mangled);
209+
210+
ASSERT_EQ(Mangled, "\x01$__lldb_func:C0:123:123:S");
211+
};
212+
213+
{
214+
std::string Mangled;
215+
llvm::raw_string_ostream OS_Mangled(Mangled);
216+
MC->mangleName(GlobalDecl(Ctor, CXXCtorType::Ctor_Base), OS_Mangled);
217+
218+
ASSERT_EQ(Mangled, "\x01$__lldb_func:C1:123:123:S");
219+
};
220+
221+
{
222+
std::string Mangled;
223+
llvm::raw_string_ostream OS_Mangled(Mangled);
224+
MC->mangleName(GlobalDecl(Dtor, CXXDtorType::Dtor_Deleting), OS_Mangled);
225+
226+
ASSERT_EQ(Mangled, "\x01$__lldb_func:D0:123:123:~S");
227+
};
228+
229+
{
230+
std::string Mangled;
231+
llvm::raw_string_ostream OS_Mangled(Mangled);
232+
MC->mangleName(GlobalDecl(Dtor, CXXDtorType::Dtor_Base), OS_Mangled);
233+
234+
ASSERT_EQ(Mangled, "\x01$__lldb_func:D2:123:123:~S");
235+
};
236+
}
237+
238+
TEST(Decl, AsmLabelAttr_LLDB_Inherit) {
239+
StringRef Code = R"(
240+
struct Base {
241+
Base(int x) {}
242+
};
243+
244+
struct Derived : Base {
245+
using Base::Base;
246+
} d(5);
247+
)";
248+
auto AST =
249+
tooling::buildASTFromCodeWithArgs(Code, {"-target", "i386-apple-darwin"});
250+
ASTContext &Ctx = AST->getASTContext();
251+
assert(Ctx.getTargetInfo().getUserLabelPrefix() == StringRef("_") &&
252+
"Expected target to have a global prefix");
253+
DiagnosticsEngine &Diags = AST->getDiagnostics();
254+
255+
const auto *Ctor = selectFirst<CXXConstructorDecl>(
256+
"ctor",
257+
match(cxxConstructorDecl(isInheritingConstructor()).bind("ctor"), Ctx));
258+
259+
const_cast<CXXConstructorDecl *>(Ctor)->addAttr(
260+
AsmLabelAttr::Create(Ctx, "$__lldb_func::123:123:Derived"));
261+
262+
std::unique_ptr<ItaniumMangleContext> MC(
263+
ItaniumMangleContext::create(Ctx, Diags));
264+
265+
{
266+
std::string Mangled;
267+
llvm::raw_string_ostream OS_Mangled(Mangled);
268+
MC->mangleName(GlobalDecl(Ctor, CXXCtorType::Ctor_Complete), OS_Mangled);
269+
270+
ASSERT_EQ(Mangled, "\x01$__lldb_func:CI0:123:123:Derived");
271+
};
272+
273+
{
274+
std::string Mangled;
275+
llvm::raw_string_ostream OS_Mangled(Mangled);
276+
MC->mangleName(GlobalDecl(Ctor, CXXCtorType::Ctor_Base), OS_Mangled);
277+
278+
ASSERT_EQ(Mangled, "\x01$__lldb_func:CI1:123:123:Derived");
279+
};
280+
}
281+
162282
TEST(Decl, MangleDependentSizedArray) {
163283
StringRef Code = R"(
164284
template <int ...N>

lldb/unittests/Symbol/TestTypeSystemClang.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1149,12 +1149,12 @@ TEST_F(TestTypeSystemClang, AsmLabel_CtorDtor) {
11491149
is_explicit, is_attr_used, is_artificial);
11501150

11511151
auto *ctor = m_ast->AddMethodToCXXRecordType(
1152-
t.GetOpaqueQualType(), "S", /*asm_label=*/"$__lldb_func:0x0:0x0:S",
1152+
t.GetOpaqueQualType(), "S", /*asm_label=*/"$__lldb_func::0x0:0x0:S",
11531153
function_type, lldb::AccessType::eAccessPublic, is_virtual, is_static,
11541154
is_inline, is_explicit, is_attr_used, is_artificial);
11551155

11561156
auto *dtor = m_ast->AddMethodToCXXRecordType(
1157-
t.GetOpaqueQualType(), "~S", /*asm_label=*/"$__lldb_func:0x0:0x0:~S",
1157+
t.GetOpaqueQualType(), "~S", /*asm_label=*/"$__lldb_func::0x0:0x0:~S",
11581158
function_type, lldb::AccessType::eAccessPublic, is_virtual, is_static,
11591159
is_inline, is_explicit, is_attr_used, is_artificial);
11601160

@@ -1180,11 +1180,11 @@ TEST_F(TestTypeSystemClang, AsmLabel_CtorDtor) {
11801180
EXPECT_STREQ(llvm::GlobalValue::dropLLVMManglingEscape(
11811181
m_ast->DeclGetMangledName(ctor).GetStringRef())
11821182
.data(),
1183-
"$__lldb_func:0x0:0x0:S");
1183+
"$__lldb_func:C0:0x0:0x0:S");
11841184
EXPECT_STREQ(llvm::GlobalValue::dropLLVMManglingEscape(
11851185
m_ast->DeclGetMangledName(dtor).GetStringRef())
11861186
.data(),
1187-
"$__lldb_func:0x0:0x0:~S");
1187+
"$__lldb_func:D1:0x0:0x0:~S");
11881188
}
11891189

11901190
struct AsmLabelTestCase {

0 commit comments

Comments
 (0)