Skip to content

Commit

Permalink
feat: implement some env-fetching instructions
Browse files Browse the repository at this point in the history
  • Loading branch information
DaniPopes committed Mar 26, 2024
1 parent a59aadb commit 6f5cb1e
Show file tree
Hide file tree
Showing 10 changed files with 687 additions and 255 deletions.
9 changes: 7 additions & 2 deletions crates/revm-jit-backend/src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ pub enum IntCC {
pub enum Attribute {
// Function attributes.
WillReturn,
NoReturn,
NoFree,
NoRecurse,
NoSync,
Expand All @@ -59,6 +60,7 @@ pub enum Attribute {
HintInline,
AlwaysInline,
NoInline,
Speculatable,

// Parameter attributes.
NoAlias,
Expand All @@ -70,7 +72,7 @@ pub enum Attribute {
ReadNone,
ReadOnly,
WriteOnly,
Writeable,
Writable,
// TODO: Range?
}

Expand Down Expand Up @@ -132,6 +134,7 @@ pub trait TypeMethods: BackendTypes {
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 type_bit_width(&self, ty: Self::Type) -> u32;
}

pub trait Builder: BackendTypes + TypeMethods {
Expand Down Expand Up @@ -200,6 +203,8 @@ pub trait Builder: BackendTypes + TypeMethods {
fn isub_imm(&mut self, lhs: Self::Value, rhs: i64) -> Self::Value;
fn imul_imm(&mut self, lhs: Self::Value, rhs: i64) -> Self::Value;

fn bswap(&mut self, value: Self::Value) -> Self::Value;

fn bitor(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
fn bitand(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
fn bitxor(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
Expand All @@ -216,7 +221,7 @@ pub trait Builder: BackendTypes + TypeMethods {
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(&mut self, ty: Self::Type, ptr: Self::Value, offset: Self::Value) -> Self::Value;
fn gep(&mut self, ty: Self::Type, ptr: Self::Value, indexes: &[Self::Value]) -> Self::Value;
fn extract_value(&mut self, value: Self::Value, index: u32) -> Self::Value;

fn call(&mut self, function: Self::Function, args: &[Self::Value]) -> Option<Self::Value>;
Expand Down
16 changes: 14 additions & 2 deletions crates/revm-jit-cranelift/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,10 @@ impl TypeMethods for JitEvmCraneliftBackend {
fn type_array(&self, ty: Self::Type, size: u32) -> Self::Type {
unimplemented!("type: {size} x {ty}")
}

fn type_bit_width(&self, ty: Self::Type) -> u32 {
ty.bits()
}
}

impl Backend for JitEvmCraneliftBackend {
Expand Down Expand Up @@ -256,6 +260,10 @@ impl<'a> TypeMethods for JitEvmCraneliftBuilder<'a> {
fn type_array(&self, ty: Self::Type, size: u32) -> Self::Type {
unimplemented!("type: {size} x {ty}")
}

fn type_bit_width(&self, ty: Self::Type) -> u32 {
ty.bits()
}
}

impl<'a> Builder for JitEvmCraneliftBuilder<'a> {
Expand Down Expand Up @@ -491,6 +499,10 @@ impl<'a> Builder for JitEvmCraneliftBuilder<'a> {
self.bcx.ins().imul_imm(lhs, rhs)
}

fn bswap(&mut self, value: Self::Value) -> Self::Value {
self.bcx.ins().bswap(value)
}

fn bitor(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value {
self.bcx.ins().bor(lhs, rhs)
}
Expand Down Expand Up @@ -539,8 +551,8 @@ impl<'a> Builder for JitEvmCraneliftBuilder<'a> {
self.bcx.ins().sextend(ty, value)
}

fn gep(&mut self, ty: Self::Type, ptr: Self::Value, offset: Self::Value) -> Self::Value {
let offset = self.bcx.ins().imul_imm(offset, ty.bytes() as i64);
fn gep(&mut self, ty: Self::Type, ptr: Self::Value, indexes: &[Self::Value]) -> Self::Value {
let offset = self.bcx.ins().imul_imm(*indexes.first().unwrap(), ty.bytes() as i64);
self.bcx.ins().iadd(ptr, offset)
}

Expand Down
34 changes: 29 additions & 5 deletions crates/revm-jit-llvm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,10 @@ impl<'ctx> TypeMethods for JitEvmLlvmBackend<'ctx> {
fn type_array(&self, ty: Self::Type, size: u32) -> Self::Type {
ty.array_type(size).into()
}

fn type_bit_width(&self, ty: Self::Type) -> u32 {
ty.into_int_type().get_bit_width()
}
}

impl<'ctx> Backend for JitEvmLlvmBackend<'ctx> {
Expand Down Expand Up @@ -328,6 +332,10 @@ impl<'a, 'ctx> TypeMethods for JitEvmLlvmBuilder<'a, 'ctx> {
fn type_array(&self, ty: Self::Type, size: u32) -> Self::Type {
self.backend.type_array(ty, size)
}

fn type_bit_width(&self, ty: Self::Type) -> u32 {
self.backend.type_bit_width(ty)
}
}

impl<'a, 'ctx> Builder for JitEvmLlvmBuilder<'a, 'ctx> {
Expand Down Expand Up @@ -571,6 +579,15 @@ impl<'a, 'ctx> Builder for JitEvmLlvmBuilder<'a, 'ctx> {
self.imul(lhs, rhs)
}

fn bswap(&mut self, value: Self::Value) -> Self::Value {
let ty = value.get_type();
let bits = ty.into_int_type().get_bit_width();
assert!(bits % 16 == 0);
let name = format!("llvm.bswap.i{bits}");
let bswap = self.get_function_or(&name, |this| this.fn_type(Some(ty), &[ty]));
self.call(bswap, &[value.into()]).unwrap()
}

fn bitor(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value {
self.bcx.build_or(lhs.into_int_value(), rhs.into_int_value(), "").unwrap().into()
}
Expand Down Expand Up @@ -628,9 +645,14 @@ impl<'a, 'ctx> Builder for JitEvmLlvmBuilder<'a, 'ctx> {
self.bcx.build_int_s_extend(value.into_int_value(), ty.into_int_type(), "").unwrap().into()
}

fn gep(&mut self, elem_ty: Self::Type, ptr: Self::Value, offset: Self::Value) -> Self::Value {
let offset = offset.into_int_value();
unsafe { self.bcx.build_in_bounds_gep(elem_ty, ptr.into_pointer_value(), &[offset], "") }
fn gep(
&mut self,
elem_ty: Self::Type,
ptr: Self::Value,
indexes: &[Self::Value],
) -> Self::Value {
let indexes = indexes.iter().map(|idx| idx.into_int_value()).collect::<Vec<_>>();
unsafe { self.bcx.build_in_bounds_gep(elem_ty, ptr.into_pointer_value(), &indexes, "") }
.unwrap()
.into()
}
Expand Down Expand Up @@ -712,6 +734,7 @@ fn convert_attribute(
let cpu;
let (key, value) = match attr {
OurAttr::WillReturn => ("willreturn", AttrValue::Enum(1)),
OurAttr::NoReturn => ("noreturn", AttrValue::Enum(1)),
OurAttr::NoFree => ("nofree", AttrValue::Enum(1)),
OurAttr::NoRecurse => ("norecurse", AttrValue::Enum(1)),
OurAttr::NoSync => ("nosync", AttrValue::Enum(1)),
Expand All @@ -729,6 +752,7 @@ fn convert_attribute(
OurAttr::HintInline => ("inlinehint", AttrValue::Enum(1)),
OurAttr::AlwaysInline => ("alwaysinline", AttrValue::Enum(1)),
OurAttr::NoInline => ("noinline", AttrValue::Enum(1)),
OurAttr::Speculatable => ("speculatable", AttrValue::Enum(1)),

OurAttr::NoAlias => ("noalias", AttrValue::Enum(1)),
OurAttr::NoCapture => ("nocapture", AttrValue::Enum(1)),
Expand All @@ -739,15 +763,15 @@ fn convert_attribute(
OurAttr::ReadNone => ("readnone", AttrValue::Enum(1)),
OurAttr::ReadOnly => ("readonly", AttrValue::Enum(1)),
OurAttr::WriteOnly => ("writeonly", AttrValue::Enum(1)),
OurAttr::Writeable => ("writeable", AttrValue::Enum(1)),
OurAttr::Writable => ("writable", AttrValue::Enum(1)),

attr => todo!("{attr:?}"),
};
match value {
AttrValue::String(value) => bcx.cx.create_string_attribute(key, value),
AttrValue::Enum(value) => {
let id = Attribute::get_named_enum_kind_id(key);
bcx.cx.create_enum_attribute(id, value as u64)
bcx.cx.create_enum_attribute(id, value)
}
}
}
Expand Down
5 changes: 3 additions & 2 deletions crates/revm-jit/benches/bench.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

use criterion::{criterion_group, criterion_main, Criterion};
use revm_interpreter::{opcode as op, Gas, EMPTY_SHARED_MEMORY};
use revm_jit::{llvm, EvmStack, JitEvm, JitEvmFn};
use revm_jit::{llvm, EvmContext, EvmStack, JitEvm, JitEvmFn};
use revm_primitives::{SpecId, U256};
use std::{hint::black_box, time::Duration};

Expand Down Expand Up @@ -37,11 +37,12 @@ fn bench(c: &mut Criterion) {
stack_buf.push(input_u256.into());
let stack = EvmStack::from_mut_vec(&mut stack_buf);
let mut stack_len = 1;
let mut cx = EvmContext::dummy_do_not_use();
let mut call_jit = |f: JitEvmFn| {
stack.as_mut_slice()[0] = input_u256.into();
gas = Gas::new(gas_limit);
stack_len = 1;
unsafe { f.call(Some(&mut gas), Some(stack), Some(&mut stack_len)) }
unsafe { f.call(Some(&mut gas), Some(stack), Some(&mut stack_len), &mut cx) }
};

g.bench_function("revm-jit/no_gas", |b| b.iter(|| call_jit(jit_no_gas)));
Expand Down
12 changes: 11 additions & 1 deletion crates/revm-jit/src/bytecode/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,11 @@ impl<'a> Bytecode<'a> {
Ok(())
}

/// Returns the raw opcode.
pub(crate) fn raw_opcode(&self, ic: usize) -> RawOpcode<'a> {
self.opcodes[ic].to_raw_in(self)
}

pub(crate) fn get_imm_of(&self, opcode: OpcodeData) -> Option<&'a [u8]> {
(opcode.imm_len() > 0).then(|| self.get_imm(opcode.data))
}
Expand All @@ -216,10 +221,15 @@ impl<'a> Bytecode<'a> {
}

/// Returns `true` if the bytecode is EOF.
fn is_eof(&self) -> bool {
pub(crate) fn is_eof(&self) -> bool {
false
}

/// Returns `true` if the opcode at the given instruction counter is diverging.
pub(crate) fn is_opcode_diverging(&self, ic: usize) -> bool {
self.opcodes[ic].is_diverging(self.is_eof())
}

// TODO: is it worth it to make this a map?
/// Converts a program counter (`self.code[ic]`) to an instruction counter (`self.opcode(pc)`).
fn pc_to_ic(&self, pc: usize) -> usize {
Expand Down
Loading

0 comments on commit 6f5cb1e

Please sign in to comment.