Skip to content

Commit 7310403

Browse files
tmiaskodwblaikie
authored andcommitted
[demangler] Initial support for the new Rust mangling scheme
Add a demangling support for a small subset of a new Rust mangling scheme, with complete support planned as a follow up work. Intergate Rust demangling into llvm-cxxfilt and use llvm-cxxfilt for end-to-end testing. The new Rust mangling scheme uses "_R" as a prefix, which makes it easy to disambiguate it from other mangling schemes. The public API is modeled after __cxa_demangle / llvm::itaniumDemangle, since potential candidates for further integration use those. Reviewed By: dblaikie Differential Revision: https://reviews.llvm.org/D101444
1 parent 73332d7 commit 7310403

File tree

8 files changed

+537
-0
lines changed

8 files changed

+537
-0
lines changed

llvm/include/llvm/Demangle/Demangle.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ char *microsoftDemangle(const char *mangled_name, size_t *n_read,
5757
char *buf, size_t *n_buf,
5858
int *status, MSDemangleFlags Flags = MSDF_None);
5959

60+
// Demangles a Rust v0 mangled symbol. The API follows that of __cxa_demangle.
61+
char *rustDemangle(const char *MangledName, char *Buf, size_t *N, int *Status);
62+
6063
/// Attempt to demangle a string using different demangling schemes.
6164
/// The function uses heuristics to determine which demangling scheme to use.
6265
/// \param MangledName - reference to string to demangle.
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
//===--- RustDemangle.h -----------------------------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLVM_DEMANGLE_RUSTDEMANGLE_H
10+
#define LLVM_DEMANGLE_RUSTDEMANGLE_H
11+
12+
#include "llvm/Demangle/DemangleConfig.h"
13+
#include "llvm/Demangle/StringView.h"
14+
#include "llvm/Demangle/Utility.h"
15+
16+
namespace llvm {
17+
namespace rust_demangle {
18+
19+
using llvm::itanium_demangle::OutputStream;
20+
using llvm::itanium_demangle::StringView;
21+
22+
struct Identifier {
23+
StringView Name;
24+
bool Punycode;
25+
26+
bool empty() const { return Name.empty(); }
27+
};
28+
29+
class Demangler {
30+
// Maximum recursion level. Used to avoid stack overflow.
31+
size_t MaxRecursionLevel;
32+
// Current recursion level.
33+
size_t RecursionLevel;
34+
35+
// Input string that is being demangled with "_R" prefix removed.
36+
StringView Input;
37+
// Position in the input string.
38+
size_t Position;
39+
40+
// True if an error occurred.
41+
bool Error;
42+
43+
public:
44+
// Demangled output.
45+
OutputStream Output;
46+
47+
Demangler(size_t MaxRecursionLevel = 500);
48+
49+
bool demangle(StringView MangledName);
50+
51+
private:
52+
void demanglePath();
53+
54+
Identifier parseIdentifier();
55+
void parseOptionalBase62Number(char Tag);
56+
uint64_t parseBase62Number();
57+
uint64_t parseDecimalNumber();
58+
59+
void print(StringView S) {
60+
if (Error)
61+
return;
62+
63+
Output += S;
64+
}
65+
66+
char look() const {
67+
if (Error || Position >= Input.size())
68+
return 0;
69+
70+
return Input[Position];
71+
}
72+
73+
char consume() {
74+
if (Error || Position >= Input.size()) {
75+
Error = true;
76+
return 0;
77+
}
78+
79+
return Input[Position++];
80+
}
81+
82+
bool consumeIf(char Prefix) {
83+
if (Error || Position >= Input.size() || Input[Position] != Prefix)
84+
return false;
85+
86+
Position += 1;
87+
return true;
88+
}
89+
90+
/// Computes A + B. When computation wraps around sets the error and returns
91+
/// false. Otherwise assigns the result to A and returns true.
92+
bool addAssign(uint64_t &A, const uint64_t B) {
93+
if (A > std::numeric_limits<uint64_t>::max() - B) {
94+
Error = true;
95+
return false;
96+
}
97+
98+
A += B;
99+
return true;
100+
}
101+
102+
/// Computes A * B. When computation wraps around sets the error and returns
103+
/// false. Otherwise assigns the result to A and returns true.
104+
bool mulAssign(uint64_t &A, const uint64_t B) {
105+
if (B != 0 && A > std::numeric_limits<uint64_t>::max() / B) {
106+
Error = true;
107+
return false;
108+
}
109+
110+
A *= B;
111+
return true;
112+
}
113+
};
114+
115+
} // namespace rust_demangle
116+
} // namespace llvm
117+
118+
#endif

llvm/lib/Demangle/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ add_llvm_component_library(LLVMDemangle
33
ItaniumDemangle.cpp
44
MicrosoftDemangle.cpp
55
MicrosoftDemangleNodes.cpp
6+
RustDemangle.cpp
67

78
ADDITIONAL_HEADER_DIRS
89
"${LLVM_MAIN_INCLUDE_DIR}/llvm/Demangle"

0 commit comments

Comments
 (0)