mirror of
https://github.com/pezkuwichain/revive.git
synced 2026-06-15 22:01:05 +00:00
@@ -7,7 +7,7 @@ pub mod r#return;
|
|||||||
pub mod runtime;
|
pub mod runtime;
|
||||||
pub mod yul_data;
|
pub mod yul_data;
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::{BTreeMap, HashMap};
|
||||||
|
|
||||||
use inkwell::debug_info::AsDIScope;
|
use inkwell::debug_info::AsDIScope;
|
||||||
|
|
||||||
@@ -29,6 +29,10 @@ pub struct Function<'ctx> {
|
|||||||
declaration: Declaration<'ctx>,
|
declaration: Declaration<'ctx>,
|
||||||
/// The stack representation.
|
/// The stack representation.
|
||||||
stack: HashMap<String, Pointer<'ctx>>,
|
stack: HashMap<String, Pointer<'ctx>>,
|
||||||
|
/// The stack variables buffer.
|
||||||
|
stack_variables: inkwell::values::GlobalValue<'ctx>,
|
||||||
|
/// The stack variable names to slot mapping.
|
||||||
|
stack_slots: BTreeMap<String, usize>,
|
||||||
/// The return value entity.
|
/// The return value entity.
|
||||||
r#return: Return<'ctx>,
|
r#return: Return<'ctx>,
|
||||||
|
|
||||||
@@ -53,6 +57,7 @@ impl<'ctx> Function<'ctx> {
|
|||||||
name: String,
|
name: String,
|
||||||
declaration: Declaration<'ctx>,
|
declaration: Declaration<'ctx>,
|
||||||
r#return: Return<'ctx>,
|
r#return: Return<'ctx>,
|
||||||
|
stack_variables: inkwell::values::GlobalValue<'ctx>,
|
||||||
|
|
||||||
entry_block: inkwell::basic_block::BasicBlock<'ctx>,
|
entry_block: inkwell::basic_block::BasicBlock<'ctx>,
|
||||||
return_block: inkwell::basic_block::BasicBlock<'ctx>,
|
return_block: inkwell::basic_block::BasicBlock<'ctx>,
|
||||||
@@ -61,6 +66,8 @@ impl<'ctx> Function<'ctx> {
|
|||||||
name,
|
name,
|
||||||
declaration,
|
declaration,
|
||||||
stack: HashMap::with_capacity(Self::STACK_HASHMAP_INITIAL_CAPACITY),
|
stack: HashMap::with_capacity(Self::STACK_HASHMAP_INITIAL_CAPACITY),
|
||||||
|
stack_variables,
|
||||||
|
stack_slots: BTreeMap::new(),
|
||||||
r#return,
|
r#return,
|
||||||
|
|
||||||
entry_block,
|
entry_block,
|
||||||
@@ -279,4 +286,40 @@ impl<'ctx> Function<'ctx> {
|
|||||||
.as_mut()
|
.as_mut()
|
||||||
.expect("The Yul data must have been initialized")
|
.expect("The Yul data must have been initialized")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the stack variables global value.
|
||||||
|
pub fn stack_variables(&self) -> inkwell::values::GlobalValue<'ctx> {
|
||||||
|
self.stack_variables
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the slot for the given variable name.
|
||||||
|
pub fn stack_variable_slot(&mut self, name: String) -> usize {
|
||||||
|
let len = self.stack_slots.len();
|
||||||
|
*self.stack_slots.entry(name).or_insert_with(|| len)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn stack_variable_pointer<D: crate::PolkaVMDependency + Clone>(
|
||||||
|
&mut self,
|
||||||
|
name: String,
|
||||||
|
context: &mut super::Context<'ctx, D>,
|
||||||
|
) -> Pointer<'ctx> {
|
||||||
|
let pointer_name = format!("var_{}", &name);
|
||||||
|
let slot = self.stack_variable_slot(name);
|
||||||
|
Pointer::new(
|
||||||
|
context.word_type(),
|
||||||
|
Default::default(),
|
||||||
|
unsafe {
|
||||||
|
context.builder().build_gep(
|
||||||
|
context.word_type(),
|
||||||
|
self.stack_variables().as_pointer_value(),
|
||||||
|
&[
|
||||||
|
context.xlen_type().const_zero(),
|
||||||
|
context.xlen_type().const_int(slot as u64, false),
|
||||||
|
],
|
||||||
|
&pointer_name,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
.unwrap(),
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -503,10 +503,17 @@ where
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let stack_variables = format!("__vars_{name}");
|
||||||
|
self.declare_global(
|
||||||
|
&stack_variables,
|
||||||
|
self.word_type().array_type(0),
|
||||||
|
Default::default(),
|
||||||
|
);
|
||||||
let function = Function::new(
|
let function = Function::new(
|
||||||
name.to_owned(),
|
name.to_owned(),
|
||||||
FunctionDeclaration::new(r#type, value),
|
FunctionDeclaration::new(r#type, value),
|
||||||
r#return,
|
r#return,
|
||||||
|
self.get_global(&stack_variables).unwrap().value,
|
||||||
entry_block,
|
entry_block,
|
||||||
return_block,
|
return_block,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ use crate::polkavm::context::Context;
|
|||||||
use crate::polkavm::Dependency;
|
use crate::polkavm::Dependency;
|
||||||
|
|
||||||
pub mod heap;
|
pub mod heap;
|
||||||
|
//pub mod stack;
|
||||||
pub mod storage;
|
pub mod storage;
|
||||||
|
|
||||||
/// The LLVM pointer.
|
/// The LLVM pointer.
|
||||||
|
|||||||
@@ -0,0 +1,111 @@
|
|||||||
|
//! The revive simulated EVM stack variable functions.
|
||||||
|
|
||||||
|
use inkwell::values::BasicValueEnum;
|
||||||
|
|
||||||
|
use crate::polkavm::context::runtime::RuntimeFunction;
|
||||||
|
use crate::polkavm::context::Context;
|
||||||
|
use crate::polkavm::Dependency;
|
||||||
|
use crate::polkavm::WriteLLVM;
|
||||||
|
|
||||||
|
/// Load a word size value from a heap pointer.
|
||||||
|
pub struct DeclareVariable;
|
||||||
|
|
||||||
|
impl<D> RuntimeFunction<D> for DeclareVariable
|
||||||
|
where
|
||||||
|
D: Dependency + Clone,
|
||||||
|
{
|
||||||
|
const NAME: &'static str = "__revive_declare_variable";
|
||||||
|
|
||||||
|
fn r#type<'ctx>(context: &Context<'ctx, D>) -> inkwell::types::FunctionType<'ctx> {
|
||||||
|
context
|
||||||
|
.llvm
|
||||||
|
.ptr_type(Default::default())
|
||||||
|
.fn_type(&[context.xlen_type().into()], false)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn emit_body<'ctx>(
|
||||||
|
&self,
|
||||||
|
context: &mut Context<'ctx, D>,
|
||||||
|
) -> anyhow::Result<Option<BasicValueEnum<'ctx>>> {
|
||||||
|
let offset = Self::paramater(context, 0).into_int_value();
|
||||||
|
let length = context
|
||||||
|
.xlen_type()
|
||||||
|
.const_int(revive_common::BYTE_LENGTH_WORD as u64, false);
|
||||||
|
let pointer = context.build_heap_gep(offset, length)?;
|
||||||
|
let value = context
|
||||||
|
.builder()
|
||||||
|
.build_load(context.word_type(), pointer.value, "value")?;
|
||||||
|
context
|
||||||
|
.basic_block()
|
||||||
|
.get_last_instruction()
|
||||||
|
.expect("Always exists")
|
||||||
|
.set_alignment(revive_common::BYTE_LENGTH_BYTE as u32)
|
||||||
|
.expect("Alignment is valid");
|
||||||
|
|
||||||
|
let swapped_value = context.build_byte_swap(value)?;
|
||||||
|
Ok(Some(swapped_value))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<D> WriteLLVM<D> for LoadWord
|
||||||
|
where
|
||||||
|
D: Dependency + Clone,
|
||||||
|
{
|
||||||
|
fn declare(&mut self, context: &mut Context<D>) -> anyhow::Result<()> {
|
||||||
|
<Self as RuntimeFunction<_>>::declare(self, context)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn into_llvm(self, context: &mut Context<D>) -> anyhow::Result<()> {
|
||||||
|
<Self as RuntimeFunction<_>>::emit(&self, context)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Store a word size value through a heap pointer.
|
||||||
|
pub struct StoreWord;
|
||||||
|
|
||||||
|
impl<D> RuntimeFunction<D> for StoreWord
|
||||||
|
where
|
||||||
|
D: Dependency + Clone,
|
||||||
|
{
|
||||||
|
const NAME: &'static str = "__revive_store_heap_word";
|
||||||
|
|
||||||
|
fn r#type<'ctx>(context: &Context<'ctx, D>) -> inkwell::types::FunctionType<'ctx> {
|
||||||
|
context.void_type().fn_type(
|
||||||
|
&[context.xlen_type().into(), context.word_type().into()],
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn emit_body<'ctx>(
|
||||||
|
&self,
|
||||||
|
context: &mut Context<'ctx, D>,
|
||||||
|
) -> anyhow::Result<Option<BasicValueEnum<'ctx>>> {
|
||||||
|
let offset = Self::paramater(context, 0).into_int_value();
|
||||||
|
let length = context
|
||||||
|
.xlen_type()
|
||||||
|
.const_int(revive_common::BYTE_LENGTH_WORD as u64, false);
|
||||||
|
let pointer = context.build_heap_gep(offset, length)?;
|
||||||
|
|
||||||
|
let value = context.build_byte_swap(Self::paramater(context, 1))?;
|
||||||
|
|
||||||
|
context
|
||||||
|
.builder()
|
||||||
|
.build_store(pointer.value, value)?
|
||||||
|
.set_alignment(revive_common::BYTE_LENGTH_BYTE as u32)
|
||||||
|
.expect("Alignment is valid");
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<D> WriteLLVM<D> for StoreWord
|
||||||
|
where
|
||||||
|
D: Dependency + Clone,
|
||||||
|
{
|
||||||
|
fn declare(&mut self, context: &mut Context<D>) -> anyhow::Result<()> {
|
||||||
|
<Self as RuntimeFunction<_>>::declare(self, context)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn into_llvm(self, context: &mut Context<D>) -> anyhow::Result<()> {
|
||||||
|
<Self as RuntimeFunction<_>>::emit(&self, context)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -100,6 +100,7 @@ impl Expression {
|
|||||||
/// Converts the expression into an LLVM value.
|
/// Converts the expression into an LLVM value.
|
||||||
pub fn into_llvm<'ctx, D>(
|
pub fn into_llvm<'ctx, D>(
|
||||||
self,
|
self,
|
||||||
|
//bindings: &[String],
|
||||||
context: &mut revive_llvm_context::PolkaVMContext<'ctx, D>,
|
context: &mut revive_llvm_context::PolkaVMContext<'ctx, D>,
|
||||||
) -> anyhow::Result<Option<revive_llvm_context::PolkaVMArgument<'ctx>>>
|
) -> anyhow::Result<Option<revive_llvm_context::PolkaVMArgument<'ctx>>>
|
||||||
where
|
where
|
||||||
|
|||||||
@@ -99,6 +99,17 @@ where
|
|||||||
mut self,
|
mut self,
|
||||||
context: &mut revive_llvm_context::PolkaVMContext<'ctx, D>,
|
context: &mut revive_llvm_context::PolkaVMContext<'ctx, D>,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
|
let pointers: Vec<revive_llvm_context::PolkaVMPointer<'ctx>> = self
|
||||||
|
.bindings
|
||||||
|
.into_iter()
|
||||||
|
.map(|binding| {
|
||||||
|
context
|
||||||
|
.current_function()
|
||||||
|
.borrow_mut()
|
||||||
|
.stack_variable_pointer(binding.inner, context)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
/*
|
||||||
if self.bindings.len() == 1 {
|
if self.bindings.len() == 1 {
|
||||||
let identifier = self.bindings.remove(0);
|
let identifier = self.bindings.remove(0);
|
||||||
context.set_debug_location(self.location.line, 0, None)?;
|
context.set_debug_location(self.location.line, 0, None)?;
|
||||||
@@ -213,6 +224,7 @@ where
|
|||||||
})?;
|
})?;
|
||||||
context.build_store(pointer, value)?;
|
context.build_store(pointer, value)?;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,10 +70,11 @@ impl Type {
|
|||||||
D: revive_llvm_context::PolkaVMDependency + Clone,
|
D: revive_llvm_context::PolkaVMDependency + Clone,
|
||||||
{
|
{
|
||||||
match self {
|
match self {
|
||||||
Self::Bool => context.integer_type(revive_common::BIT_LENGTH_BOOLEAN),
|
//Self::Bool => context.integer_type(revive_common::BIT_LENGTH_BOOLEAN),
|
||||||
Self::Int(bitlength) => context.integer_type(bitlength),
|
//Self::Int(bitlength) => context.integer_type(bitlength),
|
||||||
Self::UInt(bitlength) => context.integer_type(bitlength),
|
Self::UInt(bitlength) => context.integer_type(bitlength),
|
||||||
Self::Custom(_) => context.word_type(),
|
//Self::Custom(_) => context.word_type(),
|
||||||
|
_ => panic!("oh no"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user