lightning_sys/
lib.rs

1//! lightning-sys aims provides safe (as safe as a jit can be) rust bindings to GNU Lightning
2//!
3//! ## Examples:
4//! ### a function that increments a number by one
5//! ```
6//! use lightning_sys::{Jit, Reg, JitPointer, JitWord};
7//!
8//! let mut jit = Jit::new();
9//! let mut js = jit.new_state();
10//!
11//! js.prolog();
12//! let inarg = js.arg();
13//! js.getarg(Reg::R(0), &inarg);
14//! js.addi(Reg::R(0), Reg::R(0), 1);
15//! js.retr(Reg::R(0));
16//!
17//! let incr = unsafe { js.emit::<extern fn(JitWord) -> JitWord>() };
18//! js.clear();
19//!
20//! assert_eq!(incr(5), 6);
21//! assert_eq!(incr(6), 7);
22//!
23//! ```
24//!
25//! ### A simple function call to `printf`
26//! ```
27//! extern crate libc;
28//!
29//! use std::ffi::CString;
30//! use lightning_sys::{Jit, JitWord, Reg, JitPointer};
31//! use std::convert::TryInto;
32//!
33//! fn main() {
34//!     let mut jit = Jit::new();
35//!     let mut js = jit.new_state();
36//!
37//!     // make sure this outlives any calls
38//!     let cs = CString::new("generated %d bytes\n").unwrap();
39//!
40//!     let start = js.note(Some(file!()), line!());
41//!     js.prolog();
42//!     let inarg = js.arg();
43//!     js.getarg(Reg::R(1), &inarg);
44//!     js.prepare();
45//!     js.pushargi(cs.as_ptr() as JitWord);
46//!     js.ellipsis();
47//!     js.pushargr(Reg::R(1));
48//!     js.finishi(libc::printf as JitPointer);
49//!     js.ret();
50//!     js.epilog();
51//!     let end = js.note(Some(file!()), line!());
52//!
53//!     let my_function = unsafe{ js.emit::<extern fn(JitWord)>() };
54//!     /* call the generated code, passing its size as argument */
55//!     my_function((js.address(&end) as u64 - js.address(&start) as u64).try_into().unwrap());
56//!     js.clear();
57//!
58//!     // TODO: dissasembly has not been implemented yet
59//!     // js.dissasemble();
60//! }
61//!
62//! ```
63//!
64//! ### Fibonacci numbers
65//! ```
66//! use lightning_sys::{Jit, JitWord, Reg, JitPointer, NULL};
67//!
68//! fn main() {
69//!     let mut jit = Jit::new();
70//!     let mut js = jit.new_state();
71//!
72//!     let label = js.label();
73//!                 js.prolog();
74//!     let inarg = js.arg();
75//!                 js.getarg(Reg::R(0), &inarg);
76//!     let zero  = js.beqi(Reg::R(0), 0);
77//!                 js.movr(Reg::V(0), Reg::R(0));
78//!                 js.movi(Reg::R(0), 1);
79//!     let refr  = js.blei(Reg::V(0), 2);
80//!                 js.subi(Reg::V(1), Reg::V(0), 1);
81//!                 js.subi(Reg::V(2), Reg::V(0), 2);
82//!                 js.prepare();
83//!                 js.pushargr(Reg::V(1));
84//!     let call  = js.finishi(NULL);
85//!                 js.patch_at(&call, &label);
86//!                 js.retval(Reg::V(1));
87//!                 js.prepare();
88//!                 js.pushargr(Reg::V(2));
89//!     let call2 = js.finishi(NULL);
90//!                 js.patch_at(&call2, &label);
91//!                 js.retval(Reg::R(0));
92//!                 js.addr(Reg::R(0), Reg::R(0), Reg::V(1));
93//!
94//!                 js.patch(&refr);
95//!                 js.patch(&zero);
96//!                 js.retr(Reg::R(0));
97//!                 js.epilog();
98//!
99//!     let fib = unsafe{ js.emit::<extern fn(JitWord) -> JitWord>() };
100//!     js.clear();
101//!
102//!     println!("fib({})={}", 32, fib(32));
103//!     assert_eq!(0, fib(0));
104//!     assert_eq!(1, fib(1));
105//!     assert_eq!(1, fib(2));
106//!     assert_eq!(2178309, fib(32));
107//! }
108//! ```
109//!
110//! ### Tail Call Optimized factorial
111//! ```
112//! use lightning_sys::{Jit, JitWord, Reg, NULL};
113//!
114//! fn main() {
115//!     let mut jit = Jit::new();
116//!     let mut js = jit.new_state();
117//!
118//!     let fact = js.forward();
119//!
120//!                 js.prolog();
121//!     let inarg = js.arg();
122//!                 js.getarg(Reg::R(0), &inarg);
123//!                 js.prepare();
124//!                 js.pushargi(1);
125//!                 js.pushargr(Reg::R(0));
126//!     let call  = js.finishi(NULL);
127//!                 js.patch_at(&call, &fact);
128//!
129//!                 js.retval(Reg::R(0));
130//!                 js.retr(Reg::R(0));
131//!                 js.epilog();
132//!
133//!     js.link(&fact);
134//!                 js.prolog();
135//!                 js.frame(16);
136//!     let f_ent = js.label(); // TCO entry point
137//!     let ac    = js.arg();
138//!     let ina   = js.arg();
139//!                 js.getarg(Reg::R(0), &ac);
140//!                 js.getarg(Reg::R(1), &ina);
141//!     let f_out = js.blei(Reg::R(1), 1);
142//!                 js.mulr(Reg::R(0), Reg::R(0), Reg::R(1));
143//!                 js.putargr(Reg::R(0), &ac);
144//!                 js.subi(Reg::R(1), Reg::R(1), 1);
145//!                 js.putargr(Reg::R(1), &ina);
146//!     let jump  = js.jmpi(); // tail call optimiation
147//!                 js.patch_at(&jump, &f_ent);
148//!                 js.patch(&f_out);
149//!                 js.retr(Reg::R(0));
150//!
151//!     let factorial = unsafe{ js.emit::<extern fn(JitWord) -> JitWord>() };
152//!     js.clear();
153//!
154//!     println!("factorial({}) = {}", 5, factorial(5));
155//!     assert_eq!(1, factorial(1));
156//!     assert_eq!(2, factorial(2));
157//!     assert_eq!(6, factorial(3));
158//!     assert_eq!(24, factorial(4));
159//!     assert_eq!(120, factorial(5));
160//! }
161//! ```
162// Enforce some lints for the whole crate.
163#![deny(clippy::needless_lifetimes)]
164#![deny(clippy::transmute_ptr_to_ptr)]
165#![allow(clippy::needless_doctest_main)] // remain faithful to original examples
166
167// Suppress some lints for bindings specifically.
168#[allow(non_upper_case_globals)]
169#[allow(non_camel_case_types)]
170#[allow(dead_code)]
171#[allow(clippy::unreadable_literal)]
172#[allow(clippy::trivially_copy_pass_by_ref)]
173#[allow(clippy::useless_transmute)]
174#[allow(clippy::too_many_arguments)]
175mod bindings;
176
177#[macro_use]
178extern crate lazy_static;
179
180// The `raw` module comes first so that it can provide macros during parsing of
181// other modules. It is not yet part of the crate's public API, but in the
182// spirit of *-sys modules exposing lowest-level bindings, it may someday be so.
183#[macro_use]
184pub(crate) mod raw;
185
186pub mod jit;
187pub use jit::Jit;
188
189pub mod jitstate;
190pub use jitstate::JitState;
191
192pub mod types;
193pub use types::NULL;
194pub use types::Reg;
195pub use types::JitNode;
196pub use types::{JitWord, JitUword, JitPointer};
197pub(crate) use types::ToFFI;