Skip to content

Commit ccf5526

Browse files
committed
New tests - RSA encrypt.decrypt, fibonacchi.
Also some changes regarding `checkcast` and better handling of option in the stdlib shim (unrelated to the new tests). And a readme makeover.
1 parent eb02e25 commit ccf5526

File tree

21 files changed

+959
-473
lines changed

21 files changed

+959
-473
lines changed

Readme.md

+172-141
Original file line numberDiff line numberDiff line change
@@ -1,150 +1,181 @@
1-
# Rustc Codegen JVM 🚀
1+
# rustc_codegen_jvm 🚀
22

3-
[![License: MIT OR Apache-2.0](https://img.shields.io/badge/License-MIT%20OR%20Apache--2.0-blue.svg)](https://opensource.org/licenses/MIT)
3+
[![License: MIT/Apache-2.0](https://img.shields.io/badge/license-MIT%20%7C%20Apache--2.0-blue.svg)](https://opensource.org/licenses/MIT)
4+
[![CI](https://github.com/IntegralPilot/rustc_codegen_jvm/actions/workflows/ci.yml/badge.svg)](https://github.com/IntegralPilot/rustc_codegen_jvm/actions)
45

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+!
68

7-
## How It Works
9+
---
810

9-
The toolchain transforms Rust code into executable `.jar` files through several stages:
11+
## 📖 Table of Contents
1012

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)
1323

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+
---
1625

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
1927

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:
2229

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

Comments
 (0)