about summary refs log tree commit diff
path: root/src/librustc_codegen_utils
diff options
context:
space:
mode:
authorEduard-Mihai Burtescu <edy.burt@gmail.com>2018-12-21 17:10:21 +0200
committerEduard-Mihai Burtescu <edy.burt@gmail.com>2019-03-15 13:25:10 +0200
commita15bfc6f483c552f793932f7ac7fcbb69d187681 (patch)
tree6547c71ccaf526b15a413b46ef3708a88d850b14 /src/librustc_codegen_utils
parentb0fbca953fbdcef5e561a97e5936db0dd13c41d2 (diff)
downloadrust-a15bfc6f483c552f793932f7ac7fcbb69d187681.tar.gz
rust-a15bfc6f483c552f793932f7ac7fcbb69d187681.zip
rustc: merge PrintCx::parameterized and def_path printing.
Diffstat (limited to 'src/librustc_codegen_utils')
-rw-r--r--src/librustc_codegen_utils/symbol_names.rs182
1 files changed, 110 insertions, 72 deletions
diff --git a/src/librustc_codegen_utils/symbol_names.rs b/src/librustc_codegen_utils/symbol_names.rs
index b417091704d..4c7b00ae078 100644
--- a/src/librustc_codegen_utils/symbol_names.rs
+++ b/src/librustc_codegen_utils/symbol_names.rs
@@ -93,7 +93,7 @@ use rustc::hir::Node;
 use rustc::hir::CodegenFnAttrFlags;
 use rustc::hir::map::definitions::DefPathData;
 use rustc::ich::NodeIdHashingMode;
-use rustc::ty::print::{PrintCx, Printer};
+use rustc::ty::print::{PrettyPath, PrettyPrinter, PrintCx, Printer};
 use rustc::ty::query::Providers;
 use rustc::ty::subst::SubstsRef;
 use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
@@ -106,8 +106,9 @@ use syntax_pos::symbol::Symbol;
 
 use log::debug;
 
