From patchwork Tue Jan 30 12:07:35 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arthur Cohen X-Patchwork-Id: 84986 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id E9B19385E44F for ; Tue, 30 Jan 2024 12:37:59 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-wm1-x32c.google.com (mail-wm1-x32c.google.com [IPv6:2a00:1450:4864:20::32c]) by sourceware.org (Postfix) with ESMTPS id E6CA33857B97 for ; Tue, 30 Jan 2024 12:11:49 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org E6CA33857B97 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=embecosm.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=embecosm.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org E6CA33857B97 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2a00:1450:4864:20::32c ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1706616755; cv=none; b=Xo7pr0pI4h5kMA2AFLThaQZGlpaagzHn/SMZVTY+Wlu5pP+MCIoQfoeA//u3VBo0mKkqs2uQ8RbZ0yxgRgAxssa05G5z0ZE5gXpF9a4F4CW3shaqe1GGryxYe8cY+cDsEGqpepuShliksIOpCY10iz1x1HoIG90oKuLmLStNwes= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1706616755; c=relaxed/simple; bh=eF70jmtYtBKboAvdli2mQum0OvM6rWgKaGYE44Aqr0Y=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=We8dnWfeQzyP/mdgRkkhZVhVO0BLihSvhtK0dlK6vR/29V6eRntD/DnDVCMuLZjqZEKJfSTC0YK51JgtM21qceUCcl99vFrgo8OChnmFfsqEydYiHcXWtFnj9FCXLzhHLFPk3GQdq/Da4W05aGNJdQEnUXi6U6ZOSI1mFP75uac= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-wm1-x32c.google.com with SMTP id 5b1f17b1804b1-40faff092a2so525895e9.2 for ; Tue, 30 Jan 2024 04:11:49 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=embecosm.com; s=google; t=1706616708; x=1707221508; darn=gcc.gnu.org; h=content-transfer-encoding:mime-version:reply-to:references :in-reply-to:message-id:date:subject:cc:to:from:from:to:cc:subject :date:message-id:reply-to; bh=Xy1jbWBq/jS2DmecsSURumawZ9HzroE4Y1MAgZtpQHM=; b=Kb5Q9o6EgJVWHzL7+bg/Rb8nbldARaN1E3OHhvxbk8bk6MrEWSdVLmE8Ac2hpQSB/x L68R/01tna5hM213TCajUK9IbyItI71xA1SSuS/e01Op2eQLxTsSpXIFc4fyQZ9jxfFm eZBZHSDi430LVNBAo8+DmASHvq4qaGPFGRhSce+qUZ+XIfJV/VkBOY1kp3HNQyrOQoC8 8CqZiJrUtxjgxtZJLF0xXdgL3lmQxwSaUyscq4kFEIrXUk+1FzZKzvLkgPcmtOs/32h/ +radK5k1iagHlzy103aIUREAAPbqbVoe3FjVpqHfA4PxXN5PN46peRED9C/ZropvwLhw ByAw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1706616708; x=1707221508; h=content-transfer-encoding:mime-version:reply-to:references :in-reply-to:message-id:date:subject:cc:to:from:x-gm-message-state :from:to:cc:subject:date:message-id:reply-to; bh=Xy1jbWBq/jS2DmecsSURumawZ9HzroE4Y1MAgZtpQHM=; b=iUatp56Lim+ypwYIPgDaPTUOwP9NtIbqQasmQAWns2T7VfIJc0mR7uX2+h7eBlhLN6 +YPk92HdK1It0avzHw6OnkPk6N94nMcRkX15WqVRrCbL2TnhUI4ELIvkPW8UF7LvTVXA AJ7/X/jG8+PDDmOjUKFFSXikRKXuInwaLeK0H/f0orJfup6UbnQYul3OF6n9qsZwvgXU op6cBASboYMEk/XJN9O97fdru7XQtlEA4G4eE/QbmhU4PtiiJqpqGJfzlYOEJwpVKP4X E7wwX3A/G388p69ruexeEDasyJnn5mHQTF516PqKgMx3PsXRyereO4BFxc28I9kfegmE cDbQ== X-Gm-Message-State: AOJu0YzGMCzUTpIi5PtSZLEbIpENoFfuc8oRBebAPxiJ3xJu9xNvG9eb eN+/n2v5yUQ2DPPj9dLnbpzGwIr6xLx6tDmrSAPF8JkOjcOBmlhz9hfSG6l8AQKApT+X0jhW30D kIw== X-Google-Smtp-Source: AGHT+IE00U2IqdMfR+UglHCbetvcCv1p9buI1AaBe/W8AN54LS5cI8RtNzEqHPRy/AOpmiwJAMO1zg== X-Received: by 2002:a05:6000:1565:b0:33a:f0c5:2a00 with SMTP id 5-20020a056000156500b0033af0c52a00mr3880791wrz.61.1706616707905; Tue, 30 Jan 2024 04:11:47 -0800 (PST) Received: from platypus.localdomain ([62.23.166.218]) by smtp.gmail.com with ESMTPSA id f9-20020a056000036900b00339307d9d31sm10569894wrf.112.2024.01.30.04.11.47 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 30 Jan 2024 04:11:47 -0800 (PST) From: arthur.cohen@embecosm.com To: gcc-patches@gcc.gnu.org Cc: gcc-rust@gcc.gnu.org, Raiki Tamura Subject: [COMMITTED 079/101] gccrs: split rust-mangle.cc into two files Date: Tue, 30 Jan 2024 13:07:35 +0100 Message-ID: <20240130121026.807464-82-arthur.cohen@embecosm.com> X-Mailer: git-send-email 2.42.1 In-Reply-To: <20240130121026.807464-2-arthur.cohen@embecosm.com> References: <20240130121026.807464-2-arthur.cohen@embecosm.com> MIME-Version: 1.0 X-Spam-Status: No, score=-14.1 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: arthur.cohen@embecosm.com Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org From: Raiki Tamura gcc/rust/ChangeLog: * Make-lang.in: Add .o files * backend/rust-mangle.cc (struct V0Path): moved to splitted files (v0_path): Likewise. (legacy_mangle_name): Likewise. (legacy_mangle_canonical_path): Likewise. (legacy_hash): Likewise. (v0_tuple_prefix): Likewise. (v0_numeric_prefix): Likewise. (v0_simple_type_prefix): Likewise. (v0_complex_type_prefix): Likewise. (v0_integer_62): Likewise. (v0_opt_integer_62): Likewise. (v0_disambiguator): Likewise. (v0_type_prefix): Likewise. (v0_generic_args): Likewise. (v0_identifier): Likewise. (v0_type_path): Likewise. (v0_function_path): Likewise. (v0_scope_path): Likewise. (v0_crate_path): Likewise. (v0_inherent_or_trait_impl_path): Likewise. (v0_closure): Likewise. (legacy_mangle_item): Likewise. (v0_mangle_item): Likewise. * backend/rust-mangle.h (legacy_mangle_item): Likewise. (v0_mangle_item): Likewise. * backend/rust-mangle-legacy.cc: New file. * backend/rust-mangle-v0.cc: New file. Signed-off-by: Raiki Tamura --- gcc/rust/Make-lang.in | 2 + gcc/rust/backend/rust-mangle-legacy.cc | 164 +++++++ gcc/rust/backend/rust-mangle-v0.cc | 508 +++++++++++++++++++ gcc/rust/backend/rust-mangle.cc | 648 +------------------------ gcc/rust/backend/rust-mangle.h | 8 + 5 files changed, 700 insertions(+), 630 deletions(-) create mode 100644 gcc/rust/backend/rust-mangle-legacy.cc create mode 100644 gcc/rust/backend/rust-mangle-v0.cc diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in index b138ba26801..bdaef41c419 100644 --- a/gcc/rust/Make-lang.in +++ b/gcc/rust/Make-lang.in @@ -85,6 +85,8 @@ GRS_OBJS = \ rust/rust-session-manager.o \ rust/rust-compile.o \ rust/rust-mangle.o \ + rust/rust-mangle-v0.o \ + rust/rust-mangle-legacy.o \ rust/rust-compile-resolve-path.o \ rust/rust-macro-expand.o \ rust/rust-cfg-strip.o \ diff --git a/gcc/rust/backend/rust-mangle-legacy.cc b/gcc/rust/backend/rust-mangle-legacy.cc new file mode 100644 index 00000000000..fd0ba1b3745 --- /dev/null +++ b/gcc/rust/backend/rust-mangle-legacy.cc @@ -0,0 +1,164 @@ +// Copyright (C) 2020-2023 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// . + +#include "rust-mangle.h" +#include "fnv-hash.h" +#include "rust-unicode.h" +#include "rust-diagnostics.h" +#include "rust-system.h" +#include + +namespace Rust { +namespace Compile { + +const std::string kLegacySymbolPrefix = "_ZN"; +static const std::string kLegacySymbolDelim = "E"; +static const std::string kLegacyGenericDelim = "$C$"; +static const std::string kLegacySubstBegin = "$LT$"; +static const std::string kLegacySubstEnd = "$GT$"; +static const std::string kLegacySpace = "$u20$"; +static const std::string kLegacyRef = "$RF$"; +static const std::string kLegacyPtr = "$BP$"; +static const std::string kLegacyLeftSqParen = "$u5b$"; // [ +static const std::string kLegacyRightSqParen = "$u5d$"; // ] +static const std::string kLegacyLeftBrace = "$u7b$"; // { +static const std::string kLegacyRightBrace = "$u7d$"; // } +static const std::string kQualPathBegin = "_" + kLegacySubstBegin; +static const std::string kLegacyComma = "$C$"; + +static std::string +legacy_mangle_name (const std::string &name) +{ + // example + // <&T as core::fmt::Debug>::fmt: + // _ZN42_$LT$$RF$T$u20$as$u20$core..fmt..Debug$GT$3fmt17h6dac924c0051eef7E + // replace all white space with $ and & with RF + // + // ::fooA: + // _ZN43_$LT$example..Bar$u20$as$u20$example..A$GT$4fooA17hfc615fa76c7db7a0E: + // + // core::ptr::const_ptr::::cast: + // _ZN4core3ptr9const_ptr33_$LT$impl$u20$$BP$const$u20$T$GT$4cast17hb79f4617226f1d55E: + // + // core::ptr::const_ptr::::as_ptr: + // _ZN4core3ptr9const_ptr43_$LT$impl$u20$$BP$const$u20$$u5b$T$u5d$$GT$6as_ptr17he16e0dcd9473b04fE: + // + // example::Foo::new: + // _ZN7example12Foo$LT$T$GT$3new17h9a2aacb7fd783515E: + // + // >::call + // _ZN74_$LT$example..Identity$u20$as$u20$example..FnLike$LT$$RF$T$C$$RF$T$GT$$GT$4call17ha9ee58935895acb3E + + tl::optional utf8_name = Utf8String::make_utf8_string (name); + rust_assert (utf8_name.has_value ()); + std::vector chars = utf8_name.value ().get_chars (); + std::string buffer; + for (size_t i = 0; i < chars.size (); i++) + { + std::string m; + Codepoint c = chars.at (i); + + if (c == ' ') + m = kLegacySpace; + else if (c == '&') + m = kLegacyRef; + else if (i == 0 && c == '<') + m = kQualPathBegin; + else if (c == '<') + m = kLegacySubstBegin; + else if (c == '>') + m = kLegacySubstEnd; + else if (c == '*') + m = kLegacyPtr; + else if (c == '[') + m = kLegacyLeftSqParen; + else if (c == ']') + m = kLegacyRightSqParen; + else if (c == '{') + m = kLegacyLeftBrace; + else if (c == '}') + m = kLegacyRightBrace; + else if (c == ',') + m = kLegacyComma; + else if (c == ':') + { + rust_assert (i + 1 < chars.size ()); + rust_assert (chars.at (i + 1) == ':'); + i++; + m = ".."; + } + else if (c.is_ascii ()) + // ASCII + m.push_back (c.value); + else + { + // Non-ASCII + std::stringstream escaped; + escaped << std::hex << "$u" << c.value << "$"; + m += escaped.str (); + } + buffer += m; + } + + return std::to_string (buffer.size ()) + buffer; +} + +static std::string +legacy_mangle_canonical_path (const Resolver::CanonicalPath &path) +{ + std::string buffer; + for (size_t i = 0; i < path.size (); i++) + { + auto &seg = path.get_seg_at (i); + buffer += legacy_mangle_name (seg.second); + } + return buffer; +} + +// rustc uses a sip128 hash for legacy mangling, but an fnv 128 was quicker to +// implement for now +static std::string +legacy_hash (const std::string &fingerprint) +{ + Hash::FNV128 hasher; + hasher.write ((const unsigned char *) fingerprint.c_str (), + fingerprint.size ()); + + uint64_t hi, lo; + hasher.sum (&hi, &lo); + + char hex[16 + 1]; + memset (hex, 0, sizeof hex); + snprintf (hex, sizeof hex, "%08" PRIx64 "%08" PRIx64, lo, hi); + + return "h" + std::string (hex, sizeof (hex) - 1); +} + +std::string +legacy_mangle_item (const TyTy::BaseType *ty, + const Resolver::CanonicalPath &path) +{ + const std::string hash = legacy_hash (ty->mangle_string ()); + const std::string hash_sig = legacy_mangle_name (hash); + + return kLegacySymbolPrefix + legacy_mangle_canonical_path (path) + hash_sig + + kLegacySymbolDelim; +} + +} // namespace Compile +} // namespace Rust diff --git a/gcc/rust/backend/rust-mangle-v0.cc b/gcc/rust/backend/rust-mangle-v0.cc new file mode 100644 index 00000000000..634ccb07aa4 --- /dev/null +++ b/gcc/rust/backend/rust-mangle-v0.cc @@ -0,0 +1,508 @@ +// Copyright (C) 2020-2023 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// . + +#include "rust-mangle.h" +#include "optional.h" +#include "rust-base62.h" +#include "rust-diagnostics.h" +#include "rust-system.h" +#include "rust-tyty.h" +#include "rust-unicode.h" +#include "rust-punycode.h" +#include "rust-compile-type.h" +#include + +namespace Rust { +namespace Compile { + +struct V0Path +{ + std::string prefix = ""; + // Used for "N" + std::string ns = ""; + std::string path = ""; + // Used for "N" and "C" + std::string ident = ""; + std::string disambiguator = ""; + // Used for "M" and "X" + std::string impl_path = ""; + std::string impl_type = ""; + std::string trait_type = ""; + // Used for generic types + std::string generic_postfix = ""; + std::string generic_prefix = ""; + + std::string as_string () const + { + if (prefix == "N") + return generic_prefix + prefix + ns + path + disambiguator + ident + + generic_postfix; + else if (prefix == "M") + return prefix + impl_path + impl_type; + else if (prefix == "X") + return prefix + impl_type + trait_type; + else if (prefix == "C") + return prefix + disambiguator + ident; + else + rust_unreachable (); + } +}; + +static std::string +v0_path (Rust::Compile::Context *ctx, const TyTy::BaseType *ty, + const Resolver::CanonicalPath &path); + +static std::string +v0_tuple_prefix (const TyTy::BaseType *ty) +{ + if (ty->is_unit ()) + return "u"; + + // FIXME: ARTHUR: Add rest of algorithm + return ""; +} + +static std::string +v0_numeric_prefix (const TyTy::BaseType *ty) +{ + static const std::map num_prefixes = { + {"i8", "a"}, {"u8", "h"}, {"i16", "s"}, {"u16", "t"}, + {"i32", "l"}, {"u32", "m"}, {"i64", "x"}, {"u64", "y"}, + {"isize", "i"}, {"usize", "j"}, {"f32", "f"}, {"f64", "d"}, + }; + + auto ty_kind = ty->get_kind (); + auto ty_str = ty->as_string (); + auto numeric_iter = num_prefixes.end (); + + // Special numeric types + if (ty_kind == TyTy::TypeKind::ISIZE) + return "i"; + else if (ty_kind == TyTy::TypeKind::USIZE) + return "j"; + + numeric_iter = num_prefixes.find (ty_str); + if (numeric_iter != num_prefixes.end ()) + return numeric_iter->second; + + rust_unreachable (); +} + +static std::string +v0_simple_type_prefix (const TyTy::BaseType *ty) +{ + switch (ty->get_kind ()) + { + case TyTy::TypeKind::BOOL: + return "b"; + case TyTy::TypeKind::CHAR: + return "c"; + case TyTy::TypeKind::STR: + return "e"; + case TyTy::TypeKind::NEVER: + return "z"; + + // Placeholder types + case TyTy::TypeKind::ERROR: // Fallthrough + case TyTy::TypeKind::INFER: // Fallthrough + case TyTy::TypeKind::PLACEHOLDER: // Fallthrough + case TyTy::TypeKind::PARAM: + // FIXME: TyTy::TypeKind::BOUND is also a valid variant in rustc + return "p"; + + case TyTy::TypeKind::TUPLE: + return v0_tuple_prefix (ty); + + case TyTy::TypeKind::UINT: // Fallthrough + case TyTy::TypeKind::INT: // Fallthrough + case TyTy::TypeKind::FLOAT: // Fallthrough + case TyTy::TypeKind::ISIZE: // Fallthrough + case TyTy::TypeKind::USIZE: + return v0_numeric_prefix (ty); + + default: + return ""; + } + + rust_unreachable (); +} + +static std::string +v0_complex_type_prefix (Context *ctx, const TyTy::BaseType *ty) +{ + // FIXME: ref, slice, dyn, etc. + // TODO: generics + switch (ty->get_kind ()) + { + case TyTy::TypeKind::ADT: { + const TyTy::ADTType *adt = static_cast (ty); + return v0_path (ctx, ty, adt->get_ident ().path); + } + break; + default: + return ""; + } +} + +// Returns an underscore-terminated base62 integer. +// This corresponds to the `` grammar in the v0 mangling RFC: +// - 0 is encoded as "_" +// - any other value is encoded as itself minus one in base 62, followed by +// "_" +static std::string +v0_integer_62 (uint64_t x) +{ + std::stringstream s; + if (x > 0) + s << base62_integer (x - 1); + + s << "_"; + return s.str (); +} + +// Returns a tag-prefixed base62 integer when the +// integer is greater than 0: +// - 0 is encoded as "" (nothing) +// - any other value is encoded as + v0_integer_62(itself), that is +// + base62(itself - 1) + '_' +static std::string +v0_opt_integer_62 (std::string tag, uint64_t x) +{ + if (x > 0) + { + return tag + v0_integer_62 (x); + } + return ""; +} + +static std::string +v0_disambiguator (uint64_t dis) +{ + return v0_opt_integer_62 ("s", dis); +} + +static std::string +v0_type_prefix (Context *ctx, const TyTy::BaseType *ty) +{ + std::string ty_prefix; + + ty_prefix = v0_simple_type_prefix (ty); + if (!ty_prefix.empty ()) + return ty_prefix; + + ty_prefix = v0_complex_type_prefix (ctx, ty); + if (!ty_prefix.empty ()) + return ty_prefix; + + rust_unreachable (); +} + +static std::string +v0_generic_args (Context *ctx, const TyTy::BaseType *ty) +{ + std::stringstream ss; + const TyTy::FnType *fnty = static_cast (ty); + TyTy::SubstitutionArgumentMappings &subst_ref + = const_cast (fnty)->get_substitution_arguments (); + for (TyTy::SubstitutionArg &map : subst_ref.get_mappings ()) + { + ss << v0_type_prefix (ctx, map.get_tyty ()); + } + return ss.str (); +} + +// Returns an mangled identifier. This corresponds to the +// `` grammar in the v0 mangling RFC. +static std::string +v0_identifier (const std::string &identifier) +{ + std::stringstream mangled; + // The grammar for unicode identifier is contained in + // , right under the one. If the + // identifier contains unicode values, then an extra "u" needs to be added to + // the mangling string and `punycode` must be used to encode the characters. + + if (!is_ascii_only (identifier)) + mangled << "u"; + + tl::optional uident_opt + = Utf8String::make_utf8_string (identifier); + rust_assert (uident_opt.has_value ()); + tl::optional punycode_opt + = encode_punycode (uident_opt.value ()); + rust_assert (punycode_opt.has_value ()); + + std::string punycode = punycode_opt.value (); + + // remove a tailing hyphen + if (punycode.back () == '-') + punycode.pop_back (); + + // replace a hyphen in punycode with a underscore + std::replace (punycode.begin (), punycode.end (), '-', '_'); + + mangled << std::to_string (punycode.size ()); + + // Add extra '_' + if (punycode[0] == '_' || ('0' <= punycode[0] && punycode[0] <= '9')) + mangled << "_"; + + mangled << punycode; + return mangled.str (); +} + +static V0Path +v0_type_path (V0Path path, std::string ident) +{ + V0Path v0path; + v0path.prefix = "N"; + v0path.ns = "t"; + v0path.path = path.as_string (); + v0path.ident = ident; + // TODO: Need ? + return v0path; +} + +static V0Path +v0_function_path (V0Path path, Rust::Compile::Context *ctx, + const TyTy::BaseType *ty, HIR::Function *fn, + std::string ident) +{ + V0Path v0path; + v0path.prefix = "N"; + v0path.ns = "v"; + v0path.path = path.as_string (); + v0path.ident = ident; + if (!fn->get_generic_params ().empty ()) + { + v0path.generic_prefix = "I"; + v0path.generic_postfix = v0_generic_args (ctx, ty) + "E"; + } + return v0path; +} + +static V0Path +v0_scope_path (V0Path path, std::string ident, std::string ns) +{ + V0Path v0path; + v0path.prefix = "N"; + v0path.ns = ns; + v0path.path = path.as_string (); + v0path.ident = ident; + return v0path; +} + +static V0Path +v0_crate_path (CrateNum crate_num, std::string ident) +{ + V0Path v0path; + v0path.prefix = "C"; + v0path.disambiguator = v0_disambiguator (crate_num); + v0path.ident = ident; + return v0path; +} + +static V0Path +v0_inherent_or_trait_impl_path (Rust::Compile::Context *ctx, + HIR::ImplBlock *impl_block) +{ + V0Path v0path; + bool ok; + + // lookup impl type + TyTy::BaseType *impl_ty = nullptr; + ok = ctx->get_tyctx ()->lookup_type ( + impl_block->get_type ()->get_mappings ().get_hirid (), &impl_ty); + rust_assert (ok); + + // FIXME: dummy value for now + v0path.impl_path = "C5crate"; + v0path.impl_type = v0_type_prefix (ctx, impl_ty); + + if (impl_block->has_trait_ref ()) + { + // trait impl: X + v0path.prefix = "X"; + + TyTy::BaseType *trait_ty = nullptr; + ok = ctx->get_tyctx ()->lookup_type ( + impl_block->get_trait_ref ()->get_mappings ().get_hirid (), &trait_ty); + rust_assert (ok); + + v0path.trait_type = v0_type_prefix (ctx, trait_ty); + } + else + // inherent impl: M + v0path.prefix = "M"; + + return v0path; +} + +static V0Path +v0_closure (V0Path path, HirId closure) +{ + V0Path v0path; + v0path.prefix = "N"; + v0path.ns = "C"; + v0path.disambiguator = v0_disambiguator (closure); + v0path.path = path.as_string (); + v0path.ident = "0"; + return v0path; +} + +static std::string +v0_path (Rust::Compile::Context *ctx, const TyTy::BaseType *ty, + const Resolver::CanonicalPath &cpath) +{ + auto mappings = Analysis::Mappings::get (); + + V0Path v0path = {}; + + cpath.iterate_segs ([&] (const Resolver::CanonicalPath &seg) { + HirId hir_id; + bool ok = mappings->lookup_node_to_hir (seg.get_node_id (), &hir_id); + if (!ok) + { + // FIXME: generic arg in canonical path? (e.g. in crate::S) + rust_unreachable (); + } + + HirId parent_impl_id = UNKNOWN_HIRID; + HIR::ImplItem *impl_item + = mappings->lookup_hir_implitem (hir_id, &parent_impl_id); + HIR::TraitItem *trait_item = mappings->lookup_hir_trait_item (hir_id); + HIR::Item *item = mappings->lookup_hir_item (hir_id); + HIR::Expr *expr = mappings->lookup_hir_expr (hir_id); + + if (impl_item != nullptr) + { + switch (impl_item->get_impl_item_type ()) + { + case HIR::ImplItem::FUNCTION: { + HIR::Function *fn = static_cast (impl_item); + v0path = v0_function_path (v0path, ctx, ty, fn, + v0_identifier (seg.get ())); + } + break; + case HIR::ImplItem::CONSTANT: + v0path = v0_scope_path (v0path, v0_identifier (seg.get ()), "v"); + break; + default: + rust_internal_error_at (UNDEF_LOCATION, "Attempt to mangle '%s'", + cpath.get ().c_str ()); + break; + } + } + else if (trait_item != nullptr) + { + switch (trait_item->get_item_kind ()) + { + case HIR::TraitItem::FUNC: { + HIR::Function *fn = static_cast (impl_item); + v0path = v0_function_path (v0path, ctx, ty, fn, + v0_identifier (seg.get ())); + } + break; + case HIR::TraitItem::CONST: + v0path = v0_scope_path (v0path, v0_identifier (seg.get ()), "v"); + break; + default: + rust_internal_error_at (UNDEF_LOCATION, "Attempt to mangle '%s'", + cpath.get ().c_str ()); + break; + } + } + else if (item != nullptr) + switch (item->get_item_kind ()) + { + case HIR::Item::ItemKind::Function: { + HIR::Function *fn = static_cast (item); + v0path = v0_function_path (v0path, ctx, ty, fn, + v0_identifier (seg.get ())); + } + break; + case HIR::Item::ItemKind::Module: + v0path = v0_scope_path (v0path, v0_identifier (seg.get ()), "t"); + break; + case HIR::Item::ItemKind::Trait: // FIXME: correct? + case HIR::Item::ItemKind::Static: + case HIR::Item::ItemKind::Constant: + v0path = v0_scope_path (v0path, v0_identifier (seg.get ()), "v"); + break; + case HIR::Item::ItemKind::Struct: + case HIR::Item::ItemKind::Enum: + case HIR::Item::ItemKind::Union: + v0path = v0_type_path (v0path, v0_identifier (seg.get ())); + break; + case HIR::Item::ItemKind::Impl: + // Trait impl or inherent impl. + { + HIR::ImplBlock *impl_block = static_cast (item); + v0path = v0_inherent_or_trait_impl_path (ctx, impl_block); + } + break; + case HIR::Item::ItemKind::ExternBlock: + case HIR::Item::ItemKind::ExternCrate: + case HIR::Item::ItemKind::UseDeclaration: + case HIR::Item::ItemKind::TypeAlias: + case HIR::Item::ItemKind::EnumItem: // FIXME: correct? + rust_internal_error_at (UNDEF_LOCATION, "Attempt to mangle '%s'", + cpath.get ().c_str ()); + break; + } + else if (expr != nullptr) + { + rust_assert (expr->get_expression_type () + == HIR::Expr::ExprType::Closure); + // Use HIR ID as disambiguator. + v0path = v0_closure (v0path, hir_id); + } + else + // Not HIR item, impl item, trait impl item, nor expr. Assume a crate. + v0path + = v0_crate_path (cpath.get_crate_num (), v0_identifier (seg.get ())); + + return true; + }); + + return v0path.as_string (); +} + +std::string +v0_mangle_item (Rust::Compile::Context *ctx, const TyTy::BaseType *ty, + const Resolver::CanonicalPath &path) +{ + rust_debug ("Start mangling: %s", path.get ().c_str ()); + + // TODO: get Instanciating CrateNum + // auto mappings = Analysis::Mappings::get (); + // std::string crate_name; + // bool ok = mappings->get_crate_name (path.get_crate_num (), crate_name); + // rust_assert (ok); + + std::stringstream mangled; + mangled << "_R"; + mangled << v0_path (ctx, ty, path); + + rust_debug ("=> %s", mangled.str ().c_str ()); + + return mangled.str (); +} + +} // namespace Compile +} // namespace Rust diff --git a/gcc/rust/backend/rust-mangle.cc b/gcc/rust/backend/rust-mangle.cc index e1c9e9427c5..53ed6b54527 100644 --- a/gcc/rust/backend/rust-mangle.cc +++ b/gcc/rust/backend/rust-mangle.cc @@ -1,640 +1,28 @@ -#include "rust-mangle.h" -#include "fnv-hash.h" -#include "optional.h" -#include "rust-base62.h" -#include "rust-unicode.h" -#include "rust-diagnostics.h" -#include "rust-hir-full-decls.h" -#include "rust-hir-item.h" -#include "rust-hir-type-bounds.h" -#include "rust-system.h" -#include "rust-tyty-subst.h" -#include "rust-tyty.h" -#include "rust-unicode.h" -#include "rust-punycode.h" -#include "rust-hir.h" -#include "rust-compile-type.h" -#include - -// FIXME: Rename those to legacy_* -static const std::string kMangledSymbolPrefix = "_ZN"; -static const std::string kMangledSymbolDelim = "E"; -static const std::string kMangledGenericDelim = "$C$"; -static const std::string kMangledSubstBegin = "$LT$"; -static const std::string kMangledSubstEnd = "$GT$"; -static const std::string kMangledSpace = "$u20$"; -static const std::string kMangledRef = "$RF$"; -static const std::string kMangledPtr = "$BP$"; -static const std::string kMangledLeftSqParen = "$u5b$"; // [ -static const std::string kMangledRightSqParen = "$u5d$"; // ] -static const std::string kMangledLeftBrace = "$u7b$"; // { -static const std::string kMangledRightBrace = "$u7d$"; // } -static const std::string kQualPathBegin = "_" + kMangledSubstBegin; -static const std::string kMangledComma = "$C$"; - -namespace Rust { -namespace Compile { - -Mangler::MangleVersion Mangler::version = MangleVersion::LEGACY; - -struct V0Path -{ - std::string prefix = ""; - // Used for "N" - std::string ns = ""; - std::string path = ""; - // Used for "N" and "C" - std::string ident = ""; - std::string disambiguator = ""; - // Used for "M" and "X" - std::string impl_path = ""; - std::string impl_type = ""; - std::string trait_type = ""; - // Used for generic types - std::string generic_postfix = ""; - std::string generic_prefix = ""; - - std::string as_string () const - { - if (prefix == "N") - return generic_prefix + prefix + ns + path + disambiguator + ident - + generic_postfix; - else if (prefix == "M") - return prefix + impl_path + impl_type; - else if (prefix == "X") - return prefix + impl_type + trait_type; - else if (prefix == "C") - return prefix + disambiguator + ident; - else - rust_unreachable (); - } -}; - -static std::string -v0_path (Rust::Compile::Context *ctx, const TyTy::BaseType *ty, - const Resolver::CanonicalPath &path); - -static std::string -legacy_mangle_name (const std::string &name) -{ - // example - // <&T as core::fmt::Debug>::fmt: - // _ZN42_$LT$$RF$T$u20$as$u20$core..fmt..Debug$GT$3fmt17h6dac924c0051eef7E - // replace all white space with $ and & with RF - // - // ::fooA: - // _ZN43_$LT$example..Bar$u20$as$u20$example..A$GT$4fooA17hfc615fa76c7db7a0E: - // - // core::ptr::const_ptr::::cast: - // _ZN4core3ptr9const_ptr33_$LT$impl$u20$$BP$const$u20$T$GT$4cast17hb79f4617226f1d55E: - // - // core::ptr::const_ptr::::as_ptr: - // _ZN4core3ptr9const_ptr43_$LT$impl$u20$$BP$const$u20$$u5b$T$u5d$$GT$6as_ptr17he16e0dcd9473b04fE: - // - // example::Foo::new: - // _ZN7example12Foo$LT$T$GT$3new17h9a2aacb7fd783515E: - // - // >::call - // _ZN74_$LT$example..Identity$u20$as$u20$example..FnLike$LT$$RF$T$C$$RF$T$GT$$GT$4call17ha9ee58935895acb3E - - tl::optional utf8_name = Utf8String::make_utf8_string (name); - rust_assert (utf8_name.has_value ()); - std::vector chars = utf8_name.value ().get_chars (); - std::string buffer; - for (size_t i = 0; i < chars.size (); i++) - { - std::string m; - Codepoint c = chars.at (i); - - if (c == ' ') - m = kMangledSpace; - else if (c == '&') - m = kMangledRef; - else if (i == 0 && c == '<') - m = kQualPathBegin; - else if (c == '<') - m = kMangledSubstBegin; - else if (c == '>') - m = kMangledSubstEnd; - else if (c == '*') - m = kMangledPtr; - else if (c == '[') - m = kMangledLeftSqParen; - else if (c == ']') - m = kMangledRightSqParen; - else if (c == '{') - m = kMangledLeftBrace; - else if (c == '}') - m = kMangledRightBrace; - else if (c == ',') - m = kMangledComma; - else if (c == ':') - { - rust_assert (i + 1 < chars.size ()); - rust_assert (chars.at (i + 1) == ':'); - i++; - m = ".."; - } - else if (c.is_ascii ()) - // ASCII - m.push_back (c.value); - else - { - // Non-ASCII - std::stringstream escaped; - escaped << std::hex << "$u" << c.value << "$"; - m += escaped.str (); - } - buffer += m; - } - - return std::to_string (buffer.size ()) + buffer; -} - -static std::string -legacy_mangle_canonical_path (const Resolver::CanonicalPath &path) -{ - std::string buffer; - for (size_t i = 0; i < path.size (); i++) - { - auto &seg = path.get_seg_at (i); - buffer += legacy_mangle_name (seg.second); - } - return buffer; -} - -// rustc uses a sip128 hash for legacy mangling, but an fnv 128 was quicker to -// implement for now -static std::string -legacy_hash (const std::string &fingerprint) -{ - Hash::FNV128 hasher; - hasher.write ((const unsigned char *) fingerprint.c_str (), - fingerprint.size ()); - - uint64_t hi, lo; - hasher.sum (&hi, &lo); - - char hex[16 + 1]; - memset (hex, 0, sizeof hex); - snprintf (hex, sizeof hex, "%08" PRIx64 "%08" PRIx64, lo, hi); - - return "h" + std::string (hex, sizeof (hex) - 1); -} - -static std::string -v0_tuple_prefix (const TyTy::BaseType *ty) -{ - if (ty->is_unit ()) - return "u"; - - // FIXME: ARTHUR: Add rest of algorithm - return ""; -} - -static std::string -v0_numeric_prefix (const TyTy::BaseType *ty) -{ - static const std::map num_prefixes = { - {"i8", "a"}, {"u8", "h"}, {"i16", "s"}, {"u16", "t"}, - {"i32", "l"}, {"u32", "m"}, {"i64", "x"}, {"u64", "y"}, - {"isize", "i"}, {"usize", "j"}, {"f32", "f"}, {"f64", "d"}, - }; - - auto ty_kind = ty->get_kind (); - auto ty_str = ty->as_string (); - auto numeric_iter = num_prefixes.end (); - - // Special numeric types - if (ty_kind == TyTy::TypeKind::ISIZE) - return "i"; - else if (ty_kind == TyTy::TypeKind::USIZE) - return "j"; - - numeric_iter = num_prefixes.find (ty_str); - if (numeric_iter != num_prefixes.end ()) - return numeric_iter->second; - - rust_unreachable (); -} - -static std::string -v0_simple_type_prefix (const TyTy::BaseType *ty) -{ - switch (ty->get_kind ()) - { - case TyTy::TypeKind::BOOL: - return "b"; - case TyTy::TypeKind::CHAR: - return "c"; - case TyTy::TypeKind::STR: - return "e"; - case TyTy::TypeKind::NEVER: - return "z"; - - // Placeholder types - case TyTy::TypeKind::ERROR: // Fallthrough - case TyTy::TypeKind::INFER: // Fallthrough - case TyTy::TypeKind::PLACEHOLDER: // Fallthrough - case TyTy::TypeKind::PARAM: - // FIXME: TyTy::TypeKind::BOUND is also a valid variant in rustc - return "p"; - - case TyTy::TypeKind::TUPLE: - return v0_tuple_prefix (ty); - - case TyTy::TypeKind::UINT: // Fallthrough - case TyTy::TypeKind::INT: // Fallthrough - case TyTy::TypeKind::FLOAT: // Fallthrough - case TyTy::TypeKind::ISIZE: // Fallthrough - case TyTy::TypeKind::USIZE: // Fallthrough - return v0_numeric_prefix (ty); - - default: - return ""; - } - - rust_unreachable (); -} - -static std::string -v0_complex_type_prefix (Context *ctx, const TyTy::BaseType *ty) -{ - // FIXME: ref, slice, dyn, etc. - // TODO: generics - switch (ty->get_kind ()) - { - case TyTy::TypeKind::ADT: { - const TyTy::ADTType *adt = static_cast (ty); - return v0_path (ctx, ty, adt->get_ident ().path); - } - break; - default: - return ""; - } -} - -// Returns an underscore-terminated base62 integer. -// This corresponds to the `` grammar in the v0 mangling RFC: -// - 0 is encoded as "_" -// - any other value is encoded as itself minus one in base 62, followed by -// "_" -static std::string -v0_integer_62 (uint64_t x) -{ - std::stringstream s; - if (x > 0) - s << base62_integer (x - 1); - - s << "_"; - return s.str (); -} - -// Returns a tag-prefixed base62 integer when the -// integer is greater than 0: -// - 0 is encoded as "" (nothing) -// - any other value is encoded as + v0_integer_62(itself), that is -// + base62(itself - 1) + '_' -static std::string -v0_opt_integer_62 (std::string tag, uint64_t x) -{ - if (x > 0) - { - return tag + v0_integer_62 (x); - } - return ""; -} - -static std::string -v0_disambiguator (uint64_t dis) -{ - return v0_opt_integer_62 ("s", dis); -} - -static std::string -v0_type_prefix (Context *ctx, const TyTy::BaseType *ty) -{ - std::string ty_prefix; - - ty_prefix = v0_simple_type_prefix (ty); - if (!ty_prefix.empty ()) - return ty_prefix; - - ty_prefix = v0_complex_type_prefix (ctx, ty); - if (!ty_prefix.empty ()) - return ty_prefix; - - rust_unreachable (); -} - -static std::string -v0_generic_args (Context *ctx, const TyTy::BaseType *ty) -{ - std::stringstream ss; - const TyTy::FnType *fnty = static_cast (ty); - TyTy::SubstitutionArgumentMappings &subst_ref - = const_cast (fnty)->get_substitution_arguments (); - for (TyTy::SubstitutionArg &map : subst_ref.get_mappings ()) - { - ss << v0_type_prefix (ctx, map.get_tyty ()); - } - return ss.str (); -} - -// Returns an mangled identifier. This corresponds to the -// `` grammar in the v0 mangling RFC. -static std::string -v0_identifier (const std::string &identifier) -{ - std::stringstream mangled; - // The grammar for unicode identifier is contained in - // , right under the one. If the - // identifier contains unicode values, then an extra "u" needs to be added to - // the mangling string and `punycode` must be used to encode the characters. - - if (!is_ascii_only (identifier)) - mangled << "u"; - - tl::optional uident_opt - = Utf8String::make_utf8_string (identifier); - rust_assert (uident_opt.has_value ()); - tl::optional punycode_opt - = encode_punycode (uident_opt.value ()); - rust_assert (punycode_opt.has_value ()); - - std::string punycode = punycode_opt.value (); - - // remove a tailing hyphen - if (punycode.back () == '-') - punycode.pop_back (); +// Copyright (C) 2020-2023 Free Software Foundation, Inc. - // replace a hyphen in punycode with a underscore - std::replace (punycode.begin (), punycode.end (), '-', '_'); +// This file is part of GCC. - mangled << std::to_string (punycode.size ()); +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. - // Add extra '_' - if (punycode[0] == '_' || ('0' <= punycode[0] && punycode[0] <= '9')) - mangled << "_"; - - mangled << punycode; - return mangled.str (); -} - -static V0Path -v0_type_path (V0Path path, std::string ident) -{ - V0Path v0path; - v0path.prefix = "N"; - v0path.ns = "t"; - v0path.path = path.as_string (); - v0path.ident = ident; - // TODO: Need ? - return v0path; -} - -static V0Path -v0_function_path (V0Path path, Rust::Compile::Context *ctx, - const TyTy::BaseType *ty, HIR::Function *fn, - std::string ident) -{ - V0Path v0path; - v0path.prefix = "N"; - v0path.ns = "v"; - v0path.path = path.as_string (); - v0path.ident = ident; - if (!fn->get_generic_params ().empty ()) - { - v0path.generic_prefix = "I"; - v0path.generic_postfix = v0_generic_args (ctx, ty) + "E"; - } - return v0path; -} - -static V0Path -v0_scope_path (V0Path path, std::string ident, std::string ns) -{ - V0Path v0path; - v0path.prefix = "N"; - v0path.ns = ns; - v0path.path = path.as_string (); - v0path.ident = ident; - return v0path; -} - -static V0Path -v0_crate_path (CrateNum crate_num, std::string ident) -{ - V0Path v0path; - v0path.prefix = "C"; - v0path.disambiguator = v0_disambiguator (crate_num); - v0path.ident = ident; - return v0path; -} - -static V0Path -v0_inherent_or_trait_impl_path (Rust::Compile::Context *ctx, - HIR::ImplBlock *impl_block) -{ - V0Path v0path; - bool ok; +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. - // lookup impl type - TyTy::BaseType *impl_ty = nullptr; - ok = ctx->get_tyctx ()->lookup_type ( - impl_block->get_type ()->get_mappings ().get_hirid (), &impl_ty); - rust_assert (ok); +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// . - // FIXME: dummy value for now - v0path.impl_path = "C5crate"; - v0path.impl_type = v0_type_prefix (ctx, impl_ty); - - if (impl_block->has_trait_ref ()) - { - // trait impl: X - v0path.prefix = "X"; - - TyTy::BaseType *trait_ty = nullptr; - ok = ctx->get_tyctx ()->lookup_type ( - impl_block->get_trait_ref ()->get_mappings ().get_hirid (), &trait_ty); - rust_assert (ok); - - v0path.trait_type = v0_type_prefix (ctx, trait_ty); - } - else - // inherent impl: M - v0path.prefix = "M"; - - return v0path; -} - -static V0Path -v0_closure (V0Path path, HirId closure) -{ - V0Path v0path; - v0path.prefix = "N"; - v0path.ns = "C"; - v0path.disambiguator = v0_disambiguator (closure); - v0path.path = path.as_string (); - v0path.ident = "0"; - return v0path; -} - -static std::string -v0_path (Rust::Compile::Context *ctx, const TyTy::BaseType *ty, - const Resolver::CanonicalPath &cpath) -{ - auto mappings = Analysis::Mappings::get (); - - V0Path v0path = {}; - - cpath.iterate_segs ([&] (const Resolver::CanonicalPath &seg) { - HirId hir_id; - bool ok = mappings->lookup_node_to_hir (seg.get_node_id (), &hir_id); - if (!ok) - { - // FIXME: generic arg in canonical path? (e.g. in crate::S) - rust_unreachable (); - } - - HirId parent_impl_id = UNKNOWN_HIRID; - HIR::ImplItem *impl_item - = mappings->lookup_hir_implitem (hir_id, &parent_impl_id); - HIR::TraitItem *trait_item = mappings->lookup_hir_trait_item (hir_id); - HIR::Item *item = mappings->lookup_hir_item (hir_id); - HIR::Expr *expr = mappings->lookup_hir_expr (hir_id); - - if (impl_item != nullptr) - { - switch (impl_item->get_impl_item_type ()) - { - case HIR::ImplItem::FUNCTION: { - HIR::Function *fn = static_cast (impl_item); - v0path = v0_function_path (v0path, ctx, ty, fn, - v0_identifier (seg.get ())); - } - break; - case HIR::ImplItem::CONSTANT: - v0path = v0_scope_path (v0path, v0_identifier (seg.get ()), "v"); - break; - default: - rust_internal_error_at (UNDEF_LOCATION, "Attempt to mangle '%s'", - cpath.get ().c_str ()); - break; - } - } - else if (trait_item != nullptr) - { - switch (trait_item->get_item_kind ()) - { - case HIR::TraitItem::FUNC: { - HIR::Function *fn = static_cast (impl_item); - v0path = v0_function_path (v0path, ctx, ty, fn, - v0_identifier (seg.get ())); - } - break; - case HIR::TraitItem::CONST: - v0path = v0_scope_path (v0path, v0_identifier (seg.get ()), "v"); - break; - default: - rust_internal_error_at (UNDEF_LOCATION, "Attempt to mangle '%s'", - cpath.get ().c_str ()); - break; - } - } - else if (item != nullptr) - switch (item->get_item_kind ()) - { - case HIR::Item::ItemKind::Function: { - HIR::Function *fn = static_cast (item); - v0path = v0_function_path (v0path, ctx, ty, fn, - v0_identifier (seg.get ())); - } - break; - case HIR::Item::ItemKind::Module: - v0path = v0_scope_path (v0path, v0_identifier (seg.get ()), "t"); - break; - case HIR::Item::ItemKind::Trait: // FIXME: correct? - case HIR::Item::ItemKind::Static: - case HIR::Item::ItemKind::Constant: - v0path = v0_scope_path (v0path, v0_identifier (seg.get ()), "v"); - break; - case HIR::Item::ItemKind::Struct: - case HIR::Item::ItemKind::Enum: - case HIR::Item::ItemKind::Union: - v0path = v0_type_path (v0path, v0_identifier (seg.get ())); - break; - case HIR::Item::ItemKind::Impl: - // Trait impl or inherent impl. - { - HIR::ImplBlock *impl_block = static_cast (item); - v0path = v0_inherent_or_trait_impl_path (ctx, impl_block); - } - break; - case HIR::Item::ItemKind::ExternBlock: - case HIR::Item::ItemKind::ExternCrate: - case HIR::Item::ItemKind::UseDeclaration: - case HIR::Item::ItemKind::TypeAlias: - case HIR::Item::ItemKind::EnumItem: // FIXME: correct? - rust_internal_error_at (UNDEF_LOCATION, "Attempt to mangle '%s'", - cpath.get ().c_str ()); - break; - } - else if (expr != nullptr) - { - rust_assert (expr->get_expression_type () - == HIR::Expr::ExprType::Closure); - // Use HIR ID as disambiguator. - v0path = v0_closure (v0path, hir_id); - } - else - { - // Not HIR item, impl item, trait impl item, nor expr. Assume a crate. - - // std::string crate_name; - // bool ok = mappings->get_crate_name (path.get_crate_num (), - // crate_name); rust_assert (ok); rust_assert (crate_name == seg.get()); - - v0path - = v0_crate_path (cpath.get_crate_num (), v0_identifier (seg.get ())); - } - - return true; - }); - - return v0path.as_string (); -} - -static std::string -legacy_mangle_item (const TyTy::BaseType *ty, - const Resolver::CanonicalPath &path) -{ - const std::string hash = legacy_hash (ty->mangle_string ()); - const std::string hash_sig = legacy_mangle_name (hash); - - return kMangledSymbolPrefix + legacy_mangle_canonical_path (path) + hash_sig - + kMangledSymbolDelim; -} - -static std::string -v0_mangle_item (Rust::Compile::Context *ctx, const TyTy::BaseType *ty, - const Resolver::CanonicalPath &path) -{ - rust_debug ("Start mangling: %s", path.get ().c_str ()); - - // auto mappings = Analysis::Mappings::get (); - // std::string crate_name; - // bool ok = mappings->get_crate_name (path.get_crate_num (), crate_name); - // rust_assert (ok); - - std::stringstream mangled; - mangled << "_R"; - mangled << v0_path (ctx, ty, path); +#include "rust-mangle.h" +#include "rust-system.h" - rust_debug ("=> %s", mangled.str ().c_str ()); +namespace Rust { +namespace Compile { - return mangled.str (); -} +Mangler::MangleVersion Mangler::version = MangleVersion::LEGACY; std::string Mangler::mangle_item (Rust::Compile::Context *ctx, const TyTy::BaseType *ty, diff --git a/gcc/rust/backend/rust-mangle.h b/gcc/rust/backend/rust-mangle.h index 09329bb9923..2a84b6b1dea 100644 --- a/gcc/rust/backend/rust-mangle.h +++ b/gcc/rust/backend/rust-mangle.h @@ -49,6 +49,14 @@ private: static enum MangleVersion version; }; +std::string +legacy_mangle_item (const TyTy::BaseType *ty, + const Resolver::CanonicalPath &path); + +std::string +v0_mangle_item (Rust::Compile::Context *ctx, const TyTy::BaseType *ty, + const Resolver::CanonicalPath &path); + } // namespace Compile } // namespace Rust #endif // RUST_MANGLE_H