]> git.lizzy.rs Git - rust.git/blobdiff - src/pretty_clif.rs
Use the new cranelift-module interface
[rust.git] / src / pretty_clif.rs
index 66b3c66334f80aa4698accfd343f48864dc89efb..e99bec45a5efed5e7ddb88b7b63d78d4ae62d43d 100644 (file)
-use std::borrow::Cow;
-use std::collections::HashMap;
+//! This module provides the [CommentWriter] which makes it possible
+//! to add comments to the written cranelift ir.
+//!
+//! # Example
+//!
+//! ```clif
+//! test compile
+//! target x86_64
+//!
+//! function u0:0(i64, i64, i64) system_v {
+//! ; symbol _ZN119_$LT$example..IsNotEmpty$u20$as$u20$mini_core..FnOnce$LT$$LP$$RF$$u27$a$u20$$RF$$u27$b$u20$$u5b$u16$u5d$$C$$RP$$GT$$GT$9call_once17he85059d5e6a760a0E
+//! ; instance Instance { def: Item(DefId(0/0:29 ~ example[8787]::{{impl}}[0]::call_once[0])), substs: [ReErased, ReErased] }
+//! ; sig ([IsNotEmpty, (&&[u16],)]; c_variadic: false)->(u8, u8)
+//!
+//! ; ssa {_2: NOT_SSA, _4: NOT_SSA, _0: NOT_SSA, _3: (empty), _1: NOT_SSA}
+//! ; msg   loc.idx    param    pass mode            ssa flags  ty
+//! ; ret    _0      = v0       ByRef                NOT_SSA    (u8, u8)
+//! ; arg    _1      = v1       ByRef                NOT_SSA    IsNotEmpty
+//! ; arg    _2.0    = v2       ByVal(types::I64)    NOT_SSA    &&[u16]
+//!
+//!     ss0 = explicit_slot 0 ; _1: IsNotEmpty size=0 align=1,8
+//!     ss1 = explicit_slot 8 ; _2: (&&[u16],) size=8 align=8,8
+//!     ss2 = explicit_slot 8 ; _4: (&&[u16],) size=8 align=8,8
+//!     sig0 = (i64, i64, i64) system_v
+//!     sig1 = (i64, i64, i64) system_v
+//!     fn0 = colocated u0:6 sig1 ; Instance { def: Item(DefId(0/0:31 ~ example[8787]::{{impl}}[1]::call_mut[0])), substs: [ReErased, ReErased] }
+//!
+//! block0(v0: i64, v1: i64, v2: i64):
+//!     v3 = stack_addr.i64 ss0
+//!     v4 = stack_addr.i64 ss1
+//!     store v2, v4
+//!     v5 = stack_addr.i64 ss2
+//!     jump block1
+//!
+//! block1:
+//!     nop
+//! ; _3 = &mut _1
+//! ; _4 = _2
+//!     v6 = load.i64 v4
+//!     store v6, v5
+//! ;
+//! ; _0 = const mini_core::FnMut::call_mut(move _3, move _4)
+//!     v7 = load.i64 v5
+//!     call fn0(v0, v3, v7)
+//!     jump block2
+//!
+//! block2:
+//!     nop
+//! ;
+//! ; return
+//!     return
+//! }
+//! ```
+
 use std::fmt;
 
