calyx 0.7.1

Compiler Infrastructure for Hardware Accelerator Generation
# Adding a New Pass

All passes in the compiler are stored in the `calyx/src/passes` directory.
To add a new pass, we need to do a couple of things:
1. Define a pass struct and implement the required traits.
2. Expose the pass using in the `passes` module.
3. Register the pass in the compiler.

> It is possible to add passes outside the compiler tree, but we haven't needed to do this yet, so we will not cover it here.

## Defining a Pass Struct

We first define a [Rust structure][struct] that will manage the state of the pass:
```rust
pub struct NewPass;
```

A pass needs to implement the [`Named`][named-trait] and [`Visitor`][visitor-trait] traits.
The former defines the name, description, and [pass-specific options][pass-opts] of the pass.

```rust
impl Named for NewPass {
    fn name(&self) -> &'static str { "new-pass" }
    ...
}
impl Visitor for NewPass { ... }
```

The pass name provided in used in the compiler's driver and needs to be unique for each registered pass.

## The Visitor Trait

The visitor trait allows us to define the behavior of the pass.
The visitor visits each [control operator][control] in each component and performs some action.
Furthermore, it also allows us to control the order in which components are visited.

### Component Iteration Order

The [`Order`][order] struct allows us to control the order in which components are visited:
- `Post`: Iterate the subcomponents of a component before the component itself.
- `Pre`: Iterate the subcomponents of a component after the component itself.
- `No`: Iterate the components in any order.

### Visiting Components

Most passes will attempt to transform the structural part of the program (`wires` or `cells`), the `control` schedule, or both.
The `Visitor` trait is flexible enough to allow all of these patterns and efficiently traverse the program.

For a control program like this:
```
seq {
    one;
    if cond { two } else { three }
    invoke foo(..)
}
```

The following sequence of `Visitor` methods are called:
```
- start
- start_seq
  - enable       // group one
  - start_if
    - enable     // group two
    - enable     // group three
  - end_if
  - invoke       // invocation
- finish_seq
- finish
```

Each non-leaf control operator defines both a `start_*` and `finish_*` method which allows us to encode top-down and bottom-up traversal patterns.

Each method returns an [`Action`][action] value which allows us to control the traversal of the program.
For example, `Action::Stop` will immediately stop the traversal of the program while `Action::SkipChildren` will skip the traversal of the children of the current control operator.

## Registering the Pass

The final step is to register the pass in the compiler.
We use the [`PassManager`][pass-manager] to register the pass defined in the `default_passes.rs` file.

Registering a pass is as simple as calling the register pass:
```rust
pm.register_pass::<NewPass>();
```

Once done, the pass is accessible from the command line:
```bash
cargo run -- -p new-pass <file>
```

This will run `-p new-pass` on the input file.
In order to run this pass in the default pipeline, we need to add it to the `all` alias (which is called when no `-p` option is provided).
The `all` alias is itself defined using other aliases which separate the pipeline into different phases.
For example, if `NewPass` needs to run before the compilation passes, we can add it to the `pre-opt` alias.

## Some Useful Links

The compiler has a ton of shared infrastructure that can be useful:
- [`ir::Context`][context]: The top-level data structure that holds a complete Calyx program.
- [Rewriter][]: Helps with consistent renaming of ports, cells, groups, and comb groups in a component.
- [`analysis`][analysis]: Provides a number of useful analysis that can be used within a pass.
- IR macros: Macros useful for adding cells ([`structure!`][structure]), guards ([`guard!`][guard]) and assignments ([`build_assignments!`][build-assigns]) to component.

[pass-opts]: ./compiler.md#providing-pass-options
[control]: ./lang/ref.md#the-control-operators
[struct]: https://doc.rust-lang.org/book/ch05-01-defining-structs.html
[named-trait]: https://docs.rs/calyx-opt/0.2.1/calyx_opt/traversal/trait.Named.html
[visitor-trait]: https://docs.rs/calyx-opt/0.2.1/calyx_opt/traversal/trait.Visitor.html
[pass-manager]: https://docs.rs/calyx-opt/0.2.1/calyx_opt/pass_manager/struct.PassManager.html
[action]: https://docs.rs/calyx-opt/0.2.1/calyx_opt/traversal/enum.Action.html
[order]: https://docs.rs/calyx-opt/0.2.1/calyx_opt/traversal/enum.Order.html
[rewriter]: https://docs.rs/calyx-ir/latest/calyx_ir/rewriter/index.html
[analysis]: https://docs.rs/calyx-opt/0.2.1/calyx_opt/analysis/index.html
[build-assigns]: https://docs.rs/calyx-ir/latest/calyx_ir/macro.build_assignments.html
[guard]: https://docs.rs/calyx-ir/latest/calyx_ir/macro.guard.html
[structure]: https://docs.rs/calyx-ir/latest/calyx_ir/macro.structure.html
[context]: https://docs.rs/calyx-ir/latest/calyx_ir/struct.Context.html