Skip to content

Commit f8087e9

Browse files
committed
Init
1 parent 9548dbe commit f8087e9

File tree

11 files changed

+271
-13
lines changed

11 files changed

+271
-13
lines changed

clang/include/clang/Basic/Attr.td

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -784,6 +784,13 @@ def AbiTag : Attr {
784784
let Documentation = [AbiTagsDocs];
785785
}
786786

787+
def StructorName : Attr {
788+
let Spellings = [Clang<"structor_name">];
789+
let Args = [StringArgument<"Name">];
790+
let Subjects = SubjectList<[Function], ErrorDiag>;
791+
let Documentation = [StructorNameDocs];
792+
}
793+
787794
def AddressSpace : TypeAttr {
788795
let Spellings = [Clang<"address_space">];
789796
let Args = [IntArgument<"AddressSpace">];

clang/include/clang/Basic/AttrDocs.td

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3568,6 +3568,11 @@ manipulating bits of the enumerator when issuing warnings.
35683568
}];
35693569
}
35703570

3571+
def StructorNameDocs : Documentation {
3572+
let Category = DocCatDecl;
3573+
let Content = [{ TODO }];
3574+
}
3575+
35713576
def AsmLabelDocs : Documentation {
35723577
let Category = DocCatDecl;
35733578
let Content = [{

clang/lib/AST/Mangle.cpp

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

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

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

143+
if (const auto *SNA = D->getAttr<StructorNameAttr>()) {
144+
Out << SNA->getName() << ':';
145+
146+
if (isa<CXXConstructorDecl>(D)) {
147+
Out << 'C';
148+
Out << GD.getCtorType();
149+
} else {
150+
Out << 'D';
151+
Out << GD.getDtorType();
152+
}
153+
154+
return;
155+
}
156+
143157
// Any decl can be declared with __asm("foo") on it, and this takes precedence
144158
// over all other naming in the .o file.
145159
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
@@ -1689,6 +1689,14 @@ static void handleIFuncAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
16891689
D->addAttr(::new (S.Context) IFuncAttr(S.Context, AL, Str));
16901690
}
16911691

1692+
static void handleStructorNameAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
1693+
StringRef Str;
1694+
if (!S.checkStringLiteralArgumentAttr(AL, 0, Str))
1695+
return;
1696+
1697+
D->addAttr(::new (S.Context) StructorNameAttr(S.Context, AL, Str));
1698+
}
1699+
16921700
static void handleAliasAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
16931701
StringRef Str;
16941702
if (!S.checkStringLiteralArgumentAttr(AL, 0, Str))
@@ -6983,6 +6991,9 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL,
69836991
S.HLSL().handleParamModifierAttr(D, AL);
69846992
break;
69856993

6994+
case ParsedAttr::AT_StructorName:
6995+
handleStructorNameAttr(S, D, AL);
6996+
break;
69866997
case ParsedAttr::AT_AbiTag:
69876998
handleAbiTagAttr(S, D, AL);
69886999
break;

libcxxabi/src/demangle/ItaniumDemangle.h

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

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

1731+
int getVariant() const { return Variant; }
1732+
17311733
void printLeft(OutputBuffer &OB) const override {
17321734
if (IsDtor)
17331735
OB += "~";

lldb/source/Expression/IRExecutionUnit.cpp

Lines changed: 181 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

@@ -762,6 +771,120 @@ class LoadAddressResolver {
762771
lldb::addr_t m_best_internal_load_address = LLDB_INVALID_ADDRESS;
763772
};
764773

774+
using namespace lldb_private::plugin::dwarf;
775+
776+
struct StructorVariant {
777+
std::variant<clang::CXXCtorType, clang::CXXDtorType> m_variant;
778+
};
779+
780+
static llvm::Expected<StructorVariant>
781+
MakeStructorVariant(llvm::StringRef variant_num) {
782+
if (variant_num.consume_front("D")) {
783+
std::underlying_type_t<clang::CXXDtorType> dtor_type;
784+
if (variant_num.consumeInteger(10, dtor_type))
785+
return llvm::createStringError("Invalid ctor variant code.");
786+
787+
return StructorVariant{.m_variant =
788+
static_cast<clang::CXXDtorType>(dtor_type)};
789+
}
790+
791+
if (variant_num.consume_front("C")) {
792+
std::underlying_type_t<clang::CXXCtorType> ctor_type;
793+
if (variant_num.consumeInteger(10, ctor_type))
794+
return llvm::createStringError("Invalid dtor variant code.");
795+
796+
return StructorVariant{.m_variant =
797+
static_cast<clang::CXXCtorType>(ctor_type)};
798+
}
799+
800+
return llvm::createStringError("Incorrect structor variant prefix.");
801+
}
802+
803+
static int GetItaniumVariantCode(StructorVariant structor) {
804+
if (auto const *ctor = std::get_if<clang::CXXCtorType>(&structor.m_variant)) {
805+
switch (*ctor) {
806+
case clang::CXXCtorType::Ctor_Complete:
807+
return 1;
808+
case clang::CXXCtorType::Ctor_Base:
809+
return 2;
810+
default:
811+
llvm_unreachable("Unimplemented");
812+
}
813+
} else {
814+
switch (std::get<clang::CXXDtorType>(structor.m_variant)) {
815+
case clang::CXXDtorType::Dtor_Complete:
816+
return 1;
817+
case clang::CXXDtorType::Dtor_Base:
818+
return 2;
819+
default:
820+
llvm_unreachable("Unimplemented");
821+
}
822+
}
823+
}
824+
825+
// TODO:
826+
// 1. MS-ABI
827+
// 2. GCC-style dtor/ctor declarations
828+
// 3. Inheriting ctors
829+
// 4. Regular functions
830+
static std::string FindStructorLinkageName(DWARFDIE die,
831+
StructorVariant structor_variant) {
832+
auto *dwarf = die.GetDWARF();
833+
assert(dwarf);
834+
835+
// Note, GCC only puts DW_AT_linkage_name (not DW_AT_name) on constructor
836+
// decls Will those cases still work?
837+
ConstString func_name(die.GetName());
838+
assert(func_name);
839+
840+
SymbolContextList sc_list;
841+
Module::LookupInfo lookup_info(
842+
func_name,
843+
lldb::FunctionNameType::eFunctionNameTypeMethod |
844+
lldb::FunctionNameType::eFunctionNameTypeFull,
845+
lldb::LanguageType::eLanguageTypeUnknown);
846+
dwarf->FindFunctions(lookup_info, {}, true, sc_list);
847+
848+
llvm::DenseMap<int, std::string> variants;
849+
850+
for (auto const &sc : sc_list.SymbolContexts()) {
851+
if (!sc.function)
852+
continue;
853+
854+
auto func_die = dwarf->GetDIE(sc.function->GetID());
855+
if (!func_die.IsValid())
856+
continue;
857+
858+
auto spec_die = func_die.GetAttributeValueAsReferenceDIE(
859+
llvm::dwarf::DW_AT_specification);
860+
if (!spec_die.IsValid() || spec_die != die)
861+
continue;
862+
863+
llvm::ItaniumPartialDemangler D;
864+
if (D.partialDemangle(func_die.GetMangledName()))
865+
continue;
866+
867+
const auto maybe_structor_kind = D.getCtorDtorVariant();
868+
// TODO: this need not be true
869+
assert(maybe_structor_kind);
870+
871+
variants.insert({*maybe_structor_kind, func_die.GetMangledName()});
872+
}
873+
874+
auto itanium_code = GetItaniumVariantCode(structor_variant);
875+
auto it = variants.find(itanium_code);
876+
if (it != variants.end())
877+
return it->second;
878+
879+
// If only C2 was emitted but we tried calling C1,
880+
// we can probably (?) safely call C2.
881+
if (itanium_code == 1 && variants.size() == 1)
882+
if (auto retry = variants.find(2); retry != variants.end())
883+
return retry->second;
884+
885+
return {};
886+
}
887+
765888
lldb::addr_t
766889
IRExecutionUnit::FindInSymbols(const std::vector<ConstString> &names,
767890
const lldb_private::SymbolContext &sc,
@@ -781,6 +904,64 @@ IRExecutionUnit::FindInSymbols(const std::vector<ConstString> &names,
781904
function_options.include_inlines = false;
782905

783906
for (const ConstString &name : names) {
907+
auto ref = name.GetStringRef();
908+
if (ref.consume_front("$__lldb_func_")) {
909+
uintptr_t module_ptr;
910+
if (ref.consumeInteger(0, module_ptr))
911+
return LLDB_INVALID_ADDRESS;
912+
913+
if (module_ptr == 0) {
914+
// TODO: log this case. We should ever be putting a null module pointer
915+
// here
916+
return LLDB_INVALID_ADDRESS;
917+
}
918+
919+
auto *mod = (lldb_private::Module *)module_ptr;
920+
assert(mod);
921+
auto *sym = mod->GetSymbolFile();
922+
assert(sym);
923+
924+
if (!ref.consume_front(":"))
925+
return LLDB_INVALID_ADDRESS;
926+
927+
lldb::user_id_t die_id;
928+
if (ref.consumeInteger(10, die_id))
929+
return LLDB_INVALID_ADDRESS;
930+
931+
auto *dwarf = llvm::dyn_cast<plugin::dwarf::SymbolFileDWARF>(sym);
932+
if (!dwarf)
933+
return LLDB_INVALID_ADDRESS;
934+
935+
auto die = dwarf->GetDIE(die_id);
936+
if (!die.IsValid())
937+
return LLDB_INVALID_ADDRESS;
938+
939+
// TODO: account for MS-ABI (where there are no ctor variants in the
940+
// mangling)
941+
if (!ref.consume_front(":"))
942+
return LLDB_INVALID_ADDRESS;
943+
944+
auto structor_variant_or_err = MakeStructorVariant(ref);
945+
if (!structor_variant_or_err) {
946+
LLDB_LOG_ERROR(GetLog(LLDBLog::Expressions),
947+
structor_variant_or_err.takeError(),
948+
"Failed to parse structor variant encoding for {1}: {0}",
949+
name.GetStringRef());
950+
return LLDB_INVALID_ADDRESS;
951+
}
952+
953+
ConstString mangled(
954+
FindStructorLinkageName(die, *structor_variant_or_err));
955+
956+
Module::LookupInfo lookup_info(
957+
mangled, lldb::FunctionNameType::eFunctionNameTypeAny,
958+
lldb::LanguageType::eLanguageTypeC_plus_plus);
959+
SymbolContextList sc_list;
960+
dwarf->FindFunctions(lookup_info, {}, false, sc_list);
961+
if (auto load_addr = resolver.Resolve(sc_list))
962+
return *load_addr;
963+
}
964+
784965
if (sc.module_sp) {
785966
SymbolContextList sc_list;
786967
sc.module_sp->FindFunctions(name, CompilerDeclContext(),

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

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1040,6 +1040,16 @@ bool DWARFASTParserClang::ParseObjCMethod(
10401040
return true;
10411041
}
10421042

1043+
static bool IsStructorDIE(DWARFDIE const &die, DWARFDIE const &parent_die) {
1044+
llvm::StringRef name = die.GetName();
1045+
llvm::StringRef parent_name = parent_die.GetName();
1046+
1047+
name.consume_front("~");
1048+
parent_name = parent_name.substr(0, parent_name.find('<'));
1049+
1050+
return name == parent_name;
1051+
}
1052+
10431053
std::pair<bool, TypeSP> DWARFASTParserClang::ParseCXXMethod(
10441054
const DWARFDIE &die, CompilerType clang_type,
10451055
const ParsedDWARFTypeAttributes &attrs, const DWARFDIE &decl_ctx_die,
@@ -1140,11 +1150,22 @@ std::pair<bool, TypeSP> DWARFASTParserClang::ParseCXXMethod(
11401150
const auto accessibility =
11411151
attrs.accessibility == eAccessNone ? eAccessPublic : attrs.accessibility;
11421152

1153+
// TODO: we should also include mangled name in identifier for
1154+
// better diagnostics and easier debugging when reading the
1155+
// expression evaluator IR.
1156+
std::string mangled_name;
1157+
if (IsStructorDIE(die, decl_ctx_die))
1158+
mangled_name = llvm::formatv("$__lldb_func_{0}:{1}", die.GetModule().get(),
1159+
die.GetID())
1160+
.str();
1161+
1162+
char const *mangled =
1163+
mangled_name.empty() ? attrs.mangled_name : mangled_name.c_str();
1164+
11431165
clang::CXXMethodDecl *cxx_method_decl = m_ast.AddMethodToCXXRecordType(
1144-
class_opaque_type.GetOpaqueQualType(), attrs.name.GetCString(),
1145-
attrs.mangled_name, clang_type, accessibility, attrs.is_virtual,
1146-
is_static, attrs.is_inline, attrs.is_explicit, is_attr_used,
1147-
attrs.is_artificial);
1166+
class_opaque_type.GetOpaqueQualType(), attrs.name.GetCString(), mangled,
1167+
clang_type, accessibility, attrs.is_virtual, is_static, attrs.is_inline,
1168+
attrs.is_explicit, is_attr_used, attrs.is_artificial);
11481169

11491170
if (cxx_method_decl) {
11501171
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
@@ -7777,6 +7777,7 @@ clang::CXXMethodDecl *TypeSystemClang::AddMethodToCXXRecordType(
77777777
nullptr /*expr*/, is_explicit ? clang::ExplicitSpecKind::ResolvedTrue
77787778
: clang::ExplicitSpecKind::ResolvedFalse);
77797779

7780+
bool is_ctor_or_dtor = false;
77807781
if (name.starts_with("~")) {
77817782
cxx_dtor_decl = clang::CXXDestructorDecl::CreateDeserialized(
77827783
getASTContext(), GlobalDeclID());
@@ -7803,6 +7804,7 @@ clang::CXXMethodDecl *TypeSystemClang::AddMethodToCXXRecordType(
78037804
cxx_ctor_decl->setNumCtorInitializers(0);
78047805
cxx_ctor_decl->setExplicitSpecifier(explicit_spec);
78057806
cxx_method_decl = cxx_ctor_decl;
7807+
is_ctor_or_dtor = true;
78067808
} else {
78077809
clang::StorageClass SC = is_static ? clang::SC_Static : clang::SC_None;
78087810
clang::OverloadedOperatorKind op_kind = clang::NUM_OVERLOADED_OPERATORS;
@@ -7826,6 +7828,7 @@ clang::CXXMethodDecl *TypeSystemClang::AddMethodToCXXRecordType(
78267828
cxx_method_decl->setStorageClass(SC);
78277829
cxx_method_decl->setInlineSpecified(is_inline);
78287830
cxx_method_decl->setConstexprKind(ConstexprSpecKind::Unspecified);
7831+
is_ctor_or_dtor = true;
78297832
} else if (num_params == 0) {
78307833
// Conversion operators don't take params...
78317834
auto *cxx_conversion_decl =
@@ -7867,8 +7870,13 @@ clang::CXXMethodDecl *TypeSystemClang::AddMethodToCXXRecordType(
78677870
cxx_method_decl->addAttr(clang::UsedAttr::CreateImplicit(getASTContext()));
78687871

78697872
if (mangled_name != nullptr) {
7870-
cxx_method_decl->addAttr(clang::AsmLabelAttr::CreateImplicit(
7871-
getASTContext(), mangled_name, /*literal=*/false));
7873+
if (is_ctor_or_dtor) {
7874+
cxx_method_decl->addAttr(clang::StructorNameAttr::CreateImplicit(
7875+
getASTContext(), mangled_name));
7876+
} else {
7877+
cxx_method_decl->addAttr(clang::AsmLabelAttr::CreateImplicit(
7878+
getASTContext(), mangled_name, /*literal=*/false));
7879+
}
78727880
}
78737881

78747882
// Populate the method decl with parameter decls

0 commit comments

Comments
 (0)