1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
//! A library for manipulating [Souper] IR.
//!
//! [![](https://docs.rs/souper-ir/badge.svg)](https://docs.rs/souper-ir/)
//! [![](https://img.shields.io/crates/v/souper-ir.svg)](https://crates.io/crates/souper-ir)
//! [![](https://img.shields.io/crates/d/souper-ir.svg)](https://crates.io/crates/souper-ir)
//! ![CI](https://github.com/fitzgen/souper-ir/workflows/CI/badge.svg)
//!
//! This crate provides AST types for parsing or generating Souper IR. It is a
//! suitable building block either for writing a custom LHS extractor, or for
//! translating learned optimizations into your own peephole optimizations pass.
//!
//! ## AST
//!
//! The AST type definitions and builders live in the `souper_ir::ast` module.
//!
//! ## Parsing Souper IR
//!
//! When the `parse` Cargo feature is enabled, the `souper_ir::parse` module
//! contains functions for parsing Souper IR from a file or an in-memory string.
//!
//! ```
//! # #[cfg(feature = "parse")]
//! # fn foo() -> souper_ir::parse::Result<()> {
//! use std::path::Path;
//!
//! // We provide a filename to get better error messages.
//! let filename = Path::new("example.souper");
//!
//! let replacements = souper_ir::parse::parse_replacements_str("
//!     ;; x + x --> 2 * x
//!     %0 = var
//!     %1 = add %0, %0
//!     %2 = mul %0, 2
//!     cand %1, %2
//!
//!     ;; x & x --> x
//!     %0 = var
//!     %1 = and %0, %0
//!     cand %1, %0
//! ", Some(filename))?;
//! # let _ = replacements;
//! # Ok(())
//! # }
//! ```
//!
//! ## Emitting Souper IR's Text Format
//!
//! When the `stringify` Cargo feature is enabled, then the
//! `souper_ir::ast::Replacement`, `souper_ir::ast::LeftHandSide`, and
//! `souper_ir::ast::RightHandSide` types all implement `std::fmt::Display`. The
//! `Display` implementation writes the AST type out as Souper's text format.
//!
//! ```
//! # #[cfg(feature = "stringify")]
//! # fn foo() -> std::io::Result<()> {
//! use souper_ir::ast;
//!
//! // Build this Souper left-hand side:
//! //
//! //     %x:i32 = var
//! //     %y = mul %x, 2
//! //     infer %y
//! //
//! // We expect that Souper would be able to synthesize a right-hand side that
//! // does a left shift by one instead of a multiplication.
//!
//! let mut lhs = ast::LeftHandSideBuilder::default();
//!
//! let x = lhs.assignment(
//!     Some("x".into()),
//!     Some(ast::Type { width: 32 }),
//!     ast::AssignmentRhs::Var,
//!     vec![],
//! );
//!
//! let y = lhs.assignment(
//!     Some("y".into()),
//!     None,
//!     ast::Instruction::Mul {
//!         a: x.into(),
//!         b: ast::Constant { value: 2, r#type: None }.into(),
//!     },
//!     vec![],
//! );
//!
//! let lhs = lhs.finish(y, vec![]);
//!
//! // Now we can stringify the LHS (and then, presumably, give it to Souper)
//! // with `std::fmt::Display`:
//!
//! use std::io::Write;
//!
//! let mut file = std::fs::File::create("my-lhs.souper")?;
//! write!(&mut file, "{}", lhs)?;
//! # Ok(())
//! # }
//! ```
//! [Souper]: https://github.com/google/souper

#![deny(missing_debug_implementations)]
#![deny(missing_docs)]

pub mod ast;

#[cfg(feature = "parse")]
pub mod parse;

#[cfg(feature = "stringify")]
mod stringify;