mirror of
https://github.com/pezkuwichain/revive.git
synced 2026-06-13 13:01:06 +00:00
@@ -7,7 +7,7 @@ pub mod r#return;
|
||||
pub mod runtime;
|
||||
pub mod yul_data;
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::collections::{BTreeMap, HashMap};
|
||||
|
||||
use inkwell::debug_info::AsDIScope;
|
||||
|
||||
@@ -29,6 +29,10 @@ pub struct Function<'ctx> {
|
||||
declaration: Declaration<'ctx>,
|
||||
/// The stack representation.
|
||||
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.
|
||||
r#return: Return<'ctx>,
|
||||
|
||||
@@ -53,6 +57,7 @@ impl<'ctx> Function<'ctx> {
|
||||
name: String,
|
||||
declaration: Declaration<'ctx>,
|
||||
r#return: Return<'ctx>,
|
||||
stack_variables: inkwell::values::GlobalValue<'ctx>,
|
||||
|
||||
entry_block: inkwell::basic_block::BasicBlock<'ctx>,
|
||||
return_block: inkwell::basic_block::BasicBlock<'ctx>,
|
||||
@@ -61,6 +66,8 @@ impl<'ctx> Function<'ctx> {
|
||||
name,
|
||||
declaration,
|
||||
stack: HashMap::with_capacity(Self::STACK_HASHMAP_INITIAL_CAPACITY),
|
||||
stack_variables,
|
||||
stack_slots: BTreeMap::new(),
|
||||
r#return,
|
||||
|
||||
entry_block,
|
||||
@@ -279,4 +286,40 @@ impl<'ctx> Function<'ctx> {
|
||||
.as_mut()
|
||||
.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(
|
||||
name.to_owned(),
|
||||
FunctionDeclaration::new(r#type, value),
|
||||
r#return,
|
||||
self.get_global(&stack_variables).unwrap().value,
|
||||
entry_block,
|
||||
return_block,
|
||||
);
|
||||
|
||||
@@ -8,6 +8,7 @@ use crate::polkavm::context::Context;
|
||||
use crate::polkavm::Dependency;
|
||||
|
||||
pub mod heap;
|
||||
//pub mod stack;
|
||||
pub mod storage;
|
||||
|
||||
/// 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)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user