wip: variables

Signed-off-by: Cyrill Leutwiler <bigcyrill@hotmail.com>
This commit is contained in:
Cyrill Leutwiler
2025-07-02 20:16:06 +02:00
parent ed608699af
commit d40ef3e462
7 changed files with 180 additions and 4 deletions
@@ -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)
}
}
@@ -100,6 +100,7 @@ impl Expression {
/// Converts the expression into an LLVM value.
pub fn into_llvm<'ctx, D>(
self,
//bindings: &[String],
context: &mut revive_llvm_context::PolkaVMContext<'ctx, D>,
) -> anyhow::Result<Option<revive_llvm_context::PolkaVMArgument<'ctx>>>
where
@@ -99,6 +99,17 @@ where
mut self,
context: &mut revive_llvm_context::PolkaVMContext<'ctx, D>,
) -> 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 {
let identifier = self.bindings.remove(0);
context.set_debug_location(self.location.line, 0, None)?;
@@ -213,6 +224,7 @@ where
})?;
context.build_store(pointer, value)?;
}
*/
Ok(())
}
+4 -3
View File
@@ -70,10 +70,11 @@ impl Type {
D: revive_llvm_context::PolkaVMDependency + Clone,
{
match self {
Self::Bool => context.integer_type(revive_common::BIT_LENGTH_BOOLEAN),
Self::Int(bitlength) => context.integer_type(bitlength),
//Self::Bool => context.integer_type(revive_common::BIT_LENGTH_BOOLEAN),
//Self::Int(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"),
}
}
}