aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Demangle/RustDemangle.cpp
diff options
context:
space:
mode:
authorTomasz Miąsko <tomasz.miasko@gmail.com>2021-06-23 15:59:24 +0200
committerTomasz Miąsko <tomasz.miasko@gmail.com>2021-06-23 18:28:16 +0200
commit6cc6ada143236f16faf8b383d73e00e709fa6a9f (patch)
treee60e7eae3096cfd311f7fb08bc7768f2a05aedda /llvm/lib/Demangle/RustDemangle.cpp
parentb58dfd87da5cb19693764869a9a158f88c3d4bde (diff)
downloadllvm-6cc6ada143236f16faf8b383d73e00e709fa6a9f.zip
llvm-6cc6ada143236f16faf8b383d73e00e709fa6a9f.tar.gz
llvm-6cc6ada143236f16faf8b383d73e00e709fa6a9f.tar.bz2
[Demangle][Rust] Hide implementation details NFC
Move content of the "public" header into the implementation file. This also renames two enumerations that were previously used through `rust_demangle::` scope, to avoid breaking a build bot with older version of GCC that rejects uses of enumerator through `E::A` if there is a variable with the same name as enumeration `E` in the scope. Reviewed By: dblaikie Differential Revision: https://reviews.llvm.org/D104362
Diffstat (limited to 'llvm/lib/Demangle/RustDemangle.cpp')
-rw-r--r--llvm/lib/Demangle/RustDemangle.cpp217
1 files changed, 205 insertions, 12 deletions
diff --git a/llvm/lib/Demangle/RustDemangle.cpp b/llvm/lib/Demangle/RustDemangle.cpp
index 39db8fd..f916300 100644
--- a/llvm/lib/Demangle/RustDemangle.cpp
+++ b/llvm/lib/Demangle/RustDemangle.cpp
@@ -11,16 +11,140 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/Demangle/RustDemangle.h"
#include "llvm/Demangle/Demangle.h"
+#include "llvm/Demangle/StringView.h"
+#include "llvm/Demangle/Utility.h"
#include <algorithm>
#include <cassert>
+#include <cstdint>
#include <cstring>
#include <limits>
using namespace llvm;
-using namespace rust_demangle;
+
+using llvm::itanium_demangle::OutputStream;
+using llvm::itanium_demangle::StringView;
+using llvm::itanium_demangle::SwapAndRestore;
+
+namespace {
+
+struct Identifier {
+ StringView Name;
+ bool Punycode;
+
+ bool empty() const { return Name.empty(); }
+};
+
+enum class BasicType {
+ Bool,
+ Char,
+ I8,
+ I16,
+ I32,
+ I64,
+ I128,
+ ISize,
+ U8,
+ U16,
+ U32,
+ U64,
+ U128,
+ USize,
+ F32,
+ F64,
+ Str,
+ Placeholder,
+ Unit,
+ Variadic,
+ Never,
+};
+
+enum class IsInType {
+ No,
+ Yes,
+};
+
+enum class LeaveGenericsOpen {
+ No,
+ Yes,
+};
+
+class Demangler {
+ // Maximum recursion level. Used to avoid stack overflow.
+ size_t MaxRecursionLevel;
+ // Current recursion level.
+ size_t RecursionLevel;
+ size_t BoundLifetimes;
+ // Input string that is being demangled with "_R" prefix removed.
+ StringView Input;
+ // Position in the input string.
+ size_t Position;
+ // When true, print methods append the output to the stream.
+ // When false, the output is suppressed.
+ bool Print;
+ // True if an error occurred.
+ bool Error;
+
+public:
+ // Demangled output.
+ OutputStream Output;
+
+ Demangler(size_t MaxRecursionLevel = 500);
+
+ bool demangle(StringView MangledName);
+
+private:
+ bool demanglePath(IsInType Type,
+ LeaveGenericsOpen LeaveOpen = LeaveGenericsOpen::No);
+ void demangleImplPath(IsInType InType);
+ void demangleGenericArg();
+ void demangleType();
+ void demangleFnSig();
+ void demangleDynBounds();
+ void demangleDynTrait();
+ void demangleOptionalBinder();
+ void demangleConst();
+ void demangleConstInt();
+ void demangleConstBool();
+ void demangleConstChar();
+
+ template <typename Callable> void demangleBackref(Callable Demangler) {
+ uint64_t Backref = parseBase62Number();
+ if (Error || Backref >= Position) {
+ Error = true;
+ return;
+ }
+
+ if (!Print)
+ return;
+
+ SwapAndRestore<size_t> SavePosition(Position, Position);
+ Position = Backref;
+ Demangler();
+ }
+
+ Identifier parseIdentifier();
+ uint64_t parseOptionalBase62Number(char Tag);
+ uint64_t parseBase62Number();
+ uint64_t parseDecimalNumber();
+ uint64_t parseHexNumber(StringView &HexDigits);
+
+ void print(char C);
+ void print(StringView S);
+ void printDecimalNumber(uint64_t N);
+ void printBasicType(BasicType);
+ void printLifetime(uint64_t Index);
+
+ char look() const;
+ char consume();
+ bool consumeIf(char Prefix);
+
+ bool addAssign(uint64_t &A, uint64_t B);
+ bool mulAssign(uint64_t &A, uint64_t B);
+};
+
+} // namespace
char *llvm::rustDemangle(const char *MangledName, char *Buf, size_t *N,
int *Status) {
@@ -113,11 +237,11 @@ bool Demangler::demangle(StringView Mangled) {
Input = Mangled.substr(0, Dot);
StringView Suffix = Mangled.dropFront(Dot);
- demanglePath(rust_demangle::InType::No);
+ demanglePath(IsInType::No);
if (Position != Input.size()) {
SwapAndRestore<bool> SavePrint(Print, false);
- demanglePath(InType::No);
+ demanglePath(IsInType::No);
}
if (Position != Input.size())
@@ -149,7 +273,7 @@ bool Demangler::demangle(StringView Mangled) {
// | "S" // shim
// | <A-Z> // other special namespaces
// | <a-z> // internal namespaces
-bool Demangler::demanglePath(InType InType, LeaveOpen LeaveOpen) {
+bool Demangler::demanglePath(IsInType InType, LeaveGenericsOpen LeaveOpen) {
if (Error || RecursionLevel >= MaxRecursionLevel) {
Error = true;
return false;
@@ -175,7 +299,7 @@ bool Demangler::demanglePath(InType InType, LeaveOpen LeaveOpen) {
print("<");
demangleType();
print(" as ");
- demanglePath(rust_demangle::InType::Yes);
+ demanglePath(IsInType::Yes);
print(">");
break;
}
@@ -183,7 +307,7 @@ bool Demangler::demanglePath(InType InType, LeaveOpen LeaveOpen) {
print("<");
demangleType();
print(" as ");
- demanglePath(rust_demangle::InType::Yes);
+ demanglePath(IsInType::Yes);
print(">");
break;
}
@@ -226,7 +350,7 @@ bool Demangler::demanglePath(InType InType, LeaveOpen LeaveOpen) {
case 'I': {
demanglePath(InType);
// Omit "::" when in a type, where it is optional.
- if (InType == rust_demangle::InType::No)
+ if (InType == IsInType::No)
print("::");
print("<");
for (size_t I = 0; !Error && !consumeIf('E'); ++I) {
@@ -234,7 +358,7 @@ bool Demangler::demanglePath(InType InType, LeaveOpen LeaveOpen) {
print(", ");
demangleGenericArg();
}
- if (LeaveOpen == rust_demangle::LeaveOpen::Yes)
+ if (LeaveOpen == LeaveGenericsOpen::Yes)
return true;
else
print(">");
@@ -255,7 +379,7 @@ bool Demangler::demanglePath(InType InType, LeaveOpen LeaveOpen) {
// <impl-path> = [<disambiguator>] <path>
// <disambiguator> = "s" <base-62-number>
-void Demangler::demangleImplPath(InType InType) {
+void Demangler::demangleImplPath(IsInType InType) {
SwapAndRestore<bool> SavePrint(Print, false);
parseOptionalBase62Number('s');
demanglePath(InType);
@@ -524,7 +648,7 @@ void Demangler::demangleType() {
break;
default:
Position = Start;
- demanglePath(rust_demangle::InType::Yes);
+ demanglePath(IsInType::Yes);
break;
}
}
@@ -586,7 +710,7 @@ void Demangler::demangleDynBounds() {
// <dyn-trait> = <path> {<dyn-trait-assoc-binding>}
// <dyn-trait-assoc-binding> = "p" <undisambiguated-identifier> <type>
void Demangler::demangleDynTrait() {
- bool IsOpen = demanglePath(InType::Yes, LeaveOpen::Yes);
+ bool IsOpen = demanglePath(IsInType::Yes, LeaveGenericsOpen::Yes);
while (!Error && consumeIf('p')) {
if (!IsOpen) {
IsOpen = true;
@@ -908,6 +1032,27 @@ uint64_t Demangler::parseHexNumber(StringView &HexDigits) {
return Value;
}
+void Demangler::print(char C) {
+ if (Error || !Print)
+ return;
+
+ Output += C;
+}
+
+void Demangler::print(StringView S) {
+ if (Error || !Print)
+ return;
+
+ Output += S;
+}
+
+void Demangler::printDecimalNumber(uint64_t N) {
+ if (Error || !Print)
+ return;
+
+ Output << N;
+}
+
// Prints a lifetime. An index 0 always represents an erased lifetime. Indices
// starting from 1, are De Bruijn indices, referring to higher-ranked lifetimes
// bound by one of the enclosing binders.
@@ -932,3 +1077,51 @@ void Demangler::printLifetime(uint64_t Index) {
printDecimalNumber(Depth - 26 + 1);
}
}
+
+char Demangler::look() const {
+ if (Error || Position >= Input.size())
+ return 0;
+
+ return Input[Position];
+}
+
+char Demangler::consume() {
+ if (Error || Position >= Input.size()) {
+ Error = true;
+ return 0;
+ }
+
+ return Input[Position++];
+}
+
+bool Demangler::consumeIf(char Prefix) {
+ if (Error || Position >= Input.size() || Input[Position] != Prefix)
+ return false;
+
+ Position += 1;
+ return true;
+}
+
+/// Computes A + B. When computation wraps around sets the error and returns
+/// false. Otherwise assigns the result to A and returns true.
+bool Demangler::addAssign(uint64_t &A, uint64_t B) {
+ if (A > std::numeric_limits<uint64_t>::max() - B) {
+ Error = true;
+ return false;
+ }
+
+ A += B;
+ return true;
+}
+
+/// Computes A * B. When computation wraps around sets the error and returns
+/// false. Otherwise assigns the result to A and returns true.
+bool Demangler::mulAssign(uint64_t &A, uint64_t B) {
+ if (B != 0 && A > std::numeric_limits<uint64_t>::max() / B) {
+ Error = true;
+ return false;
+ }
+
+ A *= B;
+ return true;
+}