Lyn provides Python bindings for GNU Lightning, the light-weight just-in-time (JIT) compiler that translates to native machine code.
The code is hosted on https://github.com/cslarsen/lyn/ and is installable from https://pypi.python.org/pypi/lyn/ (although I currently don’t update PyPi quite often).
“Lyn” is the Norwegian word for “lightning”.
NOTE: This project is currently in extremely early stages!
Status
As mentioned above, Lyn is fledgling: I’ve just spent a few hours on it, so almost nothing is supported and — in particular — I’ve only targeted x86-64 opcodes just yet. Some tests are also failing: Min and max 64-bit numbers don’t seem to pass through correctly, so I’m currently working on fixing that issue first.
In spite of this, I’ve managed to create a really simple program in Python that is JIT-compiled to native x86-64 machine code: A glorious function that returns the value of 123! Here’s the code:
from lyn import Lightning, Register
with Lightning().state() as jit:
jit.prolog()
# Actual code
jit.movi(Register.v0, 123)
jit.retr(Register.v0)
# Compile to native code and wrap in a Python-callable function
func = jit.emit_function(Lightning.word_t)
print("Function returned %s and that is %s!" % (
func(), "correct" if func() == 123 else "incorrect"))
Also, I’ve not been able to compile GNU Lightning with disassembly support, so I just used Capstone instead (install with pip install capstone):
from lyn import *
import capstone
import ctypes
lib = Lightning()
jit = lib.new_state()
# A function that returns one more than its integer input
start = jit.note()
jit.prolog()
arg = jit.arg()
jit.getarg(Register.r0, arg)
jit.addi(Register.r0, Register.r0, 1)
jit.retr(Register.r0)
jit.epilog()
end = jit.note()
# Bind function to Python: returns a word (native integer), takes a word.
incr = jit.emit_function(lib.word_t, [lib.word_t])
# Sanity check
assert(incr(1234) == 1235)
# This part should be obvious to C programmers: We need to read data from raw
# memory in to a Python iterable.
length = (jit.address(end) - jit.address(start)).value
codebuf = ctypes.create_string_buffer(length)
ctypes.memmove(codebuf, ctypes.c_char_p(incr.address.value), length)
print("Compiled %d bytes starting at 0x%x" % (length, incr.address))
def hexbytes(b):
return "".join(map(lambda x: hex(x)[2:] + " ", b))
# Capstone is smart enough to stop at the first RET-like instruction.
md = capstone.Cs(capstone.CS_ARCH_X86, capstone.CS_MODE_64)
md.syntax = capstone.CS_OPT_SYNTAX_ATT # Change to Intel syntax if you want
for i in md.disasm(codebuf, incr.address.value):
print("0x%x %-15s%s %s" % (i.address, hexbytes(i.bytes), i.mnemonic, i.op_str))
raw = "".join(map(lambda x: "\\x%02x" % x, map(ord, codebuf)))
print("\nRaw bytes: %s" % raw)
This outputs:
Compiled 34 bytes starting at 0x10acf4000 0x10acf4000 48 83 ec 30 subq $0x30, %rsp 0x10acf4004 48 89 2c 24 movq %rbp, (%rsp) 0x10acf4008 48 89 e5 movq %rsp, %rbp 0x10acf400b 48 83 ec 18 subq $0x18, %rsp 0x10acf400f 48 89 f8 movq %rdi, %rax 0x10acf4012 48 83 c0 1 addq $1, %rax 0x10acf4016 48 89 ec movq %rbp, %rsp 0x10acf4019 48 8b 2c 24 movq (%rsp), %rbp 0x10acf401d 48 83 c4 30 addq $0x30, %rsp 0x10acf4021 c3 retq Raw bytes: \x48\x83\xec\x30\x48\x89\x2c\x24[...]
I’m using ctypes for creating the bindings, which comes with some challenges: GNU Lightning is written in C, and relies heavily on compile-time macros that define machine specific opcodes, register values and so on.
Because of this, it would be more natural to simply create bindings through a C extension. On the other hand, though, ctypes makes it possible to ship Lyn as a platform independent, pure Python source. I’ll chew on this for a while, and we’ll see what happens.
Installation
Either:
$ pip install lyn
or:
$ python setup.py install
Requirements
You need GNU Lightning version 2.1.0, built as a shared library.
Remember to configure GNU Lightning with the option --enable-shared. To use the disassembler, you should also add --enable-disassembler.
Release files for lyn 0.0.4
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| lyn-0.0.4.tar.gz | 18.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| lyn-0.0.4-py2.py3-none-any.whl | Python 3, Python 2 | none | any | Details |
Total release size: 30.8 kB
Release files / lyn-0.0.4.tar.gz
| Download URL | lyn-0.0.4.tar.gz |
|---|---|
| Size | 18.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
d41fd68150c4c68ee54c51ecce7c5d62f96a65a4d98180da50e0c56fc970a89a
|
|
BLAKE2b-256 checksum How to use checksums |
c765dc6b5efb99272b297f81bdb086c44d3f259f063ab55bbc60e137a238082d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
Release files / lyn-0.0.4-py2.py3-none-any.whl
| Download URL | lyn-0.0.4-py2.py3-none-any.whl |
|---|---|
| Size | 12.2 kB |
| Tags | Python 2 Python 3 |
|
SHA-256 checksum How to use checksums |
accb6407a6ce3b5147f93b2cd29afebca262931f767578ba9abd253c7e44a8d8
|
|
BLAKE2b-256 checksum How to use checksums |
9ada6b89623375ae52d8c692891ebe73738e14a417bc9d40ce03e2063cae9860
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |