prism-llvm 0.1.0

A Rust abstraction layer for LLVM with a compilation pipeline.
docs.rs failed to build prism-llvm-0.1.0
Please check the build logs for more information.
See Builds for ideas on how to fix a failed build, or Metadata for how to configure docs.rs builds.
If you believe this is docs.rs' fault, open an issue.

Prism

a Rust-based LLVM IR toolchain for turning .ll files into native executables (+ object files (.o), and bitcode files (.bc)) because apparently making an interpreter was too tuff.. and slow (unless it has some kinda JIT or AOT or whatever)... (more suffering, indeed..)

About

Prism is a Rust-based toolchain built around LLVM, designed to compile LLVM Intermediate Representation (IR) into native executables!!!

it currently accepts existing LLVM IR files rather than source code written in a programming language, because this is supposed to be a friendlier LLVM, not.. a fully-fledged programming language, too... congratulations to me because that means no lexer, parser and more here!!

i made this to practice working with:

  • LLVM and LLVM IR
  • compiler toolchain design
  • intermediate representations
  • native code generation
  • optimization pipelines
  • in-process LLVM APIs through Inkwell
  • Rust library design and LLVM abstractions (the main point)

the main idea is for Prism to provide a convenient, reusable LLVM interface and compilation pipeline for projects that wanna work with LLVM... (literally what i meant by a friendlier abstraction layer)

Features

  • LLVM IR input (.ll files)
  • LLVM bitcode generation (.bc files)
  • configurable optimization levels (-O0, -O1, -O2, -O3, -Os, -Oz)
  • native object-file generation through LLVM's in-process APIs
  • native executable linking through a configurable external linker
  • Rust API built around Inkwell and LLVM
  • programmatic LLVM module construction through Prism's builder API

How It Works

Prism takes an existing LLVM IR file and passes it through a compilation pipeline.

the general flow looks like this:

LLVM IR (.ll)
     |
     v
Inkwell / LLVM API
     |
     + ------- > Parse LLVM IR
     |
     + ------- > Optimize (when needed)
     |
     + ------- > Generate native object code
     |
     v
Object File (.o)
     |
     v
Configurable external linker
 (like: gcc / clang / cc)
     |
     v
Native Executable

Optimization

Prism supports the following optimization levels:

Flag Description
-O0 no explicit LLVM IR optimization pipeline
-O1 basic optimization
-O2 more extensive optimization
-O3 aggressive optimization
-Os optimization with a focus on code size
-Oz more aggressive optimization for code size

optimization levels configure LLVM's optimization pipeline and native code-generation settings where applicable.

for example, LLVM can fold constant expressions, simplify instructions, eliminate unnecessary work, and optimize function calls. a sufficiently simple program might end up returning a constant instead of performing all its original operations. JUST.. REMEMBER THE WORD OPTIMIZE..

but truthfully.. O2, Os, and Oz are all dumbed down to the same level..

Example

suppose you have an LLVM IR file named input.ll:

define i32 @main() {
entry:
    ret i32 42
}

you can compile it into a native executable using:

prism input.ll -o program

to enable more aggressive optimization:

prism input.ll -o program -O3

to specify a linker too:

prism input.ll -o program -O3 --linker /usr/bin/gcc

then execute the resulting program:

./program
echo $? # for result

the exit status will be 42.

yes, this program does absolutely nothing except return a number. we're starting small here!!

Command-Line Usage

the general syntax is:

prism <input.ll> -o <output> [optimization flag]? [--linker <path>]?

available optimization flags:

  • -O0
  • -O1
  • -O2
  • -O3
  • -Os
  • -Oz

example:

prism program.ll -o program -O2

the output path specifies the name of the generated executable.

Prism also generates intermediate compilation artifacts, including LLVM bitcode and an object file, during compilation.

do take note that if you don't pass an optimization flag, it uses -O0 as default!!

Requirements

you'll need:

  • Rust and Cargo
  • LLVM 22 and the LLVM libraries required by Prism's Inkwell configuration
  • a compatible system linker, such as gcc, clang, or cc

make sure the LLVM is installed and configured so Prism can build and link against it, and ensure your chosen system linker is available

Installation and Building

clone the repository:

git clone https://github.com/jayywashere/prism
cd prism

build the project:

cargo build --release

you can also run Prism directly through Cargo:

cargo run --release -- input.ll -o program -O2

if you've installed the prism launcher, you can invoke it directly:

prism input.ll -o program -O2

(you do notice there's also a .bat launcher.. for Windows users!! i just haven't tested it so.. i'll leave it up to you ^^)

Current Scope

so, Prism currently focuses on compiling existing LLVM IR into native executables.

LLVM IR can be written manually or generated by another tool. Prism also provides a Rust API for constructing LLVM modules programmatically, so projects can generate IR through Prism rather than writing .ll files themselves

for example, another project can generate LLVM IR, then pass it through Prism's compilation pipeline to produce native code. that's the point of the reusable abstraction layer!!

Related Projects

Prism is intended to fit into a larger ecosystem of programming-language projects, too

  • ARC — a reusable stack-based bytecode virtual machine.
  • TASM — an assembly-like language intended to target ARC and Prism.
  • Spark — a future language project that may use Prism as part of its compilation pipeline. (and ARC)

each project has its own responsibilities, and Prism focuses on the LLVM side of things

Why I Made This

tbh, i wanted to understand how compiler toolchains actually work instead of treating compilation as some mysterious process that magically turns code into executables. (sigh, the curious me)

i also wanted to experiment with LLVM and build reusable Rust abstractions around it, rather than just invoking random commands manually every time... the Inkwell methods give me a headache lowkey

naturally, this turned into another project where one feature leads to five more ideas and suddenly i'm thinking about optimization pipelines HAHA

goodbai

License

See LICENSE.