From 616f044633846d04d64ed319cdf03a825fc8761e Mon Sep 17 00:00:00 2001 From: Cyrill Leutwiler Date: Fri, 13 Sep 2024 21:54:42 +0200 Subject: [PATCH] always build alloca in the entry block (#46) Signed-off-by: xermicus --- crates/common/src/byte_length.rs | 9 ++--- .../llvm-context/src/polkavm/context/mod.rs | 37 +++++++++++++++---- 2 files changed, 33 insertions(+), 13 deletions(-) diff --git a/crates/common/src/byte_length.rs b/crates/common/src/byte_length.rs index c41f498..8a5aade 100644 --- a/crates/common/src/byte_length.rs +++ b/crates/common/src/byte_length.rs @@ -6,15 +6,12 @@ pub const BYTE_LENGTH_BYTE: usize = 1; /// The x86 word byte-length. pub const BYTE_LENGTH_X32: usize = 4; -/// Native stack alignment size in bytes -#[cfg(not(feature = "riscv-64"))] -pub const BYTE_LENGTH_STACK_ALIGN: usize = 4; -#[cfg(feature = "riscv-64")] -pub const BYTE_LENGTH_STACK_ALIGN: usize = 8; - /// The x86_64 word byte-length. pub const BYTE_LENGTH_X64: usize = 8; +/// EVM native stack alignment size in bytes +pub const BYTE_LENGTH_STACK_ALIGN: usize = 32; + /// The ETH address byte-length. pub const BYTE_LENGTH_ETH_ADDRESS: usize = 20; diff --git a/crates/llvm-context/src/polkavm/context/mod.rs b/crates/llvm-context/src/polkavm/context/mod.rs index f6f9c3c..4226fcb 100644 --- a/crates/llvm-context/src/polkavm/context/mod.rs +++ b/crates/llvm-context/src/polkavm/context/mod.rs @@ -441,7 +441,7 @@ where 0 => FunctionReturn::none(), 1 => { self.set_basic_block(entry_block); - let pointer = self.build_alloca(self.word_type(), "return_pointer"); + let pointer = self.build_alloca_internal(self.word_type(), "return_pointer"); FunctionReturn::primitive(pointer) } size if name.starts_with(Function::ZKSYNC_NEAR_CALL_ABI_PREFIX) => { @@ -452,7 +452,7 @@ where } size => { self.set_basic_block(entry_block); - let pointer = self.build_alloca( + let pointer = self.build_alloca_internal( self.structure_type( vec![self.word_type().as_basic_type_enum(); size].as_slice(), ), @@ -595,19 +595,42 @@ where self.builder.get_insert_block().expect("Always exists") } - /// Builds a stack allocation instruction. - /// Sets the alignment to 128 bits. + /// Builds an aligned stack allocation at the function entry. pub fn build_alloca + Clone + Copy>( &self, r#type: T, name: &str, + ) -> Pointer<'ctx> { + let current_block = self.basic_block(); + let entry_block = self.current_function().borrow().entry_block(); + + match entry_block.get_first_instruction() { + Some(instruction) => self.builder().position_before(&instruction), + None => self.builder().position_at_end(entry_block), + } + + let pointer = self.build_alloca_internal(r#type, name); + + self.set_basic_block(current_block); + return pointer; + } + + /// Builds a stack allocation and sets the alignment. + /// + /// Stack allocations should always happen at the function prelude. + /// Only use this when the position is guaranteed to be at the entry! + fn build_alloca_internal + Clone + Copy>( + &self, + r#type: T, + name: &str, ) -> Pointer<'ctx> { let pointer = self.builder.build_alloca(r#type, name).unwrap(); - self.basic_block() - .get_last_instruction() - .expect("Always exists") + pointer + .as_instruction() + .unwrap() .set_alignment(revive_common::BYTE_LENGTH_STACK_ALIGN as u32) .expect("Alignment is valid"); + Pointer::new(r#type, AddressSpace::Stack, pointer) }