LCOV - code coverage report
Current view: top level - gcc/rust/backend - rust-mangle-legacy.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 84.8 % 66 56
Test Date: 2026-02-28 14:20:25 Functions: 100.0 % 4 4
Legend: Lines:     hit not hit

            Line data    Source code
       1              : // Copyright (C) 2020-2026 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       104712 : 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       104712 :   tl::optional<Utf8String> utf8_name = Utf8String::make_utf8_string (name);
      67       104712 :   rust_assert (utf8_name.has_value ());
      68       104712 :   std::vector<Codepoint> chars = utf8_name.value ().get_chars ();
      69       104712 :   std::string buffer;
      70      1583672 :   for (size_t i = 0; i < chars.size (); i++)
      71              :     {
      72      1478960 :       std::string m;
      73      1478960 :       Codepoint c = chars.at (i);
      74              : 
      75      1478960 :       if (c == ' ')
      76        36341 :         m = kLegacySpace;
      77      1442619 :       else if (c == '&')
      78            0 :         m = kLegacyRef;
      79      1442619 :       else if (i == 0 && c == '<')
      80        16487 :         m = kQualPathBegin;
      81      1426132 :       else if (c == '<')
      82            0 :         m = kLegacySubstBegin;
      83      1426132 :       else if (c == '>')
      84        16487 :         m = kLegacySubstEnd;
      85      1409645 :       else if (c == '*')
      86            0 :         m = kLegacyPtr;
      87      1409645 :       else if (c == '[')
      88            0 :         m = kLegacyLeftSqParen;
      89      1409645 :       else if (c == ']')
      90            0 :         m = kLegacyRightSqParen;
      91      1409645 :       else if (c == '{')
      92          120 :         m = kLegacyLeftBrace;
      93      1409525 :       else if (c == '}')
      94          120 :         m = kLegacyRightBrace;
      95      1409405 :       else if (c == ',')
      96            0 :         m = kLegacyComma;
      97      1409405 :       else if (c == ':')
      98              :         {
      99        21949 :           rust_assert (i + 1 < chars.size ());
     100        21949 :           rust_assert (chars.at (i + 1) == ':');
     101        21949 :           i++;
     102        21949 :           m = "..";
     103              :         }
     104      1387456 :       else if (c.is_ascii ())
     105              :         // ASCII
     106      1387456 :         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      2957920 :       buffer += m;
     115      1478960 :     }
     116              : 
     117       104712 :   return std::to_string (buffer.size ()) + buffer;
     118       104712 : }
     119              : 
     120              : static std::string
     121        29690 : legacy_mangle_canonical_path (const Resolver::CanonicalPath &path)
     122              : {
     123        29690 :   std::string buffer;
     124       104712 :   for (size_t i = 0; i < path.size (); i++)
     125              :     {
     126        75022 :       auto &seg = path.get_seg_at (i);
     127       150044 :       buffer += legacy_mangle_name (seg.second);
     128              :     }
     129        29690 :   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        29690 : legacy_hash (const std::string &fingerprint)
     136              : {
     137        29690 :   Hash::FNV128 hasher;
     138        29690 :   hasher.write ((const unsigned char *) fingerprint.c_str (),
     139              :                 fingerprint.size ());
     140              : 
     141        29690 :   uint64_t hi, lo;
     142        29690 :   hasher.sum (&hi, &lo);
     143              : 
     144        29690 :   char hex[16 + 1];
     145        29690 :   memset (hex, 0, sizeof hex);
     146        29690 :   snprintf (hex, sizeof hex, "%08" PRIx64 "%08" PRIx64, lo, hi);
     147              : 
     148        29690 :   return "h" + std::string (hex, sizeof (hex) - 1);
     149              : }
     150              : 
     151              : std::string
     152        29690 : legacy_mangle_item (const TyTy::BaseType *ty,
     153              :                     const Resolver::CanonicalPath &path)
     154              : {
     155        29690 :   const std::string hash = legacy_hash (ty->mangle_string ());
     156        29690 :   const std::string hash_sig = legacy_mangle_name (hash);
     157              : 
     158        59380 :   return kLegacySymbolPrefix + legacy_mangle_canonical_path (path) + hash_sig
     159        29690 :          + kLegacySymbolDelim;
     160        29690 : }
     161              : 
     162              : } // namespace Compile
     163              : } // namespace Rust
        

Generated by: LCOV version 2.4-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.