-use cranelift::codegen::{
+use cranelift_codegen::{
     entity::SecondaryMap,
-    ir::{
-        self,
-        entities::AnyEntity,
-        function::DisplayFunctionAnnotations,
-    },
+    ir::{entities::AnyEntity, function::DisplayFunctionAnnotations},
     write::{FuncWriter, PlainWriter},
-    ValueLabelsRanges,
 };
 
-use crate::prelude::*;
+use rustc_session::config::OutputType;
 
-/// This module provides the [CommentWriter] which makes it possible
-/// to add comments to the written cranelift ir.
-///
-/// # Example
-///
-/// ```clif
-/// test compile
-/// target x86_64
-///
-/// function u0:0(i64, i64, i64) system_v {
-/// ; symbol _ZN119_$LT$example..IsNotEmpty$u20$as$u20$mini_core..FnOnce$LT$$LP$$RF$$u27$a$u20$$RF$$u27$b$u20$$u5b$u16$u5d$$C$$RP$$GT$$GT$9call_once17he85059d5e6a760a0E
-/// ; instance Instance { def: Item(DefId(0/0:29 ~ example[8787]::{{impl}}[0]::call_once[0])), substs: [ReErased, ReErased] }
-/// ; sig ([IsNotEmpty, (&&[u16],)]; c_variadic: false)->(u8, u8)
-///
-/// ; ssa {_2: NOT_SSA, _4: NOT_SSA, _0: NOT_SSA, _3: (empty), _1: NOT_SSA}
-/// ; msg   loc.idx    param    pass mode            ssa flags  ty
-/// ; ret    _0      = v0       ByRef                NOT_SSA    (u8, u8)
-/// ; arg    _1      = v1       ByRef                NOT_SSA    IsNotEmpty
-/// ; arg    _2.0    = v2       ByVal(types::I64)    NOT_SSA    &&[u16]
-///
-///     ss0 = explicit_slot 0 ; _1: IsNotEmpty size=0 align=1,8
-///     ss1 = explicit_slot 8 ; _2: (&&[u16],) size=8 align=8,8
-///     ss2 = explicit_slot 8 ; _4: (&&[u16],) size=8 align=8,8
-///     sig0 = (i64, i64, i64) system_v
-///     sig1 = (i64, i64, i64) system_v
-///     fn0 = colocated u0:6 sig1 ; Instance { def: Item(DefId(0/0:31 ~ example[8787]::{{impl}}[1]::call_mut[0])), substs: [ReErased, ReErased] }
-///
-/// ebb0(v0: i64, v1: i64, v2: i64):
-///     v3 = stack_addr.i64 ss0
-///     v4 = stack_addr.i64 ss1
-///     store v2, v4
-///     v5 = stack_addr.i64 ss2
-///     jump ebb1
-///
-/// ebb1:
-///     nop
-/// ; _3 = &mut _1
-/// ; _4 = _2
-///     v6 = load.i64 v4
-///     store v6, v5
-/// ;
-/// ; _0 = const mini_core::FnMut::call_mut(move _3, move _4)
-///     v7 = load.i64 v5
-///     call fn0(v0, v3, v7)
-///     jump ebb2
-///
-/// ebb2:
-///     nop
-/// ;
-/// ; return
-///     return
-/// }
-/// ```
+use crate::prelude::*;
 
 #[derive(Debug)]
-pub struct CommentWriter {
+pub(crate) struct CommentWriter {
     global_comments: Vec<String>,
-    entity_comments: HashMap<AnyEntity, String>,
-    inst_comments: HashMap<Inst, String>,
+    entity_comments: FxHashMap<AnyEntity, String>,
 }
 
 impl CommentWriter {
-    pub fn new<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, instance: Instance<'tcx>) -> Self {
-        CommentWriter {
-            global_comments: vec![
-                format!("symbol {}", tcx.symbol_name(instance).as_str()),
+    pub(crate) fn new<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> Self {
+        let global_comments = if cfg!(debug_assertions) {
+            vec![
+                format!("symbol {}", tcx.symbol_name(instance).name),
                 format!("instance {:?}", instance),
-                format!("sig {:?}", tcx.normalize_erasing_late_bound_regions(ParamEnv::reveal_all(), &instance.fn_sig(tcx))),
+                format!(
+                    "sig {:?}",
+                    tcx.normalize_erasing_late_bound_regions(
+                        ParamEnv::reveal_all(),
+                        &crate::abi::fn_sig_for_fn_abi(tcx, instance)
+                    )
+                ),
                 String::new(),
-            ],
-            entity_comments: HashMap::new(),
-            inst_comments: HashMap::new(),
+            ]
+        } else {
+            vec![]
+        };
+
+        CommentWriter {
+            global_comments,
+            entity_comments: FxHashMap::default(),
+        }
+    }
+}
+
+#[cfg(debug_assertions)]
+impl CommentWriter {
+    pub(crate) fn add_global_comment<S: Into<String>>(&mut self, comment: S) {
+        self.global_comments.push(comment.into());
+    }
+
+    pub(crate) fn add_comment<S: Into<String> + AsRef<str>, E: Into<AnyEntity>>(
+        &mut self,
+        entity: E,
+        comment: S,
+    ) {
+        use std::collections::hash_map::Entry;
+        match self.entity_comments.entry(entity.into()) {
+            Entry::Occupied(mut occ) => {
+                occ.get_mut().push('\n');
+                occ.get_mut().push_str(comment.as_ref());
+            }
+            Entry::Vacant(vac) => {
+                vac.insert(comment.into());
+            }
         }
     }
 }
 
-impl<'a> FuncWriter for &'a CommentWriter {
+impl FuncWriter for &'_ CommentWriter {
     fn write_preamble(
         &mut self,
         w: &mut dyn fmt::Write,
@@ -117,7 +146,7 @@ fn write_entity_definition(
         w: &mut dyn fmt::Write,
         _func: &Function,
         entity: AnyEntity,
-        value: &fmt::Display,
+        value: &dyn fmt::Display,
     ) -> fmt::Result {
         write!(w, "    {} = {}", entity, value)?;
 
@@ -128,15 +157,15 @@ fn write_entity_definition(
         }
     }
 
-    fn write_ebb_header(
+    fn write_block_header(
         &mut self,
         w: &mut dyn fmt::Write,
         func: &Function,
         isa: Option<&dyn isa::TargetIsa>,
-        ebb: Ebb,
+        block: Block,
         indent: usize,
     ) -> fmt::Result {
-        PlainWriter.write_ebb_header(w, func, isa, ebb, indent)
+        PlainWriter.write_block_header(w, func, isa, block, indent)
     }
 
     fn write_instruction(
@@ -149,7 +178,7 @@ fn write_instruction(
         indent: usize,
     ) -> fmt::Result {
         PlainWriter.write_instruction(w, func, aliases, isa, inst, indent)?;
-        if let Some(comment) = self.inst_comments.get(&inst) {
+        if let Some(comment) = self.entity_comments.get(&inst.into()) {
             writeln!(w, "; {}", comment.replace('\n', "\n; "))?;
         }
         Ok(())
@@ -157,53 +186,47 @@ fn write_instruction(
 }
 
 #[cfg(debug_assertions)]
-impl<'a, 'tcx: 'a, B: Backend + 'a> FunctionCx<'a, 'tcx, B> {
-    pub fn add_global_comment<S: Into<String>>(&mut self, comment: S) {
-        self.clif_comments.global_comments.push(comment.into());
+impl<M: Module> FunctionCx<'_, '_, M> {
+    pub(crate) fn add_global_comment<S: Into<String>>(&mut self, comment: S) {
+        self.clif_comments.add_global_comment(comment);
     }
 
-    pub fn add_entity_comment<'s, S: Into<Cow<'s, str>>, E: Into<AnyEntity>>(
+    pub(crate) fn add_comment<S: Into<String> + AsRef<str>, E: Into<AnyEntity>>(
         &mut self,
         entity: E,
         comment: S,
     ) {
-        use std::collections::hash_map::Entry;
-        match self.clif_comments.entity_comments.entry(entity.into()) {
-            Entry::Occupied(mut occ) => {
-                occ.get_mut().push('\n');
-                occ.get_mut().push_str(comment.into().as_ref());
-            }
-            Entry::Vacant(vac) => {
-                vac.insert(comment.into().into_owned());
-            }
-        }
-    }
-
-    pub fn add_comment<'s, S: Into<Cow<'s, str>>>(&mut self, inst: Inst, comment: S) {
-        use std::collections::hash_map::Entry;
-        match self.clif_comments.inst_comments.entry(inst) {
-            Entry::Occupied(mut occ) => {
-                occ.get_mut().push('\n');
-                occ.get_mut().push_str(comment.into().as_ref());
-            }
-            Entry::Vacant(vac) => {
-                vac.insert(comment.into().into_owned());
-            }
-        }
+        self.clif_comments.add_comment(entity, comment);
     }
 }
 
-pub fn write_clif_file<'a, 'tcx: 'a>(
-    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+pub(crate) fn write_clif_file<'tcx>(
+    tcx: TyCtxt<'tcx>,
     postfix: &str,
+    isa: Option<&dyn cranelift_codegen::isa::TargetIsa>,
     instance: Instance<'tcx>,
-    func: &ir::Function,
+    context: &cranelift_codegen::Context,
     mut clif_comments: &CommentWriter,
-    value_ranges: Option<&ValueLabelsRanges>,
 ) {
     use std::io::Write;
 
-    let symbol_name = tcx.symbol_name(instance).as_str();
+    if !cfg!(debug_assertions)
+        && !tcx
+            .sess
+            .opts
+            .output_types
+            .contains_key(&OutputType::LlvmAssembly)
+    {
+        return;
+    }
+
+    let value_ranges = isa.map(|isa| {
+        context
+            .build_value_labels_ranges(isa)
+            .expect("value location ranges")
+    });
+
+    let symbol_name = tcx.symbol_name(instance).name;
     let clif_file_name = format!(
         "{}/{}__{}.{}.clif",
         concat!(env!("CARGO_MANIFEST_DIR"), "/target/out/clif"),
@@ -213,48 +236,45 @@ pub fn write_clif_file<'a, 'tcx: 'a>(
     );
 
     let mut clif = String::new();
-    cranelift::codegen::write::decorate_function(
+    cranelift_codegen::write::decorate_function(
         &mut clif_comments,
         &mut clif,
-        &func,
+        &context.func,
         &DisplayFunctionAnnotations {
-            isa: Some(&*crate::build_isa(tcx.sess)),
-            value_ranges,
+            isa: Some(&*crate::build_isa(
+                tcx.sess, true, /* PIC doesn't matter here */
+            )),
+            value_ranges: value_ranges.as_ref(),
         },
     )
     .unwrap();
 
-    match ::std::fs::File::create(clif_file_name) {
-        Ok(mut file) => {
-            let target_triple: ::target_lexicon::Triple =
-                tcx.sess.target.target.llvm_target.parse().unwrap();
-            writeln!(file, "test compile").unwrap();
-            writeln!(file, "set is_pic").unwrap();
-            writeln!(file, "target {}", target_triple).unwrap();
-            writeln!(file, "").unwrap();
-            file.write(clif.as_bytes()).unwrap();
-        }
-        Err(e) => {
-            tcx.sess.warn(&format!("err opening clif file: {:?}", e));
-        }
+    let res: std::io::Result<()> = try {
+        let mut file = std::fs::File::create(clif_file_name)?;
+        let target_triple = crate::target_triple(tcx.sess);
+        writeln!(file, "test compile")?;
+        writeln!(file, "set is_pic")?;
+        writeln!(file, "set enable_simd")?;
+        writeln!(file, "target {} haswell", target_triple)?;
+        writeln!(file, "")?;
+        file.write(clif.as_bytes())?;
+    };
+    if let Err(err) = res {
+        tcx.sess.warn(&format!("err writing clif file: {}", err));
     }
 }
 
-impl<'a, 'tcx: 'a, B: Backend + 'a> fmt::Debug for FunctionCx<'a, 'tcx, B> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+impl<M: Module> fmt::Debug for FunctionCx<'_, '_, M> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         writeln!(f, "{:?}", self.instance.substs)?;
         writeln!(f, "{:?}", self.local_map)?;
 
         let mut clif = String::new();
-        ::cranelift::codegen::write::decorate_function(
+        ::cranelift_codegen::write::decorate_function(
             &mut &self.clif_comments,
             &mut clif,
             &self.bcx.func,
-            // FIXME use DisplayFunctionAnnotations::default() instead
-            &DisplayFunctionAnnotations {
-                isa: None,
-                value_ranges: None,
-            },
+            &DisplayFunctionAnnotations::default(),
         )
         .unwrap();
         writeln!(f, "\n{}", clif)