The first pass is used to do simple linear scan lifetime analysis.
In the future it may be expanded to add a few other quick optimizations.
The second pass is the actual meat of the backend that generates the byte buffer of output binary.
The process is pretty simple, but can get quite complex when you have to deal with memory layouts, function calls, and multiple architectures.
## Core Abstractions
This library is built with a number of core traits/generic types that may look quite weird at first glance.
The reason for all of the generics and traits is to allow rust to optimize each target specific backend.
Instead of every needing an `if linux ...` or `if arm ...` statement within the backend,
rust should be abled compile each specific target (`linux-arm`, `darwin-x86_64`, etc) as a static optimized backend without branches on target or dynamic dispatch.
**Note:** links below are to files, not specific lines. Just look up the specific type in the file.
### Backend
[Backend](https://github.com/rtfeldman/roc/blob/trunk/compiler/gen_dev/src/lib.rs) is the core abstraction.
It understands Roc's mono ir and some high level ideas about the generation process.
The main job of Backend is to do high level optimizatons (like lazy literal loading) and parse the mono ir.
Every target specific backend must implement this trait.
### Backend64Bit
[Backend64Bit](https://github.com/rtfeldman/roc/blob/trunk/compiler/gen_dev/src/generic64/mod.rs) is more or less what it sounds like.
It is the backend that understands 64 bit architectures.
Currently it is the only backend implementation, but a 32 bit implementation will probably come in the future.
This backend understands that the unit of data movement is 64 bit.
It also knows about things common to all 64 bit architectures (general purpose registers, stack, float regs, etc).
If you look at the signiture for Backend64Bit, it is actually quite complex.
Backend64Bit is generic over things like the register type, assembler, and calling convention.
This enables to backend to support multiple architectures and operating systems.
For example, the `windows-x86_64` would use the x86 register set, the x86 assembler, and the x86 windows calling convention.
`darwin-x86_64` and `linux-x86_64` would use the same register set and assembler, but they would use the system v amd64 abi calling convention.
Backend64Bit is generic over these types instead of containing these types within it's struct to avoid the cost of dynamic dispatch.
### Assembler
[Assembler](https://github.com/rtfeldman/roc/blob/trunk/compiler/gen_dev/src/generic64/mod.rs) is the trait for generating assembly bytes.
It defines a set of RISC-like assembly calls that must be implemented for each architecture.
A lot of these calls may not map one to one with actual assembly instructions for each architecture.
Instead, they are a general abstraction over functionality shared between all architectures.
This will grow regularly as more Roc builtins are added.
Here are example implementations for [arm](https://github.com/rtfeldman/roc/blob/trunk/compiler/gen_dev/src/generic64/aarch64.rs) and [x86_64](https://github.com/rtfeldman/roc/blob/trunk/compiler/gen_dev/src/generic64/x86_64.rs).
It deals with register and stack specific information related to passing and returning arguments.
Here are example implementations for [arm](https://github.com/rtfeldman/roc/blob/trunk/compiler/gen_dev/src/generic64/aarch64.rs) and [x86_64](https://github.com/rtfeldman/roc/blob/trunk/compiler/gen_dev/src/generic64/x86_64.rs).
## Adding New Features
Adding a new builtin to the dev backend can be pretty simple.
Here is [an example](https://github.com/rtfeldman/roc/pull/893/files) of adding `Num.Sub`.
A good place to look for missing features is in the test files for generation in [test_gen](https://github.com/rtfeldman/roc/tree/trunk/compiler/test_gen). Any test that is not enabled for the `gen-dev` feature still needs to be added to the dev backend. Eventually all features should be enabled for the dev backend.
1. Uncomment the code to print out procedures [from here](https://github.com/rtfeldman/roc/blob/b03ed18553569314a420d5bf1fb0ead4b6b5ecda/compiler/test_gen/src/helpers/dev.rs#L76) and run the test.
1. Generally it will fail in one of the match statements in the [Backend](https://github.com/rtfeldman/roc/blob/trunk/compiler/gen_dev/src/lib.rs) trait.