Skip to content

Commit

Permalink
feat: internal bytecode representation, add more docs
Browse files Browse the repository at this point in the history
  • Loading branch information
DaniPopes committed Mar 22, 2024
1 parent 398e804 commit b2061cc
Show file tree
Hide file tree
Showing 20 changed files with 664 additions and 205 deletions.
47 changes: 47 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ authors = ["DaniPopes <[email protected]>"]
edition = "2021"
rust-version = "1.76"
license = "MIT OR Apache-2.0"
categories = []
categories = ["compilers", "cryptography::cryptocurrencies"]
keywords = ["compile", "compiler", "jit", "evm", "ethereum"]
homepage = "https://github.com/danipopes/cranelift-jit-evm"
repository = "https://github.com/danipopes/cranelift-jit-evm"
Expand All @@ -34,3 +34,5 @@ revm-primitives = "3.1.0"
revm-interpreter = "3.4.0"

color-eyre = "0.6"
tracing = "0.1"
tracing-subscriber = "0.3"
13 changes: 11 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,19 @@
# revm-jit

Experimental [JIT compiler][JIT] for [Ethereum Virtual Machine][EVM] using [Cranelift].
Experimental [JIT compiler][JIT] for the [Ethereum Virtual Machine][EVM].

The compiler implementation is abstracted over the JIT backend.

This project hosts two backend implementations:
- [LLVM] ([`revm-jit-llvm`]): main backend with full test coverage;
- [Cranelift] ([`revm-jit-cranelift`]); currently not functional due to missing `i256` support in Cranelift. This will likely require a custom fork of Cranelift.

[EVM]: https://ethereum.org/en/developers/docs/evm/
[JIT]: https://en.wikipedia.org/wiki/Just-in-time_compilation
[EVM]: https://ethereum.org/en/developers/docs/evm/
[LLVM]: https://llvm.org/
[`revm-jit-llvm`]: /crates/revm-jit-llvm
[Cranelift]: https://cranelift.dev/
[`revm-jit-cranelift`]: /crates/revm-jit-cranelift

#### License

Expand Down
1 change: 1 addition & 0 deletions crates/revm-jit-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,4 @@ revm-primitives.workspace = true
revm-interpreter.workspace = true

color-eyre.workspace = true
tracing.workspace = true
3 changes: 3 additions & 0 deletions crates/revm-jit-core/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# revm-jit-core

Core abstraction and data structures for `revm-jit`.
15 changes: 2 additions & 13 deletions crates/revm-jit-core/src/context.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,8 @@
use revm_interpreter::InstructionResult;
use std::mem::MaybeUninit;

/// The signature of a JIT'd EVM bytecode.
pub type JitEvmFn = unsafe extern "C" fn(*mut ContextStack) -> Ret;

/// The return value of a JIT'd EVM bytecode function.
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(i32)]
pub enum Ret {
/// `STOP` instruction.
Stop,
/// Stack underflow.
StackUnderflow,
/// Stack overflow.
StackOverflow,
}
pub type JitEvmFn = unsafe extern "C" fn(*mut ContextStack) -> InstructionResult;

/// JIT EVM context stack.
#[repr(C, align(32))]
Expand Down
19 changes: 17 additions & 2 deletions crates/revm-jit-core/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,32 @@
//! TODO

#![doc = include_str!("../README.md")]
#![allow(missing_docs)]
#![cfg_attr(not(test), warn(unused_extern_crates))]
#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]

#[macro_use]
mod macros;

mod context;
pub use context::*;

mod traits;
pub use traits::*;

#[doc(no_inline)]
pub use revm_interpreter as interpreter;
#[doc(no_inline)]
pub use revm_interpreter::InstructionResult;
#[doc(no_inline)]
pub use revm_primitives as primitives;

/// JIT compilation result.
pub type Result<T, E = Error> = std::result::Result<T, E>;

/// JIT compilation error.
pub type Error = color_eyre::eyre::Error;

