Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit a30a11b

Browse files
authored
Merge pull request #11350 from swiftlang/lldb/abi-tag-structors-to-21.x
🍒[lldb][Expression] Cherry-pick ABI-tagged structor lookup infrastructure to 21.x
2 parents e7fa992 + b6c5dc6 commit a30a11b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+1380
-240
lines changed

clang/include/clang/Basic/ABI.h

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,16 @@ enum CXXCtorType {
2727
Ctor_Comdat, ///< The COMDAT used for ctors
2828
Ctor_CopyingClosure, ///< Copying closure variant of a ctor
2929
Ctor_DefaultClosure, ///< Default closure variant of a ctor
30+
Ctor_Unified, ///< GCC-style unified dtor
3031
};
3132

3233
/// C++ destructor types.
3334
enum CXXDtorType {
34-
Dtor_Deleting, ///< Deleting dtor
35-
Dtor_Complete, ///< Complete object dtor
36-
Dtor_Base, ///< Base object dtor
37-
Dtor_Comdat ///< The COMDAT used for dtors
35+
Dtor_Deleting, ///< Deleting dtor
36+
Dtor_Complete, ///< Complete object dtor
37+
Dtor_Base, ///< Base object dtor
38+
Dtor_Comdat, ///< The COMDAT used for dtors
39+
Dtor_Unified, ///< GCC-style unified dtor
3840
};
3941

4042
} // end namespace clang

clang/include/clang/Basic/DebugOptions.def

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,12 @@ DEBUGOPT(DebugNameTable, 2, 0, Affecting)
128128
/// Whether to use DWARF base address specifiers in .debug_ranges.
129129
DEBUGOPT(DebugRangesBaseAddress, 1, 0, Affecting)
130130

131+
/// Whether to add linkage names to constructor/destructor declarations.
132+
/// This is an escape hatch for cases where attaching the additional linkage
133+
/// names would increase debug-info size (particularly the .debug_str section)
134+
/// too much.
135+
DEBUGOPT(DebugStructorDeclLinkageNames, 1, 0, Benign)
136+
131137
/// Whether to embed source in DWARF debug line section.
132138
DEBUGOPT(EmbedSource, 1, 0, Affecting)
133139

clang/include/clang/Driver/Options.td

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4920,6 +4920,18 @@ def gembed_source : Flag<["-"], "gembed-source">, Group<g_flags_Group>,
49204920
def gno_embed_source : Flag<["-"], "gno-embed-source">, Group<g_flags_Group>,
49214921
Flags<[NoXarchOption]>,
49224922
HelpText<"Restore the default behavior of not embedding source text in DWARF debug sections">;
4923+
defm structor_decl_linkage_names
4924+
: BoolGOption<"structor-decl-linkage-names",
4925+
CodeGenOpts<"DebugStructorDeclLinkageNames">, DefaultTrue,
4926+
NegFlag<SetFalse>,
4927+
PosFlag<SetTrue, [], [],
4928+
"Attach linkage names to C++ constructor/destructor "
4929+
"declarations in DWARF."
4930+
"Implies -g.">,
4931+
BothFlags<[], [ClangOption, CLOption, CC1Option]>>,
4932+
DocBrief<[{On some ABIs (e.g., Itanium), constructors and destructors may have multiple variants. Historically, when generating DWARF, Clang did not attach ``DW_AT_linkage_name``s to structor DIEs because there were multiple possible manglings (depending on the structor variant) that could be used. With ``-gstructor-decl-linkage-names``, for ABIs with structor variants, we attach a "unified" mangled name to structor declarations DIEs which debuggers can use to look up all the definitions for a structor declaration. E.g., a "unified" mangled name ``_ZN3FooC4Ev`` may have multiple definitions associated with it such as ``_ZN3FooC1Ev`` and ``_ZN3FooC2Ev``.
4933+
4934+
Enabling this flag results in a better interactive debugging experience (both GDB and LLDB have support for understanding these "unified" linkage names). However, it comes with a significant increase in debug-info size (particularly the `.debug_str` section). As an escape hatch, users can disable this feature using ``-gno-structor-decl-linkage-names``.}]>;
49234935
defm key_instructions : BoolGOption<"key-instructions",
49244936
CodeGenOpts<"DebugKeyInstructions">, DefaultFalse,
49254937
NegFlag<SetFalse>, PosFlag<SetTrue, [], [],

