Skip to content

Instantly share code, notes, and snippets.

@elfsternberg
Last active April 7, 2017 16:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save elfsternberg/8ff6e845c3d49f1f1872736d3446268c to your computer and use it in GitHub Desktop.
Save elfsternberg/8ff6e845c3d49f1f1872736d3446268c to your computer and use it in GitHub Desktop.
Baby's first Just In Time Compiler, only now written in Rust!
/*
Baby's First JIT, Rust Edition
Example derived from Curtis McEnroe's Baby's first JIT, C Version:
https://cmcenroe.me/2016/10/13/babys-first-jit.html
Works with Rustc 1.15. No guarantees or warranties. License is CC-BY,
summary at the end.
You'll need these dependencies in your Cargo.toml. Then replace your
main.rs with the contents of this file.
[dependencies]
libc = "0.2.0"
memmap = "0.5.2"
*/
extern crate libc;
extern crate memmap;
use std::env;
use memmap::{Mmap, Protection};
fn main() {
if env::args().len() < 2 {
panic!("Insufficient arguments for this function.");
}
let args: Vec<String> = env::args().collect();
let term = match args[1].parse::<u32>() {
Ok(a) => a,
Err(_) => panic!("Not a number! Aieee!")
};
let pagesize: usize = unsafe { libc::sysconf(libc::_SC_PAGESIZE) } as usize;
let mut code = Mmap::anonymous(pagesize, Protection::ReadWrite).unwrap();
/*
The prog array is a representation of the tiny assembly
language function below; that function was compiled with NASM
as-is, and the binary dumped with the command
xxd -g1 <binary> | cut -d':' -f2 | sed 's/ /, 0x/g; s/^, //; s/, 0x,.*$//'
and then pasted into the initializer for prog[] below.
bits 64
mov rax, strict dword 0
add rax, rdi
ret
This represents a naive tile of a functor of one argument that adds
that argument to an value "enclosed" at run-time.
*/
let prog = [0x48, 0xc7, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x48, 0x01, 0xf8, 0xc3];
for (index, value) in prog.into_iter().enumerate() {
unsafe { *(code.mut_ptr().offset(index as isize)) = *value }
}
/*
The "JIT" part: insert a number from the command line argument
into the pre-compiled "tile" above. The bytes of our term have
to be placed into the DWORD in their little-endian order, byte
by byte. Fun!
The scope is necessary in Rust to prevent it from complaining
about `code` being borrowed twice: once here by `page`, and then again
by `set_protection`. By ending the scope, we end ownership by `page` of
the mutable, and ownership reverts back to `code`.
*/
{
let page = unsafe { code.as_mut_slice() };
page[3] = term as u8;
page[4] = (term >> 8) as u8;
page[5] = (term >> 16) as u8;
page[6] = (term >> 24) as u8;
}
code.set_protection(Protection::ReadExecute);
/*
Yup. For my third Rust experiment, I peer deep into Il Libro Di
Calgistro!
*/
let fptr = unsafe { std::mem::transmute::<*mut u8, fn(i32) -> i32>(code.mut_ptr()) };
println!("{} {} {}", fptr(1), fptr(2), fptr(3));
/* THE END */
}
/*
LICENSE:
https://creativecommons.org/licenses/by/4.0/
This is free software released under the CC-BY license. Users of this software
enjoy the following rights and responsibilities:
Share — You may copy and redistribute the material in any medium or format
Adapt — You may remix, transform, and build upon the material for any
purpose, even commercially.
Attribution — You must give appropriate credit, provide a link to the
license, and indicate if changes were made. You may do so in any
reasonable manner, but not in any way that suggests the licensor
endorses you or your use.
You may not employ technological measures or legal terms that legally
prevent others from doing anything the license permits.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment