From bfcdb8afa99609e41d8d40819228dc1aade86cf5 Mon Sep 17 00:00:00 2001 From: xermicus Date: Wed, 17 Apr 2024 12:44:54 +0200 Subject: [PATCH] implement byte stores and assert heap values to be either i256 or i8 Signed-off-by: xermicus --- crates/integration/src/lib.rs | 93 ++++++++++++++++++++ crates/llvm-context/src/eravm/context/mod.rs | 8 +- crates/llvm-context/src/eravm/evm/memory.rs | 22 ++--- 3 files changed, 108 insertions(+), 15 deletions(-) diff --git a/crates/integration/src/lib.rs b/crates/integration/src/lib.rs index 075c8d5..8c76306 100644 --- a/crates/integration/src/lib.rs +++ b/crates/integration/src/lib.rs @@ -215,4 +215,97 @@ mod tests { let received = U256::from_be_bytes::<32>(state.output.data.try_into().unwrap()); assert_eq!(received, expected); } + + #[test] + fn mstore8() { + sol!( + #[derive(Debug, PartialEq, Eq)] + contract MStore8 { + function mStore8(uint value) public pure returns (uint256 word); + } + + ); + let code = crate::compile_blob_with_options( + "MStore8", + include_str!("../contracts/mStore8.sol"), + false, + ); + let (mut instance, export) = mock_runtime::prepare(&code, None); + + let mut assert = |parameter, expected| { + let input = MStore8::mStore8Call::new((parameter,)).abi_encode(); + let state = crate::mock_runtime::call(State::new(input), &mut instance, export); + + assert_eq!(state.output.flags, 0); + + let received = U256::from_be_bytes::<32>(state.output.data.try_into().unwrap()); + assert_eq!(received, expected); + }; + + for (parameter, expected) in [ + (U256::MIN, U256::MIN), + ( + U256::from(1), + U256::from_str_radix( + "452312848583266388373324160190187140051835877600158453279131187530910662656", + 10, + ) + .unwrap(), + ), + ( + U256::from(2), + U256::from_str_radix( + "904625697166532776746648320380374280103671755200316906558262375061821325312", + 10, + ) + .unwrap(), + ), + ( + U256::from(255), + U256::from_str_radix( + "115339776388732929035197660848497720713218148788040405586178452820382218977280", + 10, + ) + .unwrap(), + ), + ( + U256::from(256), + U256::from(0), + ), + ( + U256::from(257), + U256::from_str_radix( + "452312848583266388373324160190187140051835877600158453279131187530910662656", + 10, + ) + .unwrap(), + ), + ( + U256::from(258), + U256::from_str_radix( + "904625697166532776746648320380374280103671755200316906558262375061821325312", + 10, + ) + .unwrap(), + ), + ( + U256::from(123456789), + U256::from_str_radix( + "9498569820248594155839807363993929941088553429603327518861754938149123915776", + 10, + ) + .unwrap(), + ), + ( + U256::MAX, + U256::from_str_radix( + "115339776388732929035197660848497720713218148788040405586178452820382218977280", + 10, + ) + .unwrap(), + ), + ] { + assert(parameter, expected); + } + } } diff --git a/crates/llvm-context/src/eravm/context/mod.rs b/crates/llvm-context/src/eravm/context/mod.rs index 4e64de3..241d021 100644 --- a/crates/llvm-context/src/eravm/context/mod.rs +++ b/crates/llvm-context/src/eravm/context/mod.rs @@ -789,7 +789,13 @@ where .expect("should be IntValue") .const_truncate(self.xlen_type()), )?; - let value = self.build_byte_swap(value.as_basic_value_enum()); + + let value = value.as_basic_value_enum(); + let value = match value.get_type().into_int_type().get_bit_width() as usize { + revive_common::BIT_LENGTH_FIELD => self.build_byte_swap(value), + revive_common::BIT_LENGTH_BYTE => value, + _ => unreachable!("Only word and byte sized values can be stored on EVM heap"), + }; self.builder .build_store(heap_pointer.value, value)? diff --git a/crates/llvm-context/src/eravm/evm/memory.rs b/crates/llvm-context/src/eravm/evm/memory.rs index 686757e..53de1fd 100644 --- a/crates/llvm-context/src/eravm/evm/memory.rs +++ b/crates/llvm-context/src/eravm/evm/memory.rs @@ -2,8 +2,6 @@ //! Translates the heap memory operations. //! -use inkwell::values::BasicValue; - use crate::eravm::context::address_space::AddressSpace; use crate::eravm::context::pointer::Pointer; use crate::eravm::context::Context; @@ -68,20 +66,16 @@ pub fn store_byte<'ctx, D>( where D: Dependency + Clone, { - let offset_pointer = Pointer::new_with_offset( + let byte_type = context.byte_type(); + let value = context + .builder() + .build_int_truncate(value, byte_type, "mstore8_value")?; + let pointer = Pointer::new_with_offset( context, AddressSpace::Heap, - context.byte_type(), + byte_type, offset, - "mstore8_offset_pointer", + "mstore8_destination", ); - context.build_call( - context.llvm_runtime().mstore8, - &[ - offset_pointer.value.as_basic_value_enum(), - value.as_basic_value_enum(), - ], - "mstore8_call", - ); - Ok(()) + context.build_store(pointer, value) }