Use fmt::Write instead of io::Write in write.rs.

It is common to represent a function as a String, and previously that
required re-validating the UTF-8 in a Vec<u8>. The fmt::Write trait
writes UTF-8 directly into a String, so no extra checking is required.

This also means we can implement Display for Function which gives it a
to_string() method. This makes the function_to_string() method
redundant, so delete it.

The functions in the write module are no longer generally useful, so
make the module private. The Display trait on Function is all we need.
This commit is contained in:
Jakob Stoklund Olesen
2016-09-15 13:56:42 -07:00
parent 0b8bf530b0
commit b40a3495fe
4 changed files with 21 additions and 30 deletions

View File

@@ -6,7 +6,8 @@
use ir::{FunctionName, Signature, StackSlot, StackSlotData, JumpTable, JumpTableData, use ir::{FunctionName, Signature, StackSlot, StackSlotData, JumpTable, JumpTableData,
DataFlowGraph, Layout}; DataFlowGraph, Layout};
use entity_map::{EntityMap, PrimaryEntityData}; use entity_map::{EntityMap, PrimaryEntityData};
use std::fmt::{self, Debug, Formatter}; use std::fmt::{self, Display, Debug, Formatter};
use write::write_function;
/// A function. /// A function.
/// ///
@@ -60,9 +61,14 @@ impl Function {
} }
} }
impl Debug for Function { impl Display for Function {
fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
use write::function_to_string; write_function(fmt, self)
fmt.write_str(&function_to_string(self)) }
}
impl Debug for Function {
fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
write_function(fmt, self)
} }
} }

View File

@@ -9,13 +9,13 @@ pub const VERSION: &'static str = env!("CARGO_PKG_VERSION");
pub mod ir; pub mod ir;
pub mod isa; pub mod isa;
pub mod write;
pub mod cfg; pub mod cfg;
pub mod dominator_tree; pub mod dominator_tree;
pub mod entity_map; pub mod entity_map;
pub mod settings; pub mod settings;
pub mod verifier; pub mod verifier;
mod write;
mod constant_hash; mod constant_hash;
mod predicates; mod predicates;

View File

@@ -5,9 +5,8 @@
//! `cretonne-reader` crate. //! `cretonne-reader` crate.
use ir::{Function, Ebb, Inst, Value, Type}; use ir::{Function, Ebb, Inst, Value, Type};
use std::io::{self, Write}; use std::fmt::{Result, Error, Write};
use std::result;
pub type Result = io::Result<()>;
/// Write `func` to `w` as equivalent text. /// Write `func` to `w` as equivalent text.
pub fn write_function(w: &mut Write, func: &Function) -> Result { pub fn write_function(w: &mut Write, func: &Function) -> Result {
@@ -24,15 +23,6 @@ pub fn write_function(w: &mut Write, func: &Function) -> Result {
writeln!(w, "}}") writeln!(w, "}}")
} }
/// Convert `func` to a string.
pub fn function_to_string(func: &Function) -> String {
let mut buffer: Vec<u8> = Vec::new();
// Any errors here would be out-of-memory, which should not happen with normal functions.
write_function(&mut buffer, func).unwrap();
// A UTF-8 conversion error is a real bug.
String::from_utf8(buffer).unwrap()
}
// ====--------------------------------------------------------------------------------------====// // ====--------------------------------------------------------------------------------------====//
// //
// Function spec. // Function spec.
@@ -65,7 +55,7 @@ fn write_spec(w: &mut Write, func: &Function) -> Result {
} }
} }
fn write_preamble(w: &mut Write, func: &Function) -> io::Result<bool> { fn write_preamble(w: &mut Write, func: &Function) -> result::Result<bool, Error> {
let mut any = false; let mut any = false;
for ss in func.stack_slots.keys() { for ss in func.stack_slots.keys() {
@@ -218,7 +208,6 @@ pub fn write_instruction(w: &mut Write, func: &Function, inst: Inst) -> Result {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*;
use super::{needs_quotes, escaped}; use super::{needs_quotes, escaped};
use ir::{Function, StackSlotData}; use ir::{Function, StackSlotData};
use ir::types; use ir::types;
@@ -244,26 +233,26 @@ mod tests {
#[test] #[test]
fn basic() { fn basic() {
let mut f = Function::new(); let mut f = Function::new();
assert_eq!(function_to_string(&f), "function \"\"() {\n}\n"); assert_eq!(f.to_string(), "function \"\"() {\n}\n");
f.name.push_str("foo"); f.name.push_str("foo");
assert_eq!(function_to_string(&f), "function foo() {\n}\n"); assert_eq!(f.to_string(), "function foo() {\n}\n");
f.stack_slots.push(StackSlotData::new(4)); f.stack_slots.push(StackSlotData::new(4));
assert_eq!(function_to_string(&f), assert_eq!(f.to_string(),
"function foo() {\n ss0 = stack_slot 4\n}\n"); "function foo() {\n ss0 = stack_slot 4\n}\n");
let ebb = f.dfg.make_ebb(); let ebb = f.dfg.make_ebb();
f.layout.append_ebb(ebb); f.layout.append_ebb(ebb);
assert_eq!(function_to_string(&f), assert_eq!(f.to_string(),
"function foo() {\n ss0 = stack_slot 4\n\nebb0:\n}\n"); "function foo() {\n ss0 = stack_slot 4\n\nebb0:\n}\n");
f.dfg.append_ebb_arg(ebb, types::I8); f.dfg.append_ebb_arg(ebb, types::I8);
assert_eq!(function_to_string(&f), assert_eq!(f.to_string(),
"function foo() {\n ss0 = stack_slot 4\n\nebb0(vx0: i8):\n}\n"); "function foo() {\n ss0 = stack_slot 4\n\nebb0(vx0: i8):\n}\n");
f.dfg.append_ebb_arg(ebb, types::F32.by(4).unwrap()); f.dfg.append_ebb_arg(ebb, types::F32.by(4).unwrap());
assert_eq!(function_to_string(&f), assert_eq!(f.to_string(),
"function foo() {\n ss0 = stack_slot 4\n\nebb0(vx0: i8, vx1: f32x4):\n}\n"); "function foo() {\n ss0 = stack_slot 4\n\nebb0(vx0: i8, vx1: f32x4):\n}\n");
} }
} }

View File

@@ -3,11 +3,9 @@
//! Read a sequence of Cretonne IL files and print them again to stdout. This has the effect of //! Read a sequence of Cretonne IL files and print them again to stdout. This has the effect of
//! normalizing formatting and removing comments. //! normalizing formatting and removing comments.
use std::io;
use CommandResult; use CommandResult;
use utils::read_to_string; use utils::read_to_string;
use cton_reader::parse_functions; use cton_reader::parse_functions;
use cretonne::write::write_function;
pub fn run(files: Vec<String>) -> CommandResult { pub fn run(files: Vec<String>) -> CommandResult {
for (i, f) in files.into_iter().enumerate() { for (i, f) in files.into_iter().enumerate() {
@@ -27,9 +25,7 @@ fn cat_one(filename: String) -> CommandResult {
if idx != 0 { if idx != 0 {
println!(""); println!("");
} }
let stdout = io::stdout(); print!("{}", func);
let mut handle = stdout.lock();
try!(write_function(&mut handle, &func).map_err(|e| format!("{}: {}", filename, e)));
} }
Ok(()) Ok(())