# `souper-ir`
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.
```rust
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))?;
```
### 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.
```rust
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)?;
```
[Souper]: https://github.com/google/souper