Skip to content

Commit 94ea728

Browse files
committed
[lldb][CPlusPlusLanguage] Expose ManglingSubstitutor as static helpers (llvm#155483)
Part of llvm#149827 Allows us to use the mangling substitution facilities in CPlusPlusLanguage but also SymbolFileDWARF. Added tests now that they're "public". (cherry picked from commit 9dd38b0)
1 parent f9ce2ae commit 94ea728

File tree

4 files changed

+434
-134
lines changed

4 files changed

+434
-134
lines changed

lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp

Lines changed: 188 additions & 134 deletions
Original file line numberDiff line numberDiff line change
@@ -547,126 +547,6 @@ bool CPlusPlusLanguage::ExtractContextAndIdentifier(
547547
return false;
548548
}
549549

550-
namespace {
551-
class NodeAllocator {
552-
llvm::BumpPtrAllocator Alloc;
553-
554-
public:
555-
void reset() { Alloc.Reset(); }
556-
557-
template <typename T, typename... Args> T *makeNode(Args &&...args) {
558-
return new (Alloc.Allocate(sizeof(T), alignof(T)))
559-
T(std::forward<Args>(args)...);
560-
}
561-
562-
void *allocateNodeArray(size_t sz) {
563-
return Alloc.Allocate(sizeof(llvm::itanium_demangle::Node *) * sz,
564-
alignof(llvm::itanium_demangle::Node *));
565-
}
566-
};
567-
568-
template <typename Derived>
569-
class ManglingSubstitutor
570-
: public llvm::itanium_demangle::AbstractManglingParser<Derived,
571-
NodeAllocator> {
572-
using Base =
573-
llvm::itanium_demangle::AbstractManglingParser<Derived, NodeAllocator>;
574-
575-
public:
576-
ManglingSubstitutor() : Base(nullptr, nullptr) {}
577-
578-
template <typename... Ts>
579-
ConstString substitute(llvm::StringRef Mangled, Ts &&...Vals) {
580-
this->getDerived().reset(Mangled, std::forward<Ts>(Vals)...);
581-
return substituteImpl(Mangled);
582-
}
583-
584-
protected:
585-
void reset(llvm::StringRef Mangled) {
586-
Base::reset(Mangled.begin(), Mangled.end());
587-
Written = Mangled.begin();
588-
Result.clear();
589-
Substituted = false;
590-
}
591-
592-
ConstString substituteImpl(llvm::StringRef Mangled) {
593-
Log *log = GetLog(LLDBLog::Language);
594-
if (this->parse() == nullptr) {
595-
LLDB_LOG(log, "Failed to substitute mangling in {0}", Mangled);
596-
return ConstString();
597-
}
598-
if (!Substituted)
599-
return ConstString();
600-
601-
// Append any trailing unmodified input.
602-
appendUnchangedInput();
603-
LLDB_LOG(log, "Substituted mangling {0} -> {1}", Mangled, Result);
604-
return ConstString(Result);
605-
}
606-
607-
void trySubstitute(llvm::StringRef From, llvm::StringRef To) {
608-
if (!llvm::StringRef(currentParserPos(), this->numLeft()).starts_with(From))
609-
return;
610-
611-
// We found a match. Append unmodified input up to this point.
612-
appendUnchangedInput();
613-
614-
// And then perform the replacement.
615-
Result += To;
616-
Written += From.size();
617-
Substituted = true;
618-
}
619-
620-
private:
621-
/// Input character until which we have constructed the respective output
622-
/// already.
623-
const char *Written = "";
624-
625-
llvm::SmallString<128> Result;
626-
627-
/// Whether we have performed any substitutions.
628-
bool Substituted = false;
629-
630-
const char *currentParserPos() const { return this->First; }
631-
632-
void appendUnchangedInput() {
633-
Result +=
634-
llvm::StringRef(Written, std::distance(Written, currentParserPos()));
635-
Written = currentParserPos();
636-
}
637-
};
638-
639-
/// Given a mangled function `Mangled`, replace all the primitive function type
640-
/// arguments of `Search` with type `Replace`.
641-
class TypeSubstitutor : public ManglingSubstitutor<TypeSubstitutor> {
642-
llvm::StringRef Search;
643-
llvm::StringRef Replace;
644-
645-
public:
646-
void reset(llvm::StringRef Mangled, llvm::StringRef Search,
647-
llvm::StringRef Replace) {
648-
ManglingSubstitutor::reset(Mangled);
649-
this->Search = Search;
650-
this->Replace = Replace;
651-
}
652-
653-
llvm::itanium_demangle::Node *parseType() {
654-
trySubstitute(Search, Replace);
655-
return ManglingSubstitutor::parseType();
656-
}
657-
};
658-
659-
class CtorDtorSubstitutor : public ManglingSubstitutor<CtorDtorSubstitutor> {
660-
public:
661-
llvm::itanium_demangle::Node *
662-
parseCtorDtorName(llvm::itanium_demangle::Node *&SoFar, NameState *State) {
663-
trySubstitute("C1", "C2");
664-
trySubstitute("D1", "D2");
665-
return ManglingSubstitutor::parseCtorDtorName(SoFar, State);
666-
}
667-
};
668-
} // namespace
669-
670550
std::vector<ConstString> CPlusPlusLanguage::GenerateAlternateFunctionManglings(
671551
const ConstString mangled_name) const {
672552
std::vector<ConstString> alternates;
@@ -694,29 +574,49 @@ std::vector<ConstString> CPlusPlusLanguage::GenerateAlternateFunctionManglings(
694574
alternates.push_back(ConstString(fixed_scratch));
695575
}
696576

697-
TypeSubstitutor TS;
577+
auto *log = GetLog(LLDBLog::Language);
578+
698579
// `char` is implementation defined as either `signed` or `unsigned`. As a
699580
// result a char parameter has 3 possible manglings: 'c'-char, 'a'-signed
700581
// char, 'h'-unsigned char. If we're looking for symbols with a signed char
701582
// parameter, try finding matches which have the general case 'c'.
702-
if (ConstString char_fixup =
703-
TS.substitute(mangled_name.GetStringRef(), "a", "c"))
704-
alternates.push_back(char_fixup);
583+
if (auto char_fixup_or_err =
584+
SubstituteType_ItaniumMangle(mangled_name.GetStringRef(), "a", "c")) {
585+
// LLDB_LOG(log, "Substituted mangling {0} -> {1}", Mangled, Result);
586+
if (*char_fixup_or_err)
587+
alternates.push_back(*char_fixup_or_err);
588+
} else
589+
LLDB_LOG_ERROR(log, char_fixup_or_err.takeError(),
590+
"Failed to substitute 'char' type mangling: {0}");
705591

706592
// long long parameter mangling 'x', may actually just be a long 'l' argument
707-
if (ConstString long_fixup =
708-
TS.substitute(mangled_name.GetStringRef(), "x", "l"))
709-
alternates.push_back(long_fixup);
593+
if (auto long_fixup_or_err =
594+
SubstituteType_ItaniumMangle(mangled_name.GetStringRef(), "x", "l")) {
595+
if (*long_fixup_or_err)
596+
alternates.push_back(*long_fixup_or_err);
597+
} else
598+
LLDB_LOG_ERROR(log, long_fixup_or_err.takeError(),
599+
"Failed to substitute 'long long' type mangling: {0}");
710600

711601
// unsigned long long parameter mangling 'y', may actually just be unsigned
712602
// long 'm' argument
713-
if (ConstString ulong_fixup =
714-
TS.substitute(mangled_name.GetStringRef(), "y", "m"))
715-
alternates.push_back(ulong_fixup);
716-
717-
if (ConstString ctor_fixup =
718-
CtorDtorSubstitutor().substitute(mangled_name.GetStringRef()))
719-
alternates.push_back(ctor_fixup);
603+
if (auto ulong_fixup_or_err =
604+
SubstituteType_ItaniumMangle(mangled_name.GetStringRef(), "y", "m")) {
605+
if (*ulong_fixup_or_err)
606+
alternates.push_back(*ulong_fixup_or_err);
607+
} else
608+
LLDB_LOG_ERROR(
609+
log, ulong_fixup_or_err.takeError(),
610+
"Failed to substitute 'unsigned long long' type mangling: {0}");
611+
612+
if (auto ctor_fixup_or_err = SubstituteStructorAliases_ItaniumMangle(
613+
mangled_name.GetStringRef())) {
614+
if (*ctor_fixup_or_err) {
615+
alternates.push_back(*ctor_fixup_or_err);
616+
}
617+
} else
618+
LLDB_LOG_ERROR(log, ctor_fixup_or_err.takeError(),
619+
"Failed to substitute structor alias manglings: {0}");
720620

721621
return alternates;
722622
}
@@ -2150,6 +2050,160 @@ bool CPlusPlusLanguage::HandleFrameFormatVariable(
21502050
}
21512051
}
21522052

