|
1 |
| -# Rustc Codegen JVM 🚀 |
| 1 | +# rustc_codegen_jvm 🚀 |
2 | 2 |
|
3 |
| -[](https://opensource.org/licenses/MIT) |
| 3 | +[](https://opensource.org/licenses/MIT) |
| 4 | +[](https://github.com/IntegralPilot/rustc_codegen_jvm/actions) |
4 | 5 |
|
5 |
| -Welcome! This project provides a custom Rust compiler backend (`rustc_codegen_jvm`) that compiles Rust code into Java Virtual Machine (JVM) bytecode. This allows Rust programs to run on the JVM. Currently, the generated bytecode supports JVM 8 and later versions. |
| 6 | +A **custom Rust compiler backend** that emits Java Virtual Machine bytecode. |
| 7 | +Compile your Rust code into a runnable `.jar` on JVM 8+! |
6 | 8 |
|
7 |
| -## How It Works |
| 9 | +--- |
8 | 10 |
|
9 |
| -The toolchain transforms Rust code into executable `.jar` files through several stages: |
| 11 | +## 📖 Table of Contents |
10 | 12 |
|
11 |
| -1. **Rustc Frontend (Parsing & MIR Generation)** |
12 |
| - * Your Rust code is parsed and lowered to *Mid-level Intermediate Representation (MIR)* by the standard `rustc` frontend. |
| 13 | +1. [Demos](#demos) |
| 14 | +2. [Features](#features) |
| 15 | +3. [How It Works](#how-it-works) |
| 16 | +4. [Prerequisites](#prerequisites) |
| 17 | +5. [Installation & Build](#installation--build) |
| 18 | +6. [Usage](#usage) |
| 19 | +7. [Running Tests](#running-tests) |
| 20 | +8. [Project Structure](#project-structure) |
| 21 | +9. [Contributing](#contributing) |
| 22 | +10. [License](#license) |
13 | 23 |
|
14 |
| -2. **MIR to OOMIR (Object-Oriented MIR)** |
15 |
| - * The MIR is lowered further into a custom intermediate representation called OOMIR. This step simplifies MIR constructs into a representation closer to object-oriented concepts, making the translation to JVM bytecode more manageable. (See `src/lower1.rs`). |
| 24 | +--- |
16 | 25 |
|
17 |
| -3. **OOMIR to JVM Classfile** |
18 |
| - * The OOMIR is then translated into standard Java `.class` files containing JVM bytecode. This is the core task of the `rustc_codegen_jvm` library in this repository (See `src/lower2.rs`). It utilizes the `ristretto_classfile` library for bytecode generation. |
| 26 | +## 🔥 Demos |
19 | 27 |
|
20 |
| -4. **Classfile Post-Processing (Stack Map Frames)** |
21 |
| - * The generated `.class` files are processed by a dedicated tool (`asm-processor`, written in Kotlin using the ASM library). This tool calculates and inserts *Stack Map Frames*, which are required for class verification in modern JVM versions (Java 7+). |
| 28 | +All examples live in `tests/binary` and are compiled to JVM bytecode & run/tested on the CI on every commit. Some exicting demos made in pure-Rust include: |
22 | 29 |
|
23 |
| -5. **Linking & `.jar` Generation** |
24 |
| - * Finally, the processed `.class` files for the crate and its dependencies (though dependency handling is currently basic) are linked together into a single executable `.jar` file. This step is handled by `java-linker`, a custom linker built as part of this project (See `java-linker/`). It also generates the necessary `META-INF/MANIFEST.MF` file, marking the main class if applicable. |
25 |
| - |
26 |
| -## Current Capabilities |
27 |
| - |
28 |
| -This backend currently supports a subset of Rust features: |
29 |
| - |
30 |
| -* ✅ Compiling minimal `no_std` & `no_core` Rust programs (like an empty `main`) using the `jvm-unknown-unknown` target. |
31 |
| -* ✅ Compiling simple programs using basic `core` features (like other tests) using the host target but this codegen backend to produce JVM bytecode. |
32 |
| -* ✅ Basic integer arithmetic operations on all types of numbers including floats: |
33 |
| - * Addition (`+`), Subtraction (`-`), Multiplication (`*`), Division (`/`), Remainder (`%`). |
34 |
| - * Checked addition, subtraction and multiplication returning `(result, overflowed_bool)` tuples (`rustc` requests this in debug mode even for normal operations to panic on overflow). |
35 |
| -* ✅ Comparisons between all number types (`==`, `!=`, `<`, `<=`, `>`, `>=`). |
36 |
| -* ✅ Bitwise operations on all numbers (`&`, `|`, `^`, `<<`, `>>`). |
37 |
| -* ✅ Logical operations(`&&`, `||`, `!`), support for `if` (and `else if`/`else`) and `match` statements. |
38 |
| -* ✅ Unary operations (`-`, `!`). |
39 |
| -* ✅ Type casting (e.g., `as` operator). |
40 |
| -* ✅ Support for all Rust primitive types. |
41 |
| -* ✅ Calling other functions (including recursion). |
42 |
| -* ✅ Loops such as `for`, `while`, and `loop`. |
43 |
| -* ✅ Variable assignment including subfield and array index assignment, including nesting. |
44 |
| -* ✅ Arrays and slices, including inserting, accessing and mutating at a given index (supporting nesting). |
45 |
| -* ✅ Floats (`f16`, `f32`, `f64`, `f128`) and their operations. |
46 |
| -* ✅ Structs, Tuples and Enums (including traditional C-like enums but also Rust-like enums with anonymous structs and tuples in them) including nested access/setting/mutation of fields and array indices within these. |
47 |
| -* ✅ Generating executable `.jar` files for binary crates. |
48 |
| - |
49 |
| -### Next Milestone: |
50 |
| -🚧 **Full support for the `core` crate** is the next major goal. |
51 |
| - |
52 |
| -## Prerequisites |
53 |
| - |
54 |
| -* **Rust Nightly:** Ensure you are using the latest **nightly** Rust toolchain. You can set this up with `rustup default nightly`. Some rust components are needed but will be automatically installed by the Makefile. |
55 |
| -* **Java Development Kit (JDK):** A working JDK (version 8 or later recommended) is required to run the generated `.jar` files and the `asm-processor`. Make sure `java` is in your PATH. |
56 |
| -* **Gradle:** Required to build the `asm-processor` Kotlin project. Make sure `gradle` is in your PATH. |
57 |
| -* **Python 3:** Required to run the integration tests and generate files from templates. Make sure `python3` is in your PATH. |
58 |
| - |
59 |
| -## Building the Toolchain |
60 |
| - |
61 |
| -1. **Build All Components:** |
62 |
| - * You can use the provided Makefile or build script: |
63 |
| - ```bash |
64 |
| - # Using Make |
65 |
| - make all |
66 |
| - ``` |
67 |
| - * This will: |
68 |
| - * Build the main `rustc_codegen_jvm` library (`target/debug/librustc_codegen_jvm.[dll/dylib/so]`). |
69 |
| - * Build the `java-linker` (`java-linker/target/debug/java-linker`). |
70 |
| - * Build the `asm-processor` (`asm-processor/build/libs/asm-processor-*.jar`). |
71 |
| - * Build the Kotlin shim of the Rust core library (`library`). |
72 |
| - * Generate the `config.toml` and `jvm-unknown-unknown.json` files from their templates. |
73 |
| - |
74 |
| - |
75 |
| -## Using the Toolchain (Compiling Another Rust Project) |
76 |
| - |
77 |
| -To compile *your own* Rust project using this backend: |
78 |
| - |
79 |
| -1. **Get the Toolchain:** Clone this repository and build it as described above. Ensure you build the toolchain first, as described in the previous section, by running `make all`. You will need to re-run `make gen-files` if you change the absolute path of where this repository is stored since building. |
80 |
| - |
81 |
| - |
82 |
| -2. **Configure Your Rust Project:** |
83 |
| - * In your *own* Rust project's directory, create a `.cargo/config.toml` file (if it doesn't exist). |
84 |
| - * Copy the contents from the `config.toml` file generated specifically for your system, that can be found in the root of this project after running `make all`. If since running make, you've moved this repo to a different directory, you'll need to run at least `make gen-files`. |
85 |
| - |
86 |
| -3. **Build Your Project:** |
87 |
| - * Run the standard Cargo build command, targeting the host target (using the `jvm-unknown-unknown` target is an emerging feature and means you can't even use `core`, for now, so not recommended). Cargo will read the `.cargo/config.toml` and use the specified target and flags automatically. |
88 |
| - ```bash |
89 |
| - cargo build |
90 |
| - # Or for release builds: |
91 |
| - # cargo build --release |
92 |
| - ``` |
93 |
| -
|
94 |
| -4. **Find & Run the Generated `.jar`:** |
95 |
| - * The compiled `.jar` file will be located in your project's `target` directory: |
96 |
| - * Debug: `target/debug/deps/[your_crate_name].jar` |
97 |
| - * Release: `target/release/deps/[your_crate_name].jar` |
98 |
| - * If your crate is a binary (`[[bin]]` or `src/main.rs`), run it using the `java` command: |
99 |
| - ```bash |
100 |
| - java -jar target/jvm-unknown-unknown/debug/[your_crate_name].jar |
101 |
| - ``` |
102 |
| - |
103 |
| -## Running This Project's Tests |
104 |
| - |
105 |
| -This project includes integration tests managed by a Python script. |
106 |
| - |
107 |
| -1. **Ensure Toolchain is Built:** Build the project using `make all`. If you've changed the path of the repository, run `make gen-files` to regenerate the configuration files. |
108 |
| -2. **Run the Tester:** |
109 |
| - ```bash |
110 |
| - python3 Tester.py |
111 |
| - # For release mode tests: |
112 |
| - # python3 Tester.py --release |
113 |
| - ``` |
114 |
| -3. **Check Output:** Look for the final "✅ All tests passed!" message. If tests fail, the script will generate `.generated` files in the respective test directories (`tests/binary/*`) containing error details or output diffs. |
115 |
| -
|
116 |
| -## Project Structure |
117 |
| -
|
118 |
| -* `src/`: Contains the source code for the `rustc_codegen_jvm` backend library. |
119 |
| - * `lib.rs`: Main backend integration point. |
120 |
| - * `lower1.rs`: MIR to OOMIR lowering pass. |
121 |
| - * `lower2.rs`: OOMIR to JVM bytecode generation pass. |
122 |
| - * `oomir.rs`: Definition of the Object-Oriented MIR (OOMIR). |
123 |
| -* `java-linker/`: Source code for the custom linker that creates `.jar` filesn from the generated `.class` files. |
124 |
| -* `asm-processor/`: Kotlin/Gradle project for the ASM-based bytecode post-processor that adds stack map frames to the generated `.class` files. |
125 |
| -* `tests/`: Integration tests. |
126 |
| - * `binary/`: Tests for compiling executable Rust crates. |
127 |
| -* `library/`: Source code for a minimal Kotlin-based implementation of the Rust core library. This serves as a temporary substitute to bootstrap the project until the backend can fully compile the Rust core library itself. |
128 |
| -* `shim-metadata-gen`: A tool for generating metadata for the Kotlin core library, called at compiletime to provide nessecary info (descriptors) to the codegen backend. It's generated metadata is embedded in the generated library, so not needed at runtime. |
129 |
| - * `core.json`: Metadata for the core library, generated by this tool. |
130 |
| -* `jvm-unknown-unknown.json.template`: The template for Rust target specification file (currently experimental & not recommended, use `config.toml` in your project instead). |
131 |
| -* `config.toml.template`: The template for the Cargo configuration file for the toolchain. |
132 |
| -* `Tester.py`: Python script for running integration tests. |
133 |
| -* `GenerateFiles.py` : Python script for generating the `config.toml` file and the `jvm-unknown-unknown.json` file from their templates, making them suited to your system. |
134 |
| -* `Makefile` Scripts for building the entire toolchain. |
135 |
| -* `setup.sh`: Script to install Rust components. |
136 |
| -* `Cargo.toml`, `Cargo.lock`: Rust package definition and dependencies for the backend. |
137 |
| -* `LICENSE`, `LICENSE-Apache`: Project licenses. |
138 |
| - |
139 |
| -## Contributing |
140 |
| - |
141 |
| -Contributions are welcome! Feel free to open issues or pull requests. |
142 |
| - |
143 |
| -## License |
144 |
| - |
145 |
| -This project is dual-licensed under either of: |
146 |
| - |
147 |
| -* MIT License ([LICENSE-MIT](LICENSE) or http://opensource.org/licenses/MIT) |
148 |
| -* Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-Apache) or http://www.apache.org/licenses/LICENSE-2.0) |
149 |
| - |
150 |
| -at your option. |
| 30 | +- **RSA** encryption/decryption (`rsa`) |
| 31 | +- **Fibonacci** sequence generator (`fibonacci`) |
| 32 | +- **Collatz conjecture** verifier (`collatz`) |
| 33 | +- **Large prime** generator (`primes`) |
| 34 | +- Nested data structures: enums, structs, tuples, arrays, slices (`enums`, `structs`) |
| 35 | +- …and more! |
| 36 | + |
| 37 | +--- |
| 38 | + |
| 39 | +## ✨ Features |
| 40 | + |
| 41 | +- **Minimal `no_std` & `no_core`** programs via `jvm-unknown-unknown` |
| 42 | +- Basic `core` support on host target for JVM output |
| 43 | +- Arithmetic (integers + floats, incl. checked ops) |
| 44 | +- Comparisons, bitwise & logical ops |
| 45 | +- Control flow: `if`/`else`, `match`, `for`, `while`, `loop` |
| 46 | +- Type casting (`as`), primitive types |
| 47 | +- Function calls (recursion supported) |
| 48 | +- Arrays & slices with nested indexing |
| 49 | +- Structs, tuples, enums (both C‑like and Rust‑style) |
| 50 | +- Executable `.jar` generation for binary crates |
| 51 | + |
| 52 | +🚧 **Next Milestone:** Full support for the Rust `core` crate. |
| 53 | + |
| 54 | +--- |
| 55 | + |
| 56 | +## ⚙️ How It Works |
| 57 | + |
| 58 | +1. **Rustc Frontend → MIR** |
| 59 | + Standard `rustc` parses your code into Mid‑level IR (MIR). |
| 60 | +2. **MIR → OOMIR** |
| 61 | + Custom “Object‑Oriented MIR” simplifies MIR into OOP‑style constructs. |
| 62 | + _(see `src/lower1.rs`)_ |
| 63 | +3. **OOMIR → JVM Classfile** |
| 64 | + Translate to `.class` files using `ristretto_classfile`. |
| 65 | + _(see `src/lower2.rs`)_ |
| 66 | +4. **Post‑Process Stack Map Frames** |
| 67 | + Kotlin `asm-processor` (ASM library) adds verification frames. |
| 68 | +5. **Link & Package** |
| 69 | + `java-linker` bundles `.class` files into a runnable `.jar` with `META-INF/MANIFEST.MF`. |
| 70 | + |
| 71 | +--- |
| 72 | + |
| 73 | +## 🛠 Prerequisites |
| 74 | + |
| 75 | +- **Rust Nightly** (`rustup default nightly`) |
| 76 | +- **JDK 8+** (`java` in PATH) |
| 77 | +- **Gradle** (`gradle` in PATH) |
| 78 | +- **Python 3** (`python3` in PATH) |
| 79 | + |
| 80 | +--- |
| 81 | + |
| 82 | +## 🏗 Installation & Build |
| 83 | + |
| 84 | +```bash |
| 85 | +# Clone & enter repo |
| 86 | +git clone https://github.com/your-org/rustc_codegen_jvm.git |
| 87 | +cd rustc_codegen_jvm |
| 88 | + |
| 89 | +# Build everything |
| 90 | +make all |
| 91 | +``` |
| 92 | + |
| 93 | +This will compile: |
| 94 | + |
| 95 | +- `rustc_codegen_jvm` backend library |
| 96 | +- `java-linker` |
| 97 | +- `asm-processor` |
| 98 | +- Kotlin shim for `core` |
| 99 | +- Generate `config.toml` & `jvm-unknown-unknown.json` |
| 100 | + |
| 101 | +If you relocate the repo, re-run: |
| 102 | +```bash |
| 103 | +make gen-files |
| 104 | +``` |
| 105 | + |
| 106 | +--- |
| 107 | + |
| 108 | +## 🚀 Usage |
| 109 | + |
| 110 | +1. **Configure your project** |
| 111 | + In *your* Rust project directory, create or update `.cargo/config.toml` with the generated template. |
| 112 | + |
| 113 | +2. **Build with Cargo** |
| 114 | + ```bash |
| 115 | + cargo build # debug |
| 116 | + cargo build --release # optimized |
| 117 | + ``` |
| 118 | + |
| 119 | +3. **Run the `.jar`** |
| 120 | + ```bash |
| 121 | + java -jar target/debug/deps/your_crate.jar |
| 122 | + ``` |
| 123 | + |
| 124 | +--- |
| 125 | + |
| 126 | +## 🧪 Running Tests |
| 127 | + |
| 128 | +Ensure the toolchain is built: |
| 129 | + |
| 130 | +```bash |
| 131 | +make all |
| 132 | +# If you moved the repo: |
| 133 | +make gen-files |
| 134 | +``` |
| 135 | + |
| 136 | +Then: |
| 137 | + |
| 138 | +```bash |
| 139 | +python3 Tester.py |
| 140 | +# or with --release for release‑mode tests |
| 141 | +``` |
| 142 | + |
| 143 | +Look for `✅ All tests passed!` or inspect `.generated` files on failure. |
| 144 | + |
| 145 | +--- |
| 146 | + |
| 147 | +## 📂 Project Structure |
| 148 | + |
| 149 | +``` |
| 150 | +. |
| 151 | +├── src/ # rustc_codegen_jvm backend |
| 152 | +│ ├── lib.rs |
| 153 | +│ ├── lower1.rs # MIR → OOMIR |
| 154 | +│ ├── lower2.rs # OOMIR → JVM bytecode |
| 155 | +│ └── oomir.rs # OOMIR definitions |
| 156 | +├── java-linker/ # Bundles .class files into .jar |
| 157 | +├── asm-processor/ # Kotlin ASM post‑processor |
| 158 | +├── tests/binary/ # Integration tests |
| 159 | +├── library/ # Kotlin shim for Rust core library |
| 160 | +├── shim-metadata-gen/ # Generates core.json metadata |
| 161 | +├── Makefile # build & gen-files |
| 162 | +├── config.toml.template |
| 163 | +├── jvm-unknown-unknown.json.template |
| 164 | +├── Tester.py # test runner |
| 165 | +├── GenerateFiles.py # regenerates config & target spec |
| 166 | +└── LICENSE, LICENSE-Apache |
| 167 | +``` |
| 168 | + |
| 169 | +--- |
| 170 | + |
| 171 | +## 🤝 Contributing |
| 172 | + |
| 173 | +Contributions, issues & PRs welcome! :) |
| 174 | + |
| 175 | +--- |
| 176 | + |
| 177 | +## 📄 License |
| 178 | + |
| 179 | +Dual‑licensed under **MIT** OR **Apache 2.0** at your option: |
| 180 | +<https://opensource.org/licenses/MIT> |
| 181 | +<https://www.apache.org/licenses/LICENSE-2.0> |
0 commit comments