// Not public API.
#[doc(hidden)]
pub mod private {
pub use tracing;
}
27 changes: 27 additions & 0 deletions crates/revm-jit-core/src/macros.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/// Log the time it takes to execute the given expression.
#[macro_export]
macro_rules! time {
($level:expr, $what:literal, || $e:expr) => {{
let timer = std::time::Instant::now();
let res = $e;
// $crate::private::tracing::event!($level, elapsed=?timer.elapsed(), $what);
$crate::private::tracing::event!($level, "{:>10?} - {}", timer.elapsed(), $what);
res
}};
}

/// Log the time it takes to execute the given expression at `debug` level.
#[macro_export]
macro_rules! debug_time {
($what:literal, || $e:expr) => {
$crate::time!($crate::private::tracing::Level::DEBUG, $what, || $e)
};
}

/// Log the time it takes to execute the given expression at `trace` level.
#[macro_export]
macro_rules! trace_time {
($what:literal, || $e:expr) => {
$crate::time!($crate::private::tracing::Level::TRACE, $what, || $e)
};
}
19 changes: 10 additions & 9 deletions crates/revm-jit-core/src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,26 +27,26 @@ pub enum IntCC {
UnsignedLessThanOrEqual,
}

pub trait CodegenObject: Copy + PartialEq + fmt::Debug {}
impl<T: Copy + PartialEq + fmt::Debug> CodegenObject for T {}

pub trait Builder {
type Type: CodegenObject;
type Value: CodegenObject;
type StackSlot: CodegenObject;
type BasicBlock: CodegenObject;
type Type: Copy + Eq + fmt::Debug;
type Value: Copy + Eq + fmt::Debug;
type StackSlot: Copy + Eq + fmt::Debug;
type BasicBlock: Copy + Eq + fmt::Debug;

fn type_ptr(&self) -> Self::Type;
fn type_ptr_sized_int(&self) -> Self::Type;
fn type_int(&self, bits: u32) -> Self::Type;
fn type_array(&self, ty: Self::Type, size: u32) -> Self::Type;

fn create_block(&mut self) -> Self::BasicBlock;
fn create_block(&mut self, name: &str) -> Self::BasicBlock;
fn create_block_after(&mut self, after: Self::BasicBlock, name: &str) -> Self::BasicBlock;
fn switch_to_block(&mut self, block: Self::BasicBlock);
fn seal_block(&mut self, block: Self::BasicBlock);
fn set_cold_block(&mut self, block: Self::BasicBlock);
fn current_block(&mut self) -> Option<Self::BasicBlock>;

fn add_comment_to_current_inst(&mut self, comment: &str);

fn fn_param(&mut self, index: usize) -> Self::Value;

fn bool_const(&mut self, value: bool) -> Self::Value;
Expand Down Expand Up @@ -111,7 +111,7 @@ pub trait Builder {
fn zext(&mut self, ty: Self::Type, value: Self::Value) -> Self::Value;
fn sext(&mut self, ty: Self::Type, value: Self::Value) -> Self::Value;

fn gep_add(&mut self, ty: Self::Type, ptr: Self::Value, offset: Self::Value) -> Self::Value;
fn gep(&mut self, ty: Self::Type, ptr: Self::Value, offset: Self::Value) -> Self::Value;
}

pub trait Backend {
Expand All @@ -127,6 +127,7 @@ pub trait Backend {
fn dump_disasm(&mut self, path: &Path) -> Result<()>;

fn build_function(&mut self, name: &str) -> Result<Self::Builder<'_>>;
fn verify_function(&mut self, name: &str) -> Result<()>;
fn optimize_function(&mut self, name: &str) -> Result<()>;
fn get_function(&mut self, name: &str) -> Result<JitEvmFn>;
}
8 changes: 4 additions & 4 deletions crates/revm-jit-cranelift/README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# revm-jit
# revm-jit-cranelift

Experimental [JIT compiler][JIT] for [Ethereum Virtual Machine][EVM] bytecode using [Cranelift].
[Cranelift] backend for `revm-jit`.

This crate is currently not functional due to missing `i256` support in Cranelift.

[EVM]: https://ethereum.org/en/developers/docs/evm/
[JIT]: https://en.wikipedia.org/wiki/Just-in-time_compilation
[Cranelift]: https://cranelift.dev/
Loading

0 comments on commit b2061cc

Please sign in to comment.