Branch data Line data Source code
1 : : // Copyright (C) 2020-2024 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 : : #include <sstream>
25 : :
26 : : namespace Rust {
27 : : namespace Compile {
28 : :
29 : : const std::string kLegacySymbolPrefix = "_ZN";
30 : : static const std::string kLegacySymbolDelim = "E";
31 : : static const std::string kLegacyGenericDelim = "$C$";
32 : : static const std::string kLegacySubstBegin = "$LT$";
33 : : static const std::string kLegacySubstEnd = "$GT$";
34 : : static const std::string kLegacySpace = "$u20$";
35 : : static const std::string kLegacyRef = "$RF$";
36 : : static const std::string kLegacyPtr = "$BP$";
37 : : static const std::string kLegacyLeftSqParen = "$u5b$"; // [
38 : : static const std::string kLegacyRightSqParen = "$u5d$"; // ]
39 : : static const std::string kLegacyLeftBrace = "$u7b$"; // {
40 : : static const std::string kLegacyRightBrace = "$u7d$"; // }
41 : : static const std::string kQualPathBegin = "_" + kLegacySubstBegin;
42 : : static const std::string kLegacyComma = "$C$";
43 : :
44 : : static std::string
45 : 48803 : legacy_mangle_name (const std::string &name)
46 : : {
47 : : // example
48 : : // <&T as core::fmt::Debug>::fmt:
49 : : // _ZN42_$LT$$RF$T$u20$as$u20$core..fmt..Debug$GT$3fmt17h6dac924c0051eef7E
50 : : // replace all white space with $ and & with RF
51 : : //
52 : : // <example::Bar as example::A>::fooA:
53 : : // _ZN43_$LT$example..Bar$u20$as$u20$example..A$GT$4fooA17hfc615fa76c7db7a0E:
54 : : //
55 : : // core::ptr::const_ptr::<impl *const T>::cast:
56 : : // _ZN4core3ptr9const_ptr33_$LT$impl$u20$$BP$const$u20$T$GT$4cast17hb79f4617226f1d55E:
57 : : //
58 : : // core::ptr::const_ptr::<impl *const [T]>::as_ptr:
59 : : // _ZN4core3ptr9const_ptr43_$LT$impl$u20$$BP$const$u20$$u5b$T$u5d$$GT$6as_ptr17he16e0dcd9473b04fE:
60 : : //
61 : : // example::Foo<T>::new:
62 : : // _ZN7example12Foo$LT$T$GT$3new17h9a2aacb7fd783515E:
63 : : //
64 : : // <example::Identity as example::FnLike<&T,&T>>::call
65 : : // _ZN74_$LT$example..Identity$u20$as$u20$example..FnLike$LT$$RF$T$C$$RF$T$GT$$GT$4call17ha9ee58935895acb3E
66 : :
67 : 48803 : tl::optional<Utf8String> utf8_name = Utf8String::make_utf8_string (name);
68 : 48803 : rust_assert (utf8_name.has_value ());
69 : 48803 : std::vector<Codepoint> chars = utf8_name.value ().get_chars ();
70 : 48803 : std::string buffer;
71 : 672813 : for (size_t i = 0; i < chars.size (); i++)
72 : : {
73 : 624010 : std::string m;
74 : 624010 : Codepoint c = chars.at (i);
75 : :
76 : 624010 : if (c == ' ')
77 : 7850 : m = kLegacySpace;
78 : 616160 : else if (c == '&')
79 : 300 : m = kLegacyRef;
80 : 615860 : else if (i == 0 && c == '<')
81 : 6822 : m = kQualPathBegin;
82 : 609038 : else if (c == '<')
83 : 1406 : m = kLegacySubstBegin;
84 : 607632 : else if (c == '>')
85 : 8228 : m = kLegacySubstEnd;
86 : 599404 : else if (c == '*')
87 : 298 : m = kLegacyPtr;
88 : 599106 : else if (c == '[')
89 : 394 : m = kLegacyLeftSqParen;
90 : 598712 : else if (c == ']')
91 : 394 : m = kLegacyRightSqParen;
92 : 598318 : else if (c == '{')
93 : 102 : m = kLegacyLeftBrace;
94 : 598216 : else if (c == '}')
95 : 102 : m = kLegacyRightBrace;
96 : 598114 : else if (c == ',')
97 : 184 : m = kLegacyComma;
98 : 597930 : else if (c == ':')
99 : : {
100 : 7548 : rust_assert (i + 1 < chars.size ());
101 : 7548 : rust_assert (chars.at (i + 1) == ':');
102 : 7548 : i++;
103 : 7548 : m = "..";
104 : : }
105 : 590382 : else if (c.is_ascii ())
106 : : // ASCII
107 : 590382 : m.push_back (c.value);
108 : : else
109 : : {
110 : : // Non-ASCII
111 : 0 : std::stringstream escaped;
112 : 0 : escaped << std::hex << "$u" << c.value << "$";
113 : 0 : m += escaped.str ();
114 : 0 : }
115 : 624010 : buffer += m;
116 : 624010 : }
117 : :
118 : 48803 : return std::to_string (buffer.size ()) + buffer;
119 : 48803 : }
120 : :
121 : : static std::string
122 : 17082 : legacy_mangle_canonical_path (const Resolver::CanonicalPath &path)
123 : : {
124 : 17082 : std::string buffer;
125 : 48803 : for (size_t i = 0; i < path.size (); i++)
126 : : {
127 : 31721 : auto &seg = path.get_seg_at (i);
128 : 31721 : buffer += legacy_mangle_name (seg.second);
129 : : }
130 : 17082 : return buffer;
131 : : }
132 : :
133 : : // rustc uses a sip128 hash for legacy mangling, but an fnv 128 was quicker to
134 : : // implement for now
135 : : static std::string
136 : 17082 : legacy_hash (const std::string &fingerprint)
137 : : {
138 : 17082 : Hash::FNV128 hasher;
139 : 17082 : hasher.write ((const unsigned char *) fingerprint.c_str (),
140 : : fingerprint.size ());
141 : :
142 : 17082 : uint64_t hi, lo;
143 : 17082 : hasher.sum (&hi, &lo);
144 : :
145 : 17082 : char hex[16 + 1];
146 : 17082 : memset (hex, 0, sizeof hex);
147 : 17082 : snprintf (hex, sizeof hex, "%08" PRIx64 "%08" PRIx64, lo, hi);
148 : :
149 : 17082 : return "h" + std::string (hex, sizeof (hex) - 1);
150 : : }
151 : :
152 : : std::string
153 : 17082 : legacy_mangle_item (const TyTy::BaseType *ty,
154 : : const Resolver::CanonicalPath &path)
155 : : {
156 : 17082 : const std::string hash = legacy_hash (ty->mangle_string ());
157 : 17082 : const std::string hash_sig = legacy_mangle_name (hash);
158 : :
159 : 34164 : return kLegacySymbolPrefix + legacy_mangle_canonical_path (path) + hash_sig
160 : 17082 : + kLegacySymbolDelim;
161 : 17082 : }
162 : :
163 : : } // namespace Compile
164 : : } // namespace Rust
|