-use std::fmt::Write;
-use std::mem::discriminant;
+use std::fmt::{self, Write};
+use std::iter;
+use std::mem::{self, discriminant};
 
 pub fn provide(providers: &mut Providers<'_>) {
     *providers = Providers {
@@ -225,9 +226,9 @@ fn get_symbol_hash<'a, 'tcx>(
 
 fn def_symbol_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> ty::SymbolName {
     ty::print::with_forced_absolute_paths(|| {
-        PrintCx::new(tcx, SymbolPathPrinter)
-            .print_def_path(def_id, None, Namespace::ValueNS)
-            .into_interned()
+        let mut cx = PrintCx::new(tcx, SymbolPath::new(tcx));
+        let _ = cx.print_def_path(def_id, None, Namespace::ValueNS, iter::empty());
+        cx.printer.into_interned()
     })
 }
 
@@ -323,7 +324,7 @@ fn compute_symbol_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, instance: Instance
     let mut buf = SymbolPath::from_interned(tcx.def_symbol_name(def_id), tcx);
 
     if instance.is_vtable_shim() {
-        buf.push("{{vtable-shim}}");
+        let _ = buf.write_str("{{vtable-shim}}");
     }
 
     buf.finish(hash)
@@ -347,6 +348,12 @@ struct SymbolPath {
     result: String,
     temp_buf: String,
     strict_naming: bool,
+
+    // When `true`, `finalize_pending_component` is a noop.
+    // This is needed when recursing into `path_qualified`,
+    // or `path_generic_args`, as any nested paths are
+    // logically within one component.
+    keep_within_component: bool,
 }
 
 impl SymbolPath {
@@ -355,6 +362,7 @@ impl SymbolPath {
             result: String::with_capacity(64),
             temp_buf: String::with_capacity(16),
             strict_naming: tcx.has_strict_asm_symbol_naming(),
+            keep_within_component: false,
         };
         result.result.push_str("_ZN"); // _Z == Begin name-sequence, N == nested
         result
@@ -365,109 +373,139 @@ impl SymbolPath {
             result: String::with_capacity(64),
             temp_buf: String::with_capacity(16),
             strict_naming: tcx.has_strict_asm_symbol_naming(),
+            keep_within_component: false,
         };
         result.result.push_str(&symbol.as_str());
         result
     }
 
-    fn into_interned(self) -> ty::SymbolName {
+    fn into_interned(mut self) -> ty::SymbolName {
+        self.finalize_pending_component();
         ty::SymbolName {
             name: Symbol::intern(&self.result).as_interned_str(),
         }
     }
 
-    fn push(&mut self, text: &str) {
-        self.temp_buf.clear();
-        let need_underscore = sanitize(&mut self.temp_buf, text, self.strict_naming);
-        let _ = write!(
-            self.result,
-            "{}",
-            self.temp_buf.len() + (need_underscore as usize)
-        );
-        if need_underscore {
-            self.result.push('_');
+    fn finalize_pending_component(&mut self) {
+        if !self.keep_within_component && !self.temp_buf.is_empty() {
+            let _ = write!(self.result, "{}{}", self.temp_buf.len(), self.temp_buf);
+            self.temp_buf.clear();
         }
-        self.result.push_str(&self.temp_buf);
     }
 
     fn finish(mut self, hash: u64) -> String {
+        self.finalize_pending_component();
         // E = end name-sequence
         let _ = write!(self.result, "17h{:016x}E", hash);
         self.result
     }
 }
 
-struct SymbolPathPrinter;
+// HACK(eddyb) this relies on using the `fmt` interface to get
+// `PrettyPrinter` aka pretty printing of e.g. types in paths,
+// symbol names should have their own printing machinery.
 
-impl Printer for SymbolPathPrinter {
-    type Path = SymbolPath;
+impl Printer for SymbolPath {
+    type Path = Result<PrettyPath, fmt::Error>;
 
     fn path_crate(self: &mut PrintCx<'_, '_, '_, Self>, cnum: CrateNum) -> Self::Path {
-        let mut path = SymbolPath::new(self.tcx);
-        path.push(&self.tcx.original_crate_name(cnum).as_str());
-        path
+        self.printer.write_str(&self.tcx.original_crate_name(cnum).as_str())?;
+        Ok(PrettyPath { empty: false })
+    }
+    fn path_qualified(
+        self: &mut PrintCx<'_, '_, 'tcx, Self>,
+        self_ty: Ty<'tcx>,
+        trait_ref: Option<ty::TraitRef<'tcx>>,
+    ) -> Self::Path {
+        let kept_within_component = mem::replace(&mut self.printer.keep_within_component, true);
+        let r = self.pretty_path_qualified(self_ty, trait_ref);
+        self.printer.keep_within_component = kept_within_component;
+        r
     }
     fn path_impl(self: &mut PrintCx<'_, '_, '_, Self>, text: &str) -> Self::Path {
-        let mut path = SymbolPath::new(self.tcx);
-        path.push(text);
-        path
+        self.printer.write_str(text)?;
+        Ok(PrettyPath { empty: false })
     }
     fn path_append(
         self: &mut PrintCx<'_, '_, '_, Self>,
-        mut path: Self::Path,
+        _: Self::Path,
         text: &str,
     ) -> Self::Path {
-        path.push(text);
-        path
+        self.printer.finalize_pending_component();
+        self.printer.write_str(text)?;
+        Ok(PrettyPath { empty: false })
+    }
+    fn path_generic_args(
+        self: &mut PrintCx<'_, '_, 'tcx, Self>,
+        path: Self::Path,
+        params: &[ty::GenericParamDef],
+        substs: SubstsRef<'tcx>,
+        ns: Namespace,
+        projections: impl Iterator<Item = ty::ExistentialProjection<'tcx>>,
+    ) -> Self::Path {
+        let kept_within_component = mem::replace(&mut self.printer.keep_within_component, true);
+        let r = self.pretty_path_generic_args(path, params, substs, ns, projections);
+        self.printer.keep_within_component = kept_within_component;
+        r
     }
 }
 
-// Name sanitation. LLVM will happily accept identifiers with weird names, but
-// gas doesn't!
-// gas accepts the following characters in symbols: a-z, A-Z, 0-9, ., _, $
-// NVPTX assembly has more strict naming rules than gas, so additionally, dots
-// are replaced with '$' there.
-//
-// returns true if an underscore must be added at the start
-fn sanitize(result: &mut String, s: &str, strict_naming: bool) -> bool {
-    for c in s.chars() {
-        match c {
-            // Escape these with $ sequences
-            '@' => result.push_str("$SP$"),
-            '*' => result.push_str("$BP$"),
-            '&' => result.push_str("$RF$"),
-            '<' => result.push_str("$LT$"),
-            '>' => result.push_str("$GT$"),
-            '(' => result.push_str("$LP$"),
-            ')' => result.push_str("$RP$"),
-            ',' => result.push_str("$C$"),
-
-            '-' | ':' | '.' if strict_naming => {
-                // NVPTX doesn't support these characters in symbol names.
-                result.push('$')
+impl PrettyPrinter for SymbolPath {}
+
+impl fmt::Write for SymbolPath {
+    fn write_str(&mut self, s: &str) -> fmt::Result {
+        // Name sanitation. LLVM will happily accept identifiers with weird names, but
+        // gas doesn't!
+        // gas accepts the following characters in symbols: a-z, A-Z, 0-9, ., _, $
+        // NVPTX assembly has more strict naming rules than gas, so additionally, dots
+        // are replaced with '$' there.
+
+        for c in s.chars() {
+            if self.temp_buf.is_empty() {
+                match c {
+                    'a'..='z' | 'A'..='Z' | '_' => {}
+                    _ => {
+                        // Underscore-qualify anything that didn't start as an ident.
+                        self.temp_buf.push('_');
+                    }
+                }
             }
+            match c {
+                // Escape these with $ sequences
+                '@' => self.temp_buf.push_str("$SP$"),
+                '*' => self.temp_buf.push_str("$BP$"),
+                '&' => self.temp_buf.push_str("$RF$"),
+                '<' => self.temp_buf.push_str("$LT$"),
+                '>' => self.temp_buf.push_str("$GT$"),
+                '(' => self.temp_buf.push_str("$LP$"),
+                ')' => self.temp_buf.push_str("$RP$"),
+                ',' => self.temp_buf.push_str("$C$"),
+
+                '-' | ':' | '.' if self.strict_naming => {
+                    // NVPTX doesn't support these characters in symbol names.
+                    self.temp_buf.push('$')
+                }
 
-            // '.' doesn't occur in types and functions, so reuse it
-            // for ':' and '-'
-            '-' | ':' => result.push('.'),
-
-            // These are legal symbols
-            'a'..='z' | 'A'..='Z' | '0'..='9' | '_' | '.' | '$' => result.push(c),
-
-            _ => {
-                result.push('$');
-                for c in c.escape_unicode().skip(1) {
-                    match c {
-                        '{' => {}
-                        '}' => result.push('$'),
-                        c => result.push(c),
+                // '.' doesn't occur in types and functions, so reuse it
+                // for ':' and '-'
+                '-' | ':' => self.temp_buf.push('.'),
+
+                // These are legal symbols
+                'a'..='z' | 'A'..='Z' | '0'..='9' | '_' | '.' | '$' => self.temp_buf.push(c),
+
+                _ => {
+                    self.temp_buf.push('$');
+                    for c in c.escape_unicode().skip(1) {
+                        match c {
+                            '{' => {}
+                            '}' => self.temp_buf.push('$'),
+                            c => self.temp_buf.push(c),
+                        }
                     }
                 }
             }
         }
-    }
 
-    // Underscore-qualify anything that didn't start as an ident.
-    !result.is_empty() && result.as_bytes()[0] != '_' as u8
-        && !(result.as_bytes()[0] as char).is_xid_start()
+        Ok(())
+    }
 }