Skip to content

Commit 9dd38b0

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

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
@@ -604,126 +604,6 @@ bool CPlusPlusLanguage::ExtractContextAndIdentifier(
604604
return false;
605605
}
606606

607-
namespace {
608-
class NodeAllocator {
609-
llvm::BumpPtrAllocator Alloc;
610-
611-
public:
612-
void reset() { Alloc.Reset(); }
613-
614-
template <typename T, typename... Args> T *makeNode(Args &&...args) {
615-
return new (Alloc.Allocate(sizeof(T), alignof(T)))
616-
T(std::forward<Args>(args)...);
617-
}
618-
619-
void *allocateNodeArray(size_t sz) {
620-
return Alloc.Allocate(sizeof(llvm::itanium_demangle::Node *) * sz,
621-
alignof(llvm::itanium_demangle::Node *));
622-
}
623-
};
624-
625-
template <typename Derived>
626-
class ManglingSubstitutor
627-
: public llvm::itanium_demangle::AbstractManglingParser<Derived,
628-
NodeAllocator> {
629-
using Base =
630-
llvm::itanium_demangle::AbstractManglingParser<Derived, NodeAllocator>;
631-
632-
public:
633-
ManglingSubstitutor() : Base(nullptr, nullptr) {}
634-
635-
template <typename... Ts>
636-
ConstString substitute(llvm::StringRef Mangled, Ts &&...Vals) {
637-
this->getDerived().reset(Mangled, std::forward<Ts>(Vals)...);
638-
return substituteImpl(Mangled);
639-
}
640-
641-
protected:
642-
void reset(llvm::StringRef Mangled) {
643-
Base::reset(Mangled.begin(), Mangled.end());
644-
Written = Mangled.begin();
645-
Result.clear();
646-
Substituted = false;
647-
}
648-
649-
ConstString substituteImpl(llvm::StringRef Mangled) {
650-
Log *log = GetLog(LLDBLog::Language);
651-
if (this->parse() == nullptr) {
652-
LLDB_LOG(log, "Failed to substitute mangling in {0}", Mangled);
653-
return ConstString();
654-
}
655-
if (!Substituted)
656-
return ConstString();
657-
658-
// Append any trailing unmodified input.
659-
appendUnchangedInput();
660-
LLDB_LOG(log, "Substituted mangling {0} -> {1}", Mangled, Result);
661-
return ConstString(Result);
662-
}
663-
664-
void trySubstitute(llvm::StringRef From, llvm::StringRef To) {
665-
if (!llvm::StringRef(currentParserPos(), this->numLeft()).starts_with(From))
666-
return;
667-
668-
// We found a match. Append unmodified input up to this point.
669-
appendUnchangedInput();
670-
671-
// And then perform the replacement.
672-
Result += To;
673-
Written += From.size();
674-
Substituted = true;
675-
}
676-
677-
private:
678-
/// Input character until which we have constructed the respective output
679-
/// already.
680-
const char *Written = "";
681-
682-
llvm::SmallString<128> Result;
683-
684-
/// Whether we have performed any substitutions.
685-
bool Substituted = false;
686-
687-
const char *currentParserPos() const { return this->First; }
688-
689-
void appendUnchangedInput() {
690-
Result +=
691-
llvm::StringRef(Written, std::distance(Written, currentParserPos()));
692-
Written = currentParserPos();
693-
}
694-
};
695-
696-
/// Given a mangled function `Mangled`, replace all the primitive function type
697-
/// arguments of `Search` with type `Replace`.
698-
class TypeSubstitutor : public ManglingSubstitutor<TypeSubstitutor> {
699-
llvm::StringRef Search;
700-
llvm::StringRef Replace;
701-
702-
public:
703-
void reset(llvm::StringRef Mangled, llvm::StringRef Search,
704-
llvm::StringRef Replace) {
705-
ManglingSubstitutor::reset(Mangled);
706-
this->Search = Search;
707-
this->Replace = Replace;
708-
}
709-
710-
llvm::itanium_demangle::Node *parseType() {
711-
trySubstitute(Search, Replace);
712-
return ManglingSubstitutor::parseType();
713-
}
714-
};
715-
716-
class CtorDtorSubstitutor : public ManglingSubstitutor<CtorDtorSubstitutor> {
717-
public:
718-
llvm::itanium_demangle::Node *
719-
parseCtorDtorName(llvm::itanium_demangle::Node *&SoFar, NameState *State) {
720-
trySubstitute("C1", "C2");
721-
trySubstitute("D1", "D2");
722-
return ManglingSubstitutor::parseCtorDtorName(SoFar, State);
723-
}
724-
};
725-
} // namespace
726-
727607
std::vector<ConstString> CPlusPlusLanguage::GenerateAlternateFunctionManglings(
728608
const ConstString mangled_name) const {
729609
std::vector<ConstString> alternates;
@@ -751,29 +631,49 @@ std::vector<ConstString> CPlusPlusLanguage::GenerateAlternateFunctionManglings(
751631
alternates.push_back(ConstString(fixed_scratch));
752632
}
753633

754-
TypeSubstitutor TS;
634+
auto *log = GetLog(LLDBLog::Language);
635+
755636
// `char` is implementation defined as either `signed` or `unsigned`. As a
756637
// result a char parameter has 3 possible manglings: 'c'-char, 'a'-signed
757638
// char, 'h'-unsigned char. If we're looking for symbols with a signed char
758639
// parameter, try finding matches which have the general case 'c'.
759-
if (ConstString char_fixup =
760-
TS.substitute(mangled_name.GetStringRef(), "a", "c"))
761-
alternates.push_back(char_fixup);
640+
if (auto char_fixup_or_err =
641+
SubstituteType_ItaniumMangle(mangled_name.GetStringRef(), "a", "c")) {
642+
// LLDB_LOG(log, "Substituted mangling {0} -> {1}", Mangled, Result);
643+
if (*char_fixup_or_err)
644+
alternates.push_back(*char_fixup_or_err);
645+
} else
646+
LLDB_LOG_ERROR(log, char_fixup_or_err.takeError(),
647+
"Failed to substitute 'char' type mangling: {0}");
762648

763649
// long long parameter mangling 'x', may actually just be a long 'l' argument
764-
if (ConstString long_fixup =
765-
TS.substitute(mangled_name.GetStringRef(), "x", "l"))
766-
alternates.push_back(long_fixup);
650+
if (auto long_fixup_or_err =
651+
SubstituteType_ItaniumMangle(mangled_name.GetStringRef(), "x", "l")) {
652+
if (*long_fixup_or_err)
653+
alternates.push_back(*long_fixup_or_err);
654+
} else
655+
LLDB_LOG_ERROR(log, long_fixup_or_err.takeError(),
656+
"Failed to substitute 'long long' type mangling: {0}");
767657

768658
// unsigned long long parameter mangling 'y', may actually just be unsigned
769659
// long 'm' argument
770-
if (ConstString ulong_fixup =
771-
TS.substitute(mangled_name.GetStringRef(), "y", "m"))
772-
alternates.push_back(ulong_fixup);
773-
774-
if (ConstString ctor_fixup =
775-
CtorDtorSubstitutor().substitute(mangled_name.GetStringRef()))
776-
alternates.push_back(ctor_fixup);
660+
if (auto ulong_fixup_or_err =
661+
SubstituteType_ItaniumMangle(mangled_name.GetStringRef(), "y", "m")) {
662+
if (*ulong_fixup_or_err)
663+
alternates.push_back(*ulong_fixup_or_err);
664+
} else
665+
LLDB_LOG_ERROR(
666+
log, ulong_fixup_or_err.takeError(),
667+
"Failed to substitute 'unsigned long long' type mangling: {0}");
668+
669+
if (auto ctor_fixup_or_err = SubstituteStructorAliases_ItaniumMangle(
670+
mangled_name.GetStringRef())) {
671+
if (*ctor_fixup_or_err) {
672+
alternates.push_back(*ctor_fixup_or_err);
673+
}
674+
} else
675+
LLDB_LOG_ERROR(log, ctor_fixup_or_err.takeError(),
676+
"Failed to substitute structor alias manglings: {0}");
777677

778678
return alternates;
779679
}
@@ -2442,6 +2342,160 @@ bool CPlusPlusLanguage::HandleFrameFormatVariable(
24422342
}
24432343
}
24442344

