rustc_codegen_utils: remove symbol name dumping/checking harness, and mw impl.

This commit is contained in:
Eduard-Mihai Burtescu 2019-04-10 08:33:31 +03:00
parent 6386a31c5b
commit 9cf35bfbe7
8 changed files with 10 additions and 1037 deletions

View File

@ -2699,7 +2699,6 @@ dependencies = [
"rustc_metadata 0.0.0",
"rustc_mir 0.0.0",
"rustc_target 0.0.0",
"std-mangle-rs 0.1.0 (git+https://github.com/michaelwoerister/std-mangle-rs?rev=e884304cfcb2f636db4d59ca8ad8fa95b983281c)",
"syntax 0.0.0",
"syntax_pos 0.0.0",
]
@ -3336,14 +3335,6 @@ dependencies = [
"unwind 0.0.0",
]
[[package]]
name = "std-mangle-rs"
version = "0.1.0"
source = "git+https://github.com/michaelwoerister/std-mangle-rs?rev=e884304cfcb2f636db4d59ca8ad8fa95b983281c#e884304cfcb2f636db4d59ca8ad8fa95b983281c"
dependencies = [
"unic-idna-punycode 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "string_cache"
version = "0.7.3"
@ -3858,11 +3849,6 @@ name = "ucd-util"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "unic-idna-punycode"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "unicase"
version = "2.4.0"
@ -4368,7 +4354,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b73ea3738b47563803ef814925e69be00799a8c07420be8b996f8e98fb2336db"
"checksum socket2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "c4d11a52082057d87cb5caa31ad812f4504b97ab44732cd8359df2e9ff9f48e7"
"checksum stable_deref_trait 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ffbc596e092fe5f598b12ef46cc03754085ac2f4d8c739ad61c4ae266cc3b3fa"
"checksum std-mangle-rs 0.1.0 (git+https://github.com/michaelwoerister/std-mangle-rs?rev=e884304cfcb2f636db4d59ca8ad8fa95b983281c)" = "<none>"
"checksum string_cache 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "25d70109977172b127fe834e5449e5ab1740b9ba49fa18a2020f509174f25423"
"checksum string_cache_codegen 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1eea1eee654ef80933142157fdad9dd8bc43cf7c74e999e369263496f04ff4da"
"checksum string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b1884d1bc09741d466d9b14e6d37ac89d6909cbcac41dd9ae982d4d063bbedfc"
@ -4412,7 +4397,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169"
"checksum ucd-trie 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "71a9c5b1fe77426cf144cc30e49e955270f5086e31a6441dfa8b32efc09b9d77"
"checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86"
"checksum unic-idna-punycode 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1b0366615c248bc56ea5ceafe6f71a682f6591e653b1ce61814999302617b8c0"
"checksum unicase 2.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a84e5511b2a947f3ae965dcb29b13b7b1691b6e7332cf5dbc1744138d5acb7f6"
"checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5"
"checksum unicode-normalization 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "6a0180bc61fc5a987082bfa111f4cc95c4caff7f9799f3e46df09163a937aa25"

View File

@ -23,7 +23,3 @@ rustc_target = { path = "../librustc_target" }
rustc_data_structures = { path = "../librustc_data_structures" }
rustc_metadata = { path = "../librustc_metadata" }
rustc_mir = { path = "../librustc_mir" }
[dependencies.std-mangle-rs]
git = "https://github.com/michaelwoerister/std-mangle-rs"
rev = "e884304cfcb2f636db4d59ca8ad8fa95b983281c"

View File

@ -100,9 +100,7 @@ use syntax_pos::symbol::InternedString;
use log::debug;
mod dump;
mod legacy;
mod mw;
mod v0;
pub fn provide(providers: &mut Providers<'_>) {
@ -221,19 +219,9 @@ fn symbol_name(tcx: TyCtxt<'_, 'tcx, 'tcx>, instance: Instance<'tcx>) -> Interne
};
let mangled = match mangling_version {
SymbolManglingVersion::Legacy => legacy::mangle(tcx, instance, instantiating_crate, false),
SymbolManglingVersion::V0 => v0::mangle(tcx, instance, instantiating_crate, true),
SymbolManglingVersion::Legacy => legacy::mangle(tcx, instance, instantiating_crate),
SymbolManglingVersion::V0 => v0::mangle(tcx, instance, instantiating_crate),
};
let r = InternedString::intern(&mangled);
dump::record(
tcx,
instance,
instantiating_crate,
mangling_version,
mangled,
);
r
InternedString::intern(&mangled)
}

View File

