Skip to content

Commit 4e242f8

Browse files
committed
Structors init
1 parent 326d786 commit 4e242f8

File tree

14 files changed

+217
-34
lines changed

14 files changed

+217
-34
lines changed

clang/lib/AST/Mangle.cpp

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

155+
static void tryEmitDebugStructorVariant(GlobalDecl GD, raw_ostream &Out) {
156+
if (llvm::isa<clang::CXXConstructorDecl>(GD.getDecl()))
157+
Out << "C" << GD.getCtorType();
158+
else if (llvm::isa<clang::CXXDestructorDecl>(GD.getDecl()))
159+
Out << "D" << GD.getDtorType();
160+
}
161+
155162
void MangleContext::mangleName(GlobalDecl GD, raw_ostream &Out) {
156163
const ASTContext &ASTContext = getASTContext();
157164
const NamedDecl *D = cast<NamedDecl>(GD.getDecl());
@@ -165,6 +172,11 @@ void MangleContext::mangleName(GlobalDecl GD, raw_ostream &Out) {
165172
// do not add a "\01" prefix.
166173
if (!ALA->getIsLiteralLabel() || ALA->getLabel().starts_with("llvm.")) {
167174
Out << ALA->getLabel();
175+
176+
// TODO: ideally should have separate attribute for this?
177+
if (ASTContext.getLangOpts().DebuggerSupport)
178+
tryEmitDebugStructorVariant(GD, Out);
179+
168180
return;
169181
}
170182

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: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,11 @@ struct FunctionCallLabel {
112112

113113
/// Mostly for debuggability.
114114
lldb::user_id_t m_die_id;
115+
116+
virtual ~FunctionCallLabel() = default;
117+
virtual std::optional<uint8_t> getItaniumStructorVariant() const {
118+
return std::nullopt;
119+
}
115120
};
116121

117122
/// LLDB attaches this prefix to mangled names of functions that it get called

lldb/include/lldb/Symbol/SymbolFile.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -337,8 +337,10 @@ class SymbolFile : public PluginInterface {
337337
///
338338
/// \param[in] lookup_name The UID of the function DIE to resolve.
339339
///
340-
virtual llvm::Error FindAndResolveFunction(SymbolContextList &sc_list,
341-
llvm::StringRef lookup_name) {
340+
virtual llvm::Error
341+
FindAndResolveFunction(SymbolContextList &sc_list,
342+
llvm::StringRef lookup_name, lldb::user_id_t spec,
343+
std::optional<uint8_t> structor_variant) {
342344
return llvm::createStringError("Not implemented");
343345
}
344346

lldb/include/lldb/Symbol/TypeSystem.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -559,7 +559,7 @@ class TypeSystem : public PluginInterface,
559559
}
560560

561561
// Decodes the function label into a \c FunctionCallLabel.
562-
virtual llvm::Expected<FunctionCallLabel>
562+
virtual llvm::Expected<std::unique_ptr<FunctionCallLabel>>
563563
makeFunctionCallLabel(llvm::StringRef label) const {
564564
return llvm::createStringError("Not implemented.");
565565
}

lldb/source/Expression/IRExecutionUnit.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -801,13 +801,13 @@ ResolveFunctionCallLabel(llvm::StringRef name,
801801
auto ts_sp = *ts_or_err;
802802

803803
auto label_or_err = ts_sp->makeFunctionCallLabel(name);
804-
if (!label_or_err)
804+
if (!label_or_err || !*label_or_err)
805805
return llvm::joinErrors(
806806
llvm::createStringError("failed to create FunctionCallLabel from: %s",
807807
name.data()),
808808
label_or_err.takeError());
809809

810-
const auto &label = *label_or_err;
810+
const auto &label = **label_or_err;
811811

812812
Module *module = Module::GetAllocatedModuleWithUID(label.m_module_id);
813813

@@ -821,8 +821,9 @@ ResolveFunctionCallLabel(llvm::StringRef name,
821821
llvm::formatv("no SymbolFile found on module {0:x}.", module));
822822

823823
SymbolContextList sc_list;
824-
if (auto err =
825-
symbol_file->FindAndResolveFunction(sc_list, label.m_lookup_name))
824+
if (auto err = symbol_file->FindAndResolveFunction(
825+
sc_list, label.m_lookup_name, label.m_die_id,
826+
label.getItaniumStructorVariant()))
826827
return llvm::joinErrors(
827828
llvm::createStringError("failed to resolve function by UID"),
828829
std::move(err));

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

Lines changed: 30 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::optional<std::string> MakeLLDBFuncAsmLabel(const DWARFDIE &die) {
254-
char const *name = die.GetMangledName(/*substitute_name_allowed*/ false);
282+
const char *name = GetMangledOrStructorName(die);
255283
if (!name)
256284
return std::nullopt;
257285

@@ -267,7 +295,7 @@ static std::optional<std::string> MakeLLDBFuncAsmLabel(const DWARFDIE &die) {
267295
if (die_id == LLDB_INVALID_UID)
268296
return std::nullopt;
269297

270-
return llvm::formatv("{0}:{1}:{2:x}:{3:x}", FunctionCallLabelPrefix, name,
298+
return llvm::formatv("{0}:{1}:{2:x}:{3:x}:", FunctionCallLabelPrefix, name,
271299
module_id, die_id)
272300
.str();
273301
}

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

Lines changed: 45 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@
7676

7777
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
7878
#include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"
79+
#include "llvm/Demangle/Demangle.h"
7980
#include "llvm/Support/FileSystem.h"
8081
#include "llvm/Support/FormatVariadic.h"
8182

@@ -2471,32 +2472,63 @@ bool SymbolFileDWARF::ResolveFunction(const DWARFDIE &orig_die,
24712472
return false;
24722473
}
24732474

2474-
llvm::Error
2475-
SymbolFileDWARF::FindAndResolveFunction(SymbolContextList &sc_list,
2476-
llvm::StringRef lookup_name) {
2475+
llvm::Error SymbolFileDWARF::FindAndResolveFunction(
2476+
SymbolContextList &sc_list, llvm::StringRef lookup_name,
2477+
lldb::user_id_t die_id, std::optional<uint8_t> structor_variant) {
24772478
std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
2478-
2479-
DWARFDIE die;
2480-
Module::LookupInfo info(ConstString(lookup_name), lldb::eFunctionNameTypeFull,
2479+
DWARFDIE die = GetDIE(die_id);
2480+
if (!die.IsValid())
2481+
return llvm::createStringError("invalid DIE for UID: %" PRIu64, die_id);
2482+
2483+
// eFunctionNameTypeFull for mangled name lookup.
2484+
// eFunctionNameTypeMethod is required for structor lookups (since we look
2485+
// those up by DW_AT_name).
2486+
Module::LookupInfo info(ConstString(lookup_name),
2487+
lldb::eFunctionNameTypeFull |
2488+
lldb::eFunctionNameTypeMethod,
24812489
lldb::eLanguageTypeUnknown);
24822490

24832491
m_index->GetFunctions(info, *this, {}, [&](DWARFDIE entry) {
24842492
if (entry.GetAttributeValueAsUnsigned(llvm::dwarf::DW_AT_declaration, 0))
24852493
return true;
24862494

2487-
// We don't check whether the specification DIE for this function
2488-
// corresponds to the declaration DIE because the declaration might be in
2489-
// a type-unit but the definition in the compile-unit (and it's
2490-
// specifcation would point to the declaration in the compile-unit). We
2491-
// rely on the mangled name within the module to be enough to find us the
2492-
// unique definition.
2495+
// TODO: this specification check doesn't work if declaration DIE was in a
2496+
// type-unit (we should only encode DIEs from .debug_info).
2497+
auto spec = entry.GetAttributeValueAsReferenceDIE(DW_AT_specification);
2498+
if (!spec)
2499+
return true;
2500+
2501+
if (spec != die)
2502+
return true;
2503+
2504+
// We're not picking a specific structor variant DIE, so we're done here.
2505+
if (!structor_variant) {
2506+
die = entry;
2507+
return false;
2508+
}
2509+
2510+
const char *mangled =
2511+
entry.GetMangledName(/*substitute_name_allowed=*/false);
2512+
if (!mangled)
2513+
return true;
2514+
2515+
llvm::ItaniumPartialDemangler D;
2516+
if (D.partialDemangle(mangled))
2517+
return true;
2518+
2519+
if (D.getCtorOrDtorVariant() != structor_variant)
2520+
return true;
2521+
24932522
die = entry;
2523+
24942524
return false;
24952525
});
24962526

24972527
if (!die.IsValid())
24982528
return llvm::createStringError(
2499-
llvm::formatv("failed to find definition DIE for '{0}'", lookup_name));
2529+
llvm::formatv("failed to find definition DIE for [lookup_name={0}] "
2530+
"[DIE ID={1:x}] [structor={2}]",
2531+
lookup_name, die_id, structor_variant.value_or(-1)));
25002532

25012533
if (!ResolveFunction(die, false, sc_list))
25022534
return llvm::createStringError("failed to resolve function DIE");

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -434,8 +434,10 @@ class SymbolFileDWARF : public SymbolFileCommon {
434434
DIEArray MergeBlockAbstractParameters(const DWARFDIE &block_die,
435435
DIEArray &&variable_dies);
436436

437-
llvm::Error FindAndResolveFunction(SymbolContextList &sc_list,
438-
llvm::StringRef lookup_name) override;
437+
llvm::Error
438+
FindAndResolveFunction(SymbolContextList &sc_list,
439+
llvm::StringRef lookup_name, lldb::user_id_t spec,
440+
std::optional<uint8_t> structor_variant) override;
439441

440442
// Given a die_offset, figure out the symbol context representing that die.
441443
bool ResolveFunction(const DWARFDIE &die, bool include_inlines,

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

Lines changed: 86 additions & 6 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"
@@ -9783,8 +9784,40 @@ void TypeSystemClang::LogCreation() const {
97839784
&getASTContext(), getDisplayName());
97849785
}
97859786

9787+
static llvm::Expected<
9788+
std::variant<std::monostate, clang::CXXCtorType, clang::CXXDtorType>>
9789+
ParseStructorType(llvm::StringRef label) {
9790+
if (label.empty())
9791+
return std::monostate{};
9792+
9793+
bool is_ctor = label.consume_front("C");
9794+
if (!is_ctor && label.starts_with("D"))
9795+
return llvm::createStringError("invalid structor type prefix in %s",
9796+
label.data());
9797+
9798+
uint8_t type;
9799+
if (label.consumeInteger(0, type))
9800+
return llvm::createStringError("failed to parse structor type value %s",
9801+
label.data());
9802+
9803+
if (is_ctor) {
9804+
if (type > clang::CXXCtorType::Ctor_DefaultClosure)
9805+
return llvm::createStringError("C++ constructor type %d out of range",
9806+
type);
9807+
9808+
return static_cast<CXXCtorType>(type);
9809+
}
9810+
9811+
if (type > clang::CXXDtorType::Dtor_Deleting)
9812+
return llvm::createStringError("C++ destructor type %d out of range", type);
9813+
9814+
return static_cast<CXXDtorType>(type);
9815+
}
9816+
9817+
// clang-format off
97869818
// Expected format is:
9787-
// $__lldb_func:<mangled name>:<module id>:<definition/declaration DIE id>
9819+
// $__lldb_func:<mangled name>:<module id>:<definition/declaration DIE id>:[<structor variant>]
9820+
// clang-format on
97889821
llvm::Expected<llvm::SmallVector<llvm::StringRef, 3>>
97899822
TypeSystemClang::splitFunctionCallLabel(llvm::StringRef label) const {
97909823
if (!consumeFunctionCallLabelPrefix(label))
@@ -9794,17 +9827,17 @@ TypeSystemClang::splitFunctionCallLabel(llvm::StringRef label) const {
97949827
return llvm::createStringError(
97959828
"incorrect format: expected ':' as the first character.");
97969829

9797-
llvm::SmallVector<llvm::StringRef, 3> components;
9830+
llvm::SmallVector<llvm::StringRef, 4> components;
97989831
label.split(components, ":");
97999832

9800-
if (components.size() != 3)
9833+
if (components.size() != 4)
98019834
return llvm::createStringError(
98029835
"incorrect format: too many label subcomponents.");
98039836

98049837
return components;
98059838
}
98069839

9807-
llvm::Expected<FunctionCallLabel>
9840+
llvm::Expected<std::unique_ptr<FunctionCallLabel>>
98089841
TypeSystemClang::makeFunctionCallLabel(llvm::StringRef label) const {
98099842
auto components_or_err = splitFunctionCallLabel(label);
98109843
if (!components_or_err)
@@ -9816,6 +9849,7 @@ TypeSystemClang::makeFunctionCallLabel(llvm::StringRef label) const {
98169849

98179850
llvm::StringRef module_label = components[1];
98189851
llvm::StringRef die_label = components[2];
9852+
llvm::StringRef structor_variant = components[3];
98199853

98209854
lldb::user_id_t module_id = 0;
98219855
if (module_label.consumeInteger(0, module_id))
@@ -9827,6 +9861,52 @@ TypeSystemClang::makeFunctionCallLabel(llvm::StringRef label) const {
98279861
return llvm::createStringError(
98289862
llvm::formatv("failed to parse DIE ID from '{0}'.", components[2]));
98299863

9830-
return FunctionCallLabel{/*.m_lookup_name =*/components[0],
9831-
/*.m_module_id =*/module_id, /*.m_die_id =*/die_id};
9864+
auto structor_type_or_err = ParseStructorType(structor_variant);
9865+
if (!structor_type_or_err)
9866+
return llvm::joinErrors(
9867+
llvm::createStringError(llvm::formatv(
9868+
"failed to parse structor kind from '{0}'.", components[2])),
9869+
structor_type_or_err.takeError());
9870+
9871+
auto ret = std::make_unique<ClangFunctionCallLabel>();
9872+
ret->m_lookup_name = components[0];
9873+
ret->m_module_id = module_id;
9874+
ret->m_die_id = die_id;
9875+
ret->m_structor_type = std::move(*structor_type_or_err);
9876+
9877+
return ret;
9878+
}
9879+
9880+
std::optional<uint8_t>
9881+
TypeSystemClang::ClangFunctionCallLabel::getItaniumStructorVariant() const {
9882+
if (m_structor_type.index() == 0)
9883+
return std::nullopt;
9884+
9885+
if (auto *ctor = std::get_if<clang::CXXCtorType>(&m_structor_type)) {
9886+
switch (*ctor) {
9887+
case clang::CXXCtorType::Ctor_Complete:
9888+
return 1;
9889+
case clang::CXXCtorType::Ctor_Base:
9890+
return 2;
9891+
case clang::CXXCtorType::Ctor_Comdat:
9892+
case clang::CXXCtorType::Ctor_CopyingClosure:
9893+
case clang::CXXCtorType::Ctor_DefaultClosure:
9894+
// No Itanium equivalent
9895+
return std::nullopt;
9896+
}
9897+
} else if (auto *dtor = std::get_if<clang::CXXDtorType>(&m_structor_type)) {
9898+
switch (*dtor) {
9899+
case clang::CXXDtorType::Dtor_Deleting:
9900+
return 0;
9901+
case clang::CXXDtorType::Dtor_Complete:
9902+
return 1;
9903+
case clang::CXXDtorType::Dtor_Base:
9904+
return 2;
9905+
case clang::CXXDtorType::Dtor_Comdat:
9906+
// No Itanium equivalent
9907+
return std::nullopt;
9908+
}
9909+
}
9910+
9911+
return std::nullopt;
98329912
}

0 commit comments

Comments
 (0)