Skip to content

Commit 78e9491

Browse files
tmiaskodwblaikie
authored andcommitted
[Demangle][Rust] Print special namespaces
Reviewed By: dblaikie Differential Revision: https://reviews.llvm.org/D101821
1 parent be23d5e commit 78e9491

File tree

3 files changed

+80
-16
lines changed

3 files changed

+80
-16
lines changed

llvm/include/llvm/Demangle/RustDemangle.h

+17-1
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,14 @@
1212
#include "llvm/Demangle/DemangleConfig.h"
1313
#include "llvm/Demangle/StringView.h"
1414
#include "llvm/Demangle/Utility.h"
15+
#include <cstdint>
1516

1617
namespace llvm {
1718
namespace rust_demangle {
1819

1920
using llvm::itanium_demangle::OutputStream;
2021
using llvm::itanium_demangle::StringView;
22+
using llvm::itanium_demangle::SwapAndRestore;
2123

2224
struct Identifier {
2325
StringView Name;
@@ -52,17 +54,31 @@ class Demangler {
5254
void demanglePath();
5355

5456
Identifier parseIdentifier();
55-
void parseOptionalBase62Number(char Tag);
57+
uint64_t parseOptionalBase62Number(char Tag);
5658
uint64_t parseBase62Number();
5759
uint64_t parseDecimalNumber();
5860

61+
void print(char C) {
62+
if (Error)
63+
return;
64+
65+
Output += C;
66+
}
67+
5968
void print(StringView S) {
6069
if (Error)
6170
return;
6271

6372
Output += S;
6473
}
6574

75+
void printDecimalNumber(uint64_t N) {
76+
if (Error)
77+
return;
78+
79+
Output << N;
80+
}
81+
6682
char look() const {
6783
if (Error || Position >= Input.size())
6884
return 0;

llvm/lib/Demangle/RustDemangle.cpp

+34-15
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ void Demangler::demanglePath() {
132132
Error = true;
133133
return;
134134
}
135-
RecursionLevel += 1;
135+
SwapAndRestore<size_t> SaveRecursionLevel(RecursionLevel, RecursionLevel + 1);
136136

137137
switch (consume()) {
138138
case 'C': {
@@ -149,15 +149,31 @@ void Demangler::demanglePath() {
149149
}
150150
demanglePath();
151151

152-
parseOptionalBase62Number('s');
152+
uint64_t Disambiguator = parseOptionalBase62Number('s');
153153
Identifier Ident = parseIdentifier();
154154

155-
if (!Ident.empty()) {
156-
// FIXME print special namespaces:
157-
// * "C" closures
158-
// * "S" shim
159-
print("::");
160-
print(Ident.Name);
155+
if (isUpper(NS)) {
156+
// Special namespaces
157+
print("::{");
158+
if (NS == 'C')
159+
print("closure");
160+
else if (NS == 'S')
161+
print("shim");
162+
else
163+
print(NS);
164+
if (!Ident.empty()) {
165+
print(":");
166+
print(Ident.Name);
167+
}
168+
print('#');
169+
printDecimalNumber(Disambiguator);
170+
print('}');
171+
} else {
172+
// Implementation internal namespaces.
173+
if (!Ident.empty()) {
174+
print("::");
175+
print(Ident.Name);
176+
}
161177
}
162178
break;
163179
}
@@ -166,8 +182,6 @@ void Demangler::demanglePath() {
166182
Error = true;
167183
break;
168184
}
169-
170-
RecursionLevel -= 1;
171185
}
172186

173187
// <undisambiguated-identifier> = ["u"] <decimal-number> ["_"] <bytes>
@@ -195,11 +209,16 @@ Identifier Demangler::parseIdentifier() {
195209
}
196210

197211
// Parses optional base 62 number. The presence of a number is determined using
198-
// Tag.
199-
void Demangler::parseOptionalBase62Number(char Tag) {
200-
// Parsing result is currently unused.
201-
if (consumeIf(Tag))
202-
parseBase62Number();
212+
// Tag. Returns 0 when tag is absent and parsed value + 1 otherwise.
213+
uint64_t Demangler::parseOptionalBase62Number(char Tag) {
214+
if (!consumeIf(Tag))
215+
return 0;
216+
217+
uint64_t N = parseBase62Number();
218+
if (Error || !addAssign(N, 1))
219+
return 0;
220+
221+
return N;
203222
}
204223

205224
// Parses base 62 number with <0-9a-zA-Z> as digits. Number is terminated by

llvm/test/Demangle/rust.test

+29
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,30 @@ CHECK: hello::rust
99
CHECK: a::b::c
1010
_RNvNvC1a1b1c
1111

12+
; Closure namespace
13+
14+
CHECK: crate::{closure#0}
15+
_RNCC5crate0
16+
17+
CHECK: crate::{closure#1}
18+
_RNCC5crates_0
19+
20+
CHECK: crate::{closure:foo#0}
21+
_RNCC5crate3foo
22+
23+
CHECK: crate::{closure:foo#1}
24+
_RNCC5crates_3foo
25+
26+
; Shim namespace
27+
28+
CHECK: crate::{shim:reify#0}
29+
_RNSC5crate5reify
30+
31+
; Unrecognized special namespace
32+
33+
CHECK: crate::{Z:ident#10}
34+
_RNZC5crates8_5ident
35+
1236
; Invalid mangled characters
1337

1438
CHECK: _RNvC2a.1c
@@ -17,6 +41,11 @@ CHECK: _RNvC2a.1c
1741
CHECK: _RNvC2a$1c
1842
_RNvC2a$1c
1943

44+
; Invalid namespace (not in [a-zA-Z]).
45+
46+
CHECK: _RN_C5crate4main
47+
_RN_C5crate4main
48+
2049
; Invalid identifier length (UINT64_MAX + 3, which happens to be ok after a wraparound).
2150

2251
CHECK: _RNvC2ab18446744073709551618xy

0 commit comments

Comments
 (0)