@ -1,558 +0,0 @@
use rustc::hir::def_id::{CrateNum, DefId};
use rustc::hir::map::{DefPathData, DisambiguatedDefPathData};
use rustc::session::config::SymbolManglingVersion;
use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
use rustc::ty::print::{PrettyPrinter, Printer, Print};
use rustc::ty::subst::{Kind, Subst, UnpackedKind};
use rustc_mir::monomorphize::Instance;
use std::cell::RefCell;
use std::fmt::{self, Write as FmtWrite};
use std::fs::{self, File};
use std::io::Write;
use std::ops::Range;
use std::path::PathBuf;
use std::time::SystemTime;
use crate::symbol_names::{legacy, mw, v0};
thread_local!(static OUT_DIR: Option<PathBuf> = {
std::env::var_os("RUST_SYMBOL_DUMP_DIR").map(PathBuf::from)
});
thread_local!(static OUTPUT: RefCell<Option<File>> = RefCell::new(None));
pub fn record(
tcx: TyCtxt<'_, 'tcx, 'tcx>,
instance: Instance<'tcx>,
instantiating_crate: Option<CrateNum>,
mangling_version: SymbolManglingVersion,
mangled: String,
) {
let header = "legacy+generics,legacy,mw,mw+compression,v0,v0+compression";
// Reuse the already-mangled symbol name that is used by codegen.
let (legacy_mangling, v0_mangling_plus_compression) = match mangling_version {
SymbolManglingVersion::Legacy =>
(mangled, v0::mangle(tcx, instance, instantiating_crate, true)),
SymbolManglingVersion::V0 =>
(legacy::mangle(tcx, instance, instantiating_crate, false), mangled),
};
// Always attempt all the choices of mangling.
let legacy_mangling_plus_generics =
legacy::mangle(tcx, instance, instantiating_crate, true);
let (mw_mangling, mw_mangling_plus_compression) =
mw::mangle(tcx, instance, instantiating_crate)
.unwrap_or((String::new(), String::new()));
let v0_mangling = v0::mangle(tcx, instance, instantiating_crate, false);
OUTPUT.with(|out| {
let mut out = out.borrow_mut();
if out.is_none() {
OUT_DIR.with(|out_dir| {
if let Some(out_dir) = out_dir {
let mut opts = fs::OpenOptions::new();
opts.write(true).create_new(true);
let mut time = SystemTime::now()
.duration_since(SystemTime::UNIX_EPOCH)
.map(|d| d.as_secs())
.unwrap_or(0);
let mut file = loop {
let file_path = out_dir.join(format!("{}-{}.{}.csv",
tcx.crate_name,
tcx.sess.local_crate_disambiguator(),
time,
));
match opts.open(&file_path) {
Ok(file) => break file,
Err(e) => {
if e.kind() == std::io::ErrorKind::AlreadyExists {
time += 1;
continue;
}
bug!("can't open symbol dump file `{}`: {:?}",
file_path.display(), e);
}
}
};
writeln!(file, "{}", header).unwrap();
*out = Some(file);
}
})
}
if let Some(out) = out.as_mut() {
writeln!(out, "{},{},{},{},{},{}",
legacy_mangling_plus_generics,
legacy_mangling,
mw_mangling,
mw_mangling_plus_compression,
v0_mangling,
v0_mangling_plus_compression,
).unwrap();
}
});
let def_id = instance.def_id();
// FIXME(eddyb) this should ideally not be needed.
let substs =
tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), instance.substs);
// Build the expected output of demangling, via `ty::print`.
let make_expected_demangling = |alternate| {
let cx = DemanglingPrinter {
tcx,
out: String::new(),
alternate,
in_value: true,
binders: vec![],
};
if instance.is_vtable_shim() {
cx.path_append_ns(
|cx| cx.print_def_path(def_id, substs),
'S',
0,
"",
).unwrap().out
} else {
cx.print_def_path(def_id, substs).unwrap().out
}
};
let expected_demangling_alt = make_expected_demangling(true);
let expected_demangling = make_expected_demangling(false);
for mangling in &[&v0_mangling, &v0_mangling_plus_compression] {
match rustc_demangle::try_demangle(mangling) {
Ok(demangling) => {
let demangling_alt = format!("{:#}", demangling);
if demangling_alt.contains('?') {
bug!("demangle(alt) printing failed for {:?}\n{:?}", mangling, demangling_alt);
}
assert_eq!(demangling_alt, expected_demangling_alt);
let demangling = format!("{}", demangling);
if demangling.contains('?') {
bug!("demangle printing failed for {:?}\n{:?}", mangling, demangling);
}
assert_eq!(demangling, expected_demangling);
}
Err(_) => bug!("try_demangle failed for {:?}", mangling),
}
}
}
struct BinderLevel {
lifetime_depths: Range<u32>,
}
// Our expectation of the output of demangling,
// relying on `ty::print` / `PrettyPrinter`.
struct DemanglingPrinter<'a, 'tcx> {
tcx: TyCtxt<'a, 'tcx, 'tcx>,
out: String,
/// Equivalent to `rustc-demangle`'s `{:#}` printing.
alternate: bool,
in_value: bool,
binders: Vec<BinderLevel>,
}
impl fmt::Write for DemanglingPrinter<'_, '_> {
fn write_str(&mut self, s: &str) -> fmt::Result {
self.out.write_str(s)
}
}
impl DemanglingPrinter<'_, '_> {
fn path_append_ns(
mut self,
print_prefix: impl FnOnce(Self) -> Result<Self, fmt::Error>,
ns: char,
disambiguator: u64,
name: &str,
) -> Result<Self, fmt::Error> {
self = print_prefix(self)?;
if let 'A'..='Z' = ns {
self.write_str("::{")?;
match ns {
'C' => self.write_str("closure")?,
'S' => self.write_str("shim")?,
_ => write!(self, "{}", ns)?,
}
if !name.is_empty() {
write!(self, ":{}", name)?;
}
write!(self, "#{}", disambiguator)?;
self.write_str("}")?;
} else {
if !name.is_empty() {
self.write_str("::")?;
self.write_str(&name)?;
}
}
Ok(self)
}
fn print_lifetime_at_depth(&mut self, depth: u64) -> Result<(), fmt::Error> {
if depth < 26 {
write!(self, "'{}", (b'a' + depth as u8) as char)
} else {
write!(self, "'_{}", depth)
}
}
}
impl Printer<'tcx, 'tcx> for DemanglingPrinter<'_, 'tcx> {
type Error = fmt::Error;
type Path = Self;
type Region = Self;
type Type = Self;
type DynExistential = Self;
type Const = Self;
fn tcx(&'a self) -> TyCtxt<'a, 'tcx, 'tcx> {
self.tcx
}
fn print_impl_path(
self,
impl_def_id: DefId,
substs: &'tcx [Kind<'tcx>],
mut self_ty: Ty<'tcx>,
mut impl_trait_ref: Option<ty::TraitRef<'tcx>>,
) -> Result<Self::Path, Self::Error> {
let mut param_env = self.tcx.param_env(impl_def_id)
.with_reveal_all();
if !substs.is_empty() {
param_env = param_env.subst(self.tcx, substs);
}
match &mut impl_trait_ref {
Some(impl_trait_ref) => {
assert_eq!(impl_trait_ref.self_ty(), self_ty);
*impl_trait_ref =
self.tcx.normalize_erasing_regions(param_env, *impl_trait_ref);
self_ty = impl_trait_ref.self_ty();
}
None => {
self_ty = self.tcx.normalize_erasing_regions(param_env, self_ty);
}
}
self.path_qualified(self_ty, impl_trait_ref)
}
fn print_region(
mut self,
region: ty::Region<'_>,
) -> Result<Self::Region, Self::Error> {
match *region {
ty::ReErased => write!(self, "'_")?,
ty::ReLateBound(debruijn, ty::BrAnon(i)) => {
let binder = &self.binders[self.binders.len() - 1 - debruijn.index()];
let depth = binder.lifetime_depths.start + i;
self.print_lifetime_at_depth(depth as u64)?;
}
_ => bug!("symbol_names::dump: non-erased region `{:?}`", region),
}
Ok(self)
}
fn print_type(
mut self,
ty: Ty<'tcx>,
) -> Result<Self::Type, Self::Error> {
match ty.sty {
// Mangled as paths (unlike `pretty_print_type`).
ty::FnDef(def_id, substs) |
ty::Opaque(def_id, substs) |
ty::Projection(ty::ProjectionTy { item_def_id: def_id, substs }) |
ty::UnnormalizedProjection(ty::ProjectionTy { item_def_id: def_id, substs }) |
ty::Closure(def_id, ty::ClosureSubsts { substs }) |
ty::Generator(def_id, ty::GeneratorSubsts { substs }, _) => {
self.print_def_path(def_id, substs)
}
// Mangled as placeholders.
ty::Param(_) | ty::Bound(..) | ty::Placeholder(_) |
ty::Infer(_) | ty::Error => {
write!(self, "_")?;
Ok(self)
}
// Demangled with explicit type for constants (`len` here).
ty::Array(ty, len) if !self.alternate => {
write!(self, "[")?;
self = ty.print(self)?;
write!(self, "; ")?;
if let Some(n) = len.assert_usize(self.tcx()) {
write!(self, "{}", n)?;
} else {
self = len.print(self)?;
}
write!(self, ": usize]")?;
Ok(self)
}
// Demangled without anyparens.
ty::Dynamic(data, r) => {
let print_r = self.region_should_not_be_omitted(r);
write!(self, "dyn ")?;
self = data.print(self)?;
if print_r {
write!(self, " + ")?;
self = r.print(self)?;
}
Ok(self)
}
_ => self.pretty_print_type(ty),
}
}
fn print_dyn_existential(
mut self,
predicates: &'tcx ty::List<ty::ExistentialPredicate<'tcx>>,
) -> Result<Self::DynExistential, Self::Error> {
// Generate the main trait ref, including associated types.
let mut first = true;
if let Some(principal) = predicates.principal() {
self = self.print_def_path(principal.def_id, &[])?;
// Use a type that can't appear in defaults of type parameters.
let dummy_self = self.tcx().mk_ty_infer(ty::FreshTy(0));
let principal = principal.with_self_ty(self.tcx(), dummy_self);
let args = self.generic_args_to_print(
self.tcx().generics_of(principal.def_id),
principal.substs,
);
// Don't print any regions if they're all erased.
let print_regions = args.iter().any(|arg| {
match arg.unpack() {
UnpackedKind::Lifetime(r) => *r != ty::ReErased,
_ => false,
}
});
let mut args = args.iter().cloned().filter(|arg| {
match arg.unpack() {
UnpackedKind::Lifetime(_) => print_regions,
_ => true,
}
});
let mut projections = predicates.projection_bounds();
let arg0 = args.next();
let projection0 = projections.next();
if arg0.is_some() || projection0.is_some() {
let args = arg0.into_iter().chain(args);
let projections = projection0.into_iter().chain(projections);
self = self.generic_delimiters(|mut cx| {
cx = cx.comma_sep(args)?;
if arg0.is_some() && projection0.is_some() {
write!(cx, ", ")?;
}
cx.comma_sep(projections)
})?;
}
first = false;
}
for def_id in predicates.auto_traits() {
if !first {
write!(self, " + ")?;
}
first = false;
self = self.print_def_path(def_id, &[])?;
}
Ok(self)
}
fn print_const(
mut self,
ct: &'tcx ty::Const<'tcx>,
) -> Result<Self::Const, Self::Error> {
if let ty::Uint(_) = ct.ty.sty {
if let Some(bits) = ct.assert_bits(self.tcx, ty::ParamEnv::empty().and(ct.ty)) {
write!(self, "{}", bits)?;
} else {
write!(self, "_")?;
}
} else {
write!(self, "_")?;
}
if !self.alternate {
write!(self, ": ")?;
self = ct.ty.print(self)?;
}
Ok(self)
}
fn path_crate(
mut self,
cnum: CrateNum,
) -> Result<Self::Path, Self::Error> {
self.write_str(&self.tcx.original_crate_name(cnum).as_str())?;
let fingerprint = self.tcx.crate_disambiguator(cnum).to_fingerprint();
if !self.alternate {
write!(self, "[{:x}]", fingerprint.to_smaller_hash())?;
}
Ok(self)
}
fn path_qualified(
self,
self_ty: Ty<'tcx>,
trait_ref: Option<ty::TraitRef<'tcx>>,
) -> Result<Self::Path, Self::Error> {
self.generic_delimiters(|mut cx| {
cx = self_ty.print(cx)?;
if let Some(trait_ref) = trait_ref {
write!(cx, " as ")?;
cx = trait_ref.print(cx)?;
}
Ok(cx)
})
}
fn path_append_impl(
self,
_print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
_disambiguated_data: &DisambiguatedDefPathData,
_self_ty: Ty<'tcx>,
_trait_ref: Option<ty::TraitRef<'tcx>>,
) -> Result<Self::Path, Self::Error> {
unreachable!()
}
fn path_append(
self,
print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
disambiguated_data: &DisambiguatedDefPathData,
) -> Result<Self::Path, Self::Error> {
let ns = match disambiguated_data.data {
DefPathData::ClosureExpr => 'C',
_ => '_',
};
let name = disambiguated_data.data.get_opt_name().map(|s| s.as_str());
let name = name.as_ref().map_or("", |s| &s[..]);
self.path_append_ns(
print_prefix,
ns,
disambiguated_data.disambiguator as u64,
name,
)
}
fn path_generic_args(
mut self,
print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
args: &[Kind<'tcx>],
) -> Result<Self::Path, Self::Error> {
self = print_prefix(self)?;
// Don't print any regions if they're all erased.
let print_regions = args.iter().any(|arg| {
match arg.unpack() {
UnpackedKind::Lifetime(r) => *r != ty::ReErased,
_ => false,
}
});
let args = args.iter().cloned().filter(|arg| {
match arg.unpack() {
UnpackedKind::Lifetime(_) => print_regions,
_ => true,
}
});
if args.clone().next().is_some() {
if self.in_value {
write!(self, "::")?;
}
self.generic_delimiters(|cx| cx.comma_sep(args))
} else {
Ok(self)
}
}
}
impl PrettyPrinter<'tcx, 'tcx> for DemanglingPrinter<'_, 'tcx> {
fn region_should_not_be_omitted(
&self,
region: ty::Region<'_>,
) -> bool {
*region != ty::ReErased
}
fn generic_delimiters(
mut self,
f: impl FnOnce(Self) -> Result<Self, Self::Error>,
) -> Result<Self, Self::Error> {
write!(self, "<")?;
let was_in_value = ::std::mem::replace(&mut self.in_value, false);
self = f(self)?;
self.in_value = was_in_value;
write!(self, ">")?;
Ok(self)
}
fn in_binder<T>(
mut self,
value: &ty::Binder<T>,
) -> Result<Self, Self::Error>
where T: Print<'tcx, 'tcx, Self, Output = Self, Error = Self::Error> + TypeFoldable<'tcx>
{
let regions = if value.has_late_bound_regions() {
self.tcx.collect_referenced_late_bound_regions(value)
} else {
Default::default()
};
let mut lifetime_depths =
self.binders.last().map(|b| b.lifetime_depths.end).map_or(0..0, |i| i..i);
let lifetimes = regions.into_iter().map(|br| {
match br {
ty::BrAnon(i) => i + 1,
_ => bug!("symbol_names: non-anonymized region `{:?}` in `{:?}`", br, value),
}
}).max().unwrap_or(0);
lifetime_depths.end += lifetimes;
if lifetimes > 0 {
write!(self, "for<")?;
for i in lifetime_depths.clone() {
if i > lifetime_depths.start {
write!(self, ", ")?;
}
self.print_lifetime_at_depth(i as u64)?;
}
write!(self, "> ")?;
}
self.binders.push(BinderLevel { lifetime_depths });
self = value.skip_binder().print(self)?;
self.binders.pop();
Ok(self)
}
}

View File

@ -18,7 +18,6 @@ pub(super) fn mangle(
tcx: TyCtxt<'_, 'tcx, 'tcx>,
instance: Instance<'tcx>,
instantiating_crate: Option<CrateNum>,
include_generic_args: bool,
) -> String {
let def_id = instance.def_id();
@ -57,17 +56,11 @@ pub(super) fn mangle(
let hash = get_symbol_hash(tcx, instance, instance_ty, instantiating_crate);
let substs = if include_generic_args {
// FIXME(eddyb) this should ideally not be needed.
&tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), instance.substs)[..]
} else {
&[]
};
let mut printer = SymbolPrinter {
tcx,
path: SymbolPath::new(),
keep_within_component: false,
}.print_def_path(def_id, substs).unwrap();
}.print_def_path(def_id, &[]).unwrap();
if instance.is_vtable_shim() {
let _ = printer.write_str("{{vtable-shim}}");

View File

@ -1,421 +0,0 @@
use std_mangle_rs::ast;
use rustc::hir;
use rustc::hir::def_id::{CrateNum, DefId};
use rustc::hir::map::{DefPathData, DisambiguatedDefPathData};
use rustc::ty::{self, Ty, TyCtxt};
use rustc::ty::print::{Printer, Print};
use rustc::ty::subst::{Kind, UnpackedKind};
use rustc_mir::monomorphize::Instance;
use rustc_target::spec::abi::Abi;
use syntax::ast::{IntTy, UintTy, FloatTy};
use std::sync::Arc;
pub(super) struct Unsupported;
pub(super) fn mangle(
tcx: TyCtxt<'_, 'tcx, 'tcx>,
instance: Instance<'tcx>,
instantiating_crate: Option<CrateNum>,
) -> Result<(String, String), Unsupported> {
if instance.is_vtable_shim() {
return Err(Unsupported);
}
let symbol = ast::Symbol {
version: None,
path: SymbolPrinter { tcx }
.print_def_path(instance.def_id(), instance.substs)?,
instantiating_crate: match instantiating_crate {
Some(instantiating_crate) => Some(
SymbolPrinter { tcx }
.path_crate(instantiating_crate)?
),
None => None,
},
};
let _ = symbol;
unimplemented!("missing compressor/mangler for mw symbol mangling");
/*let mut uncompressed = String::new();
symbol.mangle(&mut uncompressed);
let (compressed_symbol, _) = std_mangle_rs::compress::compress_ext(&symbol);
let mut compressed = String::new();
compressed_symbol.mangle(&mut compressed);
Ok((uncompressed, compressed))*/
}
#[derive(Copy, Clone)]
struct SymbolPrinter<'a, 'tcx> {
tcx: TyCtxt<'a, 'tcx, 'tcx>,
}
impl Printer<'tcx, 'tcx> for SymbolPrinter<'_, 'tcx> {
type Error = Unsupported;
type Path = ast::Path;
type Region = ast::Lifetime;
type Type = ast::Type;
type DynExistential = ast::DynBounds;
type Const = ast::Const;
fn tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx, 'tcx> {
self.tcx
}
fn print_impl_path(
self,
impl_def_id: DefId,
_substs: &[Kind<'tcx>],
self_ty: Ty<'tcx>,
impl_trait_ref: Option<ty::TraitRef<'tcx>>,
) -> Result<Self::Path, Self::Error> {
let key = self.tcx.def_key(impl_def_id);
let parent_def_id = DefId { index: key.parent.unwrap(), ..impl_def_id };
self.path_append_impl(
|cx| cx.print_def_path(parent_def_id, &[]),
&key.disambiguated_data,
self_ty,
impl_trait_ref,
)
}
fn print_region(
self,
region: ty::Region<'_>,
) -> Result<Self::Region, Self::Error> {
let i = match *region {
ty::ReErased => 0,
// FIXME(eddyb) copy the implementation over to here.
ty::ReLateBound(_, ty::BrAnon(_)) => {
return Err(Unsupported);
}
_ => bug!("mw: non-erased region `{:?}`", region),
};
Ok(ast::Lifetime {
debruijn_index: ast::Base62Number(i),
})
}
fn print_type(
self,
ty: Ty<'tcx>,
) -> Result<Self::Type, Self::Error> {
macro_rules! basic {
($name:ident) => (ast::Type::BasicType(ast::BasicType::$name))
}
Ok(match ty.sty {
ty::Bool => basic!(Bool),
ty::Char => basic!(Char),
ty::Str => basic!(Str),
ty::Tuple(_) if ty.is_unit() => basic!(Unit),
ty::Int(IntTy::I8) => basic!(I8),
ty::Int(IntTy::I16) => basic!(I16),
ty::Int(IntTy::I32) => basic!(I32),
ty::Int(IntTy::I64) => basic!(I64),
ty::Int(IntTy::I128) => basic!(I128),
ty::Int(IntTy::Isize) => basic!(Isize),
ty::Uint(UintTy::U8) => basic!(U8),
ty::Uint(UintTy::U16) => basic!(U16),
ty::Uint(UintTy::U32) => basic!(U32),
ty::Uint(UintTy::U64) => basic!(U64),
ty::Uint(UintTy::U128) => basic!(U128),
ty::Uint(UintTy::Usize) => basic!(Usize),
ty::Float(FloatTy::F32) => basic!(F32),
ty::Float(FloatTy::F64) => basic!(F64),
ty::Never => basic!(Never),
// Placeholders (should be demangled as `_`).
ty::Param(_) | ty::Bound(..) | ty::Placeholder(_) |
ty::Infer(_) | ty::Error => basic!(Placeholder),
ty::Ref(r, ty, mutbl) => {
let lt = if *r != ty::ReErased {
Some(r.print(self)?)
} else {
None
};
let ty = Arc::new(ty.print(self)?);
match mutbl {
hir::MutImmutable => ast::Type::Ref(lt, ty),
hir::MutMutable => ast::Type::RefMut(lt, ty),
}
}
ty::RawPtr(ty::TypeAndMut { ty, mutbl: hir::MutImmutable }) => {
ast::Type::RawPtrConst(Arc::new(ty.print(self)?))
}
ty::RawPtr(ty::TypeAndMut { ty, mutbl: hir::MutMutable }) => {
ast::Type::RawPtrMut(Arc::new(ty.print(self)?))
}
ty::Array(ty, len) => {
ast::Type::Array(Arc::new(ty.print(self)?), Arc::new(len.print(self)?))
}
ty::Slice(ty) => ast::Type::Slice(Arc::new(ty.print(self)?)),
ty::Tuple(tys) => {
let tys = tys.iter()
.map(|k| k.expect_ty().print(self))
.collect::<Result<Vec<_>, _>>()?;
ast::Type::Tuple(tys)
}
// Mangle all nominal types as paths.
ty::Adt(&ty::AdtDef { did: def_id, .. }, substs) |
ty::FnDef(def_id, substs) |
ty::Opaque(def_id, substs) |
ty::Projection(ty::ProjectionTy { item_def_id: def_id, substs }) |
ty::UnnormalizedProjection(ty::ProjectionTy { item_def_id: def_id, substs }) |
ty::Closure(def_id, ty::ClosureSubsts { substs }) |
ty::Generator(def_id, ty::GeneratorSubsts { substs }, _) => {
ast::Type::Named(Arc::new(self.print_def_path(def_id, substs)?))
}
ty::Foreign(def_id) => {
ast::Type::Named(Arc::new(self.print_def_path(def_id, &[])?))
}
ty::FnPtr(sig) => {
let mut param_types = sig.inputs().skip_binder().iter()
.map(|ty| ty.print(self))
.collect::<Result<Vec<_>, _>>()?;
if sig.c_variadic() {
param_types.push(basic!(Ellipsis));
}
let return_type = sig.output().skip_binder().print(self)?;
ast::Type::Fn(Arc::new(ast::FnSig {
binder: ast::Binder {
// FIXME(eddyb) needs to be implemented, see `print_region`.
count: ast::Base62Number(0),
},
is_unsafe: sig.unsafety() == hir::Unsafety::Unsafe,
abi: match sig.abi() {
Abi::Rust => None,
Abi::C => Some(ast::Abi::C),
abi => Some(ast::Abi::Named(ast::UIdent(abi.name().replace('-', "_")))),
},
param_types,
return_type,
}))
}
ty::Dynamic(predicates, r) => {
let bounds = Arc::new(self.print_dyn_existential(predicates.skip_binder())?);
let lt = r.print(self)?;
ast::Type::DynTrait(bounds, lt)
}
ty::GeneratorWitness(_) => {
bug!("mw: unexpected `GeneratorWitness`")
}
})
}
fn print_dyn_existential(
self,
predicates: &'tcx ty::List<ty::ExistentialPredicate<'tcx>>,
) -> Result<Self::DynExistential, Self::Error> {
let mut traits = vec![];
for predicate in predicates {
match *predicate {
ty::ExistentialPredicate::Trait(trait_ref) => {
// Use a type that can't appear in defaults of type parameters.
let dummy_self = self.tcx.mk_infer(ty::FreshTy(0));
let trait_ref = trait_ref.with_self_ty(self.tcx, dummy_self);
traits.push(ast::DynTrait {
path: self.print_def_path(trait_ref.def_id, trait_ref.substs)?,
assoc_type_bindings: vec![],
});
}
ty::ExistentialPredicate::Projection(projection) => {
let name = self.tcx.associated_item(projection.item_def_id).ident;
traits.last_mut().unwrap().assoc_type_bindings.push(ast::DynTraitAssocBinding {
ident: ast::UIdent(name.to_string()),
ty: projection.ty.print(self)?,
});
}
ty::ExistentialPredicate::AutoTrait(def_id) => {
traits.push(ast::DynTrait {
path: self.print_def_path(def_id, &[])?,
assoc_type_bindings: vec![],
});
}
}
}
Ok(ast::DynBounds {
binder: ast::Binder {
// FIXME(eddyb) needs to be implemented, see `print_region`.
count: ast::Base62Number(0),
},
traits,
})
}
fn print_const(
self,
ct: &'tcx ty::Const<'tcx>,
) -> Result<Self::Const, Self::Error> {
match ct.ty.sty {
ty::Uint(_) => {}
_ => {
bug!("mw: unsupported constant of type `{}` ({:?})",
ct.ty, ct);
}
}
let ty = ct.ty.print(self)?;
if let Some(bits) = ct.assert_bits(self.tcx, ty::ParamEnv::empty().and(ct.ty)) {
if bits as u64 as u128 != bits {
return Err(Unsupported);
}
Ok(ast::Const::Value(ty, bits as u64))
} else {
// NOTE(eddyb) despite having the path, we need to
// encode a placeholder, as the path could refer
// back to e.g. an `impl` using the constant.
Ok(ast::Const::Placeholder(ty))
}
}
fn path_crate(
self,
cnum: CrateNum,
) -> Result<Self::Path, Self::Error> {
let fingerprint = self.tcx.crate_disambiguator(cnum).to_fingerprint();
Ok(ast::Path::CrateRoot {
id: ast::Ident {
dis: ast::Base62Number(fingerprint.to_smaller_hash()),
u_ident: ast::UIdent(self.tcx.original_crate_name(cnum).to_string()),
},
})
}
fn path_qualified(
self,
self_ty: Ty<'tcx>,
trait_ref: Option<ty::TraitRef<'tcx>>,
) -> Result<Self::Path, Self::Error> {
assert!(trait_ref.is_some());
let trait_ref = trait_ref.unwrap();
// This is a default method in the trait declaration.
Ok(ast::Path::TraitDef {
self_type: self_ty.print(self)?,
trait_name: Arc::new(self.print_def_path(trait_ref.def_id, trait_ref.substs)?),
})
}
fn path_append_impl(
self,
print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
disambiguated_data: &DisambiguatedDefPathData,
self_ty: Ty<'tcx>,
trait_ref: Option<ty::TraitRef<'tcx>>,
) -> Result<Self::Path, Self::Error> {
let impl_path = ast::ImplPath {
dis: Some(ast::Base62Number(disambiguated_data.disambiguator as u64)),
path: Arc::new(print_prefix(self)?),
};
let self_type = self_ty.print(self)?;
match trait_ref {
Some(trait_ref) => Ok(ast::Path::TraitImpl {
impl_path,
self_type,
trait_name: Arc::new(self.print_def_path(trait_ref.def_id, trait_ref.substs)?),
}),
None => Ok(ast::Path::InherentImpl {
impl_path,
self_type,
}),
}
}
fn path_append(
self,
print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
disambiguated_data: &DisambiguatedDefPathData,
) -> Result<Self::Path, Self::Error> {
let inner = Arc::new(print_prefix(self)?);
let name = disambiguated_data.data.get_opt_name().map(|s| s.as_str());
let name = name.as_ref().map_or("", |s| &s[..]);
let ns = match disambiguated_data.data {
DefPathData::ClosureExpr => ast::Namespace(b'C'),
// Lowercase a-z are unspecified disambiguation categories.
_ => {
let discriminant = unsafe {
::std::intrinsics::discriminant_value(&disambiguated_data.data)
};
assert!(discriminant < 26);
// Mix in the name to avoid making it too predictable.
let mut d = (discriminant ^ 0x55) % 26;
for (i, b) in name.bytes().enumerate() {
d = (d + i as u64 + b as u64) % 26;
}
ast::Namespace(b'a' + d as u8)
}
};
Ok(ast::Path::Nested {
ns,
inner,
ident: ast::Ident {
dis: ast::Base62Number(disambiguated_data.disambiguator as u64),
u_ident: ast::UIdent(name.to_string()),
}
})
}
fn path_generic_args(
self,
print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
args: &[Kind<'tcx>],
) -> Result<Self::Path, Self::Error> {
let prefix = print_prefix(self)?;
// Don't print any regions if they're all erased.
let print_regions = args.iter().any(|arg| {
match arg.unpack() {
UnpackedKind::Lifetime(r) => *r != ty::ReErased,
_ => false,
}
});
let args = args.iter().cloned().filter(|arg| {
match arg.unpack() {
UnpackedKind::Lifetime(_) => print_regions,
_ => true,
}
});
if args.clone().next().is_none() {
return Ok(prefix);
}
let args = args.map(|arg| {
Ok(match arg.unpack() {
UnpackedKind::Lifetime(lt) => {
ast::GenericArg::Lifetime(lt.print(self)?)
}
UnpackedKind::Type(ty) => {
ast::GenericArg::Type(ty.print(self)?)
}
UnpackedKind::Const(ct) => {
ast::GenericArg::Const(ct.print(self)?)
}
})
}).collect::<Result<Vec<_>, _>>()?;
Ok(ast::Path::Generic {
inner: Arc::new(prefix),
args,
})
}
}

View File

@ -17,7 +17,6 @@ pub(super) fn mangle(
tcx: TyCtxt<'_, 'tcx, 'tcx>,
instance: Instance<'tcx>,
instantiating_crate: Option<CrateNum>,
compress: bool,
) -> String {
let def_id = instance.def_id();
// FIXME(eddyb) this should ideally not be needed.
@ -27,17 +26,13 @@ pub(super) fn mangle(
let prefix = "_R";
let mut cx = SymbolMangler {
tcx,
compress: if compress {
Some(Box::new(CompressionCaches {
start_offset: prefix.len(),
compress: Some(Box::new(CompressionCaches {
start_offset: prefix.len(),
paths: FxHashMap::default(),
types: FxHashMap::default(),
consts: FxHashMap::default(),
}))
} else {
None
},
paths: FxHashMap::default(),
types: FxHashMap::default(),
consts: FxHashMap::default(),
})),
binders: vec![],
out: String::from(prefix),
};

View File

@ -6,10 +6,6 @@ use std::path::Path;
/// List of whitelisted sources for packages.
const WHITELISTED_SOURCES: &[&str] = &[
"\"registry+https://github.com/rust-lang/crates.io-index\"",
"\"git+https://github.com/michaelwoerister/std-mangle-rs?\
rev=e884304cfcb2f636db4d59ca8ad8fa95b983281c#\
e884304cfcb2f636db4d59ca8ad8fa95b983281c\"",
];
/// Checks for external package sources.