#lightning #bindings #gnu #lightning-2

sys lightning-sys

Rust 的 GNU lightning 绑定

6 个版本

0.2.2 2020 年 8 月 22 日
0.2.1 2020 年 5 月 9 日
0.2.0 2019 年 8 月 17 日
0.1.2 2019 年 8 月 14 日
0.1.0 2019 年 7 月 21 日

#3 in #lightning

LGPL-3.0-or-later

3MB
94K SLoC

C 92K SLoC // 0.0% comments Rust 1.5K SLoC // 0.0% comments Automake 427 SLoC // 0.2% comments Bitbake 390 SLoC // 0.3% comments Shell 109 SLoC // 0.1% comments

包含 (不为人知的 autoconf 代码,9KB) vendor/gnu-lightning/configure.ac

lightning-sys

crates.io docs.rs Build Status

Rust 的安全 GNU lightning 绑定

GNU lightning 版本

此 crate 明确链接到其自己的 lightning-2.1.3 版本的副本。

MSRV

最低支持的 Rust 版本是 1.39

示例

一个将数字增加 1 的函数

use lightning_sys::{Jit, Reg, JitPointer, JitWord};

let mut jit = Jit::new();
let mut js = jit.new_state();

js.prolog();
let inarg = js.arg();
js.getarg(Reg::R(0), &inarg);
js.addi(Reg::R(0), Reg::R(0), 1);
js.retr(Reg::R(0));

let incr = unsafe { js.emit::<extern fn(JitWord) -> JitWord>() };
js.clear();

assert_eq!(incr(5), 6);
assert_eq!(incr(6), 7);

printf 的简单函数调用

extern crate libc;

use std::ffi::CString;
use lightning_sys::{Jit, JitWord, Reg, JitPointer};
use std::convert::TryInto;

fn main() {
    let mut jit = Jit::new();
    let mut js = jit.new_state();

    // make sure this outlives any calls
    let cs = CString::new("generated %d bytes\n").unwrap();

    let start = js.note(file!(), line!());
    js.prolog();
    let inarg = js.arg();
    js.getarg(Reg::R(1), &inarg);
    js.prepare();
    js.pushargi(cs.as_ptr() as JitWord);
    js.ellipsis();
    js.pushargr(Reg::R(1));
    js.finishi(libc::printf as JitPointer);
    js.ret();
    js.epilog();
    let end = js.note(file!(), line!());

    let my_function = unsafe{ js.emit::<extern fn(JitWord)>() };
    /* call the generated code, passing its size as argument */
    my_function((js.address(&end) as u64 - js.address(&start) as u64).try_into().unwrap());
    js.clear();

    // TODO: dissasembly has not been implemented yet
    // js.dissasemble();
}

斐波那契数列

use lightning_sys::{Jit, JitWord, Reg, JitPointer, NULL};

fn main() {
    let mut jit = Jit::new();
    let mut js = jit.new_state();

    let label = js.label();
                js.prolog();
    let inarg = js.arg();
                js.getarg(Reg::R(0), &inarg);
    let zero  = js.beqi(Reg::R(0), 0);
                js.movr(Reg::V(0), Reg::R(0));
                js.movi(Reg::R(0), 1);
    let refr  = js.blei(Reg::V(0), 2);
                js.subi(Reg::V(1), Reg::V(0), 1);
                js.subi(Reg::V(2), Reg::V(0), 2);
                js.prepare();
                js.pushargr(Reg::V(1));
    let call  = js.finishi(NULL);
                js.patch_at(&call, &label);
                js.retval(Reg::V(1));
                js.prepare();
                js.pushargr(Reg::V(2));
    let call2 = js.finishi(NULL);
                js.patch_at(&call2, &label);
                js.retval(Reg::R(0));
                js.addr(Reg::R(0), Reg::R(0), Reg::V(1));

                js.patch(&refr);
                js.patch(&zero);
                js.retr(Reg::R(0));
                js.epilog();

    let fib = unsafe{ js.emit::<extern fn(JitWord) -> JitWord>() };
    js.clear();

    println!("fib({})={}", 32, fib(32));
    assert_eq!(0, fib(0));
    assert_eq!(1, fib(1));
    assert_eq!(1, fib(2));
    assert_eq!(2178309, fib(32));
}

尾调用优化的阶乘

use lightning_sys::{Jit, JitWord, Reg, NULL};

fn main() {
    let mut jit = Jit::new();
    let mut js = jit.new_state();

    let fact = js.forward();

                js.prolog();
    let inarg = js.arg();
                js.getarg(Reg::R(0), &inarg);
                js.prepare();
                js.pushargi(1);
                js.pushargr(Reg::R(0));
    let call  = js.finishi(NULL);
                js.patch_at(&call, &fact);

                js.retval(Reg::R(0));
                js.retr(Reg::R(0));
                js.epilog();

    js.link(&fact);
                js.prolog();
                js.frame(16);
    let f_ent = js.label(); // TCO entry point
    let ac    = js.arg();
    let ina   = js.arg();
                js.getarg(Reg::R(0), &ac);
                js.getarg(Reg::R(1), &ina);
    let f_out = js.blei(Reg::R(1), 1);
                js.mulr(Reg::R(0), Reg::R(0), Reg::R(1));
                js.putargr(Reg::R(0), &ac);
                js.subi(Reg::R(1), Reg::R(1), 1);
                js.putargr(Reg::R(1), &ina);
    let jump  = js.jmpi(); // tail call optimiation
                js.patch_at(&jump, &f_ent);
                js.patch(&f_out);
                js.retr(Reg::R(0));

    let factorial = unsafe{ js.emit::<extern fn(JitWord) -> JitWord>() };
    js.clear();

    println!("factorial({}) = {}", 5, factorial(5));
}

依赖项

~0.1–2.7MB
~42K SLoC