Skip to content

Commit 44410a4

Browse files
committed
Structors Init
1 parent f1e3ce1 commit 44410a4

File tree

12 files changed

+171
-23
lines changed

12 files changed

+171
-23
lines changed

clang/lib/AST/Mangle.cpp

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

155+
static void tryEmitDebugStructorVariant(GlobalDecl GD, raw_ostream &Out) {
156+
// TODO: shouldn't append but instead slice
157+
if (llvm::isa<clang::CXXConstructorDecl>(GD.getDecl()))
158+
Out << "C" << GD.getCtorType();
159+
else if (llvm::isa<clang::CXXDestructorDecl>(GD.getDecl()))
160+
Out << "D" << GD.getDtorType();
161+
}
162+
155163
void MangleContext::mangleName(GlobalDecl GD, raw_ostream &Out) {
156164
const ASTContext &ASTContext = getASTContext();
157165
const NamedDecl *D = cast<NamedDecl>(GD.getDecl());
@@ -161,10 +169,12 @@ void MangleContext::mangleName(GlobalDecl GD, raw_ostream &Out) {
161169
if (const AsmLabelAttr *ALA = D->getAttr<AsmLabelAttr>()) {
162170
// If we have an asm name, then we use it as the mangling.
163171

172+
// TODO: remove this getIsLiteralLabel branch
164173
// If the label isn't literal, or if this is an alias for an LLVM intrinsic,
165174
// do not add a "\01" prefix.
166175
if (!ALA->getIsLiteralLabel() || ALA->getLabel().starts_with("llvm.")) {
167176
Out << ALA->getLabel();
177+
168178
return;
169179
}
170180

@@ -186,6 +196,11 @@ void MangleContext::mangleName(GlobalDecl GD, raw_ostream &Out) {
186196
Out << '\01'; // LLVM IR Marker for __asm("foo")
187197

188198
Out << ALA->getLabel();
199+
200+
// TODO: ideally should have separate attribute for this?
201+
if (ASTContext.getLangOpts().DebuggerSupport)
202+
tryEmitDebugStructorVariant(GD, Out);
203+
189204
return;
190205
}
191206

libcxxabi/src/demangle/ItaniumDemangle.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1766,6 +1766,8 @@ class CtorDtorName final : public Node {
17661766

17671767
template<typename Fn> void match(Fn F) const { F(Basename, IsDtor, Variant); }
17681768

1769+
int getVariant() const { return Variant; }
1770+
17691771
void printLeft(OutputBuffer &OB) const override {
17701772
if (IsDtor)
17711773
OB += "~";

lldb/include/lldb/Expression/Expression.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ class Expression {
103103
///
104104
/// The format being:
105105
///
106-
/// <prefix>:<module uid>:<symbol uid>:<name>
106+
/// <prefix>:<module uid>:<symbol uid>:<discriminator>:<name>
107107
///
108108
/// The label string needs to stay valid for the entire lifetime
109109
/// of this object.
@@ -126,14 +126,16 @@ struct FunctionCallLabel {
126126
/// ':' in the mangled name when parsing the label.
127127
llvm::StringRef lookup_name;
128128

129+
llvm::StringRef discriminator;
130+
129131
/// Decodes the specified function \c label into a \c FunctionCallLabel.
130132
static llvm::Expected<FunctionCallLabel> fromString(llvm::StringRef label);
131133

132134
/// Encode this FunctionCallLabel into its string representation.
133135
///
134136
/// The representation roundtrips through \c fromString:
135137
/// \code{.cpp}
136-
/// llvm::StringRef encoded = "$__lldb_func:0x0:0x0:_Z3foov";
138+
/// llvm::StringRef encoded = "$__lldb_func:0x0:0x0:_Z3foov:";
137139
/// FunctionCallLabel label = *fromString(label);
138140
///
139141
/// assert (label.toString() == encoded);

lldb/source/Expression/Expression.cpp

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,10 @@ Expression::Expression(ExecutionContextScope &exe_scope)
3434

3535
llvm::Expected<FunctionCallLabel>
3636
lldb_private::FunctionCallLabel::fromString(llvm::StringRef label) {
37-
llvm::SmallVector<llvm::StringRef, 4> components;
38-
label.split(components, ":", /*MaxSplit=*/3);
37+
llvm::SmallVector<llvm::StringRef, 5> components;
38+
label.split(components, ":", /*MaxSplit=*/4);
3939

40-
if (components.size() != 4)
40+
if (components.size() != 5)
4141
return llvm::createStringError("malformed function call label.");
4242

4343
if (components[0] != FunctionCallLabelPrefix)
@@ -47,6 +47,10 @@ lldb_private::FunctionCallLabel::fromString(llvm::StringRef label) {
4747

4848
llvm::StringRef module_label = components[1];
4949
llvm::StringRef die_label = components[2];
50+
llvm::StringRef lookup_name =
51+
components[3]; // TODO: mangled name should come last...clang should
52+
// splice it into the label?
53+
llvm::StringRef discriminator = components[4];
5054

5155
lldb::user_id_t module_id = 0;
5256
if (!llvm::to_integer(module_label, module_id))
@@ -60,18 +64,20 @@ lldb_private::FunctionCallLabel::fromString(llvm::StringRef label) {
6064

6165
return FunctionCallLabel{/*.module_id=*/module_id,
6266
/*.symbol_id=*/die_id,
63-
/*.lookup_name=*/components[3]};
67+
/*.lookup_name=*/lookup_name,
68+
/*.discriminator=*/discriminator};
6469
}
6570

6671
std::string lldb_private::FunctionCallLabel::toString() const {
67-
return llvm::formatv("{0}:{1:x}:{2:x}:{3}", FunctionCallLabelPrefix,
68-
module_id, symbol_id, lookup_name)
72+
return llvm::formatv("{0}:{1:x}:{2:x}:{3}:{4}", FunctionCallLabelPrefix,
73+
module_id, symbol_id, lookup_name, discriminator)
6974
.str();
7075
}
7176

7277
void llvm::format_provider<FunctionCallLabel>::format(
7378
const FunctionCallLabel &label, raw_ostream &OS, StringRef Style) {
7479
OS << llvm::formatv("FunctionCallLabel{ module_id: {0:x}, symbol_id: {1:x}, "
75-
"lookup_name: {2} }",
76-
label.module_id, label.symbol_id, label.lookup_name);
80+
"lookup_name: {2}, discriminator: {3} }",
81+
label.module_id, label.symbol_id, label.lookup_name,
82+
label.discriminator);
7783
}

lldb/source/Expression/IRExecutionUnit.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -947,7 +947,7 @@ lldb::addr_t IRExecutionUnit::FindSymbol(lldb_private::ConstString name,
947947
auto label_or_err = FunctionCallLabel::fromString(name);
948948
if (!label_or_err) {
949949
LLDB_LOG_ERROR(GetLog(LLDBLog::Expressions), label_or_err.takeError(),
950-
"failed to create FunctionCallLabel from '{0}': {1}",
950+
"failed to create FunctionCallLabel from '{1}': {0}",
951951
name.GetStringRef());
952952
return LLDB_INVALID_ADDRESS;
953953
}

lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -250,8 +250,36 @@ static unsigned GetCXXMethodCVQuals(const DWARFDIE &subprogram,
250250
return cv_quals;
251251
}
252252

253+
static const char *GetMangledOrStructorName(const DWARFDIE &die) {
254+
const char *name = die.GetMangledName(/*substitute_name_allowed*/ false);
255+
if (name)
256+
return name;
257+
258+
name = die.GetName();
259+
if (!name)
260+
return nullptr;
261+
262+
DWARFDIE parent = die.GetParent();
263+
if (!parent.IsStructUnionOrClass())
264+
return nullptr;
265+
266+
const char *parent_name = parent.GetName();
267+
if (!parent_name)
268+
return nullptr;
269+
270+
// Constructor.
271+
if (::strcmp(parent_name, name) == 0)
272+
return name;
273+
274+
// Destructor.
275+
if (name[0] == '~' && ::strcmp(parent_name, name + 1))
276+
return name;
277+
278+
return nullptr;
279+
}
280+
253281
static std::string MakeLLDBFuncAsmLabel(const DWARFDIE &die) {
254-
char const *name = die.GetMangledName(/*substitute_name_allowed*/ false);
282+
char const *name = GetMangledOrStructorName(die);
255283
if (!name)
256284
return {};
257285

@@ -285,9 +313,11 @@ static std::string MakeLLDBFuncAsmLabel(const DWARFDIE &die) {
285313
if (die_id == LLDB_INVALID_UID)
286314
return {};
287315

316+
// Note, discriminator is added by Clang during mangling.
288317
return FunctionCallLabel{/*module_id=*/module_id,
289318
/*symbol_id=*/die_id,
290-
/*.lookup_name=*/name}
319+
/*.lookup_name=*/name,
320+
/*discriminator=*/{}}
291321
.toString();
292322
}
293323

lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp

Lines changed: 88 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "SymbolFileDWARF.h"
10+
#include "clang/Basic/ABI.h"
1011
#include "llvm/ADT/STLExtras.h"
12+
#include "llvm/ADT/StringExtras.h"
1113
#include "llvm/DebugInfo/DWARF/DWARFAddressRange.h"
1214
#include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h"
1315
#include "llvm/Support/Casting.h"
@@ -77,6 +79,7 @@
7779

7880
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
7981
#include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"
82+
#include "llvm/Demangle/Demangle.h"
8083
#include "llvm/Support/FileSystem.h"
8184
#include "llvm/Support/FormatVariadic.h"
8285

@@ -2475,6 +2478,56 @@ bool SymbolFileDWARF::ResolveFunction(const DWARFDIE &orig_die,
24752478
return false;
24762479
}
24772480

2481+
static uint8_t ClangToItaniumCtorKind(clang::CXXCtorType kind) {
2482+
switch (kind) {
2483+
case clang::CXXCtorType::Ctor_Complete:
2484+
return 1;
2485+
case clang::CXXCtorType::Ctor_Base:
2486+
return 2;
2487+
case clang::CXXCtorType::Ctor_CopyingClosure:
2488+
case clang::CXXCtorType::Ctor_DefaultClosure:
2489+
case clang::CXXCtorType::Ctor_Comdat:
2490+
llvm_unreachable("Unexpected constructor kind.");
2491+
}
2492+
}
2493+
2494+
static uint8_t ClangToItaniumDtorKind(clang::CXXDtorType kind) {
2495+
switch (kind) {
2496+
case clang::CXXDtorType::Dtor_Deleting:
2497+
return 0;
2498+
case clang::CXXDtorType::Dtor_Complete:
2499+
return 1;
2500+
case clang::CXXDtorType::Dtor_Base:
2501+
return 2;
2502+
case clang::CXXDtorType::Dtor_Comdat:
2503+
llvm_unreachable("Unexpected destructor kind.");
2504+
}
2505+
}
2506+
2507+
static std::optional<uint8_t>
2508+
GetItaniumCtorDtorVariant(llvm::StringRef discriminator) {
2509+
const bool is_ctor = discriminator.consume_front("C");
2510+
if (!is_ctor && !discriminator.consume_front("D"))
2511+
return std::nullopt;
2512+
2513+
uint64_t structor_kind;
2514+
if (!llvm::to_integer(discriminator, structor_kind))
2515+
return std::nullopt;
2516+
2517+
if (is_ctor) {
2518+
if (structor_kind > clang::CXXCtorType::Ctor_DefaultClosure)
2519+
return std::nullopt;
2520+
2521+
return ClangToItaniumCtorKind(
2522+
static_cast<clang::CXXCtorType>(structor_kind));
2523+
}
2524+
2525+
if (structor_kind > clang::CXXDtorType::Dtor_Deleting)
2526+
return std::nullopt;
2527+
2528+
return ClangToItaniumDtorKind(static_cast<clang::CXXDtorType>(structor_kind));
2529+
}
2530+
24782531
llvm::Expected<SymbolContext>
24792532
SymbolFileDWARF::ResolveFunctionCallLabel(const FunctionCallLabel &label) {
24802533
std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
@@ -2487,21 +2540,49 @@ SymbolFileDWARF::ResolveFunctionCallLabel(const FunctionCallLabel &label) {
24872540
// Label was created using a declaration DIE. Need to fetch the definition
24882541
// to resolve the function call.
24892542
if (die.GetAttributeValueAsUnsigned(llvm::dwarf::DW_AT_declaration, 0)) {
2543+
// eFunctionNameTypeFull for mangled name lookup.
2544+
// eFunctionNameTypeMethod is required for structor lookups (since we look
2545+
// those up by DW_AT_name).
24902546
Module::LookupInfo info(ConstString(label.lookup_name),
2491-
lldb::eFunctionNameTypeFull,
2547+
lldb::eFunctionNameTypeFull |
2548+
lldb::eFunctionNameTypeMethod,
24922549
lldb::eLanguageTypeUnknown);
24932550

24942551
m_index->GetFunctions(info, *this, {}, [&](DWARFDIE entry) {
24952552
if (entry.GetAttributeValueAsUnsigned(llvm::dwarf::DW_AT_declaration, 0))
24962553
return true;
24972554

2498-
// We don't check whether the specification DIE for this function
2499-
// corresponds to the declaration DIE because the declaration might be in
2500-
// a type-unit but the definition in the compile-unit (and it's
2501-
// specifcation would point to the declaration in the compile-unit). We
2502-
// rely on the mangled name within the module to be enough to find us the
2503-
// unique definition.
2555+
// TODO: this specification check doesn't work if declaration DIE was in a
2556+
// type-unit (we should only encode DIEs from .debug_info).
2557+
auto spec = entry.GetAttributeValueAsReferenceDIE(DW_AT_specification);
2558+
if (!spec)
2559+
return true;
2560+
2561+
if (spec != die)
2562+
return true;
2563+
2564+
// We're not picking a specific structor variant DIE, so we're done here.
2565+
if (label.discriminator.empty()) {
2566+
die = entry;
2567+
return false;
2568+
}
2569+
2570+
const char *mangled =
2571+
entry.GetMangledName(/*substitute_name_allowed=*/false);
2572+
if (!mangled)
2573+
return true;
2574+
2575+
llvm::ItaniumPartialDemangler D;
2576+
if (D.partialDemangle(mangled))
2577+
return true;
2578+
2579+
// TODO: account for constructor alias (only an issue on Linux)
2580+
if (D.getCtorOrDtorVariant() !=
2581+
GetItaniumCtorDtorVariant(label.discriminator).value_or(-1))
2582+
return true;
2583+
25042584
die = entry;
2585+
25052586
return false;
25062587
});
25072588

lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
#include "clang/AST/DeclBase.h"
1212
#include "clang/AST/ExprCXX.h"
13+
#include "clang/Basic/ABI.h"
1314
#include "clang/Frontend/ASTConsumers.h"
1415
#include "llvm/Support/Casting.h"
1516
#include "llvm/Support/FormatAdapters.h"

lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <set>
1919
#include <string>
2020
#include <utility>
21+
#include <variant>
2122
#include <vector>
2223

2324
#include "clang/AST/ASTContext.h"
@@ -26,6 +27,7 @@
2627
#include "clang/AST/Decl.h"
2728
#include "clang/AST/TemplateBase.h"
2829
#include "clang/AST/Type.h"
30+
#include "clang/Basic/ABI.h"
2931
#include "clang/Basic/TargetInfo.h"
3032
#include "llvm/ADT/APSInt.h"
3133
#include "llvm/ADT/SmallVector.h"

llvm/include/llvm/Demangle/Demangle.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,9 @@ struct ItaniumPartialDemangler {
127127
/// If this symbol describes a constructor or destructor.
128128
DEMANGLE_ABI bool isCtorOrDtor() const;
129129

130+
/// If this symbol describes a constructor or destructor.
131+
std::optional<int> getCtorOrDtorVariant() const;
132+
130133
/// If this symbol describes a function.
131134
DEMANGLE_ABI bool isFunction() const;
132135

0 commit comments

Comments
 (0)