Skip to content

Commit 2e19453

Browse files
eddybtmiasko
authored andcommitted
rustc_symbol_mangling: support structural constants and &str in v0.
1 parent 7d2c334 commit 2e19453

File tree

2 files changed

+101
-0
lines changed

2 files changed

+101
-0
lines changed

compiler/rustc_symbol_mangling/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@
9191
#![feature(never_type)]
9292
#![feature(nll)]
9393
#![feature(in_band_lifetimes)]
94+
#![feature(iter_zip)]
9495
#![recursion_limit = "256"]
9596

9697
#[macro_use]

compiler/rustc_symbol_mangling/src/v0.rs

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
use rustc_data_structures::base_n;
22
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
33
use rustc_hir as hir;
4+
use rustc_hir::def::CtorKind;
45
use rustc_hir::def_id::{CrateNum, DefId};
56
use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData};
7+
use rustc_middle::mir::interpret::ConstValue;
68
use rustc_middle::ty::layout::IntegerExt;
79
use rustc_middle::ty::print::{Print, Printer};
810
use rustc_middle::ty::subst::{GenericArg, GenericArgKind, Subst};
@@ -11,6 +13,7 @@ use rustc_target::abi::Integer;
1113
use rustc_target::spec::abi::Abi;
1214

1315
use std::fmt::Write;
16+
use std::iter;
1417
use std::ops::Range;
1518

1619
pub(super) fn mangle(
@@ -589,6 +592,103 @@ impl Printer<'tcx> for SymbolMangler<'tcx> {
589592

590593
let _ = write!(self.out, "{:x}_", bits);
591594
}
595+
596+
// HACK(eddyb) because `ty::Const` only supports sized values (for now),
597+
// we can't use `deref_const` + supporting `str`, we have to specially
598+
// handle `&str` and include both `&` ("R") and `str` ("e") prefixes.
599+
ty::Ref(_, ty, hir::Mutability::Not) if *ty == self.tcx.types.str_ => {
600+
self.push("R");
601+
match ct.val {
602+
ty::ConstKind::Value(ConstValue::Slice { data, start, end }) => {
603+
// NOTE(eddyb) the following comment was kept from `ty::print::pretty`:
604+
// The `inspect` here is okay since we checked the bounds, and there are no
605+
// relocations (we have an active `str` reference here). We don't use this
606+
// result to affect interpreter execution.
607+
let slice =
608+
data.inspect_with_uninit_and_ptr_outside_interpreter(start..end);
609+
let s = std::str::from_utf8(slice).expect("non utf8 str from miri");
610+
611+
self.push("e");
612+
// FIXME(eddyb) use a specialized hex-encoding loop.
613+
for byte in s.bytes() {
614+
let _ = write!(self.out, "{:02x}", byte);
615+
}
616+
self.push("_");
617+
}
618+
619+
_ => {
620+
bug!("symbol_names: unsupported `&str` constant: {:?}", ct);
621+
}
622+
}
623+
}
624+
625+
ty::Ref(_, _, mutbl) => {
626+
self.push(match mutbl {
627+
hir::Mutability::Not => "R",
628+
hir::Mutability::Mut => "Q",
629+
});
630+
self = self.tcx.deref_const(ty::ParamEnv::reveal_all().and(ct)).print(self)?;
631+
}
632+
633+
ty::Array(..) | ty::Tuple(..) | ty::Adt(..) => {
634+
let contents = self.tcx.destructure_const(ty::ParamEnv::reveal_all().and(ct));
635+
let fields = contents.fields.iter().copied();
636+
637+
let print_field_list = |mut this: Self, prefix| {
638+
this.push(prefix);
639+
for field in fields.clone() {
640+
this = field.print(this)?;
641+
}
642+
this.push("E");
643+
Ok(this)
644+
};
645+
646+
match *ct.ty.kind() {
647+
ty::Array(..) => {
648+
self = print_field_list(self, "A")?;
649+
}
650+
ty::Tuple(..) => {
651+
self = print_field_list(self, "T")?;
652+
}
653+
ty::Adt(def, substs) => {
654+
let variant_idx =
655+
contents.variant.expect("destructed const of adt without variant idx");
656+
let variant_def = &def.variants[variant_idx];
657+
658+
self.push("V");
659+
self = self.print_def_path(variant_def.def_id, substs)?;
660+
661+
match variant_def.ctor_kind {
662+
CtorKind::Const => {
663+
self.push("u");
664+
}
665+
CtorKind::Fn => {
666+
self = print_field_list(self, "T")?;
667+
}
668+
CtorKind::Fictive => {
669+
for (field_def, field) in iter::zip(&variant_def.fields, fields) {
670+
// HACK(eddyb) this mimics `path_append`,
671+
// instead of simply using `field_def.ident`,
672+
// just to be able to handle disambiguators.
673+
let disambiguated_field =
674+
self.tcx.def_key(field_def.did).disambiguated_data;
675+
let field_name =
676+
disambiguated_field.data.get_opt_name().map(|s| s.as_str());
677+
self.push_disambiguator(
678+
disambiguated_field.disambiguator as u64,
679+
);
680+
self.push_ident(&field_name.as_ref().map_or("", |s| &s[..]));
681+
682+
self = field.print(self)?;
683+
}
684+
self.push("E");
685+
}
686+
}
687+
}
688+
_ => unreachable!(),
689+
}
690+
}
691+
592692
_ => {
593693
bug!("symbol_names: unsupported constant of type `{}` ({:?})", ct.ty, ct);
594694
}

0 commit comments

Comments
 (0)