diff --git a/crates/llvm-context/src/polkavm/context/pointer/storage.rs b/crates/llvm-context/src/polkavm/context/pointer/storage.rs index 01ea8a5..6de3a31 100644 --- a/crates/llvm-context/src/polkavm/context/pointer/storage.rs +++ b/crates/llvm-context/src/polkavm/context/pointer/storage.rs @@ -2,6 +2,8 @@ use inkwell::values::BasicValueEnum; +use crate::polkavm::context::address_space::AddressSpace; +use crate::polkavm::context::pointer::Pointer; use crate::polkavm::context::runtime::RuntimeFunction; use crate::polkavm::context::Context; use crate::polkavm::Dependency; @@ -17,20 +19,27 @@ where const NAME: &'static str = "__revive_load_storage_word"; fn r#type<'ctx>(context: &Context<'ctx, D>) -> inkwell::types::FunctionType<'ctx> { - context - .word_type() - .fn_type(&[context.llvm().ptr_type(Default::default()).into()], false) + context.void_type().fn_type( + &[ + context.llvm().ptr_type(Default::default()).into(), + context.llvm().ptr_type(Default::default()).into(), + ], + false, + ) } fn emit_body<'ctx>( &self, context: &mut Context<'ctx, D>, ) -> anyhow::Result>> { - Ok(Some(emit_load( - context, - Self::paramater(context, 0), - false, - )?)) + let key = Self::paramater(context, 0); + let assignment_pointer = Self::paramater(context, 1).into_pointer_value(); + let value = emit_load(context, key, false)?; + context.build_store( + Pointer::new(context.word_type(), AddressSpace::Stack, assignment_pointer), + value, + )?; + Ok(None) } } diff --git a/crates/llvm-context/src/polkavm/evm/storage.rs b/crates/llvm-context/src/polkavm/evm/storage.rs index a934f64..0f5c3f0 100644 --- a/crates/llvm-context/src/polkavm/evm/storage.rs +++ b/crates/llvm-context/src/polkavm/evm/storage.rs @@ -13,16 +13,32 @@ use crate::PolkaVMStoreTransientStorageWordFunction; pub fn load<'ctx, D>( context: &mut Context<'ctx, D>, position: &PolkaVMArgument<'ctx>, -) -> anyhow::Result> + assignment_pointer: Option>, +) -> anyhow::Result>> where D: Dependency + Clone, { - let name = >::NAME; + let _name = >::NAME; let declaration = >::declaration(context); - let arguments = [position.as_pointer(context)?.value.into()]; - Ok(context - .build_call(declaration, &arguments, "storage_load") - .unwrap_or_else(|| panic!("runtime function {name} should return a value"))) + match assignment_pointer { + Some(assignment_pointer) => { + let arguments = [ + position.as_pointer(context)?.value.into(), + assignment_pointer.into(), + ]; + context.build_call(declaration, &arguments, "storage_load"); + Ok(None) + } + None => { + let pointer = context.build_alloca_at_entry(context.word_type(), "pointer"); + let arguments = [ + position.as_pointer(context)?.value.into(), + pointer.value.into(), + ]; + context.build_call(declaration, &arguments, "storage_load"); + Ok(Some(context.build_load(pointer, "storage_value")?)) + } + } } /// Translates the storage store. diff --git a/crates/solidity/src/yul/parser/statement/assignment.rs b/crates/solidity/src/yul/parser/statement/assignment.rs index 0a13d18..6937a09 100644 --- a/crates/solidity/src/yul/parser/statement/assignment.rs +++ b/crates/solidity/src/yul/parser/statement/assignment.rs @@ -121,7 +121,7 @@ where ) -> anyhow::Result<()> { context.set_debug_location(self.location.line, 0, None)?; - let value = match self.initializer.into_llvm(context)? { + let value = match self.initializer.into_llvm(context, None)? { Some(value) => value, None => return Ok(()), }; @@ -142,7 +142,6 @@ where context.build_store(pointer, value.access(context)?)?; return Ok(()); } - let value = value.access(context)?; let llvm_type = value.into_struct_value().get_type(); let tuple_pointer = context.build_alloca(llvm_type, "assignment_pointer"); diff --git a/crates/solidity/src/yul/parser/statement/block.rs b/crates/solidity/src/yul/parser/statement/block.rs index b4ba92d..7b1bbf4 100644 --- a/crates/solidity/src/yul/parser/statement/block.rs +++ b/crates/solidity/src/yul/parser/statement/block.rs @@ -184,7 +184,7 @@ where block.into_llvm(context)?; } Statement::Expression(expression) => { - expression.into_llvm(context)?; + expression.into_llvm(context, None)?; } Statement::VariableDeclaration(statement) => statement.into_llvm(context)?, Statement::Assignment(statement) => statement.into_llvm(context)?, diff --git a/crates/solidity/src/yul/parser/statement/expression/function_call/mod.rs b/crates/solidity/src/yul/parser/statement/expression/function_call/mod.rs index 9ddb1a2..ad3b5c9 100644 --- a/crates/solidity/src/yul/parser/statement/expression/function_call/mod.rs +++ b/crates/solidity/src/yul/parser/statement/expression/function_call/mod.rs @@ -118,6 +118,7 @@ impl FunctionCall { pub fn into_llvm<'ctx, D>( mut self, context: &mut revive_llvm_context::PolkaVMContext<'ctx, D>, + assignment_pointer: Option>, ) -> anyhow::Result>> where D: revive_llvm_context::PolkaVMDependency + Clone, @@ -129,7 +130,7 @@ impl FunctionCall { let mut values = Vec::with_capacity(self.arguments.len()); for argument in self.arguments.into_iter().rev() { let value = argument - .into_llvm(context)? + .into_llvm(context, None)? .expect("Always exists") .access(context)?; values.push(value); @@ -465,7 +466,11 @@ impl FunctionCall { Name::SLoad => { let arguments = self.pop_arguments::(context)?; - revive_llvm_context::polkavm_evm_storage::load(context, &arguments[0]).map(Some) + revive_llvm_context::polkavm_evm_storage::load( + context, + &arguments[0], + assignment_pointer, + ) } Name::SStore => { let arguments = self.pop_arguments::(context)?; @@ -989,7 +994,7 @@ impl FunctionCall { for expression in self.arguments.drain(0..N).rev() { arguments.push( expression - .into_llvm(context)? + .into_llvm(context, None)? .expect("Always exists") .access(context)?, ); @@ -1009,7 +1014,7 @@ impl FunctionCall { { let mut arguments = Vec::with_capacity(N); for expression in self.arguments.drain(0..N).rev() { - arguments.push(expression.into_llvm(context)?.expect("Always exists")); + arguments.push(expression.into_llvm(context, None)?.expect("Always exists")); } arguments.reverse(); diff --git a/crates/solidity/src/yul/parser/statement/expression/mod.rs b/crates/solidity/src/yul/parser/statement/expression/mod.rs index c26820e..b5dde2f 100644 --- a/crates/solidity/src/yul/parser/statement/expression/mod.rs +++ b/crates/solidity/src/yul/parser/statement/expression/mod.rs @@ -101,6 +101,7 @@ impl Expression { pub fn into_llvm<'ctx, D>( self, context: &mut revive_llvm_context::PolkaVMContext<'ctx, D>, + assignment_pointer: Option>, ) -> anyhow::Result>> where D: revive_llvm_context::PolkaVMDependency + Clone, @@ -139,7 +140,7 @@ impl Expression { })) } Self::FunctionCall(call) => Ok(call - .into_llvm(context)? + .into_llvm(context, assignment_pointer)? .map(revive_llvm_context::PolkaVMArgument::value)), } } diff --git a/crates/solidity/src/yul/parser/statement/for_loop.rs b/crates/solidity/src/yul/parser/statement/for_loop.rs index c3d0c35..af3a7a7 100644 --- a/crates/solidity/src/yul/parser/statement/for_loop.rs +++ b/crates/solidity/src/yul/parser/statement/for_loop.rs @@ -76,7 +76,7 @@ where context.set_basic_block(condition_block); let condition = self .condition - .into_llvm(context)? + .into_llvm(context, None)? .expect("Always exists") .access(context)? .into_int_value(); diff --git a/crates/solidity/src/yul/parser/statement/if_conditional.rs b/crates/solidity/src/yul/parser/statement/if_conditional.rs index 96178c7..69543f3 100644 --- a/crates/solidity/src/yul/parser/statement/if_conditional.rs +++ b/crates/solidity/src/yul/parser/statement/if_conditional.rs @@ -55,7 +55,7 @@ where fn into_llvm(self, context: &mut revive_llvm_context::PolkaVMContext) -> anyhow::Result<()> { let condition = self .condition - .into_llvm(context)? + .into_llvm(context, None)? .expect("Always exists") .access(context)? .into_int_value(); diff --git a/crates/solidity/src/yul/parser/statement/switch/mod.rs b/crates/solidity/src/yul/parser/statement/switch/mod.rs index 177003c..e0aca0b 100644 --- a/crates/solidity/src/yul/parser/statement/switch/mod.rs +++ b/crates/solidity/src/yul/parser/statement/switch/mod.rs @@ -123,7 +123,7 @@ where D: revive_llvm_context::PolkaVMDependency + Clone, { fn into_llvm(self, context: &mut revive_llvm_context::PolkaVMContext) -> anyhow::Result<()> { - let scrutinee = self.expression.into_llvm(context)?; + let scrutinee = self.expression.into_llvm(context, None)?; if self.cases.is_empty() { if let Some(block) = self.default { diff --git a/crates/solidity/src/yul/parser/statement/variable_declaration.rs b/crates/solidity/src/yul/parser/statement/variable_declaration.rs index 3024bc0..0458a6e 100644 --- a/crates/solidity/src/yul/parser/statement/variable_declaration.rs +++ b/crates/solidity/src/yul/parser/statement/variable_declaration.rs @@ -111,7 +111,7 @@ where .insert_stack_pointer(identifier.inner.clone(), pointer); let value = if let Some(expression) = self.expression { - match expression.into_llvm(context)? { + match expression.into_llvm(context, None)? { Some(mut value) => { if let Some(constant) = value.constant.take() { context @@ -156,7 +156,7 @@ where None => return Ok(()), }; let location = expression.location(); - let expression = match expression.into_llvm(context)? { + let expression = match expression.into_llvm(context, None)? { Some(expression) => expression, None => return Ok(()), };