Skip to content

Commit 63ca211

Browse files
committed
Init
1 parent 739fe98 commit 63ca211

File tree

11 files changed

+275
-13
lines changed

11 files changed

+275
-13
lines changed

clang/include/clang/Basic/Attr.td

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -812,6 +812,13 @@ def AbiTag : Attr {
812812
let Documentation = [AbiTagsDocs];
813813
}
814814

815+
def StructorName : Attr {
816+
let Spellings = [Clang<"structor_name">];
817+
let Args = [StringArgument<"Name">];
818+
let Subjects = SubjectList<[Function], ErrorDiag>;
819+
let Documentation = [StructorNameDocs];
820+
}
821+
815822
def AddressSpace : TypeAttr {
816823
let Spellings = [Clang<"address_space">];
817824
let Args = [IntArgument<"AddressSpace">];

clang/include/clang/Basic/AttrDocs.td

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4067,6 +4067,11 @@ manipulating bits of the enumerator when issuing warnings.
40674067
}];
40684068
}
40694069

4070+
def StructorNameDocs : Documentation {
4071+
let Category = DocCatDecl;
4072+
let Content = [{ TODO }];
4073+
}
4074+
40704075
def AsmLabelDocs : Documentation {
40714076
let Category = DocCatDecl;
40724077
let Content = [{

clang/lib/AST/Mangle.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ bool MangleContext::shouldMangleDeclName(const NamedDecl *D) {
125125

126126
// Any decl can be declared with __asm("foo") on it, and this takes precedence
127127
// over all other naming in the .o file.
128-
if (D->hasAttr<AsmLabelAttr>())
128+
if (D->hasAttr<AsmLabelAttr>() || D->hasAttr<StructorNameAttr>())
129129
return true;
130130

131131
// Declarations that don't have identifier names always need to be mangled.
@@ -139,6 +139,20 @@ void MangleContext::mangleName(GlobalDecl GD, raw_ostream &Out) {
139139
const ASTContext &ASTContext = getASTContext();
140140
const NamedDecl *D = cast<NamedDecl>(GD.getDecl());
141141

142+
if (const auto *SNA = D->getAttr<StructorNameAttr>()) {
143+
Out << SNA->getName() << ':';
144+
145+
if (isa<CXXConstructorDecl>(D)) {
146+
Out << 'C';
147+
Out << GD.getCtorType();
148+
} else {
149+
Out << 'D';
150+
Out << GD.getDtorType();
151+
}
152+
153+
return;
154+
}
155+
142156
// Any decl can be declared with __asm("foo") on it, and this takes precedence
143157
// over all other naming in the .o file.
144158
if (const AsmLabelAttr *ALA = D->getAttr<AsmLabelAttr>()) {

clang/lib/Sema/SemaDeclAttr.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1730,6 +1730,14 @@ static void handleIFuncAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
17301730
D->addAttr(::new (S.Context) IFuncAttr(S.Context, AL, Str));
17311731
}
17321732

1733+
static void handleStructorNameAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
1734+
StringRef Str;
1735+
if (!S.checkStringLiteralArgumentAttr(AL, 0, Str))
1736+
return;
1737+
1738+
D->addAttr(::new (S.Context) StructorNameAttr(S.Context, AL, Str));
1739+
}
1740+
17331741
static void handleAliasAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
17341742
StringRef Str;
17351743
if (!S.checkStringLiteralArgumentAttr(AL, 0, Str))
@@ -7532,6 +7540,9 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL,
75327540
S.HLSL().handleParamModifierAttr(D, AL);
75337541
break;
75347542

7543+
case ParsedAttr::AT_StructorName:
7544+
handleStructorNameAttr(S, D, AL);
7545+
break;
75357546
case ParsedAttr::AT_AbiTag:
75367547
handleAbiTagAttr(S, D, AL);
75377548
break;

libcxxabi/src/demangle/ItaniumDemangle.h

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

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

1753+
int getVariant() const { return Variant; }
1754+
17531755
void printLeft(OutputBuffer &OB) const override {
17541756
if (IsDtor)
17551757
OB += "~";

lldb/source/Expression/IRExecutionUnit.cpp

Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,23 @@
66
//
77
//===----------------------------------------------------------------------===//
88

9+
#include "clang/Basic/ABI.h"
10+
#include "llvm/Demangle/Demangle.h"
911
#include "llvm/ExecutionEngine/ExecutionEngine.h"
1012
#include "llvm/ExecutionEngine/ObjectCache.h"
1113
#include "llvm/IR/Constants.h"
1214
#include "llvm/IR/DiagnosticHandler.h"
1315
#include "llvm/IR/DiagnosticInfo.h"
1416
#include "llvm/IR/LLVMContext.h"
1517
#include "llvm/IR/Module.h"
18+
#include "llvm/Support/ErrorHandling.h"
1619
#include "llvm/Support/SourceMgr.h"
1720
#include "llvm/Support/raw_ostream.h"
1821

22+
#include "Plugins/SymbolFile/DWARF/DWARFBaseDIE.h"
23+
#include "Plugins/SymbolFile/DWARF/DWARFDIE.h"
24+
#include "Plugins/SymbolFile/DWARF/SymbolFileDWARF.h"
25+
1926
#include "lldb/Core/Debugger.h"
2027
#include "lldb/Core/Disassembler.h"
2128
#include "lldb/Core/Module.h"
@@ -36,8 +43,10 @@
3643
#include "lldb/Utility/LLDBAssert.h"
3744
#include "lldb/Utility/LLDBLog.h"
3845
#include "lldb/Utility/Log.h"
46+
#include "lldb/lldb-defines.h"
3947

4048
#include <optional>
49+
#include <variant>
4150

4251
using namespace lldb_private;
4352

@@ -769,6 +778,180 @@ class LoadAddressResolver {
769778
lldb::addr_t m_best_internal_load_address = LLDB_INVALID_ADDRESS;
770779
};
771780

781+
using namespace lldb_private::plugin::dwarf;
782+
783+
struct StructorVariant {
784+
std::variant<clang::CXXCtorType, clang::CXXDtorType> m_variant;
785+
};
786+
787+
static llvm::Expected<StructorVariant>
788+
MakeStructorVariant(llvm::StringRef variant_num) {
789+
if (variant_num.consume_front("D")) {
790+
std::underlying_type_t<clang::CXXDtorType> dtor_type;
791+
if (variant_num.consumeInteger(10, dtor_type))
792+
return llvm::createStringError("Invalid ctor variant code.");
793+
794+
return StructorVariant{.m_variant =
795+
static_cast<clang::CXXDtorType>(dtor_type)};
796+
}
797+
798+
if (variant_num.consume_front("C")) {
799+
std::underlying_type_t<clang::CXXCtorType> ctor_type;
800+
if (variant_num.consumeInteger(10, ctor_type))
801+
return llvm::createStringError("Invalid dtor variant code.");
802+
803+
return StructorVariant{.m_variant =
804+
static_cast<clang::CXXCtorType>(ctor_type)};
805+
}
806+
807+
return llvm::createStringError("Incorrect structor variant prefix.");
808+
}
809+
810+
static int GetItaniumVariantCode(StructorVariant structor) {
811+
if (auto const *ctor = std::get_if<clang::CXXCtorType>(&structor.m_variant)) {
812+
switch (*ctor) {
813+
case clang::CXXCtorType::Ctor_Complete:
814+
return 1;
815+
case clang::CXXCtorType::Ctor_Base:
816+
return 2;
817+
default:
818+
llvm_unreachable("Unimplemented");
819+
}
820+
} else {
821+
switch (std::get<clang::CXXDtorType>(structor.m_variant)) {
822+
case clang::CXXDtorType::Dtor_Complete:
823+
return 1;
824+
case clang::CXXDtorType::Dtor_Base:
825+
return 2;
826+
default:
827+
llvm_unreachable("Unimplemented");
828+
}
829+
}
830+
}
831+
832+
// TODO:
833+
// 1. MS-ABI
834+
// 2. GCC-style dtor/ctor declarations
835+
// 3. Inheriting ctors
836+
// 4. Regular functions
837+
static std::string FindStructorLinkageName(DWARFDIE die,
838+
StructorVariant structor_variant) {
839+
auto *dwarf = die.GetDWARF();
840+
assert(dwarf);
841+
842+
// Note, GCC only puts DW_AT_linkage_name (not DW_AT_name) on constructor
843+
// decls Will those cases still work?
844+
ConstString func_name(die.GetName());
845+
assert(func_name);
846+
847+
SymbolContextList sc_list;
848+
Module::LookupInfo lookup_info(
849+
func_name,
850+
lldb::FunctionNameType::eFunctionNameTypeMethod |
851+
lldb::FunctionNameType::eFunctionNameTypeFull,
852+
lldb::LanguageType::eLanguageTypeUnknown);
853+
dwarf->FindFunctions(lookup_info, {}, true, sc_list);
854+
855+
llvm::DenseMap<int, std::string> variants;
856+
857+
for (auto const &sc : sc_list.SymbolContexts()) {
858+
if (!sc.function)
859+
continue;
860+
861+
auto func_die = dwarf->GetDIE(sc.function->GetID());
862+
if (!func_die.IsValid())
863+
continue;
864+
865+
auto spec_die = func_die.GetAttributeValueAsReferenceDIE(
866+
llvm::dwarf::DW_AT_specification);
867+
if (!spec_die.IsValid() || spec_die != die)
868+
continue;
869+
870+
llvm::ItaniumPartialDemangler D;
871+
if (D.partialDemangle(func_die.GetMangledName()))
872+
continue;
873+
874+
const auto maybe_structor_kind = D.getCtorDtorVariant();
875+
// TODO: this need not be true
876+
assert(maybe_structor_kind);
877+
878+
variants.insert({*maybe_structor_kind, func_die.GetMangledName()});
879+
}
880+
881+
auto itanium_code = GetItaniumVariantCode(structor_variant);
882+
auto it = variants.find(itanium_code);
883+
if (it != variants.end())
884+
return it->second;
885+
886+
// If only C2 was emitted but we tried calling C1,
887+
// we can probably (?) safely call C2.
888+
if (itanium_code == 1 && variants.size() == 1)
889+
if (auto retry = variants.find(2); retry != variants.end())
890+
return retry->second;
891+
892+
return {};
893+
}
894+
895+
static lldb::addr_t FindSpecialLinkageName(
896+
LoadAddressResolver &resolver,ConstString name, llvm::StringRef symbol) {
897+
uintptr_t module_ptr;
898+
if (symbol.consumeInteger(0, module_ptr))
899+
return LLDB_INVALID_ADDRESS;
900+
901+
if (module_ptr == 0) {
902+
// TODO: log this case. We should ever be putting a null module pointer
903+
// here
904+
return LLDB_INVALID_ADDRESS;
905+
}
906+
907+
auto *mod = (lldb_private::Module *)module_ptr;
908+
assert(mod);
909+
auto *sym = mod->GetSymbolFile();
910+
assert(sym);
911+
912+
if (!symbol.consume_front(":"))
913+
return LLDB_INVALID_ADDRESS;
914+
915+
lldb::user_id_t die_id;
916+
if (symbol.consumeInteger(10, die_id))
917+
return LLDB_INVALID_ADDRESS;
918+
919+
auto *dwarf = llvm::dyn_cast<plugin::dwarf::SymbolFileDWARF>(sym);
920+
if (!dwarf)
921+
return LLDB_INVALID_ADDRESS;
922+
923+
auto die = dwarf->GetDIE(die_id);
924+
if (!die.IsValid())
925+
return LLDB_INVALID_ADDRESS;
926+
927+
// TODO: account for MS-ABI (where there are no ctor variants in the
928+
// mangling)
929+
if (!symbol.consume_front(":"))
930+
return LLDB_INVALID_ADDRESS;
931+
932+
auto structor_variant_or_err = MakeStructorVariant(symbol);
933+
if (!structor_variant_or_err) {
934+
LLDB_LOG_ERROR(GetLog(LLDBLog::Expressions),
935+
structor_variant_or_err.takeError(),
936+
"Failed to parse structor variant encoding for {1}: {0}",
937+
name.GetStringRef());
938+
return LLDB_INVALID_ADDRESS;
939+
}
940+
941+
ConstString mangled(
942+
FindStructorLinkageName(die, *structor_variant_or_err));
943+
944+
Module::LookupInfo lookup_info(
945+
mangled, lldb::FunctionNameType::eFunctionNameTypeAny,
946+
lldb::LanguageType::eLanguageTypeC_plus_plus);
947+
SymbolContextList sc_list;
948+
dwarf->FindFunctions(lookup_info, {}, false, sc_list);
949+
if (auto load_addr = resolver.Resolve(sc_list))
950+
return *load_addr;
951+
952+
return LLDB_INVALID_ADDRESS;
953+
}
954+
772955
lldb::addr_t
773956
IRExecutionUnit::FindInSymbols(const std::vector<ConstString> &names,
774957
const lldb_private::SymbolContext &sc,
@@ -795,6 +978,9 @@ IRExecutionUnit::FindInSymbols(const std::vector<ConstString> &names,
795978
function_options.include_inlines = false;
796979

797980
for (const ConstString &name : names) {
981+
if (auto ref = name.GetStringRef(); ref.consume_front("$__lldb_func_"))
982+
return FindSpecialLinkageName(resolver, name, ref);
983+
798984
// The lookup order here is as follows:
799985
// 1) Functions in `sc.module_sp`
800986
// 2) Functions in the preferred modules list

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

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1112,6 +1112,16 @@ bool DWARFASTParserClang::ParseObjCMethod(
11121112
return true;
11131113
}
11141114

1115+
static bool IsStructorDIE(DWARFDIE const &die, DWARFDIE const &parent_die) {
1116+
llvm::StringRef name = die.GetName();
1117+
llvm::StringRef parent_name = parent_die.GetName();
1118+
1119+
name.consume_front("~");
1120+
parent_name = parent_name.substr(0, parent_name.find('<'));
1121+
1122+
return name == parent_name;
1123+
}
1124+
11151125
std::pair<bool, TypeSP> DWARFASTParserClang::ParseCXXMethod(
11161126
const DWARFDIE &die, CompilerType clang_type,
11171127
const ParsedDWARFTypeAttributes &attrs, const DWARFDIE &decl_ctx_die,
@@ -1212,11 +1222,22 @@ std::pair<bool, TypeSP> DWARFASTParserClang::ParseCXXMethod(
12121222
const auto accessibility =
12131223
attrs.accessibility == eAccessNone ? eAccessPublic : attrs.accessibility;
12141224

1225+
// TODO: we should also include mangled name in identifier for
1226+
// better diagnostics and easier debugging when reading the
1227+
// expression evaluator IR.
1228+
std::string mangled_name;
1229+
if (IsStructorDIE(die, decl_ctx_die))
1230+
mangled_name = llvm::formatv("$__lldb_func_{0}:{1}", die.GetModule().get(),
1231+
die.GetID())
1232+
.str();
1233+
1234+
char const *mangled =
1235+
mangled_name.empty() ? attrs.mangled_name : mangled_name.c_str();
1236+
12151237
clang::CXXMethodDecl *cxx_method_decl = m_ast.AddMethodToCXXRecordType(
1216-
class_opaque_type.GetOpaqueQualType(), attrs.name.GetCString(),
1217-
attrs.mangled_name, clang_type, accessibility, attrs.is_virtual,
1218-
is_static, attrs.is_inline, attrs.is_explicit, is_attr_used,
1219-
attrs.is_artificial);
1238+
class_opaque_type.GetOpaqueQualType(), attrs.name.GetCString(), mangled,
1239+
clang_type, accessibility, attrs.is_virtual, is_static, attrs.is_inline,
1240+
attrs.is_explicit, is_attr_used, attrs.is_artificial);
12201241

12211242
if (cxx_method_decl) {
12221243
LinkDeclContextToDIE(cxx_method_decl, die);

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

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7822,6 +7822,7 @@ clang::CXXMethodDecl *TypeSystemClang::AddMethodToCXXRecordType(
78227822
nullptr /*expr*/, is_explicit ? clang::ExplicitSpecKind::ResolvedTrue
78237823
: clang::ExplicitSpecKind::ResolvedFalse);
78247824

7825+
bool is_ctor_or_dtor = false;
78257826
if (name.starts_with("~")) {
78267827
cxx_dtor_decl = clang::CXXDestructorDecl::CreateDeserialized(
78277828
getASTContext(), GlobalDeclID());
@@ -7834,6 +7835,7 @@ clang::CXXMethodDecl *TypeSystemClang::AddMethodToCXXRecordType(
78347835
cxx_dtor_decl->setInlineSpecified(is_inline);
78357836
cxx_dtor_decl->setConstexprKind(ConstexprSpecKind::Unspecified);
78367837
cxx_method_decl = cxx_dtor_decl;
7838+
is_ctor_or_dtor = true;
78377839
} else if (decl_name == cxx_record_decl->getDeclName()) {
78387840
cxx_ctor_decl = clang::CXXConstructorDecl::CreateDeserialized(
78397841
getASTContext(), GlobalDeclID(), 0);
@@ -7848,6 +7850,7 @@ clang::CXXMethodDecl *TypeSystemClang::AddMethodToCXXRecordType(
78487850
cxx_ctor_decl->setNumCtorInitializers(0);
78497851
cxx_ctor_decl->setExplicitSpecifier(explicit_spec);
78507852
cxx_method_decl = cxx_ctor_decl;
7853+
is_ctor_or_dtor = true;
78517854
} else {
78527855
clang::StorageClass SC = is_static ? clang::SC_Static : clang::SC_None;
78537856
clang::OverloadedOperatorKind op_kind = clang::NUM_OVERLOADED_OPERATORS;
@@ -7912,8 +7915,13 @@ clang::CXXMethodDecl *TypeSystemClang::AddMethodToCXXRecordType(
79127915
cxx_method_decl->addAttr(clang::UsedAttr::CreateImplicit(getASTContext()));
79137916

79147917
if (mangled_name != nullptr) {
7915-
cxx_method_decl->addAttr(clang::AsmLabelAttr::CreateImplicit(
7916-
getASTContext(), mangled_name, /*literal=*/false));
7918+
if (is_ctor_or_dtor) {
7919+
cxx_method_decl->addAttr(clang::StructorNameAttr::CreateImplicit(
7920+
getASTContext(), mangled_name));
7921+
} else {
7922+
cxx_method_decl->addAttr(clang::AsmLabelAttr::CreateImplicit(
7923+
getASTContext(), mangled_name, /*literal=*/false));
7924+
}
79177925
}
79187926

79197927
// Parameters on member function declarations in DWARF generally don't

0 commit comments

Comments
 (0)