X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Fpretty_clif.rs;h=26407e25bc6e882de4269c40f2dfc1ebe9e0b99e;hb=49710287756b85edb5a0d82a210ab26973aec746;hp=4d05659a060e945cf63b95b4a656cfa9dd06c227;hpb=9041db962decfe6fa719d3f801b3f985f8027110;p=rust.git diff --git a/src/pretty_clif.rs b/src/pretty_clif.rs index 4d05659a060..26407e25bc6 100644 --- a/src/pretty_clif.rs +++ b/src/pretty_clif.rs @@ -1,92 +1,121 @@ -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, - entity_comments: HashMap, - inst_comments: HashMap, + entity_comments: FxHashMap, } impl CommentWriter { - pub fn new<'tcx>(tcx: TyCtxt<'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>(&mut self, comment: S) { + self.global_comments.push(comment.into()); + } + + pub(crate) fn add_comment + AsRef, E: Into>( + &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()); + } } } } @@ -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,103 +186,100 @@ fn write_instruction( } #[cfg(debug_assertions)] -impl<'a, 'tcx: 'a, B: Backend + 'a> FunctionCx<'a, 'tcx, B> { - pub fn add_global_comment>(&mut self, comment: S) { - self.clif_comments.global_comments.push(comment.into()); +impl FunctionCx<'_, '_, M> { + pub(crate) fn add_global_comment>(&mut self, comment: S) { + self.clif_comments.add_global_comment(comment); } - pub fn add_entity_comment<'s, S: Into>, E: Into>( + pub(crate) fn add_comment + AsRef, E: Into>( &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>>(&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<'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(); - let clif_file_name = format!( - "{}/{}__{}.{}.clif", - concat!(env!("CARGO_MANIFEST_DIR"), "/target/out/clif"), - tcx.crate_name(LOCAL_CRATE), - symbol_name, - postfix, - ); + 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 clif_output_dir = tcx.output_filenames(LOCAL_CRATE).with_extension("clif"); + + match std::fs::create_dir(&clif_output_dir) { + Ok(()) => {} + Err(err) if err.kind() == std::io::ErrorKind::AlreadyExists => {} + res @ Err(_) => res.unwrap(), + } + + let clif_file_name = clif_output_dir.join(format!( + "{}.{}.clif", + tcx.symbol_name(instance).name, + postfix + )); 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, true /* PIC doesn't matter here */)), - 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 = crate::target_triple(tcx.sess); - 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 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)