Branch data Line data Source code
1 : : // Copyright (C) 2020-2025 Free Software Foundation, Inc.
2 : :
3 : : // This file is part of GCC.
4 : :
5 : : // GCC is free software; you can redistribute it and/or modify it under
6 : : // the terms of the GNU General Public License as published by the Free
7 : : // Software Foundation; either version 3, or (at your option) any later
8 : : // version.
9 : :
10 : : // GCC is distributed in the hope that it will be useful, but WITHOUT ANY
11 : : // WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 : : // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 : : // for more details.
14 : :
15 : : // You should have received a copy of the GNU General Public License
16 : : // along with GCC; see the file COPYING3. If not see
17 : : // <http://www.gnu.org/licenses/>.
18 : :
19 : : #include "rust-mangle.h"
20 : : #include "fnv-hash.h"
21 : : #include "rust-unicode.h"
22 : : #include "rust-diagnostics.h"
23 : : #include "rust-system.h"
24 : :
25 : : namespace Rust {
26 : : namespace Compile {
27 : :
28 : : const std::string kLegacySymbolPrefix = "_ZN";
29 : : static const std::string kLegacySymbolDelim = "E";
30 : : static const std::string kLegacyGenericDelim = "$C$";
31 : : static const std::string kLegacySubstBegin = "$LT$";
32 : : static const std::string kLegacySubstEnd = "$GT$";
33 : : static const std::string kLegacySpace = "$u20$";
34 : : static const std::string kLegacyRef = "$RF$";
35 : : static const std::string kLegacyPtr = "$BP$";
36 : : static const std::string kLegacyLeftSqParen = "$u5b$"; // [
37 : : static const std::string kLegacyRightSqParen = "$u5d$"; // ]
38 : : static const std::string kLegacyLeftBrace = "$u7b$"; // {
39 : : static const std::string kLegacyRightBrace = "$u7d$"; // }
40 : : static const std::string kQualPathBegin = "_" + kLegacySubstBegin;
41 : : static const std::string kLegacyComma = "$C$";
42 : :
43 : : static std::string
44 : 83733 : legacy_mangle_name (const std::string &name)
45 : : {
46 : : // example
47 : : // <&T as core::fmt::Debug>::fmt:
48 : : // _ZN42_$LT$$RF$T$u20$as$u20$core..fmt..Debug$GT$3fmt17h6dac924c0051eef7E
49 : : // replace all white space with $ and & with RF
50 : : //
51 : : // <example::Bar as example::A>::fooA:
52 : : // _ZN43_$LT$example..Bar$u20$as$u20$example..A$GT$4fooA17hfc615fa76c7db7a0E:
53 : : //
54 : : // core::ptr::const_ptr::<impl *const T>::cast:
55 : : // _ZN4core3ptr9const_ptr33_$LT$impl$u20$$BP$const$u20$T$GT$4cast17hb79f4617226f1d55E:
56 : : //
57 : : // core::ptr::const_ptr::<impl *const [T]>::as_ptr:
58 : : // _ZN4core3ptr9const_ptr43_$LT$impl$u20$$BP$const$u20$$u5b$T$u5d$$GT$6as_ptr17he16e0dcd9473b04fE:
59 : : //
60 : : // example::Foo<T>::new:
61 : : // _ZN7example12Foo$LT$T$GT$3new17h9a2aacb7fd783515E:
62 : : //
63 : : // <example::Identity as example::FnLike<&T,&T>>::call
64 : : // _ZN74_$LT$example..Identity$u20$as$u20$example..FnLike$LT$$RF$T$C$$RF$T$GT$$GT$4call17ha9ee58935895acb3E
65 : :
66 : 83733 : tl::optional<Utf8String> utf8_name = Utf8String::make_utf8_string (name);
67 : 83733 : rust_assert (utf8_name.has_value ());
68 : 83733 : std::vector<Codepoint> chars = utf8_name.value ().get_chars ();
69 : 83733 : std::string buffer;
70 : 1146621 : for (size_t i = 0; i < chars.size (); i++)
71 : : {
72 : 1062888 : std::string m;
73 : 1062888 : Codepoint c = chars.at (i);
74 : :
75 : 1062888 : if (c == ' ')
76 : 13880 : m = kLegacySpace;
77 : 1049008 : else if (c == '&')
78 : 300 : m = kLegacyRef;
79 : 1048708 : else if (i == 0 && c == '<')
80 : 10796 : m = kQualPathBegin;
81 : 1037912 : else if (c == '<')
82 : 1654 : m = kLegacySubstBegin;
83 : 1036258 : else if (c == '>')
84 : 12450 : m = kLegacySubstEnd;
85 : 1023808 : else if (c == '*')
86 : 378 : m = kLegacyPtr;
87 : 1023430 : else if (c == '[')
88 : 394 : m = kLegacyLeftSqParen;
89 : 1023036 : else if (c == ']')
90 : 394 : m = kLegacyRightSqParen;
91 : 1022642 : else if (c == '{')
92 : 106 : m = kLegacyLeftBrace;
93 : 1022536 : else if (c == '}')
94 : 106 : m = kLegacyRightBrace;
95 : 1022430 : else if (c == ',')
96 : 198 : m = kLegacyComma;
97 : 1022232 : else if (c == ':')
98 : : {
99 : 10693 : rust_assert (i + 1 < chars.size ());
100 : 10693 : rust_assert (chars.at (i + 1) == ':');
101 : 10693 : i++;
102 : 10693 : m = "..";
103 : : }
104 : 1011539 : else if (c.is_ascii ())
105 : : // ASCII
106 : 1011539 : m.push_back (c.value);
107 : : else
108 : : {
109 : : // Non-ASCII
110 : 0 : std::stringstream escaped;
111 : 0 : escaped << std::hex << "$u" << c.value << "$";
112 : 0 : m += escaped.str ();
113 : 0 : }
114 : 2125776 : buffer += m;
115 : 1062888 : }
116 : :
117 : 83733 : return std::to_string (buffer.size ()) + buffer;
118 : 83733 : }
119 : :
120 : : static std::string
121 : 28488 : legacy_mangle_canonical_path (const Resolver::CanonicalPath &path)
122 : : {
123 : 28488 : std::string buffer;
124 : 83733 : for (size_t i = 0; i < path.size (); i++)
125 : : {
126 : 55245 : auto &seg = path.get_seg_at (i);
127 : 110490 : buffer += legacy_mangle_name (seg.second);
128 : : }
129 : 28488 : return buffer;
130 : : }
131 : :
132 : : // rustc uses a sip128 hash for legacy mangling, but an fnv 128 was quicker to
133 : : // implement for now
134 : : static std::string
135 : 28488 : legacy_hash (const std::string &fingerprint)
136 : : {
137 : 28488 : Hash::FNV128 hasher;
138 : 28488 : hasher.write ((const unsigned char *) fingerprint.c_str (),
139 : : fingerprint.size ());
140 : :
141 : 28488 : uint64_t hi, lo;
142 : 28488 : hasher.sum (&hi, &lo);
143 : :
144 : 28488 : char hex[16 + 1];
145 : 28488 : memset (hex, 0, sizeof hex);
146 : 28488 : snprintf (hex, sizeof hex, "%08" PRIx64 "%08" PRIx64, lo, hi);
147 : :
148 : 28488 : return "h" + std::string (hex, sizeof (hex) - 1);
149 : : }
150 : :
151 : : std::string
152 : 28488 : legacy_mangle_item (const TyTy::BaseType *ty,
153 : : const Resolver::CanonicalPath &path)
154 : : {
155 : 28488 : const std::string hash = legacy_hash (ty->mangle_string ());
156 : 28488 : const std::string hash_sig = legacy_mangle_name (hash);
157 : :
158 : 56976 : return kLegacySymbolPrefix + legacy_mangle_canonical_path (path) + hash_sig
159 : 28488 : + kLegacySymbolDelim;
160 : 28488 : }
161 : :
162 : : } // namespace Compile
163 : : } // namespace Rust
|