Skip to content

Commit 499aa52

Browse files
committed
Structors init
1 parent 5146917 commit 499aa52

File tree

16 files changed

+223
-77
lines changed

16 files changed

+223
-77
lines changed

clang/include/clang/Basic/Attr.td

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1059,22 +1059,13 @@ def AVRSignal : InheritableAttr, TargetSpecificAttr<TargetAVR> {
10591059
def AsmLabel : InheritableAttr {
10601060
let Spellings = [CustomKeyword<"asm">, CustomKeyword<"__asm__">];
10611061
let Args = [
1062-
// Label specifies the mangled name for the decl.
1063-
StringArgument<"Label">,
1064-
1065-
// IsLiteralLabel specifies whether the label is literal (i.e. suppresses
1066-
// the global C symbol prefix) or not. If not, the mangle-suppression prefix
1067-
// ('\01') is omitted from the decl name at the LLVM IR level.
1068-
//
1069-
// Non-literal labels are used by some external AST sources like LLDB.
1070-
BoolArgument<"IsLiteralLabel", /*optional=*/0, /*fake=*/1>
1071-
];
1062+
// Label specifies the mangled name for the decl.
1063+
StringArgument<"Label">, ];
10721064
let SemaHandler = 0;
10731065
let Documentation = [AsmLabelDocs];
1074-
let AdditionalMembers =
1075-
[{
1066+
let AdditionalMembers = [{
10761067
bool isEquivalent(AsmLabelAttr *Other) const {
1077-
return getLabel() == Other->getLabel() && getIsLiteralLabel() == Other->getIsLiteralLabel();
1068+
return getLabel() == Other->getLabel();
10781069
}
10791070
}];
10801071
}

clang/lib/AST/Mangle.cpp

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,20 @@ 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+
static void emitLLDBAsmLabel(llvm::StringRef label, GlobalDecl GD,
158+
llvm::raw_ostream &Out) {
159+
Out << g_lldb_func_call_label_prefix;
160+
161+
if (llvm::isa<clang::CXXConstructorDecl>(GD.getDecl()))
162+
Out << ":C" << GD.getCtorType();
163+
else if (llvm::isa<clang::CXXDestructorDecl>(GD.getDecl()))
164+
Out << ":D" << GD.getDtorType();
165+
166+
Out << label.substr(g_lldb_func_call_label_prefix.size());
167+
}
168+
155169
void MangleContext::mangleName(GlobalDecl GD, raw_ostream &Out) {
156170
const ASTContext &ASTContext = getASTContext();
157171
const NamedDecl *D = cast<NamedDecl>(GD.getDecl());
@@ -161,10 +175,10 @@ void MangleContext::mangleName(GlobalDecl GD, raw_ostream &Out) {
161175
if (const AsmLabelAttr *ALA = D->getAttr<AsmLabelAttr>()) {
162176
// If we have an asm name, then we use it as the mangling.
163177

164-
// If the label isn't literal, or if this is an alias for an LLVM intrinsic,
165-
// do not add a "\01" prefix.
166-
if (!ALA->getIsLiteralLabel() || ALA->getLabel().starts_with("llvm.")) {
178+
// If is an alias for an LLVM intrinsic, do not add a "\01" prefix.
179+
if (ALA->getLabel().starts_with("llvm.")) {
167180
Out << ALA->getLabel();
181+
168182
return;
169183
}
170184

@@ -185,7 +199,11 @@ void MangleContext::mangleName(GlobalDecl GD, raw_ostream &Out) {
185199
if (!UserLabelPrefix.empty())
186200
Out << '\01'; // LLVM IR Marker for __asm("foo")
187201

188-
Out << ALA->getLabel();
202+
if (ALA->getLabel().starts_with(g_lldb_func_call_label_prefix))
203+
emitLLDBAsmLabel(ALA->getLabel(), GD, Out);
204+
else
205+
Out << ALA->getLabel();
206+
189207
return;
190208
}
191209

clang/lib/Sema/SemaDecl.cpp

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8113,9 +8113,7 @@ NamedDecl *Sema::ActOnVariableDeclarator(
81138113
}
81148114
}
81158115

8116-
NewVD->addAttr(AsmLabelAttr::Create(Context, Label,
8117-
/*IsLiteralLabel=*/true,
8118-
SE->getStrTokenLoc(0)));
8116+
NewVD->addAttr(AsmLabelAttr::Create(Context, Label, SE->getStrTokenLoc(0)));
81198117
} else if (!ExtnameUndeclaredIdentifiers.empty()) {
81208118
llvm::DenseMap<IdentifierInfo*,AsmLabelAttr*>::iterator I =
81218119
ExtnameUndeclaredIdentifiers.find(NewVD->getIdentifier());
@@ -10345,9 +10343,8 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
1034510343
if (Expr *E = D.getAsmLabel()) {
1034610344
// The parser guarantees this is a string.
1034710345
StringLiteral *SE = cast<StringLiteral>(E);
10348-
NewFD->addAttr(AsmLabelAttr::Create(Context, SE->getString(),
10349-
/*IsLiteralLabel=*/true,
10350-
SE->getStrTokenLoc(0)));
10346+
NewFD->addAttr(
10347+
AsmLabelAttr::Create(Context, SE->getString(), SE->getStrTokenLoc(0)));
1035110348
} else if (!ExtnameUndeclaredIdentifiers.empty()) {
1035210349
llvm::DenseMap<IdentifierInfo*,AsmLabelAttr*>::iterator I =
1035310350
ExtnameUndeclaredIdentifiers.find(NewFD->getIdentifier());
@@ -20598,8 +20595,8 @@ void Sema::ActOnPragmaRedefineExtname(IdentifierInfo* Name,
2059820595
LookupOrdinaryName);
2059920596
AttributeCommonInfo Info(AliasName, SourceRange(AliasNameLoc),
2060020597
AttributeCommonInfo::Form::Pragma());
20601-
AsmLabelAttr *Attr = AsmLabelAttr::CreateImplicit(
20602-
Context, AliasName->getName(), /*IsLiteralLabel=*/true, Info);
20598+
AsmLabelAttr *Attr =
20599+
AsmLabelAttr::CreateImplicit(Context, AliasName->getName(), Info);
2060320600

2060420601
// If a declaration that:
2060520602
// 1) declares a function or a variable

clang/unittests/AST/DeclTest.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,8 +90,8 @@ TEST(Decl, AsmLabelAttr) {
9090
NamedDecl *DeclG = *(++DeclS->method_begin());
9191

9292
// Attach asm labels to the decls: one literal, and one not.
93-
DeclF->addAttr(AsmLabelAttr::Create(Ctx, "foo", /*LiteralLabel=*/true));
94-
DeclG->addAttr(AsmLabelAttr::Create(Ctx, "goo", /*LiteralLabel=*/false));
93+
DeclF->addAttr(AsmLabelAttr::Create(Ctx, "foo", /*IsLLDBFuncLabel=*/false));
94+
DeclG->addAttr(AsmLabelAttr::Create(Ctx, "goo", /*IsLLDBFuncLabel=*/true));
9595

9696
// Mangle the decl names.
9797
std::string MangleF, MangleG;

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: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,11 +103,15 @@ class Expression {
103103
///
104104
/// The format being:
105105
///
106-
/// <prefix>:<module uid>:<symbol uid>:<name>
106+
/// <prefix>:<discriminator>:<module uid>:<symbol uid>:<name>
107107
///
108108
/// The label string needs to stay valid for the entire lifetime
109109
/// of this object.
110110
struct FunctionCallLabel {
111+
/// Arbitrary string which language plugins can interpret for their
112+
/// own needs.
113+
llvm::StringRef discriminator;
114+
111115
/// Unique identifier of the lldb_private::Module
112116
/// which contains the symbol identified by \c symbol_id.
113117
lldb::user_id_t module_id;
@@ -133,7 +137,7 @@ struct FunctionCallLabel {
133137
///
134138
/// The representation roundtrips through \c fromString:
135139
/// \code{.cpp}
136-
/// llvm::StringRef encoded = "$__lldb_func:0x0:0x0:_Z3foov";
140+
/// llvm::StringRef encoded = "$__lldb_func:blah:0x0:0x0:_Z3foov";
137141
/// FunctionCallLabel label = *fromString(label);
138142
///
139143
/// assert (label.toString() == encoded);

lldb/source/Expression/Expression.cpp

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -34,19 +34,21 @@ 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)
4444
return llvm::createStringError(llvm::formatv(
4545
"expected function call label prefix '{0}' but found '{1}' instead.",
4646
FunctionCallLabelPrefix, components[0]));
4747

48-
llvm::StringRef module_label = components[1];
49-
llvm::StringRef die_label = components[2];
48+
llvm::StringRef discriminator = components[1];
49+
llvm::StringRef module_label = components[2];
50+
llvm::StringRef die_label = components[3];
51+
llvm::StringRef lookup_name = components[4];
5052

5153
lldb::user_id_t module_id = 0;
5254
if (!llvm::to_integer(module_label, module_id))
@@ -58,20 +60,23 @@ lldb_private::FunctionCallLabel::fromString(llvm::StringRef label) {
5860
return llvm::createStringError(
5961
llvm::formatv("failed to parse symbol ID from '{0}'.", die_label));
6062

61-
return FunctionCallLabel{/*.module_id=*/module_id,
63+
return FunctionCallLabel{/*.discriminator=*/discriminator,
64+
/*.module_id=*/module_id,
6265
/*.symbol_id=*/die_id,
63-
/*.lookup_name=*/components[3]};
66+
/*.lookup_name=*/lookup_name};
6467
}
6568

6669
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)
70+
return llvm::formatv("{0}:{1}:{2:x}:{3:x}:{4}", FunctionCallLabelPrefix,
71+
discriminator, module_id, symbol_id, lookup_name)
6972
.str();
7073
}
7174

7275
void llvm::format_provider<FunctionCallLabel>::format(
7376
const FunctionCallLabel &label, raw_ostream &OS, StringRef Style) {
74-
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);
77+
OS << llvm::formatv("FunctionCallLabel{ discriminator: {0}, module_id: "
78+
"{1:x}, symbol_id: {2:x}, "
79+
"lookup_name: {3} }",
80+
label.discriminator, label.module_id, label.symbol_id,
81+
label.lookup_name);
7782
}

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,7 +313,9 @@ static std::string MakeLLDBFuncAsmLabel(const DWARFDIE &die) {
285313
if (die_id == LLDB_INVALID_UID)
286314
return {};
287315

288-
return FunctionCallLabel{/*module_id=*/module_id,
316+
// Note, discriminator is added by Clang during mangling.
317+
return FunctionCallLabel{/*discriminator=*/{},
318+
/*module_id=*/module_id,
289319
/*symbol_id=*/die_id,
290320
/*.lookup_name=*/name}
291321
.toString();

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"
@@ -78,6 +80,7 @@
7880

7981
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
8082
#include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"
83+
#include "llvm/Demangle/Demangle.h"
8184
#include "llvm/Support/FileSystem.h"
8285
#include "llvm/Support/FormatVariadic.h"
8386

@@ -2476,6 +2479,56 @@ bool SymbolFileDWARF::ResolveFunction(const DWARFDIE &orig_die,
24762479
return false;
24772480
}
24782481

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

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

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

0 commit comments

Comments
 (0)