Files
revive/crates/runtime-api/src/calling_convention.rs
T
Cyrill Leutwiler 6585973e99 Updated call semantics (#56)
- Update pallet-revive dependency
- Implement calls according to pallet-revive call semantics
- Switch to the new return data API in pallet revive and get rid of return data buffer
- Remove a bunch of resulting dead code
2024-09-28 20:03:03 +02:00

109 lines
3.9 KiB
Rust

use inkwell::{
builder::Builder,
context::Context,
module::Module,
types::{BasicType, StructType},
values::{BasicValueEnum, PointerValue},
};
/// Creates a module that sets the PolkaVM minimum stack size to [`size`] if linked in.
pub fn min_stack_size<'context>(
context: &'context Context,
module_name: &str,
size: u32,
) -> Module<'context> {
let module = context.create_module(module_name);
module.set_inline_assembly(&format!(
".pushsection .polkavm_min_stack_size,\"\",@progbits
.word {size}
.popsection"
));
module
}
/// Helper for building function calls with stack spilled arguments.
/// - `pointer`: points to a struct of the packed argument struct type
/// - `type`: the packed argument struct type
/// - `arguments`: a correctly ordered list of the struct field values
pub fn spill<'ctx>(
builder: &Builder<'ctx>,
pointer: PointerValue<'ctx>,
r#type: StructType<'ctx>,
arguments: &[BasicValueEnum<'ctx>],
) -> anyhow::Result<()> {
for index in 0..r#type.get_field_types().len() {
let field_pointer = builder.build_struct_gep(
r#type,
pointer,
index as u32,
&format!("spill_parameter_{}", index),
)?;
let field_value = arguments
.get(index)
.ok_or_else(|| anyhow::anyhow!("invalid index {index} for struct type {}", r#type))?;
builder.build_store(field_pointer, *field_value)?;
}
Ok(())
}
/// Returns a packed struct argument type for the `instantiate` API.
pub fn instantiate(context: &Context) -> StructType {
context.struct_type(
&[
// code_hash_ptr: u32,
context.ptr_type(Default::default()).as_basic_type_enum(),
// ref_time_limit: u64,
context.i64_type().as_basic_type_enum(),
// proof_size_limit: u64,
context.i64_type().as_basic_type_enum(),
// deposit_ptr: u32,
context.ptr_type(Default::default()).as_basic_type_enum(),
// value_ptr: u32,
context.ptr_type(Default::default()).as_basic_type_enum(),
// input_data_ptr: u32,
context.ptr_type(Default::default()).as_basic_type_enum(),
// input_data_len: u32,
context.i32_type().as_basic_type_enum(),
// address_ptr: u32,
context.ptr_type(Default::default()).as_basic_type_enum(),
// output_ptr: u32,
context.ptr_type(Default::default()).as_basic_type_enum(),
// output_len_ptr: u32,
context.ptr_type(Default::default()).as_basic_type_enum(),
// salt_ptr: u32,
context.ptr_type(Default::default()).as_basic_type_enum(),
],
true,
)
}
/// Returns a packed struct argument type for the `call` API.
pub fn call(context: &Context) -> StructType {
context.struct_type(
&[
// flags: u32,
context.i32_type().as_basic_type_enum(),
// address_ptr:
context.ptr_type(Default::default()).as_basic_type_enum(),
// ref_time_limit: u64,
context.i64_type().as_basic_type_enum(),
// proof_size_limit: u64,
context.i64_type().as_basic_type_enum(),
// deposit_ptr: u32,
context.ptr_type(Default::default()).as_basic_type_enum(),
// value_ptr: u32,
context.ptr_type(Default::default()).as_basic_type_enum(),
// input_data_ptr: u32,
context.ptr_type(Default::default()).as_basic_type_enum(),
// input_data_len: u32,
context.i32_type().as_basic_type_enum(),
// output_ptr: u32,
context.ptr_type(Default::default()).as_basic_type_enum(),
// output_len_ptr: u32,
context.ptr_type(Default::default()).as_basic_type_enum(),
],
true,
)
}