clang/lib/AST/ItaniumMangle.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6068,6 +6068,8 @@ void CXXNameMangler::mangleCXXCtorType(CXXCtorType T,
60686068
// ::= CI2 <type> # base inheriting constructor
60696069
//
60706070
// In addition, C5 is a comdat name with C1 and C2 in it.
6071+
// C4 represents a ctor declaration and is used by debuggers to look up
6072+
// the various ctor variants.
60716073
Out << 'C';
60726074
if (InheritedFrom)
60736075
Out << 'I';
@@ -6078,6 +6080,9 @@ void CXXNameMangler::mangleCXXCtorType(CXXCtorType T,
60786080
case Ctor_Base:
60796081
Out << '2';
60806082
break;
6083+
case Ctor_Unified:
6084+
Out << '4';
6085+
break;
60816086
case Ctor_Comdat:
60826087
Out << '5';
60836088
break;
@@ -6095,6 +6100,8 @@ void CXXNameMangler::mangleCXXDtorType(CXXDtorType T) {
60956100
// ::= D2 # base object destructor
60966101
//
60976102
// In addition, D5 is a comdat name with D1, D2 and, if virtual, D0 in it.
6103+
// D4 represents a dtor declaration and is used by debuggers to look up
6104+
// the various dtor variants.
60986105
switch (T) {
60996106
case Dtor_Deleting:
61006107
Out << "D0";
@@ -6105,6 +6112,9 @@ void CXXNameMangler::mangleCXXDtorType(CXXDtorType T) {
61056112
case Dtor_Base:
61066113
Out << "D2";
61076114
break;
6115+
case Dtor_Unified:
6116+
Out << "D4";
6117+
break;
61086118
case Dtor_Comdat:
61096119
Out << "D5";
61106120
break;

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/lib/AST/MicrosoftMangle.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1497,6 +1497,8 @@ void MicrosoftCXXNameMangler::mangleCXXDtorType(CXXDtorType T) {
14971497
// it.
14981498
case Dtor_Comdat:
14991499
llvm_unreachable("not expecting a COMDAT");
1500+
case Dtor_Unified:
1501+
llvm_unreachable("not expecting a unified dtor type");
15001502
}
15011503
llvm_unreachable("Unsupported dtor type?");
15021504
}

clang/lib/CodeGen/CGClass.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1493,6 +1493,8 @@ void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) {
14931493
// we'd introduce *two* handler blocks. In the Microsoft ABI, we
14941494
// always delegate because we might not have a definition in this TU.
14951495
switch (DtorType) {
1496+
case Dtor_Unified:
1497+
llvm_unreachable("not expecting a unified dtor");
14961498
case Dtor_Comdat: llvm_unreachable("not expecting a COMDAT");
14971499
case Dtor_Deleting: llvm_unreachable("already handled deleting case");
14981500

clang/lib/CodeGen/CGDebugInfo.cpp

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2258,24 +2258,47 @@ static bool isFunctionLocalClass(const CXXRecordDecl *RD) {
22582258
return false;
22592259
}
22602260

2261+
llvm::StringRef
2262+
CGDebugInfo::GetMethodLinkageName(const CXXMethodDecl *Method) const {
2263+
assert(Method);
2264+
2265+
const bool IsCtorOrDtor =
2266+
isa<CXXConstructorDecl>(Method) || isa<CXXDestructorDecl>(Method);
2267+
2268+
if (IsCtorOrDtor && !CGM.getCodeGenOpts().DebugStructorDeclLinkageNames)
2269+
return {};
2270+
2271+
// In some ABIs (particularly Itanium) a single ctor/dtor
2272+
// corresponds to multiple functions. Attach a "unified"
2273+
// linkage name for those (which is the convention GCC uses).
2274+
// Otherwise, attach no linkage name.
2275+
if (IsCtorOrDtor && !CGM.getTarget().getCXXABI().hasConstructorVariants())
2276+
return {};
2277+
2278+
if (const auto *Ctor = llvm::dyn_cast<CXXConstructorDecl>(Method))
2279+
return CGM.getMangledName(GlobalDecl(Ctor, CXXCtorType::Ctor_Unified));
2280+
2281+
if (const auto *Dtor = llvm::dyn_cast<CXXDestructorDecl>(Method))
2282+
return CGM.getMangledName(GlobalDecl(Dtor, CXXDtorType::Dtor_Unified));
2283+
2284+
return CGM.getMangledName(Method);
2285+
}
2286+
22612287
llvm::DISubprogram *CGDebugInfo::CreateCXXMemberFunction(
22622288
const CXXMethodDecl *Method, llvm::DIFile *Unit, llvm::DIType *RecordTy) {
2263-
bool IsCtorOrDtor =
2264-
isa<CXXConstructorDecl>(Method) || isa<CXXDestructorDecl>(Method);
2289+
assert(Method);
22652290

22662291
StringRef MethodName = getFunctionName(Method);
22672292
llvm::DISubroutineType *MethodTy = getOrCreateMethodType(Method, Unit);
22682293

2269-
// Since a single ctor/dtor corresponds to multiple functions, it doesn't
2270-
// make sense to give a single ctor/dtor a linkage name.
22712294
StringRef MethodLinkageName;
22722295
// FIXME: 'isFunctionLocalClass' seems like an arbitrary/unintentional
22732296
// property to use here. It may've been intended to model "is non-external
22742297
// type" but misses cases of non-function-local but non-external classes such
22752298
// as those in anonymous namespaces as well as the reverse - external types
22762299
// that are function local, such as those in (non-local) inline functions.
2277-
if (!IsCtorOrDtor && !isFunctionLocalClass(Method->getParent()))
2278-
MethodLinkageName = CGM.getMangledName(Method);
2300+
if (!isFunctionLocalClass(Method->getParent()))
2301+
MethodLinkageName = GetMethodLinkageName(Method);
22792302

22802303
// Get the location for the method.
22812304
llvm::DIFile *MethodDefUnit = nullptr;

clang/lib/CodeGen/CGDebugInfo.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -903,6 +903,10 @@ class CGDebugInfo {
903903
std::memcpy(Data + A.size(), B.data(), B.size());
904904
return StringRef(Data, A.size() + B.size());
905905
}
906+
907+
/// If one exists, returns the linkage name of the specified \
908+
/// (non-null) \c Method. Returns empty string otherwise.
909+
llvm::StringRef GetMethodLinkageName(const CXXMethodDecl *Method) const;
906910
};
907911

908912
/// A scoped helper to set the current debug location to the specified

clang/lib/CodeGen/ItaniumCXXABI.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,8 @@ class ItaniumCXXABI : public CodeGen::CGCXXABI {
9292

9393
case Dtor_Comdat:
9494
llvm_unreachable("emitting dtor comdat as function?");
95+
case Dtor_Unified:
96+
llvm_unreachable("emitting unified dtor as function?");
9597
}
9698
llvm_unreachable("bad dtor kind");
9799
}
@@ -109,6 +111,9 @@ class ItaniumCXXABI : public CodeGen::CGCXXABI {
109111

110112
case Ctor_Comdat:
111113
llvm_unreachable("emitting ctor comdat as function?");
114+
115+
case Ctor_Unified:
116+
llvm_unreachable("emitting unified ctor as function?");
112117
}
113118
llvm_unreachable("bad dtor kind");
114119
}

0 commit comments

Comments
 (0)