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.
llvm-ir: LLVM IR in natural Rust data structures
llvm-ir
seeks to provide a Rust-y representation of LLVM IR.
It's based on the idea that an LLVM Instruction
shouldn't be an opaque
datatype, but rather an enum
with variants like Add
, Call
, and
Store
.
Likewise, types like BasicBlock
, Function
, and Module
should be
Rust structs containing as much information as possible.
Unlike other safe LLVM bindings such as inkwell
, llvm-ir
does not rely
on continuous FFI to the LLVM API.
It uses the LLVM API only for its initial parsing step, to pull in all the
data it needs to construct its rich representation of LLVM IR.
Once llvm-ir
creates a Module
data structure by parsing an LLVM file
(using the excellent llvm-sys
low-level LLVM bindings), it drops the LLVM
FFI objects and makes no further FFI calls.
This allows you to work with the resulting LLVM IR in pure safe Rust.
llvm-ir
is intended for consumption of LLVM IR, and not necessarily
production of LLVM IR (yet).
That is, it is aimed at program analysis and related applications which want
to read and analyze LLVM IR.
In the future, perhaps llvm-ir
could be able to output its Module
s back
into LLVM files, or even send them directly to the LLVM library for compiling.
If this interests you, contributions are welcome!
(Or in the meantime, check out inkwell
for a different safe interface for
producing LLVM IR.)
But if you're looking for a nice read-oriented representation of LLVM IR for
working in pure Rust, that's exactly what llvm-ir
can provide today.
Getting started
This crate is on crates.io, so you can simply
add it as a dependency in your Cargo.toml
:
[]
= "0.4.1"
Then, the easiest way to get started is to parse some existing LLVM IR into
this crate's data structures.
To do this, you need LLVM bitcode (*.bc
) files.
If you currently have C/C++ sources (say, source.c
), you can generate
*.bc
files with clang
's -c
and -emit-llvm
flags:
Then, in Rust, you can use llvm-ir
's Module::from_bc_path
function:
use Module;
use Path;
let path = new;
let module = from_bc_path?;
Documentation
Documentation for llvm-ir
can be found here,
or of course you can generate local documentation with cargo doc --open
.
The documentation includes links to relevant parts of the LLVM documentation
when appropriate.
Compatibility
Currently, llvm-ir
only supports LLVM 9. However, it should probably "just
work" with LLVM 8 if you simply open Cargo.toml
and change the line
= "90.0"
to
= "80.1"
then cargo clean
and rebuild. LLVMs older than 8 are not supported.
llvm-ir
works on stable Rust, and requires Rust 1.36+.
Development/Debugging
For development or debugging, you may want LLVM text-format (*.ll
) files in
addition to *.bc
files.
You can generate these by passing -S -emit-llvm
to clang
, instead of
-c -emit-llvm
.
E.g.,
Limitations
A few features of LLVM IR are not yet represented in llvm-ir
's data
structures, most notably debug information (metadata), which llvm-ir
currently makes no attempt to recover.
LLVM files containing metadata can still be parsed in with no problems, but
the resulting Module
structures will not contain any of the metadata.
Work-in-progress on fixing this can be found on the metadata
branch of this
repo, but be warned that the metadata
branch doesn't even build at the time
of this writing, let alone provide any meaningful functionality for crate
users.
A few other features are missing from llvm-ir
's data structures because
getters for them are missing from the LLVM C API and the Rust llvm-sys
crate, only being present in the LLVM C++ API.
These include but are not limited to:
- the
nsw
andnuw
flags onAdd
,Sub
,Mul
, andShl
, and likewise theexact
flag onUDiv
,SDiv
,LShr
, andAShr
. The C API has functionality to set these flags and/or create new instructions specifying values of these flags, but not to query the values of these flags on existing instructions. - the "fast-math flags" on various floating-point operations
- the specific opcode for the
AtomicRMW
instruction, i.e.,Xchg
,Add
,Max
,Min
, and the like. Again, the C API allows creatingAtomicRMW
instructions with any of these opcodes, but has no way to get the opcode for an existingAtomicRMW
instruction. - contents of inline assembly functions
- information about the clauses in the variadic
LandingPad
instruction - information about the operands of a
BlockAddress
constant expression - the "other labels" reachable from a
CallBr
terminator - the "prefix data" associated with a function
These issues with the LLVM C API have also been reported as
LLVM bug #42692.
As discussed there, the AtomicRMW
opcode getters have been added in trunk
(and should be available in the LLVM 10 release), but the others remain open
problems.
Any contributions to filling these gaps in the C API are greatly appreciated!
Acknowledgments
llvm-ir
is heavily inspired by the llvm-hs-pure
Haskell package.
Most of the data structures in llvm-ir
are essentially translations from
Haskell to Rust of the data structures in llvm-hs-pure
(with some tweaks).
To a lesser extent, llvm-ir
borrows from the larger llvm-hs
Haskell
package as well.