xrcf/lib.rs
1//! xrcf is an easy(ier)-to-use infrastructure for building compilers.
2//!
3//! Below is a a high-level overview of xrcf.
4//! To instead see the code in action, see the example compiler in the
5//! [`arnoldc` directory](https://github.com/rikhuijzer/xrcf/tree/main/arnoldc).
6//!
7//! What follows is some background on compilers and how this project can help you:
8//!
9//! Say you want to write a compiler for a new programming language.
10//! The compiler should take the source code in your language and convert it to platform that can execute it such as a CPU or GPU.
11//! Now you could do this via string manipulation.
12//! To sum two matrices, you read a string like `x = a + b`, but then you realize that converting this to say LLVM via string manipulation is not that easy.
13//! That's why compilers first scan and parse the source code into an intermediate representation (IR).
14//! Unlike strings, the IR provides common methods to interact with the code.
15//! For example, this project defines a `insert_before` method for operations.
16//! Whereas with strings you would need to manually search for the line where to insert the new operation, with the IR you can just call `add_op.insert_before(new_op)`.
17//!
18//! Next you decide that you want to compile this code to another platform such as a GPU.
19//! Then you would need to convert some of the operations to GPU-specific operations.
20//! This is where passes come in.
21//! A pass is a group of transformations that are applied to the IR.
22//! For example, to compile to CPU via LLVM, you would use the passes `--convert-func-to-llvm` and `--convert-llvm-to-llvm-ir`.
23//! And to compile to GPU, you would use `--convert-func-to-gpu`.
24//!
25//! This project gives you these building blocks.
26//! It contains some default IR and default passes, but more importantly you can also add your own.
27//! This means that if you want to write your own compiler for your language, you only have to convert your code into the default IR that is inside this project, and then you can choose which passes you want to use in which situation.
28//!
29//! ## Long-term Goal
30//!
31//! It is unclear where computations will be done in the future.
32//! Will it be on CPUs, GPUs, TPUs, or something else?
33//! But this is not what this project should focus on.
34//! This project focuses on what does not change: transformations.
35//! It's very likely that we still need to transform code in the future.
36//! There will probably always be a gap between code that is easy to read for humans and code that can be efficiently executed by the hardware.
37//!
38//! So, the long-term goal of this project is to provide an easy-to-use set of tools that can be used to build your own compiler.
39//! In other words, it should be easy to build a compiler that can transform your favorite language to this project's core IR, and then it should be easy to transform this to various platforms such as GPUs, CPUs, and TPUs.
40#![allow(clippy::new_without_default)]
41#![allow(clippy::arc_with_non_send_sync)]
42
43mod canonicalize;
44pub mod convert;
45pub mod dialect;
46pub mod frontend;
47pub mod ir;
48pub mod shared;
49pub mod targ3t;
50#[cfg(feature = "test-utils")]
51pub mod tester;
52mod transform;
53
54pub use transform::default_arguments;
55pub use transform::init_subscriber;
56pub use transform::transform;
57pub use transform::DefaultTransformDispatch;
58pub use transform::Passes;
59pub use transform::SinglePass;
60pub use transform::TransformDispatch;
61pub use transform::TransformOptions;
62
63/// Dialects can define new operations, attributes, and types.
64/// Each dialect is given an unique namespace that is prefixed.
65///
66/// Dialects can co-exist and can be produced and consumed by different passes.
67pub trait Dialect {
68 fn name(&self) -> &'static str;
69 fn description(&self) -> &'static str;
70}