2345+
namespace {
2346+
class NodeAllocator {
2347+
llvm::BumpPtrAllocator Alloc;
2348+
2349+
public:
2350+
void reset() { Alloc.Reset(); }
2351+
2352+
template <typename T, typename... Args> T *makeNode(Args &&...args) {
2353+
return new (Alloc.Allocate(sizeof(T), alignof(T)))
2354+
T(std::forward<Args>(args)...);
2355+
}
2356+
2357+
void *allocateNodeArray(size_t sz) {
2358+
return Alloc.Allocate(sizeof(llvm::itanium_demangle::Node *) * sz,
2359+
alignof(llvm::itanium_demangle::Node *));
2360+
}
2361+
};
2362+
2363+
template <typename Derived>
2364+
class ManglingSubstitutor
2365+
: public llvm::itanium_demangle::AbstractManglingParser<Derived,
2366+
NodeAllocator> {
2367+
using Base =
2368+
llvm::itanium_demangle::AbstractManglingParser<Derived, NodeAllocator>;
2369+
2370+
public:
2371+
ManglingSubstitutor() : Base(nullptr, nullptr) {}
2372+
2373+
template <typename... Ts>
2374+
llvm::Expected<ConstString> substitute(llvm::StringRef Mangled,
2375+
Ts &&...Vals) {
2376+
this->getDerived().reset(Mangled, std::forward<Ts>(Vals)...);
2377+
return substituteImpl(Mangled);
2378+
}
2379+
2380+
protected:
2381+
void reset(llvm::StringRef Mangled) {
2382+
Base::reset(Mangled.begin(), Mangled.end());
2383+
Written = Mangled.begin();
2384+
Result.clear();
2385+
Substituted = false;
2386+
}
2387+
2388+
llvm::Expected<ConstString> substituteImpl(llvm::StringRef Mangled) {
2389+
if (this->parse() == nullptr)
2390+
return llvm::createStringError(
2391+
llvm::formatv("Failed to substitute mangling in '{0}'", Mangled));
2392+
2393+
if (!Substituted)
2394+
return ConstString();
2395+
2396+
// Append any trailing unmodified input.
2397+
appendUnchangedInput();
2398+
return ConstString(Result);
2399+
}
2400+
2401+
void trySubstitute(llvm::StringRef From, llvm::StringRef To) {
2402+
if (!llvm::StringRef(currentParserPos(), this->numLeft()).starts_with(From))
2403+
return;
2404+
2405+
// We found a match. Append unmodified input up to this point.
2406+
appendUnchangedInput();
2407+
2408+
// And then perform the replacement.
2409+
Result += To;
2410+
Written += From.size();
2411+
Substituted = true;
2412+
}
2413+
2414+
private:
2415+
/// Input character until which we have constructed the respective output
2416+
/// already.
2417+
const char *Written = "";
2418+
2419+
llvm::SmallString<128> Result;
2420+
2421+
/// Whether we have performed any substitutions.
2422+
bool Substituted = false;
2423+
2424+
const char *currentParserPos() const { return this->First; }
2425+
2426+
void appendUnchangedInput() {
2427+
Result +=
2428+
llvm::StringRef(Written, std::distance(Written, currentParserPos()));
2429+
Written = currentParserPos();
2430+
}
2431+
};
2432+
2433+
/// Given a mangled function `Mangled`, replace all the primitive function type
2434+
/// arguments of `Search` with type `Replace`.
2435+
class TypeSubstitutor : public ManglingSubstitutor<TypeSubstitutor> {
2436+
llvm::StringRef Search;
2437+
llvm::StringRef Replace;
2438+
2439+
public:
2440+
void reset(llvm::StringRef Mangled, llvm::StringRef Search,
2441+
llvm::StringRef Replace) {
2442+
ManglingSubstitutor::reset(Mangled);
2443+
this->Search = Search;
2444+
this->Replace = Replace;
2445+
}
2446+
2447+
llvm::itanium_demangle::Node *parseType() {
2448+
trySubstitute(Search, Replace);
2449+
return ManglingSubstitutor::parseType();
2450+
}
2451+
};
2452+
2453+
class CtorDtorSubstitutor : public ManglingSubstitutor<CtorDtorSubstitutor> {
2454+
llvm::StringRef Search;
2455+
llvm::StringRef Replace;
2456+
2457+
public:
2458+
void reset(llvm::StringRef Mangled, llvm::StringRef Search,
2459+
llvm::StringRef Replace) {
2460+
ManglingSubstitutor::reset(Mangled);
2461+
this->Search = Search;
2462+
this->Replace = Replace;
2463+
}
2464+
2465+
void reset(llvm::StringRef Mangled) { ManglingSubstitutor::reset(Mangled); }
2466+
2467+
llvm::itanium_demangle::Node *
2468+
parseCtorDtorName(llvm::itanium_demangle::Node *&SoFar, NameState *State) {
2469+
if (!Search.empty() && !Replace.empty()) {
2470+
trySubstitute(Search, Replace);
2471+
} else {
2472+
trySubstitute("D1", "D2");
2473+
trySubstitute("C1", "C2");
2474+
}
2475+
return ManglingSubstitutor::parseCtorDtorName(SoFar, State);
2476+
}
2477+
};
2478+
} // namespace
2479+
2480+
llvm::Expected<ConstString>
2481+
CPlusPlusLanguage::SubstituteType_ItaniumMangle(llvm::StringRef mangled_name,
2482+
llvm::StringRef subst_from,
2483+
llvm::StringRef subst_to) {
2484+
return TypeSubstitutor().substitute(mangled_name, subst_from, subst_to);
2485+
}
2486+
2487+
llvm::Expected<ConstString> CPlusPlusLanguage::SubstituteStructor_ItaniumMangle(
2488+
llvm::StringRef mangled_name, llvm::StringRef subst_from,
2489+
llvm::StringRef subst_to) {
2490+
return CtorDtorSubstitutor().substitute(mangled_name, subst_from, subst_to);
2491+
}
2492+
2493+
llvm::Expected<ConstString>
2494+
CPlusPlusLanguage::SubstituteStructorAliases_ItaniumMangle(
2495+
llvm::StringRef mangled_name) {
2496+
return CtorDtorSubstitutor().substitute(mangled_name);
2497+
}
2498+
24452499
#define LLDB_PROPERTIES_language_cplusplus
24462500
#include "LanguageCPlusPlusProperties.inc"
24472501

0 commit comments

Comments
 (0)