Signed-off-by: Cyrill Leutwiler <bigcyrill@hotmail.com>
This commit is contained in:
Cyrill Leutwiler
2025-07-15 10:15:30 +02:00
parent a0396dd6d0
commit 94dda20880
13 changed files with 128 additions and 79 deletions
@@ -15,6 +15,8 @@ use crate::optimizer::settings::size_level::SizeLevel;
use crate::optimizer::Optimizer;
use crate::polkavm::context::attribute::Attribute;
use crate::polkavm::context::pointer::Pointer;
use crate::polkavm::context::Context;
use crate::polkavm::Dependency;
use self::declaration::Declaration;
use self::r#return::Return;
@@ -28,7 +30,9 @@ pub struct Function<'ctx> {
/// The LLVM function declaration.
declaration: Declaration<'ctx>,
/// The stack representation.
stack: HashMap<String, Pointer<'ctx>>,
stack: HashMap<String, u64>,
/// The stack variables pointer.
stack_variables: Pointer<'ctx>,
/// The return value entity.
r#return: Return<'ctx>,
@@ -56,11 +60,14 @@ impl<'ctx> Function<'ctx> {
entry_block: inkwell::basic_block::BasicBlock<'ctx>,
return_block: inkwell::basic_block::BasicBlock<'ctx>,
stack_variables: Pointer<'ctx>,
) -> Self {
Self {
name,
declaration,
stack: HashMap::with_capacity(Self::STACK_HASHMAP_INITIAL_CAPACITY),
stack_variables,
r#return,
entry_block,
@@ -210,22 +217,49 @@ impl<'ctx> Function<'ctx> {
/// Saves the pointer to a stack variable, returning the pointer to the shadowed variable,
/// if it exists.
pub fn insert_stack_pointer(
pub fn insert_stack_pointer<D: Dependency + Clone>(
&mut self,
context: &mut Context<'ctx, D>,
name: String,
pointer: Pointer<'ctx>,
) -> Option<Pointer<'ctx>> {
self.stack.insert(name, pointer)
) -> Pointer<'ctx> {
let pointer_name = format!("{}_stack_pointer", &name);
let len = self.stack.len();
let index = *self.stack.entry(name).or_insert_with(|| len as u64);
let indices = &[
context.xlen_type().const_zero(),
context.xlen_type().const_int(index, false),
];
context.build_gep(
self.stack_variables,
indices,
context.word_type(),
&pointer_name,
)
}
/// Gets the pointer to a stack variable.
pub fn get_stack_pointer(&self, name: &str) -> Option<Pointer<'ctx>> {
self.stack.get(name).copied()
}
pub fn get_stack_pointer<D: Dependency + Clone>(
&self,
context: &mut Context<'ctx, D>,
name: String,
) -> Pointer<'ctx> {
let pointer_name = format!("{}_stack_pointer", &name);
let index = *self
.stack
.get(&name)
.unwrap_or_else(|| panic!("stack pointer access prior to insertion: {name}"));
let indices = &[
context.xlen_type().const_zero(),
context.xlen_type().const_int(index, false),
];
/// Removes the pointer to a stack variable.
pub fn remove_stack_pointer(&mut self, name: &str) {
self.stack.remove(name);
context.build_gep(
self.stack_variables,
indices,
context.word_type(),
&pointer_name,
)
}
/// Returns the return entity representation.
@@ -48,6 +48,7 @@ where
function_type,
0,
Some(inkwell::module::Linkage::External),
1024,
)?;
self.inner.declare(context)
@@ -145,6 +145,7 @@ where
entry_function_type,
0,
Some(inkwell::module::Linkage::External),
0,
)?;
context.declare_global(
@@ -48,6 +48,7 @@ where
function_type,
0,
Some(inkwell::module::Linkage::External),
1024,
)?;
self.inner.declare(context)
+38 -4
View File
@@ -463,6 +463,7 @@ where
r#type: inkwell::types::FunctionType<'ctx>,
return_values_length: usize,
linkage: Option<inkwell::module::Linkage>,
stack_variables: u32,
) -> anyhow::Result<Rc<RefCell<Function<'ctx>>>> {
let value = self.module().add_function(name, r#type, linkage);
@@ -484,15 +485,30 @@ where
let entry_block = self.llvm.append_basic_block(value, "entry");
let return_block = self.llvm.append_basic_block(value, "return");
self.builder().position_at_end(entry_block);
let stack_variables_pointer = self.build_alloca(
self.word_type().array_type(stack_variables),
"stack_variables",
);
let r#return = match return_values_length {
0 => FunctionReturn::none(),
1 => {
self.set_basic_block(entry_block);
let pointer = self.build_alloca(self.word_type(), "return_pointer");
FunctionReturn::primitive(pointer)
//self.set_basic_block(entry_block);
//let pointer = self
// .current_function()
// .borrow_mut()
// .insert_stack_pointer(self, format!("{name}_return_pointer"));
FunctionReturn::primitive(self.build_gep(
stack_variables_pointer,
&[self.xlen_type().const_zero(), self.xlen_type().const_zero()],
self.word_type(),
"return_pointer",
))
}
size => {
self.set_basic_block(entry_block);
//self.set_basic_block(entry_block);
let pointer = self.build_alloca(
self.structure_type(
vec![self.word_type().as_basic_type_enum(); size].as_slice(),
@@ -509,6 +525,7 @@ where
r#return,
entry_block,
return_block,
stack_variables_pointer,
);
Function::set_default_attributes(self.llvm, function.declaration(), &self.optimizer);
let function = Rc::new(RefCell::new(function));
@@ -736,6 +753,23 @@ where
pointer
}
pub fn variable_decl<T: BasicType<'ctx> + Clone + Copy>(
&self,
r#type: T,
name: &str,
) -> Pointer<'ctx> {
let pointer = self.builder.build_alloca(r#type, name).unwrap();
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)
}
/// Truncate `address` to the ethereum address length and store it as bytes on the stack.
/// Builds an aligned stack allocation at the current position.
/// Use this if [`build_alloca_at_entry`] might change program semantics.
/// Otherwise, alloca should always be built at the function prelude!
@@ -35,6 +35,7 @@ where
Self::r#type(context),
0,
Some(inkwell::module::Linkage::External),
0,
)?;
let mut attributes = Self::ATTRIBUTES.to_vec();
@@ -40,6 +40,7 @@ pub fn check_attribute_null_pointer_is_invalid() {
.fn_type(&[context.word_type().into()], false),
1,
Some(inkwell::module::Linkage::External),
16,
)
.expect("Failed to add function");
assert!(!function
@@ -63,6 +64,7 @@ pub fn check_attribute_optimize_for_size_mode_3() {
.fn_type(&[context.word_type().into()], false),
1,
Some(inkwell::module::Linkage::External),
16,
)
.expect("Failed to add function");
assert!(!function
@@ -86,6 +88,7 @@ pub fn check_attribute_optimize_for_size_mode_z() {
.fn_type(&[context.word_type().into()], false),
1,
Some(inkwell::module::Linkage::External),
16,
)
.expect("Failed to add function");
assert!(function
@@ -109,6 +112,7 @@ pub fn check_attribute_min_size_mode_3() {
.fn_type(&[context.word_type().into()], false),
1,
Some(inkwell::module::Linkage::External),
16,
)
.expect("Failed to add function");
assert!(!function
@@ -132,6 +136,7 @@ pub fn check_attribute_min_size_mode_z() {
.fn_type(&[context.word_type().into()], false),
1,
Some(inkwell::module::Linkage::External),
16,
)
.expect("Failed to add function");
assert!(function