2053+
namespace {
2054+
class NodeAllocator {
2055+
llvm::BumpPtrAllocator Alloc;
2056+
2057+
public:
2058+
void reset() { Alloc.Reset(); }
2059+
2060+
template <typename T, typename... Args> T *makeNode(Args &&...args) {
2061+
return new (Alloc.Allocate(sizeof(T), alignof(T)))
2062+
T(std::forward<Args>(args)...);
2063+
}
2064+
2065+
void *allocateNodeArray(size_t sz) {
2066+
return Alloc.Allocate(sizeof(llvm::itanium_demangle::Node *) * sz,
2067+
alignof(llvm::itanium_demangle::Node *));
2068+
}
2069+
};
2070+
2071+
template <typename Derived>
2072+
class ManglingSubstitutor
2073+
: public llvm::itanium_demangle::AbstractManglingParser<Derived,
2074+
NodeAllocator> {
2075+
using Base =
2076+
llvm::itanium_demangle::AbstractManglingParser<Derived, NodeAllocator>;
2077+
2078+
public:
2079+
ManglingSubstitutor() : Base(nullptr, nullptr) {}
2080+
2081+
template <typename... Ts>
2082+
llvm::Expected<ConstString> substitute(llvm::StringRef Mangled,
2083+
Ts &&...Vals) {
2084+
this->getDerived().reset(Mangled, std::forward<Ts>(Vals)...);
2085+
return substituteImpl(Mangled);
2086+
}
2087+
2088+
protected:
2089+
void reset(llvm::StringRef Mangled) {
2090+
Base::reset(Mangled.begin(), Mangled.end());
2091+
Written = Mangled.begin();
2092+
Result.clear();
2093+
Substituted = false;
2094+
}
2095+
2096+
llvm::Expected<ConstString> substituteImpl(llvm::StringRef Mangled) {
2097+
if (this->parse() == nullptr)
2098+
return llvm::createStringError(
2099+
llvm::formatv("Failed to substitute mangling in '{0}'", Mangled));
2100+
2101+
if (!Substituted)
2102+
return ConstString();
2103+
2104+
// Append any trailing unmodified input.
2105+
appendUnchangedInput();
2106+
return ConstString(Result);
2107+
}
2108+
2109+
void trySubstitute(llvm::StringRef From, llvm::StringRef To) {
2110+
if (!llvm::StringRef(currentParserPos(), this->numLeft()).starts_with(From))
2111+
return;
2112+
2113+
// We found a match. Append unmodified input up to this point.
2114+
appendUnchangedInput();
2115+
2116+
// And then perform the replacement.
2117+
Result += To;
2118+
Written += From.size();
2119+
Substituted = true;
2120+
}
2121+
2122+
private:
2123+
/// Input character until which we have constructed the respective output
2124+
/// already.
2125+
const char *Written = "";
2126+
2127+
llvm::SmallString<128> Result;
2128+
2129+
/// Whether we have performed any substitutions.
2130+
bool Substituted = false;
2131+
2132+
const char *currentParserPos() const { return this->First; }
2133+
2134+
void appendUnchangedInput() {
2135+
Result +=
2136+
llvm::StringRef(Written, std::distance(Written, currentParserPos()));
2137+
Written = currentParserPos();
2138+
}
2139+
};
2140+
2141+
/// Given a mangled function `Mangled`, replace all the primitive function type
2142+
/// arguments of `Search` with type `Replace`.
2143+
class TypeSubstitutor : public ManglingSubstitutor<TypeSubstitutor> {
2144+
llvm::StringRef Search;
2145+
llvm::StringRef Replace;
2146+
2147+
public:
2148+
void reset(llvm::StringRef Mangled, llvm::StringRef Search,
2149+
llvm::StringRef Replace) {
2150+
ManglingSubstitutor::reset(Mangled);
2151+
this->Search = Search;
2152+
this->Replace = Replace;
2153+
}
2154+
2155+
llvm::itanium_demangle::Node *parseType() {
2156+
trySubstitute(Search, Replace);
2157+
return ManglingSubstitutor::parseType();
2158+
}
2159+
};
2160+
2161+
class CtorDtorSubstitutor : public ManglingSubstitutor<CtorDtorSubstitutor> {
2162+
llvm::StringRef Search;
2163+
llvm::StringRef Replace;
2164+
2165+
public:
2166+
void reset(llvm::StringRef Mangled, llvm::StringRef Search,
2167+
llvm::StringRef Replace) {
2168+
ManglingSubstitutor::reset(Mangled);
2169+
this->Search = Search;
2170+
this->Replace = Replace;
2171+
}
2172+
2173+
void reset(llvm::StringRef Mangled) { ManglingSubstitutor::reset(Mangled); }
2174+
2175+
llvm::itanium_demangle::Node *
2176+
parseCtorDtorName(llvm::itanium_demangle::Node *&SoFar, NameState *State) {
2177+
if (!Search.empty() && !Replace.empty()) {
2178+
trySubstitute(Search, Replace);
2179+
} else {
2180+
trySubstitute("D1", "D2");
2181+
trySubstitute("C1", "C2");
2182+
}
2183+
return ManglingSubstitutor::parseCtorDtorName(SoFar, State);
2184+
}
2185+
};
2186+
} // namespace
2187+
2188+
llvm::Expected<ConstString>
2189+
CPlusPlusLanguage::SubstituteType_ItaniumMangle(llvm::StringRef mangled_name,
2190+
llvm::StringRef subst_from,
2191+
llvm::StringRef subst_to) {
2192+
return TypeSubstitutor().substitute(mangled_name, subst_from, subst_to);
2193+
}
2194+
2195+
llvm::Expected<ConstString> CPlusPlusLanguage::SubstituteStructor_ItaniumMangle(
2196+
llvm::StringRef mangled_name, llvm::StringRef subst_from,
2197+
llvm::StringRef subst_to) {
2198+
return CtorDtorSubstitutor().substitute(mangled_name, subst_from, subst_to);
2199+
}
2200+
2201+
llvm::Expected<ConstString>
2202+
CPlusPlusLanguage::SubstituteStructorAliases_ItaniumMangle(
2203+
llvm::StringRef mangled_name) {
2204+
return CtorDtorSubstitutor().substitute(mangled_name);
2205+
}
2206+
21532207
#define LLDB_PROPERTIES_language_cplusplus
21542208
#include "LanguageCPlusPlusProperties.inc"
21552209

0 commit comments

Comments
 (0)